You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2006/02/17 18:20:05 UTC
svn commit: r378575 - in
/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon: ./ core/
core/container/spring/
Author: cziegeler
Date: Fri Feb 17 09:20:03 2006
New Revision: 378575
URL: http://svn.apache.org/viewcvs?rev=378575&view=rev
Log:
Spring based container works now for core (apart from tree processor)
Added:
cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/SpringCoreUtil.java (with props)
Modified:
cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/SpringCocoon.java
cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java
cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ApplicationContextFactory.java
cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/CocoonXmlWebApplicationContext.java
cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/XmlConfigCreator.java
Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/SpringCocoon.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/SpringCocoon.java?rev=378575&r1=378574&r2=378575&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/SpringCocoon.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/SpringCocoon.java Fri Feb 17 09:20:03 2006
@@ -33,6 +33,9 @@
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.environment.internal.EnvironmentHelper;
import org.apache.commons.lang.SystemUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
/**
* The Cocoon Object is the main Kernel for the entire Cocoon system.
@@ -40,7 +43,7 @@
* @version $Id$
*/
public class SpringCocoon
- implements Processor {
+ implements Processor, BeanFactoryAware {
/** Active request count. */
private volatile int activeRequestCount;
@@ -51,11 +54,8 @@
/** The environment helper. */
protected final EnvironmentHelper environmentHelper;
- /** An optional component that is called before and after processing all requests. */
- protected RequestListener requestListener;
-
/** Processor attributes. */
- protected Map processorAttributes = new HashMap();
+ protected final Map processorAttributes = new HashMap();
/** The service manager. */
protected final ServiceManager serviceManager;
@@ -63,6 +63,9 @@
/** The logger. */
protected final Logger logger;
+ /** An optional component that is called before and after processing all requests. */
+ protected RequestListener requestListener;
+
/**
* Creates a new <code>Cocoon</code> instance.
*/
@@ -81,10 +84,13 @@
}
/**
- * Set the (optional) request listener.
+ * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
- public void setRequestListener(RequestListener listener) {
- this.requestListener = listener;
+ public void setBeanFactory(BeanFactory factory) throws BeansException {
+ // get the optional request listener
+ if ( factory.containsBean(RequestListener.ROLE) ) {
+ this.requestListener = (RequestListener)factory.getBean(RequestListener.ROLE);
+ }
}
/**
@@ -191,8 +197,7 @@
throws Exception {
environment.startingProcessing();
final int environmentDepth = EnvironmentHelper.markEnvironment();
- // FIXME
- //EnvironmentHelper.enterProcessor(this, this.serviceManager, environment);
+ EnvironmentHelper.enterProcessor(this, this.serviceManager, environment);
try {
boolean result;
if (this.logger.isDebugEnabled()) {
Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java?rev=378575&r1=378574&r2=378575&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/CoreUtil.java Fri Feb 17 09:20:03 2006
@@ -31,8 +31,6 @@
import java.util.Map;
import java.util.Properties;
-import javax.servlet.ServletConfig;
-
import org.apache.avalon.excalibur.logger.Log4JConfLoggerManager;
import org.apache.avalon.excalibur.logger.LoggerManageable;
import org.apache.avalon.excalibur.logger.LoggerManager;
@@ -54,17 +52,12 @@
import org.apache.cocoon.components.container.ComponentContext;
import org.apache.cocoon.configuration.ConfigurationBuilder;
import org.apache.cocoon.core.container.SingleComponentServiceManager;
-import org.apache.cocoon.core.container.spring.ApplicationContextFactory;
-import org.apache.cocoon.core.container.spring.AvalonEnvironment;
-import org.apache.cocoon.core.container.spring.ConfigReader;
-import org.apache.cocoon.core.container.spring.ConfigurationInfo;
import org.apache.cocoon.core.logging.CocoonLogKitLoggerManager;
import org.apache.cocoon.core.logging.PerRequestLoggerManager;
import org.apache.cocoon.core.logging.SettingsContext;
import org.apache.cocoon.core.source.SimpleSourceResolver;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.matching.helpers.WildcardHelper;
-import org.apache.cocoon.servlet.CocoonServlet;
import org.apache.cocoon.util.ClassUtils;
import org.apache.cocoon.util.StringUtils;
import org.apache.cocoon.util.location.Location;
@@ -73,7 +66,6 @@
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.source.TraversableSource;
-import org.springframework.context.ApplicationContext;
/**
* This is an utility class to create a new Cocoon instance.
@@ -335,9 +327,6 @@
// The Cocoon container fetches the Core object using the context.
// FIXME - We shouldn't need this - check where it is used
this.appContext.put(Core.ROLE, core);
-
- // test the setup of the spring based container
- this.testSpringContainer();
}
/**
@@ -920,20 +909,6 @@
return this.loggerManager.getLoggerForCategory(rootlogger);
}
return this.log;
- }
-
- protected void testSpringContainer() throws Exception {
- System.out.println("Setting up test Spring container...");
- AvalonEnvironment env = new AvalonEnvironment();
- env.context = this.appContext;
- env.core = this.core;
- env.logger = this.log;
- env.servletContext = ((ServletConfig)this.appContext.get(CocoonServlet.CONTEXT_SERVLET_CONFIG)).getServletContext();
- env.settings = this.core.getSettings();
- ApplicationContext rootContext = ApplicationContextFactory.createRootApplicationContext(env);
- ConfigurationInfo result = ConfigReader.readConfiguration(settings.getConfiguration(), env);
- ApplicationContext mainContext = ApplicationContextFactory.createApplicationContext(env, result, rootContext);
- System.out.println("Getting core cocoon processor context: " + mainContext.getBean(Core.ROLE));
}
/**
Added: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/SpringCoreUtil.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/SpringCoreUtil.java?rev=378575&view=auto
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/SpringCoreUtil.java (added)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/SpringCoreUtil.java Fri Feb 17 09:20:03 2006
@@ -0,0 +1,909 @@
+/*
+ * Copyright 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.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.DefaultContext;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.cocoon.Cocoon;
+import org.apache.cocoon.Constants;
+import org.apache.cocoon.Modifiable;
+import org.apache.cocoon.Processor;
+import org.apache.cocoon.components.ContextHelper;
+import org.apache.cocoon.components.container.ComponentContext;
+import org.apache.cocoon.core.container.spring.ApplicationContextFactory;
+import org.apache.cocoon.core.container.spring.AvalonEnvironment;
+import org.apache.cocoon.core.container.spring.ConfigReader;
+import org.apache.cocoon.core.container.spring.ConfigurationInfo;
+import org.apache.cocoon.core.source.SimpleSourceResolver;
+import org.apache.cocoon.servlet.CocoonServlet;
+import org.apache.cocoon.util.ClassUtils;
+import org.apache.cocoon.util.StringUtils;
+import org.apache.cocoon.util.location.Location;
+import org.apache.cocoon.util.location.LocationImpl;
+import org.apache.cocoon.util.location.LocationUtils;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.source.TraversableSource;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * This is an utility class to create a new Cocoon instance.
+ *
+ * @version $Id$
+ * @since 2.2
+ */
+public class SpringCoreUtil {
+
+ /** Parameter map for the context protocol */
+ protected static final Map CONTEXT_PARAMETERS = Collections.singletonMap("force-traversable", Boolean.TRUE);
+
+ /** The callback to the real environment. */
+ protected final BootstrapEnvironment env;
+
+ /** "legacy" support: create an avalon context. */
+ protected final DefaultContext appContext = new ComponentContext();
+
+ /** The settings. */
+ protected MutableSettings settings;
+
+ /** The root logger. */
+ protected Logger log;
+
+ /** The Root processor instance */
+ protected Processor processor;
+
+ protected ClassLoader classloader;
+
+ /** The core object. */
+ protected Core core;
+
+ /** The servlet context. */
+ protected final ServletContext servletContext;
+
+ /** The container. */
+ protected ApplicationContext container;
+
+ // Register the location finder for Avalon configuration objects and exceptions
+ // and keep a strong reference to it.
+ private static final LocationUtils.LocationFinder confLocFinder = new LocationUtils.LocationFinder() {
+ public Location getLocation(Object obj, String description) {
+ if (obj instanceof Configuration) {
+ Configuration config = (Configuration)obj;
+ String locString = config.getLocation();
+ Location result = LocationUtils.parse(locString);
+ if (LocationUtils.isKnown(result)) {
+ // Add description
+ StringBuffer desc = new StringBuffer().append('<');
+ // Unfortunately Configuration.getPrefix() is not public
+ try {
+ if (config.getNamespace().startsWith("http://apache.org/cocoon/sitemap/")) {
+ desc.append("map:");
+ }
+ } catch (ConfigurationException e) {
+ // no namespace: ignore
+ }
+ desc.append(config.getName()).append('>');
+ return new LocationImpl(desc.toString(), result);
+ } else {
+ return result;
+ }
+ }
+
+ if (obj instanceof Exception) {
+ // Many exceptions in Cocoon have a message like "blah blah at file://foo/bar.xml:12:1"
+ String msg = ((Exception)obj).getMessage();
+ if (msg == null) return null;
+
+ int pos = msg.lastIndexOf(" at ");
+ if (pos != -1) {
+ return LocationUtils.parse(msg.substring(pos + 4));
+ } else {
+ // Will try other finders
+ return null;
+ }
+ }
+
+ // Try next finders.
+ return null;
+ }
+ };
+
+ static {
+ LocationUtils.addFinder(confLocFinder);
+ }
+
+ /**
+ * Setup a new instance.
+ * @param environment The hook back to the environment.
+ * @throws Exception
+ */
+ public SpringCoreUtil(BootstrapEnvironment environment,
+ ServletContext context)
+ throws Exception {
+ this.servletContext = context;
+ this.env = environment;
+ this.init();
+ this.createClassloader();
+ }
+
+ protected void init()
+ throws Exception {
+ // first let's set up the appContext with some values to make
+ // the simple source resolver work
+
+ // add root url
+ try {
+ appContext.put(ContextHelper.CONTEXT_ROOT_URL,
+ new URL(this.env.getContextURL()));
+ } catch (MalformedURLException ignore) {
+ // we simply ignore this
+ }
+
+ // add environment context
+ this.appContext.put(Constants.CONTEXT_ENVIRONMENT_CONTEXT,
+ this.env.getEnvironmentContext());
+
+ // now add environment specific information
+ this.env.configure(appContext);
+
+ // create settings
+ this.settings = this.createSettings();
+
+ // first init the work-directory for the logger.
+ // this is required if we are running inside a war file!
+ final String workDirParam = this.settings.getWorkDirectory();
+ File workDir;
+ if (workDirParam != null) {
+ if (this.env.getContextForWriting() == null) {
+ // No context path : consider work-directory as absolute
+ workDir = new File(workDirParam);
+ } else {
+ // Context path exists : is work-directory absolute ?
+ File workDirParamFile = new File(workDirParam);
+ if (workDirParamFile.isAbsolute()) {
+ // Yes : keep it as is
+ workDir = workDirParamFile;
+ } else {
+ // No : consider it relative to context path
+ workDir = new File(this.env.getContextForWriting(), workDirParam);
+ }
+ }
+ } else {
+ workDir = new File("cocoon-files");
+ }
+ workDir.mkdirs();
+ this.appContext.put(Constants.CONTEXT_WORK_DIR, workDir);
+ this.settings.setWorkDirectory(workDir.getAbsolutePath());
+
+ // Init logger
+ this.log = ApplicationContextFactory.createRootLogger(servletContext, this.settings.getCocoonLogger());
+ this.env.setLogger(this.log);
+
+ // Output some debug info
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Context URL: " + this.env.getContextURL());
+ this.log.debug("Writeable Context: " + this.env.getContextForWriting());
+ if (workDirParam != null) {
+ this.log.debug("Using work-directory " + workDir);
+ } else {
+ this.log.debug("Using default work-directory " + workDir);
+ }
+ }
+
+ final String uploadDirParam = this.settings.getUploadDirectory();
+ File uploadDir;
+ if (uploadDirParam != null) {
+ if (this.env.getContextForWriting() == null) {
+ uploadDir = new File(uploadDirParam);
+ } else {
+ // Context path exists : is upload-directory absolute ?
+ File uploadDirParamFile = new File(uploadDirParam);
+ if (uploadDirParamFile.isAbsolute()) {
+ // Yes : keep it as is
+ uploadDir = uploadDirParamFile;
+ } else {
+ // No : consider it relative to context path
+ uploadDir = new File(this.env.getContextForWriting(), uploadDirParam);
+ }
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Using upload-directory " + uploadDir);
+ }
+ } else {
+ uploadDir = new File(workDir, "upload-dir" + File.separator);
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Using default upload-directory " + uploadDir);
+ }
+ }
+ uploadDir.mkdirs();
+ appContext.put(Constants.CONTEXT_UPLOAD_DIR, uploadDir);
+ this.settings.setUploadDirectory(uploadDir.getAbsolutePath());
+
+ String cacheDirParam = this.settings.getCacheDirectory();
+ File cacheDir;
+ if (cacheDirParam != null) {
+ if (this.env.getContextForWriting() == null) {
+ cacheDir = new File(cacheDirParam);
+ } else {
+ // Context path exists : is cache-directory absolute ?
+ File cacheDirParamFile = new File(cacheDirParam);
+ if (cacheDirParamFile.isAbsolute()) {
+ // Yes : keep it as is
+ cacheDir = cacheDirParamFile;
+ } else {
+ // No : consider it relative to context path
+ cacheDir = new File(this.env.getContextForWriting(), cacheDirParam);
+ }
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Using cache-directory " + cacheDir);
+ }
+ } else {
+ cacheDir = new File(workDir, "cache-dir" + File.separator);
+ File parent = cacheDir.getParentFile();
+ if (parent != null) {
+ parent.mkdirs();
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("cache-directory was not set - defaulting to " + cacheDir);
+ }
+ }
+ cacheDir.mkdirs();
+ appContext.put(Constants.CONTEXT_CACHE_DIR, cacheDir);
+ this.settings.setCacheDirectory(cacheDir.getAbsolutePath());
+
+ // update configuration
+ final URL u = this.env.getConfigFile(this.settings.getConfiguration());
+ this.settings.setConfiguration(u.toExternalForm());
+ this.appContext.put(Constants.CONTEXT_CONFIG_URL, u);
+
+ // set encoding
+ this.appContext.put(Constants.CONTEXT_DEFAULT_ENCODING, settings.getFormEncoding());
+
+ // set class loader
+ this.appContext.put(Constants.CONTEXT_CLASS_LOADER, this.classloader);
+
+ // Set the system properties needed by Xalan2.
+ // FIXME Do we still need this?
+ this.setSystemProperties();
+
+ // dump system properties
+ this.dumpSystemProperties();
+
+ // create the Core object
+ this.core = this.createCore();
+
+ // settings can't be changed anymore
+ settings.makeReadOnly();
+
+ // put the core into the context - this is for internal use only
+ // The Cocoon container fetches the Core object using the context.
+ // FIXME - We shouldn't need this - check where it is used
+ this.appContext.put(Core.ROLE, core);
+
+ // test the setup of the spring based container
+ this.container = this.setupSpringContainer();
+ }
+
+ /**
+ * Return the core object.
+ */
+ public Core getCore() {
+ return this.core;
+ }
+
+ /**
+ * Create a new core instance.
+ * This method can be overwritten in sub classes.
+ * @return A new core object.
+ */
+ protected Core createCore() {
+ final Core c = new Core(this.settings, this.appContext);
+ return c;
+ }
+
+ /**
+ * Return the settings object.
+ */
+ public Settings getSettings() {
+ return this.settings;
+ }
+
+ /**
+ * Get the settings for Cocoon.
+ * This method reads several property files and merges the result. If there
+ * is more than one definition for a property, the last one wins.
+ * The property files are read in the following order:
+ * 1) context://WEB-INF/properties/*.properties
+ * Default values for the core and each block - the order in which the files are read is not guaranteed.
+ * 2) context://WEB-INF/properties/[RUNNING_MODE]/*.properties
+ * Default values for the running mode - the order in which the files are read is not guaranteed.
+ * 3) Property providers (ToBeDocumented)
+ * 4) The environment (CLI, Servlet etc.) adds own properties (e.g. from web.xml)
+ * 5) Additional property file specified by the "org.apache.cocoon.settings" system property or
+ * if the property is not found, the file ".cocoon/settings.properties" is tried to be read from
+ * the user directory.
+ * 6) System properties
+ *
+ * @return A new Settings object
+ */
+ protected MutableSettings createSettings() {
+ // get the running mode
+ final String mode = System.getProperty(Settings.PROPERTY_RUNNING_MODE, Settings.DEFAULT_RUNNING_MODE);
+ this.env.log("Running in mode: " + mode);
+
+ // create an empty settings objects
+ final MutableSettings s = new MutableSettings();
+
+ // we need our own resolver
+ final SourceResolver resolver = this.createSourceResolver(new LoggerWrapper(this.env));
+
+ // now read all properties from the properties directory
+ this.readProperties("context://WEB-INF/properties", s, resolver);
+ // read all properties from the mode dependent directory
+ this.readProperties("context://WEB-INF/properties/" + mode, s, resolver);
+
+ // Next look for custom property providers
+ Iterator i = s.getPropertyProviders().iterator();
+ while ( i.hasNext() ) {
+ final String className = (String)i.next();
+ try {
+ PropertyProvider provider = (PropertyProvider)ClassUtils.newInstance(className);
+ s.fill(provider.getProperties());
+ } catch (Exception ignore) {
+ env.log("Unable to get property provider for class " + className, ignore);
+ env.log("Continuing initialization.");
+ }
+ }
+ // fill from the environment configuration, like web.xml etc.
+ env.configure(s);
+
+ // read additional properties file
+ String additionalPropertyFile = s.getProperty(Settings.PROPERTY_USER_SETTINGS,
+ System.getProperty(Settings.PROPERTY_USER_SETTINGS));
+ // if there is no property defining the addition file, we try it in the home directory
+ if ( additionalPropertyFile == null ) {
+ additionalPropertyFile = System.getProperty("user.home") + File.separator + ".cocoon/settings.properties";
+ final File testFile = new File(additionalPropertyFile);
+ if ( !testFile.exists() ) {
+ additionalPropertyFile = null;
+ }
+ }
+ if ( additionalPropertyFile != null ) {
+ env.log("Reading user settings from '" + additionalPropertyFile + "'");
+ final Properties p = new Properties();
+ try {
+ FileInputStream fis = new FileInputStream(additionalPropertyFile);
+ p.load(fis);
+ fis.close();
+ } catch (IOException ignore) {
+ env.log("Unable to read '" + additionalPropertyFile + "'.", ignore);
+ env.log("Continuing initialization.");
+ }
+ }
+ // now overwrite with system properties
+ s.fill(System.getProperties());
+
+ return s;
+ }
+
+ /**
+ * Dump System Properties.
+ */
+ protected void dumpSystemProperties() {
+ if (this.log.isDebugEnabled()) {
+ try {
+ Enumeration e = System.getProperties().propertyNames();
+ this.log.debug("===== System Properties Start =====");
+ for (; e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ this.log.debug(key + "=" + System.getProperty(key));
+ }
+ this.log.debug("===== System Properties End =====");
+ } catch (SecurityException se) {
+ // Ignore Exceptions.
+ }
+ }
+ }
+
+ /**
+ * Sets required system properties.
+ */
+ protected void setSystemProperties() {
+ try {
+ // FIXME We shouldn't have to specify the SAXParser...
+ // This is needed by Xalan2, it is used by org.xml.sax.helpers.XMLReaderFactory
+ // to locate the SAX2 driver.
+ if (getSystemProperty("org.xml.sax.driver", null) == null) {
+ System.setProperty("org.xml.sax.driver", "org.apache.xerces.parsers.SAXParser");
+ }
+ } catch (SecurityException e) {
+ // Ignore security exceptions
+ System.out.println("Caught a SecurityException writing the system property: " + e);
+ }
+
+ try {
+ // FIXME We shouldn't have to specify these. Needed to override jaxp implementation of weblogic.
+ if (getSystemProperty("javax.xml.parsers.DocumentBuilderFactory", "").startsWith("weblogic")) {
+ System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
+ System.setProperty("javax.xml.parsers.SAXParserFactory","org.apache.xerces.jaxp.SAXParserFactoryImpl");
+ }
+ } catch (SecurityException e) {
+ // Ignore security exceptions
+ System.out.println("Caught a SecurityException writing the system property: " + e);
+ }
+ }
+
+ /**
+ * Helper method to retrieve system property.
+ * Returns default value if SecurityException is caught.
+ */
+ protected String getSystemProperty(String property, String value) {
+ try {
+ return System.getProperty(property, value);
+ } catch (SecurityException e) {
+ System.err.println("Caught a SecurityException reading the system property '" + property + "';" +
+ " Cocoon will default to '" + value + "' value.");
+ return value;
+ }
+ }
+
+ /**
+ * Read all property files from the given directory and apply them to the settings.
+ */
+ protected void readProperties(String directoryName,
+ MutableSettings s,
+ SourceResolver resolver) {
+ Source directory = null;
+ try {
+ directory = resolver.resolveURI(directoryName, null, CONTEXT_PARAMETERS);
+ if (directory.exists() && directory instanceof TraversableSource) {
+ final Iterator c = ((TraversableSource) directory).getChildren().iterator();
+ while (c.hasNext()) {
+ final Source src = (Source) c.next();
+ if ( src.getURI().endsWith(".properties") ) {
+ final InputStream propsIS = src.getInputStream();
+ env.log("Reading settings from '" + src.getURI() + "'.");
+ final Properties p = new Properties();
+ p.load(propsIS);
+ propsIS.close();
+ s.fill(p);
+ }
+ }
+ }
+ } catch (IOException ignore) {
+ env.log("Unable to read from directory 'WEB-INF/properties'.", ignore);
+ env.log("Continuing initialization.");
+ } finally {
+ resolver.release(directory);
+ }
+ }
+
+ /**
+ * Create a simple source resolver.
+ */
+ protected SourceResolver createSourceResolver(Logger logger) {
+ // Create our own resolver
+ final SimpleSourceResolver resolver = new SimpleSourceResolver();
+ resolver.enableLogging(logger);
+ try {
+ resolver.contextualize(this.appContext);
+ } catch (ContextException ce) {
+ throw new CoreInitializationException(
+ "Cannot setup source resolver.", ce);
+ }
+ return resolver;
+ }
+
+ /**
+ * Create the classloader that inlcudes all the [block]/BLOCK-INF/classes directories.
+ * @throws Exception
+ */
+ protected void createClassloader() throws Exception {
+ // get the wiring
+ final SourceResolver resolver = this.createSourceResolver(this.log);
+ Source wiringSource = null;
+ final Configuration wiring;
+ try {
+ wiringSource = resolver.resolveURI(Constants.WIRING);
+ DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
+ wiring = builder.build( wiringSource.getInputStream() );
+ } catch(org.apache.excalibur.source.SourceNotFoundException snfe) {
+ throw new WiringNotFoundException("wiring.xml not found in the root directory of your Cocoon application.");
+ } finally {
+ resolver.release(wiringSource);
+ }
+
+ // get all wired blocks and add their classed directory to the classloader
+ List urlList = new ArrayList();
+ Configuration[] blocks = wiring.getChildren("block");
+ for(int i = 0; i < blocks.length; i++) {
+ String location = blocks[i].getAttribute("location");
+ if(this.log.isDebugEnabled()) {
+ this.log.debug("Found block " + blocks[i].getAttribute("id") + " at " + location);
+ }
+ Source classesDir = null;
+ try {
+ classesDir = resolver.resolveURI(location + "/" + Constants.BLOCK_META_DIR + "/classes");
+ if(classesDir.exists()) {
+ String classesDirURI = classesDir.getURI();
+ urlList.add(new URL(classesDirURI));
+ if(this.log.isDebugEnabled()) {
+ this.log.debug("added " + classesDir.getURI());
+ }
+ }
+ } finally {
+ resolver.release(classesDir);
+ }
+ }
+
+ // setup the classloader using the current classloader as parent
+ ClassLoader parentClassloader = Thread.currentThread().getContextClassLoader();
+ URL[] urls = (URL[]) urlList.toArray(new URL[urlList.size()]);
+ URLClassLoader classloader = new URLClassLoader(urls, parentClassloader);
+ Thread.currentThread().setContextClassLoader(classloader);
+ this.classloader = Thread.currentThread().getContextClassLoader();
+ }
+
+ /**
+ * Creates the Cocoon object and handles exception handling.
+ */
+ public synchronized Cocoon createCocoon()
+ throws Exception {
+ this.createProcessor();
+ return (Cocoon)this.processor;
+ }
+
+ /**
+ * Gets the current cocoon object.
+ * Reload cocoon if configuration changed or we are reloading.
+ * Ensure that the correct classloader is set.
+ */
+ public Cocoon getCocoon(final String pathInfo, final String reloadParam)
+ throws Exception {
+ this.getProcessor(pathInfo, reloadParam);
+ return (Cocoon)this.processor;
+ }
+
+ /**
+ * Creates the root processor object and handles exception handling.
+ */
+ public synchronized Processor createProcessor()
+ throws Exception {
+
+ this.updateEnvironment();
+ this.forceLoad();
+ this.forceProperty();
+
+ try {
+ if (this.log.isInfoEnabled()) {
+ this.log.info("Reloading from: " + this.settings.getConfiguration());
+ }
+ Processor p = (Processor)this.container.getBean("org.apache.cocoon.Cocoon");
+
+ this.settings.setCreationTime(System.currentTimeMillis());
+ this.processor = p;
+ } catch (Exception e) {
+ this.log.error("Exception reloading root processor.", e);
+ throw e;
+ }
+ return this.processor;
+ }
+
+ /**
+ * Gets the current root processor object.
+ * Reload the root processor if configuration changed or we are reloading.
+ * Ensure that the correct classloader is set.
+ */
+ public Processor getProcessor(final String pathInfo, final String reloadParam)
+ throws Exception {
+ // set the blocks classloader for this thread
+ Thread.currentThread().setContextClassLoader(this.classloader);
+
+ if (this.settings.isReloadingEnabled("config")) {
+ boolean reload = false;
+
+ if (this.processor != null) {
+ if (this.processor instanceof Modifiable && ((Modifiable)this.processor).modifiedSince(this.settings.getCreationTime())) {
+ if (this.log.isInfoEnabled()) {
+ this.log.info("Configuration changed reload attempt");
+ }
+ reload = true;
+ } else if (pathInfo == null && reloadParam != null) {
+ if (this.log.isInfoEnabled()) {
+ this.log.info("Forced reload attempt");
+ }
+ reload = true;
+ }
+ } else if (pathInfo == null && reloadParam != null) {
+ if (this.log.isInfoEnabled()) {
+ this.log.info("Invalid configurations reload");
+ }
+ reload = true;
+ }
+
+ if (reload) {
+ if (this.container != null) {
+ this.container = null;
+ }
+ this.init();
+ this.createProcessor();
+ }
+ }
+ return this.processor;
+ }
+
+ protected ApplicationContext setupSpringContainer() throws Exception {
+ System.out.println("Setting up test Spring container...");
+ AvalonEnvironment env = new AvalonEnvironment();
+ env.context = this.appContext;
+ env.core = this.core;
+ env.logger = this.log;
+ env.servletContext = ((ServletConfig)this.appContext.get(CocoonServlet.CONTEXT_SERVLET_CONFIG)).getServletContext();
+ env.settings = this.core.getSettings();
+ ApplicationContext rootContext = ApplicationContextFactory.createRootApplicationContext(env);
+ ConfigurationInfo result = ConfigReader.readConfiguration(settings.getConfiguration(), env);
+ ApplicationContext mainContext = ApplicationContextFactory.createApplicationContext(env, result, rootContext, true);
+ System.out.println("Getting core cocoon processor context: " + mainContext.getBean(Core.ROLE));
+ return mainContext;
+ }
+
+ /**
+ * Handle the <code>load-class</code> parameter. This overcomes
+ * limits in many classpath issues. One of the more notorious
+ * ones is a bug in WebSphere that does not load the URL handler
+ * for the <code>classloader://</code> protocol. In order to
+ * overcome that bug, set <code>load-class</code> parameter to
+ * the <code>com.ibm.servlet.classloader.Handler</code> value.
+ *
+ * <p>If you need to load more than one class, then separate each
+ * entry with whitespace, a comma, or a semi-colon. Cocoon will
+ * strip any whitespace from the entry.</p>
+ */
+ protected void forceLoad() {
+ final Iterator i = this.settings.getLoadClasses().iterator();
+ while (i.hasNext()) {
+ final String fqcn = (String)i.next();
+ try {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Loading: " + fqcn);
+ }
+ ClassUtils.loadClass(fqcn).newInstance();
+ } catch (Exception e) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn("Could not load class: " + fqcn, e);
+ }
+ // Do not throw an exception, because it is not a fatal error.
+ }
+ }
+ }
+
+ /**
+ * Handle the "force-property" parameter.
+ *
+ * If you need to force more than one property to load, then
+ * separate each entry with whitespace, a comma, or a semi-colon.
+ * Cocoon will strip any whitespace from the entry.
+ */
+ protected void forceProperty() {
+ if (this.settings.getForceProperties().size() > 0) {
+ final Iterator i = this.settings.getForceProperties().entrySet().iterator();
+ while (i.hasNext()) {
+ final Map.Entry current = (Map.Entry)i.next();
+ try {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Setting: " + current.getKey() + "=" + current.getValue());
+ }
+ System.setProperty(current.getKey().toString(), current.getValue().toString());
+ } catch (Exception e) {
+ if (this.log.isWarnEnabled()) {
+ this.log.warn("Could not set property: " + current.getKey(), e);
+ }
+ // Do not throw an exception, because it is not a fatal error.
+ }
+ }
+ }
+ }
+
+ /**
+ * Method to update the environment before Cocoon instances are created.
+ *
+ * This is also useful if you wish to customize any of the 'protected'
+ * variables from this class before a Cocoon instance is built in a derivative
+ * of this class (eg. Cocoon Context).
+ */
+ protected void updateEnvironment() throws Exception {
+// // concatenate the class path and the extra class path
+// String classPath = this.env.getClassPath(this.settings);
+// StringBuffer buffer = new StringBuffer();
+// if ( classPath != null && classPath.length() > 0 ) {
+// buffer.append(classPath);
+// }
+// classPath = this.getExtraClassPath();
+// if ( classPath != null && classPath.length() > 0 ) {
+// if ( buffer.length() > 0 ) {
+// buffer.append(File.pathSeparatorChar);
+// }
+// buffer.append(classPath);
+// }
+ // FIXME - for now we just set an empty string as this information is looked up
+ // by other components
+ this.appContext.put(Constants.CONTEXT_CLASSPATH, "");
+ }
+
+ /**
+ * Dispose the root processor when environment is destroyed
+ */
+ public void destroy() {
+ // FIXME - we have to clean up here!
+ if ( this.container != null ) {
+ this.container = null;
+ }
+ }
+
+ /**
+ * Retreives the "extra-classpath" attribute, that needs to be
+ * added to the class path.
+ */
+ protected String getExtraClassPath() {
+ if (this.settings.getExtraClasspaths().size() > 0) {
+ StringBuffer sb = new StringBuffer();
+ final Iterator iter = this.settings.getExtraClasspaths().iterator();
+ int i = 0;
+ while (iter.hasNext()) {
+ String s = (String)iter.next();
+ if (i++ > 0) {
+ sb.append(File.pathSeparatorChar);
+ }
+ if ((s.charAt(0) == File.separatorChar) ||
+ (s.charAt(1) == ':')) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("extraClassPath is absolute: " + s);
+ }
+ sb.append(s);
+
+ } else {
+ if (s.indexOf("${") != -1) {
+ String path = StringUtils.replaceToken(s);
+ sb.append(path);
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("extraClassPath is not absolute replacing using token: [" + s + "] : " + path);
+ }
+ } else {
+ String path = null;
+ if (this.env.getContextForWriting() != null) {
+ path = this.env.getContextForWriting() + s;
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("extraClassPath is not absolute pre-pending context path: " + path);
+ }
+ } else {
+ path = this.settings.getWorkDirectory() + s;
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("extraClassPath is not absolute pre-pending work-directory: " + path);
+ }
+ }
+ sb.append(path);
+ }
+ }
+ }
+ return sb.toString();
+ }
+ return "";
+ }
+
+ protected static final class LoggerWrapper implements Logger {
+ private final BootstrapEnvironment env;
+
+ public LoggerWrapper(BootstrapEnvironment env) {
+ this.env = env;
+ }
+
+ protected void text(String arg0, Throwable arg1) {
+ if ( arg1 != null ) {
+ this.env.log(arg0, arg1);
+ } else {
+ this.env.log(arg0);
+ }
+ }
+
+ public void debug(String arg0, Throwable arg1) {
+ // we ignore debug
+ }
+
+ public void debug(String arg0) {
+ // we ignore debug
+ }
+
+ public void error(String arg0, Throwable arg1) {
+ this.text(arg0, arg1);
+ }
+
+ public void error(String arg0) {
+ this.text(arg0, null);
+ }
+
+ public void fatalError(String arg0, Throwable arg1) {
+ this.text(arg0, arg1);
+ }
+
+ public void fatalError(String arg0) {
+ this.text(arg0, null);
+ }
+
+ public Logger getChildLogger(String arg0) {
+ return this;
+ }
+
+ public void info(String arg0, Throwable arg1) {
+ // we ignore info
+ }
+
+ public void info(String arg0) {
+ // we ignore info
+ }
+
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ public boolean isErrorEnabled() {
+ return true;
+ }
+
+ public boolean isFatalErrorEnabled() {
+ return true;
+ }
+
+ public boolean isInfoEnabled() {
+ return false;
+ }
+
+ public boolean isWarnEnabled() {
+ return false;
+ }
+
+ public void warn(String arg0, Throwable arg1) {
+ // we ignore warn
+ }
+
+ public void warn(String arg0) {
+ // we ignore warn
+ }
+ }
+}
Propchange: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/SpringCoreUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/SpringCoreUtil.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ApplicationContextFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ApplicationContextFactory.java?rev=378575&r1=378574&r2=378575&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ApplicationContextFactory.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/ApplicationContextFactory.java Fri Feb 17 09:20:03 2006
@@ -15,26 +15,14 @@
*/
package org.apache.cocoon.core.container.spring;
-import java.util.Map;
+import javax.servlet.ServletContext;
-
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.DefaultConfiguration;
-import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.logger.Log4JLogger;
import org.apache.avalon.framework.logger.Logger;
-import org.apache.avalon.framework.parameters.Parameterizable;
-import org.apache.avalon.framework.parameters.Parameters;
-import org.apache.avalon.framework.service.ServiceManager;
import org.apache.cocoon.core.Core;
import org.apache.cocoon.core.Settings;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanCreationException;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
@@ -60,29 +48,29 @@
*/
public static ApplicationContext createApplicationContext(AvalonEnvironment env,
ConfigurationInfo info,
- ApplicationContext parent)
+ ApplicationContext parent,
+ boolean addCocoon)
throws Exception {
- final String xmlConfig = (new XmlConfigCreator()).createConfig(info.getComponents());
+ final String xmlConfig = (new XmlConfigCreator()).createConfig(info.getComponents(), addCocoon);
Resource rsc = new ByteArrayResource(xmlConfig.getBytes("utf-8"));
- CocoonXmlWebApplicationContext context = new CocoonXmlWebApplicationContext(rsc, parent);
+ Logger logger = env.logger;
+ if ( info.rootLogger != null ) {
+ logger = env.logger.getChildLogger(info.rootLogger);
+ }
+ CocoonXmlWebApplicationContext context = new CocoonXmlWebApplicationContext(rsc,
+ parent,
+ logger,
+ info.getComponents(),
+ env.context);
context.addBeanFactoryPostProcessor(new CocoonSettingsConfigurer(env.settings));
// TODO: Add context specific information
//context.setSourceResolver(this.resolver);
//context.setEnvironmentHelper(this.environmentHelper);
context.setServletContext(env.servletContext);
- AvalonPostProcessor processor = new AvalonPostProcessor();
- processor.components = info.getComponents();
- processor.logger = env.logger;
- if ( info.rootLogger != null ) {
- processor.logger = env.logger.getChildLogger(info.rootLogger);
- }
- processor.context = env.context;
context.refresh();
- processor.beanFactory = context.getBeanFactory();
- context.getBeanFactory().addBeanPostProcessor(processor);
if ( info.rootLogger != null ) {
- context.getBeanFactory().registerSingleton(Logger.class.getName(), processor.logger);
+ context.getBeanFactory().registerSingleton(Logger.class.getName(), logger);
}
return context;
}
@@ -100,7 +88,7 @@
public static ApplicationContext createRootApplicationContext(AvalonEnvironment env)
throws Exception {
final ApplicationContext parent = (ApplicationContext)env.servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
- CocoonXmlWebApplicationContext context = new CocoonXmlWebApplicationContext(null, parent);
+ CocoonXmlWebApplicationContext context = new CocoonXmlWebApplicationContext(parent);
context.refresh();
final ConfigurableListableBeanFactory factory = context.getBeanFactory();
factory.registerSingleton(Context.class.getName(), env.context);
@@ -110,83 +98,17 @@
return context;
}
- /**
- * This is a Spring BeanPostProcessor adding support for the Avalon lifecycle interfaces.
- */
- protected static final class AvalonPostProcessor implements DestructionAwareBeanPostProcessor {
-
- protected static final Configuration EMPTY_CONFIG = new DefaultConfiguration("empty");
-
- protected Logger logger;
- protected Context context;
- protected BeanFactory beanFactory;
- protected Map components;
-
- /**
- * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
- */
- public Object postProcessAfterInitialization(Object bean, String beanName)
- throws BeansException {
- try {
- ContainerUtil.start(bean);
- } catch (Exception e) {
- throw new BeanInitializationException("Unable to start bean " + beanName, e);
- }
- return bean;
- }
-
- /**
- * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
- */
- public Object postProcessBeforeInitialization(Object bean, String beanName)
- throws BeansException {
- final ComponentInfo info = (ComponentInfo)this.components.get(beanName);
- try {
- if ( info == null ) {
- // no info so we just return the bean and don't apply any lifecycle interfaces
- return bean;
- }
- if ( info.getLoggerCategory() != null ) {
- ContainerUtil.enableLogging(bean, this.logger.getChildLogger(info.getLoggerCategory()));
- } else {
- ContainerUtil.enableLogging(bean, this.logger);
- }
- ContainerUtil.contextualize(bean, this.context);
- ContainerUtil.service(bean, (ServiceManager)this.beanFactory.getBean(ServiceManager.class.getName()));
- if ( info != null ) {
- Configuration config = info.getConfiguration();
- if ( config == null ) {
- config = EMPTY_CONFIG;
- }
- if ( bean instanceof Configurable ) {
- ContainerUtil.configure(bean, config);
- } else if ( bean instanceof Parameterizable ) {
- Parameters p = info.getParameters();
- if ( p == null ) {
- p = Parameters.fromConfiguration(config);
- info.setParameters(p);
- }
- ContainerUtil.parameterize(bean, p);
- }
- }
- ContainerUtil.initialize(bean);
- } catch (Exception e) {
- throw new BeanCreationException("Unable to initialize Avalon component with role " + beanName, e);
- }
- return bean;
- }
-
- /**
- * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor#postProcessBeforeDestruction(java.lang.Object, java.lang.String)
- */
- public void postProcessBeforeDestruction(Object bean, String beanName)
- throws BeansException {
- try {
- ContainerUtil.stop(bean);
- } catch (Exception e) {
- throw new BeanInitializationException("Unable to stop bean " + beanName, e);
+ public static Logger createRootLogger(ServletContext context, String category) {
+ final ApplicationContext parent = (ApplicationContext)context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
+ // test for a logger in the parent context
+ if ( parent != null && parent.containsBean(Logger.class.getName()) ) {
+ if ( category == null || category.length() == 0 ) {
+ return (Logger)parent.getBean(Logger.class.getName());
}
- ContainerUtil.dispose(bean);
+ return ((Logger)parent.getBean(Logger.class.getName())).getChildLogger(category);
}
+ // create a new log4j logger
+ org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category);
+ return new Log4JLogger(logger);
}
}
Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/CocoonXmlWebApplicationContext.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/CocoonXmlWebApplicationContext.java?rev=378575&r1=378574&r2=378575&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/CocoonXmlWebApplicationContext.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/CocoonXmlWebApplicationContext.java Fri Feb 17 09:20:03 2006
@@ -17,12 +17,27 @@
import java.io.IOException;
import java.net.MalformedURLException;
+import java.util.Map;
import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.DefaultConfiguration;
+import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.parameters.Parameterizable;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceManager;
import org.apache.cocoon.environment.internal.EnvironmentHelper;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanInitializationException;
+import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
@@ -43,11 +58,24 @@
protected SourceResolver resolver;
protected String baseURL;
+ protected final Logger avalonLogger;
+ protected final Context avalonContext;
+ protected final Map avalonComponentDefinitions;
+
+ public CocoonXmlWebApplicationContext(ApplicationContext parent) {
+ this(null, parent, null, null, null);
+ }
public CocoonXmlWebApplicationContext(Resource avalonResource,
- ApplicationContext parent) {
+ ApplicationContext parent,
+ Logger avalonLogger,
+ Map avalonComponentDefs,
+ Context avalonContext) {
this.setParent(parent);
this.avalonResource = avalonResource;
+ this.avalonLogger = avalonLogger;
+ this.avalonComponentDefinitions = avalonComponentDefs;
+ this.avalonContext = avalonContext;
}
/**
@@ -61,6 +89,21 @@
}
}
+ /**
+ * @see org.springframework.context.support.AbstractRefreshableApplicationContext#createBeanFactory()
+ */
+ protected DefaultListableBeanFactory createBeanFactory() {
+ DefaultListableBeanFactory beanFactory = super.createBeanFactory();
+ if ( this.avalonComponentDefinitions != null ) {
+ AvalonPostProcessor processor = new AvalonPostProcessor(this.avalonComponentDefinitions,
+ this.avalonContext,
+ this.avalonLogger,
+ beanFactory);
+ beanFactory.addBeanPostProcessor(processor);
+ }
+ return beanFactory;
+ }
+
public void setSourceResolver(SourceResolver aResolver) {
this.resolver = aResolver;
}
@@ -116,4 +159,93 @@
return new String[]{};
}
+ /**
+ * This is a Spring BeanPostProcessor adding support for the Avalon lifecycle interfaces.
+ */
+ protected static final class AvalonPostProcessor implements DestructionAwareBeanPostProcessor {
+
+ protected static final Configuration EMPTY_CONFIG = new DefaultConfiguration("empty");
+
+ protected final Logger logger;
+ protected final Context context;
+ protected final BeanFactory beanFactory;
+ protected final Map components;
+
+ public AvalonPostProcessor(Map components,
+ Context context,
+ Logger logger,
+ BeanFactory factory) {
+ this.components = components;
+ this.context = context;
+ this.logger = logger;
+ this.beanFactory = factory;
+ }
+
+ /**
+ * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
+ */
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ try {
+ ContainerUtil.start(bean);
+ } catch (Exception e) {
+ throw new BeanInitializationException("Unable to start bean " + beanName, e);
+ }
+ return bean;
+ }
+
+ /**
+ * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
+ */
+ public Object postProcessBeforeInitialization(Object bean, String beanName)
+ throws BeansException {
+ final ComponentInfo info = (ComponentInfo)this.components.get(beanName);
+ try {
+ if ( info == null ) {
+ // no info so we just return the bean and don't apply any lifecycle interfaces
+ return bean;
+ }
+ if ( info.getLoggerCategory() != null ) {
+ ContainerUtil.enableLogging(bean, this.logger.getChildLogger(info.getLoggerCategory()));
+ } else {
+ ContainerUtil.enableLogging(bean, this.logger);
+ }
+ ContainerUtil.contextualize(bean, this.context);
+ ContainerUtil.service(bean, (ServiceManager)this.beanFactory.getBean(ServiceManager.class.getName()));
+ if ( info != null ) {
+ Configuration config = info.getConfiguration();
+ if ( config == null ) {
+ config = EMPTY_CONFIG;
+ }
+ if ( bean instanceof Configurable ) {
+ ContainerUtil.configure(bean, config);
+ } else if ( bean instanceof Parameterizable ) {
+ Parameters p = info.getParameters();
+ if ( p == null ) {
+ p = Parameters.fromConfiguration(config);
+ info.setParameters(p);
+ }
+ ContainerUtil.parameterize(bean, p);
+ }
+ }
+ ContainerUtil.initialize(bean);
+ } catch (Exception e) {
+ throw new BeanCreationException("Unable to initialize Avalon component with role " + beanName, e);
+ }
+ return bean;
+ }
+
+ /**
+ * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor#postProcessBeforeDestruction(java.lang.Object, java.lang.String)
+ */
+ public void postProcessBeforeDestruction(Object bean, String beanName)
+ throws BeansException {
+ try {
+ ContainerUtil.stop(bean);
+ } catch (Exception e) {
+ throw new BeanInitializationException("Unable to stop bean " + beanName, e);
+ }
+ ContainerUtil.dispose(bean);
+ }
+ }
}
Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/XmlConfigCreator.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/XmlConfigCreator.java?rev=378575&r1=378574&r2=378575&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/XmlConfigCreator.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/spring/XmlConfigCreator.java Fri Feb 17 09:20:03 2006
@@ -20,14 +20,20 @@
import java.util.List;
import java.util.Map;
+import org.apache.avalon.excalibur.pool.Poolable;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.cocoon.Cocoon;
+import org.apache.cocoon.Processor;
+import org.apache.cocoon.SpringCocoon;
import org.springframework.util.StringUtils;
/**
* This is a simple component that uses a {@link ConfigurationInfo} to create
* a Spring like configuration xml document.
*
- * TODO: LogManager?
* TODO: configure(Core)
* TODO: register aliases for shorthands
* @since 2.2
@@ -39,7 +45,7 @@
protected static final String DOCTYPE =
"<!DOCTYPE beans PUBLIC \"-//SPRING//DTD BEAN//EN\" \"http://www.springframework.org/dtd/spring-beans.dtd\">\n";
- public String createConfig(Map components)
+ public String createConfig(Map components, boolean addCocoon)
throws Exception {
final List pooledRoles = new ArrayList();
final StringBuffer buffer = new StringBuffer();
@@ -51,6 +57,7 @@
buffer.append("<bean");
this.appendAttribute(buffer, "id", ServiceManager.class.getName());
this.appendAttribute(buffer, "class", AvalonServiceManager.class.getName());
+ this.appendAttribute(buffer, "singleton", "true");
buffer.append("/>\n");
final Iterator i = components.entrySet().iterator();
@@ -70,6 +77,15 @@
className = AvalonServiceSelector.class.getName();
isSelector = true;
} else {
+ // test for unknown model
+ if ( current.getModel() == ComponentInfo.MODEL_UNKNOWN ) {
+ final Class serviceClass = Class.forName(className);
+ if ( ThreadSafe.class.isAssignableFrom(serviceClass) ) {
+ current.setModel(ComponentInfo.MODEL_SINGLETON);
+ } else if ( Poolable.class.isAssignableFrom(serviceClass) ) {
+ current.setModel(ComponentInfo.MODEL_POOLED);
+ }
+ }
if ( current.getModel() == ComponentInfo.MODEL_NON_THREAD_SAFE_POOLED
|| current.getModel() == ComponentInfo.MODEL_POOLED ) {
poolable = true;
@@ -142,6 +158,27 @@
buffer.append("</bean>\n");
pooledRoles.add(role);
}
+ }
+ // add the Cocoon object to the root
+ if ( addCocoon ) {
+ buffer.append("<bean");
+ this.appendAttribute(buffer, "id", Cocoon.class.getName());
+ this.appendAttribute(buffer, "class", SpringCocoon.class.getName());
+ this.appendAttribute(buffer, "singleton", "true");
+ buffer.append(">\n");
+ buffer.append(" <constructor-arg ref=\"");
+ buffer.append(Processor.ROLE);
+ buffer.append("\"/>\n");
+ buffer.append(" <constructor-arg ref=\"");
+ buffer.append(ServiceManager.class.getName());
+ buffer.append("\"/>\n");
+ buffer.append(" <constructor-arg ref=\"");
+ buffer.append(Context.class.getName());
+ buffer.append("\"/>\n");
+ buffer.append(" <constructor-arg ref=\"");
+ buffer.append(Logger.class.getName());
+ buffer.append("\"/>\n");
+ buffer.append("</bean>\n");
}
buffer.append("</beans>\n");