001: /*
002: * JavaLoadCmd.java --
003: *
004: * This class implements the built-in "java::load" 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: JavaLoadCmd.java,v 1.5 2006/04/13 07:36:50 mdejong Exp $
012: */
013:
014: package tcl.lang;
015:
016: import java.io.File;
017: import java.io.IOException;
018: import java.util.*;
019:
020: class JavaLoadCmd implements Command {
021:
022: // Switches that are legal in this command.
023:
024: private static final String validOpts[] = { "-classpath" };
025:
026: /*
027: *----------------------------------------------------------------------
028: *
029: * cmdProc --
030: *
031: * This procedure is invoked to process the "java::load" Tcl command.
032: * See the user documentation for details on what it does.
033: *
034: * Results:
035: * None
036: *
037: * Side effects:
038: * The interps result is set or a TclException is thrown.
039: *
040: *----------------------------------------------------------------------
041: */
042:
043: public void cmdProc(Interp interp, // the current interpreter.
044: TclObject argv[]) // command arguments.
045: throws TclException // if the package cannot be loaded.
046: {
047: TclClassLoader tclClassLoader;
048: TclObject classpath;
049: String packageName;
050: Class pkgClass;
051: Extension pkg = null;
052: String errorMsg;
053: boolean validLoad = false;
054:
055: if ((argv.length != 2) && (argv.length != 4)) {
056: throw new TclNumArgsException(interp, 1, argv,
057: "?-classpath arg? packageName");
058: }
059:
060: // Populate the classpath array with arguments from command line, if
061: // the -classpath option was specified.
062:
063: if (argv.length == 4) {
064: TclIndex.get(interp, argv[1], validOpts, "switch", 0);
065: classpath = argv[2];
066: packageName = argv[3].toString();
067: } else {
068: classpath = null;
069: packageName = argv[1].toString();
070: }
071:
072: errorMsg = "load \"" + packageName + "\" failed: ";
073:
074: // The class loader dosen't want .class at the end, so strip
075: // it off if it exists.
076:
077: if (packageName.endsWith(".class")) {
078: packageName = packageName.substring(0, packageName
079: .lastIndexOf(".class"));
080: }
081:
082: // When no -classpath argument is given, just use the interp
083: // TclClassLoader which reads values from TCL_CLASSPATH. If
084: // a -classpath argument was given, then defined a TclClassLoader
085: // that will delagate to the interp class loader.
086:
087: if (classpath == null) {
088: tclClassLoader = (TclClassLoader) interp.getClassLoader();
089: } else {
090: tclClassLoader = (TclClassLoader) interp.getClassLoader();
091: tclClassLoader = new TclClassLoader(interp, classpath,
092: tclClassLoader);
093: }
094:
095: // Dynamically load the class
096:
097: try {
098: validLoad = false;
099: pkgClass = tclClassLoader.loadClass(packageName);
100: validLoad = true;
101: } catch (ClassNotFoundException e) {
102: throw new TclException(interp, "package \"" + packageName
103: + "\" not found");
104: } catch (ClassFormatError e) {
105: throw new TclException(interp, errorMsg
106: + "use the fully qualified package name");
107: } catch (PackageNameException e) {
108: throw new TclException(interp, errorMsg + e);
109: } finally {
110: // If we did not have a valid load, the packageName
111: // must be removed from the static tclClassLoader's
112: // cache of loaded classes. If this is not done
113: // any other attempts to load this package will always
114: // use this tclClassLoader and will always fail.
115:
116: if (!validLoad) {
117: tclClassLoader.removeCache(packageName);
118: }
119: }
120:
121: try {
122: // Create an instance of the class. It is important that the class
123: // be casted to a class that was created by the System ClassLoader.
124: // This bridges the super class of the pkgClass with other classes
125: // instantiated by the System ClassLoader.
126:
127: validLoad = false;
128: pkg = (Extension) pkgClass.newInstance();
129:
130: // Initialize the given package. Usually, some new commands will
131: // be created inside the interp.
132:
133: pkg.init(interp);
134: validLoad = true;
135:
136: } catch (IllegalAccessException e) {
137: throw new TclException(interp, errorMsg
138: + "class or initializer is not accessible");
139: } catch (InstantiationException e) {
140: throw new TclException(interp, errorMsg
141: + "object instantiation failure");
142: } catch (ClassCastException e) {
143: throw new TclException(interp, errorMsg
144: + "not a subclass of tcl.lang.Extension");
145: } catch (Exception e) {
146: throw new TclException(interp, errorMsg
147: + "can't find class \"" + e.getMessage() + "\"");
148: } catch (LinkageError e) {
149: // Known to covers these error conditions:
150: // NoClassDefFoundError
151: // ExceptionInInitializerError
152: throw new TclException(interp, "Extension \"" + packageName
153: + "\" contains a dependency \"" + e.getMessage()
154: + "\" that could not be resolved.");
155: } finally {
156: // If we did not have a valid load, the packageName
157: // must be removed from the static tclClassLoader's
158: // cache of loaded classes. If this is not done
159: // any other attempts to load this package will always
160: // use this tclClassLoader and will always fail.
161:
162: if (!validLoad) {
163: tclClassLoader.removeCache(packageName);
164: }
165: }
166: }
167:
168: } // end JavaLoadCmd
|