2008/6/13 Kass, Samuel-P58051 <[EMAIL PROTECTED]>: > I'm investigating OSGI-ifying a large codebase, and am trying to pin > down how we're going to do resource loading. At the bottom of this > message is a bit of code that's called many times in the codebase. It > can take anything from a filename to a URL string to a resource path, > and turn it into a canonical URL that can be passed to anything in the > Java libraries that take a URL. > > Questions: > 1. I think ClassLoader.getSystemResource(spec) is going to get me into > trouble in OSGi-land. I'm not sure the > Thread.currentThread().getContextClassLoader().getResource(spec); is any > better. However, this is what was recommended by Sun in > http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/faq.htm > l#211 when trying to make our code work in JNLP-land. Would > AnyInputStream.class.getResource(spec) work any better?
using the TCCL allows clients to swap in their own classloaders and doesn't rely on any OSGi specific API, but all OSGi clients must then remember to set the TCCL to their bundle classloader before calling your library (this isn't done automatically in Felix) this is what a lot of legacy libraries do - the alternative is to use some sort of injection/plugin approach to swap in an OSGi specific resource implementation when using the library inside an OSGi framework. 2. Felix sees the string "C:\dir\file" as a URL with protocol "C:" (and > throws malformed URL exception since it doesn't recognize that protocol) > when it tries to to look it up as a resource. this problem is not specific to Felix, or even OSGi - it always happens when you have a string which might be a URL or a filename, because there's an overlap between the path syntax on some OS's and the URL syntax - you often have to fall back and query the OS to see whether it represents a valid file location before trying it as a URL (or vice-versa) this is made more difficult by the varying slashes needed with file URIs: http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx I've basically ended up doing the same sort of thing in the past for URIs ie. load the string as a URI and use toURL() method to check the syntax, otherwise fall back to loading it as a file and use the toURI() method. Moving the attempt to > stat the File to before the resource calls solves that problem, but the > common case is that we store the file in a resource, so we're doing a > lot of extra file stats if I make that change. you'll find the core Java classes perform similar checks to distinguish between URLs and filenames - it's surprising how often "stat" is called. > 3. I'd like to avoid OSGI-specific code in the core codebase and rely on > the classpath-mangling magic to accomplish this... but do I need to move > away from static calls to do it? Would a singleton pattern work better > here, or are singletons, too, evil in a multi-classloader world? > singletons should work fine, along as your exports and imports are ok. another solution (if you want to keep the static calls) is a thread local, which you then just need to set to the right implementation - this can be a very clean solution, especially if you provide utility methods to do the setup. ( just remember to clean up thread locals when you're done, as they can be a cause of memory leaks ) HTH --Sam Kass > > class AnyInputStream > { > //... > public static URL makeURL(String spec) > throws IllegalArgumentException > { > // For applets/webstart, we should use this thread's ClassLoader, > which > // will default to the system classloader if it hasn't been > overridden > URL url = > Thread.currentThread().getContextClassLoader().getResource(spec); > > // Call back to the SystemResouce if we can't find it > if (null == url) > url = ClassLoader.getSystemResource(spec); > > // Try parsing it as a pre-formed URL > if (null == url) > { > try > { > url = new URL(spec); > } > catch (MalformedURLException e) > { > url = null; > } > } > > // If we couldn't find it from the classloader, try the local > filesystem > if (url == null) > { > try > { > File file = new File(spec); > if (file.isFile()) > { > url = file.toURL(); > } > } > catch (MalformedURLException e) > { > //throw new IllegalArgumentException("Unable to open: " + > onedoc); > } > } > > if (url == null) > { > throw new IllegalArgumentException( > "Unable to create URL from \"" + spec + "\""); > } > > return url; > } > } > -- Cheers, Stuart

