views:

4881

answers:

5

Hi all,

java -classpath ../classes;../jar;. parserTester

How can i get the functionality in the above command programmatically? Like, is it possible to run as:

java parserTester

and get the same result? I tried using URLClassLoader but it modifies the classpath and does not add to it.

Thanx!

Thanks for the response Milhous. But that is what i am trying to do.. How is it possible to get the jar into the classpath first? I tried using a custom classloader too :(

That works.. But sorry that i need to run it only as: java parserTester I would like to know if such a thing is possible???

It needs to be so bcoz i have parserTester.java and .class in a separate folder. I need to retain the file structure. The parserTester makes use of a jar in a separate jar folder.

+1  A: 

You could implement your own class loader, but that class/jar has to be in the classpath for it to be executed.

try

java -cp *.jar:. myClass

or

export CLASSPATH=./lib/tool.jar:.
java myClass

or

java -jar file.jar
Milhous
A: 

Did I understand right?! The only reason you have it that you want to launch your class without specifying the classpath and load it at runtime? ...

java parserTester

instead of

java -classpath ../classes;../jar;. parserTester

Probably I didn't get your reason. But if "that's" what you want you can do the following ( although it does not make much sense to me )

  • Launch the class
  • From the main method lauch another class an programatically set the classpath there.
  • End of history.

Something like the following "java -pseudo code "

public static void main( String [] args ) {
    String classpath = "classes;../jar";
    Runtime.getRuntime().execute("java + classpath + " parserTester ");
}

Please tell me if I get it right. If you want to do something else I would gladly help.

OscarRyz
+1  A: 

I have to agree with the other two posters, it sounds like you're overcomplicating a test class. It's not that unusual to have the .java and .class files in separate folders, while depending on jar files in yet a third, without programmatically changing the classpath. If you're doing it because you don't want to have to type the classpath on the command line everytime, I would suggest a shell script or batch file. Better yet, an IDE. The question I really have is why are you doing trying to manage the classpath in code?

Jim Barrows
A: 

You can write a batch file or shell script file to export the classpath and run the java program. In Windows,

set classpath=%classpath%;../classes;../jars/* java ParserTester

In Unix, export classpath=%classpath%:../classes:../jars/* java ParserTester

If you name the file name as parser.bat or parser.sh, you can just run that by calling parser in respective OS.

From java 1.6, you can include all the jars in a directory into the classpath just by saying /*

If you are trying to generate a java file dynamically, compile and add into the classpath, set the directory into which the class file gets generated in the classpath beforehand. It should load the class. If you are modifying the already generated java class, basically recompiling after modification and if you want to load the new class, you need to use your custom class loader to avoid the caching of the class.

raffimd
+2  A: 

You can use a java.net.URLClassLoader to load classes with any program defined list of URL's you wish:

public class URLClassLoader extends SecureClassLoader

This class loader is used to load classes and resources from a search path of URLs referring to both JAR files and directories. Any URL that ends with a '/' is assumed to refer to a directory. Otherwise, the URL is assumed to refer to a JAR file which will be opened as needed.

The AccessControlContext of the thread that created the instance of URLClassLoader will be used when subsequently loading classes and resources.

The classes that are loaded are by default granted permission only to access the URLs specified when the URLClassLoader was created.

Since: 1.2

And a little fancy footwork can extend it to support using wildcarded pathnames to pick up entire directories of JARs (this code has some references to utility methods, but their implementation should be obvious in the context):

/**
 * Add classPath to this loader's classpath.
 * <p>
 * The classpath may contain elements that include a generic file base name.  A generic basename
 * is a filename without the extension that may begin and/or end with an asterisk.  Use of the
 * asterisk denotes a partial match. Any files with an extension of ".jar" whose base name match
 * the specified basename will be added to this class loaders classpath.  The case of the filename is ignored.
 * For example "/somedir/*abc" means all files in somedir that end with "abc.jar", "/somedir/abc*"
 * means all files that start with "abc" and end with ".jar", and "/somedir/*abc*" means all files
 * that contain "abc" and end with ".jar".
 *
 */
public void addClassPath(String cp) {
    String                              seps=File.pathSeparator;                // separators

    if(!File.pathSeparator.equals(";")) { seps+=";"; }                          // want to accept both system separator and ';'
    for(StringTokenizer st=new StringTokenizer(cp,seps,false); st.hasMoreTokens(); ) {
        String pe=st.nextToken();
        File   fe;
        String bn=null;

        if(pe.length()==0) { continue; }

        fe=new File(pe);
        if(fe.getName().indexOf('*')!=-1) {
            bn=fe.getName();
            fe=fe.getParentFile();
            }

        if(!fe.isAbsolute() && pe.charAt(0)!='/' && pe.charAt(0)!='\\') { fe=new File(rootPath,fe.getPath()); }
        try { fe=fe.getCanonicalFile(); }
        catch(IOException thr) {
            log.diagln("Skipping non-existent classpath element '"+fe+"' ("+thr+").");
            continue;
            }
        if(!GenUtil.isBlank(bn)) {
            fe=new File(fe,bn);
            }
        if(classPathElements.contains(fe.getPath())) {
            log.diagln("Skipping duplicate classpath element '"+fe+"'.");
            continue;
            }
        else {
            classPathElements.add(fe.getPath());
            }

        if(!GenUtil.isBlank(bn)) {
            addJars(fe.getParentFile(),bn);
            }
        else if(!fe.exists()) {                                                 // s/never be due getCanonicalFile() above
            log.diagln("Could not find classpath element '"+fe+"'");
            }
        else if(fe.isDirectory()) {
            addURL(createUrl(fe));
            }
        else if(fe.getName().toLowerCase().endsWith(".zip") || fe.getName().toLowerCase().endsWith(".jar")) {
            addURL(createUrl(fe));
            }
        else {
            log.diagln("ClassPath element '"+fe+"' is not an existing directory and is not a file ending with '.zip' or '.jar'");
            }
        }
    log.diagln("Class loader is using classpath: \""+classPath+"\".");
    }

/**
 * Adds a set of JAR files using a generic base name to this loader's classpath.  See @link:addClassPath(String) for
 * details of the generic base name.
 */
public void addJars(File dir, String nam) {
    String[]                            jars;                                   // matching jar files

    if(nam.endsWith(".jar")) { nam=nam.substring(0,(nam.length()-4)); }

    if(!dir.exists()) {
        log.diagln("Could not find directory for Class Path element '"+dir+File.separator+nam+".jar'");
        return;
        }
    if(!dir.canRead()) {
        log.error("Could not read directory for Class Path element '"+dir+File.separator+nam+".jar'");
        return;
        }

    FileSelector fs=new FileSelector(true).add("BaseName","EG",nam,true).add("Name","EW",".jar",true);
    if((jars=dir.list(fs))==null) {
        log.error("Error accessing directory for Class Path element '"+dir+File.separator+nam+".jar'");
        }
    else if(jars.length==0) {
        log.diagln("No JAR files match specification '"+new File(dir,nam)+".jar'");
        }
    else {
        log.diagln("Adding files matching specification '"+dir+File.separator+nam+".jar'");
        Arrays.sort(jars,String.CASE_INSENSITIVE_ORDER);
        for(int xa=0; xa<jars.length; xa++) { addURL(createUrl(new File(dir,jars[xa]))); }
        }
    }

private URL createUrl(File fe) {
    try {
        URL url=fe.toURI().toURL();
        log.diagln("Added URL: '"+url.toString()+"'");
        if(classPath.length()>0) { classPath+=File.pathSeparator; }
        this.classPath+=fe.getPath();
        return url;
        }
    catch(MalformedURLException thr) {
        log.diagln("Classpath element '"+fe+"' could not be used to create a valid file system URL");
        return null;
        }
    }
Software Monkey
SoftwareMonkey. I didn't understand the question. It looks an advanced matter but then the explanation he gives is totally no sense: "bcoz i have parserTester.java and .class in a separate folder. I need to retain the file structure." I think your answer will do for a more correct question :) +1
OscarRyz