Source Code Cross Referenced for ReflectObject.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:         * ReflectObject.java --
0003:         *
0004:         *	Implements the Tcl internal representation of Java
0005:         *	reflection object.
0006:         *
0007:         * See the file "license.terms" for information on usage and
0008:         * redistribution of this file, and for a DISCLAIMER OF ALL
0009:         * WARRANTIES.
0010:         *
0011:         * RCS: @(#) $Id: ReflectObject.java,v 1.19 2006/04/13 07:36:50 mdejong Exp $
0012:         *
0013:         */
0014:
0015:        package tcl.lang;
0016:
0017:        import tcl.lang.reflect.PkgInvoker;
0018:
0019:        import java.lang.reflect.*;
0020:        import java.util.*;
0021:        import java.beans.*;
0022:
0023:        /**
0024:         * A ReflectObject is used to create and access arbitrary Java objects
0025:         * using the Java Reflection API. It wraps around a Java object (i.e.,
0026:         * an instance of any Java class) and expose it to Tcl scripts. The
0027:         * object is registered inside the interpreter and is given a string
0028:         * name. Tcl scripts can manipulate this object as long as the the
0029:         * reference count of the object is greater than zero.
0030:         */
0031:
0032:        public class ReflectObject implements  InternalRep, CommandWithDispose {
0033:
0034:            // The java.lang.Object wrapped by the ReflectObject representation.
0035:
0036:            Object javaObj;
0037:            Class javaClass;
0038:
0039:            // The interpreter in which the java.lang.Object is registered in.
0040:            // ReflectObject's are not shared among interpreters for safety
0041:            // reasons.
0042:
0043:            Interp ownerInterp;
0044:
0045:            // The reference ID of this object. (same as instance command name)
0046:
0047:            String refID;
0048:
0049:            // This variables records how many TclObject's are using
0050:            // this ReflectObject internal rep. In this example:
0051:            //
0052:            //     set x [new java.lang.Integer 1]
0053:            //     set y [format %s $x]
0054:            //     java::info methods $y
0055:            //
0056:            // The two objects $x and $y share the same ReflectObject instance.
0057:            // useCount is 2 when the java::info command has just translated the
0058:            // string $y into a ReflectObject.
0059:            //
0060:            // useCount is initially 1. It will be more than 1 only when the
0061:            // script tries to refer to the object using its string form, or when
0062:            // the same object is returned by the Reflection API more than once.
0063:            //
0064:            // This variable is called useCount rather than refCount to avoid
0065:            // confusion with TclObject.refCount.
0066:
0067:            private int useCount;
0068:
0069:            // This variable marks whether the object is still considered "valid"
0070:            // in Tcl scripts. An object is no longer valid if its object command
0071:            // has been explicitly deleted from the interpreter.
0072:
0073:            private boolean isValid;
0074:
0075:            // Stores the bindings of this ReflectObject. This member variable is used
0076:            // in the BeanEventMgr class.
0077:
0078:            Hashtable bindings;
0079:
0080:            // the string representation of the null reflect object
0081:
0082:            private static final String NULL_REP = "java0x0";
0083:
0084:            /*
0085:
0086:             // this really should be final but there is a bug in Sun's javac which
0087:             // incorrectly flags this as a "final not initialized" error
0088:             //private static final ReflectObject NULL_OBJECT;
0089:
0090:             private static ReflectObject NULL_OBJECT;
0091:
0092:
0093:             // Allocate single object used to represent the untyped null java
0094:             // Object. A null object is not registered (hence it can't be deleted).  
0095:             static {
0096:             NULL_OBJECT = makeNullObject(null, null);
0097:             }
0098:
0099:             */
0100:
0101:            protected static final String NOCONVERT = "-noconvert";
0102:
0103:            protected static final String CMD_PREFIX = "java0x";
0104:
0105:            // set to true to see extra output
0106:
0107:            private static final boolean debug = false;
0108:
0109:            // set to true to see dump the relfect table
0110:            // we adding or removing an object from the table
0111:
0112:            private static final boolean dump = false;
0113:
0114:            // Private helper for creating reflected null objects
0115:
0116:            private static ReflectObject makeNullObject(Interp i, Class c) {
0117:                ReflectObject ro = new ReflectObject();
0118:
0119:                ro.ownerInterp = i;
0120:
0121:                ro.refID = NULL_REP;
0122:                ro.useCount = 1;
0123:                ro.isValid = true;
0124:
0125:                ro.javaObj = null;
0126:                ro.javaClass = c;
0127:
0128:                return ro;
0129:            }
0130:
0131:            // Return the string used to hash this Java object into the reflect table
0132:            // or the conflict table (in case of a duplicate hash in reflect table.
0133:            // For example: java.lang.Object.546464 -> ReflectObject
0134:
0135:            private static String getHashString(Class cl, Object obj) {
0136:                StringBuffer buff = new StringBuffer();
0137:                buff.append(JavaInfoCmd.getNameFromClass(cl));
0138:                buff.append('.');
0139:
0140:                // A bad hash would suck in terms of performance but it should not
0141:                // generate any errors. Use '1' for an extreme test of this case.
0142:                //buff.append('1');
0143:                buff.append(System.identityHashCode(obj));
0144:
0145:                return buff.toString();
0146:            }
0147:
0148:            // Private helper used to add a reflect object to the reflect table
0149:
0150:            private static void addToReflectTable(ReflectObject roRep) {
0151:                Interp interp = roRep.ownerInterp;
0152:                Class cl = roRep.javaClass;
0153:                Object obj = roRep.javaObj;
0154:                String id = roRep.refID;
0155:
0156:                String hash = getHashString(cl, obj);
0157:                ReflectObject found = (ReflectObject) interp.reflectObjTable
0158:                        .get(hash);
0159:
0160:                if (found == null) {
0161:                    // There was no mapping for this hash value, add one now.
0162:
0163:                    if (debug) {
0164:                        System.out.println("new reflect table entry for " + id
0165:                                + " with hash \"" + hash + "\"");
0166:                    }
0167:
0168:                    interp.reflectObjTable.put(hash, roRep);
0169:                } else {
0170:                    // If there is already an entry for this hash value, it means
0171:                    // that there are two different objects of the same class that
0172:                    // have the same hash value. In this case, add the ReflectObject
0173:                    // to the conflict table for this hash value.
0174:                    // java.lang.Object.546464 -> {ReflectObject ReflectObject ReflectObject}
0175:
0176:                    if (debug) {
0177:                        System.out
0178:                                .println("hash conflict in reflect table for "
0179:                                        + id + " with hash \"" + hash + "\"");
0180:                    }
0181:
0182:                    ArrayList conflicts = (ArrayList) interp.reflectConflictTable
0183:                            .get(hash);
0184:
0185:                    if (conflicts == null) {
0186:                        conflicts = new ArrayList();
0187:                        interp.reflectConflictTable.put(hash, conflicts);
0188:                    }
0189:
0190:                    if (debug) {
0191:                        if (conflicts.contains(roRep)) {
0192:                            throw new TclRuntimeError(
0193:                                    "the conflict table already contains the ReflectObject");
0194:                        }
0195:                    }
0196:
0197:                    conflicts.add(roRep);
0198:                }
0199:            }
0200:
0201:            // Private helper used to remove a reflected object from the reflect table.
0202:
0203:            private static void removeFromReflectTable(ReflectObject roRep) {
0204:                Interp interp = roRep.ownerInterp;
0205:                Class cl = roRep.javaClass;
0206:                Object obj = roRep.javaObj;
0207:                String id = roRep.refID;
0208:
0209:                String hash = getHashString(cl, obj);
0210:                ReflectObject found = (ReflectObject) interp.reflectObjTable
0211:                        .get(hash);
0212:
0213:                // This should never happen
0214:                if (found == null) {
0215:
0216:                    throw new TclRuntimeError(
0217:                            "reflect table returned null for " + id
0218:                                    + " with hash \"" + hash + "\"");
0219:                } else {
0220:
0221:                    // In the first case, the ReflectObject we hashed to is the same as the
0222:                    // one we passed in, we can just remove it from the reflect table.
0223:                    // Be careful to also check the conflict table, if there is 1 entry
0224:                    // in the conflict table then toast the conflict table and remap the
0225:                    // reflect object in the conflict table. Otherwise, grab the first
0226:                    // value out of the conflict table and hash that in the reflect table.
0227:
0228:                    if (found == roRep) {
0229:                        interp.reflectObjTable.remove(hash);
0230:
0231:                        if (debug) {
0232:                            System.out.println("removing reflect table entry "
0233:                                    + hash);
0234:                        }
0235:
0236:                        ArrayList conflicts = (ArrayList) interp.reflectConflictTable
0237:                                .get(hash);
0238:
0239:                        if (conflicts != null) {
0240:                            Object first = conflicts.remove(0);
0241:
0242:                            if (conflicts.isEmpty()) {
0243:                                interp.reflectConflictTable.remove(hash);
0244:                            }
0245:
0246:                            interp.reflectObjTable.put(hash, first);
0247:
0248:                            if (debug) {
0249:                                System.out
0250:                                        .println("replaced reflect table entry from conflict "
0251:                                                + hash);
0252:                            }
0253:                        }
0254:                    } else {
0255:
0256:                        // In the second case, the ReflectObject we hashed to did not match
0257:                        // the entry in the reflect table. This means it must be in the
0258:                        // conflict table so remove it from there. Be sure to remove the
0259:                        // conflict table mapping if we are removing the last conflict!
0260:
0261:                        ArrayList conflicts = (ArrayList) interp.reflectConflictTable
0262:                                .get(hash);
0263:
0264:                        // This should never happen!
0265:
0266:                        if (conflicts == null) {
0267:                            throw new TclRuntimeError(
0268:                                    "conflict table mapped to null for " + id
0269:                                            + " with hash \"" + hash + "\"");
0270:                        }
0271:
0272:                        if (debug) {
0273:                            System.out
0274:                                    .println("removing conflict table entry for "
0275:                                            + id
0276:                                            + " with hash \""
0277:                                            + hash
0278:                                            + "\"");
0279:                        }
0280:
0281:                        // FIXME: double check that this uses == compare
0282:                        // This remove should never fail!
0283:
0284:                        int index = conflicts.indexOf(roRep);
0285:                        if (index == -1) {
0286:                            throw new TclRuntimeError(
0287:                                    "no entry in conflict table for " + id
0288:                                            + " with hash \"" + hash + "\"");
0289:                        }
0290:                        conflicts.remove(index);
0291:
0292:                        if (conflicts.isEmpty()) {
0293:                            interp.reflectConflictTable.remove(hash);
0294:                        }
0295:                    }
0296:                }
0297:            }
0298:
0299:            // Find in ConflictTable will search the reflect hash conflict table
0300:            // for a given {Class Object} pair. If the pair exists its ReflectObject
0301:            // will be returned. If not, null will be returned. In the case where
0302:            // we want to add a new object that conflicts, the table will not
0303:            // exists yet so we can't find a match.
0304:
0305:            private static ReflectObject findInConflictTable(Interp interp,
0306:                    Object obj, String hash) {
0307:                ArrayList conflicts = (ArrayList) interp.reflectConflictTable
0308:                        .get(hash);
0309:
0310:                if (conflicts == null) {
0311:                    return null;
0312:                }
0313:
0314:                for (ListIterator iter = conflicts.listIterator(); iter
0315:                        .hasNext();) {
0316:                    ReflectObject found = (ReflectObject) iter.next();
0317:                    if (found.javaObj == obj) {
0318:                        if (debug) {
0319:                            System.out
0320:                                    .println("found conflict table entry for hash "
0321:                                            + hash);
0322:                        }
0323:
0324:                        return found;
0325:                    }
0326:                }
0327:
0328:                return null;
0329:            }
0330:
0331:            // Find in ReflectTable will search the reflect table for a given
0332:            // {Class Object} pair. If the pair exists its ReflectObject
0333:            // will be returned. If not, null will be returned.
0334:
0335:            private static ReflectObject findInReflectTable(Interp interp,
0336:                    Class cl, Object obj) {
0337:                String hash = getHashString(cl, obj);
0338:                ReflectObject found = (ReflectObject) interp.reflectObjTable
0339:                        .get(hash);
0340:
0341:                // If there is no mapping in the reflect table for this object, return null
0342:
0343:                if (found == null) {
0344:                    if (debug) {
0345:                        System.out
0346:                                .println("could not find reflect object for hash \""
0347:                                        + hash + "\"");
0348:                    }
0349:
0350:                    return null;
0351:                } else {
0352:                    // If we find a mapping in the reflect table there are two cases
0353:                    // we need to worry about. If the object we mapped to is the same
0354:                    // object as the one we are have, then just return it. In the
0355:                    // case where the object we map to is not the same, we need
0356:                    // to look in the reflect table because it could be in there.
0357:
0358:                    if (found.javaObj == obj) {
0359:                        if (debug) {
0360:                            System.out
0361:                                    .println("found reflect table match for id "
0362:                                            + found.refID
0363:                                            + " with hash \""
0364:                                            + hash + "\"");
0365:                        }
0366:
0367:                        return found;
0368:                    } else {
0369:                        return findInConflictTable(interp, obj, hash);
0370:                    }
0371:                }
0372:            }
0373:
0374:            // This method is only used for debugging, it will dump the contents of the
0375:            // reflect table in a human readable form. The dump is to stdout.
0376:
0377:            // dump the table from a Tcl/Java shell like this
0378:            // set i [java::getinterp]
0379:            // java::call tcl.lang.ReflectObject dump $i
0380:
0381:            public static void dump(Interp interp) {
0382:                try {
0383:                    System.out
0384:                            .println("BEGIN DUMP -------------------------------");
0385:                    System.out.println("interp.reflectObjCount = "
0386:                            + interp.reflectObjCount);
0387:                    System.out.println("interp.reflectObjTable.size() = "
0388:                            + interp.reflectObjTable.size());
0389:                    System.out.println("interp.reflectConflictTable.size() = "
0390:                            + interp.reflectConflictTable.size());
0391:
0392:                    // Loop over the entries in the reflectObjTable and dump them out.
0393:
0394:                    for (Iterator iter = interp.reflectObjTable.entrySet()
0395:                            .iterator(); iter.hasNext();) {
0396:                        Map.Entry entry = (Map.Entry) iter.next();
0397:
0398:                        System.out.println();
0399:                        String hash = (String) entry.getKey();
0400:                        ReflectObject roRep = (ReflectObject) entry.getValue();
0401:
0402:                        if (roRep == null) {
0403:                            throw new RuntimeException("Reflect table entry \""
0404:                                    + hash + "\" hashed to null");
0405:                        }
0406:
0407:                        // do sanity check
0408:                        if (roRep.ownerInterp != interp) {
0409:                            throw new RuntimeException(
0410:                                    "roRep.ownerInterp not the same as current interp");
0411:                        }
0412:
0413:                        // Check to see if the command is in the Tcl command table.
0414:                        if (interp.getCommand(roRep.refID) == null) {
0415:                            System.out
0416:                                    .println("could not find command named \""
0417:                                            + roRep.refID + "\"");
0418:                        }
0419:
0420:                        String hash2 = getHashString(roRep.javaClass,
0421:                                roRep.javaObj);
0422:
0423:                        if (!hash.equals(hash2)) {
0424:                            throw new RuntimeException("hash \"" + hash
0425:                                    + "\" is not equal to calculated"
0426:                                    + " hash \"" + hash2);
0427:                        }
0428:
0429:                        System.out
0430:                                .println("hash \""
0431:                                        + hash
0432:                                        + "\" corresponds to ReflectObject with "
0433:                                        + "refID \""
0434:                                        + roRep.refID
0435:                                        + "\" useCount = \""
0436:                                        + roRep.useCount
0437:                                        + "\" isValid = \""
0438:                                        + roRep.isValid
0439:                                        + "\""
0440:                                        + " javaClass = \""
0441:                                        + JavaInfoCmd
0442:                                                .getNameFromClass(roRep.javaClass)
0443:                                        + "\""
0444:                                        + " System.identityHashCode(javaObj) = \""
0445:                                        + System
0446:                                                .identityHashCode(roRep.javaObj)
0447:                                        + "\"");
0448:
0449:                        ArrayList conflicts = (ArrayList) interp.reflectConflictTable
0450:                                .get(hash);
0451:
0452:                        if (conflicts != null) {
0453:                            System.out.println("Found conflict table for hash "
0454:                                    + hash);
0455:
0456:                            for (ListIterator iter2 = conflicts.listIterator(); iter
0457:                                    .hasNext();) {
0458:                                ReflectObject found = (ReflectObject) iter2
0459:                                        .next();
0460:
0461:                                System.out
0462:                                        .println("hash conflict for \""
0463:                                                + hash
0464:                                                + "\" corresponds to ReflectObject with "
0465:                                                + "refID \"" + found.refID
0466:                                                + "\"");
0467:                            }
0468:                        }
0469:                    }
0470:                } catch (Throwable e) {
0471:                    e.printStackTrace(System.out);
0472:                }
0473:            }
0474:
0475:            /*
0476:             *----------------------------------------------------------------------
0477:             *
0478:             * makeReflectObject --
0479:             *
0480:             *	Wraps an Java Object in a ReflectObject. If the same Java
0481:             *	Object has already been wrapped in a ReflectObject, return
0482:             *	that ReflectObject. Otherwise, create a new ReflectObject to
0483:             *	wrap the Java Object.
0484:             *
0485:             * Results:
0486:             *	None.
0487:             *
0488:             * Side effects:
0489:             *	The object is unregistered (and thus no longer accessible from
0490:             *	Tcl scripts) if no other if no other TclObjects are
0491:             *	still using this internal rep.
0492:             *
0493:             *----------------------------------------------------------------------
0494:             */
0495:
0496:            private static ReflectObject makeReflectObject(Interp interp,
0497:                    Class cl, Object obj) throws TclException // if a null class with a non null object is passed in
0498:            {
0499:                //final boolean debug = false;
0500:
0501:                if (cl != null && !PkgInvoker.isAccessible(cl)) {
0502:                    JavaInvoke.notAccessibleError(interp, cl);
0503:                }
0504:
0505:                if (obj == null) {
0506:                    // this is the null reflect object case
0507:
0508:                    if (debug) {
0509:                        System.out.println("null object");
0510:                    }
0511:
0512:                    if (debug && (cl != null)) {
0513:                        System.out.println("non null class with null object");
0514:                        System.out.println("non null class was " + cl);
0515:                    }
0516:
0517:                    // null objects are not added to the reflect table like other instances
0518:
0519:                    return makeNullObject(interp, cl);
0520:                }
0521:
0522:                if (cl == null) {
0523:                    // we have no way to deal with a non null object that has a
0524:                    // null class reference type, we must give up in this case
0525:
0526:                    throw new TclException(interp,
0527:                            "non null reflect object with null class is not valid");
0528:                }
0529:
0530:                // apply builtin type conversion rules (so int becomes java.lang.Integer)
0531:
0532:                if (cl == Integer.TYPE)
0533:                    cl = Integer.class;
0534:                else if (cl == Boolean.TYPE)
0535:                    cl = Boolean.class;
0536:                else if (cl == Long.TYPE)
0537:                    cl = Long.class;
0538:                else if (cl == Float.TYPE)
0539:                    cl = Float.class;
0540:                else if (cl == Double.TYPE)
0541:                    cl = Double.class;
0542:                else if (cl == Byte.TYPE)
0543:                    cl = Byte.class;
0544:                else if (cl == Short.TYPE)
0545:                    cl = Short.class;
0546:                else if (cl == Character.TYPE)
0547:                    cl = Character.class;
0548:                else if (cl == Void.TYPE)
0549:                    throw new TclException(interp,
0550:                            "void object type can not be reflected");
0551:
0552:                if (debug) {
0553:                    System.out.println("object will be reflected as "
0554:                            + JavaInfoCmd.getNameFromClass(cl));
0555:                }
0556:
0557:                // Try to find this {Class Object} pair in the reflect table.
0558:
0559:                ReflectObject roRep = findInReflectTable(interp, cl, obj);
0560:
0561:                if (roRep != null) {
0562:                    // If it is already in the table just increment the use count and return it
0563:
0564:                    roRep.useCount++;
0565:
0566:                    if (debug) {
0567:                        System.out.println("incr useCount of found object "
0568:                                + roRep.refID + " to " + roRep.useCount);
0569:                    }
0570:
0571:                    return roRep;
0572:                } else {
0573:                    if (cl.isArray()) {
0574:                        roRep = new ArrayObject();
0575:                    } else {
0576:                        roRep = new ReflectObject();
0577:                    }
0578:
0579:                    roRep.ownerInterp = interp;
0580:                    roRep.javaObj = obj;
0581:                    roRep.javaClass = cl;
0582:
0583:                    // make sure the object can be represented by the given Class
0584:                    Class obj_class = roRep.javaObj.getClass();
0585:
0586:                    if (!roRep.javaClass.isAssignableFrom(obj_class)) {
0587:                        throw new TclException(interp, "object of type "
0588:                                + JavaInfoCmd.getNameFromClass(obj_class)
0589:                                + " can not be referenced as type "
0590:                                + JavaInfoCmd.getNameFromClass(roRep.javaClass));
0591:                    }
0592:
0593:                    if (dump) {
0594:                        System.out.println("PRE REGISTER DUMP");
0595:                        dump(interp);
0596:                    }
0597:
0598:                    // Register the object in the interp.
0599:
0600:                    interp.reflectObjCount++; // incr id, the first id used will be 1
0601:                    roRep.refID = CMD_PREFIX
0602:                            + Long.toHexString(interp.reflectObjCount);
0603:
0604:                    interp.createCommand(roRep.refID, roRep);
0605:                    addToReflectTable(roRep);
0606:
0607:                    if (debug) {
0608:                        System.out.println("reflect object " + roRep.refID
0609:                                + " of type "
0610:                                + JavaInfoCmd.getNameFromClass(roRep.javaClass)
0611:                                + " registered");
0612:                    }
0613:
0614:                    roRep.useCount = 1;
0615:                    roRep.isValid = true;
0616:
0617:                    if (dump) {
0618:                        System.out.println("POST REGISTER DUMP");
0619:                        dump(interp);
0620:                    }
0621:
0622:                    return roRep;
0623:                }
0624:            }
0625:
0626:            /*
0627:             *----------------------------------------------------------------------
0628:             *
0629:             * dispose --
0630:             *
0631:             *	Called when a TclObject no longers uses this internal rep. We
0632:             *	unregister the java.lang.Object if no other TclObjects are
0633:             *	still using this internal rep.
0634:             *
0635:             * Results:
0636:             *	None.
0637:             *
0638:             * Side effects:
0639:             *	The object is unregistered (and thus no longer accessible from
0640:             *	Tcl scripts) if no other if no other TclObjects are
0641:             *	still using this internal rep.
0642:             *
0643:             *----------------------------------------------------------------------
0644:             */
0645:
0646:            public void dispose() {
0647:                if (debug) {
0648:                    System.out.println("dispose called for reflect object "
0649:                            + refID);
0650:                }
0651:
0652:                useCount--;
0653:                if ((useCount == 0) && (refID != NULL_REP)) {
0654:                    // No TclObject is using this internal rep anymore. Free it.
0655:
0656:                    if (debug) {
0657:                        System.out.println("reflect object " + refID
0658:                                + " is no longer being used");
0659:                    }
0660:
0661:                    if (dump) {
0662:                        System.out.println("PRE DELETE DUMP");
0663:                        dump(ownerInterp);
0664:                    }
0665:
0666:                    // Don't delete command if interp was already deleted
0667:                    if (isValid)
0668:                        ownerInterp.deleteCommand(refID);
0669:                    removeFromReflectTable(this );
0670:
0671:                    ownerInterp = null;
0672:                    javaObj = null;
0673:                    javaClass = null;
0674:                    bindings = null;
0675:                    refID = NULL_REP;
0676:                }
0677:            }
0678:
0679:            /*
0680:             *----------------------------------------------------------------------
0681:             *
0682:             * duplicate --
0683:             *
0684:             *	Get a copy of this ReflectObject for copy-on-write
0685:             *	operations. We just increment its useCount and return the same
0686:             *	ReflectObject because ReflectObject's cannot be modified, so
0687:             *	they don't need copy-on-write protections.
0688:             *
0689:             * Results:
0690:             *	The same internal rep.
0691:             *
0692:             * Side effects:
0693:             *	None.
0694:             *
0695:             *----------------------------------------------------------------------
0696:             */
0697:
0698:            public InternalRep duplicate() {
0699:                useCount++;
0700:
0701:                if (debug) {
0702:                    System.out.println("duplicate(): incr useCount of " + refID
0703:                            + " to " + useCount);
0704:                }
0705:
0706:                return this ;
0707:            }
0708:
0709:            /*
0710:             *----------------------------------------------------------------------
0711:             *
0712:             * setReflectObjectFromAny --
0713:             *
0714:             *	Called to convert an TclObject's internal rep to ReflectObject.
0715:             *
0716:             * Results:
0717:             *	None.
0718:             *
0719:             * Side effects:
0720:             *	When successful, the internal representation of tobj is
0721:             *	changed to ReflectObject, if it is not already so.
0722:             *
0723:             *----------------------------------------------------------------------
0724:             */
0725:
0726:            private static void setReflectObjectFromAny(Interp interp, // Current interpreter. Must be non-null.
0727:                    TclObject tobj) // The TclObject to convert.
0728:                    throws TclException // If the object's internal rep is not
0729:            // already ReflectObject, and the string rep
0730:            // is not the name of a java.lang.Object
0731:            // registered in the given interpreter.
0732:            // Error message is left inside interp.
0733:            {
0734:                InternalRep rep = tobj.getInternalRep();
0735:                ReflectObject roRep;
0736:
0737:                if (rep instanceof  ReflectObject) {
0738:                    roRep = (ReflectObject) rep;
0739:                    if (roRep.isValid && (roRep.ownerInterp == interp)) {
0740:                        return;
0741:                    }
0742:                }
0743:
0744:                String s = tobj.toString();
0745:                if (s.startsWith(CMD_PREFIX)) {
0746:                    if (s.equals(NULL_REP)) {
0747:                        tobj.setInternalRep(makeReflectObject(interp, null,
0748:                                null));
0749:                        return;
0750:                    } else {
0751:                        Command cmd = interp.getCommand(s);
0752:                        if ((cmd != null) && (cmd instanceof  ReflectObject)
0753:                                && ((ReflectObject) cmd).isValid) {
0754:                            roRep = (ReflectObject) cmd;
0755:                            roRep.useCount++;
0756:
0757:                            if (debug) {
0758:                                System.out
0759:                                        .println("setReflectObjectFromAny(): incr useCount of "
0760:                                                + roRep.refID
0761:                                                + " to "
0762:                                                + roRep.useCount);
0763:                            }
0764:
0765:                            tobj.setInternalRep(roRep);
0766:                            return;
0767:                        }
0768:                    }
0769:                }
0770:
0771:                throw new TclException(interp, "unknown java object \"" + tobj
0772:                        + "\"");
0773:            }
0774:
0775:            /*
0776:             *----------------------------------------------------------------------
0777:             *
0778:             * newInstance --
0779:             *
0780:             *	Creates a new instance of a TclObject that wraps a
0781:             *	java.lang.Object.
0782:             *
0783:             * Results:
0784:             *	The newly created TclObject.
0785:             *
0786:             * Side effects:
0787:             *	The java.lang.Object will be registered in the interpreter.
0788:             *
0789:             *----------------------------------------------------------------------
0790:             */
0791:
0792:            public static TclObject newInstance(Interp interp, // Current interpreter.
0793:                    Class cl, // class of the reflect instance
0794:                    Object obj) // java.lang.Object to wrap.
0795:                    throws TclException {
0796:                return new TclObject(makeReflectObject(interp, cl, obj));
0797:            }
0798:
0799:            /*
0800:             *----------------------------------------------------------------------
0801:             *
0802:             * get --
0803:             *
0804:             *	Returns a java.lang.Object represented by tobj. tobj must have a
0805:             *	ReflectObject internal rep, or its string rep must be one of the
0806:             *	currently registered objects.
0807:             *
0808:             * Results:
0809:             *	The Java object represented by tobj.
0810:             *
0811:             * Side effects:
0812:             *	When successful, the internal representation of tobj is
0813:             *	changed to ReflectObject, if it is not already so.
0814:             *
0815:             *----------------------------------------------------------------------
0816:             */
0817:
0818:            public static Object get(Interp interp, // Current interpreter. Must be non-null.
0819:                    TclObject tobj) // The TclObject to query.
0820:                    throws TclException // If the internal rep of tobj cannot
0821:            // be converted to a ReflectObject. 
0822:            // Error message is left inside interp.
0823:            {
0824:                setReflectObjectFromAny(interp, tobj);
0825:                ReflectObject rep = (ReflectObject) tobj.getInternalRep();
0826:                return rep.javaObj;
0827:            }
0828:
0829:            /*
0830:             *----------------------------------------------------------------------
0831:             *
0832:             * getClass --
0833:             *
0834:             *	Returns a java.lang.Class object that is the ref type of this
0835:             *      reflect object. This is not always the same class as is returned
0836:             *      by a call to ((Object) o).getClass().
0837:             *
0838:             * Results:
0839:             *	The Java class object used to reference tobj.
0840:             *
0841:             * Side effects:
0842:             *	When successful, the internal representation of tobj is
0843:             *	changed to ReflectObject, if it is not already so.
0844:             *
0845:             *----------------------------------------------------------------------
0846:             */
0847:
0848:            public static Class getClass(Interp interp, // Current interpreter. Must be non-null.
0849:                    TclObject tobj) // The TclObject to query.
0850:                    throws TclException // If the internal rep of tobj cannot
0851:            // be converted to a ReflectObject. 
0852:            // Error message is left inside interp.
0853:            {
0854:                setReflectObjectFromAny(interp, tobj);
0855:                ReflectObject rep = (ReflectObject) tobj.getInternalRep();
0856:                return rep.javaClass;
0857:            }
0858:
0859:            /*
0860:             *----------------------------------------------------------------------
0861:             *
0862:             * getReflectObject --
0863:             *
0864:             *	Returns the InternalRep of a the ReflectObject represented by
0865:             *	tobj. Only the java:: commands should call this
0866:             *	method. (java::bind, java::call, etc).
0867:             *
0868:             * Results:
0869:             *	The Java object represented by tobj.
0870:             *
0871:             * Side effects:
0872:             *	When successful, the internal representation of tobj is
0873:             *	changed to ReflectObject, if it is not already so.
0874:             *
0875:             *----------------------------------------------------------------------
0876:             */
0877:
0878:            static ReflectObject getReflectObject(Interp interp, // Current interpreter. Must be non-null
0879:                    TclObject tobj) // The TclObject to query.
0880:                    throws TclException // If the internal rep of tobj cannot
0881:            // be converted to a ReflectObject.
0882:            // Error message is left inside interp.
0883:            {
0884:                setReflectObjectFromAny(interp, tobj);
0885:                return (ReflectObject) tobj.getInternalRep();
0886:            }
0887:
0888:            /*
0889:             *----------------------------------------------------------------------
0890:             *
0891:             * cmdProc --
0892:             *
0893:             *	This cmdProc implements the Tcl command used to invoke methods
0894:             *	of the java.lang.Object stored in this ReflectObject internal
0895:             *	rep. For example, this method is called to process the "$v"
0896:             *	command at the second line of this script:
0897:             *
0898:             *	    set v [java::new java.util.Vector]
0899:             *	    $v addElement "foo"
0900:             *
0901:             * Results:
0902:             *	None.
0903:             *
0904:             * Side effects:
0905:             *	If the given method returns a value, it is converted into a
0906:             *	TclObject and stored as the result of the interpreter.
0907:             *
0908:             *----------------------------------------------------------------------
0909:             */
0910:
0911:            public void cmdProc(Interp interp, // Current interpreter.
0912:                    TclObject[] argv) // Argument list.
0913:                    throws TclException // Standard Tcl exception;
0914:            {
0915:                boolean convert;
0916:                int sigIdx;
0917:
0918:                if (!isValid) {
0919:                    throw new TclException(interp,
0920:                            "reflected object is no longer valid");
0921:                }
0922:
0923:                if (argv.length < 2) {
0924:                    throw new TclNumArgsException(interp, 1, argv,
0925:                            "?-noconvert? signature ?arg arg ...?");
0926:                }
0927:
0928:                String arg1 = argv[1].toString();
0929:                if ((arg1.length() >= 2) && (NOCONVERT.startsWith(arg1))) {
0930:                    convert = false;
0931:                    sigIdx = 2;
0932:                } else {
0933:                    convert = true;
0934:                    sigIdx = 1;
0935:                }
0936:
0937:                if (argv.length < sigIdx + 1) {
0938:                    throw new TclNumArgsException(interp, 1, argv,
0939:                            "?-noconvert? signature ?arg arg ...?");
0940:                }
0941:
0942:                int startIdx = sigIdx + 1;
0943:                int count = argv.length - startIdx;
0944:
0945:                TclObject result = JavaInvoke.callMethod(interp, argv[0],
0946:                        argv[sigIdx], argv, startIdx, count, convert);
0947:
0948:                if (result == null)
0949:                    interp.resetResult();
0950:                else
0951:                    interp.setResult(result);
0952:            }
0953:
0954:            /*
0955:             *----------------------------------------------------------------------
0956:             *
0957:             * disposeCmd --
0958:             *
0959:             * 	This method is called when the object command has been deleted
0960:             * 	from an interpreter. It marks the ReflectObject no longer
0961:             * 	accessible from Tcl scripts.
0962:             *
0963:             * Results:
0964:             *	None.
0965:             *
0966:             * Side effects:
0967:             *	The ReflectObject is no longer accessible from Tcl scripts.
0968:             *
0969:             *----------------------------------------------------------------------
0970:             */
0971:
0972:            public void disposeCmd() {
0973:                if (debug) {
0974:                    System.out.println("ReflectObject instance " + refID
0975:                            + " -> disposedCmd()");
0976:                }
0977:
0978:                isValid = false;
0979:            }
0980:
0981:            /*
0982:             *----------------------------------------------------------------------
0983:             *
0984:             * toString --
0985:             *
0986:             *	Called to query the string representation of the Tcl
0987:             *	object. This method is called only by TclObject.toString()
0988:             *	when TclObject.stringRep is null.
0989:             *
0990:             * Results:
0991:             * 	Returns the string representation of this ReflectObject.
0992:             *
0993:             * Side effects:
0994:             *	None.
0995:             *
0996:             *----------------------------------------------------------------------
0997:             */
0998:
0999:            public String toString() {
1000:                return refID;
1001:            }
1002:
1003:        } // end ReflectObject
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.