Source Code Cross Referenced for FuncSig.java in  » Scripting » jacl » tcl » lang » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » jacl » tcl.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * FuncSig.java --
0003:         *
0004:         *	This class implements the internal representation of a Java
0005:         *	method or constructor signature.
0006:         *
0007:         * Copyright (c) 1997 Sun Microsystems, Inc.
0008:         *
0009:         * See the file "license.terms" for information on usage and
0010:         * redistribution of this file, and for a DISCLAIMER OF ALL
0011:         * WARRANTIES.
0012:         *
0013:         * RCS: @(#) $Id: FuncSig.java,v 1.15 2006/05/15 22:14:23 mdejong Exp $
0014:         *
0015:         */
0016:
0017:        package tcl.lang;
0018:
0019:        import tcl.lang.reflect.*;
0020:        import java.lang.reflect.*;
0021:        import java.util.*;
0022:
0023:        /**
0024:         * This class implements the internal representation of a Java method
0025:         * or constructor signature. Because methods and constructors are very
0026:         * similar to each other, the operations on method signatures and
0027:         * constructor signatures are limped in this class of "function
0028:         * signature."
0029:         */
0030:
0031:        class FuncSig implements  InternalRep {
0032:
0033:            // The class that a method signature is used against. In the case of a
0034:            // static method call by java::call, targetCls is given by the <class>
0035:            // argument to java::call. In the case of an instance method call,
0036:            // targetCls is the class of the instance. targetCls is used to test
0037:            // the validity of a cached FuncSig internal rep for method
0038:            // signatures.
0039:            //
0040:            // targetCls is not used for class signatures.
0041:
0042:            Class targetCls;
0043:
0044:            // The PkgInvoker used to access the constructor or method.
0045:
0046:            PkgInvoker pkgInvoker;
0047:
0048:            // The constructor or method given by the field signature. You need to
0049:            // apply the instanceof operator to determine whether it's a
0050:            // Constructor or a Method.
0051:            //
0052:            // func may be a public, protected, package protected or private
0053:            // member of the given class. Attempts to access func is subject to
0054:            // the Java language access control rules. Public members can always
0055:            // be accessed. Protected and package protected members can be
0056:            // accessed only if a proper TclPkgInvoker class exists. Private
0057:            // members can never be accessed.
0058:            //
0059:            // If the signature is a method signature and the specified method has
0060:            // been overloaded, then func will point to the "most public" instance
0061:            // of that method. The order of public-ness is ranked as the following
0062:            // (a larger number means more public):
0063:            //
0064:            // RANK		     METHOD ACCESS TYPE      CLASS ACCESS TYPE	
0065:            //   0			private			any
0066:            //   1			package protected	protected
0067:            //   1			protected		protected
0068:            //   1			public			protected
0069:            //   1			package protected	public
0070:            //   1			protected		public
0071:            //   2			public			public
0072:
0073:            Object func;
0074:
0075:            // Stores all accessible instance methods for a Java class
0076:            // Note that we use a Hashtable instead of a HashMap here
0077:            // since these fields could be accessed from multiple
0078:            // threads and the Hashtable class is synchronized.
0079:
0080:            static Hashtable instanceMethodTable = new Hashtable();
0081:            static Hashtable staticMethodTable = new Hashtable();
0082:
0083:            /*
0084:             *----------------------------------------------------------------------
0085:             *
0086:             * FuncSig --
0087:             *
0088:             *	Creates a new FuncSig instance.
0089:             *
0090:             * Side effects:
0091:             *	Member fields are initialized.
0092:             *
0093:             *----------------------------------------------------------------------
0094:             */
0095:
0096:            FuncSig(Class cls, // Initial value for targetCls.
0097:                    PkgInvoker p, // Initial value for pkgInvoker.
0098:                    Object f) // Initial value for func.
0099:            {
0100:                targetCls = cls;
0101:                pkgInvoker = p;
0102:                func = f;
0103:            }
0104:
0105:            /*
0106:             *----------------------------------------------------------------------
0107:             *
0108:             * duplicate --
0109:             *
0110:             *	Make a copy of an object's internal representation.
0111:             *
0112:             * Results:
0113:             *	Returns a newly allocated instance of the appropriate type.
0114:             *
0115:             * Side effects:
0116:             *	None.
0117:             *
0118:             *----------------------------------------------------------------------
0119:             */
0120:
0121:            public InternalRep duplicate() {
0122:                return new FuncSig(targetCls, pkgInvoker, func);
0123:            }
0124:
0125:            /**
0126:             * Implement this no-op for the InternalRep interface.
0127:             */
0128:
0129:            public void dispose() {
0130:            }
0131:
0132:            /*
0133:             *----------------------------------------------------------------------
0134:             *
0135:             * get --
0136:             *
0137:             *	Returns the FuncSig internal representation of the constructor
0138:             *	or method that matches with the signature and the parameters.
0139:             *
0140:             * Results:
0141:             *	The FuncSig given by the signature. An exception will be
0142:             *	raised if the constructor provided is for an abstract
0143:             *	class, or if the class is not accessible.
0144:             *
0145:             * Side effects:
0146:             *	None.
0147:             *
0148:             *----------------------------------------------------------------------
0149:             */
0150:
0151:            static FuncSig get(Interp interp, // Current interpreter.	
0152:                    Class cls, // If null, we are looking for a constructor
0153:                    // in signature. If non-null, we are looking
0154:                    // for a method of this class in signature.
0155:                    TclObject signature, // Method/constructor signature.
0156:                    TclObject[] argv, // Arguments.
0157:                    int startIdx, // Index of the first argument in argv
0158:                    int count, // Number of arguments to pass to the
0159:                    // constructor.
0160:                    boolean isStatic) // True if signature is for a static Method.
0161:                    throws TclException {
0162:                boolean isConstructor = (cls == null);
0163:
0164:                /* FIXME: commented out Method caching system
0165:                 * we comment out this code because it causes
0166:                 * the AmbiguousSignature-2.1 test to fail under Tcl Blend.
0167:                 * a new caching system might help but it is unclear if
0168:                 * determining a cache "match" is any less work then just searching.
0169:
0170:
0171:                InternalRep rep = signature.getInternalRep();
0172:
0173:                // If a valid FuncSig internal rep is already cached, return it
0174:                // right away.
0175:
0176:                if (rep instanceof FuncSig) {
0177:                FuncSig tmp = (FuncSig)rep;
0178:                Object func = tmp.func;
0179:
0180:                if (isConstructor) {
0181:                    if ((func instanceof Constructor)
0182:                	    && (((Constructor)func).getParameterTypes().length
0183:                		    == count)) {
0184:                	return tmp;
0185:                    }
0186:                } else {
0187:                    if ((func instanceof Method) && (tmp.targetCls == cls)
0188:                	    && (((Method)func).getParameterTypes().length == count)) {
0189:                	return tmp;
0190:                    }
0191:                }
0192:                }
0193:                 */
0194:
0195:                // Look up the constructor or method using the string rep of the
0196:                // signature object.
0197:                Object match;
0198:                int sigLength = TclList.getLength(interp, signature);
0199:                String methodName = null;
0200:                TclObject class_or_method;
0201:
0202:                if (sigLength == 0) {
0203:                    throw new TclException(interp, "bad signature \""
0204:                            + signature + "\"");
0205:                } else if (sigLength == 1) {
0206:                    class_or_method = signature;
0207:                } else {
0208:                    class_or_method = TclList.index(interp, signature, 0);
0209:                }
0210:
0211:                if (isConstructor) {
0212:                    cls = JavaInvoke.getClassByName(interp, class_or_method
0213:                            .toString());
0214:                } else {
0215:                    methodName = class_or_method.toString();
0216:                }
0217:
0218:                if ((isConstructor || isStatic)
0219:                        && !PkgInvoker.isAccessible(cls)) {
0220:                    JavaInvoke.notAccessibleError(interp, cls);
0221:                }
0222:
0223:                if (isConstructor && Modifier.isAbstract(cls.getModifiers())) {
0224:                    throw new TclException(interp, "Class \""
0225:                            + JavaInfoCmd.getNameFromClass(cls)
0226:                            + "\" is abstract");
0227:                }
0228:
0229:                if ((sigLength > 1) || (sigLength == 1 && count == 0)) {
0230:                    // We come to here if one of the following two cases in true:
0231:                    //
0232:                    //     [1] (sigLength > 1): A signature has been given.
0233:                    //     [2] (sigLength == 1 && count == 0): A signature of no
0234:                    //         parameters is implied.
0235:                    //
0236:                    // In both cases, we search for a method that matches exactly
0237:                    // with the signature.
0238:
0239:                    int sigNumArgs = sigLength - 1;
0240:                    Class[] paramTypes = new Class[sigNumArgs];
0241:
0242:                    for (int i = 0; i < sigNumArgs; i++) {
0243:                        String clsName = TclList
0244:                                .index(interp, signature, i + 1).toString();
0245:                        paramTypes[i] = JavaInvoke.getClassByName(interp,
0246:                                clsName);
0247:                    }
0248:
0249:                    if (isConstructor) {
0250:                        try {
0251:                            match = getAccessibleConstructor(cls, paramTypes);
0252:                        } catch (NoSuchMethodException e) {
0253:                            if (sigLength > 1) {
0254:                                throw new TclException(interp,
0255:                                        "no accessible constructor \""
0256:                                                + signature + "\"");
0257:                            } else {
0258:                                throw new TclException(interp,
0259:                                        "can't find accessible constructor with "
0260:                                                + count
0261:                                                + " argument(s) for class \""
0262:                                                + JavaInfoCmd
0263:                                                        .getNameFromClass(cls)
0264:                                                + "\"");
0265:                            }
0266:                        }
0267:                    } else {
0268:                        match = lookupMethod(interp, cls, methodName,
0269:                                paramTypes, signature, isStatic);
0270:                    }
0271:                } else {
0272:                    match = matchSignature(interp, cls, signature, methodName,
0273:                            isConstructor, argv, startIdx, count, isStatic);
0274:                }
0275:
0276:                FuncSig sig = new FuncSig(cls, PkgInvoker.getPkgInvoker(cls),
0277:                        match);
0278:                //signature.setInternalRep(sig);
0279:
0280:                return sig;
0281:            }
0282:
0283:            // lookupMethod attempts to find an exact match for the method name
0284:            // based on the types (Java Class objects) of the arguments to the
0285:            // method. If an exact match can not be found it will raise a TclException.
0286:
0287:            static Method lookupMethod(Interp interp, // the tcl interpreter
0288:                    Class cls, // the Java objects class
0289:                    String methodName, // name of method
0290:                    Class[] paramTypes, // the Class object arguments
0291:                    TclObject signature, // used for error reporting
0292:                    boolean isStatic // True if signature is for a static Method.
0293:            ) throws TclException {
0294:                Method[] methods;
0295:                boolean foundSameName = false;
0296:
0297:                if (isStatic)
0298:                    methods = getAccessibleStaticMethods(cls);
0299:                else
0300:                    methods = getAccessibleInstanceMethods(cls);
0301:
0302:                // FIXME : searching Java methods for method name match
0303:                // searching through ALL the methods is really slow
0304:                // there really should be a better way to do this
0305:                // as it needs to be done on every method invocation
0306:
0307:                for (int i = 0; i < methods.length; i++) {
0308:                    if (!methodName.equals(methods[i].getName())) {
0309:                        continue;
0310:                    }
0311:
0312:                    foundSameName = true;
0313:
0314:                    Class[] pt = methods[i].getParameterTypes();
0315:                    if (pt.length != paramTypes.length) {
0316:                        continue;
0317:                    }
0318:
0319:                    boolean good = true;
0320:                    for (int j = 0; j < pt.length; j++) {
0321:                        if (pt[j] != paramTypes[j]) {
0322:                            good = false;
0323:                            break;
0324:                        }
0325:                    }
0326:                    if (good) {
0327:                        return methods[i];
0328:                    }
0329:                }
0330:
0331:                if (paramTypes.length > 0 || !foundSameName) {
0332:                    throw new TclException(interp, "no accessible"
0333:                            + (isStatic ? " static " : " ") + "method \""
0334:                            + signature + "\" in class "
0335:                            + JavaInfoCmd.getNameFromClass(cls));
0336:                } else {
0337:                    throw new TclException(interp, "can't find accessible"
0338:                            + (isStatic ? " static " : " ") + "method \""
0339:                            + signature + "\" with " + paramTypes.length
0340:                            + " argument(s) for class \""
0341:                            + JavaInfoCmd.getNameFromClass(cls) + "\"");
0342:                }
0343:            }
0344:
0345:            // This method will attempt to find a match for a signature
0346:            // if an exact match can not be found then it will use
0347:            // the types of the argument objects to "guess" what
0348:            // method was intended by the user. If no match can be
0349:            // found after "guessing" then a TclException will be raised.
0350:
0351:            static Object matchSignature(Interp interp, // the tcl interpreter
0352:                    Class cls, // the Java objects class
0353:                    TclObject signature, // used for error reporting
0354:                    String methodName, // name of method, can be null
0355:                    boolean isConstructor, // duh
0356:                    TclObject[] argv, // arguments to Method or Constructor
0357:                    int startIdx, // Index of the first argument in argv    
0358:                    int argv_count, // set to -1 if JFK was killed by the FBI
0359:                    boolean isStatic // True if signature is for a static Method.
0360:            ) throws TclException {
0361:                Object[] funcs;
0362:                boolean foundSameName = false;
0363:                ArrayList match_list = new ArrayList();
0364:                int i, j;
0365:
0366:                final boolean debug = false;
0367:
0368:                if (isConstructor) {
0369:                    funcs = getAccessibleConstructors(cls);
0370:                } else {
0371:                    if (isStatic)
0372:                        funcs = getAccessibleStaticMethods(cls);
0373:                    else
0374:                        funcs = getAccessibleInstanceMethods(cls);
0375:                }
0376:
0377:                for (i = 0; i < funcs.length; i++) {
0378:                    Class[] paramTypes;
0379:                    if (isConstructor) {
0380:                        paramTypes = ((Constructor) funcs[i])
0381:                                .getParameterTypes();
0382:                    } else {
0383:                        Method method = (Method) funcs[i];
0384:                        if (!methodName.equals(method.getName())) {
0385:                            continue;
0386:                        }
0387:                        foundSameName = true;
0388:
0389:                        paramTypes = method.getParameterTypes();
0390:                    }
0391:
0392:                    if (paramTypes.length == argv_count) {
0393:                        match_list.add(funcs[i]);
0394:                    }
0395:                }
0396:
0397:                // If there is only a single remaining match then we can return it now
0398:
0399:                if (match_list.size() == 1) {
0400:                    // debug print the single match
0401:                    //System.out.println("single match : " + match_list.get(0));
0402:
0403:                    return match_list.get(0);
0404:                } else if (match_list.size() > 1) {
0405:
0406:                    Class[] argv_classes = new Class[argv_count];
0407:                    Class[] match_classes;
0408:
0409:                    // get the object types for the method arguments in argv
0410:                    for (i = 0; i < argv_count; i++) {
0411:                        TclObject tobj = argv[startIdx + i];
0412:
0413:                        boolean isJavaObj = true;
0414:                        Class c = null;
0415:                        try {
0416:                            c = ReflectObject.getClass(interp, tobj);
0417:                        } catch (TclException e) {
0418:                            isJavaObj = false;
0419:                        }
0420:
0421:                        if (isJavaObj) {
0422:                            argv_classes[i] = c;
0423:                        } else {
0424:                            argv_classes[i] = String.class;
0425:                        }
0426:                    }
0427:
0428:                    if (debug) {
0429:                        // debug print argv types
0430:
0431:                        System.out.println("multiple matches for method "
0432:                                + methodName);
0433:
0434:                        System.out.print("argv    is ");
0435:
0436:                        for (i = 0; i < argv_count; i++) {
0437:                            Class c = argv_classes[i];
0438:                            System.out.print(((c == null) ? "null"
0439:                                    : JavaInfoCmd.getNameFromClass(c)));
0440:                            System.out.print(" ");
0441:                        }
0442:                        System.out.println();
0443:
0444:                        // debug print possible match types
0445:
0446:                        for (i = 0; i < match_list.size(); i++) {
0447:
0448:                            if (isConstructor) {
0449:                                match_classes = ((Constructor) match_list
0450:                                        .get(i)).getParameterTypes();
0451:                            } else {
0452:                                match_classes = ((Method) match_list.get(i))
0453:                                        .getParameterTypes();
0454:                            }
0455:
0456:                            System.out.print("match " + i + " is ");
0457:
0458:                            for (j = 0; j < match_classes.length; j++) {
0459:                                Class c = match_classes[j];
0460:                                System.out.print(JavaInfoCmd
0461:                                        .getNameFromClass(c));
0462:                                System.out.print(" ");
0463:                            }
0464:
0465:                            System.out.println();
0466:                        }
0467:                    } // end if (debug)
0468:
0469:                    // try to match the argument types and the
0470:                    // match types exactly by comparing Class objects
0471:
0472:                    for (i = 0; i < match_list.size(); i++) {
0473:
0474:                        if (isConstructor) {
0475:                            match_classes = ((Constructor) match_list.get(i))
0476:                                    .getParameterTypes();
0477:                        } else {
0478:                            match_classes = ((Method) match_list.get(i))
0479:                                    .getParameterTypes();
0480:                        }
0481:
0482:                        boolean exact = true;
0483:                        for (j = 0; j < argv_count; j++) {
0484:                            if (match_classes[j] != argv_classes[j]) {
0485:                                exact = false;
0486:                                break;
0487:                            }
0488:                        }
0489:
0490:                        if (exact) {
0491:                            if (debug) {
0492:                                System.out.println("exact match at " + i);
0493:                            } // end if (debug)
0494:                            return match_list.get(i);
0495:                        }
0496:                    }
0497:
0498:                    // loop from the end of the list to the begining and
0499:                    // remove those signatures that are not assignable
0500:                    // take special care not to remove signatures that
0501:                    // have an object decended from java.lang.Object
0502:                    // in the same position as a null Class in argv_classes.
0503:                    // This means a null argument will not match a built in type.
0504:
0505:                    for (i = match_list.size() - 1; i >= 0; i--) {
0506:
0507:                        if (isConstructor) {
0508:                            match_classes = ((Constructor) match_list.get(i))
0509:                                    .getParameterTypes();
0510:                        } else {
0511:                            match_classes = ((Method) match_list.get(i))
0512:                                    .getParameterTypes();
0513:                        }
0514:
0515:                        // If any of the arguments are not assignable to the method arguments,
0516:                        // then remove this method from the list of matches.
0517:
0518:                        for (j = 0; j < argv_count; j++) {
0519:                            if (!JavaInvoke.isAssignable(match_classes[j],
0520:                                    argv_classes[j])) {
0521:
0522:                                if (debug) {
0523:                                    System.out
0524:                                            .println("removing non assignable match "
0525:                                                    + i);
0526:                                } // end if (debug)
0527:
0528:                                match_list.remove(i);
0529:                                break; // go on to next Method
0530:                            }
0531:                        }
0532:
0533:                    }
0534:
0535:                    if (debug) {
0536:                        // debug print match_list after isAssignabelFrom test
0537:
0538:                        if (match_list.size() > 0) {
0539:                            System.out.println("isAssignableFrom() matches");
0540:                        }
0541:
0542:                        for (i = 0; i < match_list.size(); i++) {
0543:
0544:                            if (isConstructor) {
0545:                                match_classes = ((Constructor) match_list
0546:                                        .get(i)).getParameterTypes();
0547:                            } else {
0548:                                match_classes = ((Method) match_list.get(i))
0549:                                        .getParameterTypes();
0550:                            }
0551:
0552:                            System.out.print("match " + i + " is ");
0553:
0554:                            for (j = 0; j < argv_count; j++) {
0555:                                Class c = match_classes[j];
0556:                                System.out.print(JavaInfoCmd
0557:                                        .getNameFromClass(c));
0558:                                System.out.print(" ");
0559:                            }
0560:
0561:                            System.out.println();
0562:                        }
0563:                    } // end if (debug)
0564:
0565:                    // If there is only a single remaining match then we can return it now
0566:
0567:                    if (match_list.size() == 1) {
0568:                        return match_list.get(0);
0569:                    }
0570:
0571:                    // at this point match_list should have only those signatures
0572:                    // that can take the argument types from argv with widining conversion
0573:
0574:                    // to figure out which method we should call we need to determine
0575:                    // which signatures are "better" then others where "better" is defined
0576:                    // as the shortest number of steps up the inheritance or interface tree
0577:
0578:                    if (match_list.size() > 1) {
0579:
0580:                        // the first thing we need to do is get the inheritance info
0581:                        // of the arguments to the method. From this we will create
0582:                        // an array of Class objects used to match against the possible
0583:                        // Method objects that we could invoke with this class name
0584:
0585:                        // as an example if we invoked a Method that took one
0586:                        // String argument then the argv_classes_lookup array would
0587:                        // end up as a 1 x 4 array with the java.lang.Class object
0588:                        // of the argument at [0,0] in the array. The inheritance
0589:                        // tree of the object would be represented by the [0,X]
0590:                        // members of the array (X depends on number of parents)
0591:                        // Class objects and Interface objects are stored and
0592:                        // null is used to keep track of the end of each Class
0593:
0594:                        // Example argument : {String}
0595:                        // Example array : {String,Serializable,null,Object}
0596:                        // Example info : String implements 1 interface = Serializable
0597:                        // Example info : String has 1 parent = Object
0598:
0599:                        Class[][] argv_classes_lookup = new Class[argv_count][];
0600:
0601:                        // we use a vector to store up all of the Class objects
0602:                        // that make up the inheritance tree for a particular class
0603:
0604:                        ArrayList class_list = new ArrayList();
0605:
0606:                        // for each argument to the method we loop up the inheritance tree
0607:                        // to find out if there is a superclass argv class that exactly matches
0608:
0609:                        for (i = 0; i < argv_count; i++) {
0610:                            Class c = argv_classes[i]; // Start with class type of argument
0611:
0612:                            if (c == null) {
0613:                                continue; // Skip lookup for argument when Class type is null
0614:                            }
0615:
0616:                            // loop over the first elements of the argv_classes_lookup to find out
0617:                            // if we have already looked up this class object and if we have just
0618:                            // use the array we found last time instead of doing the lookup again
0619:
0620:                            // Note that we would not need to do this if we cached the lookups
0621:
0622:                            for (j = 0; j < i; j++) {
0623:                                if (c == argv_classes_lookup[j][0]) {
0624:                                    if (debug) {
0625:                                        System.out
0626:                                                .println("using argv_classes_lookup shortcut");
0627:                                    } // end if (debug)
0628:                                    argv_classes_lookup[i] = argv_classes_lookup[j];
0629:                                    continue;
0630:                                }
0631:                            }
0632:
0633:                            // loop up the inheritance tree starting from c
0634:
0635:                            while (c != null) {
0636:                                // add a null to the front of the vector
0637:                                class_list.add(null);
0638:
0639:                                // add this Class and its Interfaces to the vector
0640:                                addInterfaces(c, class_list);
0641:
0642:                                c = c.getSuperclass();
0643:                            }
0644:
0645:                            // now remove the first element of the vector (it is null)
0646:                            class_list.remove(0);
0647:
0648:                            Class[] classes = new Class[class_list.size()];
0649:                            for (j = 0; j < classes.length; j++) {
0650:                                classes[j] = (Class) class_list.get(j);
0651:                            }
0652:
0653:                            argv_classes_lookup[i] = classes;
0654:
0655:                            class_list.clear();
0656:                        }
0657:
0658:                        if (debug) {
0659:                            // debug print the argv_classes_lookup array
0660:
0661:                            System.out.println("argv_classes_lookup array");
0662:
0663:                            for (i = 0; i < argv_count; i++) {
0664:
0665:                                Class[] classes = argv_classes_lookup[i];
0666:
0667:                                if (classes == null) {
0668:                                    System.out.println("{ null }");
0669:                                    continue;
0670:                                }
0671:
0672:                                System.out.print("{ ");
0673:
0674:                                for (j = 0; j < classes.length; j++) {
0675:
0676:                                    if (classes[j] == null) {
0677:                                        System.out.print("null");
0678:                                    } else {
0679:                                        System.out.print(JavaInfoCmd
0680:                                                .getNameFromClass(classes[j]));
0681:                                    }
0682:
0683:                                    System.out.print(' ');
0684:                                }
0685:
0686:                                System.out.println("}");
0687:
0688:                            }
0689:                        } // end if (debug)
0690:
0691:                        int[] super _steps = new int[match_list.size()];
0692:                        int[] total_steps = new int[match_list.size()];
0693:                        boolean[] trim_matches = new boolean[match_list.size()];
0694:                        int min_super _step;
0695:                        int min_total_step;
0696:                        Class min_class;
0697:
0698:                        // iterate over the arguments then the Methods
0699:                        // as opposed to Methods then over the arguments
0700:
0701:                        for (j = 0; j < argv_count; j++) {
0702:
0703:                            // we need to keep track of the smallest # of jumps up the
0704:                            // inheritance tree as well as the total min for the one
0705:                            // special case where an implemented interface inherits
0706:                            // from another interface that also matches the signature
0707:
0708:                            min_super _step = Integer.MAX_VALUE;
0709:                            min_total_step = Integer.MAX_VALUE;
0710:
0711:                            // define min_class as base object before we loop
0712:                            min_class = Object.class;
0713:
0714:                            // iterate over the matched methods to find the
0715:                            // minimum steps for this argument
0716:
0717:                            for (i = 0; i < match_list.size(); i++) {
0718:
0719:                                if (isConstructor) {
0720:                                    match_classes = ((Constructor) match_list
0721:                                            .get(i)).getParameterTypes();
0722:                                } else {
0723:                                    match_classes = ((Method) match_list.get(i))
0724:                                            .getParameterTypes();
0725:                                }
0726:
0727:                                Class match_to = match_classes[j];
0728:
0729:                                // Class objects we will compare the match_to Class against
0730:                                // the index (j) gives us the Class array for argv[j]
0731:                                Class[] arg_classes = argv_classes_lookup[j];
0732:
0733:                                // If the argument type is null then skip to the next
0734:                                // argument and max the steps so they do not get removed
0735:                                if (arg_classes == null) {
0736:                                    super _steps[i] = Integer.MAX_VALUE;
0737:                                    total_steps[i] = Integer.MAX_VALUE;
0738:                                    continue;
0739:                                }
0740:
0741:                                Class c;
0742:                                int super _step = 0;
0743:                                int total_step = 0;
0744:
0745:                                for (; total_step < arg_classes.length; total_step++) {
0746:                                    c = arg_classes[total_step];
0747:
0748:                                    if (c == null) {
0749:                                        super _step++; // null means we have gone up to the superclass
0750:                                    } else if (c == match_to) {
0751:                                        super _steps[i] = super _step; // # of super classes up
0752:                                        total_steps[i] = total_step; // total # of visible classes
0753:
0754:                                        // when we define the min for an argument we must make
0755:                                        // sure that three precidence rules are followed
0756:                                        // 1: an interface can replace another interface as the min
0757:                                        // 2: an interface can replace the class Object
0758:                                        // 3: a class can replace an interface or a class
0759:
0760:                                        // thus if we have already found a non Object min_class
0761:                                        // it can not be replaced by an interface
0762:
0763:                                        if (super _step <= min_super _step) {
0764:
0765:                                            if (!c.isInterface()
0766:                                                    || min_class == Object.class
0767:                                                    || min_class.isInterface()) {
0768:
0769:                                                if (debug) {
0770:                                                    //System.out.println("redefing min");
0771:                                                    //System.out.println("min_class was " + min_class);
0772:                                                    //System.out.println("min_class is now " + c);
0773:                                                } // end if (debug)
0774:
0775:                                                min_class = c;
0776:
0777:                                                min_super _step = super _step;
0778:
0779:                                                // check min_total_step only AFTER a min_super_step
0780:                                                // or equal to min_super_step has been found
0781:
0782:                                                if (total_step < min_total_step) {
0783:                                                    min_total_step = total_step;
0784:                                                }
0785:                                            }
0786:                                        }
0787:
0788:                                        break;
0789:                                    }
0790:                                }
0791:                            }
0792:
0793:                            if (debug) {
0794:                                // debug print the super_step array and the total_step array
0795:
0796:                                System.out.println("step arrays for argument "
0797:                                        + j);
0798:
0799:                                for (int loop = 0; loop < match_list.size(); loop++) {
0800:                                    System.out.println("(" + super _steps[loop]
0801:                                            + "," + total_steps[loop] + ")");
0802:                                }
0803:
0804:                                System.out.println("min_super_step = "
0805:                                        + min_super _step);
0806:                                System.out.println("min_total_step = "
0807:                                        + min_total_step);
0808:                            } // end if (debug)
0809:
0810:                            // from the step info we know the minumum so we can
0811:                            // remove those values that are "worse" then the min
0812:
0813:                            for (i = match_list.size() - 1; i >= 0; i--) {
0814:
0815:                                if (super _steps[i] > min_super _step
0816:                                        || (super _steps[i] == min_super _step && total_steps[i] > min_total_step)) {
0817:
0818:                                    if (debug) {
0819:                                        System.out.println("will trim method "
0820:                                                + i);
0821:                                    } // end if (debug)
0822:
0823:                                    trim_matches[i] = true; //trim this match # later
0824:                                }
0825:
0826:                            }
0827:
0828:                            // we should be able to short circut this so that we do
0829:                            // not waste loops when they are not needed
0830:
0831:                            // if all the methods have been trimmed then we do not
0832:                            // need to loop to the next argument
0833:
0834:                        }
0835:
0836:                        // remove the methods that were marked for deletion
0837:
0838:                        for (i = match_list.size() - 1; i >= 0; i--) {
0839:                            if (trim_matches[i]) {
0840:                                match_list.remove(i);
0841:                            }
0842:                        }
0843:
0844:                        if (debug) {
0845:                            // Debug print remaining matches
0846:
0847:                            System.out.println("after super steps trim");
0848:
0849:                            for (i = 0; i < match_list.size(); i++) {
0850:
0851:                                if (isConstructor) {
0852:                                    match_classes = ((Constructor) match_list
0853:                                            .get(i)).getParameterTypes();
0854:                                } else {
0855:                                    match_classes = ((Method) match_list.get(i))
0856:                                            .getParameterTypes();
0857:                                }
0858:
0859:                                System.out.print("match " + i + " is ");
0860:
0861:                                for (j = 0; j < argv_count; j++) {
0862:                                    Class c = match_classes[j];
0863:                                    System.out.print(JavaInfoCmd
0864:                                            .getNameFromClass(c));
0865:                                    System.out.print(" ");
0866:                                }
0867:
0868:                                System.out.println();
0869:                            }
0870:                        } // end if (debug)
0871:
0872:                    } // end if (match_list.size() > 1)
0873:
0874:                    // if there is only one item left in the match_list return it
0875:
0876:                    if (match_list.size() == 1) {
0877:                        return match_list.get(0);
0878:                    } else {
0879:                        // if we have 0 or >1 remaining matches then
0880:                        // we were unable to find the "best" match so raise an error
0881:                        // if possible, tell user what matches made the sig ambiguous.
0882:
0883:                        //System.out.println("match_list.size() is " + match_list.size());
0884:
0885:                        StringBuffer sb = new StringBuffer(100);
0886:                        sb.append("ambiguous ");
0887:                        if (isConstructor) {
0888:                            sb.append("constructor");
0889:                        } else {
0890:                            sb.append("method");
0891:                        }
0892:                        sb.append(" signature");
0893:
0894:                        if (match_list.size() == 0) {
0895:
0896:                            // FIXME : better error message for no signature matches case
0897:                            // We really should tell the user which methods we could have
0898:                            // matched but did not for one reason or another. The tricky
0899:                            // part is knowing what matches should be shown, perhaps all?
0900:
0901:                            //sb.append(" \"" + signature + "\"");
0902:                            sb.append(", could not choose between ");
0903:
0904:                            // Get all the signatures that match this name and number or args
0905:
0906:                            if (isConstructor) {
0907:                                funcs = getAccessibleConstructors(cls);
0908:                            } else {
0909:                                if (isStatic)
0910:                                    funcs = getAccessibleStaticMethods(cls);
0911:                                else
0912:                                    funcs = getAccessibleInstanceMethods(cls);
0913:                            }
0914:
0915:                            for (i = 0; i < funcs.length; i++) {
0916:                                Class[] paramTypes;
0917:                                if (isConstructor) {
0918:                                    paramTypes = ((Constructor) funcs[i])
0919:                                            .getParameterTypes();
0920:                                } else {
0921:                                    Method method = (Method) funcs[i];
0922:                                    if (!methodName.equals(method.getName())) {
0923:                                        continue;
0924:                                    }
0925:                                    foundSameName = true;
0926:
0927:                                    paramTypes = method.getParameterTypes();
0928:                                }
0929:
0930:                                if (paramTypes.length == argv_count) {
0931:                                    match_list.add(funcs[i]);
0932:                                }
0933:                            }
0934:
0935:                        } else {
0936:
0937:                            // iterate over remaining possible matches and add to error message
0938:
0939:                            sb.append(", assignable signatures are ");
0940:
0941:                        }
0942:
0943:                        TclObject siglist = TclList.newInstance();
0944:                        siglist.preserve();
0945:
0946:                        for (i = 0; i < match_list.size(); i++) {
0947:                            TclObject cur_siglist = TclList.newInstance();
0948:                            cur_siglist.preserve();
0949:
0950:                            if (isConstructor) {
0951:                                Constructor con = ((Constructor) match_list
0952:                                        .get(i));
0953:                                TclList.append(interp, cur_siglist, TclString
0954:                                        .newInstance(con.getName()));
0955:
0956:                                //System.out.println("appending constructor name " + con.getName());
0957:
0958:                                match_classes = con.getParameterTypes();
0959:                            } else {
0960:                                Method meth = ((Method) match_list.get(i));
0961:                                TclList.append(interp, cur_siglist, TclString
0962:                                        .newInstance(meth.getName()));
0963:
0964:                                //System.out.println("appending method name " + meth.getName());
0965:
0966:                                match_classes = meth.getParameterTypes();
0967:                            }
0968:
0969:                            for (j = 0; j < argv_count; j++) {
0970:                                Class c = match_classes[j];
0971:                                TclList.append(interp, cur_siglist, TclString
0972:                                        .newInstance(JavaInfoCmd
0973:                                                .getNameFromClass(c)));
0974:                                //System.out.println("appending class name " + c.getName());
0975:                            }
0976:
0977:                            TclList.append(interp, siglist, cur_siglist);
0978:                            cur_siglist.release();
0979:                        }
0980:
0981:                        sb.append(siglist.toString());
0982:                        siglist.release();
0983:
0984:                        throw new TclException(interp, sb.toString());
0985:                    }
0986:
0987:                } // end else if (match_list.size() > 1)
0988:
0989:                // if we got to here then we could not find a matching method so raise error
0990:
0991:                if (isConstructor) {
0992:                    throw new TclException(interp,
0993:                            "can't find accessible constructor with "
0994:                                    + argv_count + " argument(s) for class \""
0995:                                    + JavaInfoCmd.getNameFromClass(cls) + "\"");
0996:                } else {
0997:                    if (!foundSameName) {
0998:                        throw new TclException(interp, "no accessible"
0999:                                + (isStatic ? " static " : " ") + "method \""
1000:                                + signature + "\" in class "
1001:                                + JavaInfoCmd.getNameFromClass(cls));
1002:                    } else {
1003:                        throw new TclException(interp, "can't find accessible"
1004:                                + (isStatic ? " static " : " ") + "method \""
1005:                                + signature + "\" with " + argv_count
1006:                                + " argument(s) for class \""
1007:                                + JavaInfoCmd.getNameFromClass(cls) + "\"");
1008:                    }
1009:                }
1010:            }
1011:
1012:            // Helper method to recursively add interfaces of a class to the vector
1013:
1014:            private static void addInterfaces(Class cls, ArrayList alist) {
1015:                alist.add(cls);
1016:
1017:                Class[] interfaces = cls.getInterfaces();
1018:
1019:                for (int i = 0; i < interfaces.length; i++) {
1020:                    addInterfaces(interfaces[i], alist);
1021:                }
1022:            }
1023:
1024:            /*
1025:             *----------------------------------------------------------------------
1026:             *
1027:             * getAccessibleConstructors --
1028:             *
1029:             *	Returns all constructors that can be invoked for a given class.
1030:             *
1031:             * Results:
1032:             *	An array of all the accessible constructors in the class.
1033:             *
1034:             * Side effects:
1035:             *	None.
1036:             *
1037:             *----------------------------------------------------------------------
1038:             */
1039:
1040:            static Constructor[] getAccessibleConstructors(Class cls) // The class to query.
1041:            {
1042:                if (PkgInvoker.usesDefaultInvoker(cls)) {
1043:                    return cls.getConstructors();
1044:                } else {
1045:                    Constructor[] constructors = cls.getDeclaredConstructors();
1046:                    ArrayList alist = null;
1047:                    boolean skipped_any = false;
1048:
1049:                    for (int i = 0; i < constructors.length; i++) {
1050:                        Constructor c = constructors[i];
1051:                        if (PkgInvoker.isAccessible(c)) {
1052:                            if (alist == null) {
1053:                                alist = new ArrayList(constructors.length);
1054:                            }
1055:                            alist.add(c);
1056:                        } else {
1057:                            skipped_any = true;
1058:                        }
1059:                    }
1060:
1061:                    if (skipped_any) {
1062:                        if (alist == null) {
1063:                            constructors = new Constructor[0];
1064:                        } else {
1065:                            constructors = new Constructor[alist.size()];
1066:                            for (int i = 0; i < constructors.length; i++) {
1067:                                constructors[i] = (Constructor) alist.get(i);
1068:                            }
1069:                        }
1070:                    }
1071:                    return constructors;
1072:                }
1073:            }
1074:
1075:            /*
1076:             *----------------------------------------------------------------------
1077:             *
1078:             * getAccessibleConstructor --
1079:             *
1080:             *	Returns an accessable constructors for the given class
1081:             *	that accepts the given arguments.
1082:             *
1083:             * Results:
1084:             *	A constructor object, raises a NoSuchMethodException
1085:             *	if an accessible constructor cannot be found.
1086:             *
1087:             * Side effects:
1088:             *	None.
1089:             *
1090:             *----------------------------------------------------------------------
1091:             */
1092:
1093:            static Constructor getAccessibleConstructor(Class cls, // The class to query.
1094:                    Class[] parameterTypes) // The constructor arguments types
1095:                    throws NoSuchMethodException {
1096:                if (PkgInvoker.usesDefaultInvoker(cls)) {
1097:                    return cls.getConstructor(parameterTypes);
1098:                } else {
1099:                    Constructor constructor = cls
1100:                            .getDeclaredConstructor(parameterTypes);
1101:                    if (!PkgInvoker.isAccessible(constructor)) {
1102:                        throw new NoSuchMethodException();
1103:                    }
1104:                    return constructor;
1105:                }
1106:            }
1107:
1108:            /*
1109:             *----------------------------------------------------------------------
1110:             *
1111:             * getAccessibleInstanceMethods --
1112:             *
1113:             *	Returns all instance methods that can be invoked for a given class.
1114:             *
1115:             * Results:
1116:             *	An array of all the accessible instance methods in the class and the
1117:             *	superclasses of the class. If a method is overloaded, only the
1118:             *	"most public" instance of that method is included in the
1119:             *	array. A method is considered accessible if it has public
1120:             *	access or if it does not have private access and the package has
1121:             *	a custom PkgInvoker. See comments above the "func" member
1122:             *	variable for more details.
1123:             *
1124:             * Side effects:
1125:             *	The array of methods are saved in a hashtable for faster access
1126:             *	in the future.
1127:             *
1128:             *----------------------------------------------------------------------
1129:             */
1130:
1131:            static Method[] getAccessibleInstanceMethods(Class cls) // The class to query.
1132:            {
1133:                Method[] methods = (Method[]) instanceMethodTable.get(cls);
1134:                if (methods != null) {
1135:                    return methods;
1136:                }
1137:
1138:                // Avoid using Class.getMethods() because it includes
1139:                // static members and it does not account for interfaces
1140:                // which need to include methods from the Object class.
1141:
1142:                ArrayList alist = new ArrayList();
1143:
1144:                for (Class c = cls; c != null;) {
1145:                    methods = c.getDeclaredMethods();
1146:                    mergeInstanceMethods(c, methods, alist);
1147:
1148:                    Class interfaces[] = c.getInterfaces();
1149:                    for (int i = 0; i < interfaces.length; i++) {
1150:                        mergeInstanceMethods(interfaces[i], interfaces[i]
1151:                                .getMethods(), alist);
1152:                    }
1153:
1154:                    if (c.isInterface()) {
1155:                        c = Object.class; // if cls is an interface add Object methods
1156:                    } else {
1157:                        c = c.getSuperclass();
1158:                    }
1159:                }
1160:
1161:                sortMethods(alist);
1162:                methods = new Method[alist.size()];
1163:                for (int i = 0; i < methods.length; i++) {
1164:                    methods[i] = (Method) alist.get(i);
1165:                }
1166:                instanceMethodTable.put(cls, methods);
1167:
1168:                return methods;
1169:            }
1170:
1171:            /*
1172:             *----------------------------------------------------------------------
1173:             *
1174:             * getAccessibleStaticMethods --
1175:             *
1176:             *	Returns all static methods that can be invoked for a given class.
1177:             *
1178:             * Results:
1179:             *	An array of all the accessible static methods in the class.
1180:             *	A method is considered accessible if it has public
1181:             *	access or if it is not private and the package has
1182:             *	a custom PkgInvoker. See comments above the "func" member
1183:             *	variable for more details.
1184:             *
1185:             * Side effects:
1186:             *	None.
1187:             *
1188:             *----------------------------------------------------------------------
1189:             */
1190:
1191:            static Method[] getAccessibleStaticMethods(Class cls) // The class to query.
1192:            {
1193:                Method[] methods = (Method[]) staticMethodTable.get(cls);
1194:                if (methods != null) {
1195:                    return methods;
1196:                }
1197:
1198:                // When searching for static methods in this class,
1199:                // call getDeclaredMethods() and filter out those
1200:                // methods that are not static or are not accessible.
1201:                // This should be quicker than calling getMethods()
1202:                // since that returns both static and instance methods
1203:                // for the class and its superclasses.
1204:
1205:                methods = cls.getDeclaredMethods();
1206:                ArrayList alist = new ArrayList();
1207:
1208:                for (int i = 0; i < methods.length; i++) {
1209:                    Method m = methods[i];
1210:                    if (Modifier.isStatic(m.getModifiers())
1211:                            && PkgInvoker.isAccessible(m)) {
1212:                        alist.add(m);
1213:                    }
1214:                }
1215:
1216:                sortMethods(alist);
1217:                methods = new Method[alist.size()];
1218:                for (int i = 0; i < methods.length; i++) {
1219:                    methods[i] = (Method) alist.get(i);
1220:                }
1221:                staticMethodTable.put(cls, methods);
1222:
1223:                return methods;
1224:            }
1225:
1226:            /*
1227:             *----------------------------------------------------------------------
1228:             *
1229:             * mergeInstanceMethods --
1230:             *
1231:             *	Add instance methods declared by a super-class or an interface to
1232:             *	the list of accessible instance methods.
1233:             *
1234:             * Results:
1235:             *	None.
1236:             *
1237:             * Side effects:
1238:             *	Elements of methods[] are added to vec. If an instance of
1239:             *	an overloaded method is already in vec, it will be replaced
1240:             *	by a new instance only if the new instance has a higher rank.
1241:             *
1242:             *----------------------------------------------------------------------
1243:             */
1244:
1245:            private static void mergeInstanceMethods(Class c, Method methods[],
1246:                    ArrayList alist) {
1247:                for (int i = 0; i < methods.length; i++) {
1248:                    boolean sameSigExists = false;
1249:                    Method newMeth = methods[i];
1250:
1251:                    if (newMeth == null)
1252:                        continue;
1253:
1254:                    // Don't merge static methods or inaccessible methods
1255:                    if (Modifier.isStatic(newMeth.getModifiers())
1256:                            || !PkgInvoker.isAccessible(newMeth)) {
1257:                        continue;
1258:                    }
1259:
1260:                    for (int j = 0; j < alist.size(); j++) {
1261:                        Method oldMeth = (Method) alist.get(j);
1262:
1263:                        if (methodSigEqual(oldMeth, newMeth)) {
1264:                            sameSigExists = true;
1265:
1266:                            Class oldCls = oldMeth.getDeclaringClass();
1267:                            int newRank = getMethodRank(c, newMeth);
1268:                            int oldRank = getMethodRank(oldCls, oldMeth);
1269:
1270:                            if (newRank > oldRank) {
1271:                                alist.set(j, newMeth);
1272:                            }
1273:                            break;
1274:                        }
1275:                    }
1276:
1277:                    if (!sameSigExists) {
1278:                        // We copy a method into the list only if no method
1279:                        // with the same signature is already in the list.
1280:                        // Otherwise the matching routine in the get()
1281:                        // procedure may run into "ambiguous method signature"
1282:                        // errors when it sees instances of overloaded
1283:                        // methods.
1284:
1285:                        alist.add(newMeth);
1286:                    }
1287:                }
1288:            }
1289:
1290:            /*
1291:             *----------------------------------------------------------------------
1292:             *
1293:             * methodSigEqual --
1294:             *
1295:             *	Returns whether the two methods have the same signature.
1296:             *
1297:             * Results:
1298:             *	True if the method names and arguments are the same. False
1299:             *	otherwise
1300:             *
1301:             * Side effects:
1302:             *	None.
1303:             *
1304:             *----------------------------------------------------------------------
1305:             */
1306:
1307:            private static boolean methodSigEqual(Method method1, Method method2) {
1308:                if (!method1.getName().equals(method2.getName())) {
1309:                    return false;
1310:                }
1311:
1312:                Class param1[] = method1.getParameterTypes();
1313:                Class param2[] = method2.getParameterTypes();
1314:
1315:                if (param1.length != param2.length) {
1316:                    return false;
1317:                }
1318:
1319:                for (int i = 0; i < param1.length; i++) {
1320:                    if (param1[i] != param2[i]) {
1321:                        return false;
1322:                    }
1323:                }
1324:
1325:                return true;
1326:            }
1327:
1328:            /*
1329:             *----------------------------------------------------------------------
1330:             *
1331:             * sortMethods --
1332:             *
1333:             *	This method will sort a list of Method objects. We need to sort
1334:             *      the methods so that the order of the methods does not depend on
1335:             *      the order the methods as returned by the JVM.
1336:             *
1337:             * Results:
1338:             *	None.
1339:             *
1340:             * Side effects:
1341:             *      The order of the elements in the List is changed.
1342:             *
1343:             *----------------------------------------------------------------------
1344:             */
1345:
1346:            private static void sortMethods(ArrayList alist) {
1347:                final boolean debug = false; // set to true for debug output
1348:                int insize = alist.size();
1349:
1350:                if (debug) {
1351:                    System.out.println("Pre sort dump");
1352:                    for (int i = 0; i < alist.size(); i++) {
1353:                        Method m = (Method) alist.get(i);
1354:                        System.out.println("Method " + i + " is \t\""
1355:                                + getMethodDescription(m) + "\"");
1356:                    }
1357:                }
1358:
1359:                for (int i = 1; i < alist.size(); i++) {
1360:                    int c = i;
1361:                    Method cm = (Method) alist.get(c);
1362:                    String cms = getMethodDescription(cm);
1363:
1364:                    // loop down array swapping elements into sorted order
1365:
1366:                    for (int j = c - 1; j >= 0; j--) {
1367:                        Method jm = (Method) alist.get(j);
1368:                        String jms = getMethodDescription(jm);
1369:
1370:                        if (debug) {
1371:                            System.out.println("checking \"" + cms
1372:                                    + "\" from index " + c);
1373:                            System.out.println("against  \"" + jms
1374:                                    + "\" from index " + j);
1375:                            System.out.println("compareTo() is "
1376:                                    + cms.compareTo(jms));
1377:                        }
1378:
1379:                        if (cms.compareTo(jms) <= 0) {
1380:                            if (debug) {
1381:                                System.out.println("swapping " + c + " and "
1382:                                        + j);
1383:                            }
1384:
1385:                            // Swap the Methods at c and j
1386:                            alist.set(c, jm);
1387:                            alist.set(j, cm);
1388:
1389:                            // Current becomes the value of j for next loop
1390:                            c = j;
1391:                            //cm = jm;
1392:                            //cms = jms;
1393:
1394:                        } else {
1395:                            if (debug) {
1396:                                System.out.println("no swap at index " + j);
1397:                            }
1398:                            break;
1399:                        }
1400:                    }
1401:                }
1402:
1403:                if (debug) {
1404:                    System.out.println("Post sort dump");
1405:                    for (int i = 0; i < alist.size(); i++) {
1406:                        Method m = (Method) alist.get(i);
1407:                        System.out.println("Method " + i + " is \t\""
1408:                                + getMethodDescription(m) + "\"");
1409:                    }
1410:                }
1411:
1412:                if (insize != alist.size()) {
1413:                    throw new RuntimeException("lost elements");
1414:                }
1415:                return;
1416:            }
1417:
1418:            /*
1419:             *----------------------------------------------------------------------
1420:             *
1421:             * getMethodDescription --
1422:             *
1423:             *	This helper method will return a string description of a method
1424:             *      and the arguments and return type of the methos. This helper
1425:             *      is only called by sortMethods().
1426:             *
1427:             * Results:
1428:             *	None.
1429:             *
1430:             * Side effects:
1431:             *      None.
1432:             *
1433:             *----------------------------------------------------------------------
1434:             */
1435:            private static String getMethodDescription(Method m) {
1436:                StringBuffer sb = new StringBuffer(50);
1437:
1438:                sb.append(m.getName());
1439:
1440:                Class[] params = m.getParameterTypes();
1441:
1442:                sb.append('(');
1443:
1444:                for (int i = 0; i < params.length; i++) {
1445:
1446:                    sb.append(JavaInfoCmd.getNameFromClass(params[i]));
1447:
1448:                    if (i < (params.length - 1)) {
1449:                        sb.append(", ");
1450:                    }
1451:                }
1452:
1453:                sb.append(") returns ");
1454:
1455:                Class ret = m.getReturnType();
1456:
1457:                sb.append(JavaInfoCmd.getNameFromClass(ret));
1458:
1459:                return sb.toString();
1460:            }
1461:
1462:            /*
1463:             *----------------------------------------------------------------------
1464:             *
1465:             * getMethodRank --
1466:             *
1467:             *	Returns the rank of "public-ness" of the method. See comments
1468:             *	above the "func" member variable for more details on public-ness
1469:             *	ranking.
1470:             *
1471:             * Results:
1472:             *	The rank of "public-ness" of the method.
1473:             *
1474:             * Side effects:
1475:             *	None.
1476:             *
1477:             *----------------------------------------------------------------------
1478:             */
1479:
1480:            private static int getMethodRank(Class declaringCls, // The class that declares the method.
1481:                    Method method) // Return the rank of this method.
1482:            {
1483:                int methMod = method.getModifiers();
1484:
1485:                if (Modifier.isPrivate(methMod)) {
1486:                    return 0;
1487:                }
1488:
1489:                int clsMod = declaringCls.getModifiers();
1490:
1491:                if (Modifier.isPublic(methMod) && Modifier.isPublic(clsMod)) {
1492:                    return 2;
1493:                }
1494:
1495:                return 0;
1496:            }
1497:
1498:        } // end FuncSig.
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.