001: /*
002: * Sun Public License Notice
003: *
004: * The contents of this file are subject to the Sun Public License
005: * Version 1.0 (the "License"). You may not use this file except in
006: * compliance with the License. A copy of the License is available at
007: * http://www.sun.com/
008: *
009: * The Original Code is NetBeans. The Initial Developer of the Original
010: * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
011: * Microsystems, Inc. All Rights Reserved.
012: */
013:
014: package org.netbeans.editor.ext.java;
015:
016: import java.io.File;
017: import java.io.FileFilter;
018: import java.lang.reflect.Constructor;
019: import java.lang.reflect.Field;
020: import java.lang.reflect.Method;
021: import java.lang.reflect.Modifier;
022: import java.util.ArrayList;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.TreeSet;
026:
027: import org.netbeans.editor.TokenID;
028:
029: /**
030: * Java completion utilities
031: *
032: * @author Miloslav Metelka
033: * @version 1.00
034: */
035:
036: public class JCUtilities {
037:
038: private static final int javaTokenIDsLength = JavaTokenContext.context
039: .getTokenIDs().length;
040:
041: private static final boolean[][] primitivesAssignable = new boolean[javaTokenIDsLength][];
042:
043: private static final JCClass[][] primitivesCommonClass = new JCClass[javaTokenIDsLength][];
044:
045: static {
046: int[] typeIDs = new int[] { JavaTokenContext.BOOLEAN_ID,
047: JavaTokenContext.BYTE_ID, JavaTokenContext.CHAR_ID,
048: JavaTokenContext.DOUBLE_ID, JavaTokenContext.FLOAT_ID,
049: JavaTokenContext.INT_ID, JavaTokenContext.LONG_ID,
050: JavaTokenContext.SHORT_ID, JavaTokenContext.VOID_ID };
051:
052: boolean[][] assignVals = new boolean[][] {
053: new boolean[] { true, false, false, false, false,
054: false, false, false, false }, // boolean
055: new boolean[] { false, true, false, true, true, true,
056: true, true, false }, // byte
057: new boolean[] { false, false, true, true, true, true,
058: true, false, false }, // char
059: new boolean[] { false, false, false, true, false,
060: false, false, false, false }, // double
061: new boolean[] { false, false, false, true, true, false,
062: false, false, false }, // float
063: new boolean[] { false, false, false, true, true, true,
064: true, false, false }, // int
065: new boolean[] { false, false, false, true, true, false,
066: true, false, false }, // long
067: new boolean[] { false, false, false, true, true, true,
068: true, true, false }, // short
069: new boolean[] { false, false, false, false, false,
070: false, false, false, true } // void
071: };
072:
073: JCClass[][] classesVals = new JCClass[][] {
074: new JCClass[] { JavaCompletion.BOOLEAN_CLASS, null,
075: null, null, null, null, null, null, null }, // boolean
076:
077: new JCClass[] { null, JavaCompletion.BYTE_CLASS,
078: JavaCompletion.INT_CLASS,
079: JavaCompletion.DOUBLE_CLASS,
080: JavaCompletion.FLOAT_CLASS,
081: JavaCompletion.INT_CLASS,
082: JavaCompletion.LONG_CLASS,
083: JavaCompletion.INT_CLASS, null }, // byte
084:
085: new JCClass[] { null, JavaCompletion.INT_CLASS,
086: JavaCompletion.CHAR_CLASS,
087: JavaCompletion.DOUBLE_CLASS,
088: JavaCompletion.FLOAT_CLASS,
089: JavaCompletion.INT_CLASS,
090: JavaCompletion.LONG_CLASS,
091: JavaCompletion.INT_CLASS, null }, // char
092:
093: new JCClass[] { null, JavaCompletion.DOUBLE_CLASS,
094: JavaCompletion.DOUBLE_CLASS,
095: JavaCompletion.DOUBLE_CLASS,
096: JavaCompletion.DOUBLE_CLASS,
097: JavaCompletion.DOUBLE_CLASS,
098: JavaCompletion.DOUBLE_CLASS,
099: JavaCompletion.DOUBLE_CLASS, null }, // double
100:
101: new JCClass[] { null, JavaCompletion.FLOAT_CLASS,
102: JavaCompletion.FLOAT_CLASS,
103: JavaCompletion.DOUBLE_CLASS,
104: JavaCompletion.FLOAT_CLASS,
105: JavaCompletion.FLOAT_CLASS,
106: JavaCompletion.FLOAT_CLASS,
107: JavaCompletion.FLOAT_CLASS, null }, // float
108:
109: new JCClass[] { null, JavaCompletion.INT_CLASS,
110: JavaCompletion.INT_CLASS,
111: JavaCompletion.DOUBLE_CLASS,
112: JavaCompletion.FLOAT_CLASS,
113: JavaCompletion.INT_CLASS,
114: JavaCompletion.LONG_CLASS,
115: JavaCompletion.INT_CLASS, null }, // int
116:
117: new JCClass[] { null, JavaCompletion.LONG_CLASS,
118: JavaCompletion.LONG_CLASS,
119: JavaCompletion.DOUBLE_CLASS,
120: JavaCompletion.FLOAT_CLASS,
121: JavaCompletion.LONG_CLASS,
122: JavaCompletion.LONG_CLASS,
123: JavaCompletion.LONG_CLASS, null }, // long
124:
125: new JCClass[] { null, JavaCompletion.INT_CLASS,
126: JavaCompletion.INT_CLASS,
127: JavaCompletion.DOUBLE_CLASS,
128: JavaCompletion.FLOAT_CLASS,
129: JavaCompletion.INT_CLASS,
130: JavaCompletion.LONG_CLASS,
131: JavaCompletion.SHORT_CLASS, null }, // short
132:
133: new JCClass[] { null, null, null, null, null, null,
134: null, null, JavaCompletion.VOID_CLASS } // void
135: };
136:
137: for (int i = 0; i < typeIDs.length; i++) {
138: primitivesAssignable[typeIDs[i]] = new boolean[javaTokenIDsLength];
139: primitivesCommonClass[typeIDs[i]] = new JCClass[javaTokenIDsLength];
140:
141: for (int j = 0; j < typeIDs.length; j++) {
142: primitivesAssignable[typeIDs[i]][typeIDs[j]] = assignVals[i][j];
143: primitivesCommonClass[typeIDs[i]][typeIDs[j]] = classesVals[i][j];
144: }
145: }
146:
147: }
148:
149: private static boolean stringEqual(String s1, String s2) {
150: return (s1 == null) ? (s2 == null) : s1.equals(s2);
151: }
152:
153: private static boolean classEqual(JCClass c1, JCClass c2) {
154: return (c1 == null) ? (c2 == null) : c1.equals(c2);
155: }
156:
157: private static boolean typeEqual(JCType t1, JCType t2) {
158: return (t1 == null) ? (t2 == null) : classEqual(t1.getClazz(),
159: t2.getClazz())
160: && (t1.getArrayDepth() == t2.getArrayDepth());
161: }
162:
163: private static boolean parameterEqual(JCParameter p1, JCParameter p2) {
164: return (p1 == null) ? (p2 == null) : typeEqual(p1.getType(), p2
165: .getType())
166: && stringEqual(p1.getName(), p2.getName());
167: }
168:
169: private static boolean constructorEqual(JCConstructor c1,
170: JCConstructor c2) {
171: return (c1 == null) ? (c2 == null) : (c1.getClazz().equals(
172: c2.getClazz()) // mustn't
173: // be
174: // null
175: && c1.getModifiers() == c2.getModifiers()
176: && parameterArrayEqual(c1.getParameters(), c2
177: .getParameters()) && classArrayEqual(c1
178: .getExceptions(), c2.getExceptions()));
179: }
180:
181: private static boolean parameterArrayEqual(JCParameter[] pa1,
182: JCParameter[] pa2) {
183: if (pa1.length != pa2.length) {
184: return false;
185: }
186: for (int i = pa1.length - 1; i >= 0; i--) {
187: if (!parameterEqual(pa1[i], pa2[i])) {
188: return false;
189: }
190: }
191: return true;
192: }
193:
194: private static boolean classArrayEqual(JCClass[] ca1, JCClass[] ca2) {
195: if (ca1.length != ca2.length) {
196: return false;
197: }
198: for (int i = ca1.length - 1; i >= 0; i--) {
199: if (!classEqual(ca1[i], ca2[i])) {
200: return false;
201: }
202: }
203: return true;
204: }
205:
206: private static boolean fieldArraysEqual(JCField[] fa1, JCField[] fa2) {
207: if (fa1.length != fa2.length) {
208: return false;
209: }
210: for (int i = fa1.length - 1; i >= 0; i--) {
211: JCField f1 = fa1[i];
212: JCField f2 = fa2[i];
213: if (!parameterEqual(f1, f2)
214: || !f1.getClazz().equals(f2.getClazz()) // mustn't
215: // be
216: // null
217: || (f1.getModifiers() != f2.getModifiers())) {
218: return false;
219: }
220: }
221: return true;
222: }
223:
224: private static boolean constructorArrayEqual(JCConstructor[] ca1,
225: JCConstructor[] ca2) {
226: if (ca1.length != ca2.length) {
227: return false;
228: }
229: for (int i = ca1.length - 1; i >= 0; i--) {
230: if (!constructorEqual(ca1[i], ca2[i])) {
231: return false;
232: }
233: }
234: return true;
235: }
236:
237: private static boolean methodArraysEqual(JCMethod[] ma1,
238: JCMethod[] ma2) {
239: if (ma1.length != ma2.length) {
240: return false;
241: }
242: for (int i = ma1.length - 1; i >= 0; i--) {
243: JCMethod m1 = ma1[i];
244: JCMethod m2 = ma2[i];
245: if (!constructorEqual(m1, m2)
246: || !stringEqual(m1.getName(), m2.getName())
247: || !typeEqual(m1.getReturnType(), m2
248: .getReturnType())) {
249: return false;
250: }
251: }
252: return true;
253: }
254:
255: public static boolean equal(JCClass c1, JCClass c2) {
256: if (c1 == null && c2 == null) { // both null
257: return true;
258: }
259: if (c1 == null || c2 == null) { // one of them is null, but not both
260: return false;
261: }
262:
263: if (!c1.equals(c2) || c1.isInterface() != c2.isInterface()
264: || c1.getModifiers() != c2.getModifiers()
265: || !classEqual(c1.getSuperclass(), c2.getSuperclass())) {
266: return false;
267: }
268:
269: if (!fieldArraysEqual(c1.getFields(), c2.getFields())
270: || !constructorArrayEqual(c1.getConstructors(), c2
271: .getConstructors())
272: || !methodArraysEqual(c1.getMethods(), c2.getMethods())
273: || !classArrayEqual(c1.getInterfaces(), c2
274: .getInterfaces())) {
275: return false;
276: }
277: return true;
278: }
279:
280: public static String dumpClass(JCClass c) {
281: StringBuffer sb = new StringBuffer();
282: sb.append(Modifier.toString(c.getModifiers()));
283: sb.append(c.isInterface() ? " interface " : " class "); // NOI18N
284: sb.append(c);
285: sb.append(" extends "); // NOI18N
286: sb.append(c.getSuperclass());
287: // Add implemented interfaces
288: JCClass[] ifcs = c.getInterfaces();
289: int cntM1 = ifcs.length - 1;
290: if (cntM1 >= 0) {
291: sb.append(" implements "); // NOI18N
292: for (int i = 0; i <= cntM1; i++) {
293: sb.append(ifcs[i].toString());
294: if (i < cntM1) {
295: sb.append(", "); // NOI18N
296: }
297: }
298: }
299: sb.append('\n');
300:
301: String indentStr = " "; // NOI18N
302: // Add fields
303: JCField[] flds = c.getFields();
304: if (flds.length > 0) {
305: sb.append("FIELDS:\n"); // NOI18N
306: for (int i = 0; i < flds.length; i++) {
307: sb.append(indentStr);
308: sb.append(flds[i]);
309: sb.append('\n');
310: }
311: }
312: // Add constructors
313: JCConstructor[] cons = c.getConstructors();
314: if (cons.length > 0) {
315: sb.append("CONSTRUCTORS:\n"); // NOI18N
316: for (int i = 0; i < cons.length; i++) {
317: sb.append(indentStr);
318: sb.append(cons[i]);
319: sb.append('\n');
320: }
321: }
322: // Add methods
323: JCMethod[] mtds = c.getMethods();
324: if (mtds.length > 0) {
325: sb.append("METHODS:\n"); // NOI18N
326: for (int i = 0; i < mtds.length; i++) {
327: sb.append(indentStr);
328: sb.append(mtds[i]);
329: sb.append('\n');
330: }
331: }
332: return sb.toString();
333: }
334:
335: public static JCClass getExactClass(JCFinder finder, String name,
336: String pkgName) {
337: return finder.getExactClass((pkgName.length() != 0) ? (pkgName
338: + "." + name) : name); // NOI18N
339: }
340:
341: /**
342: * Filter the list of the methods (usually returned from
343: * Finder.findMethods()) or the list of the constructors by the given
344: * parameter specification.
345: *
346: * @param methodList
347: * list of the methods. They should have the same name but in
348: * fact they don't have to.
349: * @param parmTypes
350: * parameter types specification. If set to null, no filtering is
351: * performed and the same list is returned. If a particular
352: * @param acceptMoreParameters
353: * useful for code completion to get even the methods with more
354: * parameters.
355: */
356: public static List filterMethods(List methodList,
357: List parmTypeList, boolean acceptMoreParameters) {
358: if (parmTypeList == null) {
359: return methodList;
360: }
361:
362: List ret = new ArrayList();
363: int parmTypeCnt = parmTypeList.size();
364: int cnt = methodList.size();
365: for (int i = 0; i < cnt; i++) {
366: // Use constructor conversion to allow to use it too for the
367: // constructors
368: JCConstructor m = (JCConstructor) methodList.get(i);
369: JCParameter[] methodParms = m.getParameters();
370: if (methodParms.length == parmTypeCnt
371: || (acceptMoreParameters && methodParms.length >= parmTypeCnt)) {
372: boolean accept = true;
373: boolean bestMatch = !acceptMoreParameters;
374: for (int j = 0; accept && j < parmTypeCnt; j++) {
375: JCType mpt = methodParms[j].getType();
376: JCType t = (JCType) parmTypeList.get(j);
377: if (t != null) {
378: if (!t.equals(mpt)) {
379: bestMatch = false;
380: if (!isAssignable(t, mpt)) {
381: accept = false;
382: break;
383: }
384: }
385: } else { // type in list is null
386: bestMatch = false;
387: }
388: }
389:
390: if (accept) {
391: if (bestMatch) {
392: ret.clear();
393: }
394: ret.add(m);
395: if (bestMatch) {
396: break;
397: }
398: }
399:
400: }
401: }
402: return ret;
403: }
404:
405: /** Get the sorted constructor list for the given class. */
406: public static List getConstructors(JCClass cls) {
407: TreeSet ts = new TreeSet();
408: JCConstructor[] constructors = cls.getConstructors();
409: for (int i = constructors.length - 1; i >= 0; i--) {
410: ts.add(constructors[i]);
411: }
412: return new ArrayList(ts);
413: }
414:
415: /**
416: * Get all the interfaces the class/interface implements/extends.
417: */
418: public static List getAllInterfaces(JCClass cls) {
419: ArrayList ret = new ArrayList();
420: collectInterfaces(cls, ret);
421: return ret;
422: }
423:
424: /** Accumulate the subinterfaces recursively */
425: private static void collectInterfaces(JCClass cls, ArrayList clsList) {
426: JCClass[] ifcs = cls.getInterfaces();
427: if (ifcs != null) {
428: JCFinder finder = JavaCompletion.getFinder();
429: for (int i = 0; i < ifcs.length; i++) {
430: if (clsList.contains(ifcs[i]))
431: continue;
432: clsList.add(ifcs[i]);
433: cls = finder.getExactClass(ifcs[i].getFullName());
434: if (cls != null) {
435: collectInterfaces(cls, clsList); // recurse implemented
436: // interfaces
437: }
438: }
439: }
440: }
441:
442: /** Get the list containing the given class and all its superclasses. */
443: public static List getSuperclasses(JCClass cls) {
444: ArrayList clsList = new ArrayList();
445: JCFinder finder = JavaCompletion.getFinder();
446: cls = finder.getExactClass(cls.getFullName());
447: if (cls != null) {
448: cls = cls.getSuperclass();
449: }
450:
451: while (cls != null && clsList.indexOf(cls) < 0) {
452: clsList.add(cls);
453: cls = finder.getExactClass(cls.getFullName());
454: if (cls != null) {
455: cls = cls.getSuperclass();
456: }
457: }
458:
459: return clsList;
460: }
461:
462: public static boolean isAssignable(JCType from, JCType to) {
463: JCClass fromCls = from.getClazz();
464: JCClass toCls = to.getClazz();
465:
466: if (fromCls.equals(JavaCompletion.NULL_CLASS)) {
467: return to.getArrayDepth() > 0
468: || !JavaCompletion.isPrimitiveClass(toCls);
469: }
470:
471: if (toCls.equals(JavaCompletion.OBJECT_CLASS)) { // everything is
472: // object
473: return (from.getArrayDepth() > to.getArrayDepth())
474: || (from.getArrayDepth() == to.getArrayDepth() && !JavaCompletion
475: .isPrimitiveClass(fromCls));
476: }
477:
478: if (from.getArrayDepth() != to.getArrayDepth()) {
479: return false;
480: }
481:
482: if (fromCls.equals(toCls)) {
483: return true; // equal classes
484: }
485:
486: if (fromCls.isInterface()) {
487: return toCls.isInterface()
488: && (getAllInterfaces(fromCls).indexOf(toCls) >= 0);
489: } else { // fromCls is a class
490: TokenID fromClsKwd = JavaTokenContext.getKeyword(fromCls
491: .getName());
492: if (fromClsKwd != null) { // primitive class
493: TokenID toClsKwd = JavaTokenContext.getKeyword(toCls
494: .getName());
495: return toClsKwd != null
496: && primitivesAssignable[fromClsKwd
497: .getNumericID()][toClsKwd
498: .getNumericID()];
499: } else {
500: if (toCls.isInterface()) {
501: return (getAllInterfaces(fromCls).indexOf(toCls) >= 0);
502: } else { // toCls is a class
503: return (getSuperclasses(fromCls).indexOf(toCls) >= 0);
504: }
505: }
506: }
507: }
508:
509: public static JCType getCommonType(JCType typ1, JCType typ2) {
510: if (typ1.equals(typ2)) {
511: return typ1;
512: }
513:
514: // The following part
515: TokenID cls1Kwd = JavaTokenContext.getKeyword(typ1.getClazz()
516: .getName());
517: TokenID cls2Kwd = JavaTokenContext.getKeyword(typ2.getClazz()
518: .getName());
519: if (cls1Kwd == null && cls2Kwd == null) { // non-primitive classes
520: if (isAssignable(typ1, typ2)) {
521: return typ1;
522: } else if (isAssignable(typ2, typ1)) {
523: return typ2;
524: } else {
525: return null;
526: }
527: } else { // at least one primitive class
528: if (typ1.getArrayDepth() != typ2.getArrayDepth()) {
529: return null;
530: }
531: if (cls1Kwd != null && cls2Kwd != null) {
532: return JavaCompletion
533: .getType(
534: primitivesCommonClass[cls1Kwd
535: .getNumericID()][cls2Kwd
536: .getNumericID()], typ1
537: .getArrayDepth());
538: } else { // one primitive but other not
539: return null;
540: }
541: }
542: }
543:
544: public static JCClass createSimpleClass(Class c) {
545: if (c == null || c.getName() == null) {
546: return JavaCompletion.INVALID_CLASS;
547: }
548: return createSimpleClassImpl(c.getName());
549: }
550:
551: private static JCClass createSimpleClassImpl(String className) {
552: int dotInd = className.lastIndexOf('.');
553: return JavaCompletion.getSimpleClass(className
554: .replace('$', '.'), (dotInd >= 0) ? dotInd : 0);
555: }
556:
557: public static JavaCompletion.BaseType createType(Class c) {
558: if (c == null) {
559: return JavaCompletion.INVALID_TYPE;
560: }
561:
562: String className = c.getName();
563: int arrayDepth = 0;
564: while (className.length() > 0 && className.charAt(0) == '[') {
565: arrayDepth++;
566: className = className.substring(1);
567: }
568:
569: if (arrayDepth > 0) {
570: switch (className.charAt(0)) {
571: case 'L':
572: className = className.substring(1,
573: className.length() - 1);
574: break;
575: case 'B':
576: className = "byte"; // NOI18N
577: break;
578: case 'C':
579: className = "char"; // NOI18N
580: break;
581: case 'D':
582: className = "double"; // NOI18N
583: break;
584: case 'F':
585: className = "float"; // NOI18N
586: break;
587: case 'I':
588: className = "int"; // NOI18N
589: break;
590: case 'J':
591: className = "long"; // NOI18N
592: break;
593: case 'S':
594: className = "short"; // NOI18N
595: break;
596: case 'Z':
597: className = "boolean"; // NOI18N
598: break;
599: }
600: }
601:
602: return new JavaCompletion.BaseType(
603: createSimpleClassImpl(className), arrayDepth);
604: }
605:
606: public static List getClassList(List classNames,
607: boolean storeDeclaredClasses, int classLevel,
608: int fieldLevel, int methodLevel) {
609: ArrayList l = new ArrayList();
610: Iterator i = classNames.iterator();
611: while (i.hasNext()) {
612: String name = (String) i.next();
613: Class c = null;
614: try {
615: c = Class.forName(name);
616: } catch (ClassNotFoundException e) {
617: System.err.println("Class '" + name + "' not found."); // NOI18N
618: } catch (ThreadDeath td) {
619: throw td;
620: } catch (Throwable t) {
621: System.err
622: .println("Exception thrown during class rebuild:"); // NOI18N
623: t.printStackTrace();
624: if (t instanceof OutOfMemoryError)
625: throw (OutOfMemoryError) t;
626: }
627: if (c != null) {
628: l.addAll(createClassList(c, storeDeclaredClasses,
629: classLevel, fieldLevel, methodLevel));
630: }
631: }
632: return l;
633: }
634:
635: private static String strip(String name, String baseName,
636: String suffix) {
637: int startInd = 0;
638: int endStrip = 0;
639: if (name.startsWith(baseName)) {
640: startInd = baseName.length();
641: }
642: if (name.endsWith(suffix)) {
643: endStrip = suffix.length();
644: }
645: return name.substring(startInd, name.length() - endStrip);
646: }
647:
648: private static String separatorToDot(String s) {
649: return s.replace(File.separatorChar, '.');
650: }
651:
652: private static List createClassList(Class c,
653: boolean storeDeclaredClasses, int classLevel,
654: int fieldLevel, int methodLevel) {
655: ArrayList cL = new ArrayList();
656: if (c == null) {
657: return cL;
658: }
659:
660: if (JavaCompletion.getLevel(c.getModifiers()) >= classLevel) {
661: cL.add(new BaseJCClass(c, classLevel, fieldLevel,
662: methodLevel));
663: }
664:
665: // possibly store declared classes subclasses
666: if (storeDeclaredClasses) {
667: try {
668: Class[] dC = c.getDeclaredClasses();
669: for (int i = 0; i < dC.length; i++) {
670: if (JavaCompletion.getLevel(dC[i].getModifiers()) >= classLevel) {
671: cL.addAll(createClassList(dC[i],
672: storeDeclaredClasses, classLevel,
673: fieldLevel, methodLevel));
674: }
675: }
676: } catch (SecurityException e) {
677: // can't access declared classes
678: e.printStackTrace();
679: }
680: }
681:
682: return cL;
683: }
684:
685: public static List getClassNameList(String packageDirName) {
686: File packageDir = new File(packageDirName);
687: List classNames = new ArrayList();
688: packageDirName += File.separator; // to strip begining
689: if (packageDir.exists()) {
690: getClassListFromSourcesRec(classNames, packageDirName,
691: packageDir);
692: }
693: return classNames;
694: }
695:
696: private static void getClassListFromSourcesRec(final List l,
697: final String packageDirName, File curDir) {
698: curDir.listFiles(new FileFilter() {
699: public boolean accept(File f) {
700: if (f.isDirectory()) {
701: getClassListFromSourcesRec(l, packageDirName, f);
702: }
703: if (f.getName().endsWith(".java")) { // NOI18N
704: l.add(separatorToDot(strip(f.getAbsolutePath(),
705: packageDirName, ".java"))); // NOI18N
706: }
707: return false;
708: }
709: });
710: }
711:
712: public static class BaseJCClass extends
713: JavaCompletion.AbstractClass {
714:
715: Class c;
716:
717: int classLevel;
718:
719: int fieldLevel;
720:
721: int methodLevel;
722:
723: /** Do reflection of given class */
724: public BaseJCClass(Class c, int classLevel, int fieldLevel,
725: int methodLevel) {
726: this .c = c;
727: this .classLevel = classLevel;
728: this .fieldLevel = fieldLevel;
729: this .methodLevel = methodLevel;
730: JCClass sc = createSimpleClass(c);
731: name = sc.getName();
732: packageName = sc.getPackageName();
733: modifiers = c.getModifiers();
734: if (c.isInterface()) {
735: modifiers |= JavaCompletion.INTERFACE_BIT;
736: }
737: }
738:
739: protected void init() {
740: body = new Body();
741: ArrayList lst = new ArrayList();
742: body.super Class = createSimpleClass(c.getSuperclass());
743:
744: // create interface classes
745: Class[] dI = c.getInterfaces();
746: for (int i = 0; i < dI.length; i++) {
747: if (JavaCompletion.getLevel(dI[i].getModifiers()) >= classLevel) {
748: lst.add(createSimpleClass(dI[i]));
749: }
750: }
751: body.interfaces = new JCClass[lst.size()];
752: lst.toArray(body.interfaces);
753: lst.clear();
754:
755: // create fields
756: try {
757: Field[] dF = c.getDeclaredFields();
758: for (int i = 0; i < dF.length; i++) {
759: if (JavaCompletion.getLevel(dF[i].getModifiers()) >= fieldLevel) {
760: lst.add(new JavaCompletion.BaseField(this ,
761: dF[i].getName(), createType(dF[i]
762: .getType()), dF[i]
763: .getModifiers()));
764: }
765: }
766: body.fields = new JCField[lst.size()];
767: lst.toArray(body.fields);
768: lst.clear();
769: } catch (SecurityException e) {
770: // can't access declared fields
771: e.printStackTrace();
772: }
773:
774: // create constructors
775: try {
776: Constructor[] dC = c.getDeclaredConstructors();
777: for (int i = 0; i < dC.length; i++) {
778: if (JavaCompletion.getLevel(dC[i].getModifiers()) >= methodLevel) {
779: // get constructor parameters
780: JCParameter[] parameters = JavaCompletion.EMPTY_PARAMETERS;
781: try {
782: Class[] dP = dC[i].getParameterTypes();
783: parameters = new JCParameter[dP.length];
784: for (int j = 0; j < dP.length; j++) {
785: parameters[j] = new JavaCompletion.BaseParameter(
786: "", // name
787: // not
788: // known
789: // from
790: // reflection
791: // //
792: // NOI18N
793: createType(dP[j]));
794: }
795: } catch (SecurityException e) {
796: // can't get parameter types
797: e.printStackTrace();
798: }
799:
800: // get thrown exceptions - don't restrict to classes
801: // level
802: JCClass[] exceptions = JavaCompletion.EMPTY_CLASSES;
803: try {
804: Class[] dE = dC[i].getExceptionTypes();
805: exceptions = new JCClass[dE.length];
806: for (int j = 0; j < dE.length; j++) {
807: exceptions[j] = createSimpleClass(dE[j]);
808: }
809: } catch (SecurityException e) {
810: // can't get exception types
811: e.printStackTrace();
812: }
813:
814: lst.add(new JavaCompletion.BaseConstructor(
815: this , dC[i].getModifiers(), parameters,
816: exceptions));
817: }
818: }
819: body.constructors = new JCConstructor[lst.size()];
820: lst.toArray(body.constructors);
821: lst.clear();
822: } catch (SecurityException e) {
823: // can't access declared constructors
824: e.printStackTrace();
825: }
826:
827: // create methods
828: try {
829: Method[] dM = c.getDeclaredMethods();
830: for (int i = 0; i < dM.length; i++) {
831: if (JavaCompletion.getLevel(dM[i].getModifiers()) >= methodLevel) {
832: // get method parameters
833: JCParameter[] parameters = JavaCompletion.EMPTY_PARAMETERS;
834: try {
835: Class[] dP = dM[i].getParameterTypes();
836: parameters = new JCParameter[dP.length];
837: for (int j = 0; j < dP.length; j++) {
838: parameters[j] = new JavaCompletion.BaseParameter(
839: "", // name
840: // not
841: // known
842: // from
843: // reflection
844: // //
845: // NOI18N
846: createType(dP[j]));
847: }
848: } catch (SecurityException e) {
849: // can't get parameter types
850: e.printStackTrace();
851: }
852:
853: // get thrown exceptions - don't restrict to classes
854: // level
855: JCClass[] exceptions = JavaCompletion.EMPTY_CLASSES;
856: try {
857: Class[] dE = dM[i].getExceptionTypes();
858: exceptions = new JCClass[dE.length];
859: for (int j = 0; j < dE.length; j++) {
860: exceptions[j] = createSimpleClass(dE[j]);
861: }
862: } catch (SecurityException e) {
863: // can't get exception types
864: e.printStackTrace();
865: }
866:
867: lst.add(new JavaCompletion.BaseMethod(this ,
868: dM[i].getName(), dM[i].getModifiers(),
869: createType(dM[i].getReturnType()),
870: parameters, exceptions));
871: }
872: }
873: body.methods = new JCMethod[lst.size()];
874: lst.toArray(body.methods);
875: lst.clear();
876: } catch (SecurityException e) {
877: // can't access declared methods
878: e.printStackTrace();
879: }
880:
881: c = null; // can free this reference now
882: }
883:
884: }
885:
886: }
|