Thread: [tcljava-dev] Patch: java::import -classpath -resolve
Brought to you by:
mdejong
From: Tom P. <tpo...@ny...> - 2003-04-09 04:08:44
|
Here's a patch to java::import that adds -classpath and -resolve options. The -classpath option specifies a specific classpath and/or jar files from which to load the classes being imported. The -resolve passes the 'resolve' flag to the class loader (see docs for java.lang.ClassLoader.loadClass() ). Updated docs included. I'm using these options in my Hyde package that I hope to finally get released RSN. -- Tom Poindexter tpo...@ny... http://www.nyx.net/~tpoindex/ diff -u -r tcljava.cvs/docs/TclJava/ClassLoading.html tcljava.tp/docs/TclJava/ClassLoading.html --- tcljava.cvs/docs/TclJava/ClassLoading.html 2002-10-08 22:38:44.000000000 -0600 +++ tcljava.tp/docs/TclJava/ClassLoading.html 2003-04-08 21:21:04.000000000 -0600 @@ -44,7 +44,8 @@ files specified by <I>pathList</I>. (Available only for the <B>java::load</B> command.) <P><DT>[4]<DD> Search <I>pathList</I> again, inspecting all jar files found in -each directory. (Available only for the <B>java::load</B> command.) +each directory. (Available for the <B>java::load</B> and +<B>java::import</B>commands.) <P><DT>[5]<DD> Search the <B>env(TCL_CLASSPATH)</B> list, looking only in directories or jar files specified by <B>env(TCL_CLASSPATH)</B>. @@ -103,4 +104,4 @@ </BODY> -</HTML> \ No newline at end of file +</HTML> diff -u -r tcljava.cvs/docs/TclJava/JavaImportCmd.html tcljava.tp/docs/TclJava/JavaImportCmd.html --- tcljava.cvs/docs/TclJava/JavaImportCmd.html 2003-03-12 20:15:00.000000000 -0700 +++ tcljava.tp/docs/TclJava/JavaImportCmd.html 2003-04-08 21:23:05.000000000 -0600 @@ -18,7 +18,7 @@ Usage: </H3> -<DD><B>java::import</B> ?<B>-forget</B>? ?<B>-package</B> <I>pkg</I>? ?<I>class ...</I>? +<DD><B>java::import</B> ?<B>-forget</B>? ?<B>-resolve</B>? ?<B>-classpath</B> <I>pathList</I>? ?<B>-package</B> <I>pkg</I>? ?<I>class ...</I>? <P> @@ -36,6 +36,13 @@ specifier, meaning the '.' character must not appear in a <I>class</I> name. <P> +The <B>-classpath</B> <I>pathList</I> argument specifies a Tcl list of +directories and/or Jar files to search during class loading. If +<B>-classpath</B> <I>pathList</I> is omitted, the class loader will +search for the class on using <B>CLASSPATH</B> and +<B>env(TCL_CLASSPATH)</B>. Refer to +<A HREF="ClassLoading.html">Class Loading</A> for additional information. +<P> If the <B>java::import</B> command is invoked with no arguments it will return a list of all the currently imported classes. If the <B>java::import</B> @@ -51,6 +58,11 @@ <P> +The <B>-resolve</B> argument will cause the class loader to perform +resolution and linking steps for the classes being imported. + +<P> + </DL> <DL> diff -u -r tcljava.cvs/src/tcljava/tcl/lang/JavaImportCmd.java tcljava.tp/src/tcljava/tcl/lang/JavaImportCmd.java --- tcljava.cvs/src/tcljava/tcl/lang/JavaImportCmd.java 2003-03-12 20:15:27.000000000 -0700 +++ tcljava.tp/src/tcljava/tcl/lang/JavaImportCmd.java 2003-04-08 21:16:28.000000000 -0600 @@ -22,9 +22,20 @@ import java.util.*; - public class JavaImportCmd implements Command { +static final private String validOpts[] = { + "-resolve", + "-forget", + "-package", + "-classpath" +}; + +static final private int RESOLVE = 0; +static final private int FORGET = 1; +static final private int PACKAGE = 2; +static final private int CLASSPATH = 3; + /* *---------------------------------------------------------------------- * @@ -50,7 +61,7 @@ throws TclException // A standard Tcl exception. { - final String usage = "java::import ?-forget? ?-package pkg? ?class ...?"; + final String usage = "java::import ?-resolve? ?-forget? ?-package pkg? ?-classpath pathList? ?class ...?"; Hashtable classTable = interp.importTable[0]; Hashtable packageTable = interp.importTable[1]; @@ -61,6 +72,9 @@ Enumeration search, search2; String elem, elem2; int startIdx, i; + boolean resolve = false; + TclObject classPath = null; + int opt; // If there are no args simply return all the imported classes if (objv.length == 1) { @@ -75,15 +89,61 @@ interp.setResult(import_list); return; } - - // See if there is a -forget argument + + // process args startIdx = 1; elem = objv[startIdx].toString(); - if (elem.equals("-forget")) { - forget = true; + while (elem.charAt(0) == '-' && startIdx < objv.length) { + try { + opt = TclIndex.get(interp, objv[startIdx], validOpts, "option", 0); + } catch (TclException e) { + throw new TclException(interp, "bad option \"" + objv[startIdx] + + "\": " + usage); + } + switch (opt) { + case RESOLVE: + resolve = true; + break; + case FORGET: + forget = true; + break; + case PACKAGE: + if (startIdx + 1 < objv.length) { + pkg = objv[startIdx + 1].toString(); + if (pkg.length() == 0) { + throw new TclException(interp, + "-package \"pkg\" not specified: " + usage); + } + startIdx++; + } else { + throw new TclException(interp, + "-package \"pkg\" not specified: " + usage); + } + break; + case CLASSPATH: + if (startIdx + 1 < objv.length) { + classPath = objv[startIdx + 1]; + startIdx++; + } else { + throw new TclException(interp, + " -classpath \"arg\" not specified: " + usage); + } + break; + } + startIdx++; + if (startIdx < objv.length) { + elem = objv[startIdx].toString(); + } } + // check for mutally exclusive -resolve -forget + if (forget && resolve) { + throw new TclException(interp, + "-forget and -resolve are mutually exclusive: " + usage); + } + + // When -forget is given with no arguments, we simply // return. This is needed to support the following usage. // @@ -97,36 +157,13 @@ } - // Figure out if the "-package pkg" arguments are given - elem = objv[startIdx].toString(); - if (elem.equals("-package")) { - startIdx++; - - // "java::import -package" is not a valid usage - // "java::import -forget -package" is not a valid usage - if (startIdx >= objv.length) { - throw new TclException(interp, usage); - } - - pkg = objv[startIdx].toString(); - if (pkg.length() == 0) { - throw new TclException(interp, usage); - } - startIdx++; - } - - - // No additional arguments means we have hit one of - // two conditions. - // - // "java::import -forget -package pkg" - // "java::import -package pkg" + // No additional options, process class arguments if (startIdx >= objv.length) { if (forget) { // We must have "java::import -forget -package pkg" - // Ceck that it is not "java::import -forget" which is invalid! + // Check that it is not "java::import -forget" which is invalid! if (pkg == null) { throw new TclException(interp, usage); } @@ -225,7 +262,7 @@ operation = "forget"; } - TclClassLoader tclClassLoader = new TclClassLoader(interp, null); + TclClassLoader tclClassLoader = new TclClassLoader(interp, classPath); // Start processing class arguments begining at startIdx. @@ -275,6 +312,7 @@ fullyqualified = pkg + "." + elem; } + // split the fullyqualified name into a package and class // by looking for the last '.' character in the string. // If there is no '.' in the string the class is in the @@ -307,7 +345,7 @@ boolean inGlobal = true; try { - tclClassLoader.loadClass(class_name); + tclClassLoader.loadClass(class_name, resolve); } catch (ClassNotFoundException e) { inGlobal = false; tclClassLoader.removeCache(class_name); @@ -328,7 +366,7 @@ "\", it does not exist"); try { - Class c = tclClassLoader.loadClass(fullyqualified); + Class c = tclClassLoader.loadClass(fullyqualified, resolve); if (!PkgInvoker.isAccessible(c)) { throw new TclException(interp, "Class \"" + c.getName() + "\" is not accessible"); |
From: Mo D. <md...@un...> - 2003-04-09 08:10:49
|
On Tue, 8 Apr 2003 22:07:41 -0600 Tom Poindexter <tpo...@ny...> wrote: > Here's a patch to java::import that adds -classpath and -resolve options. > The -classpath option specifies a specific classpath and/or jar files from > which to load the classes being imported. The -resolve passes the > 'resolve' flag to the class loader (see docs for > java.lang.ClassLoader.loadClass() ). I must admit, I don't like the idea of adding a -classpath option to the import command. The java::import command is meant to act like the import statement in Java, in that it allows using a short name for a class instead of the fully qualified name. What is wrong with setting the CLASSPATH or the TCL_CLASSPATH env var before running the java::import command? I also don't see how this -resolve flag fits in with the functionality of the import command. In what situation would one want to pass this -resolve flag, and in what situation would one not want it passed? Why would we want to expose this feature at the script level? I read over the JDK docs but they were not very clear on exactly what the resolve really does. It seems one needs to read the JVM book to find out what "the class is linked" means. Mo |
From: Tom P. <tpo...@ny...> - 2003-04-09 14:40:14
|
On Wed, Apr 09, 2003 at 01:14:00AM -0700, Mo DeJong wrote: > On Tue, 8 Apr 2003 22:07:41 -0600 > I must admit, I don't like the idea of adding a -classpath option to the > import command. The java::import command is meant to act like the > import statement in Java, in that it allows using a short name for > a class instead of the fully qualified name. > > What is wrong with setting the CLASSPATH or the TCL_CLASSPATH env > var before running the java::import command? I'd like to be able to specify from where to load a class in my Hyde package. I'm now using the Pizza compiler (pizzacompiler.sf.net) as an in-process compiler for Hyde. I also would like to make Hyde as 'package friendly' as possible, not distrubing global environment's CLASSPATH or TCL_CLASSPATH. With this patch, along with my previous patches to set a Jacl library path and append that path in init.tcl, I can find the pizza jar file and invoke the compiler fairly easily. > I also don't see how this -resolve flag fits in with the functionality > of the import command. In what situation would one want to > pass this -resolve flag, and in what situation would one not want > it passed? Why would we want to expose this feature at the script > level? > > I read over the JDK docs but they were not very clear on exactly what > the resolve really does. It seems one needs to read the JVM book to > find out what "the class is linked" means. It's certainly not clear to me either! In working with Hyde, importing the main class for the Pizza compiler yielded protection errors on another Pizza compiler class when specifing the pizza jar on TCL_CLASSPATH, but using the resolve flag seemed to fix those problems. Java class loading seems to be more of a black art than it needs to be. -- Tom Poindexter tpo...@ny... http://www.nyx.net/~tpoindex/ |
From: Mo D. <md...@un...> - 2003-04-14 20:30:52
|
On Wed, 9 Apr 2003 08:39:10 -0600 Tom Poindexter <tpo...@ny...> wrote: > On Wed, Apr 09, 2003 at 01:14:00AM -0700, Mo DeJong wrote: > > On Tue, 8 Apr 2003 22:07:41 -0600 > > > I must admit, I don't like the idea of adding a -classpath option to the > > import command. The java::import command is meant to act like the > > import statement in Java, in that it allows using a short name for > > a class instead of the fully qualified name. > > > > What is wrong with setting the CLASSPATH or the TCL_CLASSPATH env > > var before running the java::import command? > > I'd like to be able to specify from where to load a class in my Hyde package. > I'm now using the Pizza compiler (pizzacompiler.sf.net) as an in-process > compiler for Hyde. I also would like to make Hyde as 'package friendly' > as possible, not distrubing global environment's CLASSPATH or TCL_CLASSPATH. Sorry, I am going to have to reject this patch. I don't see how adding a path to the TCL_CLASSPATH is more "disturbing" than passing a flag to the import command. > > I also don't see how this -resolve flag fits in with the functionality > > of the import command. In what situation would one want to > > pass this -resolve flag, and in what situation would one not want > > it passed? Why would we want to expose this feature at the script > > level? > > > > I read over the JDK docs but they were not very clear on exactly what > > the resolve really does. It seems one needs to read the JVM book to > > find out what "the class is linked" means. > > It's certainly not clear to me either! In working with Hyde, importing the > main class for the Pizza compiler yielded protection errors on another > Pizza compiler class when specifing the pizza jar on TCL_CLASSPATH, but > using the resolve flag seemed to fix those problems. Java class loading seems > to be more of a black art than it needs to be. Well, in that case perhaps the right fix is to always pass the extra resolve flag to the class loader. In any event, exposing this functionality as the script layer just does not sound like a good idea. Mo |
From: Tom P. <tpo...@ny...> - 2003-04-14 21:07:13
|
On Mon, Apr 14, 2003 at 01:32:16PM -0700, Mo DeJong wrote: > On Wed, 9 Apr 2003 08:39:10 -0600 > Tom Poindexter <tpo...@ny...> wrote: > > > On Wed, Apr 09, 2003 at 01:14:00AM -0700, Mo DeJong wrote: > > > On Tue, 8 Apr 2003 22:07:41 -0600 > > > > > I must admit, I don't like the idea of adding a -classpath option to the > Sorry, I am going to have to reject this patch. I don't see how adding a path > to the TCL_CLASSPATH is more "disturbing" than passing a flag to the > import command. This: set cp /usr/local/lib/tcljava-1.3.0/hyde/pizza/pizza-1.1.jar java::import -classpath $cp -package net.sf.pizzacompiler.compiler \ ByteArrayCompilerOutput \ ClassReader CompilerOutput Main MapSourceReader Report SourceReader # do stuff with pizza classes vs. this: global env if {[info exists env(TCL_CLASSPATH)]} { set old_tcl_classpath $env(TCL_CLASSPATH) } set cp /usr/local/lib/tcljava-1.3.0/hyde/pizza/pizza-1.1.jar lappend env(TCL_CLASSPATH) $cp java::import ByteArrayCompilerOutput \ ClassReader CompilerOutput Main MapSourceReader Report SourceReader # do stuff with pizza classes # now put TCL_CLASSPATH back the same way we found it if {[info exists old_tcl_classpath]} { set env(TCL_CLASSPATH) $old_tcl_classpath } else { unset env(TCL_CLASSPATH) } you be the judge. > Well, in that case perhaps the right fix is to always pass the extra resolve > flag to the class loader. In any event, exposing this functionality as the > script layer just does not sound like a good idea. I'd argue that exposing more functionality *is* a good idea. The 'java' package is already incredibly powerful - no need to add training wheels to a hotrod. -- Tom Poindexter tpo...@ny... http://www.nyx.net/~tpoindex/ |