Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / iapi / services / classfile / ClassHolder.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/iapi/services/classfile/ClassHolder.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/iapi/services/classfile/ClassHolder.java
new file mode 100644 (file)
index 0000000..d1806f6
--- /dev/null
@@ -0,0 +1,926 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.iapi.services.classfile.ClassHolder\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.iapi.services.classfile;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.util.Enumeration;\r
+\r
+import java.io.IOException;\r
+import java.util.Vector;\r
+\r
+import org.apache.derby.iapi.util.ByteArray;\r
+import org.apache.derby.iapi.services.classfile.VMDescriptor;\r
+import org.apache.derby.iapi.services.classfile.VMDescriptor;\r
+\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+import java.util.Enumeration;\r
+\r
+\r
+/** Based upon "THE class FILE FORMAT" chapter of "The Java Virtual Machine Specification"\r
+    corresponding to version 1.0.2 of the Java Virtual Machine and 1.0.2 of the\r
+       Java Language Specification.\r
+\r
+    ISBN  0-201-63452-X, September 1996.\r
+       */\r
+\r
+public class ClassHolder {\r
+\r
+\r
+       /*\r
+       ** Constants.\r
+       */\r
+\r
+       /*\r
+       ** Fields\r
+       */\r
+    \r
+    /**\r
+     * Minor class format number defaults to \r
+     * VMDescriptor.JAVA_CLASS_FORMAT_MINOR_VERSION\r
+     * which currently corresponds to a really old (JDK 1.0.2) setting.\r
+     * The default major and minor value is used by the generated code for Derby's\r
+     * SQL statements. Currently there is no need to bump the version\r
+     * number as the generated code does not take advantage of any of the\r
+     * new elements in the class file format. If such a need exists then\r
+     * this can be bumped. One issue is that the change in format numbers\r
+     * is not well documented.\r
+     */\r
+    protected int minor_version = VMDescriptor.JAVA_CLASS_FORMAT_MINOR_VERSION;\r
+\r
+    /**\r
+     * Minor class format number defaults to \r
+     * VMDescriptor.JAVA_CLASS_FORMAT_MAJOR_VERSION\r
+     */\r
+    protected int major_version = VMDescriptor.JAVA_CLASS_FORMAT_MAJOR_VERSION;\r
+    \r
+       protected int access_flags;\r
+       protected int this_class;\r
+       protected int super_class;\r
+\r
+       // protected InterfacesArray interfaces; // can be null\r
+       protected int[] interfaces; //can be null\r
+\r
+       protected MemberTable field_info; // can be null\r
+       protected MemberTable method_info;      // can be null\r
+       protected Attributes attribute_info; // can be null\r
+\r
+       /*\r
+       ** Fields for Constant Pool Table\r
+       */\r
+       protected Hashtable cptHashTable;\r
+       protected Vector cptEntries;\r
+       private int cptEstimatedSize;\r
+\r
+       /**\r
+               Used to search for index entries to avoid object allocation\r
+               in the case a referecne already exists.\r
+       */\r
+       private final CONSTANT_Index_info       searchIndex = new CONSTANT_Index_info(0, 0, 0);\r
+\r
+       /*\r
+       **      Constructors.\r
+       */\r
+\r
+       protected ClassHolder(int estimatedConstantPoolCount) {\r
+               // Constant Pool Information\r
+               // 100 is the estimate of the number of entries that will be generated\r
+               cptEntries = new Vector(estimatedConstantPoolCount);\r
+               cptHashTable = new Hashtable(estimatedConstantPoolCount, (float)0.75);\r
+\r
+               // reserve the 0'th constant pool entry\r
+               cptEntries.setSize(1);\r
+       }\r
+\r
+\r
+       /**\r
+               This will not define a constructor -- it is up\r
+               to the caller to add at least one.\r
+       */\r
+\r
+       public ClassHolder(String fullyQualifiedName, String superClassName,\r
+               int modifiers) {\r
+\r
+               this(100);\r
+\r
+               access_flags = modifiers | /* Modifier.SUPER */ 0x0020;\r
+\r
+               this_class = addClassReference(fullyQualifiedName);\r
+               super_class = addClassReference(superClassName);\r
+               method_info = new MemberTable(0);\r
+       }\r
+\r
+       private void put(ClassFormatOutput out) throws IOException {\r
+\r
+               /* Write out the header */\r
+               out.putU4(VMDescriptor.JAVA_CLASS_FORMAT_MAGIC);\r
+               out.putU2(minor_version);\r
+               out.putU2(major_version);\r
+\r
+               // special case checking that the number of constant\r
+               // pool entries does not exceed the limit of 65535\r
+               // (as it is stored as a U2).\r
+               // Special case to allow somewhat easier debugging\r
+               // of the resulting failure.\r
+               out.putU2("constant_pool", cptEntries.size());\r
+               cptPut(out);\r
+\r
+               out.putU2(access_flags);\r
+               out.putU2(this_class);\r
+               out.putU2(super_class);\r
+\r
+               if (interfaces != null) {\r
+                       int ilen = interfaces.length;\r
+                       out.putU2(ilen);\r
+                       for (int i = 0; i < ilen; i++) {\r
+                               out.putU2(interfaces[i]);\r
+                       }\r
+               } else {\r
+                       out.putU2(0);\r
+               }\r
+\r
+               if (field_info != null) {\r
+                       out.putU2(field_info.size());\r
+                       field_info.put(out);\r
+               } else {\r
+                       out.putU2(0);\r
+               }\r
+\r
+               if (method_info != null) {\r
+                       out.putU2(method_info.size());\r
+                       method_info.put(out);\r
+               } else {\r
+                       out.putU2(0);\r
+               }\r
+\r
+               if (attribute_info != null) {\r
+                       out.putU2(attribute_info.size());\r
+                       attribute_info.put(out);\r
+               } else {\r
+                       out.putU2(0);\r
+               }\r
+\r
+       }\r
+\r
+\r
+       /*\r
+       **      Public methods from ClassHolder.\r
+       */\r
+\r
+       /**\r
+        * Convert the object representation of the class into\r
+        * its class file format.\r
+        * @exception IOException error writing the class\r
+        */\r
+       public ByteArray getFileFormat() throws IOException {\r
+\r
+               int classFileSize = 4 + (10 * 2);\r
+               classFileSize += cptEstimatedSize;\r
+\r
+               if (interfaces != null)\r
+                       classFileSize += (interfaces.length * 2);\r
+\r
+               if (field_info != null)\r
+                       classFileSize += field_info.classFileSize();\r
+\r
+               if (method_info != null)\r
+                       classFileSize += method_info.classFileSize();\r
+\r
+               if (attribute_info != null)\r
+                       classFileSize += attribute_info.classFileSize();\r
+\r
+       \r
+               ClassFormatOutput cfo = new ClassFormatOutput(classFileSize + 200);\r
+\r
+               put(cfo);\r
+\r
+               return new ByteArray(cfo.getData(), 0, cfo.size());\r
+\r
+       }\r
+\r
+       /*\r
+       ** Public methods from ClassMember\r
+       */\r
+\r
+       /** @see ClassMember\r
+       */\r
+       public int getModifier() { return access_flags; }\r
+\r
+       /** @see ClassMember\r
+       */\r
+       public String getName() {\r
+               return className(this_class).replace('/', '.');\r
+       }\r
+       /*\r
+       **      Public methods from ClassHolder\r
+       */\r
+\r
+       /** @see ClassHolder#addMember */\r
+       public ClassMember addMember(String simpleName, String descriptor, int modifier)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (descriptor.startsWith("(")) {\r
+                               if (method_info != null) {\r
+                                       if (method_info.find(simpleName, descriptor) != null) {\r
+                                               SanityManager.THROWASSERT("Method already exists " + simpleName + " " + descriptor);\r
+                                       }\r
+                               }\r
+\r
+                       } else {\r
+                               if (field_info != null) {\r
+                                       if (field_info.find(simpleName, descriptor) != null) {\r
+                                               SanityManager.THROWASSERT("Field already exists " + simpleName + " " + descriptor);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               CONSTANT_Utf8_info utf = addUtf8Entry(simpleName);\r
+\r
+               int nameIndex = utf.getIndex();\r
+               int descriptorIndex = addUtf8Entry(descriptor).getIndex();\r
+\r
+               ClassMember item = new ClassMember(this, modifier, nameIndex, descriptorIndex);\r
+               MemberTable mt;\r
+               if (descriptor.startsWith("(")) {\r
+                       mt = method_info;\r
+                       if (mt == null)\r
+                               mt = method_info = new MemberTable(0);\r
+\r
+               }\r
+               else {\r
+                       mt = field_info;\r
+                       if (mt == null)\r
+                               mt = field_info = new MemberTable(0);\r
+               }\r
+\r
+               mt.addEntry(item);\r
+               return item;\r
+       }\r
+\r
+       /** @see ClassHolder#addFieldReference */\r
+       public int addFieldReference(String className, String simpleName, String descriptor) {\r
+               return addReference(VMDescriptor.CONSTANT_Fieldref, className, simpleName, descriptor);\r
+       }\r
+\r
+       public int addFieldReference(ClassMember field) {\r
+               return addReference(VMDescriptor.CONSTANT_Fieldref, (ClassMember) field);\r
+       }\r
+\r
+       /** @see ClassHolder#addMethodReference */\r
+       public int addMethodReference(String className, String simpleName, String descriptor, boolean isInterface) {\r
+\r
+               int tag = isInterface ? VMDescriptor.CONSTANT_InterfaceMethodref :\r
+                                                               VMDescriptor.CONSTANT_Methodref;\r
+\r
+               return addReference(tag, className, simpleName, descriptor); \r
+       }\r
+\r
+       private int addReference(int tag, String className, String simpleName, String descriptor) {\r
+\r
+               int classIndex = addClassReference(className);\r
+               int nameTypeIndex = addNameAndType(simpleName, descriptor);\r
+\r
+               return addIndexReference(tag, classIndex, nameTypeIndex);\r
+       }\r
+\r
+       private int addReference(int tag, ClassMember member) {\r
+\r
+               int nameTypeIndex = addIndexReference(VMDescriptor.CONSTANT_NameAndType,\r
+                                                       member.name_index, member.descriptor_index);\r
+\r
+               return addIndexReference(tag, this_class, nameTypeIndex);\r
+       }\r
+\r
+       /** @see ClassHolder#addConstant */\r
+       public int addConstant(String value) {\r
+\r
+               return addString(value);\r
+       }\r
+\r
+       /** @see ClassHolder#addUtf8 */\r
+       public int addUtf8(String value) {\r
+\r
+               return addUtf8Entry(value).getIndex();\r
+       }\r
+\r
+\r
+       /** @see ClassHolder#addConstant */\r
+       public int addConstant(int value) {\r
+               return addDirectEntry(new CONSTANT_Integer_info(value));\r
+       }\r
+\r
+       /** @see ClassHolder#addConstant */\r
+       public int addConstant(float value) {\r
+               return addDirectEntry(new CONSTANT_Float_info(value));\r
+       }\r
+\r
+       /** @see ClassHolder#addConstant */\r
+       public int addConstant(long value) {\r
+               return addDirectEntry(new CONSTANT_Long_info(value));\r
+       }\r
+\r
+       /** @see ClassHolder#addConstant */\r
+       public int addConstant(double value) {\r
+               return addDirectEntry(new CONSTANT_Double_info(value));\r
+       }\r
+\r
+\r
+       /** @see ClassMember\r
+       */\r
+       public int getConstantPoolIndex() { return this_class; }\r
+\r
+       public void addAttribute(String attributeName, ClassFormatOutput info) {\r
+\r
+               if (attribute_info == null)\r
+                       attribute_info = new Attributes(1);\r
+\r
+\r
+               CONSTANT_Utf8_info autf = addUtf8Entry(attributeName);\r
+\r
+               int index = autf.getIndex();\r
+\r
+               attribute_info.addEntry(new AttributeEntry(index, info));\r
+       }\r
+\r
+\r
+       public String getSuperClassName() {\r
+               if (super_class == 0)\r
+                       return null;\r
+               else\r
+                       return className(super_class).replace('/', '.');\r
+       }\r
+\r
+\r
+/*\r
+    public ClassMember getMemberReference(String fullyQualifiedClassName, String simpleName, String descriptor) {\r
+\r
+               int classIndex;\r
+\r
+               if (fullyQualifiedClassName == null)\r
+                        classIndex = this_class;\r
+               else\r
+                       classIndex = constantPool.findClass(fullyQualifiedClassName);\r
+\r
+               if (classIndex < 0)\r
+                       return null;\r
+\r
+               int nameAndTypeIndex = constantPool.findNameAndType(simpleName, descriptor);\r
+               if (nameAndTypeIndex < 0)\r
+                       return null;\r
+\r
+        return constantPool.findReference(classIndex, nameAndTypeIndex);\r
+       }\r
+*/\r
+       /*\r
+       ** Public methods from ClassRead\r
+       */\r
+\r
+\r
+\r
+       /*\r
+       ** Implementation specific methods.\r
+       */\r
+\r
+       /*\r
+       ** Methods related to Constant Pool Table\r
+       */\r
+       /**\r
+               Generic add entry to constant pool. Includes the logic\r
+               for an entry to occupy more than one slot (e.g. long).\r
+\r
+               @return The number of slots occupied by the entry.\r
+.\r
+       */\r
+       protected int addEntry(Object key, ConstantPoolEntry item) {\r
+\r
+               item.setIndex(cptEntries.size());\r
+               if (key != null)\r
+                       cptHashTable.put(key, item);\r
+               cptEntries.addElement(item);\r
+\r
+               cptEstimatedSize += item.classFileSize();\r
+\r
+               if (item.doubleSlot()) {\r
+                       cptEntries.addElement(null);\r
+                       return 2;\r
+               } else {\r
+                       return 1;\r
+               }\r
+       }\r
+       \r
+       /**\r
+               Add an entry, but only if it doesn't exist.\r
+\r
+               @return the constant pool index of the added\r
+               or existing item.\r
+       */\r
+       private int addDirectEntry(ConstantPoolEntry item) {\r
+               ConstantPoolEntry existingItem = findMatchingEntry(item);\r
+               if (existingItem != null) {\r
+                       item = existingItem;\r
+                       //foundCount++;\r
+               }\r
+               else {\r
+                       addEntry(item.getKey(), item);\r
+               }\r
+               return item.getIndex();\r
+       }\r
+\r
+       /**\r
+               Add an index reference.\r
+       */\r
+       private int addIndexReference(int tag, int i1, int i2) {\r
+\r
+               // search for the item using the pre-allocated object \r
+               searchIndex.set(tag, i1, i2);\r
+\r
+               ConstantPoolEntry item = findMatchingEntry(searchIndex);\r
+\r
+               if (item == null) {\r
+                       item = new CONSTANT_Index_info(tag, i1, i2);\r
+                       addEntry(item.getKey(), item);\r
+               }\r
+\r
+               return item.getIndex();\r
+       }\r
+\r
+       /**\r
+               Add a class entry to the pool.\r
+       */\r
+       public int addClassReference(String fullyQualifiedName) {\r
+               if (ClassHolder.isExternalClassName(fullyQualifiedName)) {\r
+                       fullyQualifiedName = ClassHolder.convertToInternalClassName(fullyQualifiedName);\r
+                       // System.out.println("addClassReference " + fullyQualifiedName);\r
+               }\r
+\r
+               int name_index = addUtf8Entry(fullyQualifiedName).getIndex();\r
+\r
+               return addIndexReference(VMDescriptor.CONSTANT_Class, name_index, 0);\r
+       }\r
+\r
+       /**\r
+               Add a name and type entry\r
+       */\r
+       private int addNameAndType(String name, String descriptor) {\r
+               int nameIndex = addUtf8Entry(name).getIndex();\r
+\r
+               int descriptorIndex = addUtf8Entry(descriptor).getIndex();\r
+\r
+               return addIndexReference(VMDescriptor.CONSTANT_NameAndType, nameIndex, descriptorIndex);\r
+       }\r
+\r
+       /**\r
+               Add a UTF8 into the pool and return the index to it.\r
+       */\r
+       private CONSTANT_Utf8_info addUtf8Entry(String value) {\r
+\r
+               CONSTANT_Utf8_info item = (CONSTANT_Utf8_info) findMatchingEntry(value);\r
+\r
+               if (item == null) {\r
+\r
+                       item = new CONSTANT_Utf8_info(value);\r
+                       addEntry(value, item);\r
+               }\r
+               return item;\r
+       }\r
+       /**\r
+               Add an extra UTF8 into the pool \r
+       */\r
+       private CONSTANT_Utf8_info addExtraUtf8(String value) {\r
+\r
+               CONSTANT_Utf8_info item = new CONSTANT_Utf8_info(value);\r
+               addEntry(null, item);\r
+\r
+               return item;\r
+       }\r
+\r
+       /**\r
+               Add a string entry\r
+       */\r
+       private int addString(String value) {\r
+               CONSTANT_Utf8_info sutf = addUtf8Entry(value);\r
+               int valueIndex = sutf.setAsString();\r
+               if (valueIndex == 0) {\r
+                       // string is already being used as code\r
+                       valueIndex = addExtraUtf8(value).getIndex();\r
+                       sutf.setAlternative(valueIndex);\r
+               }\r
+\r
+               return addIndexReference(VMDescriptor.CONSTANT_String, valueIndex, 0);\r
+       }\r
+\r
+       /**\r
+               Add a string entry\r
+       */\r
+       private int addCodeUtf8(String value) {\r
+               CONSTANT_Utf8_info sutf = addUtf8Entry(value);\r
+               int index = sutf.setAsCode();\r
+               if (index == 0) {\r
+                       // code string is already being used as string\r
+                       CONSTANT_Utf8_info eutf = addExtraUtf8(value);\r
+                       eutf.setAsCode(); // ensure the replace will happen\r
+                       index = eutf.getIndex();\r
+                       sutf.setAlternative(index);\r
+               }\r
+\r
+               return index;\r
+       }\r
+       protected void cptPut(ClassFormatOutput out) throws IOException {\r
+\r
+               for (Enumeration e = cptEntries.elements(); e.hasMoreElements(); ) {\r
+                       ConstantPoolEntry item = (ConstantPoolEntry) e.nextElement();\r
+                       if (item == null) {\r
+                               continue;\r
+                       }\r
+\r
+                       item.put(out);\r
+               }\r
+       }\r
+\r
+       /*\r
+       ** Methods to convert indexes to constant pool entries and vice-versa.\r
+       */\r
+\r
+       public ConstantPoolEntry getEntry(int index) {\r
+               return (ConstantPoolEntry) cptEntries.elementAt(index);\r
+       }\r
+\r
+       /**\r
+               Return the class name for an index to a CONSTANT_Class_info.\r
+       */\r
+\r
+       protected String className(int classIndex) {\r
+               CONSTANT_Index_info ci = (CONSTANT_Index_info) getEntry(classIndex);\r
+\r
+               return nameIndexToString(ci.getI1()).replace('/', '.');\r
+\r
+       }\r
+\r
+       /*\r
+       ** Methods to find specific types of constant pool entries.\r
+          In these methods we try to avoid using the ConstantPoolEntry.matchValue()\r
+          as that requires creating a new object for the search. The matchValue()\r
+          call is really intended for when objects are being added to the constant pool.\r
+       */\r
+\r
+       /**\r
+               Return the index of a UTF entry or -1 if it doesn't exist.\r
+       */\r
+       int findUtf8(String value) {\r
+\r
+               ConstantPoolEntry item = findMatchingEntry(value);\r
+               if (item == null)\r
+                       return -1;\r
+\r
+               return item.getIndex();\r
+       }\r
+\r
+       /**\r
+               Find a class descriptor (section 4.4.1) and return its\r
+               index, returns -1 if not found.\r
+       */\r
+       public int findClass(String fullyQualifiedName) {\r
+               String internalName = ClassHolder.convertToInternalClassName(fullyQualifiedName);\r
+               int utf_index = findUtf8(internalName);\r
+               if (utf_index < 0)\r
+                       return -1;\r
+\r
+               return findIndexIndex(VMDescriptor.CONSTANT_Class,\r
+                       utf_index, 0);\r
+       }\r
+\r
+\r
+       /**\r
+               Find a name and type descriptor (section 4.4.6) and\r
+               return it's index. \r
+        <p>\r
+        returns -1 if not found.\r
+       */\r
+       public int findNameAndType(String name, String descriptor) {\r
+\r
+               int name_index = findUtf8(name);\r
+               if (name_index < 0)\r
+                       return -1;\r
+               int descriptor_index = findUtf8(descriptor);\r
+               if (descriptor_index < 0)\r
+                       return -1;\r
+\r
+               return findIndexIndex(VMDescriptor.CONSTANT_NameAndType,\r
+                       name_index, descriptor_index);\r
+       }\r
+/*\r
+       public ClassMember findReference(int classIndex, int nameAndTypeIndex) {\r
+\r
+               CONSTANT_Index_info item = findIndexEntry(VMDescriptor.CONSTANT_Methodref,\r
+                               classIndex, nameAndTypeIndex);\r
+\r
+               if (item == null) {\r
+\r
+                       item = findIndexEntry(VMDescriptor.CONSTANT_InterfaceMethodref,\r
+                               classIndex, nameAndTypeIndex);\r
+\r
+                       if (item == null) {\r
+                               item = findIndexEntry(VMDescriptor.CONSTANT_Fieldref,\r
+                                       classIndex, nameAndTypeIndex);\r
+\r
+                               if (item == null)\r
+                                       return null;\r
+\r
+                       }\r
+               }\r
+\r
+               return new ReferenceMember(this, item);\r
+       }\r
+*/\r
+       protected CONSTANT_Index_info findIndexEntry(int tag, int i1, int i2) {\r
+               // search for the item using the pre-allocated object \r
+               searchIndex.set(tag, i1, i2);\r
+\r
+               return (CONSTANT_Index_info) findMatchingEntry(searchIndex);\r
+       }\r
+\r
+       protected int findIndexIndex(int tag, int i1, int i2) {\r
+               CONSTANT_Index_info item = findIndexEntry(tag, i1, i2);\r
+               if (item == null)\r
+                       return -1;\r
+\r
+               return item.getIndex();\r
+       }\r
+\r
+       protected ConstantPoolEntry findMatchingEntry(Object key) {\r
+               return (ConstantPoolEntry) cptHashTable.get(key);\r
+       }\r
+\r
+       /** get a string (UTF) given a name_index into the constant pool\r
+          */\r
+       String nameIndexToString(int index) {\r
+\r
+               return getEntry(index).toString();\r
+       }\r
+\r
+       /** get the class name of a Class given the index of its CONSTANT_Class_info\r
+           entry in the Constant Pool.\r
+               */\r
+\r
+       protected String getClassName(int index) {\r
+\r
+               if (index == 0)\r
+                       return ""; // must be the super class of java.lang.Object, ie. nothing.\r
+\r
+               return  nameIndexToString(getEntry(index).getI1());\r
+       }\r
+\r
+       /*\r
+        * Determine whether the class descriptor string is \r
+        * in external format or not.  Assumes that to be in external\r
+        * format means it must have a '.' or end in an ']'.\r
+        * \r
+        * @param className     the name of the class to check\r
+        *\r
+        * @return true/false\r
+        */\r
+       public static boolean isExternalClassName(String className)\r
+       {\r
+               int len;\r
+               if (className.indexOf('.') != -1)\r
+               {\r
+                       return true;\r
+               }\r
+               else if ((len = className.length()) == 0)\r
+               { \r
+                       return false;\r
+               }\r
+               return (className.charAt(len - 1) == ']');\r
+       }\r
+\r
+       /*\r
+        * Convert a class name to the internal VM class name format.\r
+          See sections 4.3.2, 4.4.1 of the vm spec.\r
+        * The normal leading 'L' and trailing ';' are left\r
+        * off of objects.  This is intended primarily for\r
+        * the class manager.\r
+        * <p>\r
+        * An example of a conversion would be java.lang.Double[]\r
+        * to "[Ljava/lang/Double;".\r
+        <BR>\r
+          java.lang.Double would be converted to "java/lang/Double"\r
+\r
+       <BR>\r
+       Note that for array types the result of convertToInternalClassName()\r
+       and convertToInternalDescriptor() are identical.\r
+\r
+        *\r
+        * @param the external name (cannot be null)\r
+        *\r
+        * @return the internal string\r
+        */\r
+       public static String convertToInternalClassName(String externalName)\r
+       {\r
+               return convertToInternal(externalName, false);\r
+       }\r
+\r
+       /*\r
+        * Convert a class name to internal JVM descriptor format.\r
+          See sections 4.3.2 of the vm spec.\r
+        * <p>\r
+        * An example of a conversion would be "java.lang.Double[]"\r
+        * to "[Ljava/lang/Double;".\r
+        *\r
+        <BR>\r
+          java.lang.Double would be converted to "Ljava/lang/Double;"\r
+\r
+       <BR>\r
+       Note that for array types the result of convertToInternalClassName()\r
+       and convertToInternalDescriptor() are identical.\r
+\r
+        * @param the external name (cannot be null)\r
+        *\r
+        * @return the internal string\r
+        */\r
+       public static String convertToInternalDescriptor(String externalName)\r
+       {\r
+               return convertToInternal(externalName, true);\r
+       }\r
+\r
+       /*\r
+       ** Workhorse method.  Convert to internal format.\r
+\r
+               @param descriptor True if converting to descriptor format, false if\r
+               converting to class name format.\r
+       **\r
+       ** Lifted from BCClass.java. \r
+       **\r
+       ** Returns the result string.\r
+       */\r
+       private static String convertToInternal(String externalName, boolean descriptor)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(externalName != null, "unexpected null");\r
+               }\r
+\r
+               int len = externalName.length();\r
+\r
+               String internalName;    \r
+               String retVal = null;   \r
+               int origLen = len;\r
+               int arity = 0;\r
+\r
+               // first walk through all array-ness\r
+               if (externalName.charAt(len-1) == ']')\r
+               {\r
+                       while (len > 0\r
+                               && externalName.charAt(len-1) == ']'\r
+                               && externalName.charAt(len-2) == '[') \r
+                       {\r
+                               len -= 2;\r
+                               arity++;\r
+                       }\r
+               }\r
+               if (SanityManager.DEBUG) {\r
+                       SanityManager.ASSERT(len > 0);\r
+               }\r
+\r
+               internalName = (origLen == len)? \r
+                                                 externalName \r
+                                               : externalName.substring(0,len);\r
+\r
+           // then check for primitive types ... \r
+               // in length by expected frequency order\r
+\r
+               switch (len) {\r
+                       case 7 :\r
+                       if ("boolean".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_BOOLEAN, arity);\r
+                               }\r
+                               break;\r
+                       case 4 :\r
+                       if ("void".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_VOID, arity);\r
+                               }\r
+                       else if ("long".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_LONG, arity);\r
+                               }\r
+                       else if ("byte".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_BYTE, arity);\r
+                               }\r
+                       else if ("char".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_CHAR, arity);\r
+                               }\r
+                               break;\r
+                       case 3 :\r
+                       if ("int".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_INT, arity);\r
+                               }\r
+                               break;\r
+                       case 6 :\r
+                       if ("double".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_DOUBLE, arity);\r
+                               }\r
+                               break;\r
+                       case 5 :\r
+                       if ("short".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_SHORT, arity);\r
+                               }\r
+                       else if ("float".equals(internalName)) {\r
+                                       retVal = makeDesc(VMDescriptor.C_FLOAT, arity);\r
+                               }\r
+                               break;\r
+               }\r
+\r
+               // then it must be a Java class\r
+               if (retVal == null)\r
+                       retVal = makeDesc(internalName, arity, descriptor);\r
+\r
+               return retVal;\r
+       }\r
+\r
+       /**\r
+               A helper to build a type description based on a built-in type\r
+               and an array arity.\r
+        */\r
+       static private String makeDesc (char builtin, int arity) {\r
+               if (arity == 0)\r
+                       switch (builtin) {\r
+                               case VMDescriptor.C_BYTE : return VMDescriptor.BYTE;\r
+                               case VMDescriptor.C_CHAR : return VMDescriptor.CHAR;\r
+                               case VMDescriptor.C_DOUBLE : return VMDescriptor.DOUBLE;\r
+                               case VMDescriptor.C_FLOAT : return VMDescriptor.FLOAT;\r
+                               case VMDescriptor.C_INT : return VMDescriptor.INT;\r
+                               case VMDescriptor.C_LONG : return VMDescriptor.LONG;\r
+                               case VMDescriptor.C_SHORT : return VMDescriptor.SHORT;\r
+                               case VMDescriptor.C_BOOLEAN : return VMDescriptor.BOOLEAN;\r
+                               case VMDescriptor.C_VOID : return VMDescriptor.VOID;\r
+                               default: \r
+                                       if (SanityManager.DEBUG)\r
+                                               SanityManager.THROWASSERT("No type match");\r
+                                       return null;\r
+                       }\r
+               else {\r
+                       StringBuffer desc = new StringBuffer(arity+3);\r
+\r
+                       for (int i=0;i<arity;i++)\r
+                               desc.append(VMDescriptor.C_ARRAY);\r
+\r
+                       desc.append(ClassHolder.makeDesc(builtin, 0));\r
+\r
+                       return desc.toString();\r
+               }\r
+       }\r
+\r
+       /**\r
+               A helper to build a type description based on a Java class\r
+               and an array arity.\r
+\r
+               If descriptor is true create a descriptor according to\r
+               section 4.3.2 of the vm spec. If false create a class name\r
+               according to sections 4.3.2 and 4.4.1 of the vm spec.\r
+       \r
+        */\r
+       static private String makeDesc (String className, int arity, boolean descriptor) {\r
+\r
+               if (!descriptor && (arity == 0)) {\r
+                       return className.replace('.','/');\r
+               }\r
+\r
+               StringBuffer desc = new StringBuffer(arity+2+className.length());\r
+\r
+               for (int i=0;i<arity;i++)\r
+                       desc.append(VMDescriptor.C_ARRAY);\r
+\r
+               desc.append(VMDescriptor.C_CLASS);\r
+\r
+               desc.append(className.replace('.','/'));\r
+\r
+               desc.append(VMDescriptor.C_ENDCLASS);\r
+\r
+               return desc.toString();\r
+       }\r
+\r
+\r
+}\r