views:

771

answers:

4

Hi all,

I would like to (and I don't know if it's possible) do something if jarA is in my classpath and do something else if jarB is in my classpath. I am NOT going to be specifying these jars in the Netbeans project library references because I don't know which of the jars will be used.

Now including the jar in my Netbeans project library references works when I try to use the jar's classes through reflection. But when I remove the netbeans project library reference but add the jar to my classpath the reflection does not work.

My question is really 1) can this be done? 2) Am I thinking about it correctly 3) How come when I specify -cp or -classpath to include the directory containing the jar it doesn't work? 4) How come when I specify the directory in my manifest.mf in the jar file it doesn't work?

Please let me know. This is really bothering me.

Thanks, Julian

+1  A: 

on point 3 - you should include the fully qualified jar name in your classpath, not just the directory.

akf
but the java help options say classpath searches a path of diretories
jbu
"-classpath <class search path of directories and zip/jar files> A ; separated list of directories, JAR archives, and ZIP archives to search for class files". Your comment is only partially correct - it applies for class files, but NOT jar files. Any references to Jar files on the classpath must be fully qualified
Dinuk
+1  A: 

A classpath can reference a directory that contains .class files, or it can reference a .jar file directly. If it references a directory that contains .jar files, they will not be included.


java -help says this about -classpath: "list of directories, JAR archives, and ZIP archives to search for class files." This is very clear that a directory on the classpath is searched for class files, not JAR archives.

erickson
+1  A: 

I believe so!

ClassLoader.getSystemClassLoader()getURLs();

This will tell you which Jar files are in your classpath. Then do X or Y as you please.

the.jxc
Oops, probably wasn't perfectly clear. It is good to know which jar files are in my classpath, but after I determine that I have to USE the jar that was found.
jbu
I might need a little more explanation. Is the problem that you have the same class which might exist in two different JAR files both in your classpath? In that case, it might be tricky to pick between them. findClass (and hence loadClass) will probably just take the first one it finds.If you have two JAR files and want to pick the source for your class, better to search for them yourself using File functions, then create your own class loader. Do you want an example of that? I have some code lying around somewhere.You can dynamically load JAR files that are not in your classpath.
the.jxc
A: 

This is how I'm doing it. The inner class encapsulates the singleton instance of the logger and its trace method (heh - I know - a singleton inside a singleton). The outer class only uses it if the special class can be loaded, otherwise we go on without it. Hopefully you can modify this to suit your needs. And any suggestions as to better code are always appreciated! :-) HTH

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Provides centralized access to standardized output formatting. Output is sent to System.out and,
 * if the classpath allows it, to the Cisco CTIOS LogManager.  (This is NOT a dependency, however.)
 * 
 */
public class LogWriter
{
    protected static LogWriter me = null;
    private SimpleDateFormat dateFormat = null;
    private StringBuffer line = null;
    CLogger ciscoLogger = null;

    /*
     * The following 2 methods constitute the thread-safe singleton pattern.
     */
    private static class LogWriterHolder 
    {
        public static LogWriter me = new LogWriter();
    }
    /**
     * Returns singleton instance of the class.  Thread-safe.  The only way to get one is to use this.
     * 
     * @return an instance of LogWriter
     */
    public static LogWriter sharedInstance() 
    {
        return LogWriterHolder.me;
    }


    @SuppressWarnings("unchecked")
    LogWriter() 
    {
        dateFormat = new SimpleDateFormat("yyyyMMddHHmmss ");
        line = new StringBuffer();
        try {
            Class x = Class.forName("com.cisco.cti.ctios.util.LogManager");
            if( x != null ) {
                java.lang.reflect.Method m = x.getMethod("Instance", new Class[0]);
                java.lang.reflect.Method n  = x.getMethod("Trace", int.class, String.class );
                if( m != null ) {
                     Object y = m.invoke( x , new Object[0] );
                     if( n != null ) {
                         ciscoLogger = new CLogger();
                         ciscoLogger.target = y;
                         ciscoLogger.traceImpl = n ;
                     }
                }
            }
        } catch(Throwable e ) 
        {
            System.err.println( e.getMessage() ) ;
            e.printStackTrace();
        }
    }

    /**
     * Formats a line and sends to System.out.  The collection and formatting of the text is 
     * thread safe.
     * 
     * @param message       The human message you want to display in the log (required).
     * @param hostAddress   Host address of server (optional)
     * @param hostPort      Port on hostAddresss (optional) - also used for className in object-specific logs.
     */
    public void log( String message, String hostAddress, String hostPort ) 
    {
        if ( message == null || message.length() < 3 ) return;

        synchronized( this ) 
        {
            try {
                line.delete(0, line.length());
                line.append(dateFormat.format(new Date()));
                line.append(hostAddress);
                line.append(":");
                line.append(hostPort);
                line.append(" ");
                while (line.length() < 28)
                    line.append(" ");
                line.append(message);

                this.write( line.toString() );

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void write(String line )
    {
        System.out.println( line ) ;
    }

    /**
     * Write a simple log message to output delegates (default is System.out).
     * <p>
     * Will prepend each line with date in yyyyMMddHHmmss format.  there will be a big space
     * after the date, in the spot where host and port are normally written, when {@link LogWriter#log(String, String, String) log(String,String,String)}
     * is used.
     * 
     * @param message What you want to record in the log.
     */
    public void log( String message )
    {
        if( ciscoLogger != null ) ciscoLogger.trace(0x01, message );
        this.log( message, "", "");
    }

    class CLogger
    {
        Object target;
        Method traceImpl;

        @SuppressWarnings("boxing")
        public void trace( int x, String y )
        {
            try {
                traceImpl.invoke( target, x, y) ;
            } catch( Throwable e ) {
                // nothing to say about this
            }
        }
    }

}