Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / iapi / services / classfile / ClassInvestigator.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/iapi/services/classfile/ClassInvestigator.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/iapi/services/classfile/ClassInvestigator.java
new file mode 100644 (file)
index 0000000..6f59386
--- /dev/null
@@ -0,0 +1,585 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.iapi.services.classfile.ClassInvestigator\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
+\r
+import java.io.InputStream;\r
+import java.util.Enumeration;\r
+\r
+import java.io.IOException;\r
+import java.util.Vector;\r
+\r
+import org.apache.derby.iapi.services.classfile.VMDescriptor;\r
+import org.apache.derby.iapi.services.classfile.VMDescriptor;\r
+import java.util.HashSet;\r
+\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+import java.util.Enumeration;\r
+import java.util.Collections;\r
+\r
+\r
+/** \r
+*/\r
+\r
+public class ClassInvestigator extends ClassHolder {\r
+\r
+       public static ClassInvestigator load(InputStream is)\r
+               throws IOException {\r
+\r
+               ClassInput classInput = new ClassInput(is);\r
+\r
+               // Check the header\r
+        int magic = classInput.getU4();\r
+        int minor_version = classInput.getU2();\r
+        int major_version = classInput.getU2();\r
+\r
+        if (magic != VMDescriptor.JAVA_CLASS_FORMAT_MAGIC)\r
+               throw new ClassFormatError();\r
+\r
+               //      Read in the Constant Pool\r
+               int constantPoolCount = classInput.getU2();\r
+\r
+               ClassInvestigator ci = new ClassInvestigator(constantPoolCount);\r
+        \r
+        ci.minor_version = minor_version;\r
+        ci.major_version = major_version;      \r
+        \r
+               // Yes, index starts at 1, The '0'th constant pool entry\r
+               // is reserved for the JVM and is not present in the class file.\r
+               for (int i = 1; i < constantPoolCount; ) {\r
+                       ConstantPoolEntry item = ClassInvestigator.getConstant(classInput);\r
+                       i += ci.addEntry(item.getKey(), item);\r
+               }\r
+\r
+               // Read in access_flags and class indexes\r
+               ci.access_flags = classInput.getU2();\r
+               ci.this_class = classInput.getU2();\r
+               ci.super_class = classInput.getU2();\r
+\r
+               // interfaces is a simple int array\r
+               int interfaceCount = classInput.getU2();\r
+               if (interfaceCount != 0) {\r
+                       ci.interfaces = new int[interfaceCount];\r
+                       for (int i = 0; i < interfaceCount; i++)\r
+                               ci.interfaces[i] = classInput.getU2();\r
+               }\r
+\r
+               int fieldCount = classInput.getU2();\r
+               if (fieldCount != 0) {\r
+                       ci.field_info = new MemberTable(fieldCount);\r
+                       for (int i = 0; i < fieldCount; i++)\r
+                       {\r
+                               ci.field_info.addEntry(readClassMember(ci, classInput));\r
+                       }\r
+               }\r
+\r
+               int methodCount = classInput.getU2();\r
+               if (methodCount != 0) {\r
+                       ci.method_info = new MemberTable(methodCount);\r
+                       for (int i = 0; i < methodCount; i++)\r
+                       {\r
+                               ci.method_info.addEntry(readClassMember(ci, classInput));\r
+                       }\r
+               }\r
+\r
+               int attributeCount = classInput.getU2();\r
+               if (attributeCount != 0) {\r
+                       ci.attribute_info = new Attributes(attributeCount);\r
+\r
+                       for (int i = 0; i < attributeCount; i++)\r
+                               ci.attribute_info.addEntry(new AttributeEntry(classInput));\r
+               }\r
+               return ci;\r
+\r
+       }\r
+\r
+       private static ClassMember readClassMember(ClassInvestigator ci, ClassInput in)\r
+               throws IOException {\r
+\r
+               ClassMember member = new ClassMember(ci, in.getU2(),  in.getU2(), in.getU2());\r
+\r
+               int attributeCount = in.getU2();\r
+               if (attributeCount != 0) {\r
+                       member.attribute_info = new Attributes(attributeCount);\r
+                       for (int i = 0; i < attributeCount; i++)\r
+                               member.attribute_info.addEntry(new AttributeEntry(in));\r
+               }\r
+                       \r
+               return member;\r
+       }\r
+\r
+       /*\r
+       **      Constructors.\r
+       */\r
+\r
+       private ClassInvestigator(int constantPoolCount) {\r
+               super(constantPoolCount);\r
+       }\r
+\r
+       /*\r
+       ** Methods to investigate this class\r
+       */\r
+\r
+\r
+       public Enumeration implementedInterfaces()\r
+       {\r
+               int interfaceCount = interfaces == null ? 0 : interfaces.length;\r
+               Vector implemented = new Vector(interfaceCount);\r
+\r
+        for (int i = 0; i < interfaceCount; i++)\r
+        {\r
+            implemented.addElement(className(interfaces[i]));\r
+        }\r
+        return implemented.elements();\r
+       }\r
+    public Enumeration getFields() {\r
+               if (field_info == null)\r
+                       return Collections.enumeration(Collections.EMPTY_LIST);\r
+\r
+               return field_info.entries.elements();\r
+       }\r
+\r
+    public Enumeration getMethods() {\r
+               if (method_info == null)\r
+                       return Collections.enumeration(Collections.EMPTY_LIST);\r
+               return method_info.entries.elements();\r
+       }\r
+\r
+    public Enumeration referencedClasses() {\r
+        return getClasses(getMethods(), getFields() );\r
+    }\r
+\r
+       /**\r
+               Return an Enumeration of all referenced classes\r
+       */\r
+\r
+       private Enumeration getClasses(Enumeration methods, Enumeration fields)\r
+       {\r
+               return new ClassEnumeration(this, cptEntries.elements(), methods, fields);\r
+       }\r
+\r
+       public Enumeration getStrings() {\r
+               HashSet strings = new HashSet(30, 0.8f);\r
+               \r
+               int size = cptEntries.size();\r
+               for (int i = 1; i < size; i++) {\r
+                       ConstantPoolEntry cpe = getEntry(i);\r
+\r
+                       if ((cpe == null) || (cpe.getTag() != VMDescriptor.CONSTANT_String))\r
+                               continue;\r
+\r
+                       CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;\r
+\r
+                       strings.add(nameIndexToString(cii.getI1()));\r
+               }\r
+\r
+               return java.util.Collections.enumeration(strings);\r
+       }\r
+\r
+    public ClassMember getMember(String simpleName, String descriptor) {\r
+\r
+               if (descriptor.startsWith("(")) {\r
+                       if (method_info == null)\r
+                               return null;\r
+                       return method_info.find(simpleName, descriptor);\r
+               }\r
+               else {\r
+                       if (field_info == null)\r
+                               return null;\r
+                       return  field_info.find(simpleName, descriptor);\r
+               }\r
+       }\r
+\r
+       /**\r
+               Return an Enumeration of all Member References\r
+       */\r
+/*\r
+       Enumeration getMemberReferences() {\r
+               return new ReferenceEnumeration(this, elements());\r
+       }\r
+*/\r
+\r
+       /*\r
+       ** Methods to modify the class.\r
+       */\r
+       // remove all atttributes that are not essential\r
+       public void removeAttributes() throws IOException {\r
+\r
+               // Class level attributes\r
+               if (attribute_info != null) {\r
+                       for (int i = attribute_info.size() - 1; i >= 0 ; i--) {\r
+\r
+                               AttributeEntry ae = (AttributeEntry) attribute_info.elementAt(i);\r
+                               String name = nameIndexToString(ae.getNameIndex());\r
+                               if (name.equals("SourceFile"))\r
+                                       attribute_info.removeElementAt(i);\r
+                               else if (name.equals("InnerClasses"))\r
+                                       ; // leave in\r
+                               else\r
+                                       System.err.println("WARNING - Unknown Class File attribute " + name);\r
+                       }\r
+\r
+                       if (attribute_info.size() == 0)\r
+                               attribute_info = null;\r
+               }\r
+               attribute_info = null;\r
+\r
+               // fields\r
+               for (Enumeration e = getFields(); e.hasMoreElements(); ) {\r
+                       ClassMember member = (ClassMember) e.nextElement();\r
+\r
+                       Attributes attrs = member.attribute_info;\r
+\r
+                       if (attrs != null) {\r
+\r
+                               for (int i = attrs.size() - 1; i >= 0 ; i--) {\r
+\r
+                                       AttributeEntry ae = (AttributeEntry) attrs.elementAt(i);\r
+                                       String name = nameIndexToString(ae.getNameIndex());\r
+                                       if (name.equals("ConstantValue"))\r
+                                               ; // leave in\r
+                                       else if (name.equals("Synthetic"))\r
+                                               ; // leave in\r
+                                       else\r
+                                               System.err.println("WARNING - Unknown Field attribute " + name);\r
+                               }\r
+\r
+                               if (attrs.size() == 0)\r
+                                       member.attribute_info = null;\r
+                       }\r
+\r
+               }\r
+\r
+               // methods\r
+               for (Enumeration e = getMethods(); e.hasMoreElements(); ) {\r
+                       ClassMember member = (ClassMember) e.nextElement();\r
+\r
+                       Attributes attrs = member.attribute_info;\r
+\r
+                       if (attrs != null) {\r
+\r
+                               for (int i = attrs.size() - 1; i >= 0 ; i--) {\r
+\r
+                                       AttributeEntry ae = (AttributeEntry) attrs.elementAt(i);\r
+                                       String name = nameIndexToString(ae.getNameIndex());\r
+                                       if (name.equals("Code"))\r
+                                               processCodeAttribute(member, ae);\r
+                                       else if (name.equals("Exceptions"))\r
+                                               ; // leave in\r
+                                       else if (name.equals("Deprecated"))\r
+                                               ; // leave in\r
+                                       else if (name.equals("Synthetic"))\r
+                                               ; // leave in\r
+                                       else\r
+                                               System.err.println("WARNING - Unknown method attribute " + name);\r
+                               }\r
+\r
+                               if (attrs.size() == 0)\r
+                                       member.attribute_info = null;\r
+                       }\r
+\r
+               }\r
+       }\r
+\r
+       private void processCodeAttribute(ClassMember member, AttributeEntry ae) throws IOException {\r
+\r
+               ClassInput ci = new ClassInput(new java.io.ByteArrayInputStream(ae.infoIn));\r
+\r
+\r
+               ci.skipBytes(4); // puts us at code_length\r
+               int len = ci.getU4();\r
+               ci.skipBytes(len); // puts us at exception_table_length\r
+               int count = ci.getU2();\r
+               if (count != 0)\r
+                       ci.skipBytes(8 * count);\r
+\r
+               int nonAttrLength = 4 + 4 + len + 2 + (8 * count);\r
+\r
+               // now at attributes\r
+\r
+               count = ci.getU2();\r
+               if (count == 0)\r
+                       return;\r
+\r
+               int newCount = count;\r
+               for (int i = 0; i < count; i++) {\r
+\r
+                       int nameIndex = ci.getU2();\r
+                       String name = nameIndexToString(nameIndex);\r
+                       if (name.equals("LineNumberTable") || name.equals("LocalVariableTable"))\r
+                               newCount--;\r
+                       else\r
+                               System.err.println("ERROR - Unknown code attribute " + name);\r
+\r
+                       len = ci.getU4();\r
+                       ci.skipBytes(len);\r
+               }\r
+\r
+               if (newCount != 0) {\r
+                       System.err.println("ERROR - expecting all code attributes to be removed");\r
+                       System.exit(1);\r
+               }\r
+\r
+               // this is only coded for all attributes within a Code attribute being removed.\r
+\r
+               byte[] newInfo = new byte[nonAttrLength + 2];\r
+               System.arraycopy(ae.infoIn, 0, newInfo, 0, nonAttrLength);\r
+               // last two bytes are left at 0 which means 0 attributes\r
+               ae.infoIn = newInfo;\r
+       }\r
+\r
+       public void renameClassElements(Hashtable classNameMap, Hashtable memberNameMap) {\r
+\r
+               // this & super class\r
+               renameString(classNameMap, (CONSTANT_Index_info) getEntry(this_class));\r
+               renameString(classNameMap, (CONSTANT_Index_info) getEntry(super_class));\r
+\r
+               // implemented interfaces\r
+               // handled by Class entries below\r
+\r
+               // classes & Strings\r
+               // descriptors\r
+               int size = cptEntries.size();\r
+               for (int i = 1; i < size; i++) {\r
+                       ConstantPoolEntry cpe = getEntry(i);\r
+\r
+                       if (cpe == null)\r
+                               continue;\r
+\r
+                       switch (cpe.getTag()) {\r
+                       case VMDescriptor.CONSTANT_String:\r
+                       case VMDescriptor.CONSTANT_Class:\r
+                               {\r
+                               CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;\r
+                               renameString(classNameMap, cii);\r
+                               break;\r
+                               }\r
+                       case VMDescriptor.CONSTANT_NameAndType:\r
+                               {\r
+                               CONSTANT_Index_info cii = (CONSTANT_Index_info) cpe;\r
+                               String newDescriptor = newDescriptor(classNameMap, nameIndexToString(cii.getI2()));\r
+                               if (newDescriptor != null) {\r
+                                       doRenameString(cii.getI2(), newDescriptor);\r
+                               }\r
+                               break;\r
+                               }\r
+\r
+                       default:\r
+                               continue;\r
+                       }\r
+\r
+               }\r
+\r
+               //System.out.println("Starting Fields");\r
+\r
+               // now the methods & fields, only descriptors at this time\r
+               renameMembers(getFields(), classNameMap, memberNameMap);\r
+\r
+               renameMembers(getMethods(), classNameMap, memberNameMap);\r
+       }\r
+\r
+       private void renameMembers(Enumeration e, Hashtable classNameMap, Hashtable memberNameMap) {\r
+\r
+               for (; e.hasMoreElements(); ) {\r
+                       ClassMember member = (ClassMember) e.nextElement();\r
+\r
+                       String oldMemberName = nameIndexToString(member.name_index);\r
+                       String newMemberName = (String) memberNameMap.get(oldMemberName);\r
+                       if (newMemberName != null)\r
+                               doRenameString(member.name_index, newMemberName);\r
+\r
+                       String newDescriptor = newDescriptor(classNameMap, nameIndexToString(member.descriptor_index));\r
+                       if (newDescriptor != null) {\r
+                               doRenameString(member.descriptor_index, newDescriptor);\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+       private void renameString(Hashtable classNameMap, CONSTANT_Index_info cii) {\r
+\r
+               int index = cii.getI1();\r
+\r
+               String name = nameIndexToString(index);\r
+               String newName = (String) classNameMap.get(name);\r
+               if (newName != null) {\r
+\r
+                       doRenameString(index, newName);\r
+\r
+                       return;\r
+               }\r
+\r
+               // have to look for arrays\r
+               if (cii.getTag() == VMDescriptor.CONSTANT_Class) {\r
+\r
+                       if (name.charAt(0) == '[') {\r
+                               int classOffset = name.indexOf('L') + 1;\r
+\r
+                               String baseClassName = name.substring(classOffset, name.length() - 1);\r
+\r
+\r
+                               newName = (String) classNameMap.get(baseClassName);\r
+\r
+                               if (newName != null) {\r
+\r
+                                       String newArrayClassName = name.substring(0, classOffset) + newName + ";";\r
+\r
+                                       doRenameString(index, newArrayClassName);\r
+\r
+                               }\r
+\r
+                       }\r
+               }\r
+       }\r
+\r
+       private void doRenameString(int index, String newName) {\r
+               ConstantPoolEntry cpe = getEntry(index);\r
+               if (cpe.getTag() != VMDescriptor.CONSTANT_Utf8)\r
+                       throw new RuntimeException("unexpected type " + cpe);\r
+\r
+               CONSTANT_Utf8_info newCpe = new CONSTANT_Utf8_info(newName);\r
+\r
+               cptHashTable.remove(cpe.getKey());\r
+               cptHashTable.put(newCpe.getKey(), newCpe);\r
+\r
+               newCpe.index = index;\r
+\r
+               cptEntries.setElementAt(newCpe, index);\r
+       }\r
+\r
+       private static ConstantPoolEntry getConstant(ClassInput in)\r
+               throws IOException {\r
+\r
+               ConstantPoolEntry item;\r
+               int tag;                \r
+               tag = in.readUnsignedByte();\r
+\r
+               switch (tag) {\r
+               case VMDescriptor.CONSTANT_Class:\r
+               case VMDescriptor.CONSTANT_String:\r
+                       item = new CONSTANT_Index_info(tag, in.getU2(), 0);\r
+                       break;\r
+\r
+               case VMDescriptor.CONSTANT_NameAndType:\r
+               case VMDescriptor.CONSTANT_Fieldref:\r
+               case VMDescriptor.CONSTANT_Methodref:\r
+               case VMDescriptor.CONSTANT_InterfaceMethodref:\r
+                       item = new CONSTANT_Index_info(tag, in.getU2(), in.getU2());\r
+                       break;\r
+\r
+               case VMDescriptor.CONSTANT_Integer:\r
+                       item = new CONSTANT_Integer_info(in.getU4());\r
+                       break;\r
+\r
+               case VMDescriptor.CONSTANT_Float:\r
+                       item = new CONSTANT_Float_info(in.readFloat());\r
+                       break;\r
+\r
+               case VMDescriptor.CONSTANT_Long:\r
+                       item = new CONSTANT_Long_info(in.readLong());\r
+                       break;\r
+\r
+               case VMDescriptor.CONSTANT_Double:\r
+                       item = new CONSTANT_Double_info(in.readDouble());\r
+                       break;\r
+\r
+               case VMDescriptor.CONSTANT_Utf8:\r
+                       item = new CONSTANT_Utf8_info(in.readUTF());\r
+                       break;\r
+               default:\r
+                       throw new ClassFormatError();\r
+               }\r
+\r
+               return item;\r
+       }\r
+       public static String newDescriptor(Hashtable classNameMap, String descriptor) {\r
+\r
+               String newDescriptor = null;\r
+\r
+               int dlen = descriptor.length();\r
+               for (int offset = 0; offset < dlen; ) {\r
+                       char c = descriptor.charAt(offset);\r
+                       switch (c) {\r
+                       case VMDescriptor.C_VOID :\r
+                       case VMDescriptor.C_BOOLEAN:\r
+                       case VMDescriptor.C_BYTE:\r
+                       case VMDescriptor.C_CHAR:\r
+                       case VMDescriptor.C_SHORT:\r
+                       case VMDescriptor.C_INT:\r
+                       case VMDescriptor.C_LONG:\r
+                       case VMDescriptor.C_FLOAT:\r
+                       case VMDescriptor.C_DOUBLE:\r
+                       case VMDescriptor.C_ARRAY:\r
+                       case VMDescriptor.C_METHOD:\r
+                       case VMDescriptor.C_ENDMETHOD:\r
+                       default:\r
+                               offset++;\r
+                               continue;\r
+\r
+                       case VMDescriptor.C_CLASS:\r
+                               {\r
+                               int startOffset = offset;\r
+                               while (descriptor.charAt(offset++) != VMDescriptor.C_ENDCLASS)\r
+                                       ;\r
+                               int endOffset = offset;\r
+\r
+                               // name includes L and ;\r
+                               String name = descriptor.substring(startOffset, endOffset);\r
+                               String newName = (String) classNameMap.get(name);\r
+                               if (newName != null) {\r
+                                       if (newDescriptor == null)\r
+                                               newDescriptor = descriptor;\r
+\r
+                                       // we just replace the first occurance of it,\r
+                                       // the loop will hit any next occurance.\r
+                                       int startPos = newDescriptor.indexOf(name);\r
+\r
+                                       String tmp;\r
+                                       if (startPos == 0)\r
+                                               tmp = newName;\r
+                                       else\r
+                                               tmp = newDescriptor.substring(0, startPos) +\r
+                                                               newName;\r
+\r
+                                       int endPos = startPos + name.length();\r
+\r
+                                       if (endPos < newDescriptor.length()) {\r
+\r
+                                               tmp += newDescriptor.substring(endPos , newDescriptor.length());\r
+                                       }\r
+\r
+\r
+                                       newDescriptor = tmp;\r
+                               }\r
+                               }\r
+                       }\r
+\r
+\r
+               }\r
+               //if (newDescriptor != null) {\r
+               //      System.out.println("O - " + descriptor);\r
+               //      System.out.println("N - " + newDescriptor);\r
+               //}\r
+               return newDescriptor;\r
+       }\r
+}\r