You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2001/11/08 15:39:24 UTC
cvs commit: xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap ActionNode.java ComponentsNodeBuilder.java GeneratorNode.java GeneratorNodeBuilder.java PipelineNode.java SitemapNode.java SitemapNodeBuilder.java
sylvain 01/11/08 06:39:24
Added: scratchpad/src/org/apache/cocoon treeprocessor.txt
scratchpad/src/org/apache/cocoon/treeprocessor
AbstractParentProcessingNode.java
AbstractParentProcessingNodeBuilder.java
AbstractProcessingNode.java
AbstractProcessingNodeBuilder.java
EnvironmentSourceResolver.java
ListOfMapsResolver.java ProcessingNode.java
ProcessingNodeBuilder.java TreeBuilder.java
TreeBuilderComponentManager.java TreeProcessor.java
treeprocessor.xconf
scratchpad/src/org/apache/cocoon/treeprocessor/sitemap
ActionNode.java ComponentsNodeBuilder.java
GeneratorNode.java GeneratorNodeBuilder.java
PipelineNode.java SitemapNode.java
SitemapNodeBuilder.java
Log:
Scratchpad for the new TreeProcessor, for Ovidiu to look at !
Revision Changes Path
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor.txt
Index: treeprocessor.txt
===================================================================
The treeprocessor package is the reimplementation of the sitemap as a tree traversal engine.
This is the current snapshot from my hard disk, as asked by Ovidiu who wanted to look at it. It is compilable, but not finished, so don't ask why it doesn't work :)
Any suggestions are welcome.
Sylvain Wallez
sylvain@apache.org
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractParentProcessingNode.java
Index: AbstractParentProcessingNode.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import java.util.List;
import java.util.Map;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public abstract class AbstractParentProcessingNode extends AbstractProcessingNode {
protected ProcessingNode[] childNodes;
/**
* Invoke in order all children, until one fails.
*
* @parameter currentMap the <code>Map<code> of parameters produced by this node,
* which is added to <code>listOfMap</code> if not null.
*/
protected boolean invokeChildren (
Environment env,
StreamPipeline pipeline,
EventPipeline eventPipeline,
List listOfMaps, Map currentMap)
throws Exception {
if (currentMap != null) {
listOfMaps.add(currentMap);
}
boolean success = true;
for (int i = 0; i < childNodes.length; i++) {
if (! childNodes[i].invoke(env, pipeline, eventPipeline, listOfMaps)) {
success = false;
break;
}
}
if (currentMap != null) {
listOfMaps.remove(listOfMaps.size() - 1);
}
return success;
}
/**
* Disposes all children of this node.
*/
protected void disposeChildren() {
for (int i = 0; i < childNodes.length; i++) {
childNodes[i].dispose();
}
}
/**
* Dispose this node. At this level, simply call <code>disposeChildren()</code>.
*/
public void dispose() {
disposeChildren();
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractParentProcessingNodeBuilder.java
Index: AbstractParentProcessingNodeBuilder.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.logger.AbstractLoggable;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public abstract class AbstractParentProcessingNodeBuilder extends AbstractProcessingNodeBuilder {
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractProcessingNode.java
Index: AbstractProcessingNode.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public abstract class AbstractProcessingNode extends AbstractLoggable implements ProcessingNode {
/** The node parameters, as a <code>Map</code> of <code>ListOfMapsResolver</code>. */
protected Map parameters;
protected SourceResolver getSourceResolver(Map objectModel) {
return (SourceResolver)objectModel.get(OBJECT_SOURCE_RESOLVER);
}
protected Redirector getRedirector(Map objectModel) {
return (Redirector)objectModel.get(OBJECT_REDIRECTOR);
}
/**
* By default, do nothing. Subclasses can redefine it when needed.
*/
public void dispose() {
// Nothing
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/AbstractProcessingNodeBuilder.java
Index: AbstractProcessingNodeBuilder.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.logger.AbstractLoggable;
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.component.Composable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.cocoon.sitemap.PatternException;
import java.util.Map;
import java.util.HashMap;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public abstract class AbstractProcessingNodeBuilder extends AbstractLoggable
implements ProcessingNodeBuilder {
protected TreeBuilder builder;
public void setBuilder(TreeBuilder builder) {
this.builder = builder;
}
/**
* Get <xxx:parameter> elements as a <ocd>Map</code> of </code>ListOfMapResolver</code>s,
* that can be turned into parameters using <code>ListOfMapResolver.buildParameters()</code>.
*
* @return the Map of ListOfMapResolver, or <code>null</code> if there are no parameters.
*/
protected Map getParameters(Configuration config) throws ConfigurationException {
Configuration[] children = config.getChildren("parameter");
if (children.length == 0) {
return null;
}
Map params = new HashMap();
for (int i = 0; i < children.length; i++) {
Configuration child = children[i];
if (true) { // FIXME : check namespace
String value = child.getAttribute("value");
try {
params.put(child.getAttribute("name"), ListOfMapsResolver.getResolver(value));
} catch(PatternException pe) {
throw new ConfigurationException("Invalid pattern '" + value +
", at " + child.getLocation());
}
}
}
return params;
}
/**
* Check if the namespace URI of the given configuraition is the same as the
* one given by the builder.
*/
protected void checkNamespace(Configuration config) throws ConfigurationException {
// FIXME : check namespace of config (need new Avalon)
if (false) //!builder.getNamespace().equals(config.getNamespace().getURI())
{
throw new ConfigurationException("Invalid namespace, at " + config.getLocation());
}
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/EnvironmentSourceResolver.java
Index: EnvironmentSourceResolver.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.cocoon.components.source.SourceHandler;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.Source;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.ProcessingException;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.net.URL;
/**
* A <code>SourceResolver</code> that resolves URIs relative to an <code>Environment</code>.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public class EnvironmentSourceResolver implements SourceResolver, Disposable {
private ComponentManager manager;
private Source contextSource;
private SourceHandler sourceHandler;
public EnvironmentSourceResolver(ComponentManager manager, Environment env) throws Exception {
this.manager = manager;
this.contextSource = env.resolve("");
this.sourceHandler = (SourceHandler)manager.lookup(SourceHandler.ROLE);
}
/**
* Resolve an entity.
*/
public Source resolve(String systemId) throws ProcessingException, SAXException, IOException {
if (systemId == null) throw new SAXException("Invalid System ID");
URL context = new URL(this.contextSource.getSystemId());
if (systemId.length() == 0)
return this.sourceHandler.getSource(null, context, systemId);
if (systemId.indexOf(":") > 1)
return this.sourceHandler.getSource(null, systemId);
if (systemId.charAt(0) == '/')
return this.sourceHandler.getSource(null, context.getProtocol() + ":" + systemId);
return this.sourceHandler.getSource(null, context, systemId);
}
public void dispose() {
if (contextSource != null)
{
contextSource.recycle();
}
manager.release(sourceHandler);
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ListOfMapsResolver.java
Index: ListOfMapsResolver.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.sitemap.PatternException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Utility class for handling {...} pattern substitutions from a List of Maps.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public abstract class ListOfMapsResolver extends AbstractLoggable {
/**
* An empty <code>Parameters</code> object, returned by <code>buildParameters()</code>
* if it is given a <code>null</code> Map.
*/
public static final Parameters EMPTY_PARAMETERS;
static {
EMPTY_PARAMETERS = new Parameters();
EMPTY_PARAMETERS.makeReadOnly();
}
/**
* Resolve all {...} patterns using the values given in the list of maps.
*/
public abstract String resolve(List listOfMaps) throws PatternException;
/**
* Does an expression need resolving (i.e. contain {...} patterns) ?
*/
public static boolean needsResolve(String expression) {
if (expression == null || expression.length() == 0) {
return false;
}
// Is the first char a '{' ?
if (expression.charAt(0) == '{') {
return true;
}
if (expression.length() < 2) {
return false;
}
// Is there any unescaped '{' ?
int pos = 1;
while ( (pos = expression.indexOf('{', pos)) != -1) {
// Found a '{' : is it escaped ?
if (expression.charAt(pos - 1) != '\\') {
// No : need to resolve
return true;
}
pos++;
}
// Nothing found...
return false;
}
/**
* Unescape an expression that doesn't need to be resolved, but may contain
* escaped '{' characters.
*
* @param expression the expression to unescape.
* @return the unescaped result, or <code>expression</code> if unescaping isn't necessary.
*/
public static String unescape(String expression) {
// Does it need escaping ?
if (expression == null || expression.indexOf("\\{") == -1) {
return expression;
}
StringBuffer buf = new StringBuffer();
for (int i = 0; i < expression.length(); i++) {
char ch = expression.charAt(i);
if (ch != '\\' || i >= (expression.length() - 1) || expression.charAt(i+1) != '{') {
buf.append(ch);
}
}
return buf.toString();
}
/**
* Get a resolver for a given expression. Chooses the most efficient implementation
* depending on <code>expression</code>.
*/
public static ListOfMapsResolver getResolver(String expression) throws PatternException {
if (needsResolve(expression)) {
return new RealResolver(expression);
} else {
return new NullResolver(expression);
}
}
/**
* Build a <code>Parameters</code> object from a Map of named <code>ListOfMapResolver</code>s and
* a list of Maps used for resolution.
*
* @return a fully resolved <code>Parameters</code>.
*/
public static Parameters buildParameters(Map expressions, List listOfMaps) throws PatternException {
if (expressions == null || expressions.size() == 0) {
return EMPTY_PARAMETERS;
}
Parameters result = new Parameters();
Iterator iter = expressions.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
String value = ((ListOfMapsResolver)entry.getValue()).resolve(listOfMaps);
result.setParameter((String)entry.getKey(), value);
}
return result;
}
//-------------------------------------------------------------------------
/**
* No-op resolver for expressions that don't need to be resolved.
*/
private static class NullResolver extends ListOfMapsResolver {
private String expression;
public NullResolver(String expression) {
this.expression = this.unescape(expression);
}
public String resolve(List listOfMaps) {
return this.expression;
}
}
//-------------------------------------------------------------------------
/**
* Real resolver for expressions containing {..} patterns
*/
// TODO : for now, just borrowed from AbstractSitemap, but the
// pattern should be precompiled for faster substitution.
private static class RealResolver extends ListOfMapsResolver {
private String expression;
public RealResolver(String expression) throws PatternException {
this.expression = expression;
}
public String resolve(List listOfMaps) throws PatternException {
if (expression == null) {
return null;
}
StringBuffer result = new StringBuffer();
String s = null;
int j = 0;
int k = 0;
int l = 0;
int m = 0;
int ii = 0;
int i = -1;
try {
while (ii <= expression.length() && (i = expression.indexOf('{', ii)) != -1) {
result.append(expression.substring(ii, i));
j = expression.indexOf('}', i);
if (j < i) {
throw new PatternException("invalid expression in \"" + expression + "\"");
}
ii = j + 1;
k = listOfMaps.size() - 1;
s = expression.substring(i + 1, j);
l = -3;
m = -1;
while ((l = s.indexOf("../", l + 3)) != -1) {
k--;
m = l;
}
if (m != -1) {
s = s.substring(m + 3);
}
Object value = ((Map)listOfMaps.get(k)).get(s);
if (value != null){
result.append(value.toString());
getLogger().debug("Substitute evaluated value for " + s + " as " + value);
}else{
getLogger().warn("Substitute: value not found for " + s + " while evaluating " + expression);
}
}
if (ii < expression.length()) {
result.append(expression.substring(ii));
}
return (result.toString());
} catch (Exception e) {
getLogger().error("AbstractSitemap:substitute()", e);
throw new PatternException("error occurred during evaluation of expression \"" + expression + "\" at position " +
(i + 1) + "\n" + e.getMessage());
}
}
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ProcessingNode.java
Index: ProcessingNode.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import java.util.List;
import org.apache.avalon.framework.activity.Disposable;
/**
*
* Note : this interface extends <code>Disposable</code> to ensure that resources
* held at any level in the hierarchy can be disposed by calling <code>dispose()</code>
* on the root node.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public interface ProcessingNode extends ThreadSafe, Disposable {
/**
* The key of the <code>SourceResolver</code> in the object model.
*/
public static String OBJECT_SOURCE_RESOLVER = "source-resolver";
/**
* Process environment.
*/
boolean invoke(
Environment env,
StreamPipeline pipeline,
EventPipeline eventPipeline,
List listOfMaps
) throws Exception;
/**
* Dispose recursively any resources held.
*/
void dispose();
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/ProcessingNodeBuilder.java
Index: ProcessingNodeBuilder.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
/**
* A <code>ProcessingNode</code> builder.
* <p>
* The lifecycle of <code>ProcessingNodeBuilder</code>s is as follows :
* <ul>
* <li>{@link #setBuilder(Map)} is called after all Avalon lifecycle methods.
* </li>
* <li>{@link #buildNode(Configuration, Map)} is called for every node builder in the hierarchy.<br>
* This is where <code>ProcessingNodes</code> that should be made public to other
* <code>ProcessingNodeBuilder</code>s (such as sitemap resources) should be
* exported using <code>Builder.addNode()</code>..
* </li>
* <li>then {@link #getNode(Map)} is called for every node builder in the hierarchy.<br>
* This is where node builders can resolve references to other public nodes
* that have been registered during the <code>buildNode()</code> phase.
* </ul>
* The <code>buildModel</code> parameter passed to <code>buildNode()</code> contains
* additional information placed here by the ancestor <code>ProcessingNodeBuilder</code>s.
* The information added to or read from <code>buildModel</code> should be described in relevant
* implementations.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
import java.util.Map;
public interface ProcessingNodeBuilder extends Component {
/**
* Set the builder for which we are building.
*/
void setBuilder(TreeBuilder builder);
/**
* Build the {@link ProcessingNode} from the given <code>Configuration</code>,
* and register it in the {@link Builder} if needed.
*/
void buildNode(Configuration config, Map buildModel) throws Exception;
/**
* Get the ProcessingNode, ready for use. Can be <code>null</code> for builders
* that just set up the environment, such as <code>ComponentsNodeBuilder</code>.
*/
ProcessingNode getNode() throws Exception;
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeBuilder.java
Index: TreeBuilder.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.excalibur.component.DefaultRoleManager;
import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
import org.apache.avalon.excalibur.logger.LogKitManageable;
import org.apache.avalon.excalibur.logger.LogKitManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.cocoon.util.ClassUtils;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public class TreeBuilder extends AbstractLoggable implements
Composable, Configurable, Contextualizable, LogKitManageable {
/**
* The role name to be used by composable <code>ProcessingNodeBuilder</code>s to get
* the <code>Builder</code> for which they operate.
*/
public static final String ROLE = "org.apache.cocoon.components.treeprocessor.Builder";
/**
* The categories of node Maps.
*/
private Map categories = new HashMap();
/**
* The tree processor that we're building.
*/
private TreeProcessor processor;
private Context context;
private LogKitManager logKit;
private ComponentManager parentManager;
private TreeBuilderComponentManager manager;
private ExcaliburComponentSelector builderSelector;
private DefaultRoleManager emptyRoleManager;
private String namespace;
private String languageName;
private boolean canGetNode = false;
public void contextualize(Context context) throws ContextException {
this.context = context;
}
public void setLogKitManager(LogKitManager logKit) {
this.logKit = logKit;
}
public void compose(ComponentManager manager) throws ComponentException {
this.parentManager = manager;
// Setup role manager for the component manager
// FIXME : what roles should we put here ? Pipelines and Connector roles from sitemap.roles ?
this.emptyRoleManager = new DefaultRoleManager();
this.emptyRoleManager.setLogger(getLogger());
try {
this.emptyRoleManager.configure(new DefaultConfiguration("role-list", "-"));
} catch(ConfigurationException ce) {
throw new ComponentException("Cannot configure Builder role manager", ce);
}
// Create the new component manager
this.manager = new TreeBuilderComponentManager(this.parentManager);
this.manager.setLogger(getLogger());
this.manager.contextualize(this.context);
this.manager.setRoleManager(this.emptyRoleManager);
this.manager.setLogKitManager(this.logKit);
// this.manager.configure( - no configuration - );
// initialize() is called later. In the meanwhile, only parent components will be visible.
}
public void configure(Configuration config) throws ConfigurationException {
this.languageName = config.getAttribute("name");
getLogger().debug("Configuring Builder for language : " + this.languageName);
this.namespace = config.getAttribute("namespace");
try {
// Create the NodeBuilder selector.
ExcaliburComponentSelector selector = new ExcaliburComponentSelector();
selector.setLogger(getLogger());
selector.contextualize(this.context);
selector.setRoleManager(this.emptyRoleManager);
selector.setLogKitManager(logKit);
selector.compose(this.manager);
//selector.configure(new DefaultConfiguration("node-builders","-"));
this.builderSelector = selector;
// Add components in the selector for all nodes in the configuration
Configuration nodesConfig = config.getChild("nodes", false);
if (nodesConfig == null) {
throw new ConfigurationException("Missing 'nodes' element, at " + config.getLocation());
}
Configuration[] nodes = nodesConfig.getChildren("node");
for (int i = 0; i < nodes.length; i++) {
Configuration node = nodes[i];
String name = node.getAttribute("name");
String className = node.getAttribute("builder");
Class clazz;
try {
clazz = ClassUtils.loadClass(className);
} catch(Exception e) {
throw new ConfigurationException("Cannot load class '" + className +
"', at " + node.getLocation());
}
if (! ProcessingNodeBuilder.class.isAssignableFrom(clazz)) {
throw new ConfigurationException("Class '" + className +
"' does not implement ProcessingNodeBuilder, at " + node.getLocation());
}
// Add it to the builder selector
getLogger().debug("Adding ProcessingNodeBuilder '" + name + "' : class = " + className);
selector.addComponent(name, clazz, node);
}
selector.initialize();
} catch(ComponentException ce) {
throw new ConfigurationException("Cannot setup selector for node builders", ce);
}
}
public void setProcessor(TreeProcessor processor) {
this.processor = processor;
}
public TreeProcessor getProcessor() {
return this.processor;
}
/**
* Returns the language that is being built (e.g. "sitemap").
*/
public String getLanguage() {
return this.languageName;
}
/**
* Register a named <code>ProcessingNode</code> in a given category.
* For example, <code>ResourceNodeBuilder</code> stores here the <code>ProcessingNode</code>
* it produces for use by sitemap pipelines. This allows to turn the tree into a graph.
*/
public void addNode(ProcessingNode node, String category, String name) {
Map nodes = (Map)categories.get(category);
if (nodes == null) {
nodes = new HashMap();
categories.put(category, nodes);
}
nodes.put(name, node);
}
public ProcessingNode getNode(String category, String name) {
if (this.canGetNode)
{
Map nodes = (Map)categories.get(category);
if (nodes == null) {
return null;
} else {
return (ProcessingNode)nodes.get(name);
}
} else {
throw new IllegalArgumentException("Cannot call getNode() now, but during buildNode()");
}
}
/**
* Some NodeBuilders create components to be used by others
*/
public void addComponent(String role, Class component, Configuration configuration)
throws ComponentException {
this.manager.addComponent(role, component, configuration);
}
public void addComponentInstance(String role, Component instance) {
this.manager.addComponentInstance(role, instance);
}
public ProcessingNodeBuilder createNodeBuilder(Configuration config) throws Exception {
//FIXME : check namespace
String nodeName = config.getName();
int pos;
if ((pos = nodeName.indexOf(':')) != -1)
nodeName = nodeName.substring(pos+1);
ProcessingNodeBuilder builder = (ProcessingNodeBuilder)this.builderSelector.select(nodeName);
builder.setBuilder(this);
return builder;
}
/**
* Get the namespace URI that builders should use to find their nodes.
*/
public String getNamespace() {
return this.namespace;
}
/**
* Build a processing tree from a <code>Configuration</code>.
*/
public ProcessingNode build(Configuration config) throws Exception {
// Create a node builder from the top-level element
ProcessingNodeBuilder rootBuilder = createNodeBuilder(config);
// Build the whole tree (with an empty buildModel)
rootBuilder.buildNode(config, new HashMap());
// Expose newly added components
this.manager.initialize();
// Calls to getNode() are now allowed
this.canGetNode = true;
// And get the tree
return rootBuilder.getNode();
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeBuilderComponentManager.java
Index: TreeBuilderComponentManager.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
/**
* An <code>ExcaliburComponentManager</code> which directs all calls to
* <code>ComponentManager</code> methods to its parent while it isn't
* initialized.
* <p>
* This allows to give <code>ProcessingNodesBuilder</code>s a component manager
* they can use to lookup parent-defined components while also allowing it to be
* enriched through <code>Builder.addComponent()</code>.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public class TreeBuilderComponentManager extends ExcaliburComponentManager {
private ComponentManager parent;
private boolean initialized = false;
public TreeBuilderComponentManager(ComponentManager parent) {
super(parent);
this.parent = parent;
}
public Component lookup(String role) throws ComponentException {
if (initialized) {
return super.lookup(role);
} else {
return parent.lookup(role);
}
}
/**
* Check to see if a <code>Component</code> exists for a role.
*
* @param role a string identifying the role to check.
* @return True if the component exists, False if it does not.
*/
public boolean hasComponent(String role) {
if (initialized) {
return super.hasComponent(role);
} else {
return parent.hasComponent(role);
}
}
/**
* Return the <code>Component</code> when you are finished with it. This
* allows the <code>ComponentManager</code> to handle the End-Of-Life Lifecycle
* events associated with the Component. Please note, that no Exceptions
* should be thrown at this point. This is to allow easy use of the
* ComponentManager system without having to trap Exceptions on a release.
*
* @param component The Component we are releasing.
*/
public void release(Component component) {
if (initialized) {
super.release(component);
} else {
parent.release(component);
}
}
public void initialize() {
super.initialize();
initialized = true;
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/TreeProcessor.java
Index: TreeProcessor.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor;
import org.apache.avalon.excalibur.logger.LogKitManageable;
import org.apache.avalon.excalibur.logger.LogKitManager;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.ComponentSelector;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
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.logger.AbstractLoggable;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.Processor;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import org.apache.cocoon.components.source.URLSource;
import org.apache.cocoon.components.url.URLFactory;
import org.apache.cocoon.components.source.SourceHandler;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.Source;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* Interpreted tree-traversal implementation of the a Processor language.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
*/
public class TreeProcessor extends AbstractLoggable implements ThreadSafe, Processor,
Composable, Configurable, LogKitManageable, Initializable, Contextualizable {
private static final String XCONF_URL = "resource://org/apache/cocoon/treeprocessor/treeprocessor.xconf";
/** The parent TreeProcessor, if any */
protected TreeProcessor parent;
/** The context */
protected Context context;
/** The component manager */
protected ComponentManager manager;
/** The logkit manager to get Loggers */
protected LogKitManager logKit;
/** The language used by this processor */
protected String language;
/** The configuration for each language */
protected Map languageConfigs;
/** The root node of the processing tree */
protected ProcessingNode rootNode;
/** Last modification time */
protected long lastModified = 0;
/** The relative file name of the tree definition */
protected String sourceName;
/** The current language configuration */
protected Configuration currentLanguage;
/** Build the root TreeProcessor */
public TreeProcessor() {
// Language can be overriden in the configuration.
this(null, "sitemap");
}
/** Build a child processor for the same language as its parent */
public TreeProcessor(TreeProcessor parent) {
this(parent, parent.language);
}
/** Build a child processor for a given language */
public TreeProcessor(TreeProcessor parent, String language) {
this.parent = parent;
this.language = language;
}
public void contextualize(Context context) throws ContextException {
this.context = context;
}
public void compose(ComponentManager manager) throws ComponentException {
this.manager = manager;
}
public void setLogKitManager(LogKitManager logKit) {
this.logKit = logKit;
}
/*
<processor>
<root-language name="sitemap"/>
<language>...</language>
</processor>
*/
public void configure(Configuration config) throws ConfigurationException {
if (this.parent != null) {
// Configuration is inherited from parent
getLogger().info("Child TreeProcessor ignores call to configure()");
return;
}
Configuration rootLangConfig = config.getChild("root-language", false);
if (rootLangConfig != null) {
this.language = rootLangConfig.getAttribute("name");
}
// Read the builtin languages definition file
Configuration builtin;
try {
URLFactory factory = (URLFactory)this.manager.lookup(URLFactory.ROLE);
URLSource source = new URLSource(factory.getURL(XCONF_URL), this.manager);
try {
SAXConfigurationHandler handler = new SAXConfigurationHandler();
source.toSAX(handler);
builtin = handler.getConfiguration();
} finally {
this.manager.release((Component)factory);
if (source != null) {
source.recycle();
}
}
} catch(Exception e) {
String msg = "Error while reading treeprocessor.xconf : " + e.getMessage();
getLogger().error(msg, e);
throw new ConfigurationException(msg, e);
}
this.languageConfigs = new HashMap();
// Add builtin languages
addLanguages("builtin", builtin.getChildren("language"));
// Add additional languages from the configuration
addLanguages("additional", config.getChildren("language"));
}
private void addLanguages(String type, Configuration[] languages)
throws ConfigurationException {
for (int i = 0; i < languages.length; i++) {
String name = languages[i].getAttribute("name");
if (this.languageConfigs.containsKey(name)) {
getLogger().info("Redefining language '" + name + "' in " + type + " configuration.");
} else {
getLogger().debug("Adding " + type + " language '" + name + "'");
}
this.languageConfigs.put(name, languages[i]);
}
}
public void initialize() throws Exception {
if (this.parent != null) {
// Copy parent configuration
this.languageConfigs = this.parent.languageConfigs;
}
this.currentLanguage = (Configuration)this.languageConfigs.get(this.language);
if (this.currentLanguage == null) {
throw new ConfigurationException("No configuration defined for language '" + this.language + "'");
}
Configuration fileConfig = this.currentLanguage.getChild("file", false);
if (fileConfig == null) {
throw new ConfigurationException("Missing 'file' configuration for language '" +
this.language + "', at " + this.currentLanguage.getLocation());
}
this.sourceName = fileConfig.getAttribute("name");
}
public boolean process(Environment environment) throws Exception {
return process(environment, null, null);
}
public boolean process(Environment environment, StreamPipeline pipeline, EventPipeline eventPipeline) throws Exception {
SourceHandler oldSourceHandler = environment.getSourceHandler();
SourceHandler sourceHandler = (SourceHandler)this.manager.lookup(SourceHandler.ROLE);
try {
environment.setSourceHandler(sourceHandler);
setupRootNode(environment);
return this.rootNode.invoke(environment, pipeline, eventPipeline, new ArrayList());
} finally {
environment.setSourceHandler(oldSourceHandler);
}
}
protected void setupRootNode(Environment env) throws Exception {
Source source = env.resolve(this.sourceName);
if (this.rootNode != null && source.getLastModified() <= this.lastModified) {
// Nothing changed
source.recycle();
return;
}
// Read the tree definition file as a Configuration
Configuration treeConfig;
try {
getLogger().debug("Building " + this.language + " from " + source.getSystemId());
SAXConfigurationHandler handler = new SAXConfigurationHandler();
source.toSAX(handler);
treeConfig = handler.getConfiguration();
} finally {
source.recycle();
}
// Dispose the current tree, if any
if (this.rootNode != null) {
this.rootNode.dispose();
}
TreeBuilder builder = new TreeBuilder();
builder.setLogger(getLogger());
builder.contextualize(this.context);
// builder.setRoleManager( - none - );
builder.setLogKitManager(this.logKit);
builder.compose(this.manager);
builder.configure(this.currentLanguage);
//builder.initialize();
this.rootNode = builder.build(treeConfig);
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/treeprocessor.xconf
Index: treeprocessor.xconf
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!--
*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************
@author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
@version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:23 $
-->
<tree-processor>
<!-- The sitemap language -->
<language name="sitemap" namespace="http://apache.org/cocoon/sitemap/1.0">
<!-- Should we allow to specify the builder class ? -->
<!-- builder class="org.apache.cocoon.treeprocessor.Builder"/ -->
<!-- The file name for this language -->
<file name="sitemap.xmap"/>
<nodes>
<!-- Sitemap root node -->
<node name="sitemap" builder="org.apache.cocoon.treeprocessor.sitemap.SitemapNodeBuilder">
<allowed-children>components, pipeline, views, resources, action-sets</allowed-children>
</node>
<!-- Components definition : fills selectors on the TreeProcessor -->
<node name="components" builder="org.apache.cocoon.treeprocessor.sitemap.ComponentsNodeBuilder">
<selector section="matchers" elements="matcher"
role="org.apache.cocoon.matching.MatcherSelector"/>
<selector section="selectors" elements="selector"
role="org.apache.cocoon.selection.SelectorSelector"/>
<selector section="actions" elements="action"
role="org.apache.cocoon.acting.ActionSelector"/>
<selector section="generators" elements="generator"
role="org.apache.cocoon.generation.GeneratorSelector"/>
<selector section="transformers" elements="transformer"
role="org.apache.cocoon.transformation.TransformerSelector"/>
<selector section="serializers" elements="serializer"
role="org.apache.cocoon.serialization.SerializerSelector"/>
<selector section="readers" elements="reader"
role="org.apache.cocoon.reading.ReaderSelector"/>
</node>
<!--node name="action" builder="org.apache.cocoon.treeprocessor.sitemap.ActionNodeBuilder">
<forbidden-children>sitemap, components, pipeline, error-handler</forbidden-children>
</node-->
<node name="generator" builder="org.apache.cocoon.treeprocessor.sitemap.GeneratorNodeBuilder"/>
</nodes>
</language>
</tree-processor>
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/ActionNode.java
Index: ActionNode.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor.sitemap;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentSelector;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.acting.Action;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import org.apache.cocoon.sitemap.PatternException;
import org.apache.cocoon.treeprocessor.AbstractParentProcessingNode;
import org.apache.cocoon.treeprocessor.ListOfMapsResolver;
import java.util.List;
import java.util.Map;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $
*/
public class ActionNode extends AbstractParentProcessingNode {
/** The action name */
protected String name;
/** The 'src' attribute */
protected ListOfMapsResolver source;
/** Selector where to get Actions from */
protected ComponentSelector selector;
/** Pre-selected action, if it's ThreadSafe */
protected Action threadSafeAction;
public ActionNode(String name, String source) throws PatternException {
this.name = name;
this.source = ListOfMapsResolver.getResolver(source);
}
public void setSelector(ComponentSelector selector) throws ComponentException {
this.selector = selector;
// Is it a ThreadSafe action ?
Action action = (Action)selector.select(name);
if (action instanceof ThreadSafe) {
// Yes : keep it.
this.threadSafeAction = action;
} else {
this.threadSafeAction = null;
selector.release(action);
}
}
public boolean invoke(Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps)
throws Exception {
// Extract required data from the object model
Map objectModel = env.getObjectModel();
// Execute the action
Action action = this.threadSafeAction;
if (action == null) {
action = (Action)this.selector.select(this.name);
}
Map actionResult;
try {
actionResult = action.act(
getRedirector(objectModel),
getSourceResolver(objectModel),
objectModel,
source.resolve(listOfMaps),
ListOfMapsResolver.buildParameters(this.parameters, listOfMaps)
);
} finally {
if (this.threadSafeAction == null) {
this.selector.release(action);
}
}
if (actionResult == null) {
// Action failed
return false;
} else {
// Action succeeded : process children
return this.invokeChildren(env, pipeline, eventPipeline, listOfMaps, actionResult);
}
}
public void dispose() {
super.dispose();
if (this.threadSafeAction != null) {
this.selector.release(this.threadSafeAction);
}
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/ComponentsNodeBuilder.java
Index: ComponentsNodeBuilder.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor.sitemap;
import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
import org.apache.avalon.excalibur.component.DefaultRoleManager;
import org.apache.avalon.excalibur.logger.LogKitManager;
import org.apache.avalon.excalibur.logger.LogKitManageable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
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.configuration.DefaultConfiguration;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.ComponentSelector;
import org.apache.cocoon.treeprocessor.AbstractProcessingNodeBuilder;
import org.apache.cocoon.treeprocessor.ProcessingNode;
import org.apache.cocoon.util.ClassUtils;
import java.util.Map;
import java.util.HashMap;
/**
* Handles <map:components>. It doesn't actually create a <code>ProcessingNode</code>,
* but creates <code>ComponentSelectors</code> that are made available to other nodes.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $
*/
public class ComponentsNodeBuilder extends AbstractProcessingNodeBuilder implements
Composable, Configurable, Contextualizable, LogKitManageable {
/** The hint name to use to select the default component in a selector */
public static final String DEFAULT_HINT = "!default!";
private Context context;
private LogKitManager logKit;
private ComponentManager parentManager;
protected ComponentManager manager;
/** Association of element names to section names */
protected Map sectionElements = new HashMap();
/** Association of role names to section names */
protected Map sectionRoles = new HashMap();
public void contextualize(Context context) {
this.context = context;
}
public void setLogKitManager(LogKitManager logKit) {
this.logKit = logKit;
}
public void compose(ComponentManager manager) throws ComponentException {
this.manager = manager;
}
public void configure(Configuration config) throws ConfigurationException {
// Iterate on all "section" children
Configuration[] sectionsConfig = config.getChildren("selector");
for (int i = 0; i < sectionsConfig.length; i++) {
Configuration sectionConfig = sectionsConfig[i];
// "section" : name of the section
String name = sectionConfig.getAttribute("section");
// "elements" : name of elements in the section
sectionElements.put(name, sectionConfig.getAttribute("elements"));
// "role" : role of the Selector in the component manager
sectionRoles.put(name, sectionConfig.getAttribute("role"));
}
}
/**
* Build a <code>ComponentSelector</code> for each component section and add it
* each component contained in the section. Selectors are also published on the
* <code>TreeBuilder</code> for use by other nodes.
*/
public void buildNode(Configuration config, Map buildModel) throws Exception {
// Iterate on all sections
Configuration[] sections = config.getChildren();
for (int i = 0; i < sections.length; i++) {
Configuration section = sections[i];
checkNamespace(section);
String sectionName = section.getName();
// Is it a known section ?
String elementName = (String)this.sectionElements.get(sectionName);
if (elementName == null) {
// Unknown section
throw new ConfigurationException("Unknown section named '" + sectionName +
"', at " + section.getLocation());
}
// default component
String defaultElement = section.getAttribute("default", null);
if (defaultElement == null) {
getLogger().debug("Component section '" + sectionName + "' has no default");
}
// Create the selector for this section
getLogger().debug("Creating component selector for " + sectionName);
// Prepare an empty role manager
DefaultRoleManager emptyRoleManager = new DefaultRoleManager();
emptyRoleManager.setLogger(getLogger());
try {
emptyRoleManager.configure(new DefaultConfiguration("role-list", "-"));
} catch(ConfigurationException ce) {
throw new ComponentException("Cannot configure role manager", ce);
}
ExcaliburComponentSelector selector = new ExcaliburComponentSelector();
selector.setLogger(getLogger());
selector.contextualize(this.context);
selector.setRoleManager(emptyRoleManager);
selector.setLogKitManager(this.logKit);
selector.compose(this.manager);
// selector.configure( - no configuration - );
// Iterate on all components
Configuration[] elements = section.getChildren();
for (int j = 0; i < elements.length; j++) {
Configuration element = elements[i];
checkNamespace(element);
// Is it the right name ?
if (! element.getName().equals(elementName)) {
throw new ConfigurationException("Unknown element named '" + element.getName() +
", at " + element.getLocation());
}
// Get the element name
String name = element.getAttribute("name");
// Register the class
String className = element.getAttribute("src");
Class clazz;
try {
clazz = ClassUtils.loadClass(className);
} catch(Exception e) {
throw new ConfigurationException("Cannot load class '" + className +
"' for " + elementName + " '" + name + "', at " + element.getLocation(), e);
}
// Register the component
selector.addComponent(name, clazz, element);
if (name.equals(defaultElement)) {
// Also register as default component
selector.addComponent(DEFAULT_HINT, clazz, element);
// Clear default to mark it as found
defaultElement = null;
}
} // end for elements
if (defaultElement != null) {
// default not found
throw new ConfigurationException("Default element '" + defaultElement +
"' does not exist, at " + section.getLocation());
}
selector.initialize();
// Publish the selector
this.builder.addComponentInstance((String)this.sectionRoles.get(sectionName), selector);
} // end for sections
}
/**
* Always return <code>null</code>.
*/
public ProcessingNode getNode() {
// Nothing to do at runtime.
return null;
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/GeneratorNode.java
Index: GeneratorNode.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor.sitemap;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import org.apache.cocoon.treeprocessor.AbstractProcessingNode;
import org.apache.cocoon.treeprocessor.ListOfMapsResolver;
import java.util.List;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $
*/
public class GeneratorNode extends AbstractProcessingNode {
protected String generatorName;
protected ListOfMapsResolver source;
public boolean invoke(Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps)
throws Exception {
eventPipeline.setGenerator(
this.generatorName,
source.resolve(listOfMaps),
ListOfMapsResolver.buildParameters(this.parameters, listOfMaps)
);
return true;
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/GeneratorNodeBuilder.java
Index: GeneratorNodeBuilder.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor.sitemap;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.cocoon.treeprocessor.AbstractProcessingNodeBuilder;
import org.apache.cocoon.treeprocessor.ProcessingNode;
import java.util.Map;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $
*/
public class GeneratorNodeBuilder extends AbstractProcessingNodeBuilder {
public void buildNode(Configuration config, Map buildModel) {
}
public ProcessingNode getNode() {
return null;
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/PipelineNode.java
Index: PipelineNode.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor.sitemap;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import org.apache.cocoon.treeprocessor.AbstractParentProcessingNode;
import java.util.List;
import java.util.Map;
/**
*
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $
*/
public class PipelineNode extends AbstractParentProcessingNode {
public boolean invoke(Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps)
throws Exception {
boolean success = false;
// Try each of the children until one is successfull.
try {
for (int i = 0; i < childNodes.length; i++) {
if (childNodes[i].invoke(env, pipeline, eventPipeline, listOfMaps)) {
success = true;
break;
}
}
} catch(Exception e) {
// FIXME Error pipelines.
getLogger().debug("Error while processing pipeline", e);
throw e;
}
return success;
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/SitemapNode.java
Index: SitemapNode.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor.sitemap;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.components.pipeline.EventPipeline;
import org.apache.cocoon.components.pipeline.StreamPipeline;
import org.apache.cocoon.sitemap.SitemapRedirector;
import org.apache.cocoon.treeprocessor.AbstractParentProcessingNode;
import org.apache.cocoon.treeprocessor.EnvironmentSourceResolver;
import java.util.List;
import java.util.Map;
/**
* The root node of a sitemap.
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $
*/
public class SitemapNode extends AbstractParentProcessingNode implements Composable {
private static final String INTERNAL_ATTR = "sitemap:internal-request";
private static final String REDIRECTOR_ATTR = "sitemap:redirector";
protected ComponentManager manager;
public static boolean isInternalRequest(Environment env) {
return env.getAttribute(INTERNAL_ATTR) != null;
}
public static Redirector getRedirector(Environment env) {
return (Redirector)env.getAttribute(REDIRECTOR_ATTR);
}
/**
* Keep the component manager used everywhere in the tree so that we can
* cleanly dispose it.
*/
public void compose(ComponentManager manager) {
this.manager = manager;
}
/**
* Process the environment. Also adds an <code>EnvironmentSourceResolver</code>
* and a <code>Redirector</code> in the object model. The previous resolver and
* redirector, if any, are restored before return.
*/
public boolean invoke(Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps)
throws Exception {
boolean internal = false;
if (pipeline == null && eventPipeline == null) {
// External request : create pipelines
try {
eventPipeline = (EventPipeline) this.manager.lookup(EventPipeline.ROLE);
pipeline = (StreamPipeline) this.manager.lookup(StreamPipeline.ROLE);
pipeline.setEventPipeline(eventPipeline);
return doInvoke(env, pipeline, eventPipeline, listOfMaps);
} finally {
this.manager.release(eventPipeline);
this.manager.release(pipeline);
}
} else {
// Internal request
Object oldInternal = env.getAttribute(INTERNAL_ATTR);
try {
// Mark environment as internal request
env.setAttribute(INTERNAL_ATTR, Boolean.TRUE);
return doInvoke(env, pipeline, eventPipeline, listOfMaps);
} finally {
// Restore old internal-request value
env.setAttribute(INTERNAL_ATTR, oldInternal);
}
}
}
protected final boolean doInvoke(Environment env, StreamPipeline pipeline, EventPipeline eventPipeline, List listOfMaps)
throws Exception {
// Create the source resolver relative to the environment.
// Design note : creating the SourceResolver could also have been done
// in TreeProcessor.invoke(), but doing it here ensures we use the local
// component manager used by all other nodes, which may redefine the
// SourceHandler to use.
EnvironmentSourceResolver resolver = new EnvironmentSourceResolver(this.manager, env);
Map objectModel = env.getObjectModel();
Object oldResolver = objectModel.get(OBJECT_SOURCE_RESOLVER);
Object oldRedirector = env.getAttribute(REDIRECTOR_ATTR);
objectModel.put(OBJECT_SOURCE_RESOLVER, resolver);
env.setAttribute(REDIRECTOR_ATTR, new SitemapRedirector(env));
boolean success = true;
try {
// FIXME : is there any useful information that can be passed as top-level parameters,
// such as the URI of the mount point ?
for (int i = 0; i < childNodes.length; i++) {
if (! childNodes[i].invoke(env, pipeline, eventPipeline, listOfMaps)) {
success = false;
break;
}
}
//TODO : check redirector
return success;
} finally {
// Restore old redirector and resolver
env.setAttribute(REDIRECTOR_ATTR, oldRedirector);
objectModel.put(OBJECT_SOURCE_RESOLVER, oldResolver);
// Dispose the resolver
resolver.dispose();
}
}
/**
* Dispose all children and the component manager.
*/
public void dispose() {
this.disposeChildren();
if (this.manager instanceof Disposable) {
((Disposable)this.manager).dispose();
}
}
}
1.1 xml-cocoon2/scratchpad/src/org/apache/cocoon/treeprocessor/sitemap/SitemapNodeBuilder.java
Index: SitemapNodeBuilder.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.treeprocessor.sitemap;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.cocoon.treeprocessor.ProcessingNode;
import org.apache.cocoon.treeprocessor.AbstractParentProcessingNodeBuilder;
import java.util.Map;
/**
*
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Revision: 1.1 $ $Date: 2001/11/08 14:39:24 $
*/
public class SitemapNodeBuilder extends AbstractParentProcessingNodeBuilder implements Composable {
protected ComponentManager manager;
protected SitemapNode node;
public void compose(ComponentManager manager) throws ComponentException {
this.manager = manager;
}
public void buildNode(Configuration config, Map buildModel) throws Exception {
node = new SitemapNode();
node.compose(this.manager);
}
public ProcessingNode getNode() throws Exception {
return this.node;
}
}
----------------------------------------------------------------------
In case of troubles, e-mail: webmaster@xml.apache.org
To unsubscribe, e-mail: cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org