cziegeler 2002/11/20 03:21:50 Modified: src/java/org/apache/cocoon Tag: cocoon_2_0_3_branch Cocoon.java src/java/org/apache/cocoon/components Tag: cocoon_2_0_3_branch CocoonComponentManager.java src/java/org/apache/cocoon/components/source Tag: cocoon_2_0_3_branch SitemapSource.java . Tag: cocoon_2_0_3_branch changes.xml Log: Fixing bug 12293: RequestLifecycleComponents are not handled properly when the cocoon: protocol is used Revision Changes Path No revision No revision 1.22.2.5 +4 -2 xml-cocoon2/src/java/org/apache/cocoon/Cocoon.java Index: Cocoon.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/Cocoon.java,v retrieving revision 1.22.2.4 retrieving revision 1.22.2.5 diff -u -r1.22.2.4 -r1.22.2.5 --- Cocoon.java 21 Sep 2002 02:34:08 -0000 1.22.2.4 +++ Cocoon.java 20 Nov 2002 11:21:49 -0000 1.22.2.5 @@ -568,6 +568,7 @@ throw new IllegalStateException("You cannot process a Disposed Cocoon engine."); } + Object key = CocoonComponentManager.startProcessing(environment); try { if (this.getLogger().isDebugEnabled()) { ++activeRequestCount; @@ -586,7 +587,8 @@ } } } finally { - if (this.getLogger().isDebugEnabled()) { + CocoonComponentManager.endProcessing(key); + if (this.getLogger().isDebugEnabled()) { --activeRequestCount; } } No revision No revision 1.13.2.4 +254 -40 xml-cocoon2/src/java/org/apache/cocoon/components/CocoonComponentManager.java Index: CocoonComponentManager.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/CocoonComponentManager.java,v retrieving revision 1.13.2.3 retrieving revision 1.13.2.4 diff -u -r1.13.2.3 -r1.13.2.4 --- CocoonComponentManager.java 4 Aug 2002 04:11:52 -0000 1.13.2.3 +++ CocoonComponentManager.java 20 Nov 2002 11:21:49 -0000 1.13.2.4 @@ -51,15 +51,20 @@ package org.apache.cocoon.components; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Stack; import org.apache.avalon.excalibur.component.ExcaliburComponentManager; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.component.ComponentException; import org.apache.avalon.framework.component.ComponentManager; +import org.apache.avalon.framework.component.ComponentSelector; import org.apache.avalon.framework.component.Recomposable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.DefaultConfiguration; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.Processor; import org.apache.cocoon.environment.Environment; @@ -78,6 +83,12 @@ public final class CocoonComponentManager extends ExcaliburComponentManager { + + /** The key used to store the current process environment */ + private static final String PROCESS_KEY = + "org.apache.cocoon.components.CocoonComponentManager"; + + /** The environment information */ private static InheritableThreadLocal environmentStack = new InheritableThreadLocal(); @@ -105,9 +116,6 @@ super(manager); } - private static final Integer ONE = new Integer(1); - private static final Integer TWO = new Integer(2); - /** * This hook must be called by the sitemap each time a sitemap is entered */ @@ -118,14 +126,13 @@ environmentStack.set(new Stack()); } final Stack stack = (Stack)environmentStack.get(); - if (!stack.empty() ) { - final Object[] objects = (Object[])stack.peek(); - if ( objects[1] == objectModel ) { - stack.push(new Object[] {env, objectModel, objects[2], TWO, processor}); - return; - } + stack.push(new Object[] {env, processor}); + + EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); + if ( null != desc ) { + // this is only for 2.1 + // desc.addSitemapConfiguration(processor.getComponentConfigurations()); } - stack.push(new Object[] {env, objectModel, new HashMap(5), ONE, processor}); } /** @@ -135,20 +142,40 @@ final Stack stack = (Stack)environmentStack.get(); if (null != stack && !stack.empty()) { final Object[] objects = (Object[])stack.pop(); - if (objects[3] == ONE) { - final Map components = (Map)objects[2]; - final Iterator iter = components.values().iterator(); - while (iter.hasNext()) { - final Object[] o = (Object[])iter.next(); - final Component component = (Component)o[0]; - ((CocoonComponentManager)o[1]).releaseRLComponent( component ); - } + EnvironmentDescription desc = (EnvironmentDescription)((Environment)objects[0]).getObjectModel().get(PROCESS_KEY); + if ( null != desc ) { + // this is only for 2.1 + //desc.removeLastSitemapConfiguration(); } } } /** - * Return the current environment object (for the cocoon: protocol) + * This hook has to be called before a request is processed. + * The hook is called by the Cocoon component and by the + * cocoon protocol implementation. + * @return A unique key within this thread. + */ + public static Object startProcessing(Environment env) { + EnvironmentDescription desc = new EnvironmentDescription(env); + env.getObjectModel().put(PROCESS_KEY, desc); + return desc; + } + + /** + * This hook has to be called before a request is processed. + * The hook is called by the Cocoon component and by the + * cocoon protocol implementation. + * @param key A unique key within this thread return by + * {@link startProcessing(Environment)}. + */ + public static void endProcessing(Object key) { + EnvironmentDescription desc = (EnvironmentDescription)key; + desc.release(); + } + + /** + * Return the current environment (for the cocoon: protocol) */ public static Environment getCurrentEnvironment() { final Stack stack = (Stack)environmentStack.get(); @@ -159,12 +186,12 @@ } /** - * Return the current processor object (for the cocoon: protocol) + * Return the current processor (for the cocoon: protocol) */ public static Processor getCurrentProcessor() { final Stack stack = (Stack)environmentStack.get(); if (null != stack && !stack.empty()) { - return (Processor) ((Object[])stack.peek())[4]; + return (Processor) ((Object[])stack.peek())[1]; } return null; } @@ -179,10 +206,10 @@ final Stack stack = (Stack)environmentStack.get(); if ( null != stack && !stack.empty()) { final Object[] objects = (Object[])stack.peek(); - final Map components = (Map)objects[2]; - final Object[] o = (Object[])components.get(role); - if ( null != o ) { - final Component component = (Component) o[0]; + final Map objectModel = ((Environment)objects[0]).getObjectModel(); + EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); + if ( null != desc ) { + final Component component = desc.getRequestLifecycleComponent(role); if (null != component) { return component; } @@ -195,19 +222,23 @@ throw new ComponentException("ComponentManager has no Environment Stack."); } final Object[] objects = (Object[]) stack.peek(); - final Map components = (Map)objects[2]; - // first test if the parent CM has already initialized this component - if (components.containsKey( role ) == false) { - try { - if (component instanceof Recomposable) { - ((Recomposable) component).recompose(this); + final Map objectModel = ((Environment)objects[0]).getObjectModel(); + EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); + if ( null != desc ) { + + // first test if the parent CM has already initialized this component + if ( !desc.containsRequestLifecycleComponent( role ) ) { + try { + if (component instanceof Recomposable) { + ((Recomposable) component).recompose(this); + } + ((RequestLifecycleComponent) component).setup((org.apache.cocoon.environment.SourceResolver)objects[0], + objectModel); + } catch (Exception local) { + throw new ComponentException("Exception during setup of RequestLifecycleComponent with role '"+role+"'", local); } - ((RequestLifecycleComponent) component).setup((org.apache.cocoon.environment.SourceResolver)objects[0], - (Map)objects[1]); - } catch (Exception local) { - throw new ComponentException("Exception during setup of RequestLifecycleComponent with role '"+role+"'", local); + desc.addRequestLifecycleComponent(role, component, this); } - components.put(role, new Object[] {component, this}); } } return component; @@ -229,9 +260,192 @@ } /** - * Release a RequestLifecycleComponent + * Add an automatically released component + */ + public static void addComponentForAutomaticRelease(final ComponentSelector selector, + final Component component, + final ComponentManager manager) + throws ProcessingException { + final Stack stack = (Stack)environmentStack.get(); + if ( null != stack && !stack.empty()) { + final Object[] objects = (Object[])stack.firstElement(); + final Map objectModel = ((Environment)objects[0]).getObjectModel(); + EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); + if ( null != desc ) { + desc.addToAutoRelease(selector, component, manager); + } + } else { + throw new ProcessingException("Unable to add component for automatic release: no environment available."); + } + } + + /** + * Add an automatically released component + */ + public static void addComponentForAutomaticRelease(final ComponentManager manager, + final Component component) + throws ProcessingException { + final Stack stack = (Stack)environmentStack.get(); + if ( null != stack && !stack.empty()) { + final Object[] objects = (Object[])stack.firstElement(); + final Map objectModel = ((Environment)objects[0]).getObjectModel(); + EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); + if ( null != desc ) { + desc.addToAutoRelease(manager, component); + } + } else { + throw new ProcessingException("Unable to add component for automatic release: no environment available."); + } + } + + /** + * Remove from automatically released components + */ + public static void removeFromAutomaticRelease(final Component component) + throws ProcessingException { + final Stack stack = (Stack)environmentStack.get(); + if ( null != stack && !stack.empty()) { + final Object[] objects = (Object[])stack.firstElement(); + final Map objectModel = ((Environment)objects[0]).getObjectModel(); + EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); + if ( null != desc ) { + desc.removeFromAutoRelease(component); + } + } else { + throw new ProcessingException("Unable to remove component from automatic release: no environment available."); + } + } + +} + +final class EnvironmentDescription { + + private static final Configuration EMPTY_CONFIGURATION = + new DefaultConfiguration("config", ""); + + Environment environment; + Map objectModel; + Map requestLifecycleComponents = new HashMap(5); + List autoreleaseComponents = new ArrayList(2); + List sitemapConfigurations = new ArrayList(4); + /** + * Constructor */ - protected void releaseRLComponent( final Component component ) { - super.release( component ); + EnvironmentDescription(Environment env) { + this.environment = env; + this.objectModel = env.getObjectModel(); + } + + /** + * Release all components of this environment + * All RequestLifecycleComponents and autoreleaseComponents are + * released. + */ + void release() { + final Iterator iter = this.requestLifecycleComponents.values().iterator(); + while (iter.hasNext()) { + final Object[] o = (Object[])iter.next(); + final Component component = (Component)o[0]; + ((ComponentManager)o[1]).release( component ); + } + + for(int i = 0; i < autoreleaseComponents.size(); i++) { + final Object[] o = (Object[])autoreleaseComponents.get(i); + final Component component = (Component)o[0]; + if (o[1] instanceof ComponentManager) { + ((ComponentManager)o[1]).release( component ); + } else { + ((ComponentSelector)o[1]).release( component ); + if (o[2] != null) { + ((ComponentManager)o[2]).release( (Component)o[1] ); + } + } + } + } + + + /** + * Add a RequestLifecycleComponent to the environment + */ + void addRequestLifecycleComponent(final String role, + final Component co, + final ComponentManager manager) { + this.requestLifecycleComponents.put(role, new Object[] {co, manager}); + } + + boolean containsRequestLifecycleComponent(final String role) { + return this.requestLifecycleComponents.containsKey( role ); + } + + /** + * Search a RequestLifecycleComponent + */ + Component getRequestLifecycleComponent(final String role) { + final Object[] o = (Object[])this.requestLifecycleComponents.get(role); + if ( null != o ) { + return (Component)o[0]; + } + return null; + } + + /** + * Add an automatically released component + */ + void addToAutoRelease(final ComponentSelector selector, + final Component component, + final ComponentManager manager) { + this.autoreleaseComponents.add(new Object[] {component, selector, manager}); + } + + /** + * Add an automatically released component + */ + void addToAutoRelease(final ComponentManager manager, + final Component component) { + this.autoreleaseComponents.add(new Object[] {component, manager}); + } + + /** + * Remove from automatically released components + */ + void removeFromAutoRelease(final Component component) + throws ProcessingException { + int i = 0; + boolean found = false; + while (i < this.autoreleaseComponents.size() && !found) { + final Object[] o = (Object[])this.autoreleaseComponents.get(i); + if (o[0] == component) { + found = true; + if (o[1] instanceof ComponentManager) { + ((ComponentManager)o[1]).release( component ); + } else { + ((ComponentSelector)o[1]).release( component ); + if (o[2] != null) { + ((ComponentManager)o[2]).release( (Component)o[1] ); + } + } + this.autoreleaseComponents.remove(i); + } else { + i++; + } + } + if (!found) { + throw new ProcessingException("Unable to remove component from automatic release: component not found."); + } + } + + + void addSitemapConfiguration(Configuration conf) { + if (conf != null) { + this.sitemapConfigurations.add(conf); + } } + + List getSitemapConfigurations() { + return this.sitemapConfigurations; + } + + void removeLastSitemapConfiguration() { + this.sitemapConfigurations.remove(this.sitemapConfigurations.size()-1); + } } No revision No revision 1.9.2.4 +31 -3 xml-cocoon2/src/java/org/apache/cocoon/components/source/SitemapSource.java Index: SitemapSource.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/source/SitemapSource.java,v retrieving revision 1.9.2.3 retrieving revision 1.9.2.4 diff -u -r1.9.2.3 -r1.9.2.4 --- SitemapSource.java 4 Aug 2002 04:11:52 -0000 1.9.2.3 +++ SitemapSource.java 20 Nov 2002 11:21:49 -0000 1.9.2.4 @@ -59,6 +59,8 @@ import org.apache.cocoon.components.pipeline.CacheableEventPipeline; import org.apache.cocoon.components.pipeline.EventPipeline; import org.apache.cocoon.components.pipeline.StreamPipeline; +import org.apache.cocoon.components.sax.XMLDeserializer; +import org.apache.cocoon.components.sax.XMLSerializer; import org.apache.cocoon.environment.Environment; import org.apache.cocoon.environment.ModifiableSource; import org.apache.cocoon.environment.Source; @@ -107,6 +109,7 @@ /** The processor */ private Processor processor; + /** The pipeline processor */ private Processor pipelineProcessor; /** The environment */ @@ -130,6 +133,9 @@ /** Do I need a refresh ? */ private boolean needsRefresh; + /** The unique key for this processing */ + private Object processKey; + /** * Construct a new object */ @@ -237,6 +243,9 @@ } try { + CocoonComponentManager.enterEnvironment(this.environment, + this.environment.getObjectModel(), + this.pipelineProcessor); ByteArrayOutputStream os = new ByteArrayOutputStream(); this.environment.setOutputStream(os); this.pipeline.process(this.environment); @@ -246,7 +255,8 @@ } catch (Exception e) { throw new ProcessingException("Exception during processing of " + this.systemId, e); } finally { - // Unhide wrapped environment output stream + CocoonComponentManager.leaveEnvironment(); + // Unhide wrapped environment output stream this.environment.setOutputStream(null); reset(); } @@ -267,6 +277,7 @@ reset(); try { // initialize the pipelines + this.processKey = CocoonComponentManager.startProcessing(this.environment); this.eventPipeline = (EventPipeline)this.manager.lookup(EventPipeline.ROLE); this.pipeline = (StreamPipeline)this.manager.lookup(StreamPipeline.ROLE); @@ -357,15 +368,28 @@ if (this.redirectSource != null) { this.redirectSource.toSAX(consumer); } else { + // We have to buffer the result in order to get + // clean environment stack handling. + XMLSerializer xmls = (XMLSerializer) this.manager.lookup(XMLSerializer.ROLE); + Object fragment; try { CocoonComponentManager.enterEnvironment(this.environment, this.environment.getObjectModel(), this.pipelineProcessor); - ((XMLProducer)eventPipeline).setConsumer(consumer); + ((XMLProducer)eventPipeline).setConsumer(xmls); eventPipeline.process(this.environment); + fragment = xmls.getSAXFragment(); } finally { + this.manager.release(xmls); CocoonComponentManager.leaveEnvironment(); } + XMLDeserializer xmld = (XMLDeserializer) this.manager.lookup(XMLDeserializer.ROLE); + try { + xmld.setConsumer(consumer); + xmld.deserialize(fragment); + } finally { + this.manager.release(xmld); + } } } catch (ComponentException cme) { throw new ProcessingException("Could not lookup pipeline components", cme); @@ -383,6 +407,10 @@ private void reset() { if (this.eventPipeline != null) this.manager.release(this.eventPipeline); if (this.pipeline != null) this.manager.release(this.pipeline); + if (this.processKey != null) { + CocoonComponentManager.endProcessing(this.processKey); + this.processKey = null; + } this.eventPipeline = null; this.pipeline = null; this.lastModificationDate = 0; No revision No revision 1.138.2.69 +4 -1 xml-cocoon2/changes.xml Index: changes.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/changes.xml,v retrieving revision 1.138.2.68 retrieving revision 1.138.2.69 diff -u -r1.138.2.68 -r1.138.2.69 --- changes.xml 17 Nov 2002 19:01:39 -0000 1.138.2.68 +++ changes.xml 20 Nov 2002 11:21:50 -0000 1.138.2.69 @@ -39,6 +39,9 @@ </devs> <release version="@version@" date="@date@"> + <action dev="CZ" type="fix" fixes-bug="12293"> + RequestLifecycleComponents were not handled properly when the cocoon: protocol is used + </action> <action dev="CH" type="update"> Changed SimpleFormTransformer to use InputModules. </action>
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]