001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.tools.javah;
019:
020: import java.util.Enumeration;
021: import java.util.Vector;
022:
023: import org.apache.bcel.Constants;
024: import org.apache.bcel.classfile.Attribute;
025: import org.apache.bcel.classfile.Field;
026: import org.apache.bcel.classfile.InnerClass;
027: import org.apache.bcel.classfile.InnerClasses;
028: import org.apache.bcel.classfile.JavaClass;
029: import org.apache.bcel.classfile.Method;
030: import org.apache.bcel.classfile.Utility;
031: import org.apache.bcel.generic.BasicType;
032: import org.apache.bcel.generic.Type;
033: import org.apache.harmony.tools.ClassProvider;
034: import org.apache.harmony.tools.Mangler;
035:
036: /**
037: * This class is a wrapper of BCEL's Class class.
038: *
039: * This class depends on Apache Byte Code Engineering Library (BCEL) 5.0 or
040: * later. Please see http://jakarta.apache.org/bcel for more information
041: * about this library.
042: */
043: public class Clazz {
044:
045: /**
046: * A wrapped class.
047: */
048: private JavaClass wrappedClass;
049:
050: /**
051: * Inner classes of a wrapped class.
052: */
053: private String innerClassNames[];
054:
055: /**
056: * Fields that will be included in a header file.
057: */
058: private Vector fields;
059:
060: /**
061: * Methods that will be included in a header file.
062: */
063: private Vector methods;
064:
065: /**
066: * Constructs a <code>Clazz</code> object.
067: *
068: * @param classProvider - a helper that provides the class information.
069: * @param className - a fully qualified name of a class.
070: */
071: public Clazz(ClassProvider classProvider, String className)
072: throws ClassNotFoundException {
073: wrappedClass = classProvider.getJavaClass(className);
074:
075: // Assign an empty array by default.
076: Vector foundInners = new Vector();
077: // Get the class attributes.
078: Attribute attrs[] = wrappedClass.getAttributes();
079: for (int i = 0; i < attrs.length; i++) {
080: // Find the InnerClasses attribute, if any.
081: if (attrs[i] instanceof InnerClasses) {
082: // The InnerClasses attribute is found.
083: InnerClasses innerAttr = (InnerClasses) attrs[i];
084:
085: // Get an array of the inner classes.
086: InnerClass inners[] = innerAttr.getInnerClasses();
087: for (int j = 0; j < inners.length; j++) {
088:
089: // Get the inner class name from a constant pool.
090: String innerClassName = Utility
091: .compactClassName(
092: innerAttr
093: .getConstantPool()
094: .getConstantString(
095: inners[j]
096: .getInnerClassIndex(),
097: Constants.CONSTANT_Class),
098: false);
099:
100: // The inner class has the InnerClasses attribute as well
101: // as its outer class. So, we should ignore such an inner
102: // class.
103: if (!innerClassName.equals(className)) {
104: foundInners.addElement(innerClassName);
105: }
106: }
107: break;
108: }
109: }
110: // Fill in the inner class array with the found inner classes.
111: innerClassNames = new String[foundInners.size()];
112: foundInners.toArray(innerClassNames);
113:
114: // Collect up fields of the given class and all its ancestors.
115: fields = new Vector();
116: JavaClass clss = wrappedClass;
117: while (true) {
118: searchForFields(clss);
119: String super ClassName = clss.getSuperclassName();
120: if (clss.getClassName().equals(super ClassName)) {
121: break;
122: }
123: // Retrieve the next super class.
124: clss = classProvider.getJavaClass(super ClassName);
125: }
126:
127: // Collect up methods.
128: methods = new Vector();
129: searchForMethods(wrappedClass);
130: }
131:
132: /**
133: * Returns a name of a wrapped class.
134: *
135: * @return a class name.
136: */
137: public String getName() {
138: return wrappedClass.getClassName();
139: }
140:
141: /**
142: * Returns a mangled name of a wrapped method.
143: *
144: * @return a mangled method name.
145: */
146: public String getMangledName() {
147: return Mangler.mangleClassName(getName());
148: }
149:
150: /**
151: * Returns an array of inner classes of this class.
152: *
153: * @return an array of inner class names.
154: */
155: public String[] getInnerClassNames() {
156: return innerClassNames;
157: }
158:
159: /**
160: * Searches the given class for the static final fields type of which
161: * is a primitive data type.
162: *
163: * @param clss - a searched class.
164: */
165: private void searchForFields(JavaClass clss) {
166: Field field[] = clss.getFields();
167: for (int i = 0; i < field.length; i++) {
168: Field f = field[i];
169: if (f.isStatic() && f.isFinal()) {
170: if (Type.getReturnType(f.getSignature()) instanceof BasicType) {
171: fields.addElement(new ClazzField(this , f));
172: }
173: }
174: }
175: }
176:
177: /**
178: * Searches the given class for the native methods.
179: *
180: * @param clss - a searched class.
181: */
182: private void searchForMethods(JavaClass clss) {
183: Method method[] = clss.getMethods();
184: for (int i = 0; i < method.length; i++) {
185: Method m = method[i];
186: if (m.isNative()) {
187: boolean overloaded = false;
188: // Check if the current method is overloaded.
189: for (int j = 0; j < method.length; j++) {
190: Method mj = method[j];
191: if (mj != m && mj.isNative()
192: && mj.getName().equals(m.getName())) {
193: overloaded = true;
194: }
195: }
196: methods
197: .addElement(new ClazzMethod(this , m, overloaded));
198: }
199: }
200: }
201:
202: /**
203: * Returns a string that represents a class part of
204: * a JNI-style header file.
205: */
206: public String toString() {
207: String n = System.getProperty("line.separator");
208: StringBuffer result = new StringBuffer();
209:
210: if (fields.size() > 0) {
211: result.append(n);
212: result.append("/* Static final fields */" + n);
213: result.append(n);
214:
215: for (Enumeration e = fields.elements(); e.hasMoreElements();) {
216: result.append((ClazzField) e.nextElement());
217: }
218: }
219:
220: if (methods.size() > 0) {
221: result.append(n);
222: result.append("/* Native methods */" + n);
223: result.append(n);
224:
225: for (Enumeration e = methods.elements(); e
226: .hasMoreElements();) {
227: result.append(((ClazzMethod) e.nextElement())
228: .toString());
229: }
230: }
231:
232: return result.toString();
233: }
234: }
|