Files
Brainstorm/Foundation Web Server/src/com/foundation/web/application/ServerClassLoader.java

231 lines
6.5 KiB
Java
Raw Normal View History

2014-05-30 10:31:51 -07:00
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//