Browse Source

HADOOP-5470. RunJar.unJar() should write the last modified time found in the jar entry to the uncompressed file. (Contributed by Andras Bakor)

Arpit Agarwal 9 năm trước cách đây
mục cha
commit
3337ef2bfe

+ 12 - 0
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/RunJar.java

@@ -43,12 +43,16 @@ import org.apache.hadoop.classification.InterfaceStability;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileUtil;
 import org.apache.hadoop.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** Run a Hadoop job jar. */
 @InterfaceAudience.Private
 @InterfaceStability.Unstable
 public class RunJar {
 
+  private static final Logger LOG = LoggerFactory.getLogger(RunJar.class);
+
   /** Pattern that matches any string */
   public static final Pattern MATCH_ANY = Pattern.compile(".*");
 
@@ -93,6 +97,7 @@ public class RunJar {
     throws IOException {
     JarFile jar = new JarFile(jarFile);
     try {
+      int numOfFailedLastModifiedSet = 0;
       Enumeration<JarEntry> entries = jar.entries();
       while (entries.hasMoreElements()) {
         final JarEntry entry = entries.nextElement();
@@ -108,11 +113,18 @@ public class RunJar {
             } finally {
               out.close();
             }
+            if (!file.setLastModified(entry.getTime())) {
+              numOfFailedLastModifiedSet++;
+            }
           } finally {
             in.close();
           }
         }
       }
+      if (numOfFailedLastModifiedSet > 0) {
+        LOG.warn("Could not set last modfied time for {} file(s)",
+                numOfFailedLastModifiedSet);
+      }
     } finally {
       jar.close();
     }

+ 21 - 2
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestRunJar.java

@@ -42,6 +42,8 @@ public class TestRunJar extends TestCase {
 
   private static final String TEST_JAR_NAME="test-runjar.jar";
   private static final String TEST_JAR_2_NAME = "test-runjar2.jar";
+  private static final long MOCKED_NOW = 1_460_389_972_000L;
+  private static final long MOCKED_NOW_PLUS_TWO_SEC = MOCKED_NOW + 2_000;
 
   @Override
   @Before
@@ -68,9 +70,13 @@ public class TestRunJar extends TestCase {
     File jarFile = new File(TEST_ROOT_DIR, TEST_JAR_NAME);
     JarOutputStream jstream =
         new JarOutputStream(new FileOutputStream(jarFile));
-    jstream.putNextEntry(new ZipEntry("foobar.txt"));
+    ZipEntry zipEntry1 = new ZipEntry("foobar.txt");
+    zipEntry1.setTime(MOCKED_NOW);
+    jstream.putNextEntry(zipEntry1);
     jstream.closeEntry();
-    jstream.putNextEntry(new ZipEntry("foobaz.txt"));
+    ZipEntry zipEntry2 = new ZipEntry("foobaz.txt");
+    zipEntry2.setTime(MOCKED_NOW_PLUS_TWO_SEC);
+    jstream.putNextEntry(zipEntry2);
     jstream.closeEntry();
     jstream.close();
   }
@@ -113,6 +119,19 @@ public class TestRunJar extends TestCase {
 
   }
 
+  public void testUnJarDoesNotLooseLastModify() throws Exception {
+    File unjarDir = new File(TEST_ROOT_DIR, "unjar-lastmod");
+    assertFalse("unjar dir shouldn't exist at test start",
+            new File(unjarDir, "foobar.txt").exists());
+
+    // Unjar everything
+    RunJar.unJar(new File(TEST_ROOT_DIR, TEST_JAR_NAME),
+            unjarDir);
+
+    assertEquals("Last modify time was lost during unJar", MOCKED_NOW, new File(unjarDir, "foobar.txt").lastModified());
+    assertEquals("Last modify time was lost during unJar", MOCKED_NOW_PLUS_TWO_SEC, new File(unjarDir, "foobaz.txt").lastModified());
+  }
+
   /**
    * Tests the client classloader to verify the main class and its dependent
    * class are loaded correctly by the application classloader, and others are