[jcifs] java.net.MalformedURLException further analysis

Glass, Eric eric.glass at capitalone.com
Thu Dec 12 00:01:45 EST 2002


OK, I have figured out what is going on here.

This should work if you install the jCIFS jar as an extension (move it into
the "lib/ext" directory under $JAVA_HOME), specify it in your classpath, or
otherwise make it available to the system classloader.

When the URL class attempts to find a protocol handler, it first checks the
cache of loaded handlers.  When no handler is found it then looks to see if
the installed URLStreamHandlerFactory (if any) can create a handler.  If
not, it looks to the java.protocol.handler.pkgs property.  This is where
things start to get relevant to us.

For each token in the property string, the URL class builds a class name
<token> + "." + <protocol> + ".Handler" (in our case, "jcifs.smb.Handler").
It then attempts to obtain the Class object for this class as follows:

Class cls = null;
try {
    cls = Class.forName(clsName);
} catch (ClassNotFoundException e) {
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    if (cl != null) {
        cls = cl.loadClass(clsName);
    }
}

The main problem here is that the above will (under normal circumstances)
ONLY load classes from the system class loader;  the first call uses the
defining class loader of the URL class, which will almost always be the
system class loader (unless you are have defined the
"java.system.class.loader" property and changed the default class loader).
I am not sure if this is a bug in the URL class or intentional; a seemingly
more useful statement would have been:

Class cls = null;
try {
    cls = Class.forName(clsName);
} catch (ClassNotFoundException e) {
    try {
        ClassLoader threadLoader = Thread.getContextClassLoader();
        if (threadLoader != null) {
            cls = threadLoader.loadClass(clsName);
        }
    } catch (ClassNotFoundException ignore) {
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        if (cl != null) {
            cls = cl.loadClass(clsName);
        }
    }
}

which would further attempt to load the class using the context classloader
for the current thread (which is set to the web application classloader by
Tomcat).

Eric

> -----Original Message-----
> From: andrea.lanza at frameweb.it [mailto:andrea.lanza at frameweb.it]
> Sent: Wednesday, December 11, 2002 6:25 AM
> To: jcifs at lists.samba.org
> Subject: [jcifs] java.net.MalformedURLException further analysis
>
>
>
> I tried to follow the idea proposed by Eric, and I put part
> of that code at
> the real beginning of my class, in order to see what happend.
>
> My final idea is that Tomcat could be innocent, and I am
> doing something
> wrong.
>
> Here is the code I added
>
>     try {
> // added by Andrea for testing purpose, 11/12/2002
> String ver = System.getProperty( "java.version" );
> if( ver.startsWith( "1.1." ) || ver.startsWith( "1.2." )) {
>    System.out.println( "jcifs-0.7.0b4+ requires Java 1.3 or
> above. You are
> running " + ver );
> } else {
>    System.out.println( " JAVA Version is OK. You are running
> " + ver );
> }
> String pkgs = System.getProperty( "java.protocol.handler.pkgs" );
> if( pkgs == null ) {
>    System.out.println("pkgs==null");
>    pkgs = "jcifs";
> } else {
>    System.out.println("pkgs NOT null: actual value:" + pkgs);
> }
> try {
>    System.setProperty( "java.protocol.handler.pkgs", pkgs );
> } catch (SecurityException ex) {
>         System.out.println("SecurityException "+ ex.toString());
>  }
>
> // now I test if System.setProperty worked out
> pkgs = System.getProperty( "java.protocol.handler.pkgs" );
> if( pkgs == null ) {
>    System.out.println("2nd time: pkgs IS STILL
> null,setProperty did not
> work");
> } else {
>    System.out.println("2nd time: pkgs NOT null: actual
> value:" + pkgs);
> }
>
>
> FileInputStream localin=null;
> try {
>    String filename = System.getProperty( "jcifs.properties" );
>    if( filename != null && filename.length() > 1 ) {
>          System.out.println("filename value is: "+filename );
>          localin = new FileInputStream( filename );
>          jcifs.util.Config.load( localin );
>    } else {
>         System.out.println("filename value is null or 0 legth ");
>    }
> } catch( IOException ioe ) {
>       System.out.println("IOException: "+ioe.toString());
> }
> Class.forName( "jcifs.Config" );
> System.out.println("Class forname was successful, no exceptions ");
> sourceFile = new SmbFile("smb://");
> System.out.println("new SMBFile was successful, no exceptions");
> // END OF added by Andrea for testing purpose, 11/12/2002
> ......
> then there is the catch and so on.......
>
>
> When I get the usual error  ( java.net.MalformedURLException: unknown
> protocol: smb ) I can read in the standard out file
> (Sorry, I am used to use standard output, non standard
> error....it's a mine
> bug!)
>
> stdout file:
>
> Bootstrap: Create Catalina server
> Bootstrap: Starting service
> Starting service Tomcat-Standalone
> Apache Tomcat/4.1.12
> Bootstrap: Service started
>  JAVA Version is OK. You are running 1.4.1_01
> pkgs==null
> 2nd time: pkgs NOT null: actual value:jcifs
> filename value is null or 0 legth
> Class forname was successful, no exceptions
> Error in SmbPrx.execute() : java.net.MalformedURLException: unknown
> protocol: smb
>
>
> So what can we see ? that System.getProperty worked and
> System.setProperty
> too......
> In addition to the entry in stdout (Error in
> SmbPrx.execute()......), in
> standard error I print the StackTrace
>
> java.net.MalformedURLException: unknown protocol: smb
>       at java.net.URL.<init>(URL.java:586)
>       at java.net.URL.<init>(URL.java:476)
>       at java.net.URL.<init>(URL.java:425)
>       at jcifs.smb.SmbFile.<init>(SmbFile.java:355)
>       at SmbPrx.execute(SmbPrx.java)
>       at SmbPrx.doTutto(SmbPrx.java)
>       at SmbPrx.doPost(SmbPrx.java)
>       at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
>       at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
>       at
> org.apache.catalina.servlets.InvokerServlet.serveRequest(Invok
> erServlet.java:458)
>       at
> org.apache.catalina.servlets.InvokerServlet.doPost(InvokerServ
> let.java:216)
>       at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
>       at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
>       at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilt
> er(ApplicationFilterChain.java:247)
>       at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(Appli
> cationFilterChain.java:193)
>       at
> org.apache.catalina.core.StandardWrapperValve.invoke(StandardW
> rapperValve.java:260)
>       at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValv
> eContext.invokeNext(StandardPipeline.java:643)
>       at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipel
> ine.java:480)
>       at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
>       at
> org.apache.catalina.core.StandardContextValve.invoke(StandardC
> ontextValve.java:191)
>       at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValv
> eContext.invokeNext(StandardPipeline.java:643)
>       at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipel
> ine.java:480)
>       at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
>       at
> org.apache.catalina.core.StandardContext.invoke(StandardContex
> t.java:2396)
>       at
> org.apache.catalina.core.StandardHostValve.invoke(StandardHost
> Valve.java:180)
>       at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValv
> eContext.invokeNext(StandardPipeline.java:643)
>       at
> org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDi
> spatcherValve.java:170)
>       at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValv
> eContext.invokeNext(StandardPipeline.java:641)
>       at
> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReport
> Valve.java:172)
>       at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValv
> eContext.invokeNext(StandardPipeline.java:641)
>       at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipel
> ine.java:480)
>       at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
>       at
> org.apache.catalina.core.StandardEngineValve.invoke(StandardEn
> gineValve.java:174)
>       at
> org.apache.catalina.core.StandardPipeline$StandardPipelineValv
> eContext.invokeNext(StandardPipeline.java:643)
>       at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipel
> ine.java:480)
>       at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
>       at
> org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.
> java:223)
>       at
> org.apache.coyote.http11.Http11Processor.process(Http11Process
> or.java:405)
>       at
> org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandle
> r.processConnection(Http11Protocol.java:380)
>       at
> org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoi
> nt.java:508)
>       at
> org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(
> ThreadPool.java:533)
>       at java.lang.Thread.run(Thread.java:536)
>
> the line 355 in SmbFile.java appears to be :
> 354 │    public SmbFile( String url ) throws MalformedURLException {
> 355 │        this( new URL( url ));
> 356 │    }
>
> So again the question is: How can I be sure to use the
> correct java.net.URL
> ?
> Following the source of java.net.URL (java 2) the lines 425
> and  476 are
> constructors "redirected" to the "standard 3-argument"
> constructor for URL
>
>     public URL(URL context, String spec, URLStreamHandler
> handler)   throws
> MalformedURLException
>
>
> line  586 is part of this last constructor method
> line  586 and neighboroud:
>
> 582 │          // Get the protocol handler if not specified
> or the protocol
> 583 │        // of the context could not be used
> 584 │        if (handler == null &&
> 585 │             (handler = getURLStreamHandler(protocol)) == null) {
> 586 │             throw new MalformedURLException("unknown protocol: "
> +protocol);
> 587 │         }
>
>
> So , conforted by the line numbers (better than nothing ! ) 
> I believe to
> have the right  java.net.URL version
> I think that  the getURLStreamHandler(protocol) returns null.
>
> But here I stop, becouse everything seems to be OK to me (java version
> right, java.net.URL correct, jcifs in classpath and reachable,
> getSystemproperty and setSystemProperty working...)
>
> Next step, I will try to start tomcat adding the
> -Djava.protocol.handler.pkgs=jcifs if I will discover where
> to add that
> argument
>
> Andrea
>
> 
 
**************************************************************************
The information transmitted herewith is sensitive information intended only
for use by the individual or entity to which it is addressed. If the reader
of this message is not the intended recipient, you are hereby notified that
any review, retransmission, dissemination, distribution, copying or other
use of, or taking of any action in reliance upon this information is
strictly prohibited. If you have received this communication in error,
please contact the sender and delete the material from your computer.



More information about the jcifs mailing list