Revision: 10355
Author:   zun...@google.com
Date:     Mon Jun 20 09:36:25 2011
Log:      Turns on reading from archives by default.
Adds an optimization to CompileModule to not load multiple files.
Lowers the priority of some error messages so they don't fill
the screen with useless output when TRACE is turned on.

Review at http://gwt-code-reviews.appspot.com/1461801

Review by: jbrosenb...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=10355

Added:
 /trunk/dev/core/src/com/google/gwt/dev/ArchivePreloader.java
Modified:
 /trunk/dev/core/src/com/google/gwt/dev/CompileModule.java
 /trunk/dev/core/src/com/google/gwt/dev/DevModeBase.java
 /trunk/dev/core/src/com/google/gwt/dev/Precompile.java
 /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefLoader.java
 /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java
 /trunk/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
 /trunk/dev/core/src/com/google/gwt/dev/javac/UnitCacheFactory.java
 /trunk/dev/core/src/com/google/gwt/dev/util/Util.java
/trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java

=======================================
--- /dev/null
+++ /trunk/dev/core/src/com/google/gwt/dev/ArchivePreloader.java Mon Jun 20 09:36:25 2011
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.dev.cfg.ModuleDef;
+import com.google.gwt.dev.javac.CompilationStateBuilder;
+import com.google.gwt.dev.javac.CompilationUnitArchive;
+import com.google.gwt.dev.util.Util;
+import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
+import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Handles loading archived modules into the CompilationState for the Compiler
+ * and DevMode.
+ */
+public class ArchivePreloader {
+ static final boolean ARCHIVES_ENABLED = Boolean.valueOf(System.getProperty("gwt.usearchives",
+      "true"));
+ private static Map<String, Long> alreadyLoaded = new HashMap<String, Long>();
+
+  /**
+   * Load any .gwtar files into the cache before building CompilationState.
+   */
+  static void preloadArchives(TreeLogger logger, ModuleDef module) {
+    if (!ArchivePreloader.ARCHIVES_ENABLED) {
+      return;
+    }
+
+    logger.log(TreeLogger.TRACE,
+ "Looking for precompiled archives. To disable, use -Dgwt.usearchives=false");
+
+ SpeedTracerLogger.Event loadArchive = SpeedTracerLogger.start(CompilerEventType.LOAD_ARCHIVE);
+    try {
+ Collection<URL> archiveURLs = module.getAllCompilationUnitArchiveURLs();
+
+      for (URL archiveURL : archiveURLs) {
+        Long lastModifiedTime = Util.getResourceModifiedTime(archiveURL);
+        String toLoad = archiveURL.toExternalForm();
+        Long previousLoadTime = alreadyLoaded.get(toLoad);
+ if (previousLoadTime == null | | !previousLoadTime.equals(lastModifiedTime)) { + logger.log(TreeLogger.TRACE, "Loading archived module: " + archiveURL);
+          try {
+ CompilationUnitArchive archive = CompilationUnitArchive.createFromURL(archiveURL);
+            // Pre-populate CompilationStateBuilder with .gwtar files
+            CompilationStateBuilder.addArchive(archive);
+          } catch (IOException ex) {
+ logger.log(TreeLogger.WARN, "Unable to read: " + archiveURL + ". Skipping: " + ex);
+          } catch (ClassNotFoundException ex) {
+ logger.log(TreeLogger.WARN, "Incompatible archived module: " + archiveURL
+                + ". Skipping: " + ex);
+          }
+ // Mark it loaded whether or not it worked. We don't want to continue
+          // to try and fail.
+          alreadyLoaded.put(toLoad, lastModifiedTime);
+        } else {
+ logger.log(TreeLogger.TRACE, "Skipping already loaded archive: " + archiveURL);
+        }
+      }
+    } finally {
+      loadArchive.end();
+    }
+  }
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/CompileModule.java Wed Jun 8 16:44:32 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/CompileModule.java Mon Jun 20 09:36:25 2011
@@ -186,6 +186,8 @@
    */
public boolean run(final TreeLogger logger) throws UnableToCompleteException {

+    Set<String> alreadyLoadedArchives = new HashSet<String>();
+
     // TODO(zundel): There is an optimal order to compile these modules in.
// Modify ModuleDefLoader to be able to figure that out and sort them for
     // us.
@@ -211,10 +213,14 @@
         }

         for (URL archiveURL : archiveURLs) {
+          String archiveURLstring = archiveURL.toString();
+          if (alreadyLoadedArchives.contains(archiveURLstring)) {
+            continue;
+          }
+          alreadyLoadedArchives.add(archiveURLstring);
           SpeedTracerLogger.Event loadArchive =
- SpeedTracerLogger.start(CompilerEventType.LOAD_ARCHIVE, "dependentModule", archiveURL
-                  .toString());
-
+ SpeedTracerLogger.start(CompilerEventType.LOAD_ARCHIVE, "dependentModule", archiveURL
+                .toString());
           try {
CompilationUnitArchive archive = CompilationUnitArchive.createFromURL(archiveURL);
             // Pre-populate CompilationStateBuilder with .gwtar files
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/DevModeBase.java Wed Jun 8 16:44:32 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/DevModeBase.java Mon Jun 20 09:36:25 2011
@@ -103,9 +103,7 @@
         ModuleDef moduleDef = loadModule(logger, moduleName, true);
         assert (moduleDef != null);

-        if (Boolean.valueOf(System.getProperty("gwt.usearchives"))) {
-          Precompile.preloadArchives(logger, moduleDef);
-        }
+        ArchivePreloader.preloadArchives(logger, moduleDef);

         CompilationState compilationState =
             moduleDef.getCompilationState(logger, !options.isStrict());
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/Precompile.java Wed Jun 8 16:44:32 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/Precompile.java Mon Jun 20 09:36:25 2011
@@ -29,9 +29,7 @@
 import com.google.gwt.dev.cfg.ModuleDefLoader;
 import com.google.gwt.dev.cfg.PropertyPermutations;
 import com.google.gwt.dev.javac.CompilationState;
-import com.google.gwt.dev.javac.CompilationStateBuilder;
 import com.google.gwt.dev.javac.CompilationUnit;
-import com.google.gwt.dev.javac.CompilationUnitArchive;
 import com.google.gwt.dev.jjs.AbstractCompiler;
 import com.google.gwt.dev.jjs.JJSOptions;
 import com.google.gwt.dev.jjs.JavaScriptCompiler;
@@ -47,9 +45,7 @@
 import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;

 import java.io.File;
-import java.io.IOException;
 import java.lang.management.ManagementFactory;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -244,9 +240,7 @@
     // doesn't block when the library is accessed for the first time.
     new GraphicsInitThread().start();

-    if (Boolean.valueOf(System.getProperty("gwt.usearchives"))) {
-      preloadArchives(logger, module);
-    }
+    ArchivePreloader.preloadArchives(logger, module);

     try {
       CompilationState compilationState =
@@ -341,36 +335,6 @@
       precompileEvent.end();
     }
   }
-
-  /**
-   * Load any .gwtar files into the cache before building CompilationState.
-   */
-  static void preloadArchives(TreeLogger logger, ModuleDef module) {
- SpeedTracerLogger.Event loadArchive = SpeedTracerLogger.start(CompilerEventType.LOAD_ARCHIVE);
-    try {
- Collection<URL> archiveURLs = module.getAllCompilationUnitArchiveURLs();
-      if (logger.isLoggable(TreeLogger.TRACE) && archiveURLs != null) {
-        for (URL archiveURL : archiveURLs) {
- logger.log(TreeLogger.TRACE, "Found archived module: " + archiveURL);
-        }
-      }
-
-      for (URL archiveURL : archiveURLs) {
-        try {
- CompilationUnitArchive archive = CompilationUnitArchive.createFromURL(archiveURL);
-          // Pre-populate CompilationStateBuilder with .gwt files
-          CompilationStateBuilder.addArchive(archive);
-        } catch (IOException ex) {
- logger.log(TreeLogger.WARN, "Unable to read: " + archiveURL + ". Skipping: " + ex);
-        } catch (ClassNotFoundException ex) {
- logger.log(TreeLogger.WARN, "Incompatible archived module: " + archiveURL
-              + ". Skipping: " + ex);
-        }
-      }
-    } finally {
-      loadArchive.end();
-    }
-  }

private static void abortDueToStrictMode(TreeLogger logger) throws UnableToCompleteException { logger.log(TreeLogger.ERROR, "Aborting compile due to errors in some input files");
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefLoader.java Wed Jun 8 16:44:32 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefLoader.java Mon Jun 20 09:36:25 2011
@@ -211,10 +211,9 @@
       @Override
public void load(TreeLogger logger, String moduleName, ModuleDef moduleDef)
           throws UnableToCompleteException {
+ logger.log(TreeLogger.TRACE, "Loading module '" + moduleName + "'");
         for (String inherit : inherits) {
-          TreeLogger branch = logger.branch(TreeLogger.TRACE,
-              "Loading inherited module '" + inherit + "'", null);
-          nestedLoad(branch, inherit, moduleDef);
+          nestedLoad(logger, inherit, moduleDef);
         }
       }
     };
@@ -223,23 +222,22 @@
   /**
    * Loads a new module into <code>moduleDef</code> as an included module.
    *
-   * @param logger Logs the process.
+   * @param parentLogger Logs the process.
    * @param moduleName The module to load.
    * @param moduleDef The module to add the new module to.
    * @throws UnableToCompleteException
    */
- void nestedLoad(TreeLogger logger, String moduleName, ModuleDef moduleDef) + void nestedLoad(TreeLogger parentLogger, String moduleName, ModuleDef moduleDef)
       throws UnableToCompleteException {

     if (alreadyLoadedModules.contains(moduleName)) {
-      if (logger.isLoggable(TreeLogger.TRACE)) {
-        logger.log(TreeLogger.TRACE, "Module '" + moduleName
-            + "' has already been loaded and will be skipped", null);
-      }
+      // No need to parse module again.
       return;
-    } else {
-      alreadyLoadedModules.add(moduleName);
-    }
+    }
+
+ TreeLogger logger = parentLogger.branch(TreeLogger.DEBUG, "Loading inherited module '"
+        + moduleName + "'", null);
+    alreadyLoadedModules.add(moduleName);

     // Find the specified module using the classpath.
     //
@@ -249,8 +247,8 @@

     if (moduleURL != null) {
       String externalForm = moduleURL.toExternalForm();
-      if (logger.isLoggable(TreeLogger.TRACE)) {
- logger.log(TreeLogger.TRACE, "Module location: " + externalForm, null);
+      if (logger.isLoggable(TreeLogger.DEBUG)) {
+ logger.log(TreeLogger.DEBUG, "Module location: " + externalForm, null);
       }
       try {
         if ((!(externalForm.startsWith("jar:file")))
@@ -271,10 +269,8 @@
       }
     }
     if (moduleURL == null) {
-      String msg = "Unable to find '"
-          + resName
- + "' on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?";
-      logger.log(TreeLogger.ERROR, msg, null);
+ logger.log(TreeLogger.ERROR,"Unable to find '" + resName + "' on your classpath; " + + "could be a typo, or maybe you forgot to include a classpath entry for source?");
       throw new UnableToCompleteException();
     }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java Mon Mar 21 12:22:19 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/cfg/ModuleDefSchema.java Mon Jun 20 09:36:25 2011
@@ -490,9 +490,7 @@
     @SuppressWarnings("unused") // called reflectively
     protected Schema __inherits_begin(String name)
         throws UnableToCompleteException {
-      TreeLogger branch = logger.branch(TreeLogger.TRACE,
-          "Loading inherited module '" + name + "'", null);
-      loader.nestedLoad(branch, name, moduleDef);
+      loader.nestedLoad(logger, name, moduleDef);
       return null;
     }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java Wed Jun 8 16:44:32 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java Mon Jun 20 09:36:25 2011
@@ -315,7 +315,7 @@

       // Sort, then report all errors (re-report for cached units).
       Collections.sort(resultUnits, CompilationUnit.COMPARATOR);
- logger = logger.branch(TreeLogger.DEBUG, "Validating newly compiled units");
+      logger = logger.branch(TreeLogger.DEBUG, "Validating units:");
       int errorCount = 0;
       for (CompilationUnit unit : resultUnits) {
if (CompilationProblemReporter.reportErrors(logger, unit, suppressErrors)) {
@@ -346,9 +346,6 @@
       // archive
       if (cachedCompilationUnit == null
|| cachedCompilationUnit.getLastModified() < unit.getLastModified()) {
-        // TODO(zundel): mark these units as being a part of an archive.
- // that way, the persistent unit cache won't need to bother to write
-        // them out.
         unitCache.addArchivedUnit(unit);
       }
     }
@@ -440,7 +437,7 @@
       builders.add(builder);
     }
     if (logger.isLoggable(TreeLogger.TRACE)) {
- logger.log(TreeLogger.TRACE, "Found " + cachedUnits.size() + " cached units. Used " + logger.log(TreeLogger.TRACE, "Found " + cachedUnits.size() + " cached/archived units. Used " + cachedUnits.size() + " / " + resources.size() + " units from cache.");
     }

=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/javac/UnitCacheFactory.java Mon May 23 04:05:48 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/javac/UnitCacheFactory.java Mon Jun 20 09:36:25 2011
@@ -51,7 +51,8 @@
         if (propertyCacheDir != null) {
           cacheDir = new File(propertyCacheDir);
         } else if (cacheDir == null) {
- logger.log(TreeLogger.TRACE, "To enable persistent unit caching, specify the -Dgwt.persistentunitcachedir=<dir> system property."); + logger.log(TreeLogger.TRACE, "Persistent caching disabled - no directory specified.\n" + + "To enable persistent unit caching use -Dgwt.persistentunitcachedir=<dir>");
         }
         if (cacheDir != null) {
           try {
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/util/Util.java Mon Apr 18 04:15:28 2011 +++ /trunk/dev/core/src/com/google/gwt/dev/util/Util.java Mon Jun 20 09:36:25 2011
@@ -56,7 +56,9 @@
 import java.lang.reflect.Array;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.net.JarURLConnection;
 import java.net.MalformedURLException;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.ByteBuffer;
@@ -83,6 +85,9 @@

   public static final String[] EMPTY_ARRAY_STRING = new String[0];

+  private static final String FILE_PROTOCOL = "file";
+
+  private static final String JAR_PROTOCOL = "jar";
   /**
* The size of a {@link #threadLocalBuf}, which should be large enough for * efficient data transfer but small enough to fit easily into the L2 cache of
@@ -433,6 +438,48 @@
     File file = new File(installPath + '/' + relativePath);
     return readFileAsString(file);
   }
+
+  /**
+   * Retrieves the last modified time of a provided URL.
+   *
+ * @return a positive value indicating milliseconds since the epoch (00:00:00
+   *         Jan 1, 1970), or 0L on failure, such as a SecurityException or
+   *         IOException.
+   */
+  public static long getResourceModifiedTime(URL url) {
+    long lastModified = 0L;
+    try {
+      if (url.getProtocol().equals(JAR_PROTOCOL)) {
+        /*
+ * If this resource is contained inside a jar file, such as can happen + * if it's bundled in a 3rd-party library, we use the jar file itself to
+         * test whether it's up to date. We don't want to call
+ * JarURLConnection.getLastModified(), as this is much slower than using
+         * the jar File resource directly.
+         */
+        JarURLConnection jarConn = (JarURLConnection) url.openConnection();
+        url = jarConn.getJarFileURL();
+      }
+      if (url.getProtocol().equals(FILE_PROTOCOL)) {
+        /*
+ * Need to handle possibly wonky syntax in a file URL resource. Modeled
+         * after suggestion in this blog entry:
+         * http://weblogs.java.net/blog/2007
+         * /04/25/how-convert-javaneturl-javaiofile
+         */
+        File file;
+        try {
+          file = new File(url.toURI());
+        } catch (URISyntaxException uriEx) {
+          file = new File(url.getPath());
+        }
+        lastModified = file.lastModified();
+      }
+    } catch (IOException ignored) {
+    } catch (RuntimeException ignored) {
+    }
+    return lastModified;
+  }

   /**
    * A 4-digit hex result.
=======================================
--- /trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java Tue Jun 14 12:19:31 2011 +++ /trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java Mon Jun 20 09:36:25 2011
@@ -52,11 +52,7 @@
 import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
 import com.google.gwt.user.rebind.SourceWriter;

-import java.io.File;
-import java.io.IOException;
 import java.io.PrintWriter;
-import java.net.JarURLConnection;
-import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -119,9 +115,6 @@
  * another by simply emitting a call to <code>resource()</code>.
  */
 public abstract class AbstractClientBundleGenerator extends GeneratorExt {
-
-  private static final String FILE_PROTOCOL = "file";
-  private static final String JAR_PROTOCOL = "jar";
private static final String CACHED_PROPERTY_INFORMATION = "cached-property-info"; private static final String CACHED_RESOURCE_INFORMATION = "cached-resource-info";
   private static final String CACHED_TYPE_INFORMATION = "cached-type-info";
@@ -138,10 +131,12 @@
private final Map<String, String> fieldsToDeclarations = new LinkedHashMap<String, String>(); private final Map<String, String> fieldsToInitializers = new HashMap<String, String>();

+    @Override
     public String define(JType type, String name) {
       return define(type, name, null, true, false);
     }

+    @Override
     public String define(JType type, String name, String initializer,
         boolean isStatic, boolean isFinal) {

@@ -231,6 +226,7 @@
       }
     }

+    @Override
     public void addConfigurationProperty(String propertyName)
         throws BadPropertyValueException {

@@ -242,6 +238,7 @@
       configProps.add(propertyName);
     }

+    @Override
     public void addPermutationAxis(String propertyName)
         throws BadPropertyValueException {

@@ -266,6 +263,7 @@
       }
     }

+    @Override
public void addResolvedResource(String partialPath, URL resolvedResourceUrl) {
       if (!canBeCacheable) {
         return;
@@ -273,6 +271,7 @@
       resolvedResources.put(partialPath, resolvedResourceUrl);
     }

+    @Override
     public void addTypeHierarchy(JClassType type) {
       if (!canBeCacheable) {
         return;
@@ -618,7 +617,9 @@
         return false;
       }

- if (!checkDependentResourceUpToDate(lastTimeGenerated, resolvedUrl)) { + // Check whether the resource referenced by the provided URL is up to date
+      long modifiedTime = Util.getResourceModifiedTime(resolvedUrl);
+      if (modifiedTime == 0L || modifiedTime > lastTimeGenerated) {
logger.log(TreeLogger.TRACE, "Found dependent resource that has changed: " + resourceName);
         return false;
       }
@@ -626,62 +627,6 @@

     return true;
   }
-
-  /**
-   * Checks whether a dependent resource referenced by the provided URL is
-   * up to date, based on the provided referenceTime.
-   */
- private boolean checkDependentResourceUpToDate(long referenceTime, URL url) {
-    try {
-      if (url.getProtocol().equals(JAR_PROTOCOL)) {
-        /*
-         * If this resource is contained inside a jar file, such as can
-         * happen if it's bundled in a 3rd-party library, we use the jar
-         * file itself to test whether it's up to date.  We don't want
-         * to call JarURLConnection.getLastModified(), as this is much
-         * slower than using the jar File resource directly.
-         */
-        JarURLConnection jarConn = (JarURLConnection) url.openConnection();
-        url = jarConn.getJarFileURL();
-      }
-
-      long lastModified;
-      if (url.getProtocol().equals(FILE_PROTOCOL)) {
-        /*
-         * Need to handle possibly wonky syntax in a file URL resource.
-         * Modeled after suggestion in this blog entry:
- * http://weblogs.java.net/blog/2007/04/25/how-convert-javaneturl-javaiofile
-         */
-        File file;
-        try {
-          file = new File(url.toURI());
-        } catch (URISyntaxException uriEx) {
-          file = new File(url.getPath());
-        }
-        lastModified = file.lastModified();
-      } else {
-        /*
-         * Don't attempt to handle any other protocol
-         */
-        return false;
-      }
-      if (lastModified == 0L ||
-          lastModified > referenceTime) {
-        return false;
-      }
-    } catch (IOException ioEx) {
-      return false;
-    } catch (RuntimeException ruEx) {
-      /*
- * Return false for any RuntimeException (e.g. a SecurityException), and - * allow the cacheability check to fail, since we don't want to change the - * behavior that would be encountered if no cache is available. Force
-       * resource generators to utilize their own exception handling.
-       */
-      return false;
-    }
-    return true;
-  }

   /*
    * Check properties for cacheability

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to