Author: [EMAIL PROTECTED]
Date: Thu Sep  4 15:38:41 2008
New Revision: 3622

Added:
    trunk/dev/core/src/com/google/gwt/dev/shell/EmmaStrategy.java    
(contents, props changed)
Modified:
    trunk/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
    trunk/dev/core/src/com/google/gwt/dev/util/Util.java

Log:
Adds Emma integration for client classes running in hosted mode.  Here are  
the key parts:

1) Bridge Emma's RT class.  This is necessary to allow classes living in  
the CCL to access the outside world, in this case the Emma coverage data  
hook points.

2) Allow instrumented classes to load from disk.  This is necessary to pick  
up the modifications to pre-instrumented classes, which is the most common  
use case with Emma.  This is the only case we currently support, although  
tobyr has some indication that Java class transformers might also work.  We  
only conditionally read class files off disk because it's slower; you have  
to stat the class and java files to compare dates, and then actually read  
the bytes, whereas normally the compiled bytes are already in RAM.  Instant  
hosted mode should level the playing field by always preferring disk.

Review by: bobv


Modified:  
trunk/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java
==============================================================================
--- trunk/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java       
 
(original)
+++ trunk/dev/core/src/com/google/gwt/dev/shell/CompilingClassLoader.java       
 
Thu Sep  4 15:38:41 2008
@@ -354,10 +354,25 @@
     */
    private static byte[] javaScriptHostBytes;

+  private static EmmaStrategy emmaStrategy;
+
    static {
      for (Class<?> c : BRIDGE_CLASSES) {
        BRIDGE_CLASS_NAMES.put(c.getName(), c);
      }
+    /*
+     * Specific support for bridging to Emma since the user classloader is
+     * generally completely isolated.
+     */
+    boolean emmaIsAvailable = false;
+    try {
+      Class<?> emmaBridge = Class.forName(EmmaStrategy.EMMA_RT_CLASSNAME,
+          false, Thread.currentThread().getContextClassLoader());
+      BRIDGE_CLASS_NAMES.put(EmmaStrategy.EMMA_RT_CLASSNAME, emmaBridge);
+      emmaIsAvailable = true;
+    } catch (ClassNotFoundException ignored) {
+    }
+    emmaStrategy = EmmaStrategy.get(emmaIsAvailable);
    }

    private static void classDump(String name, byte[] bytes) {
@@ -637,6 +652,8 @@
        injectJsniFor(compiledClass);

        byte[] classBytes = compiledClass.getBytes();
+      classBytes = emmaStrategy.getEmmaClassBytes(classBytes,  
lookupClassName,
+          compiledClass.getUnit().getLastModified());
        if (classRewriter != null) {
          byte[] newBytes = classRewriter.rewrite(className, classBytes);
          if (CLASS_DUMP) {

Added: trunk/dev/core/src/com/google/gwt/dev/shell/EmmaStrategy.java
==============================================================================
--- (empty file)
+++ trunk/dev/core/src/com/google/gwt/dev/shell/EmmaStrategy.java       Thu Sep 
  
4 15:38:41 2008
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2008 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.shell;
+
+import com.google.gwt.dev.util.Util;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * Provides various strategies for emma integration based on runtime  
detection.
+ */
+abstract class EmmaStrategy {
+
+  private static class NoEmmaStrategy extends EmmaStrategy {
+    public byte[] getEmmaClassBytes(byte[] classBytes, String slashedName,
+        long unitLastModified) {
+      return classBytes;
+    }
+  }
+
+  private static class PreinstrumentedEmmaStrategy extends EmmaStrategy {
+    public byte[] getEmmaClassBytes(byte[] classBytes, String slashedName,
+        long unitLastModified) {
+      // Check for an existing class on the classpath.
+      URL url = Thread.currentThread().getContextClassLoader().getResource(
+          slashedName + ".class");
+      if (url != null) {
+        // We found it on the class path.
+        try {
+          URLConnection conn = url.openConnection();
+          if (conn.getLastModified() >= unitLastModified) {
+            // It's as new as the source file, let's use it.
+            byte[] result = Util.readURLConnectionAsBytes(conn);
+            if (result != null) {
+              return result;
+            }
+            // Fall through.
+          }
+          // Fall through.
+        } catch (IOException ignored) {
+          // Fall through.
+        }
+      }
+
+      // Just return what we got.
+      return classBytes;
+    }
+  }
+
+  /**
+   * Classname for Emma's RT, to enable bridging.
+   */
+  public static final String EMMA_RT_CLASSNAME = "com.vladium.emma.rt.RT";
+
+  /**
+   * Gets the emma classloading strategy.
+   */
+  public static EmmaStrategy get(boolean emmaIsAvailable) {
+    /*
+     * Theoretically, emmarun could be using an instrumented ClassLoader,  
but in
+     * practice we haven't been able to make GWT run at all in this case.
+     */
+    if (!emmaIsAvailable) {
+      return new NoEmmaStrategy();
+    } else {
+      return new PreinstrumentedEmmaStrategy();
+    }
+  }
+
+  public abstract byte[] getEmmaClassBytes(byte[] classBytes,
+      String slashedName, long unitLastModified);
+
+}

Modified: trunk/dev/core/src/com/google/gwt/dev/util/Util.java
==============================================================================
--- trunk/dev/core/src/com/google/gwt/dev/util/Util.java        (original)
+++ trunk/dev/core/src/com/google/gwt/dev/util/Util.java        Thu Sep  4  
15:38:41 2008
@@ -599,22 +599,12 @@
     * @return null if the file could not be read
     */
    public static byte[] readURLAsBytes(URL url) {
-    // ENH: add a weak cache that has an additional check against the file  
date
-    InputStream input = null;
      try {
-      URLConnection connection = url.openConnection();
-      connection.setUseCaches(false);
-      input = connection.getInputStream();
-      int contentLength = connection.getContentLength();
-      if (contentLength < 0) {
-        return null;
-      }
-
-      return readBytesFromInputStream(input, contentLength);
+      URLConnection conn = url.openConnection();
+      conn.setUseCaches(false);
+      return readURLConnectionAsBytes(conn);
      } catch (IOException e) {
        return null;
-    } finally {
-      Utility.close(input);
      }
    }

@@ -622,13 +612,30 @@
     * @return null if the file could not be read
     */
    public static char[] readURLAsChars(URL url) {
-    // ENH: add a weak cache that has an additional check against the file  
date
      byte[] bytes = readURLAsBytes(url);
      if (bytes != null) {
        return toString(bytes, DEFAULT_ENCODING).toCharArray();
      }

      return null;
+  }
+
+  public static byte[] readURLConnectionAsBytes(URLConnection connection) {
+    // ENH: add a weak cache that has an additional check against the file  
date
+    InputStream input = null;
+    try {
+      input = connection.getInputStream();
+      int contentLength = connection.getContentLength();
+      if (contentLength < 0) {
+        return null;
+      }
+
+      return readBytesFromInputStream(input, contentLength);
+    } catch (IOException e) {
+      return null;
+    } finally {
+      Utility.close(input);
+    }
    }

    /**

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

Reply via email to