home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / VCAFE.3.0A / Main.bin / DTClass.java < prev    next >
Text File  |  1998-12-04  |  90KB  |  2,541 lines

  1. /*
  2.  * Copyright 1998 Symantec Corporation, All Rights Reserved.
  3.  */
  4.  
  5. package com.symantec.itools.vcafe.openapi.dtreflect;
  6.  
  7. import java.lang.reflect.*;
  8. import java.util.*;
  9. import java.io.*;
  10. import com.symantec.itools.vcafe.openapi.VisualCafe;
  11. import com.symantec.itools.vcafe.openapi.VisualProject;
  12. import com.symantec.itools.vcafe.openapi.Range;
  13. import com.symantec.itools.vcafe.openapi.ProjectFile;
  14. import com.symantec.itools.vcafe.openapi.SourceFile;
  15.  
  16. /**
  17.  * DTClass is the root class for the dtreflect API for Design Time Reflection.
  18.  *
  19.  * <p>Design Time Reflection provides services analogous to the Java
  20.  * reflection API, based upon parse information gathered
  21.  * by Visual Cafe. Thus, classes reflected upon need not be compiled
  22.  * or in a compilable state.
  23.  *
  24.  * <p>There are several significant differences between the dtreflect and
  25.  * reflect packages:
  26.  *
  27.  * <p>dtreflect usually does not throw an exception when a
  28.  * class, method, field, etc. cannot be found. Instead, the API uniformly
  29.  * returns null, allowing simpler caller code. The nonNull()
  30.  * methods allow callers to quickly and conveniently convert null
  31.  * returns to NullPointerException if this is desired.
  32.  *
  33.  * <p>The DTListener interface combined with the notify()/notifyAll()
  34.  * methods allows a dtreflect user to listen to specific/all classes
  35.  * for changes. The validate() method of a dtreflect object verifies
  36.  * that the information in the object is up-to-date. validate() should
  37.  * also be called when a dtreflect object is serialized in, as the underlying
  38.  * class, method, etc. may no longer exist or may have changed.
  39.  *
  40.  * <p>To avoid confusion, the forName() method is renamed findClass().
  41.  * <p>Since classes may be unique to projects and different classes
  42.  * with the same name may exist in different projects, findClass() requires a
  43.  * Project argument. The findSystemClass() method returns information
  44.  * about classes that are common to all open projects.
  45.  *
  46.  * <p> dtreflect objects obtain their information from a parser for project files
  47.  * and from compiled code for files outside the project. Because a parser
  48.  * is more forgiving than the compiler, some information may be incomplete
  49.  * or innacurate. In particular, variable, method return and argument types may
  50.  * not be fully qualified. Each object has a validate interface that verifies
  51.  * that all types used by the object could be used to create valid DTClass objects.
  52.  */
  53. public class DTClass implements Serializable
  54. {
  55.     static final long serialVersionUID = 8946402831128459801L;
  56.  
  57.     static final boolean DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS = false;
  58.  
  59.     /**
  60.      * Converts the object to a string. The string representation is the
  61.      * string <code>"class"</code> or <code>"interface"</code> followed
  62.      * by a space and then the fully qualified name of the class.
  63.      * If this DTClass object represents a primitive type,
  64.      * returns the name of the primitive type.
  65.      *
  66.      * @return    a string representation of this class object.
  67.      */
  68.     public String toString() {
  69.         return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
  70.         + getName();
  71.     }
  72.  
  73.     /**
  74.      * Returns the <code>DTClass</code> object associated with the class
  75.      * with the given string name.
  76.      *
  77.      * <p>Given a project and the fully-qualified name for a class or interface, this
  78.      * method attempts to create a DTClass object for the class.  If it
  79.      * succeeds, returns the DTClass object representing the class.  If
  80.      * it fails, the method returns null.
  81.      *
  82.      * <p>For example, the following code fragment returns the runtime
  83.      * <code>DTClass</code> descriptor for the class named
  84.      * <code>com.user.MyClass</code>:
  85.      * <ul><code>
  86.      *     DTClass t = DTClass.findClass(aproject, "com.user.MyClass")
  87.      * </code></ul>
  88.      *
  89.      * <p>Array classes are represented using standard notation, e.g.,
  90.      * "java.lang.String[]" and "byte[][]".
  91.      *
  92.      * <p>If the className names a system class or the project is null,
  93.      * findClass() is the same as findSystemClass(). NB: A project must
  94.      * be specified for a component library class, which is not in the
  95.      * system classpath.
  96.      *
  97.      * @param    project        the project context that defines the class.
  98.      * @param    className    the fully qualified name of the desired class.
  99.      * @return     the <code>DTClass</code> descriptor for the class with the
  100.      *             specified name. Returns null if class not found.
  101.      *
  102.      * @see com.symantec.itools.vcafe.openapi.VisualProject#getDTClassObject()
  103.      * @see com.symantec.itools.vcafe.openapi.dtreflect.DTClass#findSystemClass()
  104.      */
  105.     public static DTClass findClass(VisualProject project, String className) {
  106.         if (project != null)
  107.             return project.getDTClassObject(className);
  108.  
  109.         return DTClass.findSystemClass(className);
  110.     }
  111.  
  112.  
  113.     /**
  114.      * Returns the <code>DTClass</code> object associated with the class
  115.      * with the given string name.
  116.      *
  117.      * <p>The class must be loadable from the system classpath.
  118.      *
  119.      * <p>For example, the following code fragment returns the runtime
  120.      * <code>DTClass</code> descriptor for the standard String class:
  121.      * <ul><code>
  122.      *     DTClass t = DTClass.findSystemClass("java.lang.String")
  123.      * </code></ul>
  124.      *
  125.      * @param    className    the fully qualified name of the desired class.
  126.      * @return     the <code>DTClass</code> descriptor for the class with the
  127.      *             specified name. Returns null if class not found.
  128.      */
  129.     public static DTClass findSystemClass(String className) {
  130.         if (className.charAt(0) == '[')                        // "[Ljava.lang.Object;" format!
  131.             className = classnameToString(className);        // Convert it to "java.lang.Object[]" format
  132.  
  133.         // Check the cache
  134.         DTClass systemClass = (DTClass) systemClassHash.get(className);
  135.         if (systemClass != null)
  136.             return systemClass;
  137.  
  138.         int dim = scanDim(className);
  139.         String baseName = (dim > 0) ? componentName(className) : className;
  140.  
  141.         // first check primitives
  142.         systemClass = getPrimitiveClass(baseName);
  143.         if (systemClass != null) {
  144.             if (dim != 0)
  145.                 systemClass = new DTClass(systemClass, dim);
  146.         }
  147.         // otherwise may be component class
  148.         else {
  149.             try {
  150.                 Class clazz = Class.forName(getClassname(className, dim));
  151.                 systemClass = new DTClass(null, className, clazz, dim, false, false);
  152.             } catch (Exception e) {
  153.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  154.                     System.out.println("    DTClass: findSystemClass(" + baseName + ") threw " + e);
  155.                     e.printStackTrace();
  156.                 }
  157.             }
  158.         }
  159.  
  160.         // Cache it
  161.         return DTClass.registerSystemClass(systemClass);
  162.     }
  163.  
  164.  
  165.     private static DTClass registerClass(DTClass dtClass, boolean replace) {
  166.         if (dtClass.project != null)
  167.             return DTClass.registerProjectClass(dtClass, replace);
  168.         return DTClass.registerSystemClass(dtClass);
  169.     }
  170.     private static DTClass registerProjectClass(DTClass dtClass, boolean replace) {
  171.         if (dtClass == null) return null;
  172.         return (DTClass) ((symantec.itools.vcafe.visual.PVisualProject)dtClass.project).registerDTClassObject(dtClass, replace);
  173.     }
  174.     private static DTClass registerSystemClass(DTClass systemClass) {
  175.         if (systemClass != null)
  176.             systemClassHash.put(systemClass.name, systemClass);
  177.         return systemClass;
  178.     }
  179.  
  180.     /**
  181.      * Return true if class is in a project, as opposed to component
  182.      * library or system classpath.
  183.      */
  184.     public boolean isProjectClass() {
  185.         return projectClass;
  186.     }
  187.  
  188.     /**
  189.      * Return classloader for this class (project's classloader).
  190.      */
  191.     public ClassLoader getProjectLoader() {
  192.         if (project == null) return null;
  193.         return project.getClassLoader();
  194.     }
  195.  
  196.     /**
  197.      * Determines if the class or interface
  198.      * represented by this DTClass object is either the same as, or is a
  199.      * superclass or superinterface of, the class or interface
  200.      * represented by the specified DTClass parameter. It returns true
  201.      * if so, false otherwise. If this DTClass object represents a
  202.      * primitive type, returns true if the specified DTClass parameter
  203.      * is exactly this DTClass object, false otherwise.
  204.      *
  205.      * <p>Specifically, this method tests whether the type represented
  206.      * by the specified DTClass parameter can be converted to the type
  207.      * represented by this DTClass object via an identity conversion or
  208.      * via a widening reference conversion. See <em>The Java Language
  209.      * Specification</em>, sections 5.1.1 and 5.1.4 , for details.
  210.      *
  211.      * <p>This method works the same as Class.isAssignableFrom(), which
  212.      * means it is not accurate for primitive classes.
  213.      * @see isAssignable
  214.      * @exception NullPointerException if the specified DTClass parameter is null.
  215.      */
  216.     public boolean isAssignableFrom(DTClass cls) {
  217.         if (this == VoidType || cls == VoidType || this == NullType) return false;
  218.         if (this == AnyType || cls == AnyType) return true;
  219.         if (cls == NullType)
  220.             return !primitive;
  221.         if (primitive || cls.primitive)
  222.             return this == cls;
  223.         else
  224.             return equals(cls) || cls.isSuperclass(this);
  225.     }
  226.  
  227.     /**
  228.      * Determines if a value of a specified type can be assigned
  229.      * without explicit conversion or casting to a value of this type.
  230.      *
  231.      * <p>Differs from isAssignableFrom() in its treatment of primitive
  232.      * classes.
  233.      *
  234.      * <p>Specifically, this method tests whether the type represented
  235.      * by the specified DTClass parameter can be converted to the type
  236.      * represented by this DTClass object via an identity conversion,
  237.      * a widening reference conversion or a widening numeric conversion.
  238.      * See <em>The Java Language Specification</em>, sections 5.1.1, 5.1.4
  239.      * and 5.2, for details.
  240.      *
  241.      * <p>Note that a particular numeric constant value might be assignable
  242.      * via a narrowing conversion if its value fits in the destination
  243.      * type without loss of information, e.g., byte b = 52; where the
  244.      * constant 52 is an int. This must be tested using isAssignable(int)
  245.      * with the specific value.
  246.      *
  247.      * @exception NullPointerException if the specified DTClass parameter is null.
  248.      */
  249.     public boolean isAssignable(DTClass cls) {
  250.         boolean assignable;
  251.         if (this == VoidType || cls == VoidType || this == NullType) {
  252.             assignable = false;
  253.         } else if (this == AnyType || cls == AnyType) {
  254.             assignable = true;
  255.         } else if (primitive) {
  256.             if (this == cls) {
  257.                 assignable = true;
  258.             } else if (cls == ByteType) {
  259.                 assignable = (this == ShortType || this == IntegerType || this == LongType || this == FloatType || this == DoubleType);
  260.             } else if (cls == ShortType) {
  261.                 assignable = (this == IntegerType || this == LongType || this == FloatType || this == DoubleType);
  262.             } else if (cls == IntegerType) {
  263.                 assignable = (this == LongType || this == FloatType || this == DoubleType);
  264.             } else if (cls == LongType) {
  265.                 assignable = (this == FloatType || this == DoubleType);
  266.             } else if (cls == FloatType) {
  267.                 assignable = (this == DoubleType);
  268.             } else {
  269.                 assignable = false;
  270.             }
  271.         } else if (cls.primitive) {
  272.             assignable = cls == NullType;
  273.         } else {
  274.               assignable = equals(cls) || cls.isSuperclass(this);
  275.         }
  276.  
  277.         return assignable;
  278.     }
  279.  
  280.     /**
  281.      * Determines if a specified constant value can be assigned
  282.      * without explicit conversion or casting to a value of this type.
  283.      *
  284.      * <p>A particular numeric constant value is assignable if its value
  285.      * fits in the destination
  286.      * type without loss of information, e.g., byte b = 52; where the
  287.      * constant 52 is an int.
  288.      */
  289.     public boolean isAssignable(long value) {
  290.         if (this == AnyType) return true;
  291.         return (this == ByteType &&
  292.                     (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)) ||
  293.                 (this == ShortType &&
  294.                     (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)) ||
  295.                 (this == IntegerType &&
  296.                     (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE)) ||
  297.                 (this == LongType);
  298.     }
  299.  
  300.     /**
  301.      * Determines if the class or interface
  302.      * represented by this DTClass object implements or extends
  303.      * the class or interface represented by the specified DTClass parameter.
  304.      * It returns true if so, false otherwise. If this DTClass object represents a
  305.      * primitive type, returns true if the specified DTClass parameter
  306.      * is exactly this DTClass object, false otherwise.
  307.      *
  308.      * <p>For non-primitive types, returns what the implements operator
  309.      * would for corresponding Class objects.
  310.      *
  311.      * <p>This is the opposite of isAssignableFrom().
  312.      *
  313.      * @exception NullPointerException if the specified DTClass parameter is null.
  314.      */
  315.     public boolean isImplementationOf(DTClass cls) {
  316.         return cls.isAssignableFrom(this);
  317.     }
  318.  
  319.     /**
  320.      * Determines if the specified DTClass object represents an interface type.
  321.      *
  322.      * @return    <code>true</code> if this object represents an interface;
  323.      *          <code>false</code> otherwise.
  324.      */
  325.     public boolean isInterface() {
  326.         return Modifier.isInterface(modifier);
  327.     }
  328.  
  329.     /**
  330.      * If this DTClass object represents an array type, returns true,
  331.      * otherwise returns false.
  332.      */
  333.     public boolean isArray() {
  334.         return dim != 0;
  335.     }
  336.  
  337.     /**
  338.      * If this DTClass object represents an array type, returns the number of array dimensions,
  339.      * otherwise returns false.
  340.      */
  341.     public int getDimensions() {
  342.         return dim;
  343.     }
  344.  
  345.     /**
  346.      * Return an array with the bounds of each array dimension
  347.      * for the current class.The length of the returned int array
  348.      * is equal to the number of dimensions of the class.
  349.      * Returns empty array if the class is not an array.
  350.      */
  351.     public int[] getBounds() {
  352.         int[] array = new int[dim];
  353.         if (dim > 0) {
  354.             int n = name.length()-1;
  355.             char[] chars = name.toCharArray();
  356.             for (int i = dim-1; i >=0; i--) {
  357.                 int idim = 0, mul = 1;
  358.                 char c;
  359.                 while ((c = chars[--n]) >= '0' && c <= '9') {
  360.                     idim += ((int)c - (int)'0') * mul;
  361.                     mul *= 10;
  362.                 }
  363.                 --n;
  364.                 array[i] = idim;
  365.             }
  366.         }
  367.         return array;
  368.     }
  369.  
  370.     /**
  371.      * Determines if the specified DTClass object represents a primitive Java
  372.      * type.
  373.      *
  374.      * <p>There are nine predefined DTClass objects to represent the eight
  375.      * primitive Java types and void.  These are created by the DTReflection API,
  376.      * and have the same names as the primitive types
  377.      * that they represent, namely boolean, byte, char, short, int,
  378.      * long, float, and double, and void.
  379.      *
  380.      * <p>These objects may only be accessed via the following public
  381.      * static final variables, and are the only DTClass objects for
  382.      * which this method returns true.
  383.      *
  384.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.BooleanType
  385.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.CharacterType
  386.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.ByteType
  387.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.ShortType
  388.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.IntegerType
  389.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.LongType
  390.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.FloatType
  391.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.DoubleType
  392.      * com.symantec.itools.vcafe.openapi.dtreflect.DTClass.VoidType
  393.      */
  394.     public boolean isPrimitive() {
  395.         return primitive;
  396.     }
  397.  
  398.     // Helpful constants. getPrimitiveClass() and getDTClassObject() always
  399.     // return these references for "boolean", "char", etc.
  400.  
  401.     public static final DTClass BooleanType = DTClass.getPrimitiveClass("boolean");
  402.     public static final DTClass CharacterType = DTClass.getPrimitiveClass("char");
  403.     public static final DTClass ByteType = DTClass.getPrimitiveClass("byte");
  404.     public static final DTClass ShortType = DTClass.getPrimitiveClass("short");
  405.     public static final DTClass IntegerType = DTClass.getPrimitiveClass("int");
  406.     public static final DTClass LongType = DTClass.getPrimitiveClass("long");
  407.     public static final DTClass FloatType = DTClass.getPrimitiveClass("float");
  408.     public static final DTClass DoubleType = DTClass.getPrimitiveClass("double");
  409.     public static final DTClass VoidType = DTClass.getPrimitiveClass("void");
  410.  
  411.     // A type that is assignable to/from any type
  412.     public static final DTClass AnyType = DTClass.getPrimitiveClass("*");
  413.  
  414.     // A type that is assignable to any non-primitive type
  415.     public static final DTClass NullType = DTClass.getPrimitiveClass("null");
  416.  
  417.     /**
  418.      * Returns the fully-qualified name of the type (class, interface,
  419.      * array, or primitive) represented by this DTClass object, as a String.
  420.      *
  421.      * <p>Array classes are named using standard notation, e.g.,
  422.      * "java.lang.String[]" and "byte[][]".
  423.      */
  424.     public String getName() {
  425.         return name;
  426.     }
  427.  
  428.     /**
  429.      * Returns the package of the type (class, interface, array, or primitive) represented
  430.      * by this DTClass object as a String, or null if the class isn't in a package
  431.      */
  432.     public String getPackageName() {
  433.         return packageName;
  434.     }
  435.  
  436.     /**
  437.      * Returns the unqualified name (package is excluded) of the type (class, interface,
  438.      * array, or primitive) represented by this DTClass object, as a String.
  439.      *
  440.      * <p>Array classes are named using standard notation, e.g.,
  441.      * "String[]" and "byte[][]".
  442.      */
  443.     public String getUnqualifiedName() {
  444.         if (packageName == null || packageName.length() == 0) return name;
  445.         return name.substring(packageName.length() + 1);
  446.     }
  447.  
  448.     /**
  449.      * Returns true if the argument object is a superclass of the current class.
  450.      */
  451.     public boolean isSuperclass(DTClass superClass) {
  452.         if (primitive || superClass.primitive) return false;
  453.  
  454.         // The both have to be arrays of the same dimension or neither can be arrays
  455.         // This can be checked by comparing dimension directly
  456.         if (dim != superClass.dim)
  457.             return false;
  458.  
  459.         boolean bIsSuperclass = false;
  460.  
  461.         // Look in our hash of checked superclasses, before checking deep.
  462.         if (checkedSuperclasses != null) {
  463.             Boolean b = (Boolean) checkedSuperclasses.get(superClass);
  464.             if (b != null)
  465.                 return b.booleanValue();
  466.         } else {
  467.             checkedSuperclasses = new Hashtable();
  468.         }
  469.  
  470.         // Determine if superClass is a super class of this class
  471.         if (!projectClass) {
  472.             try    {
  473.                 Class from = loadClass();
  474.                 Class to = superClass.loadClass();
  475.                 bIsSuperclass = to.isAssignableFrom(from);
  476.             } catch    (Exception e) {
  477.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  478.                     System.out.println("    DTClass: " + name + ".isSuperclass(" + superClass.name + ") threw " + e);
  479.                     e.printStackTrace();
  480.                 }
  481.             }
  482.         } else {
  483.             bIsSuperclass = isSuperClass0(superClass);
  484.  
  485.         }
  486.  
  487.         // Cache the lookup value
  488.         checkedSuperclasses.put(superClass, new Boolean(bIsSuperclass));
  489.  
  490.         return bIsSuperclass;
  491.     }
  492.  
  493.     /**
  494.      * If this object represents any class other than the class
  495.      * </code>Object</code>, then the object that represents the superclass
  496.      * of that class is returned.
  497.      *
  498.      * <p>If this object is the one that represents the class
  499.      * </code>Object</code> or this object represents an interface,
  500.      * </code>null</code> is returned.
  501.      *
  502.      * @return    the superclass of the class represented by this object.
  503.      */
  504.     public DTClass getSuperclass() {
  505.         if (primitive)
  506.             return null;
  507.  
  508.         if (gotSuperClass)
  509.             return superClass;
  510.  
  511.         if (!projectClass) {
  512.             try {
  513.                 Class clazz = loadComponentClass();
  514.                 Class superClazz = clazz.getSuperclass();
  515.  
  516.                 superClass = new DTClass(project, superClazz.getName()+arrayPart(name), superClazz, scanDim(name), false, false);
  517.                 superClass = DTClass.registerClass(superClass, false /*!replace*/);
  518.             } catch (Exception e) {
  519.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  520.                     System.out.println("    DTClass: " + name + ".getSuperclass() threw " + e);
  521.                     e.printStackTrace();
  522.                 }
  523.             }
  524.         } else {
  525.             superClass = DTClass.registerProjectClass(getSuperclass0(), false/*!replace*/);
  526.         }
  527.  
  528.         gotSuperClass = true;
  529.         return superClass;
  530.     }
  531.  
  532.     /**
  533.      * Determines the interfaces implemented by the class or interface
  534.      * represented by this object.
  535.      *
  536.      * <p>If this object represents a class, the return value is an array
  537.      * containing objects representing all interfaces implemented by the
  538.      * class. The order of the interface objects in the array corresponds
  539.      * to the order of the interface names in the </code>implements</code>
  540.      * clause of the declaration of the class represented by this object.
  541.      *
  542.      * <p>If this object represents an interface, the array contains
  543.      * objects representing all interfaces extended by the interface. The
  544.      * order of the interface objects in the array corresponds to the
  545.      * order of the interface names in the </code>extends</code> clause of
  546.      * the declaration of the interface represented by this object.
  547.      *
  548.      * <p>If the class or interface implements no interfaces, the method
  549.      * returns an array of length 0.
  550.      *
  551.      * @return    an array of interfaces implemented by this class.
  552.      */
  553.     public DTClass[] getInterfaces() {
  554.         if (primitive || isArray()) return new DTClass[0];
  555.         if (!projectClass) {
  556.             try {
  557.                 Class clazz = loadClass();
  558.                 Class[] ifaces = clazz.getInterfaces();
  559.                 return classToDTClassArray(ifaces);
  560.             } catch (Exception e) {
  561.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  562.                     System.out.println("    DTClass: " + name + ".getInterfaces() threw " + e);
  563.                     e.printStackTrace();
  564.                 }
  565.             }
  566.             return new DTClass[0];
  567.         }
  568.  
  569.         DTClass[] interfaces = getInterfaces0();
  570.         for (int i = 0; i < interfaces.length; i++)
  571.             interfaces[i] = DTClass.registerProjectClass(interfaces[i], false /*!replace*/);
  572.         return interfaces;
  573.     }
  574.  
  575.     /**
  576.      * If this class represents an array type, returns the DTClass
  577.      * object representing the component type of the array; otherwise
  578.      * returns null.
  579.      */
  580.     public DTClass getComponentType() {
  581.         return isArray() ? findClass(project, getComponentName()) : null;
  582.     }
  583.  
  584.     /**
  585.      * If this class represents an array type, returns the name
  586.      * of the component type; otherwise
  587.      * returns the class name.
  588.      */
  589.     public String getComponentName() {
  590.         if (dim > 0)
  591.             return componentName(name);
  592.         else
  593.             return name;
  594.     }
  595.  
  596.  
  597.     protected static int scanDim(String className) {
  598.         int i, dim = 0, n = className.length();
  599.         for (i = n-1; i >= 0; i--) {
  600.             char c = className.charAt(i);
  601.             if (c == '[') dim++;
  602.             if (!(c == '[' || c == ']' || (c >= '0' && c <= '9')))
  603.                 break;
  604.         }
  605.         return dim;
  606.     }
  607.  
  608.     protected static String componentName(String str) {
  609.         int len = str.indexOf('[');
  610.         if (len >= 0)
  611.             return str.substring(0,len);
  612.         return str;
  613.     }
  614.  
  615.     static String arrayPart(String str) {
  616.         int len = str.indexOf('[');
  617.         if (len >= 0)
  618.             return str.substring(len);
  619.         return "";
  620.     }
  621.  
  622.     /**
  623.      * Returns the Java language modifiers for this class or
  624.      * interface, encoded in an integer. The modifiers consist of the
  625.      * Java Virtual Machine's constants for public, protected,
  626.      * private, final, and interface; they should be decoded using the
  627.      * methods of class Modifier.
  628.      *
  629.      * <p>The modifier encodings are defined in <em>The Java Virtual
  630.      * Machine Specification</em>, table 4.1.
  631.      *
  632.      * @see     java.lang.reflect.Modifier
  633.      */
  634.     public int getModifiers() {
  635.         return modifier;
  636.     }
  637.  
  638.     /**
  639.      * If the class or interface represented by this DTClass object is
  640.      * a member of another class, returns the DTClass object
  641.      * representing the class of which it is a member (its
  642.      * <em>declaring class</em>).  Returns null if this class or
  643.      * interface is not a member of any other class.
  644.      *
  645.      */
  646.     public DTClass getDeclaringClass(){
  647.         if (!(primitive || isArray())) {
  648.             if (projectClass) {
  649.                    return DTClass.registerProjectClass(getDeclaringClass0(), false /*!replace*/);
  650.             }
  651.  
  652.             try {
  653.                 Class clazz = loadClass();
  654.                 DTClass dtClass = new DTClass(project, clazz.getDeclaringClass());
  655.                 return DTClass.registerClass(dtClass, false /*!replace*/);
  656.             } catch (Exception e) {
  657.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  658.                     System.out.println("    DTClass: " + name + ".getDeclaringClass() threw " + e);
  659.                     e.printStackTrace();
  660.                 }
  661.             }
  662.         }
  663.         return null;
  664.     }
  665.  
  666.     /**
  667.      * Returns an array containing DTClass objects representing all the
  668.      * public classes and interfaces that are members of the class
  669.      * represented by this DTClass object. This includes public class
  670.      * and interface members inherited from superclasses and public
  671.      * class and interface members declared by the class.  Returns an
  672.      * array of length 0 if the class has no public member classes or
  673.      * interfaces, or if this DTClass object represents a primitive
  674.      * type.
  675.      *
  676.      */
  677.     public DTClass[] getClasses() {
  678.         return getClasses(Member.PUBLIC);
  679.     }
  680.  
  681.     /**
  682.      * Returns an array containing DTField objects reflecting all the
  683.      * accessible public fields of the class or interface represented
  684.      * by this DTClass object. Returns an array of length 0 if the
  685.      * class or interface has no accessible public fields, or if it
  686.      * represents an array type or a primitive type.
  687.      *
  688.      * <p>Specifically, if this DTClass object represents a class,
  689.      * returns the public fields of this class and of all its
  690.      * superclasses.  If this DTClass object represents an interface,
  691.      * returns the fields of this interface and of all its
  692.      * superinterfaces.  If this DTClass object represents an array type
  693.      * or a primitive type, returns an array of length 0.
  694.      *
  695.      * <p>The implicit length field for array types is not reflected
  696.      * by this method. User code should use the methods of class Array
  697.      * to manipulate arrays.
  698.      *
  699.      * <p>See <em>The Java Language Specification</em>, sections 8.2 and 8.3.
  700.      *
  701.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTField
  702.      */
  703.     public DTField[] getFields() {
  704.         synchronized (cacheFlusher) {
  705.             if (publicFields == null)
  706.                 publicFields = getFields(Member.PUBLIC);
  707.             cacheFlusher.scheduleCacheFlush(this);
  708.             return publicFields;
  709.         }
  710.     }
  711.  
  712.     /**
  713.      * Returns an array containing DTMethod objects reflecting all the
  714.      * public <em>member</em> methods of the class or interface
  715.      * represented by this DTClass object, including those declared by
  716.      * the class or interface and and those inherited from
  717.      * superclasses and superinterfaces. Returns an array of length 0
  718.      * if the class or interface has no public member methods.
  719.      *
  720.      * <p>See <em>The Java Language Specification</em>, sections 8.2
  721.      * and 8.4.
  722.      *
  723.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTMethod
  724.      */
  725.     public DTMethod[] getMethods() {
  726.         return getMethods(Member.PUBLIC);
  727.     }
  728.  
  729.     /**
  730.      * Returns an array containing DTConstructor objects reflecting
  731.      * all the public constructors of the class    represented    by this
  732.      * DTClass object.    An array of    length 0 is    returned if    the    class
  733.      * has no public constructors.
  734.      *
  735.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTConstructor
  736.      */
  737.     public DTConstructor[] getConstructors() {
  738.         return getConstructors(Member.PUBLIC);
  739.     }
  740.  
  741.     /**
  742.      * Returns a DTField object    that reflects the specified    public
  743.      * member field    of the class or    interface represented by
  744.      * this    DTClass    object.    The    name parameter is a    String specifying
  745.      * the simple name of the desired field.
  746.      *
  747.      * <p>The field    to be reflected    is located by searching    all    the
  748.      * member fields of    the    class or interface represented by this
  749.      * DTClass object for a    public field with the specified    name.
  750.      *
  751.      * <p>See <em>The Java Language    Specification</em>,    sections 8.2 and 8.3.
  752.      *
  753.      * @return field or    null if    no such    field.
  754.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTField
  755.      */
  756.     public DTField getField(String name) {
  757.         return getField(name, Member.PUBLIC);
  758.     }
  759.  
  760.     /**
  761.      * Returns a DTMethod object that reflects the specified public
  762.      * member method of    the    class or interface represented by this
  763.      * DTClass object. The name    parameter is a String specifying the
  764.      * simple name the desired method, and the parameterTypes
  765.      * parameter is    an array of    DTClass    objects    that identify the
  766.      * method's    formal parameter types,    in declared    order.
  767.      *
  768.      * <p>The method to    reflect    is located by searching    all    the    member
  769.      * methods of the class    or interface represented by    this DTClass
  770.      * object for a    public method with the specified name and exactly
  771.      * the same    formal parameter types.
  772.      *
  773.      * <p>See <em>The Java Language    Specification</em>,    sections 8.2
  774.      * and 8.4.
  775.      *
  776.      * @return method or null if no    such method.
  777.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTMethod
  778.      */
  779.     public DTMethod    getMethod(String name, DTClass[] parameterTypes) {
  780.         return getMethod(name,    parameterTypes,    Member.PUBLIC);
  781.     }
  782.  
  783.     /**
  784.      * Returns a DTMethod object that reflects the specified public
  785.      * member method of the class or interface represented by this
  786.      * DTClass object. The name parameter is a String specifying the
  787.      * simple name the desired method, and the parameterTypeNames
  788.      * parameter is an array of String objects that identify the
  789.      * method's formal parameter types, in declared order.
  790.      *
  791.      * <p>The method to reflect is located by searching all the member
  792.      * methods of the class or interface represented by this DTClass
  793.      * object for a public method with the specified name and exactly
  794.      * the same formal parameter types.
  795.      *
  796.      * <p>See <em>The Java Language Specification</em>, sections 8.2
  797.      * and 8.4.
  798.      *
  799.      * @return method or null if no such method.
  800.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTMethod
  801.      */
  802.     public DTMethod    getMethod(String name, String[] parameterTypeNames) {
  803.         return getMethod(name, parameterTypeNames, Member.PUBLIC);
  804.     }
  805.  
  806.     /**
  807.      * Returns a DTConstructor object that reflects    the    specified public
  808.      * constructor of the class    represented    by this    DTClass    object.    The
  809.      * parameterTypes parameter    is an array    of DTClass objects that
  810.      * identify    the    constructor's formal parameter types, in declared
  811.      * order.
  812.      *
  813.      * <p>The constructor to reflect is    located    by searching all the
  814.      * constructors    of the class represented by    this DTClass object    for
  815.      * a public    constructor    with the exactly the same formal parameter
  816.      * types.
  817.      *
  818.      * @return constructor or null if no such constructor.
  819.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTConstructor
  820.      */
  821.     public DTConstructor getConstructor(DTClass[] parameterTypes) {
  822.         return getConstructor(parameterTypes, Member.PUBLIC);
  823.     }
  824.  
  825.     /**
  826.      * Returns a DTConstructor object that reflects the specified public
  827.      * constructor of the class represented by this DTClass object. The
  828.      * parameterTypeNames parameter is an array of String objects that
  829.      * identify the constructor's formal parameter types, in declared
  830.      * order.
  831.      *
  832.      * <p>The constructor to reflect is located by searching all the
  833.      * constructors of the class represented by this DTClass object for
  834.      * a public constructor with the exactly the same formal parameter
  835.      * types.
  836.      *
  837.      * @return constructor or null if no such constructor.
  838.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTConstructor
  839.      */
  840.     public DTConstructor getConstructor(String[] parameterTypeNames) {
  841.         return getConstructor(parameterTypeNames, Member.PUBLIC);
  842.     }
  843.  
  844.     /**
  845.      * Returns an array    of DTClass objects reflecting all the classes
  846.      * and interfaces declared as members of the class represented by
  847.      * this    DTClass    object.    This includes public, protected, default
  848.      * (package) access, and private classes and interfaces    declared
  849.      * by the class, but excludes inherited    classes    and    interfaces.
  850.      * Returns an array    of length 0    if the class declares no classes
  851.      * or interfaces as    members, or    if this    DTClass    object represents a
  852.      * primitive type.
  853.      *
  854.      */
  855.     public DTClass[] getDeclaredClasses() {
  856.         return getClasses(Member.DECLARED);
  857.     }
  858.  
  859.     /**
  860.      * Returns an array    of DTField objects reflecting all the fields
  861.      * declared    by the class or    interface represented by this DTClass
  862.      * object. This    includes public, protected,    default    (package)
  863.      * access, and private fields, but excludes    inherited
  864.      * fields. Returns an array    of length 0    if the class or    interface
  865.      * declares    no fields, or if this DTClass object represents    a
  866.      * primitive type.
  867.      *
  868.      * See <em>The Java    Language Specification</em>, sections 8.2 and
  869.      * 8.3.
  870.      *
  871.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTField
  872.      */
  873.     public DTField[] getDeclaredFields() {
  874.         synchronized (cacheFlusher) {
  875.             if (declaredFields == null)
  876.                 declaredFields = getFields(Member.DECLARED);
  877.             cacheFlusher.scheduleCacheFlush(this);
  878.             return declaredFields;
  879.         }
  880.     }
  881.  
  882.     /**
  883.      * Returns an array    of DTMethod    objects    reflecting all the methods
  884.      * declared    by the class or    interface represented by this DTClass
  885.      * object. This    includes public, protected,    default    (package)
  886.      * access, and private methods,    but    excludes inherited
  887.      * methods.    Returns    an array of    length 0 if    the    class or interface
  888.      * declares    no methods,    or if this DTClass object represents a
  889.      * primitive type.
  890.      *
  891.      * <p>See <em>The Java Language    Specification</em>,    section    8.2.
  892.      *
  893.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTMethod
  894.      */
  895.     public DTMethod[] getDeclaredMethods() {
  896.         return getMethods(Member.DECLARED);
  897.     }
  898.  
  899.     /**
  900.      * Returns an array    of DTConstructor objects reflecting    all    the
  901.      * constructors    declared by    the    class represented by this DTClass
  902.      * object. These are public, protected,    default    (package) access,
  903.      * and private constructors.  Returns an array of length 0 if this
  904.      * DTClass object represents an    interface or a primitive type.
  905.      *
  906.      * <p>See <em>The Java Language    Specification</em>,    section    8.2.
  907.      *
  908.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTConstructor
  909.      */
  910.     public DTConstructor[] getDeclaredConstructors() {
  911.         return getConstructors(Member.DECLARED);
  912.     }
  913.  
  914.     /**
  915.      * Returns a DTField object    that reflects the specified    declared
  916.      * field of    the    class or interface represented by this DTClass
  917.      * object. The name    parameter is a String that specifies the
  918.      * simple name of the desired field.
  919.      *
  920.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTField
  921.      */
  922.     public DTField getDeclaredField(String name) {
  923.         return getField(name, Member.DECLARED);
  924.     }
  925.  
  926.     /**
  927.      * Returns a DTMethod object that reflects the specified declared
  928.      * method of the class or interface    represented    by this    DTClass
  929.      * object. The name    parameter is a String that specifies the
  930.      * simple name of the desired method, and the parameterTypes
  931.      * parameter is    an array of    DTClass    objects    that identify the
  932.      * method's    formal parameter types,    in declared    order.
  933.      *
  934.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTMethod
  935.      */
  936.     public DTMethod    getDeclaredMethod(String name, DTClass[] parameterTypes) {
  937.         return getMethod(name,    parameterTypes,    Member.DECLARED);
  938.     }
  939.  
  940.     /**
  941.      * Returns a DTMethod object that reflects the specified declared
  942.      * method of the class or interface represented by this DTClass
  943.      * object. The name parameter is a String that specifies the
  944.      * simple name of the desired method, and the parameterTypeNames
  945.      * parameter is an array of DTClass objects that identify the
  946.      * method's formal parameter types, in declared order.
  947.      *
  948.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTMethod
  949.      */
  950.     public DTMethod getDeclaredMethod(String name, String[] parameterTypeNames) {
  951.         return getMethod(name, parameterTypeNames, Member.DECLARED);
  952.     }
  953.  
  954.     /**
  955.      * Returns a DTConstructor object that reflects    the    specified declared
  956.      * constructor of the class    or interface represented by    this DTClass
  957.      * object.    The    parameterTypes parameter is    an array of    DTClass
  958.      * objects that    identify the constructor's formal parameter    types,
  959.      * in declared order.
  960.      *
  961.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTConstructor
  962.      */
  963.     public DTConstructor getDeclaredConstructor(DTClass[] parameterTypes) {
  964.         return getConstructor(parameterTypes, Member.DECLARED);
  965.     }
  966.  
  967.     /**
  968.      * Returns a DTConstructor object that reflects the specified declared
  969.      * constructor of the class or interface represented by this DTClass
  970.      * object. The parameterTypeNames parameter is an array of String
  971.      * objects that identify the constructor's formal parameter types,
  972.      * in declared order.
  973.      *
  974.      * @see       com.symantec.itools.vcafe.openapi.dtreflect.DTConstructor
  975.      */
  976.     public DTConstructor getDeclaredConstructor(String[] parameterTypeNames) {
  977.         return getConstructor(parameterTypeNames, Member.DECLARED);
  978.     }
  979.  
  980.  
  981.     /**
  982.      * Returns an array    of DTMethod    objects    reflecting all the methods
  983.      * in the class or    interface represented by this DTClass object that
  984.      * can be seen by accessibleBy.
  985.      * This includes all public methods, protected methods if accessibleBy is
  986.      * a subclass of this class (and they represent the same object), and
  987.      * methods with package access if accessibleBy is in the same package as this class.
  988.      * Inherited methods are included.
  989.      *
  990.      * Returns an array of length 0 if the class or interface declares no methods,
  991.      * or if this DTClass object represents a primitive type.
  992.      *
  993.      * @see       getMethods
  994.      */
  995.     public DTMethod[] getAccessibleMethods(DTClass accessibleByClass, boolean sameObject) {
  996.         if (!(primitive    || isArray())) {
  997.  
  998.             synchronized(cacheFlusher) {
  999.                 // See if the list of accessible methods is in our toplevel cache
  1000.                 //    (what we last searched for)
  1001.                 String accessibleMethodsKey = accessibleByClass.name + sameObject;
  1002.                 if (allAccessibleMethods != null && !accessibleMethodsKey.equals(allAccessibleMethodsKey)) {
  1003.                     allAccessibleMethods = null;
  1004.                 }
  1005.  
  1006.                 // Not in the toplevel cache.  Walk the hierarchy to build the list
  1007.                 if (allAccessibleMethods == null) {
  1008.                     // Get the (filtered) list of methods
  1009.                     Hashtable dtMethodsHash = new Hashtable();
  1010.                     Vector dtMethodsVector = new Vector(100);
  1011.                     AccessibleMemberFilter accessFilter = new AccessibleMemberFilter(accessibleMethodsKey, accessibleByClass, sameObject);
  1012.                     getAccessibleMethodsImpl(accessFilter, dtMethodsHash, dtMethodsVector);
  1013.  
  1014.                     // Build an array of the methods
  1015.                     dtMethodsHash = null;
  1016.                     allAccessibleMethodsKey = accessibleMethodsKey;
  1017.                     allAccessibleMethods = new DTMethod[dtMethodsVector.size()];
  1018.                     dtMethodsVector.copyInto(allAccessibleMethods);
  1019.                 }
  1020.  
  1021.                 cacheFlusher.scheduleCacheFlush(this);
  1022.                 return allAccessibleMethods;
  1023.             }
  1024.         }
  1025.         return new DTMethod[0];
  1026.     }
  1027.  
  1028.         // Worker function to walk down the hierarchy getting the accessible methods
  1029.     private void getAccessibleMethodsImpl(AccessibleMemberFilter accessFilter, Hashtable dtMethodsHash, Vector dtMethodsVector) {
  1030.         DTMethod[] dtMethods;
  1031.  
  1032.         //
  1033.         //    First, get the list of ALL accessible methods at this level
  1034.         //
  1035.  
  1036.         // See if the list of accessible methods is in our cache
  1037.         if (accessibleMethods == null) {
  1038.             accessibleMethods = new Hashtable();
  1039.             dtMethods = null;
  1040.         } else {
  1041.             dtMethods = (DTMethod[])accessibleMethods.get(accessFilter.membersKey);
  1042.         }
  1043.  
  1044.         // Not in the cache.  Look 'em up.
  1045.         if (dtMethods == null) {
  1046.             if (projectClass) {
  1047.                 dtMethods = getAccessibleMethods0(accessFilter.accessibleByClass.name, accessFilter.isSameObject);
  1048.             } else {
  1049.                 dtMethods = getMethods1(Member.DECLARED, (accessFilter.isSameClass ? null : accessFilter));
  1050.             }
  1051.  
  1052.             // Cache the methods we found (If we didn't find any, remember that too)
  1053.             if (dtMethods == null)
  1054.                 dtMethods = new DTMethod[0];
  1055.  
  1056.             accessibleMethods.put(accessFilter.membersKey, dtMethods);
  1057.         }
  1058.  
  1059.  
  1060.         //
  1061.         //    Next, filter out duplicates by only adding new methods to the Hashtable & Vector
  1062.         //
  1063.         for (int i = 0; i < dtMethods.length; i++) {
  1064.             DTMethod dtMethod = dtMethods[i];
  1065.             String methodName = dtMethod.toShortString();
  1066.             if (!dtMethodsHash.containsKey(methodName)) {
  1067.                 dtMethodsHash.put(methodName, dtMethod);
  1068.                 dtMethodsVector.addElement(dtMethod);
  1069.             }
  1070.         }
  1071.  
  1072.  
  1073.         //
  1074.         //    Now, get the superclass's accessible methods
  1075.         //
  1076.         DTClass superClass = this.getSuperclass();
  1077.         if (superClass != null) {
  1078.             accessFilter.adjustLevel(superClass);
  1079.             superClass.getAccessibleMethodsImpl(accessFilter, dtMethodsHash, dtMethodsVector);
  1080.         }
  1081.     }
  1082.  
  1083.  
  1084.     /**
  1085.      * Returns an array    of DTField objects reflecting all the fields
  1086.      * in the class or interface represented by this DTClass object that
  1087.      * can be seen by accessibleBy.
  1088.      * This includes all public fields, protected fields if accessibleBy is
  1089.      * a subclass of this class (and they represent the same object), and
  1090.      * fields with package access if accessibleBy is in the same package as this class.
  1091.      * Inherited fields are included.
  1092.      *
  1093.      * Returns an array of length 0 if the class or interface declares no fields,
  1094.      * or if this DTClass object represents a primitive type.
  1095.      *
  1096.      * @see       getFields
  1097.      */
  1098.     public DTField[] getAccessibleFields(DTClass accessibleByClass, boolean sameObject) {
  1099.         if (!(primitive    || isArray())) {
  1100.  
  1101.             synchronized(cacheFlusher) {
  1102.                 // See if the list of accessible fields is in our toplevel cache
  1103.                 //    (what we last searched for)
  1104.                 String accessibleFieldsKey = accessibleByClass.name + sameObject;
  1105.                 if (allAccessibleFields != null && !accessibleFieldsKey.equals(allAccessibleFieldsKey)) {
  1106.                     allAccessibleFields = null;
  1107.                 }
  1108.  
  1109.                 // Not in the toplevel cache.  Walk the hierarchy to build the list
  1110.                 if (allAccessibleFields == null) {
  1111.                     // Get the (filtered) list of fields
  1112.                     Hashtable dtFieldsHash = new Hashtable();
  1113.                     Vector dtFieldsVector = new Vector(100);
  1114.                     AccessibleMemberFilter accessFilter = new AccessibleMemberFilter(accessibleFieldsKey, accessibleByClass, sameObject);
  1115.                     getAccessibleFieldsImpl(accessFilter, dtFieldsHash, dtFieldsVector);
  1116.  
  1117.                     // Build an array of the fields
  1118.                     dtFieldsHash = null;
  1119.                     allAccessibleFieldsKey = accessibleFieldsKey;
  1120.                     allAccessibleFields = new DTField[dtFieldsVector.size()];
  1121.                     dtFieldsVector.copyInto(allAccessibleFields);
  1122.                 }
  1123.  
  1124.                 cacheFlusher.scheduleCacheFlush(this);
  1125.                 return allAccessibleFields;
  1126.             }
  1127.         }
  1128.         return new DTField[0];
  1129.     }
  1130.  
  1131.         // Worker function to walk down the hierarchy getting the accessible fields
  1132.     private void getAccessibleFieldsImpl(AccessibleMemberFilter accessFilter, Hashtable dtFieldsHash, Vector dtFieldsVector) {
  1133.         DTField[] dtFields;
  1134.  
  1135.         //
  1136.         //    First, get the list of ALL accessible fields at this level
  1137.         //
  1138.  
  1139.         // See if the list of accessible fields is in our cache
  1140.         if (accessibleFields == null) {
  1141.             accessibleFields = new Hashtable();
  1142.             dtFields = null;
  1143.         } else {
  1144.             dtFields = (DTField[])accessibleFields.get(accessFilter.membersKey);
  1145.         }
  1146.  
  1147.         // Not in the cache.  Look 'em up.
  1148.         if (dtFields == null) {
  1149.             if (projectClass) {
  1150.                 dtFields = getAccessibleFields0(accessFilter.accessibleByClass.name, accessFilter.isSameObject);
  1151.             } else {
  1152.                 dtFields = getFields1(Member.DECLARED, (accessFilter.isSameClass ? null : accessFilter));
  1153.             }
  1154.  
  1155.             // Cache the fields we found (If we didn't find any, remember that too)
  1156.             if (dtFields == null)
  1157.                 dtFields = new DTField[0];
  1158.  
  1159.             accessibleFields.put(accessFilter.membersKey, dtFields);
  1160.         }
  1161.  
  1162.  
  1163.         //
  1164.         //    Next, filter out duplicates by only adding new fields to the Hashtable & Vector
  1165.         //
  1166.         for (int i = 0; i < dtFields.length; i++) {
  1167.             DTField dtField = dtFields[i];
  1168.             if (!dtFieldsHash.containsKey(dtField.name)) {
  1169.                 dtFieldsHash.put(dtField.name, dtField);
  1170.                 dtFieldsVector.addElement(dtField);
  1171.             }
  1172.         }
  1173.  
  1174.  
  1175.         //
  1176.         //    Now, get the superclass's accessible fields
  1177.         //
  1178.         DTClass superClass = this.getSuperclass();
  1179.         if (superClass != null) {
  1180.             accessFilter.adjustLevel(superClass);
  1181.             superClass.getAccessibleFieldsImpl(accessFilter, dtFieldsHash, dtFieldsVector);
  1182.         }
  1183.     }
  1184.  
  1185.     class AccessibleMemberFilter implements AccessFilter {
  1186.         String membersKey;
  1187.         DTClass accessibleByClass;
  1188.         String accessibleByPackage;
  1189.         boolean isSameObject;
  1190.         boolean isSameClass;
  1191.         boolean isSuperclass;
  1192.  
  1193.         boolean allowPackage;
  1194.         boolean allowProtected;
  1195.  
  1196.         AccessibleMemberFilter(String key, DTClass accessibleByClass, boolean isSameObject) {
  1197.             this.membersKey = key;
  1198.             this.accessibleByClass = accessibleByClass;
  1199.             this.accessibleByPackage = accessibleByClass.getPackageName();
  1200.  
  1201.             this.isSameObject = isSameObject;
  1202.             if (isSameObject)
  1203.                 isSameClass = DTClass.this.name.equals(accessibleByClass.name);
  1204.             this.isSuperclass = accessibleByClass.isSuperclass(DTClass.this); // this DTClass is a superclass of accessibleByClass;
  1205.  
  1206.             // package and protected members can be accessed by any class in the same package
  1207.             // protected members can be inherited, but not accessed by subclasses (must be the same object)
  1208.             if (DTClass.this.getPackageName().equals(accessibleByPackage)) {
  1209.                 this.allowPackage = true;
  1210.                 this.allowProtected = true;
  1211.             }
  1212.             else if (isSameObject && isSuperclass) {
  1213.                 this.allowProtected = true;
  1214.             }
  1215.         }
  1216.  
  1217.         void adjustLevel(DTClass dtClass) {
  1218.             this.isSameClass = false;
  1219.             this.isSuperclass = this.isSuperclass && accessibleByClass.isSuperclass(dtClass); // dtClass is a superclass of accessibleByClass
  1220.  
  1221.             // package and protected members can be accessed by any class in the same package
  1222.             // protected members can be inherited, but not accessed by subclasses (must be the same object)
  1223.             if (dtClass.getPackageName().equals(accessibleByPackage)) {
  1224.                 this.allowPackage = true;
  1225.                 this.allowProtected = true;
  1226.             }
  1227.             else if (isSameObject && isSuperclass) {
  1228.                 this.allowPackage = false;
  1229.                 this.allowProtected = true;
  1230.             }
  1231.             else {
  1232.                 this.allowPackage = false;
  1233.                 this.allowProtected = false;
  1234.             }
  1235.         }
  1236.  
  1237.         public boolean filterAccess(int modifiers) {
  1238.             if (Modifier.isPublic(modifiers))        // Public are always visible
  1239.                 return false;
  1240.  
  1241.             if (Modifier.isProtected(modifiers))    // Don't filter protected if allowing protected
  1242.                 return !allowProtected;
  1243.  
  1244.             if (Modifier.isPrivate(modifiers))        // If filtering, always filter private
  1245.                 return true;
  1246.  
  1247.             // Must be package
  1248.             return !allowPackage;                    // Package are visible from same package
  1249.         }
  1250.     }
  1251.  
  1252.  
  1253.     /**
  1254.      * gets the text range from the beginning of the "class" statement to the closing brace
  1255.      */
  1256.     public Range getSourceRange() {
  1257.         if (primitive || isArray()) return null;
  1258.         return getRange0(SOURCE_RANGE);
  1259.     }
  1260.  
  1261.     /**
  1262.      * gets the text range from the beginning of the first line of the class' Javadoc comment
  1263.      * to the closing asterisk-slash characters
  1264.      */
  1265.     public Range getJavadocRange() {
  1266.         if (primitive || isArray()) return null;
  1267.         return getRange0(JAVADOC_RANGE);
  1268.     }
  1269.  
  1270.     /**
  1271.      * gets the text range from the beginning of the member declaration to the semicolon
  1272.      */
  1273.     Range getSourceRange(DTField field) {
  1274.         if (primitive || isArray()) return null;
  1275.         return getFieldRange0(field.getName(), SOURCE_RANGE);
  1276.     }
  1277.  
  1278.     /**
  1279.      * gets the text range from the beginning of the first line of the field's Javadoc comment
  1280.      * to the closing asterisk-slash characters
  1281.      */
  1282.     Range getJavadocRange(DTField field) {
  1283.         if (primitive || isArray()) return null;
  1284.         return getFieldRange0(field.getName(), JAVADOC_RANGE);
  1285.     }
  1286.  
  1287.     /**
  1288.      * gets the text range from the beginning of the method declaration to the closing brace
  1289.      * (or semicolon for native or abstract members)
  1290.      */
  1291.     Range getSourceRange(DTMethod method) {
  1292.         if (primitive || isArray()) return null;
  1293.         return getMethodRange0(method.getName(), ((method.parameters == null) ? null : method.getParameterTypeNames()), SOURCE_RANGE);
  1294.     }
  1295.  
  1296.     /**
  1297.      * gets the text range from the beginning of the first line of the method's Javadoc comment
  1298.      * to the closing asterisk-slash characters
  1299.      */
  1300.     Range getJavadocRange(DTMethod method) {
  1301.         if (primitive || isArray()) return null;
  1302.         return getMethodRange0(method.getName(), ((method.parameters == null) ? null : method.getParameterTypeNames()), JAVADOC_RANGE);
  1303.     }
  1304.  
  1305.     /**
  1306.      * gets the text range from the beginning of the member declaration to the closing brace
  1307.      */
  1308.     Range getSourceRange(DTConstructor constructor) {
  1309.         if (primitive || isArray()) return null;
  1310.         return getConstructorRange0(((constructor.parameters == null) ? null : constructor.getParameterTypeNames()), SOURCE_RANGE);
  1311.     }
  1312.  
  1313.     /**
  1314.      * Gets the text range from the beginning of the first line of the member's Javadoc comment
  1315.      * to the closing asterisk-slash characters
  1316.      */
  1317.     Range getJavadocRange(DTConstructor constructor) {
  1318.         if (primitive || isArray()) return null;
  1319.         return getConstructorRange0(((constructor.parameters == null) ? null : constructor.getParameterTypeNames()), JAVADOC_RANGE);
  1320.     }
  1321.  
  1322.     /**
  1323.      * Renames a type to new name
  1324.      * param newName: The new name of the class
  1325.      * @return Success (true) or failure (false)...
  1326.      */
  1327.     public boolean rename(String newName) {
  1328.         if (primitive || isArray()) return false;
  1329.         return renameClass0(newName);
  1330.     }
  1331.  
  1332.     /**
  1333.      * Renames a field to new name
  1334.      * @param field: the field we need to rename
  1335.      * @param newName: The new name of the field
  1336.      * @return Success (true) or failure (false)...
  1337.      */
  1338.     boolean rename(DTField field, String newName) {
  1339.         if (primitive || isArray()) return false;
  1340.         return renameField0(field.getName(), newName);
  1341.     }
  1342.  
  1343.     /**
  1344.      * Renames a method to new name
  1345.      * @param method: the method we need to rename
  1346.      * @param newName: The new name of the field
  1347.      * @return: Success (true) or failure (false)...
  1348.      */
  1349.     boolean rename(DTMethod method, String newName) {
  1350.         if (primitive || isArray()) return false;
  1351.         return renameMethod0(method.getName(), ((method.parameters == null) ? null : method.getParameterTypeNames()), newName);
  1352.     }
  1353.  
  1354.     /**
  1355.      * Gets the closest member to the location.  The closest member is the member with a
  1356.      * source range or Javadoc range that surrounds the location
  1357.      */
  1358.     public DTMember getClosestMember(int location) {
  1359.         if (primitive || isArray()) return null;
  1360.         return getClosestMember0(location);
  1361.     }
  1362.  
  1363.     /**
  1364.      * Return true if the argument is a byte, short, int or long.
  1365.      */
  1366.     public boolean isInteger() {
  1367.         return this == LongType || this == IntegerType || this == ShortType || this == ByteType;
  1368.     }
  1369.  
  1370.     /**
  1371.      * Return true if the argument is a number, i.e.,
  1372.      * byte, short, int, long, float or double.
  1373.      */
  1374.     public boolean isNumeric() {
  1375.         return isInteger() || this == FloatType || this == DoubleType;
  1376.     }
  1377.  
  1378.     /**
  1379.      * Return a    DTClass    object for the named primitive type.
  1380.      * @return    null if    name is    not    a primitive    type
  1381.      */
  1382.     public static DTClass getPrimitiveClass(String name) {
  1383.         if (primHash ==    null) {
  1384.             primHash = new Hashtable();
  1385.             primHash.put("boolean",    new    DTClass("boolean"));
  1386.             primHash.put("char", new DTClass("char"));
  1387.             primHash.put("byte", new DTClass("byte"));
  1388.             primHash.put("short", new DTClass("short"));
  1389.             primHash.put("int",    new    DTClass("int"));
  1390.             primHash.put("long", new DTClass("long"));
  1391.             primHash.put("float", new DTClass("float"));
  1392.             primHash.put("double", new DTClass("double"));
  1393.             primHash.put("void", new DTClass("void"));
  1394.             primHash.put("*", new DTClass("*"));
  1395.             primHash.put("null", new DTClass("null"));
  1396.         }
  1397.         return (DTClass) primHash.get(name);
  1398.     }
  1399.  
  1400.     /**
  1401.      * Return the VisualProject that defines the class, or null for a system class.
  1402.      */
  1403.     public VisualProject getProject() {
  1404.         return project;
  1405.     }
  1406.  
  1407.     /**
  1408.      * Return the ID of the ProjectFile that defines the class, or 0 for a system class.
  1409.      */
  1410.     public int getProjectFileID() {
  1411.         if (projectFileID == -1) {    // Unknown?
  1412.             if (primitive || isArray() || project == null) {
  1413.                 projectFileID = 0;
  1414.             } else {
  1415.                 projectFileID = getProjectFileID0();
  1416.             }
  1417.         }
  1418.         return projectFileID;
  1419.     }
  1420.  
  1421.     /**
  1422.      * Return the ProjectFile that defines the class, or null for a system class.
  1423.      */
  1424.     public ProjectFile getProjectFile() {
  1425.         // Make sure projectFileID is setup
  1426.         if (this.getProjectFileID() == 0) return null;
  1427.         return project.getProjectFile(projectFileID);
  1428.     }
  1429.  
  1430.     /**
  1431.      * Return the SourceFile that contains the class, or null if not found.
  1432.      */
  1433.     public SourceFile getSourceFile() {
  1434.         if (primitive || isArray()) return null;
  1435.         return getSourceFile0();
  1436.     }
  1437.  
  1438.  
  1439.     /**
  1440.      * Validate    that the class still exists    and    the    information    about
  1441.      * the class is    correct. Sets the valid    flag to    the    result of
  1442.      * validate().
  1443.      *
  1444.      * @return true    if the DTClass object is valid,    false otherwise.
  1445.      */
  1446.     public boolean validate() {
  1447.         if (primitive) return true;
  1448.         if (!projectClass) {
  1449.             try    {
  1450.                 Class clazz    = loadClass();
  1451.                 return getModifiers() == clazz.getModifiers();
  1452.             } catch    (Exception e) {
  1453.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  1454.                     System.out.println("    DTClass: " + name + ".validate() threw " + e);
  1455.                     e.printStackTrace();
  1456.                 }
  1457.             }
  1458.             return valid = false;
  1459.         }
  1460.         return valid = validate0();
  1461.     }
  1462.  
  1463.     /**
  1464.      * Return value    of last    validate().
  1465.      */
  1466.     public boolean isValid() {
  1467.         return valid;
  1468.     }
  1469.  
  1470.     /**
  1471.      * Return true if the other    class is the same as this.
  1472.      * <p> If classes are equal    and    both are valid,
  1473.      * all of the information about    the    class is the same.
  1474.      *
  1475.      * @param    other    class to be    compared.
  1476.      */
  1477.     public boolean equals(Object obj) {
  1478.         if (this ==    obj) return true;
  1479.         if (obj instanceof DTClass) {
  1480.             DTClass other = (DTClass) obj;
  1481.             return this.equals(other);
  1482.         }
  1483.         return false;
  1484.     }
  1485.  
  1486.     /**
  1487.      * Return true if the other    class is the same as this.
  1488.      * <p> If classes are equal    and    both are valid,
  1489.      * all of the information about    the    class is the same.
  1490.      *
  1491.      * @param    other    class to be    compared.
  1492.      */
  1493.     public boolean equals(DTClass other) {
  1494.         if (this ==    other) return true;
  1495.         return (other != null) && name.equals(other.name);
  1496.     }
  1497.  
  1498.     /**
  1499.      * nonNull does    nothing    except throw a NullPointerException    if
  1500.      * called with null    DTClass    reference
  1501.      *
  1502.      * @return    reference to calling object
  1503.      */
  1504.     public final DTClass nonNull() { return    this; }
  1505.  
  1506.     /**
  1507.      * nonNull does    nothing    except throw a NullPointerException    if
  1508.      * called with null    reference
  1509.      *
  1510.      * @return    reference to calling object
  1511.      */
  1512.     public final Object nonNull(Object obj) {
  1513.         if (obj == null) throw new NullPointerException("nonNull() check failed");
  1514.         return    obj;
  1515.     }
  1516.  
  1517.     /**
  1518.      * nonNull does    nothing    except throw a NullPointerException    if
  1519.      * called with a null DTClass[]    reference or if    any    of its
  1520.      * components are null.
  1521.      *
  1522.      # @param    array    of DTClass references
  1523.      * @return    reference to array argument
  1524.      */
  1525.     public static final    DTClass[] nonNull(DTClass[]    array) {
  1526.         for    (int i = 0;    i <    array.length; i++)
  1527.             array[i].nonNull();
  1528.         return array;
  1529.     }
  1530.  
  1531.     private String            packageName;    // class's package
  1532.     private    String            name;            // class fully qualified name (includes packageName)
  1533.     private    int                modifier;        // standard    flags
  1534.     private    int                dim;            // number of dimensions
  1535.     private    boolean            primitive;        // true    if primitive class
  1536.     private    boolean            projectClass;    // true    if defined by project
  1537.  
  1538.     private    transient VisualProject    project;        // containing project
  1539.     private transient int            projectFileID;    // ID of file within its project
  1540.     private transient boolean        valid;            // set by validate()
  1541.     private transient Class            clazz;            // 'real' class for non-projectClasses
  1542.  
  1543.     private    static Hashtable            primHash;
  1544.     private static Hashtable            systemClassHash = new Hashtable();
  1545.  
  1546.     // Cached information
  1547.     private transient Hashtable            checkedSuperclasses = null;
  1548.     private transient boolean            gotSuperClass = false;    // Need to differentiate gotSuperClass from superClass != null
  1549.     private transient DTClass            superClass = null;        //    because java.lang.Object's superClass IS null.
  1550.  
  1551.     // Cached information that is periodically purged to free memory
  1552.     private transient DTField[]            publicFields = null;
  1553.     private transient DTField[]            declaredFields = null;
  1554.     private transient Hashtable            accessibleMethods = null;        // Hash of accessible DECLARED method arrays
  1555.     private transient DTMethod[]        allAccessibleMethods = null;    // Cache of last found list of accessible methods (includes superclasses)
  1556.     private transient String            allAccessibleMethodsKey = null;
  1557.     private transient Hashtable            accessibleFields = null;        // Hash of accessible DECLARED field arrays
  1558.     private transient DTField[]            allAccessibleFields = null;        // Cache of last found list of accessible fields (includes superclasses)
  1559.     private transient String            allAccessibleFieldsKey = null;
  1560.  
  1561.     public static int                    cacheFlushDelay = 180000;        // 3 minutes
  1562.     private static CacheFlusher            cacheFlusher = new CacheFlusher();
  1563.  
  1564.     static class CacheFlusher implements java.awt.event.ActionListener {
  1565.         com.sun.java.swing.Timer cacheFlushTimer;
  1566.         Hashtable scheduledFlushes = new Hashtable();
  1567.  
  1568.         CacheFlusher() {
  1569.             cacheFlushTimer = new com.sun.java.swing.Timer(cacheFlushDelay, this);
  1570.             cacheFlushTimer.setRepeats(false);
  1571.         }
  1572.  
  1573.         /**
  1574.         * Invoked when the action occurs.
  1575.         */
  1576.         synchronized public void actionPerformed(java.awt.event.ActionEvent e) {
  1577.             Enumeration elements = scheduledFlushes.elements();
  1578.             while (elements.hasMoreElements()) {
  1579.                 DTClass dtClass = (DTClass) elements.nextElement();
  1580.                 dtClass.publicFields = null;
  1581.                 dtClass.declaredFields = null;
  1582.                 dtClass.accessibleMethods = null;
  1583.                 dtClass.allAccessibleMethods = null;
  1584.                 dtClass.allAccessibleMethodsKey = null;
  1585.                 dtClass.accessibleFields = null;
  1586.                 dtClass.allAccessibleFields = null;
  1587.                 dtClass.allAccessibleFieldsKey = null;
  1588.             }
  1589.             scheduledFlushes.clear();
  1590.         }
  1591.  
  1592.         synchronized void scheduleCacheFlush(DTClass dtClass) {
  1593.             if (!scheduledFlushes.containsKey(dtClass))
  1594.                 scheduledFlushes.put(dtClass, dtClass);
  1595.             cacheFlushTimer.setInitialDelay(cacheFlushDelay);
  1596.             cacheFlushTimer.restart();
  1597.         }
  1598.     }
  1599.  
  1600.     // native methods
  1601.     private    static native boolean isProjectClass0(VisualProject    project, String    name);
  1602.     private    native DTClass[] getInterfaces0();
  1603.     private    native DTClass getSuperclass0();
  1604.     private native DTClass getDeclaringClass0();
  1605.     private native Vector getClasses0(int which);
  1606.     private    native boolean isSuperClass0(DTClass superClass);
  1607.     private    native boolean validate0();
  1608.     private native DTField[] getFields0(int kind);
  1609.     private native DTMethod[] getMethods0(int kind);
  1610.     private native DTConstructor[] getConstructors0(int kind);
  1611.     private native DTField getField0(String name, int kind);
  1612.     private native DTMethod getMethod0(String name, String[] parameterTypes, int kind);
  1613.     private native DTConstructor getConstructor0(String[] parameterTypes, int kind);
  1614.  
  1615.     private native DTField[] getAccessibleFields0(String accessibleByClassName, boolean sameObject);
  1616.     private native DTMethod[] getAccessibleMethods0(String accessibleByClassName, boolean sameObject);
  1617.  
  1618.     private native int getProjectFileID0();
  1619.     private native SourceFile getSourceFile0();
  1620.     private native DTMember getClosestMember0(int location);
  1621.  
  1622.     static final int SOURCE_RANGE = 0;
  1623.     static final int JAVADOC_RANGE = 1;
  1624.     private native Range getRange0(int rangeKind);
  1625.     private native Range getFieldRange0(String name, int rangeKind);
  1626.     private native Range getMethodRange0(String name, String[] parameterTypeNames, int rangeKind);
  1627.     private native Range getConstructorRange0(String[] parameterTypeNames, int rangeKind);
  1628.  
  1629.     private native boolean renameClass0(String newName);
  1630.     private native boolean renameField0(String sOldName, String newName);
  1631.     private native boolean renameMethod0(String name, String[] parameterTypeNames, String newName);
  1632.  
  1633.     private static boolean isProjectClass(VisualProject project, String name) {
  1634.         if (project    == null) return    false;
  1635.         return isProjectClass0(project,name);
  1636.     }
  1637.  
  1638.     private static String classesToString(Class[] classes) {
  1639.         StringBuffer buf = new StringBuffer();
  1640.         int    i, n = classes.length;
  1641.         for    (i = 0;    i <    n; i++)    {
  1642.             if (i >    0) buf.append(',');
  1643.             buf.append(classToString(classes[i]));
  1644.         }
  1645.         return buf.toString();
  1646.     }
  1647.  
  1648.     private static String classToString(Class clazz) {
  1649.         return classnameToString(clazz.getName());
  1650.     }
  1651.     protected static String classnameToString(String name) {
  1652.         int    n =    name.length();
  1653.         if (n == 0)    return "";
  1654.         if (name.charAt(0) != '[')
  1655.             return name;
  1656.         // array classes are signature-encoded
  1657.         StringBuffer buf = new StringBuffer();
  1658.         int    i, dim = 0;
  1659.         Vector bounds =    new    Vector();
  1660.         dimloop: for (i    = 0; i < n && name.charAt(i) ==    '['; i++) {
  1661.             dim++;
  1662.             int    bound =    0;
  1663.             char c;
  1664.             while (i+1 < n && (c = name.charAt(i+1)) >=    '0'    && c <=    '9') {
  1665.                 bound =    bound*10 + (int)c -    (int)'0';
  1666.                 i++;
  1667.             }
  1668.             bounds.addElement(new Integer(bound));
  1669.         }
  1670.         if (i >= n)    throw new NullPointerException();
  1671.         char code =    name.charAt(i);
  1672.         switch (code) {
  1673.             case 'B':
  1674.                 buf.append("byte");
  1675.                 break;
  1676.             case 'C':
  1677.                 buf.append("char");
  1678.                 break;
  1679.             case 'D':
  1680.                 buf.append("double");
  1681.                 break;
  1682.             case 'F':
  1683.                 buf.append("float");
  1684.                 break;
  1685.             case 'I':
  1686.                 buf.append("int");
  1687.                 break;
  1688.             case 'J':
  1689.                 buf.append("long");
  1690.                 break;
  1691.             case 'S':
  1692.                 buf.append("short");
  1693.                 break;
  1694.             case 'V':
  1695.                 buf.append("void");
  1696.                 break;
  1697.             case 'Z':
  1698.                 buf.append("boolean");
  1699.                 break;
  1700.             case 'L':
  1701.                 buf.append(name.substring(i+1,n-1));
  1702.                 break;
  1703.             default:
  1704.                 buf.append(name.substring(i));
  1705.         }
  1706.         for    (i = 0;    i <    dim; i++) {
  1707.             buf.append("[");
  1708.             Integer    bound =    (Integer) bounds.elementAt(i);
  1709.             if (bound.intValue() > 0)
  1710.                 buf.append(bound.toString());
  1711.             buf.append("]");
  1712.         }
  1713.         return buf.toString();
  1714.     }
  1715.  
  1716.     private    DTClass[] classToDTClassArray(Class[] classes) {
  1717.         int    i, n = classes.length;
  1718.         DTClass[] array    = new DTClass[n];
  1719.         for    (i = 0;    i <    n; i++)
  1720.             array[i] = classToDTClass(classes[i]);
  1721.         return array;
  1722.     }
  1723.  
  1724.     private DTClass classToDTClass(Class clazz) {
  1725.         String dtname =    classToString(clazz);
  1726.         DTClass dtClass = new DTClass(project, dtname, clazz, scanDim(dtname), clazz.isPrimitive(),
  1727.                                                 isProjectClass(project,componentName(dtname)));
  1728.         return DTClass.registerClass(dtClass, false /*!replace*/);
  1729.     }
  1730.  
  1731.  
  1732.     private    static Class[] dtclassToClassArray(DTClass[] dtclasses) throws ClassNotFoundException {
  1733.         int    i, n = dtclasses.length;
  1734.         Class[]    classes    = new Class[n];
  1735.         for    (i = 0;    i <    n; i++)    {
  1736.             DTClass    dtclass    = dtclasses[i];
  1737.             if (dtclass.primitive) {
  1738.                 Class clazz    = null;
  1739.                 if (dtclass    == DTClass.BooleanType)
  1740.                     clazz =    Boolean.TYPE;
  1741.                 else if    (dtclass ==    DTClass.CharacterType)
  1742.                     clazz =    Character.TYPE;
  1743.                 else if    (dtclass ==    DTClass.ByteType)
  1744.                     clazz =    Byte.TYPE;
  1745.                 else if    (dtclass ==    DTClass.ShortType)
  1746.                     clazz =    Short.TYPE;
  1747.                 else if    (dtclass ==    DTClass.IntegerType)
  1748.                     clazz =    Integer.TYPE;
  1749.                 else if    (dtclass ==    DTClass.LongType)
  1750.                     clazz =    Long.TYPE;
  1751.                 else if    (dtclass ==    DTClass.FloatType)
  1752.                     clazz =    Float.TYPE;
  1753.                 else if    (dtclass ==    DTClass.DoubleType)
  1754.                     clazz =    Double.TYPE;
  1755.                 else if    (dtclass ==    DTClass.VoidType)
  1756.                     clazz =    Void.TYPE;
  1757.                 classes[i] = clazz;
  1758.             } else
  1759.                 classes[i] = dtclass.loadClass();
  1760.         }
  1761.         return classes;
  1762.     }
  1763.  
  1764.     private    Class[] stringToClassArray(String[] classNames) throws ClassNotFoundException {
  1765.         int    i, n = classNames.length;
  1766.         Class[]    classes    = new Class[n];
  1767.         for    (i = 0;    i <    n; i++)    {
  1768.             String className = classNames[i];
  1769.             DTClass primitive = getPrimitiveClass(className);
  1770.             if (primitive != null) {
  1771.                 Class clazz    = null;
  1772.                 if (primitive == DTClass.BooleanType)
  1773.                     clazz =    Boolean.TYPE;
  1774.                 else if    (primitive == DTClass.CharacterType)
  1775.                     clazz =    Character.TYPE;
  1776.                 else if    (primitive == DTClass.ByteType)
  1777.                     clazz =    Byte.TYPE;
  1778.                 else if    (primitive == DTClass.ShortType)
  1779.                     clazz =    Short.TYPE;
  1780.                 else if    (primitive == DTClass.IntegerType)
  1781.                     clazz =    Integer.TYPE;
  1782.                 else if    (primitive == DTClass.LongType)
  1783.                     clazz =    Long.TYPE;
  1784.                 else if    (primitive == DTClass.FloatType)
  1785.                     clazz =    Float.TYPE;
  1786.                 else if    (primitive == DTClass.DoubleType)
  1787.                     clazz =    Double.TYPE;
  1788.                 else if    (primitive == DTClass.VoidType)
  1789.                     clazz =    Void.TYPE;
  1790.                 classes[i] = clazz;
  1791.             } else {
  1792.                 classes[i] = loadClass(className);
  1793.             }
  1794.         }
  1795.         return classes;
  1796.     }
  1797.  
  1798.     private    DTField[] getFields(int which)    {
  1799.         if (!(primitive    || isArray())) {
  1800.             if (projectClass) {
  1801.                    DTField[] dtFields = getFields0(which);
  1802.  
  1803.                 //
  1804.                 // If we may have gotten inherited fields, need to fixup the member classes
  1805.                 //    to refer to DTClasses in our cache.
  1806.                 //
  1807.                 if (which == Member.PUBLIC) {
  1808.                     Hashtable memberDTClassHash = null;
  1809.                     for (int i = 0; i < dtFields.length; i++) {
  1810.                         DTField dtField = dtFields[i];
  1811.                         if (dtField.clazz != this) {
  1812.                             DTClass memberDTClass;
  1813.                             if (memberDTClassHash == null) {
  1814.                                 memberDTClassHash = new Hashtable();
  1815.                                 memberDTClass = null;
  1816.                             } else {
  1817.                                 memberDTClass = (DTClass) memberDTClassHash.get(dtField.clazz);
  1818.                             }
  1819.                             if (memberDTClass == null) {
  1820.                                 memberDTClass = DTClass.registerClass(dtField.clazz, false /*!replace*/);
  1821.                                 memberDTClassHash.put(memberDTClass, memberDTClass);
  1822.                             }
  1823.                             if (dtField.clazz != memberDTClass)
  1824.                                 dtField.clazz = memberDTClass;
  1825.                         }
  1826.                     }
  1827.                 }
  1828.  
  1829.                 return dtFields;
  1830.             }
  1831.             else {
  1832.                 return getFields1(which, null);
  1833.             }
  1834.         }
  1835.         return new DTField[0];
  1836.     }
  1837.  
  1838.  
  1839.     interface AccessFilter {
  1840.         /** return true if a member with this access level should not be included */
  1841.         public boolean filterAccess(int accessModifiers);
  1842.     }
  1843.  
  1844.     private DTField[] getFields1(int which, AccessFilter accessFilter) {
  1845.         try    {
  1846.             Class clazz    = loadClass();
  1847.             Field[] fields = which == Member.PUBLIC ? clazz.getFields() : clazz.getDeclaredFields();
  1848.             int    n = fields.length;
  1849.  
  1850.             DTField[] dtfields = null;
  1851.             Vector vdtfields = null;
  1852.             Hashtable memberDTClassHash = null;
  1853.  
  1854.             if (accessFilter == null)
  1855.                 dtfields = new DTField[n];
  1856.             else
  1857.                 vdtfields = new Vector(n, 0);    // Start with the size of the array, no incrementing will be necessary
  1858.  
  1859.             for    (int i = 0;    i <    n; i++)    {
  1860.                 Field field = fields[i];
  1861.                 int fieldModifiers = field.getModifiers();
  1862.  
  1863.                 if (accessFilter != null && accessFilter.filterAccess(fieldModifiers))
  1864.                     continue;
  1865.  
  1866.                 // Determine in which class this field is declared
  1867.                 DTClass memberDTClass = null;
  1868.                 if (which == Member.DECLARED) {
  1869.                     memberDTClass = this;                    // Obviously must be declared in this class
  1870.                 } else {
  1871.                     Class memberClazz = field.getDeclaringClass();
  1872.                     if (memberClazz.equals(clazz)) {        // Declared in this class
  1873.                         memberDTClass = this;
  1874.                     } else {                                // Search the hash of known classes
  1875.                         if (memberDTClassHash == null)
  1876.                             memberDTClassHash = new Hashtable();
  1877.                         else
  1878.                             memberDTClass = (DTClass) memberDTClassHash.get(memberClazz);
  1879.                         if (memberDTClass == null) {
  1880.                             memberDTClass = new DTClass(project, memberClazz);
  1881.                             memberDTClass = DTClass.registerClass(memberDTClass, false /*!replace*/);
  1882.                             memberDTClassHash.put(memberClazz, memberDTClass);
  1883.                         }
  1884.                     }
  1885.                 }
  1886.  
  1887.                 DTField dtfield = new DTField(memberDTClass,
  1888.                                                 field.getName(),
  1889.                                                 fieldModifiers,
  1890.                                                 classToString(field.getType()));
  1891.                 if (accessFilter == null)
  1892.                     dtfields[i] = dtfield;
  1893.                 else
  1894.                     vdtfields.addElement(dtfield);
  1895.             }
  1896.             if (accessFilter != null) {
  1897.                 dtfields = new DTField[vdtfields.size()];
  1898.                 vdtfields.copyInto(dtfields);
  1899.             }
  1900.             return dtfields;
  1901.         } catch    (Exception e) {
  1902.             if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  1903.                 System.out.println("    DTClass: " + name + ".getFields() threw " + e);
  1904.                 e.printStackTrace();
  1905.             }
  1906.         }
  1907.         return new DTField[0];
  1908.     }
  1909.  
  1910.  
  1911.     private    DTMethod[] getMethods(int which) {
  1912.         if (!(primitive    || isArray())) {
  1913.             if (projectClass) {
  1914.                 DTMethod[] dtMethods = getMethods0(which);
  1915.  
  1916.                 //
  1917.                 // If we may have gotten inherited methods, need to fixup the member classes
  1918.                 //    to refer to DTClasses in our cache.
  1919.                 //
  1920.                 if (which == Member.PUBLIC) {
  1921.                     Hashtable memberDTClassHash = null;
  1922.                     for (int i = 0; i < dtMethods.length; i++) {
  1923.                         DTMethod dtMethod = dtMethods[i];
  1924.                         if (dtMethod.clazz != this) {
  1925.                             DTClass memberDTClass;
  1926.                             if (memberDTClassHash == null) {
  1927.                                 memberDTClassHash = new Hashtable();
  1928.                                 memberDTClass = null;
  1929.                             } else {
  1930.                                 memberDTClass = (DTClass) memberDTClassHash.get(dtMethod.clazz);
  1931.                             }
  1932.                             if (memberDTClass == null) {
  1933.                                 memberDTClass = DTClass.registerClass(dtMethod.clazz, false /*!replace*/);
  1934.                                 memberDTClassHash.put(memberDTClass, memberDTClass);
  1935.                             }
  1936.                             if (dtMethod.clazz != memberDTClass)
  1937.                                 dtMethod.clazz = memberDTClass;
  1938.                         }
  1939.                     }
  1940.                 }
  1941.  
  1942.                 return dtMethods;
  1943.             }
  1944.             else {
  1945.                 return getMethods1(which, null);
  1946.             }
  1947.         }
  1948.         return new DTMethod[0];
  1949.     }
  1950.  
  1951.  
  1952.     private DTMethod[] getMethods1(int which, AccessFilter accessFilter) {
  1953.         try    {
  1954.             Class clazz    = loadClass();
  1955.             Method[] methods = which == Member.PUBLIC ? clazz.getMethods() : clazz.getDeclaredMethods();
  1956.             int    n = methods.length;
  1957.  
  1958.             DTMethod[] dtmethods = null;
  1959.             Vector vdtmethods = null;
  1960.             Hashtable memberDTClassHash = null;
  1961.  
  1962.             if (accessFilter == null)
  1963.                 dtmethods = new DTMethod[n];
  1964.             else
  1965.                 vdtmethods = new Vector(n, 0);    // Start with the size of the array, no incrementing will be necessary
  1966.  
  1967.             for    (int i = 0;    i <    n; i++)    {
  1968.                 Method method =    methods[i];
  1969.                 int methodModifiers = method.getModifiers();
  1970.  
  1971.                 if (accessFilter != null && accessFilter.filterAccess(methodModifiers))
  1972.                     continue;
  1973.  
  1974.                 // Determine in which class this method is declared
  1975.                 DTClass memberDTClass = null;
  1976.                 if (which == Member.DECLARED) {
  1977.                     memberDTClass = this;                    // Obviously must be declared in this class
  1978.                 } else {
  1979.                     Class memberClazz = method.getDeclaringClass();
  1980.                     if (memberClazz.equals(clazz)) {        // Declared in this class
  1981.                         memberDTClass = this;
  1982.                     } else {                                // Search the hash of known classes
  1983.                         if (memberDTClassHash == null)
  1984.                             memberDTClassHash = new Hashtable();
  1985.                         else
  1986.                             memberDTClass = (DTClass) memberDTClassHash.get(memberClazz);
  1987.                         if (memberDTClass == null) {
  1988.                             memberDTClass = new DTClass(project, memberClazz);
  1989.                             memberDTClass = DTClass.registerClass(memberDTClass, false /*!replace*/);
  1990.                             memberDTClassHash.put(memberClazz, memberDTClass);
  1991.                         }
  1992.                     }
  1993.                 }
  1994.  
  1995.                 DTMethod dtmethod = new DTMethod(memberDTClass,
  1996.                                                 method.getName(),
  1997.                                                 methodModifiers,
  1998.                                                 classToString(method.getReturnType()),
  1999.                                                 classesToString(method.getParameterTypes()),
  2000.                                                 "",
  2001.                                                 classesToString(method.getExceptionTypes()));
  2002.                 if (accessFilter == null)
  2003.                     dtmethods[i] = dtmethod;
  2004.                 else
  2005.                     vdtmethods.addElement(dtmethod);
  2006.             }
  2007.             if (accessFilter != null) {
  2008.                 dtmethods = new DTMethod[vdtmethods.size()];
  2009.                 vdtmethods.copyInto(dtmethods);
  2010.             }
  2011.             return dtmethods;
  2012.         } catch    (Exception e) {
  2013.             if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  2014.                 System.out.println("    DTClass: " + name + ".getMethods() threw " + e);
  2015.                 e.printStackTrace();
  2016.             }
  2017.         }
  2018.         return new DTMethod[0];
  2019.     }
  2020.  
  2021.  
  2022.     private    DTConstructor[]    getConstructors(int which)    {
  2023.         if (!(primitive    || isArray())) {
  2024.             if (projectClass) {
  2025.                    return getConstructors0(which);
  2026.             }
  2027.             try    {
  2028.                 Class clazz    = loadClass();
  2029.                 Constructor[] constructors = which == Member.PUBLIC    ? clazz.getConstructors() :    clazz.getDeclaredConstructors();
  2030.                 int    n = constructors.length;
  2031.  
  2032.                 DTConstructor[]    dtconstructors = new DTConstructor[n];
  2033.                 Hashtable memberDTClassHash = null;
  2034.  
  2035.                 for    (int i = 0; i < n; i++) {
  2036.                     Constructor    constructor    = constructors[i];
  2037.  
  2038.                     // Determine in which class this constructor is declared
  2039.                     DTClass memberDTClass = null;
  2040.                     if (which == Member.DECLARED) {
  2041.                         memberDTClass = this;                    // Obviously must be declared in this class
  2042.                     } else {
  2043.                         Class memberClazz = constructor.getDeclaringClass();
  2044.                         if (memberClazz.equals(clazz)) {        // Declared in this class
  2045.                             memberDTClass = this;
  2046.                         } else {                                // Search the hash of known classes
  2047.                             if (memberDTClassHash == null)
  2048.                                 memberDTClassHash = new Hashtable();
  2049.                             else
  2050.                                 memberDTClass = (DTClass) memberDTClassHash.get(memberClazz);
  2051.                             if (memberDTClass == null) {
  2052.                                 memberDTClass = new DTClass(project, memberClazz);
  2053.                                 memberDTClass = DTClass.registerClass(memberDTClass, false /*!replace*/);
  2054.                                 memberDTClassHash.put(memberClazz, memberDTClass);
  2055.                             }
  2056.                         }
  2057.                     }
  2058.  
  2059.                     dtconstructors[i] =    new    DTConstructor(memberDTClass,
  2060.                                                             constructor.getName(),
  2061.                                                             constructor.getModifiers(),
  2062.                                                             classesToString(constructor.getParameterTypes()),
  2063.                                                             "",
  2064.                                                             classesToString(constructor.getExceptionTypes()));
  2065.                 }
  2066.                 return dtconstructors;
  2067.             } catch    (Exception e) {
  2068.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  2069.                     System.out.println("    DTClass: " + name + ".getConstructors() threw " + e);
  2070.                     e.printStackTrace();
  2071.                 }
  2072.             }
  2073.         }
  2074.         return new DTConstructor[0];
  2075.     }
  2076.  
  2077.     private DTClass[] getClasses(int which) {
  2078.         if (!(primitive    || isArray())) {
  2079.             if (projectClass) {
  2080.                 Vector v = getClasses0(which);
  2081.  
  2082.                 if (v == null) return new DTClass[0];
  2083.                 DTClass[] dtclasses = new DTClass[v.size()];
  2084.                 v.copyInto(dtclasses);
  2085.                 for (int i = 0; i < dtclasses.length; i++) {
  2086.                     dtclasses[i] = DTClass.registerProjectClass(dtclasses[i], false /*!replace*/);
  2087.                 }
  2088.                 return dtclasses;
  2089.             }
  2090.             try    {
  2091.                 Class clazz    = loadClass();
  2092.                 Class[] classes = which == Member.PUBLIC ? clazz.getClasses() : clazz.getDeclaredClasses();
  2093.                 return classToDTClassArray(classes);
  2094.             } catch    (Exception e) {
  2095.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  2096.                     System.out.println("    DTClass: " + name + ".getClasses() threw " + e);
  2097.                     e.printStackTrace();
  2098.                 }
  2099.             }
  2100.         }
  2101.         return new DTClass[0];
  2102.     }
  2103.  
  2104.     private    DTField    getField(String fieldName, int which) {
  2105.         if (!(primitive    || isArray())) {
  2106.             if (projectClass) {
  2107.                    return getField0(fieldName, which);
  2108.             }
  2109.             try    {
  2110.                 Class clazz    = loadClass();
  2111.                 Field field    = which    == Member.PUBLIC ? clazz.getField(fieldName) : clazz.getDeclaredField(fieldName);
  2112.  
  2113.                 // Determine in which class this field is declared
  2114.                 DTClass memberDTClass = null;
  2115.                 if (which == Member.DECLARED) {
  2116.                     memberDTClass = this;                    // Obviously must be declared in this class
  2117.                 } else {
  2118.                     Class memberClazz = field.getDeclaringClass();
  2119.                     if (memberClazz.equals(clazz)) {        // Declared in this class
  2120.                         memberDTClass = this;
  2121.                     } else {                                // (Maybe) Make a new DTClass for the member's Class
  2122.                         memberDTClass = new DTClass(project, memberClazz);
  2123.                         memberDTClass = DTClass.registerClass(memberDTClass, false /*!replace*/);
  2124.                     }
  2125.                 }
  2126.  
  2127.                 return new DTField(memberDTClass,
  2128.                                     field.getName(),
  2129.                                     field.getModifiers(),
  2130.                                     classToString(field.getType()));
  2131.             } catch    (Exception e) {
  2132.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  2133.                     System.out.println("    DTClass: " + name + ".getField(" + fieldName + ") threw " + e);
  2134.                     e.printStackTrace();
  2135.                 }
  2136.             }
  2137.         }
  2138.         return null;
  2139.     }
  2140.  
  2141.     private    DTMethod getMethod(String methodName, DTClass[] parameterTypes, int which) {
  2142.         if (!(primitive    || isArray())) {
  2143.             if (projectClass) {
  2144.                 // Convert parameterTypes into names
  2145.                 String[] parameterTypeNames;
  2146.                 if (parameterTypes == null) {
  2147.                     parameterTypeNames = null;
  2148.                 } else {
  2149.                     parameterTypeNames = new String[parameterTypes.length];
  2150.                     for (int i = 0; i < parameterTypes.length; i++)
  2151.                         parameterTypeNames[i] = parameterTypes[i].name;
  2152.                 }
  2153.                    return getMethod0(methodName, parameterTypeNames, which);
  2154.             }
  2155.             try    {
  2156.                 Class clazz    = loadClass();
  2157.                 Class[]    types =    dtclassToClassArray(parameterTypes);
  2158.                 Method method =    which == Member.PUBLIC ? clazz.getMethod(methodName,types) : clazz.getDeclaredMethod(methodName,types);
  2159.  
  2160.                 // Determine in which class this method is declared
  2161.                 DTClass memberDTClass = null;
  2162.                 if (which == Member.DECLARED) {
  2163.                     memberDTClass = this;                    // Obviously must be declared in this class
  2164.                 } else {
  2165.                     Class memberClazz = method.getDeclaringClass();
  2166.                     if (memberClazz.equals(clazz)) {        // Declared in this class
  2167.                         memberDTClass = this;
  2168.                     } else {                                // (Maybe) Make a new DTClass for the member's Class
  2169.                         memberDTClass = new DTClass(project, memberClazz);
  2170.                         memberDTClass = DTClass.registerClass(memberDTClass, false /*!replace*/);
  2171.                     }
  2172.                 }
  2173.  
  2174.                 return new DTMethod(memberDTClass,
  2175.                                     method.getName(),
  2176.                                     method.getModifiers(),
  2177.                                     classToString(method.getReturnType()),
  2178.                                     classesToString(method.getParameterTypes()),
  2179.                                     "",
  2180.                                     classesToString(method.getExceptionTypes()));
  2181.             } catch    (Exception e) {
  2182.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  2183.                     System.out.println("    DTClass: " + name + ".getMethod(" + methodName + ") threw " + e);
  2184.                     e.printStackTrace();
  2185.                 }
  2186.             }
  2187.         }
  2188.         return null;
  2189.     }
  2190.  
  2191.     private    DTMethod getMethod(String methodName, String[] parameterTypeNames, int which) {
  2192.         if (!(primitive    || isArray())) {
  2193.             if (projectClass) {
  2194.                    return getMethod0(methodName, parameterTypeNames, which);
  2195.             }
  2196.             try    {
  2197.                 Class clazz    = loadClass();
  2198.                 Class[]    types =    stringToClassArray(parameterTypeNames);
  2199.                 Method method =    which == Member.PUBLIC ? clazz.getMethod(methodName,types) : clazz.getDeclaredMethod(methodName,types);
  2200.  
  2201.                 // Determine in which class this method is declared
  2202.                 DTClass memberDTClass = null;
  2203.                 if (which == Member.DECLARED) {
  2204.                     memberDTClass = this;                    // Obviously must be declared in this class
  2205.                 } else {
  2206.                     Class memberClazz = method.getDeclaringClass();
  2207.                     if (memberClazz.equals(clazz)) {        // Declared in this class
  2208.                         memberDTClass = this;
  2209.                     } else {                                // (Maybe) Make a new DTClass for the member's Class
  2210.                         memberDTClass = new DTClass(project, memberClazz);
  2211.                         memberDTClass = DTClass.registerClass(memberDTClass, false /*!replace*/);
  2212.                     }
  2213.                 }
  2214.  
  2215.                 return new DTMethod(memberDTClass,
  2216.                                     method.getName(),
  2217.                                     method.getModifiers(),
  2218.                                     classToString(method.getReturnType()),
  2219.                                     classesToString(method.getParameterTypes()),
  2220.                                     "",
  2221.                                     classesToString(method.getExceptionTypes()));
  2222.             } catch    (Exception e) {
  2223.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  2224.                     System.out.println("    DTClass: " + name + ".getMethod(" + methodName + ") threw " + e);
  2225.                     e.printStackTrace();
  2226.                 }
  2227.             }
  2228.         }
  2229.         return null;
  2230.     }
  2231.  
  2232.     private    DTConstructor getConstructor(DTClass[] parameterTypes, int    which) {
  2233.         if (!(primitive    || isArray())) {
  2234.             if (projectClass) {
  2235.                 // Convert parameterTypes into names
  2236.                 String[] parameterTypeNames;
  2237.                 if (parameterTypes == null) {
  2238.                     parameterTypeNames = null;
  2239.                 } else {
  2240.                     parameterTypeNames = new String[parameterTypes.length];
  2241.                     for (int i = 0; i < parameterTypes.length; i++)
  2242.                         parameterTypeNames[i] = parameterTypes[i].name;
  2243.                 }
  2244.                 return getConstructor0(parameterTypeNames, which);
  2245.             }
  2246.             try    {
  2247.                 Class clazz    = loadClass();
  2248.                 Class[]    types =    dtclassToClassArray(parameterTypes);
  2249.                 Constructor    constructor    = which    == Member.PUBLIC ? clazz.getConstructor(types) : clazz.getDeclaredConstructor(types);
  2250.  
  2251.                 // Determine in which class this constructor is declared
  2252.                 DTClass memberDTClass = null;
  2253.                 if (which == Member.DECLARED) {
  2254.                     memberDTClass = this;                    // Obviously must be declared in this class
  2255.                 } else {
  2256.                     Class memberClazz = constructor.getDeclaringClass();
  2257.                     if (memberClazz.equals(clazz)) {        // Declared in this class
  2258.                         memberDTClass = this;
  2259.                     } else {                                // (Maybe) Make a new DTClass for the member's Class
  2260.                         memberDTClass = new DTClass(project, memberClazz);
  2261.                         memberDTClass = DTClass.registerClass(memberDTClass, false /*!replace*/);
  2262.                     }
  2263.                 }
  2264.  
  2265.                 return new DTConstructor(memberDTClass,
  2266.                                         constructor.getName(),
  2267.                                         constructor.getModifiers(),
  2268.                                         classesToString(constructor.getParameterTypes()),
  2269.                                         "",
  2270.                                         classesToString(constructor.getExceptionTypes()));
  2271.             } catch    (Exception e) {
  2272.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  2273.                     System.out.println("    DTClass: " + name + ".getConstructor() threw " + e);
  2274.                     e.printStackTrace();
  2275.                 }
  2276.             }
  2277.         }
  2278.         return null;
  2279.     }
  2280.  
  2281.  
  2282.     private    DTConstructor getConstructor(String[] parameterTypeNames, int which) {
  2283.         if (!(primitive    || isArray())) {
  2284.             if (projectClass) {
  2285.                 return getConstructor0(parameterTypeNames, which);
  2286.             }
  2287.             try    {
  2288.                 Class clazz    = loadClass();
  2289.                 Class[]    types =    stringToClassArray(parameterTypeNames);
  2290.                 Constructor    constructor    = which    == Member.PUBLIC ? clazz.getConstructor(types) : clazz.getDeclaredConstructor(types);
  2291.  
  2292.                 // Determine in which class this constructor is declared
  2293.                 DTClass memberDTClass = null;
  2294.                 if (which == Member.DECLARED) {
  2295.                     memberDTClass = this;                    // Obviously must be declared in this class
  2296.                 } else {
  2297.                     Class memberClazz = constructor.getDeclaringClass();
  2298.                     if (memberClazz.equals(clazz)) {        // Declared in this class
  2299.                         memberDTClass = this;
  2300.                     } else {                                // (Maybe) Make a new DTClass for the member's Class
  2301.                         memberDTClass = new DTClass(project, memberClazz);
  2302.                         memberDTClass = DTClass.registerClass(memberDTClass, false /*!replace*/);
  2303.                     }
  2304.                 }
  2305.  
  2306.                 return new DTConstructor(memberDTClass,
  2307.                                         constructor.getName(),
  2308.                                         constructor.getModifiers(),
  2309.                                         classesToString(constructor.getParameterTypes()),
  2310.                                         "",
  2311.                                         classesToString(constructor.getExceptionTypes()));
  2312.             } catch    (Exception e) {
  2313.                 if (DEBUG_DTCLASS_JAVA_LANG_CLASS_EXCEPTIONS) {
  2314.                     System.out.println("    DTClass: " + name + ".getConstructor() threw " + e);
  2315.                     e.printStackTrace();
  2316.                 }
  2317.             }
  2318.         }
  2319.         return null;
  2320.     }
  2321.  
  2322.     /**
  2323.      * Derive a java class name, given a name in our internal format.
  2324.      * for example, this turns "java.lang.Object[]",1 into "[Ljava.lang.Object;"
  2325.      */
  2326.     protected static String getClassname(String name, int dim) {
  2327.         if (dim == 0) return name;
  2328.  
  2329.         StringBuffer classnameBuffer = new StringBuffer();
  2330.         for (int i = 0; i < dim; i++) {
  2331.             classnameBuffer.append("[");
  2332.         }
  2333.         classnameBuffer.append("L");
  2334.         classnameBuffer.append(componentName(name));
  2335.         
  2336.         return classnameBuffer.append(";").toString();
  2337.     }
  2338.     
  2339.     private String getClassname() {
  2340.         if (dim > 0)
  2341.             return getClassname(name, dim);
  2342.         else
  2343.             return name;
  2344.     }
  2345.  
  2346.  
  2347.     /**
  2348.      * Gets the Class object for this DTClass.  If this DTClass refers to an array, the
  2349.      * array Class is returned (rather than the array's component class).
  2350.      * for example, for "java.lang.Object[]", the Class for "[Ljava.lang.Object;" is returned.
  2351.      */
  2352.     private    Class loadClass() throws ClassNotFoundException    {
  2353.         if (clazz != null) return clazz;
  2354.  
  2355.         String classname = getClassname();
  2356.         if (project    != null) {
  2357.             ClassLoader    loader = getProjectLoader();
  2358.             clazz = loader.loadClass(classname);
  2359.         } else {
  2360.             clazz = Class.forName(classname);
  2361.         }
  2362.         return clazz;
  2363.     }
  2364.  
  2365.     /**
  2366.      * Gets the Class object for this DTClass.  If this DTClass refers to an array, the
  2367.      * array's component Class is returned.
  2368.      * for example, for "java.lang.Object[]", the Class for "java.lang.Object" is returned.
  2369.      */
  2370.     private Class loadComponentClass() throws ClassNotFoundException {
  2371.         if (project    != null) {
  2372.             ClassLoader    loader = getProjectLoader();
  2373.             return loader.loadClass(getComponentName());
  2374.         } else {
  2375.             return Class.forName(getComponentName());
  2376.         }
  2377.     }
  2378.  
  2379.     /**
  2380.      * Gets the Class object for the className.  If className refers to an array, the 
  2381.      * array Class is returned (rather than the array's component class).
  2382.      */
  2383.     private Class loadClass(String className) throws ClassNotFoundException {
  2384.         String classname = DTClass.getClassname(className, scanDim(className));
  2385.         if (project    != null) {
  2386.             ClassLoader    loader = getProjectLoader();
  2387.             return loader.loadClass(classname);
  2388.         } else {
  2389.             return Class.forName(classname);
  2390.         }
  2391.     }
  2392.  
  2393. /*
  2394.     private    Class loadClass() throws ClassNotFoundException    {
  2395.         if (clazz != null) return clazz;
  2396.  
  2397.         // ??? use component name until    clear how array    names encoded
  2398.         // may need    two    methods    then, as some depend on    this behavior
  2399.         if (project    != null) {
  2400.             ClassLoader    loader = getProjectLoader();
  2401.             clazz = loader.loadClass(getComponentName());
  2402.         } else {
  2403.             clazz = Class.forName(getComponentName());
  2404.         }
  2405.         return clazz;
  2406.     }
  2407.  
  2408.     private Class loadClass(String className) throws ClassNotFoundException {
  2409.         // ??? use component name until    clear how array    names encoded
  2410.         // may need    two    methods    then, as some depend on    this behavior
  2411.         if (project    != null) {
  2412.             ClassLoader    loader = getProjectLoader();
  2413.             return loader.loadClass(className);
  2414.         } else {
  2415.             return Class.forName(className);
  2416.         }
  2417.     }
  2418. */
  2419.  
  2420.  
  2421.     /**
  2422.      * Constructor used locally for primitive types (boolean, char, etc).
  2423.      */
  2424.     private    DTClass(String primitiveName) {
  2425.         this.project = null;
  2426.         this.projectFileID = 0;
  2427.         this.name =    primitiveName;
  2428.         this.packageName = null;
  2429.         this.modifier =    Modifier.PUBLIC|Modifier.FINAL;
  2430.         this.dim = 0;
  2431.         this.primitive = true;
  2432.         this.projectClass =    false;
  2433.     }
  2434.  
  2435.     /**
  2436.      * Constructor used locally for primitive array types (boolean[], char[], etc).
  2437.      */
  2438.     protected DTClass(DTClass primitiveType, int dim) {
  2439.         if (!primitiveType.primitive || primitiveType.dim > 0 || primitiveType.packageName != null)
  2440.             throw new IllegalArgumentException();
  2441.  
  2442.         this.project = null;
  2443.         this.projectFileID = 0;
  2444.         this.name = primitiveType.name;
  2445.         this.packageName = null;
  2446.         this.modifier = primitiveType.modifier;
  2447.         this.dim = dim;
  2448.         this.primitive = true;
  2449.         this.projectClass = false;
  2450.         for (int i = 0; i < dim; i++) {
  2451.             name += "[]";
  2452.         }
  2453.     }
  2454.  
  2455.     /**
  2456.      * Constructor used    locally to make a DTClass from a system java.lang.Class
  2457.      */
  2458.     private    DTClass(VisualProject project, Class clazz) {
  2459.         this.project = project;
  2460.         this.projectFileID = -1;    // unknown
  2461.         this.name =    clazz.getName();
  2462.         int lastDot = name.lastIndexOf('.');
  2463.         if (lastDot == -1)
  2464.             this.packageName = "";
  2465.         else
  2466.             this.packageName = name.substring(0, lastDot-1);
  2467.         this.modifier =    clazz.getModifiers();
  2468.         this.dim = 0;
  2469.         this.primitive = false;
  2470.         this.projectClass =    false;
  2471.         this.clazz = clazz;
  2472.         // a class may have    a project but not be a project class;
  2473.         // the project is used to obtain the project loader
  2474.     }
  2475.  
  2476.     /**
  2477.      * Constructor used    locally to make a DTClass, usually from a system java.lang.Class
  2478.      */
  2479.     protected DTClass(VisualProject project, String name, Class clazz, int dim, boolean primitive, boolean projectClass) {
  2480.         this.project = project;
  2481.         this.projectFileID = -1;    // unknown
  2482.         int lastDot = name.lastIndexOf('.');
  2483.         if (lastDot == -1)
  2484.             this.packageName = "";
  2485.         else
  2486.             this.packageName = name.substring(0, lastDot-1);
  2487.         this.name =    name;
  2488.         this.modifier =    clazz.getModifiers();
  2489.         this.dim = dim;
  2490.         this.primitive = primitive;
  2491.         this.projectClass =    projectClass;
  2492.         this.clazz = clazz;
  2493.         // a class may have    a project but not be a project class;
  2494.         // the project is used to obtain the project loader
  2495.     }
  2496.  
  2497.     /**
  2498.      * Constructor used by native methods.
  2499.      */
  2500.     private DTClass(VisualProject project, int projectFileID, String name, String packageName, int modifier, int dim, boolean projectClass) {
  2501.         this.project = project;
  2502.         this.projectFileID = projectFileID;
  2503.         this.packageName = packageName;
  2504.         this.name = name;
  2505.         this.modifier = modifier;
  2506.         this.dim = dim;
  2507.         this.primitive = false;
  2508.         this.projectClass = projectClass;
  2509.         // a class may have a project but not be a project class;
  2510.         // the project is used to obtain the project loader
  2511.     }
  2512.  
  2513.     protected DTClass() {    }
  2514.  
  2515.     /**
  2516.      * Override.
  2517.      */
  2518.     private void readObject(java.io.ObjectInputStream in)
  2519.     throws IOException, ClassNotFoundException {    // no good can come from suppressing exceptions here
  2520.         in.defaultReadObject();
  2521.         boolean hadProject = in.readBoolean();
  2522.         this.projectFileID = -1;    // unknown
  2523.         if (hadProject)
  2524.             project = ((VisualProject.ProjectInputStream)in).getProject();
  2525.         validate();
  2526.  
  2527.         if (valid)
  2528.             DTClass.registerClass(this, true /*replace*/);
  2529.     }
  2530.  
  2531.     /**
  2532.      * Override.
  2533.      */
  2534.     private void writeObject(java.io.ObjectOutputStream out)
  2535.     throws IOException, ClassNotFoundException {
  2536.  
  2537.         out.defaultWriteObject();
  2538.         out.writeBoolean(project != null);
  2539.     }
  2540. }
  2541.