You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by da...@apache.org on 2005/04/10 21:11:41 UTC

svn commit: r160799 - in cocoon/trunk/src: java/org/apache/cocoon/components/pipeline/ java/org/apache/cocoon/components/treeprocessor/sitemap/ java/org/apache/cocoon/environment/internal/ java/org/apache/cocoon/generation/ java/org/apache/cocoon/reading/ java/org/apache/cocoon/serialization/ java/org/apache/cocoon/sitemap/impl/ java/org/apache/cocoon/transformation/ test/org/apache/cocoon/generation/ test/org/apache/cocoon/reading/ test/org/apache/cocoon/serialization/ test/org/apache/cocoon/transformation/ webapp/WEB-INF/xconf/

Author: danielf
Date: Sun Apr 10 12:11:35 2005
New Revision: 160799

URL: http://svn.apache.org/viewcvs?view=rev&rev=160799
Log:
Added VirtualPipelineSerializer and VirtualPipelineTransformer and refactored the two other VPCs. New environment functionality for adding and removing the current environment in pipelines. Additions to the VirtualProcessingPipeline to support transformer and serializer. Various test cases for everything. All test cases works. Added the environment-attr to cocoon-core.xconf.

Added:
    cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PopEnvironmentChanger.java   (with props)
    cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PushEnvironmentChanger.java   (with props)
    cocoon/trunk/src/java/org/apache/cocoon/serialization/VirtualPipelineSerializer.java   (with props)
    cocoon/trunk/src/java/org/apache/cocoon/transformation/VirtualPipelineTransformer.java   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/serialization/
    cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.java   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.xconf   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-include.xsl   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-sitemap.xmap   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test.xml   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test2.xml   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-v2-expected.xml   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.java   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.xconf   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-include.xsl   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-sitemap.xmap   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test.xml   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test2.xml   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-transform.xsl   (with props)
    cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-v2-expected.xml   (with props)
Modified:
    cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java
    cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCsNodeBuilder.java
    cocoon/trunk/src/java/org/apache/cocoon/environment/internal/EnvironmentHelper.java
    cocoon/trunk/src/java/org/apache/cocoon/generation/VirtualPipelineGenerator.java
    cocoon/trunk/src/java/org/apache/cocoon/reading/VirtualPipelineReader.java
    cocoon/trunk/src/java/org/apache/cocoon/sitemap/impl/AbstractVirtualSitemapComponent.java
    cocoon/trunk/src/test/org/apache/cocoon/generation/VirtualPipelineGeneratorTestCase.xconf
    cocoon/trunk/src/test/org/apache/cocoon/generation/vpc-source-param-expected.xml
    cocoon/trunk/src/test/org/apache/cocoon/reading/VirtualPipelineReaderTestCase.xconf
    cocoon/trunk/src/webapp/WEB-INF/xconf/cocoon-core.xconf

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/pipeline/VirtualProcessingPipeline.java Sun Apr 10 12:11:35 2005
@@ -84,6 +84,12 @@
     private boolean prepared;
 
     /**
+     * This is the first consumer component in the pipeline, either
+     * the first transformer or the serializer.
+     */
+    protected XMLConsumer firstConsumer;
+
+    /**
      * This is the last component in the pipeline, either the serializer
      * or a custom xmlconsumer for the cocoon: protocol etc.
      */
@@ -174,15 +180,9 @@
      * @param source the source used to setup the transformer (e.g. XSL file), or
      *        <code>null</code> if no source is given.
      * @param param the parameters for the transfomer.
-     * @throws org.apache.cocoon.ProcessingException if the generator couldn't be obtained.
      */
     public void addTransformer(String role, String source, Parameters param, Parameters hintParam)
     throws ProcessingException {
-        if (this.generator == null) {
-            throw new ProcessingException ("Must set a generator before adding transformer '" + role +
-                                           "' at " + getLocation(param));
-        }
-
         try {
             this.transformers.add(this.newManager.lookup(Transformer.ROLE + '/' + role));
         } catch (ServiceException ce) {
@@ -204,11 +204,6 @@
                                            "' at " + getLocation(param));
         }
 
-        if (this.generator == null) {
-            throw new ProcessingException ("Must set a generator before setting serializer '" + role +
-                                           "' at " + getLocation(param));
-        }
-
         try {
             this.serializer = (Serializer)this.newManager.lookup(Serializer.ROLE + '/' + role);
         } catch (ServiceException ce) {
@@ -231,13 +226,9 @@
 
     /**
      * Sanity check
-     * @return true if the pipeline is 'sane', false otherwise.
+     * @return true if the pipeline is 'sane', for VPCs all pipelines are sane
      */
     protected boolean checkPipeline() {
-        if (this.generator == null) {
-            return false;
-        }
-
         return true;
     }
 
@@ -250,12 +241,12 @@
             // SourceResolver resolver = this.processor.getSourceResolver();
 
             // setup the generator
-            this.generator.setup(
-                resolver,
-                environment.getObjectModel(),
-                generatorSource,
-                generatorParam
-            );
+            if (this.generator != null) {
+                this.generator.setup(resolver,
+                                     environment.getObjectModel(),
+                                     generatorSource,
+                                     generatorParam);
+            }
 
             Iterator transformerItt = this.transformers.iterator();
             Iterator transformerSourceItt = this.transformerSources.iterator();
@@ -270,7 +261,7 @@
                 );
             }
 
-            if (this.serializer instanceof SitemapModelComponent) {
+            if (this.serializer != null && this.serializer instanceof SitemapModelComponent) {
                 ((SitemapModelComponent)this.serializer).setup(
                     resolver,
                     environment.getObjectModel(),
@@ -305,14 +296,24 @@
         XMLProducer prev = this.generator;
 
         Iterator itt = this.transformers.iterator();
+
+        // No generator for VPC transformer and serializer 
+        if (this.generator == null && itt.hasNext()) {
+            this.firstConsumer = (XMLConsumer)(prev = (XMLProducer)itt.next());
+        }
+
         while (itt.hasNext()) {
             Transformer next = (Transformer) itt.next();
             connect(environment, prev, next);
             prev = next;
         }
-
+        
         // insert the serializer
-        connect(environment, prev, this.lastConsumer);
+        if (prev != null) {
+            connect(environment, prev, this.lastConsumer);
+        } else {
+            this.firstConsumer = this.lastConsumer;
+        }
     }
 
     /**
@@ -395,13 +396,119 @@
     }
 
     /**
+     * Process the given <code>Environment</code>, but do not use the
+     * serializer. Instead the sax events are streamed to the XMLConsumer.
+     */
+    public boolean process(Environment environment, XMLConsumer consumer)
+    throws ProcessingException {
+        // Exception happened during setup and was handled
+        if (this.errorPipeline != null) {
+            return this.errorPipeline.processingPipeline.process(environment, consumer);
+        }
+
+        // Have to buffer events if error handler is specified.
+        SaxBuffer buffer = null;
+        this.lastConsumer = this.errorHandler == null? consumer: (buffer = new SaxBuffer());
+        try {
+            connectPipeline(environment);
+            return processXMLPipeline(environment);
+        } catch (ProcessingException e) {
+            buffer = null;
+            return processErrorHandler(environment, e, consumer);
+        } finally {
+            if (buffer != null) {
+                try {
+                    buffer.toSAX(consumer);
+                } catch (SAXException e) {
+                    throw new ProcessingException("Failed to execute pipeline.", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Get the first consumer - used for VPC transformers
+     */
+    public XMLConsumer getXMLConsumer(Environment environment, XMLConsumer consumer)
+        throws ProcessingException {
+        if (!this.prepared) {
+            preparePipeline(environment);
+        }
+
+        this.lastConsumer = consumer;
+        connectPipeline(environment);
+
+        if (this.firstConsumer == null)
+            throw new ProcessingException("A VPC transformer pipeline should not contain a generator.");
+
+        return this.firstConsumer;
+    }
+
+    /**
+     * Get the first consumer - used for VPC serializers
+     */
+    public XMLConsumer getXMLConsumer(Environment environment) throws ProcessingException {
+        if (!this.prepared) {
+            preparePipeline(environment);
+        }
+
+        // If this is an internal request, lastConsumer was reset!
+        if (this.lastConsumer == null) {
+            this.lastConsumer = this.serializer;
+        }
+        
+        connectPipeline(environment);
+
+        if (this.serializer == null) {
+            throw new ProcessingException("A VPC serializer pipeline must contain a serializer.");
+        }
+
+        try {
+            this.serializer.setOutputStream(environment.getOutputStream(0));
+        } catch (Exception e) {
+            throw new ProcessingException("Couldn't set output stream ", e);
+        }
+            
+        if (this.firstConsumer == null)
+            throw new ProcessingException("A VPC serializer pipeline should not contain a generator.");
+
+        return this.firstConsumer;
+    }
+
+    /**
+     * Get the mime-type for the serializer
+     */
+    public String getMimeType() {
+        if (this.lastConsumer == null) {
+            // internal processing: text/xml
+            return "text/xml";
+        } else {
+            // Get the mime-type
+            if (serializerMimeType != null) {
+                // there was a serializer defined in the sitemap
+                return serializerMimeType;
+            } else {
+                // ask to the component itself
+                return this.serializer.getMimeType();
+            }
+        }
+    }
+
+    /**
+     * Test if the serializer wants to set the content length
+     */
+    public boolean shouldSetContentLength() {
+        return this.serializer.shouldSetContentLength();
+    }
+
+    /**
      * Process the SAX event pipeline
      */
     protected boolean processXMLPipeline(Environment environment)
     throws ProcessingException {
 
         try {
-            if (this.lastConsumer == null) {
+            if (this.lastConsumer == null || this.serializer == null) {
                 // internal processing
                 this.generator.generate();
             } else {
@@ -430,7 +537,6 @@
         return true;
     }
 
-
     public void recycle() {
         this.prepared = false;
 
@@ -458,43 +564,13 @@
         this.serializer = null;
         this.processor = null;
         this.lastConsumer = null;
+        this.firstConsumer = null;
 
         // Release error handler
         this.errorHandler = null;
         if (this.errorPipeline != null) {
             this.errorPipeline.release();
             this.errorPipeline = null;
-        }
-    }
-
-    /**
-     * Process the given <code>Environment</code>, but do not use the
-     * serializer. Instead the sax events are streamed to the XMLConsumer.
-     */
-    public boolean process(Environment environment, XMLConsumer consumer)
-    throws ProcessingException {
-        // Exception happened during setup and was handled
-        if (this.errorPipeline != null) {
-            return this.errorPipeline.processingPipeline.process(environment, consumer);
-        }
-
-        // Have to buffer events if error handler is specified.
-        SaxBuffer buffer = null;
-        this.lastConsumer = this.errorHandler == null? consumer: (buffer = new SaxBuffer());
-        try {
-            connectPipeline(environment);
-            return processXMLPipeline(environment);
-        } catch (ProcessingException e) {
-            buffer = null;
-            return processErrorHandler(environment, e, consumer);
-        } finally {
-            if (buffer != null) {
-                try {
-                    buffer.toSAX(consumer);
-                } catch (SAXException e) {
-                    throw new ProcessingException("Failed to execute pipeline.", e);
-                }
-            }
         }
     }
 

Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCsNodeBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCsNodeBuilder.java?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCsNodeBuilder.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCsNodeBuilder.java Sun Apr 10 12:11:35 2005
@@ -23,6 +23,8 @@
 import org.apache.cocoon.components.treeprocessor.ProcessingNode;
 import org.apache.cocoon.generation.VirtualPipelineGenerator;
 import org.apache.cocoon.reading.VirtualPipelineReader;
+import org.apache.cocoon.serialization.VirtualPipelineSerializer;
+import org.apache.cocoon.transformation.VirtualPipelineTransformer;
 
 /**
  * Handles a set of virtual sitemap components.
@@ -45,6 +47,8 @@
 
         String clazz = child.getAttribute("src");
         return VirtualPipelineGenerator.class.getName().equals(clazz)
+            || VirtualPipelineSerializer.class.getName().equals(clazz)
+            || VirtualPipelineTransformer.class.getName().equals(clazz)
             || VirtualPipelineReader.class.getName().equals(clazz);
     }
 

Modified: cocoon/trunk/src/java/org/apache/cocoon/environment/internal/EnvironmentHelper.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/environment/internal/EnvironmentHelper.java?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/environment/internal/EnvironmentHelper.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/environment/internal/EnvironmentHelper.java Sun Apr 10 12:11:35 2005
@@ -294,6 +294,38 @@
     }
 
     /**
+     * This method is used for entering a new environment.
+     *
+     * @throws ProcessingException if there is no current processing environment
+     */
+    public static void enterEnvironment(Environment env)
+    throws ProcessingException {
+        final EnvironmentStack stack = (EnvironmentStack)environmentStack.get();
+        EnvironmentInfo info = null;
+        if ( stack != null && !stack.isEmpty()) {
+            info = stack.getCurrentInfo();
+        } else {
+            throw new ProcessingException("There must be a current processing environment.");
+        }
+
+        stack.pushInfo(new EnvironmentInfo(info.processor, stack.getOffset(), info.manager, env));
+        stack.setOffset(stack.size() - 1);
+    }
+
+    /**
+     * This method is used for leaving the current environment.
+     * 
+     * <p>It's the counterpart to the {@link #enterEnvironment(Environment)} method.</p>
+     */
+    public static Environment leaveEnvironment() {
+        final EnvironmentStack stack = (EnvironmentStack)environmentStack.get();
+        final EnvironmentInfo info = (EnvironmentInfo)stack.pop();
+        stack.setOffset(info.oldStackCount);
+
+        return info.environment;
+    }
+
+    /**
      * INTERNAL METHOD. Do not use, can be removed without warning or deprecation cycle.
      */
     public static int markEnvironment() {
@@ -370,6 +402,22 @@
         final EnvironmentInfo info = stack.getCurrentInfo();
         return stack.getEnvironmentAwareConsumerWrapper(consumer, info.oldStackCount);
     }
+
+    /**
+     * Create an environment aware xml consumer that push an
+     * environment before calling the consumer.
+     */
+    public static XMLConsumer createPushEnvironmentConsumer(XMLConsumer consumer, Environment environment) {
+        return new PushEnvironmentChanger(consumer, environment);
+    }
+
+    /**
+     * Create an environment aware xml consumer that pop and save the
+     * current environment before calling the consumer.
+     */
+    public static XMLConsumer createPopEnvironmentConsumer(XMLConsumer consumer) {
+        return new PopEnvironmentChanger(consumer);
+    }
 }
 
 final class CloningInheritableThreadLocal
@@ -394,4 +442,3 @@
         return null;
     }
 }
-

Added: cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PopEnvironmentChanger.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PopEnvironmentChanger.java?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PopEnvironmentChanger.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PopEnvironmentChanger.java Sun Apr 10 12:11:35 2005
@@ -0,0 +1,193 @@
+/*
+ * Copyright 1999-2004 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.environment.internal;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.Environment;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * This is an internal class, and it might change in an incompatible way over time.
+ * For developing your own components/applications based on Cocoon, you shouldn't 
+ * really need it.
+ *
+ * This class is an {@link 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.
+ *
+ * This environment changer pop the current environment from the
+ * environment stack before calling the embeded consumer and push it
+ * back afterwards. It should be placed after a sitemap component that
+ * is be executed in another environment.
+ */
+
+final class PopEnvironmentChanger
+implements XMLConsumer {
+
+    final XMLConsumer consumer;
+    
+    PopEnvironmentChanger(XMLConsumer consumer) {
+        this.consumer = consumer;
+    }
+    
+    private Environment leaveEnvironment() {
+        return EnvironmentHelper.leaveEnvironment();
+    }
+
+    private void enterEnvironment(Environment environment) throws SAXException {
+        try {
+            EnvironmentHelper.enterEnvironment(environment);
+        } catch (ProcessingException e) {
+            throw new SAXException("PopEnvironmentChanger: ", e);
+        }
+    }
+
+    public void setDocumentLocator(Locator locator) {
+        Environment environment = leaveEnvironment();
+        this.consumer.setDocumentLocator(locator);
+        try {
+            enterEnvironment(environment);
+        } catch (SAXException e) {
+            throw new RuntimeException("PopEnvironmentChanger: ", e);
+        }
+    }
+
+    public void startDocument()
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.startDocument();
+        enterEnvironment(environment);
+    }
+
+    public void endDocument()
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.endDocument();
+        enterEnvironment(environment);
+    }
+
+    public void startPrefixMapping(String prefix, String uri)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.startPrefixMapping(prefix, uri);
+        enterEnvironment(environment);
+    }
+
+    public void endPrefixMapping(String prefix)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.endPrefixMapping(prefix);
+        enterEnvironment(environment);
+    }
+
+    public void startElement(String uri, String loc, String raw, Attributes a)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.startElement(uri, loc, raw, a);
+        enterEnvironment(environment);
+    }
+
+
+    public void endElement(String uri, String loc, String raw)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.endElement(uri, loc, raw);
+        enterEnvironment(environment);
+    }
+    
+    public void characters(char c[], int start, int len)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.characters(c, start, len);
+        enterEnvironment(environment);
+    }
+
+    public void ignorableWhitespace(char c[], int start, int len)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.ignorableWhitespace(c, start, len);
+        enterEnvironment(environment);
+    }
+
+    public void processingInstruction(String target, String data)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.processingInstruction(target, data);
+        enterEnvironment(environment);
+    }
+
+    public void skippedEntity(String name)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.skippedEntity(name);
+        enterEnvironment(environment);
+    }
+
+    public void startDTD(String name, String publicId, String systemId)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.startDTD(name, publicId, systemId);
+        enterEnvironment(environment);
+    }
+
+    public void endDTD()
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.endDTD();
+        enterEnvironment(environment);
+    }
+
+    public void startEntity(String name)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.startEntity(name);
+        enterEnvironment(environment);
+    }
+
+    public void endEntity(String name)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.endEntity(name);
+        enterEnvironment(environment);
+    }
+
+    public void startCDATA()
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.startCDATA();
+        enterEnvironment(environment);
+    }
+
+    public void endCDATA()
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.endCDATA();
+        enterEnvironment(environment);
+    }
+
+    public void comment(char ch[], int start, int len)
+    throws SAXException {
+        Environment environment = leaveEnvironment();
+        this.consumer.comment(ch, start, len);
+        enterEnvironment(environment);
+    }
+}

Propchange: cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PopEnvironmentChanger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PushEnvironmentChanger.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PushEnvironmentChanger.java?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PushEnvironmentChanger.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PushEnvironmentChanger.java Sun Apr 10 12:11:35 2005
@@ -0,0 +1,195 @@
+/*
+ * Copyright 1999-2004 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.environment.internal;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.Environment;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * This is an internal class, and it might change in an incompatible way over time.
+ * For developing your own components/applications based on Cocoon, you shouldn't 
+ * really need it.
+ *
+ * This class is an {@link 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.
+ *
+ * This environment changer push a given environment on the
+ * environment stack before calling the embeded consumer and pops it
+ * afterwards. It should be placed before a sitemap component that
+ * should be executed in another environment.
+ */
+
+final class PushEnvironmentChanger
+implements XMLConsumer {
+
+    final XMLConsumer consumer;
+    final Environment environment;
+    
+    PushEnvironmentChanger(XMLConsumer consumer, Environment environment) {
+        this.consumer = consumer;
+        this.environment = environment;
+    }
+    
+    private void enterEnvironment() throws SAXException {
+        try {
+            EnvironmentHelper.enterEnvironment(this.environment);
+        } catch (ProcessingException e) {
+            throw new SAXException("PushEnvironmentChanger: ", e);
+        }
+    }
+
+    private void leaveEnvironment() {
+        EnvironmentHelper.leaveEnvironment();
+    }
+
+    public void setDocumentLocator(Locator locator) {
+        try {
+            enterEnvironment();
+        } catch (SAXException e) {
+            throw new RuntimeException("PushEnvironmentChanger", e);
+        }
+        this.consumer.setDocumentLocator(locator);
+        leaveEnvironment();
+    }
+
+    public void startDocument()
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.startDocument();
+        leaveEnvironment();
+    }
+
+    public void endDocument()
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.endDocument();
+        leaveEnvironment();
+    }
+
+    public void startPrefixMapping(String prefix, String uri)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.startPrefixMapping(prefix, uri);
+        leaveEnvironment();
+    }
+
+    public void endPrefixMapping(String prefix)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.endPrefixMapping(prefix);
+        leaveEnvironment();
+    }
+
+    public void startElement(String uri, String loc, String raw, Attributes a)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.startElement(uri, loc, raw, a);
+        leaveEnvironment();
+    }
+
+
+    public void endElement(String uri, String loc, String raw)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.endElement(uri, loc, raw);
+        leaveEnvironment();
+    }
+    
+    public void characters(char c[], int start, int len)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.characters(c, start, len);
+        leaveEnvironment();
+    }
+
+    public void ignorableWhitespace(char c[], int start, int len)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.ignorableWhitespace(c, start, len);
+        leaveEnvironment();
+    }
+
+    public void processingInstruction(String target, String data)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.processingInstruction(target, data);
+        leaveEnvironment();
+    }
+
+    public void skippedEntity(String name)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.skippedEntity(name);
+        leaveEnvironment();
+    }
+
+    public void startDTD(String name, String publicId, String systemId)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.startDTD(name, publicId, systemId);
+        leaveEnvironment();
+    }
+
+    public void endDTD()
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.endDTD();
+        leaveEnvironment();
+    }
+
+    public void startEntity(String name)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.startEntity(name);
+        leaveEnvironment();
+    }
+
+    public void endEntity(String name)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.endEntity(name);
+        leaveEnvironment();
+    }
+
+    public void startCDATA()
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.startCDATA();
+        leaveEnvironment();
+    }
+
+    public void endCDATA()
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.endCDATA();
+        leaveEnvironment();
+    }
+
+    public void comment(char ch[], int start, int len)
+    throws SAXException {
+        enterEnvironment();
+        this.consumer.comment(ch, start, len);
+        leaveEnvironment();
+    }
+}

Propchange: cocoon/trunk/src/java/org/apache/cocoon/environment/internal/PushEnvironmentChanger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: cocoon/trunk/src/java/org/apache/cocoon/generation/VirtualPipelineGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/generation/VirtualPipelineGenerator.java?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/generation/VirtualPipelineGenerator.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/generation/VirtualPipelineGenerator.java Sun Apr 10 12:11:35 2005
@@ -15,68 +15,40 @@
  */
 package org.apache.cocoon.generation;
 
-import org.apache.cocoon.Constants;
 import org.apache.cocoon.ProcessingException;
-import org.apache.cocoon.environment.Environment;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.sitemap.impl.AbstractVirtualSitemapComponent;
-import org.apache.cocoon.xml.XMLConsumer;
 
 import org.xml.sax.SAXException;
 
 import java.io.IOException;
-import java.util.Map;
-
 
 public class VirtualPipelineGenerator extends AbstractVirtualSitemapComponent
     implements Generator {
 
-    protected XMLConsumer consumer;
-
     protected String getTypeName() {
         return "generator";
     }
 
-    public void setConsumer(XMLConsumer consumer) {
-        this.consumer = consumer;
-    }
-
     public void generate()
     throws IOException, SAXException, ProcessingException {
 
-        // Should use SourceResolver of the this components' sitemap, not caller sitemap
-        // Have to switch to another environment...
-        Environment env = EnvironmentHelper.getCurrentEnvironment();
-        String oldPrefix = env.getURIPrefix();
-        String oldURI    = env.getURI();
-
-        // save callers resolved sources if there are any
-        Map oldSourceMap = (Map)env.getAttribute(this.sourceMapName);
-        // place for resolved sources
-        env.setAttribute(this.sourceMapName, this.sourceMap);
-
+        // Should use SourceResolver and context of the this
+        // components' sitemap, not caller sitemap
+        EnvironmentHelper.enterEnvironment(this.getVPCEnvironment());
         try {
-            try {
-                String uri = (String) this.context.get(Constants.CONTEXT_ENV_URI);
-                String prefix = (String) this.context.get(Constants.CONTEXT_ENV_PREFIX);
-                env.setURI(prefix, uri);
-                
-                this.pipeline.prepareInternal(env);
-            } catch (Exception e) {
-                throw new ProcessingException("Oops", e);
-            } finally {
-                // Restore context
-                env.setURI(oldPrefix, oldURI);
-            }
-
-            this.pipeline.process(env, this.consumer);
+            this.getPipeline().prepareInternal(this.getVPCEnvironment());
+        } finally {
+            EnvironmentHelper.leaveEnvironment();
+        }
 
+        // Should use SourceResolver of the this components' sitemap, not caller sitemap
+        EnvironmentHelper.enterEnvironment(this.getMappedSourceEnvironment());
+        try {
+            this.getPipeline().process(this.getMappedSourceEnvironment(),
+                                  EnvironmentHelper.createPopEnvironmentConsumer(this.xmlConsumer));
         } finally {
-            // restore sourceMap
-            if (oldSourceMap != null)
-                env.setAttribute(this.sourceMapName, oldSourceMap);
-            else
-                env.removeAttribute(this.sourceMapName);
+            EnvironmentHelper.leaveEnvironment();
         }
     }
  }

Modified: cocoon/trunk/src/java/org/apache/cocoon/reading/VirtualPipelineReader.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/reading/VirtualPipelineReader.java?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/reading/VirtualPipelineReader.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/reading/VirtualPipelineReader.java Sun Apr 10 12:11:35 2005
@@ -15,9 +15,7 @@
  */
 package org.apache.cocoon.reading;
 
-import org.apache.cocoon.Constants;
 import org.apache.cocoon.ProcessingException;
-import org.apache.cocoon.environment.Environment;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.sitemap.impl.AbstractVirtualSitemapComponent;
 
@@ -25,15 +23,10 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.Map;
-
 
 public class VirtualPipelineReader extends AbstractVirtualSitemapComponent
     implements Reader {
 
-    /** The <code>OutputStream</code> to write on. */
-    protected OutputStream out;
-
     protected String getTypeName() {
         return "reader";
     }
@@ -41,20 +34,15 @@
     /**
      * Set the <code>OutputStream</code>
      */
-    // The output stream from
-    // EnvironmentHelper.getCurrentEnvironment() is used instead. Is
-    // it always the same?
     public void setOutputStream(OutputStream out) {
-	this.out = out;
+        this.getMappedSourceEnvironment().setOutputStream(out);
     }
 
     /**
      * Get the mime-type of the output of this <code>Reader</code>
-     * This default implementation returns null to indicate that the
-     * mime-type specified in the sitemap is to be used
      */
     public String getMimeType() {
-        return null;
+        return this.getPipeline().getMimeType();
     }
 
     /**
@@ -66,55 +54,30 @@
     }
 
     /**
-     * Recycle the component
-     */
-    public void recycle() {
-        this.out = null;
-    }
-
-    /**
      * Test if the component wants to set the content length
      */
     public boolean shouldSetContentLength() {
-        return false;
+        return this.getPipeline().shouldSetContentLength();
     }
 
     public void generate()
     throws IOException, SAXException, ProcessingException {
 
-        // Should use SourceResolver of the this components' sitemap, not caller sitemap
-        // Have to switch to another environment...
-        Environment env = EnvironmentHelper.getCurrentEnvironment();
-        String oldPrefix = env.getURIPrefix();
-        String oldURI    = env.getURI();
-
-        // save callers resolved sources if there are any
-        Map oldSourceMap = (Map)env.getAttribute(this.sourceMapName);
-        // place for resolved sources
-        env.setAttribute(this.sourceMapName, this.sourceMap);
-
+        // Should use SourceResolver and context of the this
+        // components' sitemap, not caller sitemap
+        EnvironmentHelper.enterEnvironment(this.getVPCEnvironment());
         try {
-            try {
-                String uri = (String) this.context.get(Constants.CONTEXT_ENV_URI);
-                String prefix = (String) this.context.get(Constants.CONTEXT_ENV_PREFIX);
-                env.setURI(prefix, uri);
-                
-                this.pipeline.prepareInternal(env);
-            } catch (Exception e) {
-                throw new ProcessingException("Oops", e);
-            } finally {
-                // Restore context
-                env.setURI(oldPrefix, oldURI);
-            }
-
-            this.pipeline.process(env);
+            this.getPipeline().prepareInternal(this.getVPCEnvironment());
+        } finally {
+            EnvironmentHelper.leaveEnvironment();
+        }
 
+        // Should use SourceResolver of the this components' sitemap, not caller sitemap
+        EnvironmentHelper.enterEnvironment(this.getMappedSourceEnvironment());
+        try {
+            this.getPipeline().process(this.getMappedSourceEnvironment());
         } finally {
-            // restore sourceMap
-            if (oldSourceMap != null)
-                env.setAttribute(this.sourceMapName, oldSourceMap);
-            else
-                env.removeAttribute(this.sourceMapName);
+            EnvironmentHelper.leaveEnvironment();
         }
     }
- }
+}

Added: cocoon/trunk/src/java/org/apache/cocoon/serialization/VirtualPipelineSerializer.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/serialization/VirtualPipelineSerializer.java?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/serialization/VirtualPipelineSerializer.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/serialization/VirtualPipelineSerializer.java Sun Apr 10 12:11:35 2005
@@ -0,0 +1,84 @@
+/*
+ * Copyright 1999-2004 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.serialization;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.internal.EnvironmentHelper;
+import org.apache.cocoon.sitemap.impl.AbstractVirtualSitemapComponent;
+import org.apache.cocoon.xml.XMLConsumer;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class VirtualPipelineSerializer extends AbstractVirtualSitemapComponent
+    implements Serializer {
+
+    protected String getTypeName() {
+        return "serializer";
+    }
+
+    /**
+     * Set the <code>OutputStream</code>
+     */
+    public void setOutputStream(OutputStream out) {
+        this.getMappedSourceEnvironment().setOutputStream(out);
+    }
+
+    /**
+     * Get the mime-type of the output of this <code>Reader</code>
+     */
+    public String getMimeType() {
+        return this.getPipeline().getMimeType();
+    }
+
+    /**
+     * Test if the component wants to set the content length
+     */
+    public boolean shouldSetContentLength() {
+        return this.getPipeline().shouldSetContentLength();
+    }
+
+    /**
+     *  Process the SAX event. A new document is processed. The
+     *  internal pipeline is prepared.
+     *
+     *  @see org.xml.sax.ContentHandler#startDocument()
+     */
+    public void startDocument() throws SAXException {
+        // Should use SourceResolver and context of the this
+        // components' sitemap, not caller sitemap
+        try {
+            EnvironmentHelper.enterEnvironment(this.getVPCEnvironment());
+            this.getPipeline().prepareInternal(this.getVPCEnvironment());
+        } catch (Exception e) {
+            throw new SAXException("VirtualPipelineSerializer: couldn't create internal pipeline ", e);
+        } finally {
+            EnvironmentHelper.leaveEnvironment();
+        }
+
+        try {
+            super.setConsumer(EnvironmentHelper
+                              .createPushEnvironmentConsumer(this.getPipeline().getXMLConsumer(this.getMappedSourceEnvironment()),
+                                                             this.getMappedSourceEnvironment()));
+        } catch (ProcessingException e) {
+            throw new SAXException("VirtualPipelineSerializer: couldn't get xml consumer from the pipeline ", e);
+        }
+
+        super.startDocument();
+    }
+ }

Propchange: cocoon/trunk/src/java/org/apache/cocoon/serialization/VirtualPipelineSerializer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: cocoon/trunk/src/java/org/apache/cocoon/sitemap/impl/AbstractVirtualSitemapComponent.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/sitemap/impl/AbstractVirtualSitemapComponent.java?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/sitemap/impl/AbstractVirtualSitemapComponent.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/sitemap/impl/AbstractVirtualSitemapComponent.java Sun Apr 10 12:11:35 2005
@@ -23,7 +23,7 @@
 import org.apache.avalon.framework.context.ContextException;
 import org.apache.avalon.framework.context.Contextualizable;
 import org.apache.avalon.framework.context.DefaultContext;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.logger.Logger;
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
@@ -32,7 +32,7 @@
 import org.apache.cocoon.Constants;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.components.source.SourceUtil;
-import org.apache.cocoon.components.pipeline.ProcessingPipeline;
+import org.apache.cocoon.components.source.impl.SitemapSourceInfo;
 import org.apache.cocoon.components.pipeline.VirtualProcessingPipeline;
 import org.apache.cocoon.components.treeprocessor.InvokeContext;
 import org.apache.cocoon.components.treeprocessor.ProcessingNode;
@@ -40,7 +40,9 @@
 import org.apache.cocoon.environment.Environment;
 import org.apache.cocoon.environment.SourceResolver;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
+import org.apache.cocoon.environment.wrapper.EnvironmentWrapper;
 import org.apache.cocoon.sitemap.SitemapModelComponent;
+import org.apache.cocoon.xml.AbstractXMLPipe;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceException;
 import org.apache.excalibur.xml.sax.XMLizable;
@@ -60,24 +62,28 @@
  * <li>Implement caching
  * </ul>
  */
-public abstract class AbstractVirtualSitemapComponent extends AbstractLogEnabled
+public abstract class AbstractVirtualSitemapComponent extends AbstractXMLPipe
     implements SitemapModelComponent, Serviceable, Disposable, Contextualizable, Configurable {
 
-    protected SourceResolver resolver;
+    private ProcessingNode node;
+    private String sourceMapName;
+    private Map sourceMap = new HashMap();
+    private Set sources;
+    private VirtualProcessingPipeline pipeline;
+    // An environment containing a map with the souces from the calling environment
+    private EnvironmentWrapper mappedSourceEnvironment;
+    // An environment with the URI and URI prefix of the sitemap where the VPC is defined
+    private EnvironmentWrapper vpcEnvironment;
+
     protected DefaultContext context;
+    protected SourceResolver resolver;
     protected ServiceManager manager;
-    protected ProcessingNode node;
-    protected ProcessingPipeline pipeline;
-    protected String sourceMapName;
-    protected Map sourceMap = new HashMap();
-    protected Set sources;
-    protected String name;
 
-
-    protected class MyInvokeContext extends InvokeContext {
-        public MyInvokeContext() throws Exception {
+    private class MyInvokeContext extends InvokeContext {
+        public MyInvokeContext(Logger logger) throws Exception {
             super(true);
             super.processingPipeline = new VirtualProcessingPipeline(AbstractVirtualSitemapComponent.this.context);
+            ((VirtualProcessingPipeline)super.processingPipeline).enableLogging(logger);
         }
     }
 
@@ -111,16 +117,16 @@
     }
 
     public void configure(Configuration configuration) throws ConfigurationException {
-        this.name = configuration.getAttribute("name");
+        String name = configuration.getAttribute("name");
         this.sourceMapName =
-            Constants.CONTEXT_ENV_PREFIX + "-" + getTypeName() + "-source-map-" + this.name;
+            Constants.CONTEXT_ENV_PREFIX + "-" + getTypeName() + "-source-map-" + name;
         try {
             this.node = (ProcessingNode)this.context.get(Constants.CONTEXT_VPC_PREFIX +
-                                                         getTypeName() + "-" + this.name);
+                                                         getTypeName() + "-" + name);
             this.sources = ((VPCNode)node).getSources();
         } catch (Exception e) {
             throw new ConfigurationException("Can not find VirtualPipelineComponent '" +
-                                             this.name + "' configuration");
+                                             name + "' configuration");
         }
     }
 
@@ -129,13 +135,16 @@
         this.resolver = resolver;
 
         Environment env = EnvironmentHelper.getCurrentEnvironment();
-        String oldPrefix = env.getURIPrefix();
-        String oldURI    = env.getURI();
 
-        // save callers resolved sources if there are any
-        Map oldSourceMap = (Map)env.getAttribute(this.sourceMapName);
+        // Hack to get an info object with the right uri for the
+        // current sitemap, there is no vpc protocol.
+        SitemapSourceInfo mappedSourceEnvironmentInfo =
+            SitemapSourceInfo.parseURI(env, "vpc:/");
+
+        this.mappedSourceEnvironment =
+            new EnvironmentWrapper(env, mappedSourceEnvironmentInfo, getLogger());
         // place for resolved sources
-        env.setAttribute(this.sourceMapName, this.sourceMap);
+        this.mappedSourceEnvironment.setAttribute(this.sourceMapName, this.sourceMap);
 
         MyInvokeContext invoker = null;
 
@@ -143,17 +152,29 @@
             // resolve the sources in the parameter map before switching context
             Map resolvedParams = resolveParams(par, src);
 
-            String uri = (String) this.context.get(Constants.CONTEXT_ENV_URI);
-            String prefix = (String) this.context.get(Constants.CONTEXT_ENV_PREFIX);
-            env.setURI(prefix, uri);
+            // set up info object for VPC environment wrapper, would
+            // better be done in a constructor for the info.
+            SitemapSourceInfo vpcEnvironmentInfo = new SitemapSourceInfo();
+            vpcEnvironmentInfo.prefix = (String) this.context.get(Constants.CONTEXT_ENV_PREFIX);
+            vpcEnvironmentInfo.uri = (String) this.context.get(Constants.CONTEXT_ENV_URI);
+            vpcEnvironmentInfo.requestURI = vpcEnvironmentInfo.prefix + vpcEnvironmentInfo.uri;
+            vpcEnvironmentInfo.rawMode = false;
+
+            // set up the vpc environment
+            this.vpcEnvironment =
+                new EnvironmentWrapper(this.mappedSourceEnvironment,
+                                       vpcEnvironmentInfo, getLogger());
+
+            EnvironmentHelper.enterEnvironment(this.vpcEnvironment);
 
-            invoker = new MyInvokeContext();
+            // set up invoker with sitemap params
+            invoker = new MyInvokeContext(getLogger());
             invoker.enableLogging(getLogger());
             invoker.service(this.manager);
             invoker.pushMap(null, resolvedParams);
 
-            this.node.invoke(env, invoker);
-            this.pipeline = invoker.getProcessingPipeline();
+            this.node.invoke(this.vpcEnvironment, invoker);
+            this.pipeline = (VirtualProcessingPipeline)invoker.getProcessingPipeline();
         } catch (Exception e) {
             throw new ProcessingException("Oops", e);
         } finally {
@@ -162,16 +183,25 @@
                 invoker.dispose();
             }
             // Restore context
-            env.setURI(oldPrefix, oldURI);
-            // restore sourceMap
-            if (oldSourceMap != null)
-                env.setAttribute(this.sourceMapName, oldSourceMap);
-            else
-                env.removeAttribute(this.sourceMapName);
+            EnvironmentHelper.leaveEnvironment();
         }
     }
 
-    protected Map resolveParams(Parameters par, String src)
+    protected VirtualProcessingPipeline getPipeline() {
+        return this.pipeline;
+    }
+
+    // An environment containing a map with the souces from the calling environment
+    protected EnvironmentWrapper getMappedSourceEnvironment() {
+        return this.mappedSourceEnvironment;
+    }
+
+    // An environment with the URI and URI prefix of the sitemap where the VPC is defined
+    protected EnvironmentWrapper getVPCEnvironment() {
+        return this.vpcEnvironment;
+    }
+
+    private Map resolveParams(Parameters par, String src)
         throws ProcessingException, IOException {
         HashMap map = new HashMap();
 
@@ -192,7 +222,7 @@
         return map;
     }
 
-    protected String resolveAndMapSourceURI(String name, String uri)
+    private String resolveAndMapSourceURI(String name, String uri)
         throws ProcessingException, IOException {
 
         // Resolve the URI
@@ -209,9 +239,9 @@
         // Create a new URI that refers to the source in the context
         String mappedURI;
         if (src instanceof XMLizable)
-            mappedURI = "xmodule:environment-attribute:" + this.sourceMapName + "#" + name;
+            mappedURI = "xmodule:environment-attr:" + this.sourceMapName + "#" + name;
         else
-            mappedURI = "module:environment-attribute:" + this.sourceMapName + "#" + name;
+            mappedURI = "module:environment-attr:" + this.sourceMapName + "#" + name;
         
         return mappedURI;
     }

Added: cocoon/trunk/src/java/org/apache/cocoon/transformation/VirtualPipelineTransformer.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/transformation/VirtualPipelineTransformer.java?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/transformation/VirtualPipelineTransformer.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/transformation/VirtualPipelineTransformer.java Sun Apr 10 12:11:35 2005
@@ -0,0 +1,86 @@
+/*
+ * Copyright 1999-2004 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.transformation;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.internal.EnvironmentHelper;
+import org.apache.cocoon.sitemap.impl.AbstractVirtualSitemapComponent;
+import org.apache.cocoon.xml.XMLConsumer;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class VirtualPipelineTransformer extends AbstractVirtualSitemapComponent
+    implements Transformer {
+
+    /** Exception that might occur during setConsumer */
+    private SAXException exceptionDuringSetConsumer;
+
+    protected String getTypeName() {
+        return "transformer";
+    }
+
+    /**
+     * Set the <code>XMLConsumer</code> that will receive XML data.
+     * And set up the internal pipeline for processing.
+     */
+    public void setConsumer(XMLConsumer consumer) {
+        // Should use SourceResolver and context of the this
+        // components' sitemap, not caller sitemap
+        try {
+            EnvironmentHelper.enterEnvironment(this.getVPCEnvironment());
+            this.getPipeline().prepareInternal(this.getVPCEnvironment());
+        } catch (Exception e) {
+            this.exceptionDuringSetConsumer =
+                new SAXException("VirtualPipelineTransformer: couldn't create internal pipeline ", e);
+            return;
+        } finally {
+            EnvironmentHelper.leaveEnvironment();
+        }
+
+        try {
+            // Remove the current environment before calling next pipeline component
+            XMLConsumer outConsumer =
+                EnvironmentHelper.createPopEnvironmentConsumer(consumer);
+            // Call the internal VPC transformer pipeline
+            XMLConsumer transformConsumer =
+                this.getPipeline().getXMLConsumer(this.getMappedSourceEnvironment(),
+                                                  outConsumer);
+            // Add the current environment
+            XMLConsumer inConsumer =
+                EnvironmentHelper.createPushEnvironmentConsumer(transformConsumer,
+                                                                this.getMappedSourceEnvironment());
+            super.setConsumer(inConsumer);
+        } catch (ProcessingException e) {
+            this.exceptionDuringSetConsumer =
+                new SAXException("VirtualPipelineSerializer: couldn't get xml consumer from the pipeline ", e);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.xml.sax.ContentHandler#startDocument()
+     */
+    public void startDocument() throws SAXException {
+        // did an exception occur during setConsumer?
+        // if so, throw it here
+        if ( this.exceptionDuringSetConsumer != null ) {
+            throw this.exceptionDuringSetConsumer;
+        }
+        super.startDocument();
+    }
+ }

Propchange: cocoon/trunk/src/java/org/apache/cocoon/transformation/VirtualPipelineTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: cocoon/trunk/src/test/org/apache/cocoon/generation/VirtualPipelineGeneratorTestCase.xconf
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/generation/VirtualPipelineGeneratorTestCase.xconf?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/generation/VirtualPipelineGeneratorTestCase.xconf (original)
+++ cocoon/trunk/src/test/org/apache/cocoon/generation/VirtualPipelineGeneratorTestCase.xconf Sun Apr 10 12:11:35 2005
@@ -27,7 +27,7 @@
   <xmlizer/>
 
   <input-modules>
-    <component-instance class="org.apache.cocoon.components.modules.input.EnvironmentAttributeModule" name="environment-attribute"/>
+    <component-instance class="org.apache.cocoon.components.modules.input.EnvironmentAttributeModule" name="environment-attr"/>
   </input-modules>
 
   <source-factories>

Modified: cocoon/trunk/src/test/org/apache/cocoon/generation/vpc-source-param-expected.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/generation/vpc-source-param-expected.xml?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/generation/vpc-source-param-expected.xml (original)
+++ cocoon/trunk/src/test/org/apache/cocoon/generation/vpc-source-param-expected.xml Sun Apr 10 12:11:35 2005
@@ -1 +1 @@
-<?xml version="1.0" encoding="UTF-8"?><test source="module:environment-attribute:env-prefix-generator-source-map-virtual3#source" foo2="bar"/>
\ No newline at end of file
+<?xml version="1.0" encoding="UTF-8"?><test source="module:environment-attr:env-prefix-generator-source-map-virtual3#source" foo2="bar"/>
\ No newline at end of file

Modified: cocoon/trunk/src/test/org/apache/cocoon/reading/VirtualPipelineReaderTestCase.xconf
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/reading/VirtualPipelineReaderTestCase.xconf?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/reading/VirtualPipelineReaderTestCase.xconf (original)
+++ cocoon/trunk/src/test/org/apache/cocoon/reading/VirtualPipelineReaderTestCase.xconf Sun Apr 10 12:11:35 2005
@@ -27,7 +27,7 @@
   <xmlizer/>
 
   <input-modules>
-    <component-instance class="org.apache.cocoon.components.modules.input.EnvironmentAttributeModule" name="environment-attribute"/>
+    <component-instance class="org.apache.cocoon.components.modules.input.EnvironmentAttributeModule" name="environment-attr"/>
   </input-modules>
 
   <source-factories>

Added: cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.java?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.java (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.java Sun Apr 10 12:11:35 2005
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1999-2004 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.serialization;
+
+import org.apache.cocoon.SitemapTestCase;
+
+public class VirtualPipelineSerializerTestCase extends SitemapTestCase {
+    public void testSerializer() throws Exception {
+        pipeTest("v1", "vpc-test.xml");
+    }
+
+    public void testInclude() throws Exception {
+        pipeTest("v2", "vpc-v2-expected.xml");
+    }
+}

Propchange: cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.xconf
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.xconf?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.xconf (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.xconf Sun Apr 10 12:11:35 2005
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 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.
+-->
+
+<components>
+  <xml-parser class="org.apache.excalibur.xml.impl.JaxpParser">
+    <parameter name="validate" value="false"/>
+    <parameter name="namespace-prefixes" value="false"/>
+    <parameter name="stop-on-warning" value="true"/>
+    <parameter name="stop-on-recoverable-error" value="true"/>
+    <parameter name="reuse-parsers" value="false"/>
+  </xml-parser>
+
+  <xmlizer/>
+
+  <xslt-processor>
+     <parameter name="use-store" value="false"/>
+     <parameter name="incremental-processing" value="false"/>
+  </xslt-processor>
+
+  <component role="org.apache.excalibur.xml.xslt.XSLTProcessor/xalan"
+             class="org.apache.excalibur.xml.xslt.XSLTProcessorImpl">
+     <parameter name="use-store" value="false"/>
+     <parameter name="incremental-processing" value="false"/>
+     <parameter name="transformer-factory" value="org.apache.xalan.processor.TransformerFactoryImpl"/>
+  </component>
+
+  <input-modules>
+    <component-instance class="org.apache.cocoon.components.modules.input.EnvironmentAttributeModule" name="environment-attr"/>
+  </input-modules>
+
+  <source-factories>
+    <component-instance class="org.apache.excalibur.source.impl.ResourceSourceFactory" name="resource"/>
+    <component-instance class="org.apache.cocoon.components.source.impl.ContextSourceFactory" name="context"/>
+    <component-instance class="org.apache.cocoon.components.source.impl.ModuleSourceFactory" name="module"/>
+    <component-instance class="org.apache.cocoon.components.source.impl.XModuleSourceFactory" name="xmodule"/>
+    <component-instance class="org.apache.excalibur.source.impl.FileSourceFactory" name="file"/>
+    <component-instance class="org.apache.excalibur.source.impl.URLSourceFactory" name="*"/>
+  </source-factories>
+
+  <!-- Relative sitemap path works during sitemap execution but
+       give exceptions during decommissioning -->
+  <sitemap file="resource://org/apache/cocoon/serialization/vpc-sitemap.xmap"/>
+
+</components>
\ No newline at end of file

Propchange: cocoon/trunk/src/test/org/apache/cocoon/serialization/VirtualPipelineSerializerTestCase.xconf
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-include.xsl
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-include.xsl?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-include.xsl (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-include.xsl Sun Apr 10 12:11:35 2005
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:param name="file"/>
+
+  <xsl:template match="/test">
+    <test-out file="{$file}">
+      <xsl:copy-of select="document($file)"/>
+    </test-out>
+  </xsl:template>
+
+</xsl:stylesheet>

Propchange: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-include.xsl
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-sitemap.xmap
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-sitemap.xmap?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-sitemap.xmap (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-sitemap.xmap Sun Apr 10 12:11:35 2005
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright 1999-2004 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.
+-->
+
+<!-- SVN $Id$ -->
+
+<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
+
+  <map:components>
+    <map:generators default="file">
+      <map:generator name="file" src="org.apache.cocoon.generation.FileGenerator"/>
+    </map:generators>
+
+    <map:transformers default="xslt">
+      <map:transformer name="xslt" src="org.apache.cocoon.transformation.TraxTransformer">
+        <xslt-processor-role>xalan</xslt-processor-role>
+      </map:transformer>
+    </map:transformers>
+
+    <map:serializers default="xml">
+      <map:serializer mime-type="text/xml" name="xml" src="org.apache.cocoon.serialization.XMLSerializer"/>
+      <map:serializer name="virtual1" src="org.apache.cocoon.serialization.VirtualPipelineSerializer">
+        <map:serialize type="xml"/>
+      </map:serializer>
+      <map:serializer name="virtual2" src="org.apache.cocoon.serialization.VirtualPipelineSerializer">
+        <map:transform src="vpc-include.xsl">
+           <map:parameter name="file" value="{src}"/>
+        </map:transform>
+        <map:serialize type="xml"/>
+      </map:serializer>
+    </map:serializers>
+
+    <map:matchers default="wildcard">
+      <map:matcher name="wildcard" src="org.apache.cocoon.matching.WildcardURIMatcher"/>
+    </map:matchers>
+
+    <map:pipes default="noncaching">
+      <map:pipe name="noncaching" src="org.apache.cocoon.components.pipeline.impl.NonCachingProcessingPipeline">
+      </map:pipe>
+    </map:pipes>
+  </map:components>
+
+  <map:pipelines>
+    <map:pipeline>
+
+      <map:match pattern="v1">
+        <map:generate src="vpc-test.xml"/>
+        <map:serialize type="virtual1"/>
+      </map:match>
+
+      <map:match pattern="v2">
+        <map:generate src="vpc-test.xml"/>
+        <map:serialize type="virtual2" src="vpc-test2.xml"/>
+      </map:match>
+
+    </map:pipeline>
+  </map:pipelines>
+</map:sitemap>

Propchange: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-sitemap.xmap
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test.xml?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test.xml (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test.xml Sun Apr 10 12:11:35 2005
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><test/>
\ No newline at end of file

Propchange: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test2.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test2.xml?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test2.xml (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test2.xml Sun Apr 10 12:11:35 2005
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><test2/>
\ No newline at end of file

Propchange: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-test2.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-v2-expected.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-v2-expected.xml?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-v2-expected.xml (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-v2-expected.xml Sun Apr 10 12:11:35 2005
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><test-out file="module:environment-attr:env-prefix-serializer-source-map-virtual2#src"><test2/></test-out>
\ No newline at end of file

Propchange: cocoon/trunk/src/test/org/apache/cocoon/serialization/vpc-v2-expected.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.java?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.java (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.java Sun Apr 10 12:11:35 2005
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1999-2004 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.transformation;
+
+import org.apache.cocoon.SitemapTestCase;
+
+public class VirtualPipelineTransformerTestCase extends SitemapTestCase {
+    public void testTransformer() throws Exception {
+        pipeTest("v1", "vpc-test.xml");
+    }
+
+    public void testInclude() throws Exception {
+        pipeTest("v2", "vpc-v2-expected.xml");
+    }
+}

Propchange: cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.xconf
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.xconf?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.xconf (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.xconf Sun Apr 10 12:11:35 2005
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 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.
+-->
+
+<components>
+  <xml-parser class="org.apache.excalibur.xml.impl.JaxpParser">
+    <parameter name="validate" value="false"/>
+    <parameter name="namespace-prefixes" value="false"/>
+    <parameter name="stop-on-warning" value="true"/>
+    <parameter name="stop-on-recoverable-error" value="true"/>
+    <parameter name="reuse-parsers" value="false"/>
+  </xml-parser>
+
+  <xmlizer/>
+
+  <xslt-processor>
+     <parameter name="use-store" value="false"/>
+     <parameter name="incremental-processing" value="false"/>
+  </xslt-processor>
+
+  <component role="org.apache.excalibur.xml.xslt.XSLTProcessor/xalan"
+             class="org.apache.excalibur.xml.xslt.XSLTProcessorImpl">
+     <parameter name="use-store" value="false"/>
+     <parameter name="incremental-processing" value="false"/>
+     <parameter name="transformer-factory" value="org.apache.xalan.processor.TransformerFactoryImpl"/>
+  </component>
+
+  <input-modules>
+    <component-instance class="org.apache.cocoon.components.modules.input.EnvironmentAttributeModule" name="environment-attr"/>
+  </input-modules>
+
+  <source-factories>
+    <component-instance class="org.apache.excalibur.source.impl.ResourceSourceFactory" name="resource"/>
+    <component-instance class="org.apache.cocoon.components.source.impl.ContextSourceFactory" name="context"/>
+    <component-instance class="org.apache.cocoon.components.source.impl.ModuleSourceFactory" name="module"/>
+    <component-instance class="org.apache.cocoon.components.source.impl.XModuleSourceFactory" name="xmodule"/>
+    <component-instance class="org.apache.excalibur.source.impl.FileSourceFactory" name="file"/>
+    <component-instance class="org.apache.excalibur.source.impl.URLSourceFactory" name="*"/>
+  </source-factories>
+
+  <!-- Relative sitemap path works during sitemap execution but
+       give exceptions during decommissioning -->
+  <sitemap file="resource://org/apache/cocoon/transformation/vpc-sitemap.xmap"/>
+
+</components>
\ No newline at end of file

Propchange: cocoon/trunk/src/test/org/apache/cocoon/transformation/VirtualPipelineTransformerTestCase.xconf
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-include.xsl
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-include.xsl?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-include.xsl (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-include.xsl Sun Apr 10 12:11:35 2005
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:param name="file"/>
+
+  <xsl:template match="/test">
+    <test>
+      <xsl:copy-of select="*"/>
+      <xsl:copy-of select="document($file)"/>
+    </test>
+  </xsl:template>
+
+</xsl:stylesheet>

Propchange: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-include.xsl
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-sitemap.xmap
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-sitemap.xmap?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-sitemap.xmap (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-sitemap.xmap Sun Apr 10 12:11:35 2005
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright 1999-2004 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.
+-->
+
+<!-- SVN $Id$ -->
+
+<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
+
+  <map:components>
+    <map:generators default="file">
+      <map:generator name="file" src="org.apache.cocoon.generation.FileGenerator"/>
+    </map:generators>
+
+    <map:transformers default="xslt">
+      <map:transformer name="xslt" src="org.apache.cocoon.transformation.TraxTransformer">
+        <xslt-processor-role>xalan</xslt-processor-role>
+      </map:transformer>
+      <map:transformer name="virtual1" src="org.apache.cocoon.transformation.VirtualPipelineTransformer">
+        <map:transform src="vpc-transform.xsl"/>
+      </map:transformer>
+      <map:transformer name="virtual2" src="org.apache.cocoon.transformation.VirtualPipelineTransformer">
+        <map:source param="src2"/>
+        <map:transform src="vpc-include.xsl">
+           <map:parameter name="file" value="{src}"/>
+        </map:transform>
+        <map:transform src="vpc-include.xsl">
+           <map:parameter name="file" value="{src2}"/>
+        </map:transform>
+      </map:transformer>
+    </map:transformers>
+
+    <map:serializers default="xml">
+      <map:serializer mime-type="text/xml" name="xml" src="org.apache.cocoon.serialization.XMLSerializer"/>
+    </map:serializers>
+
+    <map:matchers default="wildcard">
+      <map:matcher name="wildcard" src="org.apache.cocoon.matching.WildcardURIMatcher"/>
+    </map:matchers>
+
+    <map:pipes default="noncaching">
+      <map:pipe name="noncaching" src="org.apache.cocoon.components.pipeline.impl.NonCachingProcessingPipeline">
+      </map:pipe>
+    </map:pipes>
+  </map:components>
+
+  <map:pipelines>
+    <map:pipeline>
+
+      <map:match pattern="v1">
+        <map:generate src="vpc-test.xml"/>
+        <map:transform type="virtual1"/>
+        <map:serialize/>
+      </map:match>
+
+      <map:match pattern="v2">
+        <map:generate src="vpc-test.xml"/>
+        <map:transform type="virtual2" src="vpc-test.xml">
+          <map:parameter name="src2" value="vpc-test2.xml"/>
+        </map:transform>
+        <map:serialize/>
+      </map:match>
+
+    </map:pipeline>
+  </map:pipelines>
+</map:sitemap>

Propchange: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-sitemap.xmap
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test.xml?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test.xml (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test.xml Sun Apr 10 12:11:35 2005
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><test/>
\ No newline at end of file

Propchange: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test2.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test2.xml?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test2.xml (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test2.xml Sun Apr 10 12:11:35 2005
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><test2/>
\ No newline at end of file

Propchange: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-test2.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-transform.xsl
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-transform.xsl?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-transform.xsl (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-transform.xsl Sun Apr 10 12:11:35 2005
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:template match="/test">
+    <test/>
+  </xsl:template>
+
+</xsl:stylesheet>

Propchange: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-transform.xsl
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-v2-expected.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-v2-expected.xml?view=auto&rev=160799
==============================================================================
--- cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-v2-expected.xml (added)
+++ cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-v2-expected.xml Sun Apr 10 12:11:35 2005
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><test><test/><test2/></test>
\ No newline at end of file

Propchange: cocoon/trunk/src/test/org/apache/cocoon/transformation/vpc-v2-expected.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: cocoon/trunk/src/webapp/WEB-INF/xconf/cocoon-core.xconf
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/webapp/WEB-INF/xconf/cocoon-core.xconf?view=diff&r1=160798&r2=160799
==============================================================================
--- cocoon/trunk/src/webapp/WEB-INF/xconf/cocoon-core.xconf (original)
+++ cocoon/trunk/src/webapp/WEB-INF/xconf/cocoon-core.xconf Sun Apr 10 12:11:35 2005
@@ -164,6 +164,7 @@
     <component-instance logger="core.modules.input" name="request"          class="org.apache.cocoon.components.modules.input.RequestModule"/>
     <component-instance logger="core.modules.input" name="baselink"         class="org.apache.cocoon.components.modules.input.BaseLinkModule" />
     <component-instance logger="core.modules.input" name="session"          class="org.apache.cocoon.components.modules.input.SessionModule"/>
+    <component-instance logger="core.modules.input" name="environment-attr" class="org.apache.cocoon.components.modules.input.EnvironmentAttributeModule"/>
     <component-instance logger="core.modules.input" name="request-param"    class="org.apache.cocoon.components.modules.input.RequestParameterModule"/>
     <component-instance logger="core.modules.input" name="raw-request-param" class="org.apache.cocoon.components.modules.input.RawRequestParameterModule"/>
     <component-instance logger="core.modules.input" name="request-attr"     class="org.apache.cocoon.components.modules.input.RequestAttributeModule"/>