Author: rfeng
Date: Tue Feb 6 16:48:21 2007
New Revision: 504392
URL: http://svn.apache.org/viewvc?view=rev&rev=504392
Log:
Copy the MultiParentClassLoader from Axis2
Added:
incubator/tuscany/java/sca/kernel/spi/src/main/java/org/apache/
tuscany/spi/util/MultiParentClassLoader.java (with props)
Added: incubator/tuscany/java/sca/kernel/spi/src/main/java/org/
apache/tuscany/spi/util/MultiParentClassLoader.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sca/kernel/
spi/src/main/java/org/apache/tuscany/spi/util/
MultiParentClassLoader.java?view=auto&rev=504392
======================================================================
========
--- incubator/tuscany/java/sca/kernel/spi/src/main/java/org/apache/
tuscany/spi/util/MultiParentClassLoader.java (added)
+++ incubator/tuscany/java/sca/kernel/spi/src/main/java/org/apache/
tuscany/spi/util/MultiParentClassLoader.java Tue Feb 6 16:48:21 2007
@@ -0,0 +1,402 @@
+/*
+ * 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.tuscany.spi.util;
+
+import java.beans.Introspector;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLStreamHandlerFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A MultiParentClassLoader is a simple extension of the
URLClassLoader that
+ * simply changes the single parent class loader model to support
a list of
+ * parent class loaders. Each operation that accesses a parent,
has been
+ * replaced with a operation that checks each parent in order.
This getParent
+ * method of this class will always return null, which may be
interpreted by the
+ * calling code to mean that this class loader is a direct child
of the system
+ * class loader.
+ *
+ * @version $Rev$ $Date$
+ */
+public class MultiParentClassLoader extends URLClassLoader {
+ private boolean destroyed;
+ private final String[] hiddenClasses;
+ private final String[] hiddenResources;
+ private final boolean inverseClassLoading;
+ private final String[] nonOverridableClasses;
+ private final String[] nonOverridableResources;
+
+ private final ClassLoader[] parents;
+
+ /**
+ * Creates a named class loader with no parents.
+ *
+ * @param urls the urls from which this class loader will
classes and
+ * resources
+ */
+ public MultiParentClassLoader(URL[] urls) {
+ super(urls);
+ parents = new ClassLoader[]
{ClassLoader.getSystemClassLoader()};
+ inverseClassLoading = false;
+ hiddenClasses = new String[0];
+ nonOverridableClasses = new String[0];
+ hiddenResources = new String[0];
+ nonOverridableResources = new String[0];
+ }
+
+ /**
+ * Creates a named class loader as a child of the specified
parent.
+ *
+ * @param urls the urls from which this class loader will
classes and
+ * resources
+ * @param parent the parent of this class loader
+ */
+ public MultiParentClassLoader(URL[] urls, ClassLoader parent) {
+ this(urls, new ClassLoader[] {parent});
+ }
+
+ public MultiParentClassLoader(URL[] urls,
+ ClassLoader parent,
+ boolean inverseClassLoading,
+ String[] hiddenClasses,
+ String[] nonOverridableClasses) {
+ this(urls, new ClassLoader[] {parent},
inverseClassLoading, hiddenClasses, nonOverridableClasses);
+ }
+
+ /**
+ * Creates a named class loader as a child of the specified
parent and using
+ * the specified URLStreamHandlerFactory for accessing the urls..
+ *
+ * @param urls the urls from which this class loader will
classes and
+ * resources
+ * @param parent the parent of this class loader
+ * @param factory the URLStreamHandlerFactory used to access
the urls
+ */
+ public MultiParentClassLoader(URL[] urls, ClassLoader parent,
URLStreamHandlerFactory factory) {
+ this(urls, new ClassLoader[] {parent}, factory);
+ }
+
+ /**
+ * Creates a named class loader as a child of the specified
parents.
+ *
+ * @param urls the urls from which this class loader will
classes and
+ * resources
+ * @param parents the parents of this class loader
+ */
+ public MultiParentClassLoader(URL[] urls, ClassLoader[]
parents) {
+ super(urls);
+ this.parents = copyParents(parents);
+ inverseClassLoading = false;
+ hiddenClasses = new String[0];
+ nonOverridableClasses = new String[0];
+ hiddenResources = new String[0];
+ nonOverridableResources = new String[0];
+ }
+
+ public MultiParentClassLoader(URL[] urls,
+ ClassLoader[] parents,
+ boolean inverseClassLoading,
+ Collection<String> hiddenClasses,
+ Collection<String>
nonOverridableClasses) {
+ this(urls, parents, inverseClassLoading, (String[])
hiddenClasses.toArray(new String[hiddenClasses.size()]),
+ (String[])nonOverridableClasses.toArray(new String
[nonOverridableClasses.size()]));
+ }
+
+ public MultiParentClassLoader(URL[] urls,
+ ClassLoader[] parents,
+ boolean inverseClassLoading,
+ String[] hiddenClasses,
+ String[] nonOverridableClasses) {
+ super(urls);
+ this.parents = copyParents(parents);
+ this.inverseClassLoading = inverseClassLoading;
+ this.hiddenClasses = hiddenClasses;
+ this.nonOverridableClasses = nonOverridableClasses;
+ hiddenResources = toResources(hiddenClasses);
+ nonOverridableResources = toResources(nonOverridableClasses);
+ }
+
+ /**
+ * Creates a named class loader as a child of the specified
parents and
+ * using the specified URLStreamHandlerFactory for accessing
the urls..
+ *
+ * @param urls the urls from which this class loader will
classes and
+ * resources
+ * @param parents the parents of this class loader
+ * @param factory the URLStreamHandlerFactory used to access
the urls
+ */
+ public MultiParentClassLoader(URL[] urls, ClassLoader[]
parents, URLStreamHandlerFactory factory) {
+ super(urls, null, factory);
+ this.parents = copyParents(parents);
+ inverseClassLoading = false;
+ hiddenClasses = new String[0];
+ nonOverridableClasses = new String[0];
+ hiddenResources = new String[0];
+ nonOverridableResources = new String[0];
+ }
+
+ private static ClassLoader[] copyParents(ClassLoader[] parents) {
+ ClassLoader[] newParentsArray = new ClassLoader
[parents.length];
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader parent = parents[i];
+ if (parent == null) {
+ throw new RuntimeException("parent[" + i + "] is
null");
+ }
+ newParentsArray[i] = parent;
+ }
+ return newParentsArray;
+ }
+
+ public void addURL(URL url) {
+ // todo this needs a security check
+ super.addURL(url);
+ }
+
+ public void destroy() {
+ synchronized (this) {
+ if (destroyed) {
+ return;
+ }
+ destroyed = true;
+ }
+
+ // clearSoftCache(ObjectInputStream.class, "subclassAudits");
+ // clearSoftCache(ObjectOutputStream.class,
"subclassAudits");
+ // clearSoftCache(ObjectStreamClass.class, "localDescs");
+ // clearSoftCache(ObjectStreamClass.class, "reflectors");
+
+ // The beanInfoCache in java.beans.Introspector will hold
on to Classes
+ // which
+ // it has introspected. If we don't flush the cache, we
may run out of
+ // Permanent Generation space.
+ Introspector.flushCaches();
+ }
+
+ public Enumeration<URL> findResources(String name) throws
IOException {
+ if (isDestroyed()) {
+ Set<URL> emptySet = Collections.emptySet();
+ return Collections.enumeration(emptySet);
+ }
+
+ List<URL> resources = new ArrayList<URL>();
+
+ //
+ // if we are using inverse class loading, add the
resources from local
+ // urls first
+ //
+ if (inverseClassLoading && !isDestroyed()) {
+ List<URL> myResources = Collections.list
(super.findResources(name));
+ resources.addAll(myResources);
+ }
+
+ //
+ // Add parent resources
+ //
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader parent = parents[i];
+ List<URL> parentResources = Collections.list
(parent.getResources(name));
+ resources.addAll(parentResources);
+ }
+
+ //
+ // if we are not using inverse class loading, add the
resources from
+ // local urls now
+ //
+ if (!inverseClassLoading && !isDestroyed()) {
+ List<URL> myResources = Collections.list
(super.findResources(name));
+ resources.addAll(myResources);
+ }
+
+ return Collections.enumeration(resources);
+ }
+
+ /**
+ * Gets the parents of this class loader.
+ *
+ * @return the parents of this class loader
+ */
+ public ClassLoader[] getParents() {
+ return parents;
+ }
+
+ public URL getResource(String name) {
+ if (isDestroyed()) {
+ return null;
+ }
+
+ //
+ // if we are using inverse class loading, check local urls
first
+ //
+ if (inverseClassLoading && !isDestroyed() && !
isNonOverridableResource(name)) {
+ URL url = findResource(name);
+ if (url != null) {
+ return url;
+ }
+ }
+
+ //
+ // Check parent class loaders
+ //
+ if (!isHiddenResource(name)) {
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader parent = parents[i];
+ URL url = parent.getResource(name);
+ if (url != null) {
+ return url;
+ }
+ }
+ }
+
+ //
+ // if we are not using inverse class loading, check local
urls now
+ //
+ // don't worry about excluding non-overridable resources
here... we
+ // have alredy checked he parent and the parent didn't
have the
+ // resource, so we can override now
+ if (!isDestroyed()) {
+ // parents didn't have the resource; attempt to load
it from my urls
+ return findResource(name);
+ }
+
+ return null;
+ }
+
+ public synchronized boolean isDestroyed() {
+ return destroyed;
+ }
+
+ private boolean isHiddenClass(String name) {
+ for (int i = 0; i < hiddenClasses.length; i++) {
+ if (name.startsWith(hiddenClasses[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isHiddenResource(String name) {
+ for (int i = 0; i < hiddenResources.length; i++) {
+ if (name.startsWith(hiddenResources[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isNonOverridableClass(String name) {
+ for (int i = 0; i < nonOverridableClasses.length; i++) {
+ if (name.startsWith(nonOverridableClasses[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isNonOverridableResource(String name) {
+ for (int i = 0; i < nonOverridableResources.length; i++) {
+ if (name.startsWith(nonOverridableResources[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected synchronized Class loadClass(String name, boolean
resolve) throws ClassNotFoundException {
+ //
+ // Check if class is in the loaded classes cache
+ //
+ Class cachedClass = findLoadedClass(name);
+ if (cachedClass != null) {
+ return resolveClass(cachedClass, resolve);
+ }
+
+ //
+ // if we are using inverse class loading, check local urls
first
+ //
+ if (inverseClassLoading && !isDestroyed() && !
isNonOverridableClass(name)) {
+ try {
+ Class clazz = findClass(name);
+ return resolveClass(clazz, resolve);
+ } catch (ClassNotFoundException ignored) {
+ // Ignore it
+ }
+ }
+
+ //
+ // Check parent class loaders
+ //
+ if (!isHiddenClass(name)) {
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader parent = parents[i];
+ try {
+ Class clazz = parent.loadClass(name);
+ return resolveClass(clazz, resolve);
+ } catch (ClassNotFoundException ignored) {
+ // this parent didn't have the class; try the
next one
+ }
+ }
+ }
+
+ //
+ // if we are not using inverse class loading, check local
urls now
+ //
+ // don't worry about excluding non-overridable classes
here... we
+ // have alredy checked he parent and the parent didn't
have the
+ // class, so we can override now
+ if (!isDestroyed()) {
+ try {
+ Class clazz = findClass(name);
+ return resolveClass(clazz, resolve);
+ } catch (ClassNotFoundException ignored) {
+ // Ignore it
+ }
+ }
+
+ throw new ClassNotFoundException(name);
+ }
+
+ private Class resolveClass(Class clazz, boolean resolve) {
+ if (resolve) {
+ resolveClass(clazz);
+ }
+ return clazz;
+ }
+
+ private String[] toResources(String[] classes) {
+ String[] resources = new String[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ String className = classes[i];
+ resources[i] = className.replace('.', '/');
+ }
+ return resources;
+ }
+
+ public String toString() {
+ return "[" + getClass().getName() + "]";
+ }
+
+}
Propchange: incubator/tuscany/java/sca/kernel/spi/src/main/java/org/
apache/tuscany/spi/util/MultiParentClassLoader.java
----------------------------------------------------------------------
--------
svn:eol-style = native
Propchange: incubator/tuscany/java/sca/kernel/spi/src/main/java/org/
apache/tuscany/spi/util/MultiParentClassLoader.java
----------------------------------------------------------------------
--------
svn:keywords = Rev Date
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]