231 lines
6.5 KiB
Java
231 lines
6.5 KiB
Java
|
|
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//
|