From ece4fd35da7b7fc76264776f81705e6b5b52d3e0 Mon Sep 17 00:00:00 2001 From: lresende Date: Wed, 11 Nov 2009 23:11:48 +0000 Subject: Moving 1.x branches git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835140 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/tuscany/common/TuscanyException.java | 133 +++++++++++++++ .../tuscany/common/TuscanyRuntimeException.java | 134 +++++++++++++++ .../apache/tuscany/common/monitor/LogLevel.java | 38 +++++ .../tuscany/common/monitor/MonitorFactory.java | 35 ++++ .../common/monitor/impl/InvalidLevelException.java | 60 +++++++ .../monitor/impl/JavaLoggingMonitorFactory.java | 186 +++++++++++++++++++++ .../common/monitor/impl/NullMonitorFactory.java | 48 ++++++ .../tuscany/common/resource/ResourceLoader.java | 90 ++++++++++ .../common/resource/impl/GeneratedClassLoader.java | 45 +++++ .../common/resource/impl/ResourceLoaderImpl.java | 137 +++++++++++++++ 10 files changed, 906 insertions(+) create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/TuscanyException.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/TuscanyRuntimeException.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/LogLevel.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/MonitorFactory.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/InvalidLevelException.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/JavaLoggingMonitorFactory.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/NullMonitorFactory.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/ResourceLoader.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/impl/GeneratedClassLoader.java create mode 100644 sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/impl/ResourceLoaderImpl.java (limited to 'sca-java-1.x/branches/java-post-M1/sca/common/src/main/java') diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/TuscanyException.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/TuscanyException.java new file mode 100644 index 0000000000..2bf802520d --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/TuscanyException.java @@ -0,0 +1,133 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common; + +import java.util.ArrayList; +import java.util.List; + +/** + * The root checked exception for the Tuscany runtime. + * + * @version $Rev: 368822 $ $Date: 2006-01-13 10:54:38 -0800 (Fri, 13 Jan 2006) $ + */ +public abstract class TuscanyException extends Exception { + private static final long serialVersionUID = -7847121698339635268L; + private List contextStack; + private String identifier; + + /** + * Override constructor from Exception. + * + * @see Exception + */ + public TuscanyException() { + super(); + } + + /** + * Override constructor from Exception. + * + * @param message passed to Exception + * @see Exception + */ + public TuscanyException(String message) { + super(message); + } + + /** + * Override constructor from Exception. + * + * @param message passed to Exception + * @param cause passed to Exception + * @see Exception + */ + public TuscanyException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Override constructor from Exception. + * + * @param cause passed to Exception + * @see Exception + */ + public TuscanyException(Throwable cause) { + super(cause); + } + + /** + * Returns a collection of names representing the context call stack where the error occured. + * The top of the stack is the first element in the collection. + * + * @return a collection of names representing the context call stack + */ + public List returnContextNames() { + if (contextStack == null) { + contextStack = new ArrayList(); + } + return contextStack; + } + + /** + * Pushes a context name where an error occured onto the call stack. + * + * @param name the name of a context to push on the stack + */ + public void addContextName(String name) { + if (contextStack == null) { + contextStack = new ArrayList(); + } + contextStack.add(name); + } + + /** + * Returns a string representing additional error information referred to in the error message. + * + * @return additional error information + */ + public String getIdentifier() { + return identifier; + } + + /** + * Sets an additional error information referred to in the error message. + * + * @param identifier additional error information + */ + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public String getMessage() { + if (identifier == null && contextStack == null) { + return super.getMessage(); + } + StringBuilder b = new StringBuilder(256); + b.append(super.getMessage()); + + if (identifier != null) { + b.append(" [").append(identifier).append(']'); + } + if (contextStack != null) { + b.append("\nContext stack trace: "); + for (int i = contextStack.size() - 1; i >= 0; i--) { + b.append('[').append(contextStack.get(i)).append(']'); + } + } + return b.toString(); + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/TuscanyRuntimeException.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/TuscanyRuntimeException.java new file mode 100644 index 0000000000..60f2e2287a --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/TuscanyRuntimeException.java @@ -0,0 +1,134 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common; + +import java.util.ArrayList; +import java.util.List; + +/** + * The root unchecked exception for the Tuscany runtime. + * + * @version $Rev: 368822 $ $Date: 2006-01-13 10:54:38 -0800 (Fri, 13 Jan 2006) $ + */ + +public abstract class TuscanyRuntimeException extends RuntimeException { + private static final long serialVersionUID = -759677431966121786L; + private List contextStack; + private String identifier; + + /** + * Override constructor from RuntimeException. + * + * @see RuntimeException + */ + public TuscanyRuntimeException() { + super(); + } + + /** + * Override constructor from RuntimeException. + * + * @param message passed to RuntimeException + * @see RuntimeException + */ + public TuscanyRuntimeException(String message) { + super(message); + } + + /** + * Override constructor from RuntimeException. + * + * @param message passed to RuntimeException + * @param cause passed to RuntimeException + * @see RuntimeException + */ + public TuscanyRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Override constructor from RuntimeException. + * + * @param cause passed to RuntimeException + * @see RuntimeException + */ + public TuscanyRuntimeException(Throwable cause) { + super(cause); + } + + /** + * Returns a collection of names representing the context call stack where the error occured. + * The top of the stack is the first element in the collection. + * + * @return a collection of names representing the context call stack + */ + public List returnContextNames() { + if (contextStack == null) { + contextStack = new ArrayList(); + } + return contextStack; + } + + /** + * Pushes a context name where an error occured onto the call stack. + * + * @param name the name of a context to push on the stack + */ + public void addContextName(String name) { + if (contextStack == null) { + contextStack = new ArrayList(); + } + contextStack.add(name); + } + + /** + * Returns a string representing additional error information referred to in the error message. + * + * @return additional error information + */ + public String getIdentifier() { + return identifier; + } + + /** + * Sets an additional error information referred to in the error message. + * + * @param identifier additional error information + */ + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public String getMessage() { + if (identifier == null && contextStack == null) { + return super.getMessage(); + } + StringBuilder b = new StringBuilder(256); + b.append(super.getMessage()); + + if (identifier != null) { + b.append(" [").append(identifier).append(']'); + } + if (contextStack != null) { + b.append("\nContext stack trace: "); + for (int i = contextStack.size() - 1; i >= 0; i--) { + b.append('[').append(contextStack.get(i)).append(']'); + } + } + return b.toString(); + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/LogLevel.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/LogLevel.java new file mode 100644 index 0000000000..45134c7556 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/LogLevel.java @@ -0,0 +1,38 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common.monitor; + +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; + +/** + * Annotation that can be applied to methods in a monitoring interface + * to indicate to logging frameworks the severity of the event. + * + * @version $Rev$ $Date$ + */ +@Target({METHOD}) +@Retention(RUNTIME) +public @interface LogLevel { + + /** + * The log level as specified by {@link java.util.logging.Level}. + */ + @SuppressWarnings({"JavaDoc"}) String value(); +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/MonitorFactory.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/MonitorFactory.java new file mode 100644 index 0000000000..aa92092005 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/MonitorFactory.java @@ -0,0 +1,35 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common.monitor; + +/** + * A MonitorFactory creates implementations of components' monitor interfaces + * that interface with a its monitoring scheme. For example, a implementation + * may create versions that emit appropriate logging events or which send + * notifications to a management API. + * + * @version $Rev$ $Date$ + */ +public interface MonitorFactory { + /** + * Return a monitor for a component's monitor interface. + * + * @param monitorInterface the component's monitoring interface + * @return an implementation of the monitoring interface; will not be null + */ + T getMonitor(Class monitorInterface); +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/InvalidLevelException.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/InvalidLevelException.java new file mode 100644 index 0000000000..baf4e8b7cc --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/InvalidLevelException.java @@ -0,0 +1,60 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common.monitor.impl; + +/** + * Exception indicating an invalid log level has been passed. + * + * @version $Rev$ $Date$ + */ +public class InvalidLevelException extends IllegalArgumentException { + private static final long serialVersionUID = 7767234706427841915L; + private final String method; + private final String level; + + /** + * Constructor specifying the method name and the level affected. + * + * @param method the name of the method being monitored + * @param level the invalid log level value + */ + public InvalidLevelException(String method, String level) { + super(); + this.method = method; + this.level = level; + } + + /** + * Returns the name of the method being monitored. + * @return the name of the method being monitored + */ + public String getMethod() { + return method; + } + + /** + * Returns the invalid log level specified. + * @return the invalid log level that was specified + */ + public String getLevel() { + return level; + } + + public String getMessage() { + return "Invalid level for method " + method + " : " + level; + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/JavaLoggingMonitorFactory.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/JavaLoggingMonitorFactory.java new file mode 100644 index 0000000000..daef77d4ae --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/JavaLoggingMonitorFactory.java @@ -0,0 +1,186 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common.monitor.impl; + +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.WeakHashMap; +import java.util.ResourceBundle; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.LogRecord; + +import org.apache.tuscany.common.monitor.LogLevel; +import org.apache.tuscany.common.monitor.MonitorFactory; + +/** + * A factory for monitors that forwards events to a {@link java.util.logging.Logger Java Logging (JSR47) Logger}. + * + * @version $Rev$ $Date$ + * @see java.util.logging + */ +public class JavaLoggingMonitorFactory implements MonitorFactory { + private final String bundleName; + private final Level defaultLevel; + private final Map levels; + + private final Map, WeakReference> proxies = new WeakHashMap, WeakReference>(); + + /** + * Construct a MonitorFactory that will monitor the specified methods at the specified levels + * and generate messages using java.util.logging. + *

+ * The supplied Properties can be used to specify custom log levels for specific monitor + * methods. The key should be the method name in form returned by + * Class.getName() + '#' + Method.getName() and the value the log level to use + * as defined by {@link java.util.logging.Level}. + * + * @param levels definition of custom levels for specific monitored methods + * @param defaultLevel the default log level to use + * @param bundleName the name of a resource bundle that will be passed to the logger + * @see java.util.logging.Logger + */ + public JavaLoggingMonitorFactory(Properties levels, Level defaultLevel, String bundleName) { + this.defaultLevel = defaultLevel; + this.bundleName = bundleName; + this.levels = new HashMap(levels.size()); + for (Map.Entry entry : levels.entrySet()) { + String method = (String) entry.getKey(); + String level = (String) entry.getValue(); + try { + this.levels.put(method, Level.parse(level)); + } catch (IllegalArgumentException e) { + throw new InvalidLevelException(method, level); + } + } + } + + public synchronized T getMonitor(Class monitorInterface) { + T proxy = getCachedMonitor(monitorInterface); + if (proxy == null) { + proxy = createMonitor(monitorInterface, bundleName); + proxies.put(monitorInterface, new WeakReference(proxy)); + } + return proxy; + } + + private T getCachedMonitor(Class monitorInterface) { + WeakReference ref = proxies.get(monitorInterface); + return (ref != null) ? monitorInterface.cast(ref.get()) : null; + } + + private T createMonitor(Class monitorInterface, String bundleName) { + String className = monitorInterface.getName(); + Logger logger = Logger.getLogger(className); + Method[] methods = monitorInterface.getMethods(); + Map levels = new HashMap(methods.length); + for (Method method : methods) { + String key = className + '#' + method.getName(); + Level level = this.levels.get(key); + + // if not specified the in config properties, look for an annotation on the method + if (level == null) { + LogLevel annotation = method.getAnnotation(LogLevel.class); + if (annotation != null && annotation.value() != null) { + try { + level = Level.parse(annotation.value()); + } catch (IllegalArgumentException e) { + // bad value, just use the default + level = defaultLevel; + } + } + } + if (level == null) { + level = defaultLevel; + } + levels.put(method.getName(), level); + } + + ResourceBundle bundle = locateBundle(monitorInterface, bundleName); + + InvocationHandler handler = new LoggingHandler(logger, levels, bundle); + return monitorInterface.cast(Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class[]{monitorInterface}, handler)); + } + + private static ResourceBundle locateBundle(Class monitorInterface, String bundleName) { + Locale locale = Locale.getDefault(); + ClassLoader cl = monitorInterface.getClassLoader(); + String packageName = monitorInterface.getPackage().getName(); + while (true) { + try { + return ResourceBundle.getBundle(packageName + '.' + bundleName, locale, cl); + } catch (MissingResourceException e) { + } + int index = packageName.lastIndexOf('.'); + if (index == -1) { + break; + } + packageName = packageName.substring(0, index); + } + try { + return ResourceBundle.getBundle(bundleName, locale, cl); + } catch (Exception e) { + return null; + } + } + + private static final class LoggingHandler implements InvocationHandler { + private final Logger logger; + private final Map methodLevels; + private final ResourceBundle bundle; + + public LoggingHandler(Logger logger, Map methodLevels, ResourceBundle bundle) { + this.logger = logger; + this.methodLevels = methodLevels; + this.bundle = bundle; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String sourceMethod = method.getName(); + Level level = methodLevels.get(sourceMethod); + if (level != null && logger.isLoggable(level)) { + // construct the key for the resource bundle + String className = logger.getName(); + String key = className + '#' + sourceMethod; + + LogRecord logRecord = new LogRecord(level, key); + logRecord.setLoggerName(className); + logRecord.setSourceClassName(className); + logRecord.setSourceMethodName(sourceMethod); + logRecord.setParameters(args); + if (args != null) { + for (Object o : args) { + if (o instanceof Throwable) { + logRecord.setThrown((Throwable) o); + break; + } + } + } + logRecord.setResourceBundle(bundle); + logger.log(logRecord); + } + return null; + } + } +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/NullMonitorFactory.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/NullMonitorFactory.java new file mode 100644 index 0000000000..827aeec84c --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/monitor/impl/NullMonitorFactory.java @@ -0,0 +1,48 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common.monitor.impl; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.apache.tuscany.common.monitor.MonitorFactory; + +/** + * Implementation of a {@link MonitorFactory} that produces implementations that simply return. + * + * @version $Rev$ $Date$ + */ +public class NullMonitorFactory implements MonitorFactory { + public T getMonitor(Class monitorInterface) { + /* + * This uses a reflection proxy to implement the monitor interface which + * is a simple but perhaps not very performant solution. Performance + * might be improved by code generating an implementation with empty methods. + */ + return monitorInterface.cast(Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class[]{monitorInterface}, NULL_MONITOR)); + } + + /** + * Singleton wire hander that does nothing. + */ + private static final InvocationHandler NULL_MONITOR = new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) { + return null; + } + }; +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/ResourceLoader.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/ResourceLoader.java new file mode 100644 index 0000000000..897c5e06c0 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/ResourceLoader.java @@ -0,0 +1,90 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common.resource; + +import java.io.IOException; +import java.net.URL; +import java.util.Iterator; +import java.util.List; + +/** + * Interface which abstracts the implementation of something that is able to + * load resources (such as a ClassLoader). All Tuscany code should use this + * API rather than a ClassLoader directly in order to reduce the risk of + * memory leaks due to ClassLoader references. + * + * @version $Rev: 379878 $ $Date: 2006-02-22 12:45:50 -0800 (Wed, 22 Feb 2006) $ + */ +public interface ResourceLoader { + + /** + * Returns the parent resource loaders. + * + * @return resource loaders that are parents to this one + */ + List getParents(); + + /** + * Loads the class with the specified binary name. + * + * @param name the binary name of the class + * @return the resulting Class object + * @throws ClassNotFoundException if the class was not found + * @see ClassLoader#loadClass(String) + */ + Class loadClass(String name) throws ClassNotFoundException; + + /** + * Converts an array of bytes into a Class. + * + * @param bytes the bytecode for the class; must match the class file format + * @return a Class defined from the supplied bytecode + */ + Class addClass(byte[] bytes); + + /** + * Finds the first resource with the given name. + *

+ * Each parent is searched first (in the order returned by {@link #getParents()}) + * and the first resource located is found. If no parent returns a resource then + * the first resource defined by this ResourceLoader is returned. + * + * @param name the resource name + * @return a {@link URL} that can be used to read the resource, or null if no resource could be found + */ + URL getResource(String name); + + /** + * Find resources with the given name that are available from this + * ResourceLoader or any of its parents. + * + * @param name the resource name + * @return an Iterator of {@link URL} objects for the resource + * @throws IOException if there was a problem locating the resources + */ + Iterator getResources(String name) throws IOException; + + //FIXME this is temporary to work around classloader problems with SDO when running in Tomcat + + /** + * Returns the underlying classloader this loader is wrapping. + * + * @return the underlying classloader this loader is wrapping + */ + ClassLoader getClassLoader(); + +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/impl/GeneratedClassLoader.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/impl/GeneratedClassLoader.java new file mode 100644 index 0000000000..953908b9f2 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/impl/GeneratedClassLoader.java @@ -0,0 +1,45 @@ +/** + * + * Copyright 2006 The Apache Software Foundation + * + * 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.apache.tuscany.common.resource.impl; + +/** + * A class loader that allows new classes to be defined from an array of bytes. + * + * @version $Rev: 369102 $ $Date: 2006-01-14 13:48:56 -0800 (Sat, 14 Jan 2006) $ + */ +@SuppressWarnings({"CustomClassloader"}) +class GeneratedClassLoader extends ClassLoader { + + /** + * Constructs a new GeneratedClassLoader. + * @param classLoader the parent classloader + */ + GeneratedClassLoader(ClassLoader classLoader) { + super(classLoader); + } + + /** + * Converts an array of bytes into a Class. + * + * @param bytes the bytecode for the class; must match the class file format + * @return a Class defined from the supplied bytecode + */ + Class addClass(byte[] bytes) { + return defineClass(null, bytes, 0, bytes.length); + } + +} diff --git a/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/impl/ResourceLoaderImpl.java b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/impl/ResourceLoaderImpl.java new file mode 100644 index 0000000000..d306edf3b4 --- /dev/null +++ b/sca-java-1.x/branches/java-post-M1/sca/common/src/main/java/org/apache/tuscany/common/resource/impl/ResourceLoaderImpl.java @@ -0,0 +1,137 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * 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.apache.tuscany.common.resource.impl; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.apache.tuscany.common.resource.ResourceLoader; + +/** + * Default implementation of the ResourceLoader interface + * + * @version $Rev: 369102 $ $Date: 2006-01-14 13:48:56 -0800 (Sat, 14 Jan 2006) $ + */ +@SuppressWarnings({"ClassLoader2Instantiation"}) +public class ResourceLoaderImpl implements ResourceLoader { + private final WeakReference classLoaderReference; + private WeakReference generatedClassLoaderReference; + private final List parents; + + /** + * Constructs a new ResourceLoaderImpl to wrap a ClassLoader. + * + * @param classLoader the classloader to wrap + */ + public ResourceLoaderImpl(ClassLoader classLoader) { + classLoaderReference = new WeakReference(classLoader); + generatedClassLoaderReference = new WeakReference(new GeneratedClassLoader(classLoader)); + ClassLoader parentCL = classLoader.getParent(); + if (null == parentCL) { + parents = Collections.emptyList(); + } else { + parents = Collections.singletonList((ResourceLoader) new ResourceLoaderImpl(parentCL)); + } + } + + + public ClassLoader getClassLoader() throws IllegalStateException { + ClassLoader cl = classLoaderReference.get(); + if (cl == null) { + throw new IllegalStateException("Referenced ClassLoader has been garbage collected"); + } + return cl; + } + + public List getParents() { + return parents; + } + + public Class loadClass(String name) throws ClassNotFoundException { + GeneratedClassLoader cl = generatedClassLoaderReference.get(); + if (cl != null) { + return Class.forName(name, true, cl); + } else { + return Class.forName(name, true, getClassLoader()); + } + } + + public Class addClass(byte[] bytes) { + GeneratedClassLoader cl = generatedClassLoaderReference.get(); + if (cl == null) { + cl = new GeneratedClassLoader(getClassLoader()); + generatedClassLoaderReference = new WeakReference(cl); + } + return cl.addClass(bytes); + } + + public Iterator getResources(String name) throws IOException { + return new EnumerationIterator(getClassLoader().getResources(name)); + } + + public URL getResource(String name) { + return getClassLoader().getResource(name); + } + + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof ResourceLoaderImpl)) { + return false; + } + final ResourceLoaderImpl other = (ResourceLoaderImpl) obj; + return getClassLoader() == other.getClassLoader(); + } + + public int hashCode() { + return getClassLoader().hashCode(); + } + + private static class EnumerationIterator implements Iterator { + private final Enumeration e; + + public EnumerationIterator(Enumeration e) { + this.e = e; + } + + public boolean hasNext() { + return e.hasMoreElements(); + } + + public E next() { + // the try/catch is needed here to get IDEA to shut up + // there should be no performance overhead here except when the Exception is thrown + // so I am going to leave it in - feel free to remove if there is any issue + try { + return e.nextElement(); + } catch (NoSuchElementException e1) { + throw e1; + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } +} -- cgit v1.2.3