/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* Licensed 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
*******************************************************************************/
package org.ebayopensource.turmeric.eclipse.utils.classloader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.osgi.framework.Bundle;
/**
* The Class SOAPluginClassLoader.
*
* @author smathew
*/
public class SOAPluginClassLoader extends URLClassLoader {
private static final URL[] EMPTY_URLS = new URL[0];
private static final Comparator<URL> URL_COMPARATOR = new Comparator<URL>() {
@Override
public int compare(URL o1, URL o2) {
return (o1 != null && o2 != null) ? o1.toString().compareTo(
o2.toString()) : 0;
}
};
private Set<URL> m_jarURLs = new TreeSet<URL>(URL_COMPARATOR);
private Set<URL> m_dirURLs = new TreeSet<URL>(URL_COMPARATOR);
private Set<URL> m_classPathURLs = new TreeSet<URL>(URL_COMPARATOR);
private List<Bundle> pluginBundles = new ArrayList<Bundle>();
private static final Logger logger = Logger
.getLogger(SOAPluginClassLoader.class.getName());
/**
* Instantiates a new sOA plugin class loader.
*
* @param name the name
* @param urls the urls
*/
public SOAPluginClassLoader(String name, URL[] urls) {
super(EMPTY_URLS);
for (int i = 0; i < urls.length; i++) {
File file = FileUtils.toFile(urls[i]);
if (file.isDirectory()) {
m_dirURLs.add(urls[i]);
} else if (file.isFile()) {
m_jarURLs.add(urls[i]);
}
}
for (URL dirURL : m_dirURLs) {
addURL(dirURL);
}
m_classPathURLs.addAll(m_jarURLs);
m_classPathURLs.addAll(m_dirURLs);
if (logger.isLoggable(Level.FINE)) {
logger.fine("Inside soa plugin loader setM_classPathURLs: "
+ m_classPathURLs);
}
}
/* (non-Javadoc)
* @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
*/
@Override
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
try {
Class<?> _class = doLoadClass(name);
if (_class != null)
return _class;
} catch (Exception e) {
//oops, got some problems just ignore it.
}
return super.loadClass(name, resolve);
}
private Class<?> doLoadClass(String className) throws ClassNotFoundException {
Class<?> clazz = null;
try {
for (Bundle pluginBundle : pluginBundles) {
clazz = pluginBundle.loadClass(className);
if (clazz != null) {
//logger.info("loaded using bundle class loader->"
// + className);
return clazz;
}
}
} catch (ClassNotFoundException classNotFoundException) {
}
return clazz;
}
/**
* {@inheritDoc}
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> loadedClass = findLoadedClass(name);
if (loadedClass != null) {
return loadedClass;
}
StringBuilder sb = new StringBuilder(name.length() + 6);
sb.append(name.replace('.', '/')).append(".class");
InputStream is = getResourceAsStream(sb.toString());
if (is == null)
throw new ClassNotFoundException("Class not found " + sb);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = is.read(buf)) >= 0)
baos.write(buf, 0, len);
buf = baos.toByteArray();
// define package if not defined yet
int i = name.lastIndexOf('.');
if (i != -1) {
String pkgname = name.substring(0, i);
Package pkg = getPackage(pkgname);
if (pkg == null)
definePackage(pkgname, null, null, null, null, null, null,
null);
}
baos.close();
is.close();
return defineClass(name, buf, 0, buf.length);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
}
/**
* {@inheritDoc}
*/
@Override
public URL findResource(String resourceName) {
//logger.info("resource name in findresource is " + resourceName);
try {
URL retUrl = null;
for (Bundle pluginBundle : pluginBundles) {
retUrl = pluginBundle.getResource(resourceName);
if (retUrl != null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("found resource using bundle " + resourceName);
}
return retUrl;
}
}
} catch (Exception exception) {
}
for (URL url : m_jarURLs) {
try {
File file = FileUtils.toFile(url);
JarFile jarFile;
jarFile = new JarFile(file);
JarEntry jarEntry = jarFile.getJarEntry(resourceName);
if (jarEntry != null) {
SOAToolFileUrlHandler handler = new SOAToolFileUrlHandler(
jarFile, jarEntry);
URL retUrl = new URL("jar", "", -1, new File(jarFile
.getName()).toURI().toURL()
+ "!/" + jarEntry.getName(), handler);
handler.setExpectedUrl(retUrl);
return retUrl;
}
} catch (IOException e) {
e.printStackTrace(); // KEEPME
}
}
return super.findResource(resourceName);
}
/**
* Gets the plugin bundles.
*
* @return the plugin bundles
*/
public List<Bundle> getPluginBundles() {
return pluginBundles;
}
/**
* Sets the plugin bundles.
*
* @param pluginBundles the new plugin bundles
*/
public void setPluginBundles(List<Bundle> pluginBundles) {
this.pluginBundles = pluginBundles;
}
/* (non-Javadoc)
* @see java.net.URLClassLoader#getURLs()
*/
@Override
public URL[] getURLs() {
return m_classPathURLs.toArray(new URL[0]);
}
/**
* Gets the m_class path ur ls.
*
* @return the m_class path ur ls
*/
public Set<URL> getM_classPathURLs() {
return m_classPathURLs;
}
/**
* Sets the m_class path ur ls.
*
* @param pathURLs the new m_class path ur ls
*/
public void setM_classPathURLs(Set<URL> pathURLs) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Inside soa plugin loader setM_classPathURLs: " + pathURLs);
}
m_classPathURLs = pathURLs;
}
}