Author: danielf Date: Mon Mar 28 13:12:47 2005 New Revision: 159310 URL: http://svn.apache.org/viewcvs?view=rev&rev=159310 Log: VPCs, ongoing work. Source resolving for source params doesn't work yet.
Added: cocoon/trunk/src/java/org/apache/cocoon/components/modules/input/AvalonContextModule.java cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNode.java cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNodeBuilder.java cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCsNodeBuilder.java Modified: cocoon/trunk/src/java/org/apache/cocoon/components/source/impl/ModuleSource.java cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap-language.xml cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsNodeBuilder.java cocoon/trunk/src/java/org/apache/cocoon/generation/VirtualPipelineGenerator.java Added: cocoon/trunk/src/java/org/apache/cocoon/components/modules/input/AvalonContextModule.java URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/modules/input/AvalonContextModule.java?view=auto&rev=159310 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/components/modules/input/AvalonContextModule.java (added) +++ cocoon/trunk/src/java/org/apache/cocoon/components/modules/input/AvalonContextModule.java Mon Mar 28 13:12:47 2005 @@ -0,0 +1,59 @@ +/* + * 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.components.modules.input; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.ContextException; +import org.apache.avalon.framework.context.Contextualizable; + +/** + * AvalonContextModule provides access to the Avalon Context. + * + * @version $Id$ + */ +public class AvalonContextModule implements InputModule, Contextualizable { + + Context context; + + public void contextualize(Context context) throws ContextException { + this.context = context; + } + + public Object getAttribute( String name, Configuration modeConf, Map objectModel ) + throws ConfigurationException { + try { + return this.context.get(name); + } catch (ContextException e) { + throw new ConfigurationException("Couldn't get " + name + " from context", e); + } + } + + public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel) + throws ConfigurationException { + throw new UnsupportedOperationException(); + } + + public Iterator getAttributeNames(Configuration modeConf, Map objectModel) + throws ConfigurationException { + throw new UnsupportedOperationException(); + } +} Modified: cocoon/trunk/src/java/org/apache/cocoon/components/source/impl/ModuleSource.java URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/source/impl/ModuleSource.java?view=diff&r1=159309&r2=159310 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/components/source/impl/ModuleSource.java (original) +++ cocoon/trunk/src/java/org/apache/cocoon/components/source/impl/ModuleSource.java Mon Mar 28 13:12:47 2005 @@ -28,6 +28,7 @@ import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.ServiceSelector; +import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceException; import org.apache.excalibur.source.impl.AbstractSource; @@ -143,6 +144,8 @@ if ( obj instanceof InputStream ) { return (InputStream)obj; + } else if ( obj instanceof Source ) { + return ((Source)obj).getInputStream(); } else if ( obj instanceof String ) { return new ByteArrayInputStream( ((String)obj).getBytes() ); } else if (obj instanceof byte[]) { Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap-language.xml URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap-language.xml?view=diff&r1=159309&r2=159310 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap-language.xml (original) +++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap-language.xml Mon Mar 28 13:12:47 2005 @@ -47,12 +47,16 @@ <node name="components" builder="org.apache.cocoon.components.treeprocessor.sitemap.ComponentsNodeBuilder"/> + <node name="generators" builder="org.apache.cocoon.components.treeprocessor.sitemap.VPCsNodeBuilder"/> + + <node name="generator" builder="org.apache.cocoon.components.treeprocessor.sitemap.VPCNodeBuilder"> + <ignored-children>source</ignored-children> + </node> + <node name="pipelines" builder="org.apache.cocoon.components.treeprocessor.sitemap.PipelinesNodeBuilder"> <allowed-children>pipeline, handle-errors</allowed-children> <ignored-children>component-configurations</ignored-children> </node> - - <node name="components" builder="org.apache.cocoon.components.treeprocessor.sitemap.ComponentsNodeBuilder"/> <node name="flow" builder="org.apache.cocoon.components.treeprocessor.sitemap.FlowNodeBuilder"/> Modified: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsNodeBuilder.java URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsNodeBuilder.java?view=diff&r1=159309&r2=159310 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsNodeBuilder.java (original) +++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/ComponentsNodeBuilder.java Mon Mar 28 13:12:47 2005 @@ -16,15 +16,9 @@ package org.apache.cocoon.components.treeprocessor.sitemap; import org.apache.avalon.framework.configuration.Configuration; -import org.apache.avalon.framework.context.Context; -import org.apache.avalon.framework.context.ContextException; -import org.apache.avalon.framework.context.Contextualizable; -import org.apache.avalon.framework.context.DefaultContext; - -import org.apache.cocoon.Constants; import org.apache.cocoon.components.treeprocessor.AbstractProcessingNodeBuilder; import org.apache.cocoon.components.treeprocessor.ProcessingNode; -import org.apache.cocoon.generation.VirtualPipelineGenerator; +import org.apache.cocoon.components.treeprocessor.ProcessingNodeBuilder; /** * Handles <map:components>. It doesn't actually create a <code>ProcessingNode</code>. @@ -32,14 +26,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a> * @version CVS $Id$ */ -public class ComponentsNodeBuilder extends AbstractProcessingNodeBuilder - implements Contextualizable { - - private DefaultContext context; - - public void contextualize(Context context) throws ContextException { - this.context = (DefaultContext) context; - } +public class ComponentsNodeBuilder extends AbstractProcessingNodeBuilder { /** This builder has no parameters -- return <code>false</code> */ protected boolean hasParameters() { @@ -47,28 +34,13 @@ } public ProcessingNode buildNode(Configuration config) throws Exception { - // Check for component configurations + // Handle the VPCs Configuration child = config.getChild("generators", false); if (child != null) { - Configuration[] generators = child.getChildren("generator"); - for (int i = 0; i < generators.length; i++) { - Configuration generator = generators[i]; - - String clazz = generator.getAttribute("src"); - if (VirtualPipelineGenerator.class.getName().equals(clazz)) { - // Got it - PipelineNodeBuilder builder = new PipelineNodeBuilder(); - builder.setBuilder(this.treeBuilder); - ProcessingNode node = builder.buildNode(generator); - - // Stuff this node into the context of current Sitemap - // so that VirtualPipelineComponent can find it. - String name = generator.getAttribute("name"); - context.put(Constants.CONTEXT_VPC_PREFIX + "generator-" + name, node); - } - } + ProcessingNodeBuilder childBuilder = this.treeBuilder.createNodeBuilder(child); + childBuilder.buildNode(child); } - return null; } } + Added: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNode.java URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNode.java?view=auto&rev=159310 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNode.java (added) +++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNode.java Mon Mar 28 13:12:47 2005 @@ -0,0 +1,40 @@ +/* + * 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.components.treeprocessor.sitemap; + +import java.util.Set; + +import org.apache.cocoon.components.treeprocessor.NamedContainerNode; + +/** + * A VPC node that just invokes its children and store what parameters are sources. + * + * @version $Id$ + */ + +public class VPCNode extends NamedContainerNode { + + Set sourceSet; + + public VPCNode(String name, Set sourceSet) { + super(name); + this.sourceSet = sourceSet; + } + + public Set getSources() { + return this.sourceSet; + } +} Added: cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNodeBuilder.java URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNodeBuilder.java?view=auto&rev=159310 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNodeBuilder.java (added) +++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCNodeBuilder.java Mon Mar 28 13:12:47 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.components.treeprocessor.sitemap; + +import java.util.HashSet; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.ContextException; +import org.apache.avalon.framework.context.Contextualizable; +import org.apache.avalon.framework.context.DefaultContext; +import org.apache.cocoon.Constants; +import org.apache.cocoon.components.treeprocessor.CategoryNodeBuilder; +import org.apache.cocoon.components.treeprocessor.ProcessingNode; +import org.apache.cocoon.components.treeprocessor.LinkedProcessingNodeBuilder; +import org.apache.cocoon.components.treeprocessor.NamedContainerNodeBuilder; +import org.apache.cocoon.components.treeprocessor.ProcessingNode; + +/** + * Handles a virtual sitemap component. + * + * @version $Id$ + */ +public class VPCNodeBuilder extends NamedContainerNodeBuilder + implements Contextualizable, LinkedProcessingNodeBuilder { + + private DefaultContext context; + private String type; + private String name; + + public void contextualize(Context context) throws ContextException { + this.context = (DefaultContext) context; + } + + public ProcessingNode buildNode(Configuration config) throws Exception { + this.type = config.getName(); + this.name = config.getAttribute(this.nameAttr); + + // Find out which parameters that should be handled as sources + // and put the info in the context. + Configuration[] sources = config.getChildren("source"); + HashSet sourceSet = new HashSet(); + for (int j = 0; j < sources.length; j++) + sourceSet.add(sources[j].getAttribute("param")); + + VPCNode node = new VPCNode(this.name, sourceSet); + this.setupNode(node, config); + + return node; + } + + public void linkNode() throws Exception { + // Stuff this node into the context of current Sitemap so that + // VirtualPipelineComponent can find it. + // + // This probably doesn't work if the component is redifined in + // a subsitemap, either the stack functionality in DefaultContext + // should be used for context switches, or this info should + // be put in the current processor instead. + // + // The plural "s" is because the category name is from the + // embeding container and I didn't found a way to get that name. + // But for VPCs we know that a generator is part of the + // category geerators etc. + + ProcessingNode node = + CategoryNodeBuilder.getNamedNode(this.treeBuilder, this.type + "s", this.name); + + this.context.put(Constants.CONTEXT_VPC_PREFIX + this.type + "-" + this.name, node); + } +} Added: 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=auto&rev=159310 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCsNodeBuilder.java (added) +++ cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/VPCsNodeBuilder.java Mon Mar 28 13:12:47 2005 @@ -0,0 +1,46 @@ +/* + * 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.components.treeprocessor.sitemap; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; + +import org.apache.cocoon.components.treeprocessor.CategoryNodeBuilder; +import org.apache.cocoon.generation.VirtualPipelineGenerator; + +/** + * Handles a set of virtual sitemap components. + * + * @version $Id$ + */ +public class VPCsNodeBuilder extends CategoryNodeBuilder { + + /** + * Checks if a child element is a VPC, and if not throws a <code>ConfigurationException</code>. + * + * @param child the child configuration to check. + * @return <code>true</code> if this child should be considered or <code>false</code> + * if it should be ignored. + * @throws ConfigurationException if this child isn't allowed. + */ + protected boolean isChild(Configuration child) throws ConfigurationException { + + checkNamespace(child); + + String clazz = child.getAttribute("src"); + return VirtualPipelineGenerator.class.getName().equals(clazz); + } +} 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=159309&r2=159310 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/generation/VirtualPipelineGenerator.java (original) +++ cocoon/trunk/src/java/org/apache/cocoon/generation/VirtualPipelineGenerator.java Mon Mar 28 13:12:47 2005 @@ -15,12 +15,15 @@ */ package org.apache.cocoon.generation; +import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.context.Context; 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.parameters.Parameters; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; @@ -28,19 +31,28 @@ 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.pipeline.VirtualProcessingPipeline; +import org.apache.cocoon.components.treeprocessor.CategoryNode; import org.apache.cocoon.components.treeprocessor.InvokeContext; import org.apache.cocoon.components.treeprocessor.ProcessingNode; +import org.apache.cocoon.components.treeprocessor.sitemap.VPCNode; import org.apache.cocoon.environment.Environment; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.environment.internal.EnvironmentHelper; import org.apache.cocoon.xml.XMLConsumer; +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceException; +import org.apache.excalibur.xml.sax.XMLizable; import org.xml.sax.SAXException; import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import java.util.Set; /** * TODO List: @@ -51,14 +63,19 @@ * <li>Implement caching * </ul> */ -public class VirtualPipelineGenerator implements Generator, Serviceable, - Contextualizable, Configurable { +public class VirtualPipelineGenerator extends AbstractLogEnabled + implements Generator, Serviceable, Disposable, Contextualizable, Configurable { - private Context context; + private SourceResolver resolver; + private DefaultContext context; private ServiceManager manager; private XMLConsumer consumer; private ProcessingNode node; private ProcessingPipeline pipeline; + private String sourceMapName; + private Map sourceMap = new HashMap(); + private Set sources; + private String name; private class MyInvokeContext extends InvokeContext { @@ -69,19 +86,42 @@ } public void contextualize(Context context) throws ContextException { - this.context = context; + this.context = (DefaultContext)context; } public void service(ServiceManager manager) throws ServiceException { this.manager = manager; } + /** + * Release all resources. + */ + public void dispose() { + try { + Iterator sources = + this.sourceMap.values().iterator(); + while (sources.hasNext()) { + Source source = (Source)sources.next(); + // These are allready disposed, why? + //this.resolver.release(source); + } + } catch (Exception e) { + throw new RuntimeException("Could not dispose sources", e); + } + this.manager = null; + } + public void configure(Configuration configuration) throws ConfigurationException { - String name = configuration.getAttribute("name"); + this.name = configuration.getAttribute("name"); + this.sourceMapName = Constants.CONTEXT_ENV_PREFIX + "-source-map-" + this.name; try { - this.node = (ProcessingNode) this.context.get(Constants.CONTEXT_VPC_PREFIX + "generator-" + name); - } catch (ContextException e) { - throw new ConfigurationException("Can not find VirtualPipelineGenerator '" + name + "' configuration"); + this.node = + (ProcessingNode)this.context.get(Constants.CONTEXT_VPC_PREFIX + + "generator-" + this.name); + this.sources = ((VPCNode)node).getSources(); + } catch (Exception e) { + throw new ConfigurationException("Can not find VirtualPipelineGenerator '" + + this.name + "' configuration"); } } @@ -92,29 +132,115 @@ public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException { + this.resolver = resolver; + + // save callers resolved sources if there are any + Map oldSourceMap = null; + try { + oldSourceMap = (Map)this.context.get(this.sourceMapName); + } catch (ContextException e) { + // This VPC has not been used by the caller + } + // place for resolved sources + this.context.put(this.sourceMapName, this.sourceMap); + Environment env = EnvironmentHelper.getCurrentEnvironment(); String oldPrefix = env.getURIPrefix(); String oldURI = env.getURI(); + MyInvokeContext invoker = null; + try { + // 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_URI); + String prefix = (String) this.context.get(Constants.CONTEXT_ENV_PREFIX); env.setURI(prefix, uri); - MyInvokeContext invoker = new MyInvokeContext(); + invoker = new MyInvokeContext(); + invoker.enableLogging(getLogger()); invoker.service(this.manager); + invoker.pushMap(null, resolvedParams); + this.node.invoke(env, invoker); this.pipeline = invoker.getProcessingPipeline(); } catch (Exception e) { throw new ProcessingException("Oops", e); } finally { + if (invoker != null) { + invoker.popMap(); + invoker.dispose(); + } // Restore context env.setURI(oldPrefix, oldURI); + // restore sourceMap + this.context.put(this.sourceMapName, oldSourceMap); + } + } + + private Map resolveParams(Parameters par, String src) + throws ProcessingException, IOException { + HashMap map = new HashMap(); + + // resolve and map params + Iterator names = par.getParameterNames(); + while (names.hasNext()) { + String name = (String)names.next(); + String value = par.getParameter(name, null); + if (this.sources.contains(name)) + value = resolveAndMapSourceURI(name, value); + map.put(name, value); + } + + // resolve and map src + if (src != null) + map.put("src", resolveAndMapSourceURI("src", src)); + + return map; + } + + private String resolveAndMapSourceURI(String name, String uri) + throws ProcessingException, IOException { + + // Resolve the URI + getLogger().debug("VPCGenerator: resolve " + name + " = " + uri); + Source src = null; + try { + src = this.resolver.resolveURI(uri); + } catch (SourceException se) { + throw SourceUtil.handle("Error during resolving of " + uri, se); } + + getLogger().debug("VPCGenerator: URI " + name + " = " + src.getURI()); + + // Save the source + this.sourceMap.put(name, src); + + // Create a new URI that refers to the source in the context + String mappedURI; + if (src instanceof XMLizable) + mappedURI = "xmodule:avalon-context:" + this.sourceMapName + "#" + name; + else + mappedURI = "module:avalon-context:" + this.sourceMapName + "#" + name; + + getLogger().debug("VPCGenerator: mapped URI " + name + " = " + mappedURI); + + return mappedURI; } public void generate() throws IOException, SAXException, ProcessingException { + // save callers resolved sources if there are any + Map oldSourceMap = null; + try { + oldSourceMap = (Map)this.context.get(this.sourceMapName); + } catch (ContextException e) { + // This VPC has not been used by the caller + } + // place for resolved sources + this.context.put(this.sourceMapName, this.sourceMap); + // Should use SourceResolver of the this components' sitemap, not caller sitemap // Have to switch to another environment... Environment env = EnvironmentHelper.getCurrentEnvironment(); @@ -122,7 +248,7 @@ String oldURI = env.getURI(); try { String uri = (String) this.context.get(Constants.CONTEXT_ENV_URI); - String prefix = (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); @@ -134,5 +260,8 @@ } this.pipeline.process(env, this.consumer); + + // restore sourceMap + this.context.put(this.sourceMapName, oldSourceMap); } }