Restores DevMode specific linker hacks.

This is a rollback of https://gwt-review.googlesource.com/#/c/10360/

Change-Id: I1ce782c912193e09fa9c92cac5ae190430359814
Review-Link: https://gwt-review.googlesource.com/#/c/13918/
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/SelectionScriptLinker.java b/dev/core/src/com/google/gwt/core/ext/linker/impl/SelectionScriptLinker.java
index 23f7309..cf74dfe 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/SelectionScriptLinker.java
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/SelectionScriptLinker.java
@@ -295,7 +295,18 @@
   protected EmittedArtifact emitSelectionScript(TreeLogger logger,
       LinkerContext context, ArtifactSet artifacts)
       throws UnableToCompleteException {
-    long lastModified = context.getModuleLastModified();
+    /*
+     * Last modified is important to keep Development Mode refreses from
+     * clobbering Production Mode compiles. We set the timestamp on the
+     * Development Mode selection script to the same mod time as the module (to
+     * allow updates). For Production Mode, we just set it to now.
+     */
+    long lastModified;
+    if (permutationsUtil.getPermutationsMap().isEmpty()) {
+      lastModified = context.getModuleLastModified();
+    } else {
+      lastModified = System.currentTimeMillis();
+    }
     String ss = generateSelectionScript(logger, context, artifacts);
     return emitString(logger, ss, context.getModuleName()
         + ".nocache.js", lastModified);
diff --git a/dev/core/src/com/google/gwt/dev/util/OutputFileSet.java b/dev/core/src/com/google/gwt/dev/util/OutputFileSet.java
index 6cadaeb..c507080 100644
--- a/dev/core/src/com/google/gwt/dev/util/OutputFileSet.java
+++ b/dev/core/src/com/google/gwt/dev/util/OutputFileSet.java
@@ -65,14 +65,15 @@
 
   /**
    * Opens a file for write. If writing to a zip file and the file already exists,
-   * there will be no effect. If writing to a directory already existing files are
-   * overwritten.
+   * there will be no effect. If writing to a directory, the file exists, and the
+   * given timestamp is older than the current timestamp, there will be no effect.
    *
-   * @param timeStampMillis last modified time in milliseconds.
+   * @param timeStampMillis last modified time in milliseconds, or
+   *          TIMESTAMP_UNAVAILABLE to force an overwrite.
    * @return the output stream to write to, possibly a NullOutputStream
    */
-  public OutputStream openForWrite(String path, long timeStampMillis)
-      throws IOException {
+  // TODO: revalidate whether any timestamp based overwrite prevention is needed.
+  public OutputStream openForWrite(String path, long timeStampMillis) throws IOException {
     pathsSeen.add(path);
     return createNewOutputStream(path, timeStampMillis);
   }
diff --git a/dev/core/src/com/google/gwt/dev/util/OutputFileSetOnDirectory.java b/dev/core/src/com/google/gwt/dev/util/OutputFileSetOnDirectory.java
index 17720f7..652ab9e 100644
--- a/dev/core/src/com/google/gwt/dev/util/OutputFileSetOnDirectory.java
+++ b/dev/core/src/com/google/gwt/dev/util/OutputFileSetOnDirectory.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.dev.util;
 
+import com.google.gwt.dev.util.NullOutputFileSet.NullOutputStream;
 import com.google.gwt.dev.util.collect.HashSet;
 
 import java.io.File;
@@ -45,6 +46,12 @@
   protected OutputStream createNewOutputStream(String path,
       final long timeStampMillis) throws IOException {
     final File file = pathToFile(path);
+    if (file.exists()
+        && timeStampMillis != TIMESTAMP_UNAVAILABLE
+        && file.lastModified() > timeStampMillis) {
+      return new NullOutputStream();
+    }
+
     mkdirs(file.getParentFile());
     return new FileOutputStream(file) {
       @Override
diff --git a/dev/core/test/com/google/gwt/dev/util/OutputFileSetOnDirectoryTest.java b/dev/core/test/com/google/gwt/dev/util/OutputFileSetOnDirectoryTest.java
index 599e9ce..0c2283e 100644
--- a/dev/core/test/com/google/gwt/dev/util/OutputFileSetOnDirectoryTest.java
+++ b/dev/core/test/com/google/gwt/dev/util/OutputFileSetOnDirectoryTest.java
@@ -65,7 +65,7 @@
     }
   }
 
-  public void testNewFileOlderTimestampOverwrites() throws IOException {
+  public void testNewFileOlderTimestampDies() throws IOException {
     File work = Utility.makeTemporaryDirectory(null, "outputfileset");
     try {
       OutputFileSetOnDirectory output = new OutputFileSetOnDirectory(work, "test/");
@@ -75,7 +75,7 @@
       firstStream.close();
 
       OutputStream secondStream = output.createNewOutputStream("path/to/file", 1000);
-      assertTrue(secondStream instanceof FileOutputStream);
+      assertFalse(secondStream instanceof FileOutputStream);
       secondStream.close();
     } finally {
       Util.recursiveDelete(work, false);
diff --git a/user/test/com/google/gwt/core/ext/linker/impl/SelectionScriptLinkerUnitTest.java b/user/test/com/google/gwt/core/ext/linker/impl/SelectionScriptLinkerUnitTest.java
index 0d92b6a..2f80a9f 100644
--- a/user/test/com/google/gwt/core/ext/linker/impl/SelectionScriptLinkerUnitTest.java
+++ b/user/test/com/google/gwt/core/ext/linker/impl/SelectionScriptLinkerUnitTest.java
@@ -147,8 +147,8 @@
   }
 
   /**
-   * Test timestamps on the selection script. For both Development Mode and ProductionMode it should
-   * match the module's timestamp.
+   * Test timestamps on the selection script. For Development Mode, it should match
+   * the module's timestamp. For Production Mode, it should be current.
    */
   public void testTimestampOnSelectionScript() throws UnableToCompleteException {
     // Development Mode
@@ -170,7 +170,7 @@
       updated = new ShardableSelectionScriptLinker().link(TreeLogger.NULL,
           new MockLinkerContext(), updated, false);
       EmittedArtifact selectionScript = findSelectionScript(updated);
-      assertEquals(MOCK_MODULE_LAST_MODIFIED, selectionScript.getLastModified());
+      assertTrue(MOCK_MODULE_LAST_MODIFIED != selectionScript.getLastModified());
     }
   }