blob: e78f18f6173eda86838489d0d51865ea2e54acd6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.axis2.tools.idea;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class PluginClassLoader extends URLClassLoader {
//urls which gives to create the classLoader
private URL[] urls;
//To keep jar files inside /lib directory in the main jar
private ArrayList lib_jars_list;
/**
* PluginClassLoader is exetend form URLClassLoader , and the constructor
* has not overide the super constroctor , but has done some stuff to find out
* jar fils inside /lib director
*
* @param urls <code>URL</code>
* @param parent parent classloader <code>ClassLoader</code>
*/
public PluginClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
this.urls = urls;
lib_jars_list = new ArrayList();
findLibJars();
}
/**
* This just search for jar files inside /lib dirctory and if there are any then those
* will be added to the arraylit (only the name of the jar file)
*/
private void findLibJars() {
/**
* though the URL array can contains one or more urls , I have only consider the
* first one , that is this classLoader is only for Axis2 stuff and the classloader
* is created by Deployment , so there wont be any chance to have more the one urls for
* the URL array list
*/
File file = new File(urls[0].getFile());
try {
ZipInputStream zin = new ZipInputStream(new FileInputStream(file));
ZipEntry entry;
String entryName = "";
while ((entry = zin.getNextEntry()) != null) {
entryName = entry.getName();
/**
* id the entry name start with /lib and end with .jar
* then those entry name will be added to the arraylist
*/
if (entryName != null && (entryName.startsWith("lib/") ||
entryName.startsWith("Lib/")) &&
entryName.endsWith(".jar")) {
lib_jars_list.add(entryName);
}
}
zin.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @param name <code>String</code> Name of the file to be loaded
* @return <code>Class</code> return a class object if it found else
* will return null or a ClassNotFoundException
* <p/>
* This method has been overridden in the following way
* 1. It calls the super class and checks to see whether the class is there
* If the class is found then return it, else if super return ClassNotfoundException
* 2. Check whether the entry corresponding to the class name exists in one of jar files
* in /lib director
* 3. If it is there get the byte array out of that and create a Class object out of that
* by calling "defineClass()" , if it succeeds then return that else
* 4. Throw a ClassNotFoundException
* @throws ClassNotFoundException
*/
protected Class findClass(final String name)
throws ClassNotFoundException {
Class cla = null;
try {
boolean foundClass = false;
try {
cla = super.findClass(name);
foundClass = true;
return cla;
} catch (ClassNotFoundException e) {
foundClass = false;
}
if (!foundClass) {
byte raw[] = getBytes(name);
cla = defineClass(name, raw, 0, raw.length);
foundClass = true;
return cla;
}
if (!foundClass) {
throw new ClassNotFoundException("Class Not found : " + name);
}
} catch (Exception e) {
}
return null;
}
/**
* Read jar file (/lib) one by one , then for each file craete <code>ZipInputStream</code>
* that and check to see wether there is any entry eith given name if it found then
* Creat ByteArrayOutPutStream and get the class bytes to that .
* after goning throgh each and evry jar file if there is no entry with given name
* will throug a ClassNotFound execption
*
* @param filename <code>String</code> Name of the file to be loaded (Class Name)
* @return bytt[]
* @throws java.io.IOException <code>Exception</code>
*/
private byte[] getBytes(String filename) throws Exception {
String completeFileName = filename;
/**
* Replacing org.apache. -> org/apache/...
*/
completeFileName = completeFileName.replace('.', '/').concat(".class");
byte raw[] = null;
for (int i = 0; i < lib_jars_list.size(); i++) {
String libjar_name = (String) lib_jars_list.get(i);
InputStream in = this.getResourceAsStream(libjar_name);
try {
ZipInputStream zin = new ZipInputStream(in);
ZipEntry entry;
String entryName = "";
while ((entry = zin.getNextEntry()) != null) {
entryName = entry.getName();
if (entryName != null &&
entryName.endsWith(completeFileName)) {
byte data[] = new byte[2048];
ByteArrayOutputStream out = new ByteArrayOutputStream();
int count;
while ((count = zin.read(data, 0, 2048)) != -1) {
out.write(data, 0, count);
}
raw = out.toByteArray();
out.close();
zin.close();
return raw;
}
}
} catch (IOException e) {
throw e;
}
}
throw new ClassNotFoundException("Class Not found : " + filename);
}
}