Bug 344350 - [runtime][bcel] NPE in
InstructionList.getInstructionHandles()
store here the two (original) classes needing a patch
diff --git a/plugins/org.eclipse.objectteams.runtime/.classpath b/plugins/org.eclipse.objectteams.runtime/.classpath
index 304e861..bd0e74a 100644
--- a/plugins/org.eclipse.objectteams.runtime/.classpath
+++ b/plugins/org.eclipse.objectteams.runtime/.classpath
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" output="bcelpatchbin" path="bcelpatchsrc"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
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
new file mode 100755
index 0000000..4aa69e8
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/BranchHandle.java
@@ -0,0 +1,139 @@
+/**********************************************************************
+ * This file is part of "Object Teams Runtime Environment"-Software
+ *
+ * Copyright 2012 GK Software AG
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Stephan Herrmann - Initial API and implementation
+ *
+ * This file is based on class org.apache.bcel.generic.BranchHandle
+ * originating from the Apache BCEL project which was provided under the
+ * Apache 2.0 license. Original Copyright from BCEL:
+ *
+ * Copyright 2000-2004 The Apache Software Foundation
+ *
+ * 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 org.apache.bcel.generic;
+
+/**
+ * BranchHandle is returned by specialized InstructionList.append() whenever a
+ * BranchInstruction is appended. This is useful when the target of this
+ * instruction is not known at time of creation and must be set later
+ * via setTarget().
+ *
+ * @see InstructionHandle
+ * @see Instruction
+ * @see InstructionList
+ * @version $Id: BranchHandle.java 386056 2006-03-15 11:31:56Z tcurdt $
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class BranchHandle extends InstructionHandle {
+
+ private BranchInstruction bi; // An alias in fact, but saves lots of casts
+
+
+ private BranchHandle(BranchInstruction i) {
+ super(i);
+ bi = i;
+ }
+
+ /** Factory methods.
+ */
+ private static BranchHandle bh_list = null; // List of reusable handles
+
+
+ static final BranchHandle getBranchHandle( BranchInstruction i ) {
+ if (bh_list == null) {
+ return new BranchHandle(i);
+ }
+ BranchHandle bh = bh_list;
+ bh_list = (BranchHandle) bh.next;
+ bh.setInstruction(i);
+ return bh;
+ }
+
+
+ /** Handle adds itself to the list of resuable handles.
+ */
+ protected void addHandle() {
+ next = bh_list;
+ bh_list = this;
+ }
+
+
+ /* Override InstructionHandle methods: delegate to branch instruction.
+ * Through this overriding all access to the private i_position field should
+ * be prevented.
+ */
+ public int getPosition() {
+ return bi.position;
+ }
+
+
+ void setPosition( int pos ) {
+ i_position = bi.position = pos;
+ }
+
+
+ protected int updatePosition( int offset, int max_offset ) {
+ int x = bi.updatePosition(offset, max_offset);
+ i_position = bi.position;
+ return x;
+ }
+
+
+ /**
+ * Pass new target to instruction.
+ */
+ public void setTarget( InstructionHandle ih ) {
+ bi.setTarget(ih);
+ }
+
+
+ /**
+ * Update target of instruction.
+ */
+ public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
+ bi.updateTarget(old_ih, new_ih);
+ }
+
+
+ /**
+ * @return target of instruction.
+ */
+ public InstructionHandle getTarget() {
+ return bi.getTarget();
+ }
+
+
+ /**
+ * Set new contents. Old instruction is disposed and may not be used anymore.
+ */
+ public void setInstruction( Instruction i ) {
+ super.setInstruction(i);
+ if (!(i instanceof BranchInstruction)) {
+ throw new ClassGenException("Assigning " + i
+ + " to branch handle which is not a branch instruction");
+ }
+ bi = (BranchInstruction) i;
+ }
+}
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
new file mode 100755
index 0000000..b0d6caa
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.runtime/bcelpatchsrc/org/apache/bcel/generic/InstructionHandle.java
@@ -0,0 +1,308 @@
+/**********************************************************************
+ * This file is part of "Object Teams Runtime Environment"-Software
+ *
+ * Copyright 2012 GK Software AG
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * Stephan Herrmann - Initial API and implementation
+ *
+ * This file is based on class org.apache.bcel.classfile.ConstantPool
+ * originating from the Apache BCEL project which was provided under the
+ * Apache 2.0 license. Original Copyright from BCEL:
+ *
+ * Copyright 2000-2004 The Apache Software Foundation
+ *
+ * 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 org.apache.bcel.generic;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.bcel.classfile.Utility;
+
+/**
+ * Instances of this class give users a handle to the instructions contained in
+ * an InstructionList. Instruction objects may be used more than once within a
+ * list, this is useful because it saves memory and may be much faster.
+ *
+ * Within an InstructionList an InstructionHandle object is wrapped
+ * around all instructions, i.e., it implements a cell in a
+ * doubly-linked list. From the outside only the next and the
+ * previous instruction (handle) are accessible. One
+ * can traverse the list via an Enumeration returned by
+ * InstructionList.elements().
+ *
+ * @version $Id: InstructionHandle.java 386056 2006-03-15 11:31:56Z tcurdt $
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Instruction
+ * @see BranchHandle
+ * @see InstructionList
+ */
+public class InstructionHandle implements java.io.Serializable {
+
+ InstructionHandle next, prev; // Will be set from the outside
+ Instruction instruction;
+ protected int i_position = -1; // byte code offset of instruction
+ private Set targeters;
+ private Map attributes;
+
+
+ public final InstructionHandle getNext() {
+ return next;
+ }
+
+
+ public final InstructionHandle getPrev() {
+ return prev;
+ }
+
+
+ public final Instruction getInstruction() {
+ return instruction;
+ }
+
+
+ /**
+ * Replace current instruction contained in this handle.
+ * Old instruction is disposed using Instruction.dispose().
+ */
+ public void setInstruction( Instruction i ) { // Overridden in BranchHandle
+ if (i == null) {
+ throw new ClassGenException("Assigning null to handle");
+ }
+ if ((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) {
+ throw new ClassGenException("Assigning branch instruction " + i + " to plain handle");
+ }
+ if (instruction != null) {
+ instruction.dispose();
+ }
+ instruction = i;
+ }
+
+
+ /**
+ * Temporarily swap the current instruction, without disturbing
+ * anything. Meant to be used by a debugger, implementing
+ * breakpoints. Current instruction is returned.
+ */
+ public Instruction swapInstruction( Instruction i ) {
+ Instruction oldInstruction = instruction;
+ instruction = i;
+ return oldInstruction;
+ }
+
+
+ /*private*/protected InstructionHandle(Instruction i) {
+ setInstruction(i);
+ }
+
+ private static InstructionHandle ih_list = null; // List of reusable handles
+
+
+ /** Factory method.
+ */
+ static final InstructionHandle getInstructionHandle( Instruction i ) {
+ if (ih_list == null) {
+ return new InstructionHandle(i);
+ } else {
+ InstructionHandle ih = ih_list;
+ ih_list = ih.next;
+ ih.setInstruction(i);
+ return ih;
+ }
+ }
+
+
+ /**
+ * Called by InstructionList.setPositions when setting the position for every
+ * instruction. In the presence of variable length instructions `setPositions()'
+ * performs multiple passes over the instruction list to calculate the
+ * correct (byte) positions and offsets by calling this function.
+ *
+ * @param offset additional offset caused by preceding (variable length) instructions
+ * @param max_offset the maximum offset that may be caused by these instructions
+ * @return additional offset caused by possible change of this instruction's length
+ */
+ protected int updatePosition( int offset, int max_offset ) {
+ i_position += offset;
+ return 0;
+ }
+
+
+ /** @return the position, i.e., the byte code offset of the contained
+ * instruction. This is accurate only after
+ * InstructionList.setPositions() has been called.
+ */
+ public int getPosition() {
+ return i_position;
+ }
+
+
+ /** Set the position, i.e., the byte code offset of the contained
+ * instruction.
+ */
+ void setPosition( int pos ) {
+ i_position = pos;
+ }
+
+
+ /** Overridden in BranchHandle
+ */
+ protected void addHandle() {
+ next = ih_list;
+ ih_list = this;
+ }
+
+
+ /**
+ * Delete contents, i.e., remove user access and make handle reusable.
+ */
+ void dispose() {
+ next = prev = null;
+ instruction.dispose();
+ instruction = null;
+ i_position = -1;
+ attributes = null;
+ removeAllTargeters();
+ addHandle();
+ }
+
+
+ /** Remove all targeters, if any.
+ */
+ public void removeAllTargeters() {
+ if (targeters != null) {
+ targeters.clear();
+ }
+ }
+
+
+ /**
+ * Denote this handle isn't referenced anymore by t.
+ */
+ public void removeTargeter( InstructionTargeter t ) {
+ if (targeters != null) {
+ targeters.remove(t);
+ }
+ }
+
+
+ /**
+ * Denote this handle is being referenced by t.
+ */
+ public void addTargeter( InstructionTargeter t ) {
+ if (targeters == null) {
+ targeters = new HashSet();
+ }
+ //if(!targeters.contains(t))
+ targeters.add(t);
+ }
+
+
+ public boolean hasTargeters() {
+ return (targeters != null) && (targeters.size() > 0);
+ }
+
+
+ /**
+ * @return null, if there are no targeters
+ */
+ public InstructionTargeter[] getTargeters() {
+ if (!hasTargeters()) {
+ return null;
+ }
+ InstructionTargeter[] t = new InstructionTargeter[targeters.size()];
+ targeters.toArray(t);
+ return t;
+ }
+
+
+ /** @return a (verbose) string representation of the contained instruction.
+ */
+ public String toString( boolean verbose ) {
+ return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose);
+ }
+
+
+ /** @return a string representation of the contained instruction.
+ */
+ public String toString() {
+ return toString(true);
+ }
+
+
+ /** Add an attribute to an instruction handle.
+ *
+ * @param key the key object to store/retrieve the attribute
+ * @param attr the attribute to associate with this handle
+ */
+ public void addAttribute( Object key, Object attr ) {
+ if (attributes == null) {
+ attributes = new HashMap(3);
+ }
+ attributes.put(key, attr);
+ }
+
+
+ /** Delete an attribute of an instruction handle.
+ *
+ * @param key the key object to retrieve the attribute
+ */
+ public void removeAttribute( Object key ) {
+ if (attributes != null) {
+ attributes.remove(key);
+ }
+ }
+
+
+ /** Get attribute of an instruction handle.
+ *
+ * @param key the key object to store/retrieve the attribute
+ */
+ public Object getAttribute( Object key ) {
+ if (attributes != null) {
+ return attributes.get(key);
+ }
+ return null;
+ }
+
+
+ /** @return all attributes associated with this handle
+ */
+ public Collection getAttributes() {
+ if (attributes == null) {
+ attributes = new HashMap(3);
+ }
+ return attributes.values();
+ }
+
+
+ /** Convenience method, simply calls accept() on the contained instruction.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ instruction.accept(v);
+ }
+}