--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.iapi.services.classfile.ClassEnumeration\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 java.util.Enumeration;\r
+import java.util.HashSet;\r
+import java.util.StringTokenizer;\r
+import org.apache.derby.iapi.services.classfile.VMDescriptor;\r
+\r
+/**\r
+ An enumeration that filters only classes\r
+ from the enumeration of the class pool.\r
+\r
+ Code has been added to also include classes referenced in method and\r
+ field signatures.\r
+*/\r
+\r
+\r
+class ClassEnumeration implements Enumeration {\r
+ ClassHolder cpt;\r
+ Enumeration inner;\r
+ CONSTANT_Index_info position;\r
+ HashSet foundClasses;\r
+ Enumeration classList;\r
+\r
+ ClassEnumeration( ClassHolder cpt,\r
+ Enumeration e,\r
+ Enumeration methods,\r
+ Enumeration fields)\r
+ {\r
+ this.cpt = cpt;\r
+ inner = e;\r
+ foundClasses = new HashSet(30, 0.8f);\r
+ findMethodReferences(methods, foundClasses);\r
+ findFieldReferences(fields, foundClasses);\r
+ findClassReferences(foundClasses);\r
+ classList = java.util.Collections.enumeration(foundClasses);\r
+\r
+ }\r
+\r
+ public boolean hasMoreElements() {\r
+ return classList.hasMoreElements();\r
+ }\r
+\r
+ // uses cpt and inner\r
+ private void findClassReferences(HashSet foundClasses)\r
+ {\r
+\r
+ ConstantPoolEntry item;\r
+ CONSTANT_Index_info ref;\r
+\r
+\r
+ while (inner.hasMoreElements())\r
+ {\r
+ item = (ConstantPoolEntry) inner.nextElement();\r
+ if (item == null)\r
+ continue;\r
+ if (item.getTag() == VMDescriptor.CONSTANT_Class)\r
+ {\r
+ ref = (CONSTANT_Index_info) item;\r
+\r
+ String className = cpt.className(ref.getIndex());\r
+\r
+ // if this is an array type, distillClasses can\r
+ // handle it\r
+ if (className.startsWith("["))\r
+ {\r
+ distillClasses(className, foundClasses);\r
+ continue;\r
+ }\r
+\r
+ // now we've got either a primitive type or a classname\r
+ // primitive types are all a single char\r
+\r
+ if (className.length() > 1)\r
+ {\r
+ //we've got a class\r
+ if (className.startsWith("java"))\r
+ {\r
+ //skip it\r
+ continue;\r
+ }\r
+\r
+ foundClasses.add(className);\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ private void findMethodReferences( Enumeration methods,\r
+ HashSet foundClasses)\r
+ {\r
+ while (methods.hasMoreElements())\r
+ {\r
+ ClassMember member = (ClassMember) methods.nextElement();\r
+ String description = member.getDescriptor();\r
+ distillClasses(description, foundClasses);\r
+ }\r
+ }\r
+\r
+ private void findFieldReferences( Enumeration fields,\r
+ HashSet foundClasses)\r
+ {\r
+ while (fields.hasMoreElements())\r
+ {\r
+ ClassMember member = (ClassMember) fields.nextElement();\r
+ String description = member.getDescriptor();\r
+ distillClasses(description, foundClasses);\r
+ }\r
+ }\r
+\r
+ void distillClasses(String fieldOrMethodSig, HashSet foundClasses)\r
+ {\r
+ if (fieldOrMethodSig == null || fieldOrMethodSig.length() < 1)\r
+ {\r
+ //empty string\r
+ return;\r
+ }\r
+\r
+ if (fieldOrMethodSig.charAt(0) != '(')\r
+ {\r
+ // first time through, we're dealing with a field here\r
+ // otherwise, it is a token from a method signature\r
+\r
+ int classNameStart = fieldOrMethodSig.indexOf('L');\r
+\r
+ if (classNameStart == -1)\r
+ {\r
+ // no class in the type, so stop\r
+ return;\r
+ }\r
+\r
+ // chop off any leading ['s or other Java-primitive type\r
+ // signifiers (like I or L) *AND* substitute the dots\r
+ String fieldType =\r
+ fieldOrMethodSig.substring(classNameStart + 1).replace('/', '.');\r
+\r
+ // we have to check for the semi-colon in case we are\r
+ // actually looking at a token from a method signature\r
+ if (fieldType.endsWith(";"))\r
+ {\r
+ fieldType = fieldType.substring(0,fieldType.length()-1);\r
+ }\r
+\r
+ if (fieldType.startsWith("java"))\r
+ {\r
+ return; // it's a java base class and we don't care about\r
+ // that either\r
+ }\r
+\r
+ foundClasses.add(fieldType);\r
+ return;\r
+ }\r
+ else\r
+ {\r
+ // it's a method signature\r
+ StringTokenizer tokens = new StringTokenizer(fieldOrMethodSig, "();[");\r
+ while (tokens.hasMoreElements())\r
+ {\r
+ String aToken = (String) tokens.nextToken();\r
+ // because of the semi-colon delimiter in the tokenizer, we\r
+ // can have only one class name per token and it must be the\r
+ // last item in the token\r
+ int classNameStart = aToken.indexOf('L');\r
+ if (classNameStart != -1)\r
+ {\r
+ distillClasses(aToken, foundClasses);\r
+ }\r
+ else\r
+ {\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ public Object nextElement() {\r
+ return classList.nextElement();\r
+ }\r
+\r
+}\r