Friday, March 6, 2009

Accessing resources in a WAR file

you can easily read the content of a directory in Java, even if this directory is in the classpath:

Here is a useful method to load only the resources:

public static List getDirContent(String dir, boolean throwExceptionIfNotFound) throws IOException {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
URL configDir = contextClassLoader.getResource(dir);
if (configDir == null && throwExceptionIfNotFound) throw new IllegalArgumentException("Unable to locate directory " + dir);
List result = new ArrayList();
if (configDir != null) {
URLConnection openConnection = configDir.openConnection();
openConnection.connect();
InputStream is = openConnection.getInputStream();
String content = NuonFileUtils.convertStreamToString(is);
String[] resources = content.split("\n");
for (String resource : resources) {
URL resurl = Thread.currentThread().getContextClassLoader().getResource(resource);
result.add(resurl);
}
}
return result;
}


the content of the resource can be read with a URL using its InputStream.
This method doesn't work in a WAR file, since the classloader's resource locator can't introspect the WAR file. The solution is to use the ServletContext and ServletConfig pattern:

in a JSP, you can do:

String path = ""/WEB-INF/config";
java.net.URL url = config.getServletContext().getResource(path);

and it works beautyfully!

The more elegant way is to have a ServletContextListener intercepting your servlet's initialization, and loading the resources:

public void contextInitialized(ServletContextEvent sce) {
String path = "/WEB-INF/classes";
try {
sce.getServletContext().getResource(path);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


No comments: