/*
* Copyright to the original author or authors.
*
* 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
*
* 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.rioproject.loader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URL;
import java.net.URLClassLoader;
/**
* The CommonClassLoader is created by the <code>RioServiceDescriptor</code> when starting a Rio
* service and contains common declared platform JARs to be made available to its
* children.
*
* <p>The CommonClassLoader enables a platform oriented framework conducive towards
* creating a layered product. The resulting capabilities allow the declaration of
* JARs that are added to the CommonClassLoader, making the classes accessible by
* all ClassLoader instances which delegate to the CommonClassLoader. In this
* fashion a platform can be declared, initialized and made available.
*
@author Dennis Reedy
*/
public final class CommonClassLoader extends URLClassLoader {
private static final String COMPONENT = "org.rioproject.loader";
private static Logger logger = LoggerFactory.getLogger(COMPONENT);
private static CommonClassLoader instance;
/**
* Create a CommonClassLoader
*
* @param parent The parent ClassLoader
*/
private CommonClassLoader(final ClassLoader parent) {
super(new URL[0], parent);
}
/**
* Get an instance of the CommonCLassLoader
*
* @return The CommonClassLoader
*/
public static synchronized CommonClassLoader getInstance() {
if(instance==null) {
instance = new CommonClassLoader(ClassLoader.getSystemClassLoader());
}
return(instance);
}
/**
* Override getURLs to ensure when an Object is marshalled its
* annotation is correct
*
* @return Array of URLs
*/
public URL[] getURLs() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
URL[] urls = doGetURLs(cl);
if(logger.isTraceEnabled()) {
StringBuilder buffer = new StringBuilder();
for(int i=0; i<urls.length; i++) {
if(i>0)
buffer.append(", ");
buffer.append(urls[i].toExternalForm());
}
logger.trace("Context ClassLoader={} URLs={}", cl.toString(), buffer.toString());
}
return(urls);
}
/**
* Get the URLs, ensuring when an Object is marshalled the annotation is
* correct
*
* @param cl The current context ClassLoader
*
* @return Array of URLs
*/
private URL[] doGetURLs(final ClassLoader cl) {
URL[] urls;
if(cl.equals(this)) {
urls = super.getURLs();
} else {
if(cl instanceof ServiceClassLoader) {
ServiceClassLoader scl = (ServiceClassLoader)cl;
urls = scl.getURLs();
} else {
urls = super.getURLs();
}
}
return(urls);
}
/**
* Add common JARs
*
* @param jars Array of URLs
*/
public void addCommonJARs(final URL[] jars) {
if(jars==null)
return;
for (URL jar : jars) {
if (!hasURL(jar))
addURL(jar);
}
}
/*
* Check if the URL already is registered
*/
private boolean hasURL(final URL url) {
URL[] urls = getURLs();
for (URL url1 : urls) {
if (url1.equals(url))
return (true);
}
return(false);
}
/**
* Returns a string representation of this class loader.
**/
public String toString() {
URL[] urls = doGetURLs(this);
StringBuilder buffer = new StringBuilder();
for(int i=0; i<urls.length; i++) {
if(i>0)
buffer.append(" ");
buffer.append(urls[i].toExternalForm());
}
return(super.toString()+" ["+buffer.toString()+"]");
}
}