changeset 2168:8dc6e1ff8ccf

Fix a number of issues and enable the Rhino rewriter in the build. 2010-02-17 Andrew John Hughes <ahughes@redhat.com> PR icedtea/179 * ChangeLog: Remove rogue whitespace highlighted by emacs. * Makefile.am: (REWRITER_SRCS): Sources for class file rewriter. Only set RHINO_JAR when WITH_RHINO is set. Point to rewritten JAR file in build directory. Add rewriter and license to EXTRA_DIST. Make icedtea, icedtea-debug and icedtea-boot depend on rewrite-rhino.stamp. (stamps/rewriter.stamp): Build the class file rewriter. (stamps/rewrite-rhino.stamp): Rewrite the system Rhino JAR file to use the sun.org.mozilla namespace to avoid conflicts. (rewriter): New alias for stamps/rewriter.stamp. (rewrite-rhino): Likewise for stamps/rewrite-rhino.stamp. * patches/icedtea-rhino.patch: Copy rather than symlink the JAR file. Only drop the internal suffix on the javascript package names. * rewriter/com/redhat/rewriter/ClassRewriter.java: (executor): Use a single threaded executor when debugging is enabled. (tasks): Store the Futures returned by the executor for later checking. (main(String[])): Log what happens when processFile returns and handle any exceptions using Futures. (call()): Ensure srcDir/destDir replacement always matches with a trailing slash to avoid odd rewrites. Loop directory creation to avoid possible race issues. Increase logging and fix a number of issues with the rewrite: * Fix off-by-one loop bug so final entry is inspected. * Handle double entries which occur with 8-byte entries (doubles and longs): http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#16628
author Andrew John Hughes <ahughes@redhat.com>
date Thu, 20 May 2010 14:37:32 +0100
parents c2fd9278967c
children 156a49055853
files ChangeLog Makefile.am patches/icedtea-rhino.patch rewriter/com/redhat/rewriter/ClassRewriter.java
diffstat 4 files changed, 148 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Feb 17 14:46:46 2010 +0100
+++ b/ChangeLog	Thu May 20 14:37:32 2010 +0100
@@ -1,3 +1,38 @@
+2010-02-17 Andrew John Hughes  <ahughes@redhat.com>
+
+	PR icedtea/179
+	* ChangeLog: Remove rogue whitespace highlighted
+	by emacs.
+	* Makefile.am:
+	(REWRITER_SRCS): Sources for class file rewriter.
+	Only set RHINO_JAR when WITH_RHINO is set.  Point
+	to rewritten JAR file in build directory.  Add
+	rewriter and license to EXTRA_DIST.  Make icedtea,
+	icedtea-debug and icedtea-boot depend on rewrite-rhino.stamp.
+	(stamps/rewriter.stamp): Build the class file rewriter.
+	(stamps/rewrite-rhino.stamp): Rewrite the system Rhino JAR
+	file to use the sun.org.mozilla namespace to avoid conflicts.
+	(rewriter): New alias for stamps/rewriter.stamp.
+	(rewrite-rhino): Likewise for stamps/rewrite-rhino.stamp.
+	* patches/icedtea-rhino.patch:
+	Copy rather than symlink the JAR file.  Only drop the
+	internal suffix on the javascript package names.
+	* rewriter/com/redhat/rewriter/ClassRewriter.java:
+	(executor): Use a single threaded executor when
+	debugging is enabled.
+	(tasks): Store the Futures returned by the executor
+	for later checking.
+	(main(String[])): Log what happens when processFile
+	returns and handle any exceptions using Futures.
+	(call()): Ensure srcDir/destDir replacement always
+	matches with a trailing slash to avoid odd rewrites.
+	Loop directory creation to avoid possible race issues.
+	Increase logging and fix a number of issues with the rewrite:
+	  * Fix off-by-one loop bug so final entry is inspected.
+	  * Handle double entries which occur with 8-byte entries
+	    (doubles and longs):
+	http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#16628
+
 2010-02-17  Xerxes RĂ„nby  <xerxes@zafena.se>
 
 	* ports/hotspot/src/share/vm/shark/sharkCompiler.cpp
@@ -9,7 +44,7 @@
 	Allways define llvm/Support/CommandLine.h.
 
 2010-02-16  Gary Benson  <gbenson@redhat.com>
-	
+
 	* contrib/jck/compile-native-code.sh: Add s390.
 
 2009-10-05  Edward Nevill    <ed@camswl.com>
--- a/Makefile.am	Wed Feb 17 14:46:46 2010 +0100
+++ b/Makefile.am	Thu May 20 14:37:32 2010 +0100
@@ -258,6 +258,8 @@
 
 PLUGIN_TEST_SRCS = $(abs_top_srcdir)/plugin/tests/LiveConnect/*.java
 
+REWRITER_SRCS = $(abs_top_srcdir)/rewriter/com/redhat/rewriter/ClassRewriter.java
+
 # Patch list
 
 ICEDTEA_PATCHES = \
@@ -507,7 +509,6 @@
 	JDK_HOME="" \
 	QUIETLY="" \
 	ANT_RESPECT_JAVA_HOME="TRUE" \
-	RHINO_JAR="$(RHINO_JAR)" \
 	DISTRIBUTION_ID="$(DIST_ID)" \
 	DERIVATIVE_ID="$(ICEDTEA_NAME) $(PACKAGE_VERSION)$(ICEDTEA_REV)" \
 	ALT_JIBX_LIBS_PATH="$(JIBX_DEPS_DIR)" \
@@ -544,6 +545,11 @@
 	HOTSPOT_BUILD_VERSION="$(HOTSPOT_REVISION)"
 endif
 
+if WITH_RHINO
+ICEDTEA_ENV += \
+	RHINO_JAR="$(abs_top_builddir)/rhino/rhino.jar"
+endif
+
 # OpenJDK boot build environment.
 ICEDTEA_ENV_BOOT = $(ICEDTEA_ENV) \
 	BOOTCLASSPATH_CLS_RT="-bootclasspath $(ICEDTEA_CLS_DIR_BOOT):$(ICEDTEA_RT)" \
@@ -729,7 +735,9 @@
 	tapset/hotspot.stp.in \
 	tapset/hotspot_jni.stp.in \
 	scripts/jni_create_stap.c \
-	scripts/jni_desc
+	scripts/jni_desc \
+	rewriter/agpl-3.0.txt \
+	$(REWRITER_SRCS)
 
 # Top-Level Targets
 # =================
@@ -1781,7 +1789,8 @@
 stamps/icedtea.stamp: stamps/bootstrap-directory-symlink-stage2.stamp \
  stamps/download.stamp stamps/extract.stamp $(OPENJDK_TREE) \
  stamps/plugin.stamp $(JNLP_ABOUT_TARGET) stamps/cacao.stamp \
- stamps/netx-dist.stamp stamps/liveconnect-dist.stamp stamps/pulse-java.stamp
+ stamps/netx-dist.stamp stamps/liveconnect-dist.stamp stamps/pulse-java.stamp \
+ stamps/rewrite-rhino.stamp
 	$(ARCH_PREFIX) $(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk/ \
@@ -1864,7 +1873,8 @@
 stamps/icedtea-debug.stamp: stamps/bootstrap-directory-symlink-stage2.stamp \
  stamps/download.stamp stamps/extract.stamp $(OPENJDK_TREE) \
  stamps/plugin.stamp $(JNLP_ABOUT_TARGET) stamps/cacao.stamp \
- stamps/netx-dist.stamp stamps/liveconnect-dist.stamp stamps/pulse-java.stamp
+ stamps/netx-dist.stamp stamps/liveconnect-dist.stamp stamps/pulse-java.stamp \
+ stamps/rewrite-rhino.stamp
 	$(ARCH_PREFIX) $(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk/ \
@@ -1975,7 +1985,8 @@
 
 stamps/icedtea-boot.stamp: stamps/bootstrap-directory-symlink-stage1.stamp \
  stamps/download.stamp $(OPENJDK_BOOT_TREE) stamps/plugs.stamp \
- stamps/netx-dist.stamp stamps/liveconnect-dist.stamp stamps/cacao.stamp
+ stamps/netx-dist.stamp stamps/liveconnect-dist.stamp stamps/cacao.stamp \
+ stamps/rewrite-rhino.stamp
 	$(ARCH_PREFIX) $(MAKE) \
 	  $(ICEDTEA_ENV_BOOT) \
 	  -C openjdk-boot \
@@ -2270,6 +2281,39 @@
 
 # end of pulse-java
 
+# Rhino support
+
+stamps/rewriter.stamp: $(INITIAL_BOOTSTRAP_LINK_STAMP)
+if WITH_RHINO
+	(cd $(abs_top_srcdir)/rewriter ; \
+	 $(ICEDTEA_BOOT_DIR)/bin/javac -g \
+	 -d $(abs_top_builddir)/rewriter $(REWRITER_SRCS) \
+	)
+endif
+	mkdir -p stamps
+	touch stamps/rewriter.stamp
+
+stamps/rewrite-rhino.stamp: stamps/rewriter.stamp $(RHINO_JAR)
+if WITH_RHINO
+	mkdir -p rhino/rhino.{old,new}
+	(cd rhino/rhino.old ; jar xf $(RHINO_JAR))
+	$(ICEDTEA_BOOT_DIR)/bin/java -cp $(abs_top_builddir)/rewriter \
+	  com.redhat.rewriter.ClassRewriter \
+	  $(abs_top_builddir)/rhino/rhino.old $(abs_top_builddir)/rhino/rhino.new \
+	  org.mozilla sun.org.mozilla
+	(cd rhino/rhino.old ; \
+	 for files in `find -type f -not -name '*.class'` ; do \
+	   new_file=../rhino.new/`echo $$files|sed -e 's#org#sun/org#'` ; \
+	   mkdir -p `dirname $$new_file` ; \
+	   cp -v $$files $$new_file ; \
+	   sed -ie 's#org\.mozilla#sun.org.mozilla#g' $$new_file ; \
+	 done \
+	)
+	(cd rhino/rhino.new ; jar cfm ../rhino.jar META-INF/MANIFEST.MF sun )
+endif
+	mkdir -p stamps
+	touch stamps/rewrite-rhino.stamp
+
 # VisualVM
 
 stamps/nbplatform.stamp: $(INITIAL_BOOTSTRAP_LINK_STAMP) stamps/extract-visualvm.stamp
@@ -2785,6 +2829,10 @@
 
 plugin-tests: stamps/plugin-tests.stamp
 
+rewriter: stamps/rewriter.stamp
+
+rewrite-rhino: stamps/rewrite-rhino.stamp
+
 plugs: stamps/plugs.stamp
 
 pulse-java: stamps/pulse-java.stamp
--- a/patches/icedtea-rhino.patch	Wed Feb 17 14:46:46 2010 +0100
+++ b/patches/icedtea-rhino.patch	Thu May 20 14:37:32 2010 +0100
@@ -54,7 +54,7 @@
  	$(CP) $(RT_JAR) $(JRE_IMAGE_DIR)/lib/rt.jar
  	$(CP) $(RESOURCES_JAR) $(JRE_IMAGE_DIR)/lib/resources.jar
  	$(CP) $(JSSE_JAR) $(JRE_IMAGE_DIR)/lib/jsse.jar
-+	$(LN) -sf $(RHINO_JAR) $(JRE_IMAGE_DIR)/lib/rhino.jar
++	$(CP) $(RHINO_JAR) $(JRE_IMAGE_DIR)/lib/rhino.jar
  	@# Generate meta-index to make boot and extension class loaders lazier
  	$(CD) $(JRE_IMAGE_DIR)/lib && \
  	    $(BOOT_JAVA_CMD) -jar $(BUILDMETAINDEX_JARFILE) \
@@ -66,7 +66,7 @@
  
  package com.sun.script.javascript;
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  import javax.script.*;
  import java.util.*;
  
@@ -78,7 +78,7 @@
  
  import javax.script.Invocable;
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  
  /**
   * This class implements Rhino-like JavaAdapter to help implement a Java
@@ -90,7 +90,7 @@
  package com.sun.script.javascript;
  
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  import java.util.*;
  
  /**
@@ -102,7 +102,7 @@
  
  import java.util.*;
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  
  /**
   * This class prevents script access to certain sensitive classes.
@@ -114,7 +114,7 @@
  package com.sun.script.javascript;
  import javax.script.*;
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  
  /**
   * Represents compiled JavaScript code.
@@ -126,7 +126,7 @@
  import javax.script.*;
  import java.util.*;
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  import com.sun.script.util.*;
  
  /**
@@ -138,7 +138,7 @@
  import com.sun.script.util.*;
  import javax.script.*;
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  import java.lang.reflect.Method;
  import java.io.*;
  import java.util.*;
@@ -150,7 +150,7 @@
  package com.sun.script.javascript;
  
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  import javax.script.*;
  
  /**
@@ -162,7 +162,7 @@
  import java.lang.reflect.*;
  import static sun.security.util.SecurityConstants.*;
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  
  /**
   * This wrap factory is used for security reasons. JSR 223 script
--- a/rewriter/com/redhat/rewriter/ClassRewriter.java	Wed Feb 17 14:46:46 2010 +0100
+++ b/rewriter/com/redhat/rewriter/ClassRewriter.java	Thu May 20 14:37:32 2010 +0100
@@ -27,11 +27,15 @@
 
 import java.nio.charset.Charset;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 import java.util.logging.ConsoleHandler;
@@ -56,15 +60,21 @@
   /**
    * The executor for submitting rewriting jobs.
    */
-  private static final ExecutorService executor = Executors.newCachedThreadPool();
+  private static final ExecutorService executor = DEBUG ?
+    Executors.newSingleThreadExecutor() : Executors.newCachedThreadPool();
 
   /**
    * The source directory, set once by main.
    */
   private static File srcDir;
 
+  /**
+   * The list of tasks submitted to the executor.
+   */
+  private static List<Future<Void>> tasks = new ArrayList<Future<Void>>();
+
   public static void main(String[] args)
-    throws Exception
+    throws ExecutionException, InterruptedException
   {
     if (args.length < 4)
       {
@@ -78,17 +88,15 @@
     handler.setLevel(level);
     logger.addHandler(handler);
     srcDir = new File(args[0]);
-    try
-      {
-        processFile(srcDir, args[1], args[2], args[3]);
-      }
-    finally
-      {
-        executor.shutdown();
-        executor.awaitTermination(1, TimeUnit.MINUTES);
-        if (!executor.isTerminated())
-          throw new Exception("Rewriting failed to complete");
-      }
+    processFile(srcDir, args[1], args[2], args[3]);
+    logger.info("Waiting for rewrites to complete...");
+    executor.shutdown();
+    executor.awaitTermination(1, TimeUnit.MINUTES);
+    logger.info("Checking for errors...");
+    // Check for exceptions
+    for (Future<Void> f : tasks)
+      f.get();
+    logger.info("Rewriting completed successfully.");
   }
 
   private static void processFile(File srcDir, String destDir,
@@ -103,7 +111,8 @@
     else if (srcDir.getName().endsWith(".class"))
       {
         logger.info("Processing class " + srcDir);
-        executor.submit(new ClassRewriter(srcDir, destDir, oldPkg, newPkg));
+        tasks.add(executor.submit(new ClassRewriter(srcDir, destDir,
+                                                    oldPkg, newPkg)));
       }
     else
       logger.fine("Skipping " + srcDir);
@@ -147,8 +156,11 @@
     String dollaredNewPackage = newPackage.replace(".", "$");
 
     File outClass =
-      new File(classFile.getPath().replace(srcDir.getPath(), destDir).replace(slashedOldPackage, slashedNewPackage));
-    outClass.getParentFile().mkdirs();
+      new File(classFile.getPath().replace(srcDir.getPath() + File.separator,
+                                           destDir + File.separator).replace(slashedOldPackage, slashedNewPackage));
+    File targetDir = outClass.getParentFile();
+    while (!targetDir.exists())
+      outClass.getParentFile().mkdirs();
 
     DataInputStream is = new DataInputStream(new FileInputStream(classFile));
     DataOutputStream os = new DataOutputStream(new FileOutputStream(outClass));
@@ -170,14 +182,14 @@
       throw new IOException("Could not read version number.");
     os.write(version);
 
-    short cpCount = is.readShort();
+    int cpCount = is.readUnsignedShort();
     os.writeShort(cpCount);
     logger.fine("Constant pool has " + cpCount + " items.");
 
-    for (int a = 1; a < cpCount - 1; ++a)
+    for (int a = 1; a < cpCount ; ++a)
       {
-        String prefix = "At index " + a + " : ";
-        byte tag = (byte) is.read();
+        byte tag = is.readByte();
+        String prefix = "At index " + a + ", tag " + tag + ": ";
         os.write(tag);
         switch (tag)
           {
@@ -186,11 +198,23 @@
             String data = is.readUTF();
             logger.fine(prefix + "String " + data);
             if (data.contains(oldPackage))
-              data = data.replace(oldPackage, newPackage);
+              {
+                logger.fine(String.format("%s: Found %s\n", outClass.toString(), data));
+                data = data.replace(oldPackage, newPackage);
+                logger.fine(String.format("%s: Rewriting to %s\n", outClass.toString(), data));
+              }
             else if (data.contains(slashedOldPackage))
-              data = data.replace(slashedOldPackage, slashedNewPackage);
+              {
+                logger.fine(String.format("%s: Found %s\n", outClass.toString(), data));
+                data = data.replace(slashedOldPackage, slashedNewPackage);
+                logger.fine(String.format("%s: Rewriting to %s\n", outClass.toString(), data));
+              }
             else if (data.contains(dollaredOldPackage))
-              data = data.replace(dollaredOldPackage, dollaredNewPackage);
+              {
+                logger.fine(String.format("%s: Found %s\n", outClass.toString(), data));
+                data = data.replace(dollaredOldPackage, dollaredNewPackage);
+                logger.fine(String.format("%s: Rewriting to %s\n", outClass.toString(), data));
+              }
             os.writeUTF(data);
             break;
           case 3:
@@ -210,12 +234,14 @@
             long longBytes = is.readLong();
             logger.fine(prefix + "Long " + longBytes);
             os.writeLong(longBytes);
+            ++a; // longs count as two entries
             break;
           case 6:
             /* CONSTANT_Double_Info */
             double doubleBytes = is.readDouble();
             logger.fine(prefix + "Double " + doubleBytes);
             os.writeDouble(doubleBytes);
+            ++a; // doubles count as two entries
             break;
           case 7:
           case 8: