changeset 1716:9ad8a3d44a67

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-ecj 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, 18 Mar 2010 14:56:35 +0000
parents 5d2b941b522e
children 0fe3a89b2dfb
files ChangeLog Makefile.am patches/icedtea-rhino.patch rewriter/com/redhat/rewriter/ClassRewriter.java
diffstat 4 files changed, 152 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Feb 15 17:25:12 2010 +0000
+++ b/ChangeLog	Thu Mar 18 14:56:35 2010 +0000
@@ -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-ecj 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-15 Andrew John Hughes  <ahughes@redhat.com>
 
 	* rewriter/agpl-3.0.txt,
--- a/Makefile.am	Mon Feb 15 17:25:12 2010 +0000
+++ b/Makefile.am	Thu Mar 18 14:56:35 2010 +0000
@@ -116,7 +116,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)
 
 # The Binary plugs directory is called jdk1.7.0 for historical reasons. The
 # name is completely irrelevant; only contains the plugs to build IcedTea.
@@ -190,7 +192,6 @@
 	ALT_PARALLEL_COMPILE_JOBS="$(PARALLEL_JOBS)" \
 	HOTSPOT_BUILD_JOBS="$(PARALLEL_JOBS)" \
 	JAVAC="" \
-	RHINO_JAR="$(RHINO_JAR)" \
 	DISTRIBUTION_ID="$(DIST_ID)"
 
 if WITH_CACAO
@@ -224,6 +225,11 @@
 	@echo 'unset JAVA_HOME'
 	@echo 'export $(ICEDTEA_ENV)'
 
+if WITH_RHINO
+ICEDTEA_ENV += \
+	RHINO_JAR="$(abs_top_builddir)/rhino/rhino.jar"
+endif
+
 # OpenJDK ecj build environment.
 ICEDTEA_BUILD_DIR_ECJ = \
 	$(abs_top_builddir)/$(ECJ_BUILD_OUTPUT_DIR)/
@@ -271,7 +277,6 @@
 	ALT_PARALLEL_COMPILE_JOBS="$(PARALLEL_JOBS)" \
 	HOTSPOT_BUILD_JOBS="$(PARALLEL_JOBS)" \
 	JAVAC="" \
-	RHINO_JAR="$(RHINO_JAR)" \
 	JAR_KNOWS_ATFILE="$(JAR_KNOWS_ATFILE)" \
 	JAR_KNOWS_J_OPTIONS="$(JAR_KNOWS_J_OPTIONS)" \
 	JAR_ACCEPTS_STDIN_LIST="$(JAR_ACCEPTS_STDIN_LIST)"
@@ -298,6 +303,11 @@
 	CROSS_TARGET_ARCH="$(CROSS_TARGET_ARCH)"
 endif
 
+if WITH_RHINO
+ICEDTEA_ENV_ECJ += \
+	RHINO_JAR="$(abs_top_builddir)/rhino/rhino.jar"
+endif
+
 env-ecj:
 	@echo 'unset JAVA_HOME'
 	@echo 'export $(ICEDTEA_ENV_ECJ)'
@@ -1162,7 +1172,8 @@
 	stamps/ports.stamp stamps/patch.stamp stamps/overlay.stamp \
 	$(ICEDTEAPLUGIN_TARGET) $(ICEDTEANPPLUGIN_TARGET) \
 	extra-lib/about.jar stamps/cacao.stamp stamps/visualvm.stamp \
-	stamps/pulse-java.stamp $(ZERO_ASM_BC_ASM_COND)
+	stamps/pulse-java.stamp $(ZERO_ASM_BC_ASM_COND) \
+	stamps/rewrite-rhino.stamp
 	$(ARCH_PREFIX) $(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk \
@@ -1254,7 +1265,8 @@
 	stamps/ports.stamp stamps/patch.stamp stamps/overlay.stamp \
 	$(ICEDTEAPLUGIN_TARGET) $(ICEDTEANPPLUGIN_TARGET) \
 	extra-lib/about.jar stamps/cacao.stamp stamps/visualvm.stamp \
-	stamps/pulse-java.stamp $(ZERO_ASM_BC_ASM_COND)
+	stamps/pulse-java.stamp $(ZERO_ASM_BC_ASM_COND) \
+	stamps/rewrite-rhino.stamp
 	$(ARCH_PREFIX) $(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk \
@@ -1374,7 +1386,7 @@
 stamps/icedtea-ecj.stamp: stamps/bootstrap-directory-symlink-ecj.stamp \
 	stamps/hotspot-tools.stamp stamps/plugs.stamp \
 	stamps/ports-ecj.stamp stamps/patch-ecj.stamp stamps/cacao.stamp \
-	$(ZERO_ASM_BC_ASM_COND)
+	$(ZERO_ASM_BC_ASM_COND) stamps/rewrite-rhino.stamp
 	$(ARCH_PREFIX) $(MAKE) \
 	  $(ICEDTEA_ENV_ECJ) \
 	  -C openjdk-ecj/ \
@@ -2044,6 +2056,39 @@
 
 check-local: jtregcheck
 
+# 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/visualvm.stamp: $(BOOTSTRAP_DIRECTORY_STAMP) stamps/download.stamp \
@@ -2103,6 +2148,9 @@
 dist-openjdk-fsg: stamps/patch-fsg.stamp
 	$(ZIP) -r openjdk-fsg-$(OPENJDK_VERSION) openjdk/
 
+REWRITER_SRCS = $(abs_top_srcdir)/rewriter/com/redhat/rewriter/ClassRewriter.java
+
+
 # Target Aliases
 # ===============
 
@@ -2146,6 +2194,10 @@
 
 overlay: stamps/overlay.stamp
 
+rewriter: stamps/rewriter.stamp
+
+rewrite-rhino: stamps/rewrite-rhino.stamp
+
 plugs: stamps/plugs.stamp
 
 rt-class-files: stamps/rt-class-files.stamp
--- a/patches/icedtea-rhino.patch	Mon Feb 15 17:25:12 2010 +0000
+++ b/patches/icedtea-rhino.patch	Thu Mar 18 14:56:35 2010 +0000
@@ -44,7 +44,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) \
@@ -55,7 +55,7 @@
  package com.sun.script.javascript;
  
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  import javax.script.*;
  
  /**
@@ -66,7 +66,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.*;
  
  /**
@@ -77,7 +77,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.*;
  
@@ -88,7 +88,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.*;
@@ -99,7 +99,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.
@@ -110,7 +110,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
@@ -121,7 +121,7 @@
  package com.sun.script.javascript;
  
 -import sun.org.mozilla.javascript.internal.*;
-+import org.mozilla.javascript.*;
++import sun.org.mozilla.javascript.*;
  import java.util.*;
  
  /**
@@ -132,7 +132,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
@@ -143,7 +143,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.
--- a/rewriter/com/redhat/rewriter/ClassRewriter.java	Mon Feb 15 17:25:12 2010 +0000
+++ b/rewriter/com/redhat/rewriter/ClassRewriter.java	Thu Mar 18 14:56:35 2010 +0000
@@ -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: