Source Code Cross Referenced for PackageCmd.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) 


001:        /* 
002:         * PackageCmd.java --
003:         *
004:         *	This class implements the built-in "package" command in Tcl.
005:         *
006:         * Copyright (c) 1997 by Sun Microsystems, Inc.
007:         *
008:         * See the file "license.terms" for information on usage and redistribution
009:         * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
010:         *
011:         * RCS: @(#) $Id: PackageCmd.java,v 1.7 2006/01/26 19:49:18 mdejong Exp $
012:         */
013:
014:        package tcl.lang;
015:
016:        import java.util.*;
017:
018:        class PackageCmd implements  Command {
019:
020:            private static final String[] validCmds = { "forget", "ifneeded",
021:                    "names", "present", "provide", "require", "unknown",
022:                    "vcompare", "versions", "vsatisfies" };
023:
024:            static final private int OPT_FORGET = 0;
025:            static final private int OPT_IFNEEDED = 1;
026:            static final private int OPT_NAMES = 2;
027:            static final private int OPT_PRESENT = 3;
028:            static final private int OPT_PROVIDE = 4;
029:            static final private int OPT_REQUIRE = 5;
030:            static final private int OPT_UNKNOWN = 6;
031:            static final private int OPT_VCOMPARE = 7;
032:            static final private int OPT_VERSIONS = 8;
033:            static final private int OPT_VSATISFIES = 9;
034:
035:            /*
036:             *----------------------------------------------------------------------
037:             *
038:             * pkgProvide --
039:             *
040:             *	This procedure is invoked to declare that a particular version
041:             *	of a particular package is now present in an interpreter.  There
042:             *	must not be any other version of this package already
043:             *	provided in the interpreter.
044:             *
045:             * Results:
046:             *	Normally does nothing; if there is already another version
047:             *	of the package loaded then an error is raised.
048:             *
049:             * Side effects:
050:             *	The interpreter remembers that this package is available,
051:             *	so that no other version of the package may be provided for
052:             *	the interpreter.
053:             *
054:             *----------------------------------------------------------------------
055:             */
056:
057:            static void pkgProvide(Interp interp, // Interpreter in which package is now
058:                    // available. 
059:                    String pkgName, // Name of package. 
060:                    String version) // Version string for package.
061:                    throws TclException {
062:                Package pkg;
063:
064:                // Validate the version string that was passed in.
065:
066:                checkVersion(interp, version);
067:                pkg = findPackage(interp, pkgName);
068:                if (pkg.version == null) {
069:                    pkg.version = version;
070:                    return;
071:                }
072:                if (compareVersions(pkg.version, version, null) != 0) {
073:                    throw new TclException(interp,
074:                            "conflicting versions provided for package \""
075:                                    + pkgName + "\": " + pkg.version
076:                                    + ", then " + version);
077:                }
078:            }
079:
080:            /*
081:             *----------------------------------------------------------------------
082:             *
083:             * pkgRequire --
084:             *
085:             *	This procedure is called by code that depends on a particular
086:             *	version of a particular package.  If the package is not already
087:             *	provided in the interpreter, this procedure invokes a Tcl script
088:             *	to provide it.  If the package is already provided, this
089:             *	procedure makes sure that the caller's needs don't conflict with
090:             *	the version that is present.
091:             *
092:             * Results:
093:             *	If successful, returns the version string for the currently
094:             *	provided version of the package, which may be different from
095:             *	the "version" argument.  If the caller's requirements
096:             *	cannot be met (e.g. the version requested conflicts with
097:             *	a currently provided version, or the required version cannot
098:             *	be found, or the script to provide the required version
099:             *	generates an error), a TclException is raised.
100:             *
101:             * Side effects:
102:             *	The script from some previous "package ifneeded" command may
103:             *	be invoked to provide the package.
104:             *
105:             *----------------------------------------------------------------------
106:             */
107:
108:            static String pkgRequire(Interp interp, // Interpreter in which package is now
109:                    // available.
110:                    String pkgName, // Name of desired package.
111:                    String version, // Version string for desired version;
112:                    // null means use the latest version
113:                    // available.
114:                    boolean exact) // true means that only the particular
115:                    // version given is acceptable. false means
116:                    // use the latest compatible version.
117:                    throws TclException {
118:                VersionSatisfiesResult vsres;
119:                Package pkg;
120:                PkgAvail avail, best;
121:                String script;
122:                StringBuffer sbuf;
123:                int pass, result;
124:
125:                // Do extra check to make sure that version is not
126:                // null when the exact flag is set to true.
127:
128:                if (version == null && exact) {
129:                    throw new TclException(interp,
130:                            "conflicting arguments : version == null and exact == true");
131:                }
132:
133:                // Before we can compare versions the version string
134:                // must be verified but if it is null we are just looking
135:                // for the latest version so skip the check in this case.
136:
137:                if (version != null) {
138:                    checkVersion(interp, version);
139:                }
140:
141:                // It can take up to three passes to find the package:  one pass to
142:                // run the "package unknown" script, one to run the "package ifneeded"
143:                // script for a specific version, and a final pass to lookup the
144:                // package loaded by the "package ifneeded" script.
145:
146:                vsres = new VersionSatisfiesResult();
147:                for (pass = 1;; pass++) {
148:                    pkg = findPackage(interp, pkgName);
149:                    if (pkg.version != null) {
150:                        break;
151:                    }
152:
153:                    // The package isn't yet present.  Search the list of available
154:                    // versions and invoke the script for the best available version.
155:
156:                    best = null;
157:                    for (avail = pkg.avail; avail != null; avail = avail.next) {
158:                        if ((best != null)
159:                                && (compareVersions(avail.version,
160:                                        best.version, null) <= 0)) {
161:                            continue;
162:                        }
163:                        if (version != null) {
164:                            result = compareVersions(avail.version, version,
165:                                    vsres);
166:                            if ((result != 0) && exact) {
167:                                continue;
168:                            }
169:                            if (!vsres.satisfies) {
170:                                continue;
171:                            }
172:                        }
173:                        best = avail;
174:                    }
175:                    if (best != null) {
176:                        // We found an ifneeded script for the package.  Be careful while
177:                        // executing it:  this could cause reentrancy, so (a) protect the
178:                        // script itself from deletion and (b) don't assume that best
179:                        // will still exist when the script completes.
180:
181:                        script = best.script;
182:                        try {
183:                            interp.eval(script, TCL.EVAL_GLOBAL);
184:                        } catch (TclException e) {
185:                            interp
186:                                    .addErrorInfo("\n    (\"package ifneeded\" script)");
187:
188:                            // Throw the error with new info added to errorInfo.
189:
190:                            throw e;
191:                        }
192:                        interp.resetResult();
193:                        pkg = findPackage(interp, pkgName);
194:                        break;
195:                    }
196:
197:                    // Package not in the database.  If there is a "package unknown"
198:                    // command, invoke it (but only on the first pass;  after that,
199:                    // we should not get here in the first place).
200:
201:                    if (pass > 1) {
202:                        break;
203:                    }
204:                    script = interp.packageUnknown;
205:                    if (script != null) {
206:                        sbuf = new StringBuffer();
207:                        try {
208:                            Util.appendElement(interp, sbuf, script);
209:                            Util.appendElement(interp, sbuf, pkgName);
210:                            if (version == null) {
211:                                Util.appendElement(interp, sbuf, "");
212:                            } else {
213:                                Util.appendElement(interp, sbuf, version);
214:                            }
215:                            if (exact) {
216:                                Util.appendElement(interp, sbuf, "-exact");
217:                            }
218:                        } catch (TclException e) {
219:                            throw new TclRuntimeError(
220:                                    "unexpected TclException: " + e);
221:                        }
222:                        try {
223:                            interp.eval(sbuf.toString(), TCL.EVAL_GLOBAL);
224:                        } catch (TclException e) {
225:                            interp
226:                                    .addErrorInfo("\n    (\"package unknown\" script)");
227:
228:                            // Throw the first exception.
229:
230:                            throw e;
231:                        }
232:                        interp.resetResult();
233:                    }
234:                }
235:                if (pkg.version == null) {
236:                    sbuf = new StringBuffer();
237:                    sbuf.append("can't find package " + pkgName);
238:                    if (version != null) {
239:                        sbuf.append(" " + version);
240:                    }
241:                    throw new TclException(interp, sbuf.toString());
242:                }
243:
244:                // At this point we know that the package is present.  Make sure that the
245:                // provided version meets the current requirement.
246:
247:                if (version == null) {
248:                    return pkg.version;
249:                }
250:
251:                result = compareVersions(pkg.version, version, vsres);
252:                if ((vsres.satisfies && !exact) || (result == 0)) {
253:                    return pkg.version;
254:                }
255:
256:                // If we have a version conflict we throw a TclException.
257:
258:                throw new TclException(interp,
259:                        "version conflict for package \"" + pkgName
260:                                + "\": have " + pkg.version + ", need "
261:                                + version);
262:            }
263:
264:            /*
265:             *----------------------------------------------------------------------
266:             *
267:             * Tcl_PkgPresent -> pkgPresent
268:             *
269:             *	Checks to see whether the specified package is present. If it
270:             *	is not then no additional action is taken.
271:             *
272:             * Results:
273:             *	If successful, returns the version string for the currently
274:             *	provided version of the package, which may be different from
275:             *	the "version" argument.  If the caller's requirements
276:             *	cannot be met (e.g. the version requested conflicts with
277:             *	a currently provided version), a TclException is raised.
278:             *
279:             * Side effects:
280:             *	None.
281:             *
282:             *----------------------------------------------------------------------
283:             */
284:            static String pkgPresent(Interp interp, // Interpreter in which package is now
285:                    // available.
286:                    String pkgName, // Name of desired package.
287:                    String version, // Version string for desired version;
288:                    // null means use the latest version
289:                    // available.
290:                    boolean exact) // true means that only the particular
291:                    // version given is acceptable. false means
292:                    // use the latest compatible version.
293:                    throws TclException {
294:                Package pkg;
295:                VersionSatisfiesResult vsres = new VersionSatisfiesResult();
296:                int result;
297:
298:                pkg = (Package) interp.packageTable.get(pkgName);
299:                if (pkg != null) {
300:                    if (pkg.version != null) {
301:
302:                        // At this point we know that the package is present.  Make sure
303:                        // that the provided version meets the current requirement.
304:
305:                        if (version == null) {
306:                            return pkg.version;
307:                        }
308:                        result = compareVersions(pkg.version, version, vsres);
309:                        if ((vsres.satisfies && !exact) || (result == 0)) {
310:                            return pkg.version;
311:                        }
312:                        throw new TclException(interp,
313:                                "version conflict for package \"" + pkgName
314:                                        + "\": have " + pkg.version + ", need "
315:                                        + version);
316:                    }
317:                }
318:
319:                if (version != null) {
320:                    throw new TclException(interp, "package " + pkgName + " "
321:                            + version + " is not present");
322:                } else {
323:                    throw new TclException(interp, "package " + pkgName
324:                            + " is not present");
325:                }
326:            }
327:
328:            /*
329:             *----------------------------------------------------------------------
330:             *
331:             * cmdProc --
332:             *
333:             *	This procedure is invoked to process the "package" Tcl command.
334:             *	See the user documentation for details on what it does.
335:             *
336:             * Side effects:
337:             *	|>None.<|
338:             *
339:             *----------------------------------------------------------------------
340:             */
341:
342:            public void cmdProc(Interp interp, // The current interpreter.
343:                    TclObject[] objv) // Command arguments.
344:                    throws TclException // Thrown if an error occurs.
345:            {
346:                VersionSatisfiesResult vsres;
347:                Package pkg;
348:                PkgAvail avail;
349:                PkgAvail prev;
350:                String version;
351:                String pkgName;
352:                String key;
353:                String cmd;
354:                String ver1, ver2;
355:                StringBuffer sbuf;
356:                Enumeration e;
357:                int i, opt, exact;
358:                boolean once;
359:
360:                if (objv.length < 2) {
361:                    throw new TclNumArgsException(interp, 1, objv,
362:                            "option ?arg arg ...?");
363:                }
364:                opt = TclIndex.get(interp, objv[1], validCmds, "option", 0);
365:                switch (opt) {
366:                case OPT_FORGET: {
367:                    // Forget takes 0 or more arguments.
368:
369:                    for (i = 2; i < objv.length; i++) {
370:                        // We do not need to check to make sure
371:                        // package name is "" because it would not
372:                        // be in the hash table so name will be ignored.
373:
374:                        pkgName = objv[i].toString();
375:                        pkg = (Package) interp.packageTable.get(pkgName);
376:
377:                        // If this package does not exist, go to next one.
378:
379:                        if (pkg == null) {
380:                            continue;
381:                        }
382:                        interp.packageTable.remove(pkgName);
383:                        while (pkg.avail != null) {
384:                            avail = pkg.avail;
385:                            pkg.avail = avail.next;
386:                            avail = null;
387:                        }
388:                        pkg = null;
389:                    }
390:                    return;
391:                }
392:                case OPT_IFNEEDED: {
393:                    if ((objv.length < 4) || (objv.length > 5)) {
394:                        throw new TclNumArgsException(interp, 1, objv,
395:                                "ifneeded package version ?script?");
396:                    }
397:                    pkgName = objv[2].toString();
398:                    version = objv[3].toString();
399:
400:                    // Verify that this version string is valid.
401:
402:                    checkVersion(interp, version);
403:                    if (objv.length == 4) {
404:                        pkg = (Package) interp.packageTable.get(pkgName);
405:                        if (pkg == null)
406:                            return;
407:
408:                    } else {
409:                        pkg = findPackage(interp, pkgName);
410:                    }
411:                    for (avail = pkg.avail, prev = null; avail != null; prev = avail, avail = avail.next) {
412:                        if (compareVersions(avail.version, version, null) == 0) {
413:                            if (objv.length == 4) {
414:                                // If doing a query return current script.
415:
416:                                interp.setResult(avail.script);
417:                                return;
418:                            }
419:
420:                            // We matched so we must be setting the script.
421:
422:                            break;
423:                        }
424:                    }
425:
426:                    // When we do not match on a query return nothing.
427:
428:                    if (objv.length == 4) {
429:                        return;
430:                    }
431:                    if (avail == null) {
432:                        avail = new PkgAvail();
433:                        avail.version = version;
434:                        if (prev == null) {
435:                            avail.next = pkg.avail;
436:                            pkg.avail = avail;
437:                        } else {
438:                            avail.next = prev.next;
439:                            prev.next = avail;
440:                        }
441:                    }
442:                    avail.script = objv[4].toString();
443:                    return;
444:                }
445:                case OPT_NAMES: {
446:                    if (objv.length != 2) {
447:                        throw new TclNumArgsException(interp, 1, objv, "names");
448:                    }
449:
450:                    try {
451:                        sbuf = new StringBuffer();
452:                        once = false;
453:                        for (Iterator iter = interp.packageTable.entrySet()
454:                                .iterator(); iter.hasNext();) {
455:                            Map.Entry entry = (Map.Entry) iter.next();
456:                            key = (String) entry.getKey();
457:                            pkg = (Package) entry.getValue();
458:                            once = true;
459:                            if ((pkg.version != null) || (pkg.avail != null)) {
460:                                Util.appendElement(interp, sbuf, key);
461:                            }
462:                        }
463:                        if (once) {
464:                            interp.setResult(sbuf.toString());
465:                        }
466:                    } catch (TclException ex) {
467:                        throw new TclRuntimeError("unexpected TclException: "
468:                                + ex);
469:                    }
470:                    return;
471:                }
472:                case OPT_PRESENT: {
473:                    if (objv.length < 3) {
474:                        throw new TclNumArgsException(interp, 2, objv,
475:                                "?-exact? package ?version?");
476:                    }
477:                    if (objv[2].toString().equals("-exact")) {
478:                        exact = 1;
479:                    } else {
480:                        exact = 0;
481:                    }
482:
483:                    version = null;
484:                    if (objv.length == (4 + exact)) {
485:                        version = objv[3 + exact].toString();
486:                        checkVersion(interp, version);
487:                    } else if ((objv.length != 3) || (exact == 1)) {
488:                        throw new TclNumArgsException(interp, 2, objv,
489:                                "?-exact? package ?version?");
490:                    }
491:                    if (exact == 1) {
492:                        version = pkgPresent(interp, objv[3].toString(),
493:                                version, true);
494:                    } else {
495:                        version = pkgPresent(interp, objv[2].toString(),
496:                                version, false);
497:                    }
498:                    interp.setResult(version);
499:                    break;
500:                }
501:                case OPT_PROVIDE: {
502:                    if ((objv.length < 3) || (objv.length > 4)) {
503:                        throw new TclNumArgsException(interp, 1, objv,
504:                                "provide package ?version?");
505:                    }
506:                    if (objv.length == 3) {
507:                        pkg = (Package) interp.packageTable.get(objv[2]
508:                                .toString());
509:                        if (pkg != null) {
510:                            if (pkg.version != null) {
511:                                interp.setResult(pkg.version);
512:                            }
513:                        }
514:                        return;
515:                    }
516:                    pkgProvide(interp, objv[2].toString(), objv[3].toString());
517:                    return;
518:                }
519:                case OPT_REQUIRE: {
520:                    if ((objv.length < 3) || (objv.length > 5)) {
521:                        throw new TclNumArgsException(interp, 1, objv,
522:                                "require ?-exact? package ?version?");
523:                    }
524:                    if (objv[2].toString().equals("-exact")) {
525:                        exact = 1;
526:                    } else {
527:                        exact = 0;
528:                    }
529:                    version = null;
530:                    if (objv.length == (4 + exact)) {
531:                        version = objv[3 + exact].toString();
532:                        checkVersion(interp, version);
533:                    } else if ((objv.length != 3) || (exact == 1)) {
534:                        throw new TclNumArgsException(interp, 1, objv,
535:                                "require ?-exact? package ?version?");
536:                    }
537:                    if (exact == 1) {
538:                        version = pkgRequire(interp, objv[3].toString(),
539:                                version, true);
540:                    } else {
541:                        version = pkgRequire(interp, objv[2].toString(),
542:                                version, false);
543:                    }
544:                    interp.setResult(version);
545:                    return;
546:                }
547:                case OPT_UNKNOWN: {
548:                    if (objv.length > 3) {
549:                        throw new TclNumArgsException(interp, 1, objv,
550:                                "unknown ?command?");
551:                    }
552:                    if (objv.length == 2) {
553:                        if (interp.packageUnknown != null) {
554:                            interp.setResult(interp.packageUnknown);
555:                        }
556:                    } else if (objv.length == 3) {
557:                        interp.packageUnknown = null;
558:                        cmd = objv[2].toString();
559:                        if (cmd.length() > 0) {
560:                            interp.packageUnknown = cmd;
561:                        }
562:                    }
563:                    return;
564:                }
565:                case OPT_VCOMPARE: {
566:                    if (objv.length != 4) {
567:                        throw new TclNumArgsException(interp, 1, objv,
568:                                "vcompare version1 version2");
569:                    }
570:                    ver1 = objv[2].toString();
571:                    ver2 = objv[3].toString();
572:                    checkVersion(interp, ver1);
573:                    checkVersion(interp, ver2);
574:                    interp.setResult(compareVersions(ver1, ver2, null));
575:                    return;
576:                }
577:                case OPT_VERSIONS: {
578:                    if (objv.length != 3) {
579:                        throw new TclNumArgsException(interp, 1, objv,
580:                                "versions package");
581:                    }
582:                    pkg = (Package) interp.packageTable.get(objv[2].toString());
583:                    if (pkg != null) {
584:                        try {
585:                            sbuf = new StringBuffer();
586:                            once = false;
587:                            for (avail = pkg.avail; avail != null; avail = avail.next) {
588:                                once = true;
589:                                Util.appendElement(interp, sbuf, avail.version);
590:                            }
591:                            if (once) {
592:                                interp.setResult(sbuf.toString());
593:                            }
594:                        } catch (TclException ex) {
595:                            throw new TclRuntimeError(
596:                                    "unexpected TclException: " + ex);
597:                        }
598:                    }
599:                    return;
600:                }
601:                case OPT_VSATISFIES: {
602:                    if (objv.length != 4) {
603:                        throw new TclNumArgsException(interp, 1, objv,
604:                                "vsatisfies version1 version2");
605:                    }
606:
607:                    ver1 = objv[2].toString();
608:                    ver2 = objv[3].toString();
609:                    checkVersion(interp, ver1);
610:                    checkVersion(interp, ver2);
611:                    vsres = new VersionSatisfiesResult();
612:                    compareVersions(ver1, ver2, vsres);
613:                    interp.setResult(vsres.satisfies);
614:                    return;
615:                }
616:                default: {
617:                    throw new TclRuntimeError("TclIndex.get() error");
618:                }
619:                } // end switch(opt)
620:            }
621:
622:            /*
623:             *----------------------------------------------------------------------
624:             *
625:             * findPackage --
626:             *
627:             *	This procedure finds the Package record for a particular package
628:             *	in a particular interpreter, creating a record if one doesn't
629:             *	already exist.
630:             *
631:             * Results:
632:             *	The return value is a ref to the Package record for the
633:             *	package.
634:             *
635:             * Side effects:
636:             *	A new Package record may be created.
637:             *
638:             *----------------------------------------------------------------------
639:             */
640:
641:            private static Package findPackage(Interp interp, // Interpreter to use for package lookup.
642:                    String pkgName) // Name of package to find. 
643:                    throws TclException {
644:                Package pkg;
645:
646:                // check package name to make sure it is not null or "".
647:
648:                if (pkgName == null || pkgName.length() == 0) {
649:                    throw new TclException(interp,
650:                            "expected package name but got \"\"");
651:                }
652:
653:                pkg = (Package) interp.packageTable.get(pkgName);
654:                if (pkg == null) {
655:                    // We should add a package with this name.
656:
657:                    pkg = new Package();
658:                    interp.packageTable.put(pkgName, pkg);
659:                }
660:                return pkg;
661:            }
662:
663:            /*
664:             *----------------------------------------------------------------------
665:             *
666:             * checkVersion --
667:             *
668:             *	This procedure checks to see whether a version number has
669:             *	valid syntax.
670:             *
671:             * Results:
672:             *	If string is not properly formed version number then a TclException
673:             *      is raised.
674:             *
675:             * Side effects:
676:             *	None.
677:             *
678:             *----------------------------------------------------------------------
679:             */
680:
681:            private static void checkVersion(Interp interp, // Used for error reporting.
682:                    String version) // Supposedly a version number, which is
683:                    // groups of decimal digits separated
684:                    // by dots.
685:                    throws TclException {
686:                int i, len;
687:                char c, prevChar;
688:                boolean error = true;
689:
690:                try {
691:                    if ((version == null) || (version.length() == 0)) {
692:                        version = "";
693:                        return;
694:                    }
695:                    if (!Character.isDigit(version.charAt(0))) {
696:                        return;
697:                    }
698:                    len = version.length();
699:                    for (prevChar = version.charAt(0), i = 1; i < len; i++) {
700:                        c = version.charAt(i);
701:                        if (!Character.isDigit(c)
702:                                && ((c != '.') || (prevChar == '.'))) {
703:                            return;
704:                        }
705:                        prevChar = c;
706:                    }
707:                    if (prevChar != '.') {
708:                        error = false;
709:                        return;
710:                    }
711:                } finally {
712:                    if (error) {
713:                        throw new TclException(interp,
714:                                "expected version number but got \"" + version
715:                                        + "\"");
716:                    }
717:                }
718:            }
719:
720:            /*
721:             *----------------------------------------------------------------------
722:             *
723:             * compareVersions --
724:             *
725:             *	This procedure compares two version numbers.
726:             *
727:             * Results:
728:             *      This function will return a -1 if v1 is less than v2, 0
729:             *      if the two version numbers are the same, and 1 if v1 is
730:             *      greater than v2. If the sat argument is not null then
731:             *      then its VersionSatisfiesResult.satisifes field will be
732:             *      true if v2 >= v1 and both numbers have the same major number
733:             *	or false otherwise.
734:             *
735:             * Side effects:
736:             *	None.
737:             *
738:             *----------------------------------------------------------------------
739:             */
740:
741:            private static int compareVersions(String v1, // Versions strings. (e.g.  2.1.3)
742:                    String v2, VersionSatisfiesResult vsres)
743:
744:            {
745:                int i;
746:                int max;
747:                int n1 = 0;
748:                int n2 = 0;
749:                boolean this IsMajor = true;
750:                String[] v1ns;
751:                String[] v2ns;
752:
753:                // Each iteration of the following loop processes one number from
754:                // each string, terminated by a ".".  If those numbers don't match
755:                // then the comparison is over;  otherwise, we loop back for the
756:                // next number.
757:
758:                // This should never happen because null strings would not
759:                // have gotten past the version verify.
760:
761:                if ((v1 == null) || (v2 == null)) {
762:                    throw new TclRuntimeError(
763:                            "null version in package version compare");
764:                }
765:                v1ns = split(v1, '.');
766:                v2ns = split(v2, '.');
767:
768:                // We are sure there is at least one string in each array so 
769:                // this should never happen.
770:
771:                if (v1ns.length == 0 || v2ns.length == 0) {
772:                    throw new TclRuntimeError("version length is 0");
773:                }
774:                if (v1ns.length > v2ns.length) {
775:                    max = v1ns.length;
776:                } else {
777:                    max = v2ns.length;
778:                }
779:
780:                for (i = 0; i < max; i++) {
781:                    n1 = n2 = 0;
782:
783:                    // Grab number from each version ident if version spec
784:                    // ends the use a 0 as value.
785:
786:                    try {
787:                        if (i < v1ns.length) {
788:                            n1 = Integer.parseInt(v1ns[i]);
789:                        }
790:                        if (i < v2ns.length) {
791:                            n2 = Integer.parseInt(v2ns[i]);
792:                        }
793:                    } catch (NumberFormatException ex) {
794:                        throw new TclRuntimeError(
795:                                "NumberFormatException for package versions \""
796:                                        + v1 + "\" or \"" + v2 + "\"");
797:                    }
798:
799:                    // Compare and go on to the next version number if the
800:                    // current numbers match.
801:
802:                    if (n1 != n2) {
803:                        break;
804:                    }
805:                    this IsMajor = false;
806:                }
807:                if (vsres != null) {
808:                    vsres.satisfies = ((n1 == n2) || ((n1 > n2) && !this IsMajor));
809:                }
810:                if (n1 > n2) {
811:                    return 1;
812:                } else if (n1 == n2) {
813:                    return 0;
814:                } else {
815:                    return -1;
816:                }
817:            }
818:
819:            /*
820:             *----------------------------------------------------------------------
821:             *
822:             * split --
823:             *
824:             *	Util function used in version compare to split a string on a
825:             *	single char it is only used in the version compare function.
826:             *
827:             * Results:
828:             *	|>None.<|
829:             *
830:             * Side effects:
831:             *	|>None.<|
832:             *
833:             *----------------------------------------------------------------------
834:             */
835:
836:            static String[] split(String in, char splitchar) {
837:                ArrayList words;
838:                int i;
839:                int len;
840:                char[] str;
841:                int wordstart = 0;
842:
843:                // Create an array that is as big as the input
844:                // str plus one for an extra split char.
845:
846:                len = in.length();
847:                str = new char[len + 1];
848:                in.getChars(0, len, str, 0);
849:                str[len++] = splitchar;
850:                words = new ArrayList(5);
851:
852:                for (i = 0; i < len; i++) {
853:
854:                    // Compare this char to the split char
855:                    // if they are the same the we need to
856:                    // add the last word to the array.
857:
858:                    if (str[i] == splitchar) {
859:                        if (wordstart <= (i - 1)) {
860:                            words
861:                                    .add(new String(str, wordstart, i
862:                                            - wordstart));
863:                        }
864:                        wordstart = (i + 1);
865:                    }
866:                }
867:
868:                // Create an array that is as big as the number
869:                // of elements in the vector, copy over and return.
870:
871:                String[] ret = { (String) null };
872:                ret = (String[]) words.toArray(ret);
873:                return ret;
874:            }
875:
876:            // If compare versions is called with a third argument then one of
877:            // these structures needs to be created and passed in
878:
879:            static class VersionSatisfiesResult {
880:                boolean satisfies = false;
881:            }
882:
883:            // Each invocation of the "package ifneeded" command creates a class
884:            // of the following type, which is used to load the package into the
885:            // interpreter if it is requested with a "package require" command.
886:
887:            static class PkgAvail {
888:                String version = null; // Version string.
889:                String script = null; // Script to invoke to provide this package version
890:                PkgAvail next = null; // Next in list of available package versions
891:            }
892:
893:            // For each package that is known in any way to an interpreter, there
894:            // is one record of the following type.  These records are stored in
895:            // the "packageTable" hash table in the interpreter, keyed by
896:            // package name such as "Tk" (no version number).
897:
898:            static class Package {
899:                String version = null; // Version that has been supplied in this
900:                // interpreter via "package provide"
901:                // null means the package doesn't
902:                // exist in this interpreter yet.
903:
904:                PkgAvail avail = null; // First in list of all available package versions
905:            }
906:
907:        } //end of class PackageCmd
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.