Bug 344350 - [runtime][bcel] NPE in
InstructionList.getInstructionHandles()
Replace entire class files rather than patching individual bytes.
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/bcelpatch/org.apache.bcel.generic.BranchHandle.class b/plugins/org.eclipse.objectteams.otequinox.hook/bcelpatch/org.apache.bcel.generic.BranchHandle.class
new file mode 100644
index 0000000..6ac249e
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/bcelpatch/org.apache.bcel.generic.BranchHandle.class
Binary files differ
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/bcelpatch/org.apache.bcel.generic.InstructionHandle.class b/plugins/org.eclipse.objectteams.otequinox.hook/bcelpatch/org.apache.bcel.generic.InstructionHandle.class
new file mode 100644
index 0000000..52432e5
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/bcelpatch/org.apache.bcel.generic.InstructionHandle.class
Binary files differ
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/build.properties b/plugins/org.eclipse.objectteams.otequinox.hook/build.properties
index 293aa98..3ccfbe8 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/build.properties
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/build.properties
@@ -2,7 +2,8 @@
 bin.includes = .,\
                META-INF/,\
                plugin.properties,\
-               about.html
+               about.html,\
+               bcelpatch/
 jars.compile.order = .
 source.. = src/
 javacProjectSettings = true
diff --git a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/TransformerHook.java b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/TransformerHook.java
index af98cfc..52e3762 100644
--- a/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/TransformerHook.java
+++ b/plugins/org.eclipse.objectteams.otequinox.hook/src/org/eclipse/objectteams/otequinox/internal/hook/TransformerHook.java
@@ -113,6 +113,7 @@
 	// As an OSGI extension bundle, we can't depend on the transformer plugin, so we have to hardcode this
 	public static final String  TRANSFORMER_PLUGIN_ID           = "org.eclipse.objectteams.otequinox";
 	
+	private static final String TRANSFORMER_HOOK_ID           = "org.eclipse.objectteams.otequinox.hook";
 	private static final String WORKSPACE_INITIALIZER_PLUGIN_ID = "org.eclipse.objectteams.otdt.earlyui";
 	private static final String OTDT_QUALIFIER = "OTDT";
 
@@ -121,6 +122,7 @@
 	
 	// this one requires hot-fixing:
 	private static final String BCEL_PLUGIN_ID = "org.apache.bcel";
+	private static final String BCEL_PATH_DIR = "bcelpatch/";
 
 	// specific action may be required when this class is loaded:
 	private static final String ORG_OBJECTTEAMS_TEAM = "org.objectteams.Team";
@@ -130,6 +132,8 @@
 
 	
 	private static final HashSet<String> WEAVE_BUNDLES = new HashSet<String>();
+
+	
 	static {
 		String value = System.getProperty("otequinox.weave");
 		if (value != null && value.length() > 0) {
@@ -392,6 +396,7 @@
 	}
 
 	private byte[] fixBCEL(String name, byte[] classbytes) {
+		boolean shouldPatch = false;
 		if ("org.apache.bcel.generic.InstructionHandle".equals(name)) {
 			CRC32 crc32 = new CRC32();
 			crc32.update(classbytes);
@@ -406,10 +411,7 @@
 			if (classbytes[0x105C] != 0x04)
 				detail+="\n\tmodifiers of addHandle="+classbytes[0x105C];			// modifiers of method getHandle at "protected"
 			if (detail.length() == 0) {
-				classbytes[0x0F00] |= 0x20; 				// add "synchronized"
-				classbytes[0x105C] |= 0x20; 				// add "synchronized"
-				this.logger.log(Util.INFO, "hot-patched a bug in class org.apache.bcel.generic.InstructionHandle\n"+
-										"\tsee https://bugs.eclipse.org/bugs/show_bug.cgi?id=344350");
+				shouldPatch = true;
 			} else {
 				this.logger.log(Util.WARNING, "Class org.apache.bcel.generic.InstructionHandle needs a hot-patch but has unexpected byte code:"+detail);
 			}
@@ -427,14 +429,28 @@
 			if (classbytes[0x06F8] != 0x04)
 				detail+="\n\tmodifiers of addHandle="+classbytes[0x06F8];		// modifiers of method getHandle at "protected"
 			if (detail.length() == 0) {
-				classbytes[0x067E] |= 0x20; 				// add "synchronized"
-				classbytes[0x06F8] |= 0x20; 				// add "synchronized"
-				this.logger.log(Util.INFO, "hot-patched a bug in class org.apache.bcel.generic.BranchHandle\n"+
-										"\tsee https://bugs.eclipse.org/bugs/show_bug.cgi?id=344350");
+				shouldPatch = true;
 			} else {
 				this.logger.log(Util.WARNING, "Class org.apache.bcel.generic.BranchHandle needs a hot-patch but has unexpected byte code:"+detail);
 			}
 		}
+		if (shouldPatch) {
+			Bundle transformer = this.packageAdmin.getBundles(TRANSFORMER_HOOK_ID, null)[0];
+			URL entry = transformer.getEntry(BCEL_PATH_DIR+name+".class");
+			byte[] newBytes;
+			try {
+				InputStream stream = entry.openStream();
+				int len = stream.available();
+				newBytes = new byte[len];
+				stream.read(newBytes);
+			} catch (IOException e) {
+				this.logger.log(e, "Failed to hot-patch bcel class "+name);
+				return classbytes;
+			}
+			this.logger.log(Util.INFO, "hot-patched a bug in class "+name+"\n"+
+					"\tsee https://bugs.eclipse.org/bugs/show_bug.cgi?id=344350");
+			return newBytes;
+		}
 		return classbytes;
 	}
 
diff --git a/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/BranchHandle.java b/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/BranchHandle.java
index 4aa69e8..2291b5a 100755
--- a/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/BranchHandle.java
+++ b/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/BranchHandle.java
@@ -61,7 +61,7 @@
     private static BranchHandle bh_list = null; // List of reusable handles
 
 
-    static final BranchHandle getBranchHandle( BranchInstruction i ) {
+    synchronized static final BranchHandle getBranchHandle( BranchInstruction i ) {
         if (bh_list == null) {
             return new BranchHandle(i);
         }
@@ -75,8 +75,10 @@
     /** Handle adds itself to the list of resuable handles.
      */
     protected void addHandle() {
-        next = bh_list;
-        bh_list = this;
+    	synchronized (BranchHandle.class) {
+    		next = bh_list;
+    		bh_list = this;			
+		}
     }
 
 
diff --git a/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/InstructionHandle.java b/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/InstructionHandle.java
index b0d6caa..0b8d416 100755
--- a/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/InstructionHandle.java
+++ b/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/InstructionHandle.java
@@ -122,7 +122,7 @@
 
     /** Factory method.
      */
-    static final InstructionHandle getInstructionHandle( Instruction i ) {
+    synchronized static final InstructionHandle getInstructionHandle( Instruction i ) {
         if (ih_list == null) {
             return new InstructionHandle(i);
         } else {
@@ -170,8 +170,10 @@
     /** Overridden in BranchHandle
      */
     protected void addHandle() {
-        next = ih_list;
-        ih_list = this;
+    	synchronized (InstructionHandle.class) {			
+    		next = ih_list;
+    		ih_list = this;
+		}
     }