package com.foundation.web.application; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; import java.util.zip.*; import java.util.jar.*; /** * Used to load the view component builders only. */ public class ServerClassLoader extends ClassLoader { private File[] jars = null; /** * ServerClassLoader constructor. * @param jars The java.io.File objects for each jar loadable. */ public ServerClassLoader(File[] jars) throws IOException { super(); this.jars = jars; for(int index = 0; index < jars.length; index++) { File jar = jars[index]; if(!jar.exists() || !jar.canRead()) { throw new IOException("Cannot find or access the jar: " + jar.getCanonicalPath()); }//if// else if(!jar.getPath().toLowerCase().endsWith(".jar")) { throw new IOException("The passed file is not a jar: " + jar.getCanonicalPath()); }//else if// }//for// }//ServerClassLoader()// /* (non-Javadoc) * @see java.lang.ClassLoader#findResource(java.lang.String) */ protected URL findResource(String name) { URL result = null; name = name.replace('\\', '/'); while(name.charAt(0) == '/') { name = name.substring(1); }//while// for(int index = 0; result == null && index < jars.length; index++) { result = findResource(jars[index], name); }//for// return result; }//findResource()// /** * Finds the given class by searching the given file or directory. * @param file The file or directory to search. * @param classFileName The name of the class to find. */ private URL findResource(File file, String name) { URL result = null; if(file.exists()) { boolean cleanup = true; try { JarFile jar = new JarFile(file, false, JarFile.OPEN_READ); try { JarEntry entry = jar.getJarEntry(name); if(entry != null) { /* final JarFile jf = jar; final JarEntry je = entry; cleanup = false; result = new URL("", null, 0, name, new URLStreamHandler() { protected URLConnection openConnection(URL u) throws IOException { return new URLConnection(u) { public void connect() throws IOException { }//connect()// public InputStream getInputStream() throws IOException { return jf.getInputStream(je); }//getInputStream()// public void finalize() { try {jf.close();} catch(IOException e) {e.printStackTrace();} }//finalize()// }; }//openConnection()// }); */ final File jFile = file; final String jeName = name; result = new URL("", null, 0, name, new URLStreamHandler() { protected URLConnection openConnection(URL u) throws IOException { return new URLConnection(u) { public void connect() throws IOException { }//connect()// public InputStream getInputStream() throws IOException { return new InputStream() { JarFile _jar = new JarFile(jFile, false, JarFile.OPEN_READ); JarEntry _entry = _jar.getJarEntry(jeName); InputStream _in = _jar.getInputStream(_entry); public int read() throws IOException { return _in.read(); }//read()// public int available() throws IOException { return _in.available(); }//available()// public synchronized void mark(int readlimit) { _in.mark(readlimit); }//mark()// public boolean markSupported() { return _in.markSupported(); }//markSupported()// public int read(byte[] b, int off, int len) throws IOException { return _in.read(b, off, len); }//read()// public int read(byte[] b) throws IOException { return _in.read(b); }//read()// public synchronized void reset() throws IOException { _in.reset(); }//reset()// public long skip(long n) throws IOException { return _in.skip(n); }//skip()// public void close() throws IOException { try {_jar.close();} catch(IOException e) {e.printStackTrace();} super.close(); }//close()// }; }//getInputStream()// }; }//openConnection()// }); }//if// }//try// finally { if(cleanup && jar != null) { jar.close(); }//if// }//finally// }//try// catch(IOException e) { throw new RuntimeException(e); }//catch// }//if// return result; }//findResource()// /* (non-Javadoc) * @see java.lang.ClassLoader#findClass(java.lang.String) */ protected Class findClass(String className) throws ClassNotFoundException { Class type = null; String classFileName = className.replace('.', '/') + ".class"; //Debug.log("ServerClassLoader - Looking the for class: " + className); /* try { type = super.findClass(className); }//try// catch(ClassNotFoundException e) { //Ignore.// }//catch// */ for(int index = 0; type == null && index < jars.length; index++) { type = findClass(jars[index], className, classFileName); }//for// if(type == null) { throw new ClassNotFoundException("Couldn't find the class: " + className); }//if// return type; }//findClass()// /** * Finds the given class by searching the given file or directory. * @param file The file or directory to search. * @param classFileName The name of the class to find. */ private Class findClass(File file, String className, String classFileName) throws ClassNotFoundException { Class type = null; if(file.exists()) { byte[] bytes = null; try { JarFile jar = new JarFile(file, false, JarFile.OPEN_READ); try { JarEntry entry = jar.getJarEntry(classFileName); if(entry != null) { InputStream in = jar.getInputStream(entry); int approximateSize = in.available(); int readCount = 0; //TODO: Can this be optimized? Maybe smaller buffer.. maybe use a native buffer (nio)? byte[] buffer = new byte[1000]; ByteArrayOutputStream bout = new ByteArrayOutputStream(approximateSize); //Read all the bytes into an in-memory buffer.// while(readCount != -1) { bout.write(buffer, 0, readCount); readCount = in.read(buffer); }//while// bytes = bout.toByteArray(); in.close(); }//if// }//try// finally { if(jar != null) { jar.close(); }//if// }//finally// if(bytes != null) { type = defineClass(className, bytes, 0, bytes.length); }//if// }//try// catch(IOException e) { throw new RuntimeException(e); }//catch// }//if// return type; }//findClass()// }//ServerClassLoader//