/*
* JavaLoadCmd.java --
*
* This class implements the built-in "java::load" command in Tcl.
*
* Copyright (c) 1997 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: JavaLoadCmd.java,v 1.5 2006/04/13 07:36:50 mdejong Exp $
*/
package tcl.lang;
import java.io.File;
import java.io.IOException;
import java.util.*;
class JavaLoadCmd implements Command {
// Switches that are legal in this command.
private static final String validOpts[] = {"-classpath"};
/*
*----------------------------------------------------------------------
*
* cmdProc --
*
* This procedure is invoked to process the "java::load" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* None
*
* Side effects:
* The interps result is set or a TclException is thrown.
*
*----------------------------------------------------------------------
*/
public void
cmdProc(
Interp interp, // the current interpreter.
TclObject argv[]) // command arguments.
throws
TclException // if the package cannot be loaded.
{
TclClassLoader tclClassLoader;
TclObject classpath;
String packageName;
Class pkgClass;
Extension pkg = null;
String errorMsg;
boolean validLoad = false;
if ((argv.length != 2) && (argv.length != 4)) {
throw new TclNumArgsException(interp, 1, argv,
"?-classpath arg? packageName");
}
// Populate the classpath array with arguments from command line, if
// the -classpath option was specified.
if (argv.length == 4) {
TclIndex.get(interp, argv[1], validOpts, "switch", 0);
classpath = argv[2];
packageName = argv[3].toString();
} else {
classpath = null;
packageName = argv[1].toString();
}
errorMsg = "load \"" + packageName + "\" failed: ";
// The class loader dosen't want .class at the end, so strip
// it off if it exists.
if (packageName.endsWith(".class")) {
packageName = packageName.substring(0,
packageName.lastIndexOf(".class"));
}
// When no -classpath argument is given, just use the interp
// TclClassLoader which reads values from TCL_CLASSPATH. If
// a -classpath argument was given, then defined a TclClassLoader
// that will delagate to the interp class loader.
if (classpath == null) {
tclClassLoader = (TclClassLoader) interp.getClassLoader();
} else {
tclClassLoader = (TclClassLoader) interp.getClassLoader();
tclClassLoader = new TclClassLoader(interp, classpath, tclClassLoader);
}
// Dynamically load the class
try {
validLoad = false;
pkgClass = tclClassLoader.loadClass(packageName);
validLoad = true;
} catch (ClassNotFoundException e) {
throw new TclException(interp, "package \"" + packageName +
"\" not found");
} catch (ClassFormatError e) {
throw new TclException(interp, errorMsg +
"use the fully qualified package name");
} catch (PackageNameException e) {
throw new TclException(interp, errorMsg + e);
} finally {
// If we did not have a valid load, the packageName
// must be removed from the static tclClassLoader's
// cache of loaded classes. If this is not done
// any other attempts to load this package will always
// use this tclClassLoader and will always fail.
if (!validLoad) {
tclClassLoader.removeCache(packageName);
}
}
try {
// Create an instance of the class. It is important that the class
// be casted to a class that was created by the System ClassLoader.
// This bridges the super class of the pkgClass with other classes
// instantiated by the System ClassLoader.
validLoad = false;
pkg = (Extension)pkgClass.newInstance();
// Initialize the given package. Usually, some new commands will
// be created inside the interp.
pkg.init(interp);
validLoad = true;
} catch (IllegalAccessException e) {
throw new TclException (interp, errorMsg +
"class or initializer is not accessible");
} catch (InstantiationException e) {
throw new TclException (interp, errorMsg +
"object instantiation failure");
} catch (ClassCastException e) {
throw new TclException (interp, errorMsg +
"not a subclass of tcl.lang.Extension");
} catch (Exception e) {
throw new TclException (interp, errorMsg +
"can't find class \"" + e.getMessage() + "\"");
} catch (LinkageError e) {
// Known to covers these error conditions:
// NoClassDefFoundError
// ExceptionInInitializerError
throw new TclException(interp, "Extension \"" +
packageName +
"\" contains a dependency \"" + e.getMessage() +
"\" that could not be resolved.");
} finally {
// If we did not have a valid load, the packageName
// must be removed from the static tclClassLoader's
// cache of loaded classes. If this is not done
// any other attempts to load this package will always
// use this tclClassLoader and will always fail.
if (!validLoad) {
tclClassLoader.removeCache(packageName);
}
}
}
} // end JavaLoadCmd