cziegeler 2003/10/20 01:15:27
Modified: src/java/org/apache/cocoon/servlet CocoonServlet.java src/java/org/apache/cocoon Constants.java Cocoon.java src/java/org/apache/cocoon/components/treeprocessor TreeProcessor.java src/java/org/apache/cocoon/components/treeprocessor/sitemap MountNode.java src/java/org/apache/cocoon/environment EnvironmentHelper.java Added: src/java/org/apache/cocoon/environment EnvironmentStack.java Log: Starting cleaner environment handling Removing deprecated code Revision Changes Path 1.18 +8 -6 cocoon-2.2/src/java/org/apache/cocoon/servlet/CocoonServlet.java Index: CocoonServlet.java =================================================================== RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/servlet/CocoonServlet.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- CocoonServlet.java 19 Oct 2003 17:20:23 -0000 1.17 +++ CocoonServlet.java 20 Oct 2003 08:15:27 -0000 1.18 @@ -86,6 +86,7 @@ import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; +import org.apache.avalon.framework.container.ContainerUtil; import org.apache.avalon.framework.context.Contextualizable; import org.apache.avalon.framework.context.DefaultContext; import org.apache.avalon.framework.logger.LogEnabled; @@ -1349,14 +1350,15 @@ getLogger().info("Reloading from: " + configFile.toExternalForm()); } Cocoon c = (Cocoon) ClassUtils.newInstance("org.apache.cocoon.Cocoon"); - c.enableLogging( getCocoonLogger() ); + ContainerUtil.enableLogging(c, this.getCocoonLogger()); c.setLoggerManager( getLoggerManager() ); - c.contextualize(this.appContext); - c.compose(getParentComponentManager()); + ContainerUtil.contextualize(c, this.appContext); + ContainerUtil.compose(c, getParentComponentManager()); + ContainerUtil.service(c, this.getParentComponentManager()); if (this.enableInstrumentation) { c.setInstrumentManager(getInstrumentManager()); } - c.initialize(); + ContainerUtil.initialize(c); this.creationTime = System.currentTimeMillis(); disposeCocoon(); @@ -1486,7 +1488,7 @@ private final void disposeCocoon() { if (this.cocoon != null) { - this.cocoon.dispose(); + ContainerUtil.dispose(this.cocoon); this.cocoon = null; } } 1.11 +1 -5 cocoon-2.2/src/java/org/apache/cocoon/Constants.java Index: Constants.java =================================================================== RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/Constants.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- Constants.java 19 Oct 2003 17:20:23 -0000 1.10 +++ Constants.java 20 Oct 2003 08:15:27 -0000 1.11 @@ -141,10 +141,6 @@ /** The name of the class for the default XML parser to use */ public static final String DEFAULT_PARSER = "org.apache.excalibur.xml.impl.JaxpParser"; - /** The name of the property holding the class for a XML parser - * @deprecated This will be removed in future release */ - public static final String DEPRECATED_PARSER_PROPERTY = "org.apache.cocoon.components.parser.Parser"; - /** The namespace for the XSP core logicsheet. */ public static final String XSP_URI = "http://apache.org/xsp"; 1.25 +3 -1 cocoon-2.2/src/java/org/apache/cocoon/Cocoon.java Index: Cocoon.java =================================================================== RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/Cocoon.java,v retrieving revision 1.24 retrieving revision 1.25 diff -u -r1.24 -r1.25 --- Cocoon.java 19 Oct 2003 17:43:17 -0000 1.24 +++ Cocoon.java 20 Oct 2003 08:15:27 -0000 1.25 @@ -371,6 +371,7 @@ CocoonComponentManager.enterEnvironment(environment, this.serviceManager, this); */ + EnvironmentHelper.enterProcessor(this); try { boolean result; if (this.getLogger().isDebugEnabled()) { @@ -395,6 +396,7 @@ environment.tryResetResponse(); throw any; } finally { + EnvironmentHelper.leaveProcessor(); // CocoonComponentManager.leaveEnvironment(); // CocoonComponentManager.endProcessing(environment, key); if (this.getLogger().isDebugEnabled()) { 1.19 +9 -7 cocoon-2.2/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java Index: TreeProcessor.java =================================================================== RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- TreeProcessor.java 19 Oct 2003 17:43:17 -0000 1.18 +++ TreeProcessor.java 20 Oct 2003 08:15:27 -0000 1.19 @@ -209,11 +209,11 @@ * @param language the language to be used by the child processor. * @return a new child processor. */ - public TreeProcessor createChildProcessor( - ServiceManager manager, - String language, - Source source) - throws Exception { + public TreeProcessor createChildProcessor(ServiceManager manager, + String language, + Source source, + String prefix) + throws Exception { // Note: lifecycle methods aren't called, since this constructors copies all // that can be copied from the parent (see above) @@ -364,7 +364,8 @@ } // and now process - CocoonComponentManager.enterEnvironment(environment, this.sitemapComponentManager, this); + //CocoonComponentManager.enterEnvironment(environment, this.sitemapComponentManager, this); + EnvironmentHelper.enterProcessor(this); try { boolean success = this.rootNode.invoke(environment, context); @@ -386,6 +387,7 @@ } } finally { + EnvironmentHelper.leaveProcessor(); CocoonComponentManager.leaveEnvironment(); } } 1.8 +16 -11 cocoon-2.2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java Index: MountNode.java =================================================================== RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- MountNode.java 6 Oct 2003 16:42:39 -0000 1.7 +++ MountNode.java 20 Oct 2003 08:15:27 -0000 1.8 @@ -54,9 +54,9 @@ import java.util.Iterator; import java.util.Map; -import org.apache.avalon.framework.component.ComponentException; -import org.apache.avalon.framework.component.ComponentManager; -import org.apache.avalon.framework.component.Composable; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; import org.apache.cocoon.components.pipeline.ProcessingPipeline; import org.apache.cocoon.components.treeprocessor.AbstractProcessingNode; import org.apache.cocoon.components.treeprocessor.InvokeContext; @@ -72,7 +72,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> * @version CVS $Id$ */ -public class MountNode extends AbstractProcessingNode implements Composable { +public class MountNode extends AbstractProcessingNode implements Serviceable { /** The 'uri-prefix' attribute */ private VariableResolver prefix; @@ -90,7 +90,7 @@ private String language; /** The component manager to be used by the mounted processor */ - private ComponentManager manager; + private ServiceManager manager; public MountNode(VariableResolver prefix, VariableResolver source, String language, TreeProcessor parentProcessor) { this.prefix = prefix; this.source = source; @@ -98,7 +98,7 @@ this.parentProcessor = parentProcessor; } - public void compose(ComponentManager manager) throws ComponentException { + public void service(ServiceManager manager) throws ServiceException { this.manager = manager; } @@ -108,10 +108,10 @@ Map objectModel = env.getObjectModel(); String resolvedSource = this.source.resolve(context, objectModel); - TreeProcessor processor = getProcessor(resolvedSource); - String resolvedPrefix = this.prefix.resolve(context, objectModel); + TreeProcessor processor = getProcessor(resolvedSource, resolvedPrefix); + String oldPrefix = env.getURIPrefix(); String oldURI = env.getURI(); String oldContext = env.getContext(); @@ -140,7 +140,12 @@ } } - private synchronized TreeProcessor getProcessor(String source) throws Exception { + /** + * Get the processor for the sub sitemap + * FIXME Better synchronization strategy + */ + private synchronized TreeProcessor getProcessor(String source, String prefix) + throws Exception { TreeProcessor processor = (TreeProcessor)processors.get(source); @@ -156,7 +161,7 @@ SourceResolver resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE); Source src = resolver.resolveURI(actualSource); try { - processor = this.parentProcessor.createChildProcessor(this.manager, this.language, src); + processor = this.parentProcessor.createChildProcessor(this.manager, this.language, src, prefix); } finally { resolver.release(src); this.manager.release(resolver); 1.3 +90 -15 cocoon-2.2/src/java/org/apache/cocoon/environment/EnvironmentHelper.java Index: EnvironmentHelper.java =================================================================== RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/environment/EnvironmentHelper.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- EnvironmentHelper.java 19 Oct 2003 17:27:32 -0000 1.2 +++ EnvironmentHelper.java 20 Oct 2003 08:15:27 -0000 1.3 @@ -59,7 +59,10 @@ import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.Serviceable; +import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.Processor; import org.apache.cocoon.components.source.SourceUtil; +import org.apache.cocoon.xml.XMLConsumer; import org.apache.excalibur.source.Source; /** @@ -80,9 +83,8 @@ /** The service manager */ protected ServiceManager manager; - /** The current prefix to strip off from the request uri - * TODO (CZ) Convert this to a String */ - protected StringBuffer prefix = new StringBuffer(); + /** The current prefix to strip off from the request uri */ + protected String prefix; /** The Context path */ protected String context; @@ -90,6 +92,9 @@ /** The root context path */ protected String rootContext; + /** The environment information */ + private static InheritableThreadLocal environmentStack = new CloningInheritableThreadLocal(); + /** * Constructor * @@ -162,40 +167,47 @@ return this.resolveURI(location, null, null); } - public void changeContext(Environment env) { + public void changeContext(Environment env) + throws ProcessingException { String uris = env.getURI(); - final int l = this.prefix.length(); - if ( l >= 1 ) { - if (!uris.startsWith(this.prefix.toString())) { + if ( this.prefix != null ) { + if (!uris.startsWith(this.prefix)) { String message = "The current URI (" + uris + ") doesn't start with given prefix (" + prefix + ")"; getLogger().error(message); - throw new RuntimeException(message); + throw new ProcessingException(message); } // we don't need to check for slash at the beginning // of uris - the prefix always ends with a slash! + final int l = this.prefix.length(); uris = uris.substring(l); // TODO (CZ) Implement this in the environment // env.setURI(uris); } } + /** * Adds an prefix to the overall stripped off prefix from the request uri */ - public void changeContext(String prefix, String newContext) + public void changeContext(String newPrefix, String newContext) throws IOException { if (getLogger().isDebugEnabled()) { getLogger().debug("Changing Cocoon context"); getLogger().debug(" from context(" + this.context + ") and prefix(" + this.prefix + ")"); - getLogger().debug(" to context(" + newContext + ") and prefix(" + prefix + ")"); + getLogger().debug(" to context(" + newContext + ") and prefix(" + newPrefix + ")"); } - int l = prefix.length(); + int l = newPrefix.length(); if (l >= 1) { - this.prefix.append(prefix); + if ( this.prefix == null ) { + this.prefix = ""; + } + final StringBuffer buffer = new StringBuffer(this.prefix); + buffer.append(newPrefix); // check for a slash at the beginning to avoid problems with subsitemaps - if ( !this.prefix.toString().endsWith("/") ) { - this.prefix.append('/'); + if ( buffer.charAt(buffer.length()-1) != '/') { + buffer.append('/'); } + this.prefix = buffer.toString(); } if (SourceUtil.getScheme(this.context).equals("zip")) { @@ -246,4 +258,67 @@ } } + /** + * This hook must be called by the sitemap each time a sitemap is entered + * This method should never raise an exception, except when the + * parameters are not set! + */ + public static void enterProcessor(Processor processor) { + if ( null == processor) { + throw new IllegalArgumentException("Processor is not set."); + } + + EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); + if (stack == null) { + stack = new EnvironmentStack(); + environmentStack.set(stack); + } + stack.push(new Object[] {processor, new Integer(stack.getOffset())}); + stack.setOffset(stack.size()-1); + } + + /** + * This hook must be called by the sitemap each time a sitemap is left. + * It's the counterpart to [EMAIL PROTECTED] #enterProcessor(Processor)}. + */ + public static void leaveProcessor() { + final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); + final Object[] objs = (Object[])stack.pop(); + stack.setOffset(((Integer)objs[1]).intValue()); + } + + /** + * Create an environment aware xml consumer for the cocoon + * protocol + */ + public static XMLConsumer createEnvironmentAwareConsumer(XMLConsumer consumer) { + final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); + final Object[] objs = (Object[])stack.getCurrent(); + return stack.getEnvironmentAwareConsumerWrapper(consumer, ((Integer)objs[1]).intValue()); + } } + +final class CloningInheritableThreadLocal + extends InheritableThreadLocal { + + /** + * Computes the child's initial value for this InheritableThreadLocal + * as a function of the parent's value at the time the child Thread is + * created. This method is called from within the parent thread before + * the child is started. + * <p> + * This method merely returns its input argument, and should be overridden + * if a different behavior is desired. + * + * @param parentValue the parent thread's value + * @return the child thread's initial value + */ + protected Object childValue(Object parentValue) { + if ( null != parentValue) { + return ((EnvironmentStack)parentValue).clone(); + } else { + return null; + } + } +} + 1.1 cocoon-2.2/src/java/org/apache/cocoon/environment/EnvironmentStack.java Index: EnvironmentStack.java =================================================================== /* ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact [EMAIL PROTECTED] 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi <[EMAIL PROTECTED]>. For more information on the Apache Software Foundation, please see <http://www.apache.org/>. */ package org.apache.cocoon.environment; import org.apache.cocoon.xml.XMLConsumer; import org.apache.commons.collections.ArrayStack; import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.xml.sax.SAXException; /** * The stack for the processing environment. * This is a special implementation of a stack for the handling of the * cocoon protocol and the sitemap source resolving. * * @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a> * @version CVS $Id: EnvironmentStack.java,v 1.1 2003/10/20 08:15:27 cziegeler Exp $ */ final class EnvironmentStack extends ArrayStack implements Cloneable { int offset; Object getCurrent() { return this.get(offset); //return this.peek(this.offset); } int getOffset() { return this.offset; } void setOffset(int value) { this.offset = value; } public Object clone() { EnvironmentStack old = (EnvironmentStack) super.clone(); old.offset = offset; return old; } XMLConsumer getEnvironmentAwareConsumerWrapper(XMLConsumer consumer, int oldOffset) { return new EnvironmentChanger(consumer, this, oldOffset, this.offset); } } /** * This class is an [EMAIL PROTECTED] XMLConsumer} that changes the current environment. * When a pipeline calls an internal pipeline, two environments are * established: one for the calling pipeline and one for the internal pipeline. * Now, if SAX events are send from the internal pipeline, they are * received by some component of the calling pipeline, so inbetween we * have to change the environment forth and back. */ final class EnvironmentChanger implements XMLConsumer { final XMLConsumer consumer; final EnvironmentStack stack; final int oldOffset; final int newOffset; EnvironmentChanger(XMLConsumer consumer, EnvironmentStack es, int oldOffset, int newOffset) { this.consumer = consumer; this.stack = es; this.oldOffset = oldOffset; this.newOffset = newOffset; } public void setDocumentLocator(Locator locator) { this.stack.setOffset(this.oldOffset); this.consumer.setDocumentLocator(locator); this.stack.setOffset(this.newOffset); } public void startDocument() throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.startDocument(); this.stack.setOffset(this.newOffset); } public void endDocument() throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.endDocument(); this.stack.setOffset(this.newOffset); } public void startPrefixMapping(String prefix, String uri) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.startPrefixMapping(prefix, uri); this.stack.setOffset(this.newOffset); } public void endPrefixMapping(String prefix) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.endPrefixMapping(prefix); this.stack.setOffset(this.newOffset); } public void startElement(String uri, String loc, String raw, Attributes a) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.startElement(uri, loc, raw, a); this.stack.setOffset(this.newOffset); } public void endElement(String uri, String loc, String raw) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.endElement(uri, loc, raw); this.stack.setOffset(this.newOffset); } public void characters(char c[], int start, int len) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.characters(c, start, len); this.stack.setOffset(this.newOffset); } public void ignorableWhitespace(char c[], int start, int len) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.ignorableWhitespace(c, start, len); this.stack.setOffset(this.newOffset); } public void processingInstruction(String target, String data) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.processingInstruction(target, data); this.stack.setOffset(this.newOffset); } public void skippedEntity(String name) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.skippedEntity(name); this.stack.setOffset(this.newOffset); } public void startDTD(String name, String publicId, String systemId) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.startDTD(name, publicId, systemId); this.stack.setOffset(this.newOffset); } public void endDTD() throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.endDTD(); this.stack.setOffset(this.newOffset); } public void startEntity(String name) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.startEntity(name); this.stack.setOffset(this.newOffset); } public void endEntity(String name) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.endEntity(name); this.stack.setOffset(this.newOffset); } public void startCDATA() throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.startCDATA(); this.stack.setOffset(this.newOffset); } public void endCDATA() throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.endCDATA(); this.stack.setOffset(this.newOffset); } public void comment(char ch[], int start, int len) throws SAXException { this.stack.setOffset(this.oldOffset); this.consumer.comment(ch, start, len); this.stack.setOffset(this.newOffset); } }