Author: sylvain
Date: Tue Mar 8 14:49:06 2005
New Revision: 156576
URL: http://svn.apache.org/viewcvs?view=rev&rev=156576
Log:
New per-sitemap classpath
Added:
cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java
(with props)
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
(with props)
Modified:
cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles
cocoon/trunk/status.xml
Added: cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java
URL:
http://svn.apache.org/viewcvs/cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java?view=auto&rev=156576
==============================================================================
--- cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java
(added)
+++ cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java
Tue Mar 8 14:49:06 2005
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2005 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.cocoon.core;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+
+/**
+ * A <code>ClassLoader</code> factory, setting up the classpath given a
+ * <classpath> configuration.
+ *
+ * @version $Id$
+ */
+public interface ClassLoaderFactory {
+ final static String ROLE = ClassLoaderFactory.class.getName();
+
+ ClassLoader createClassLoader(ClassLoader parent, Configuration config)
throws ConfigurationException;
+}
Propchange:
cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java
------------------------------------------------------------------------------
svn:keywords = Id
Added:
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
URL:
http://svn.apache.org/viewcvs/cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java?view=auto&rev=156576
==============================================================================
---
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
(added)
+++
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
Tue Mar 8 14:49:06 2005
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2002-2005 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.cocoon.core;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLStreamHandlerFactory;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.source.TraversableSource;
+
+/**
+ * Default implementation of [EMAIL PROTECTED] ClassLoaderFactory}. It accepts
both class directory and jar
+ * directory configurations.
+ * <p>
+ * Example:
+ * <pre>
+ * <classpath>
+ * <class-dir src="BLOCK-INF/classes"/>
+ * <lib-dir src="BLOCK-INF/lib"/>
+ * &/lt;classpath>
+ *
+ */
+public class DefaultClassLoaderFactory extends AbstractLogEnabled implements
ClassLoaderFactory,
+ Serviceable, ThreadSafe, Disposable {
+
+ private ServiceManager manager;
+ private SourceResolver resolver;
+
+ /* (non-Javadoc)
+ * @see
org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+ */
+ public void service(ServiceManager manager) throws ServiceException {
+ this.manager = manager;
+ this.resolver = (SourceResolver)manager.lookup(SourceResolver.ROLE);
+ }
+
+ private URL[] parseConfiguration(Configuration config) throws
ConfigurationException {
+ List urlList = new ArrayList();
+ Configuration[] children = config.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ Configuration child = children[i];
+ String name = child.getName();
+ Source src = null;
+ try {
+ src = resolver.resolveURI(child.getAttribute("src"));
+ // A class dir: simply add its URL
+ if ("class-dir".equals(name)) {
+ urlList.add(new URL(src.getURI()));
+
+ // A lib dir: scan for all jar and zip it contains
+ } else if ("lib-dir".equals(name)) {
+ if (src instanceof TraversableSource) {
+ Iterator iter =
((TraversableSource)src).getChildren().iterator();
+ while (iter.hasNext()) {
+ Source childSrc = (Source)iter.next();
+ String childURI = childSrc.getURI();
+ resolver.release(childSrc);
+ if (childURI.endsWith(".jar") ||
childURI.endsWith(".zip")) {
+ urlList.add(new URL(childURI));
+ }
+ }
+ } else {
+ throw new ConfigurationException(src.getURI() + " is
not a directory, at " + child.getLocation());
+ }
+ } else {
+ throw new ConfigurationException("Unexpected element " +
name + " at " + child.getLocation());
+ }
+ } catch(ConfigurationException ce) {
+ resolver.release(src);
+ throw ce;
+ } catch(Exception e) {
+ resolver.release(src);
+ throw new ConfigurationException("Error loading " + name + "
at " + child.getLocation(), e);
+ }
+ }
+
+ return (URL[])urlList.toArray(new URL[urlList.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see
org.apache.cocoon.core.ClassLoaderFactory#createClassLoader(java.lang.ClassLoader)
+ */
+ public ClassLoader createClassLoader(ClassLoader parent, Configuration
config) throws ConfigurationException {
+ URL[] urls = parseConfiguration(config);
+ return new DefaultClassLoader(urls, parent);
+ }
+
+ public static class DefaultClassLoader extends URLClassLoader {
+
+ /**
+ * Alternate constructor to define a parent and initial
<code>URL</code>
+ * s.
+ */
+ public DefaultClassLoader(final URL[] urls, final ClassLoader parent) {
+ this(urls, parent, null);
+ }
+
+ /**
+ * Alternate constructor to define a parent, initial <code>URL</code>s,
+ * and a default <code>URLStreamHandlerFactory</code>.
+ */
+ public DefaultClassLoader(final URL[] urls, final ClassLoader parent,
final URLStreamHandlerFactory factory) {
+ super(urls, parent, factory);
+ }
+
+ /**
+ * Loads the class from this <code>ClassLoader</class>. If the
+ * class does not exist in this one, we check the parent. Please
+ * note that this is the exact opposite of the
+ * <code>ClassLoader</code> spec. We use it to work around
+ * inconsistent class loaders from third party vendors.
+ *
+ * @param name the name of the class
+ * @param resolve if <code>true</code> then resolve the class
+ * @return the resulting <code>Class</code> object
+ * @exception ClassNotFoundException if the class could not be found
+ */
+ public final Class loadClass(String name, boolean resolve) throws
ClassNotFoundException {
+ // First check if it's already loaded
+ Class clazz = findLoadedClass(name);
+
+ if (clazz == null) {
+
+ try {
+ clazz = findClass(name);
+ //System.err.println("Paranoid load : " + name);
+ } catch (ClassNotFoundException cnfe) {
+ ClassLoader parent = getParent();
+ if (parent != null) {
+ // Ask to parent ClassLoader (can also throw a CNFE).
+ clazz = parent.loadClass(name);
+ } else {
+ // Propagate exception
+ throw cnfe;
+ }
+ }
+ }
+
+ if (resolve) {
+ resolveClass(clazz);
+ }
+
+ return clazz;
+ }
+
+ /**
+ * Gets a resource from this <code>ClassLoader</class>. If the
+ * resource does not exist in this one, we check the parent.
+ * Please note that this is the exact opposite of the
+ * <code>ClassLoader</code> spec. We use it to work around
+ * inconsistent class loaders from third party vendors.
+ *
+ * @param name of resource
+ */
+ public final URL getResource(final String name) {
+
+ URL resource = findResource(name);
+ ClassLoader parent = this.getParent();
+ if (resource == null && parent != null) {
+ resource = parent.getResource(name);
+ }
+
+ return resource;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.avalon.framework.activity.Disposable#dispose()
+ */
+ public void dispose() {
+ this.manager.release(this.resolver);
+ }
+}
Propchange:
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles
URL:
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles?view=diff&r1=156575&r2=156576
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles Tue Mar 8 14:49:06
2005
@@ -30,6 +30,9 @@
<role-list>
+ <role name="org.apache.cocoon.core.ClassLoaderFactory"
+ default-class="org.apache.cocoon.core.DefaultClassLoaderFactory"/>
+
<role name="org.apache.excalibur.source.SourceFactorySelector"
shorthand="source-factories"
default-class="org.apache.cocoon.core.container.DefaultServiceSelector">
@@ -163,7 +166,7 @@
model="non-thread-safe-pooled"/>
<role name="org.apache.cocoon.generation.Generator/<aggregator>"
- default-class="org.apache.cocoon.sitemap.ContentAggregator"
+ default-class="org.apache.cocoon.sitemap.DefaultContentAggregator"
model="non-thread-safe-pooled"/>
<role name="org.apache.cocoon.transformation.Transformer/<translator>"
Modified: cocoon/trunk/status.xml
URL:
http://svn.apache.org/viewcvs/cocoon/trunk/status.xml?view=diff&r1=156575&r2=156576
==============================================================================
--- cocoon/trunk/status.xml (original)
+++ cocoon/trunk/status.xml Tue Mar 8 14:49:06 2005
@@ -202,6 +202,11 @@
<changes>
<release version="@version@" date="@date@">
+ <action dev="SW" type="add">
+ Each sitemap can now have its own classpath using
<code><map:classpath></code>. This allows
+ sitemap-specific components to be deployed locally with the sitemap.
Reloading the sitemap
+ recreates the classloader, thus allowing hot reloading of changed classes.
+ </action>
<action dev="CZ" type="update">
Mail block: Remove deprecated MailCommandSelector.
</action>