You are viewing a plain text version of this content. The canonical link for it is here.
Posted to svn@forrest.apache.org by th...@apache.org on 2008/12/02 12:54:20 UTC
svn commit: r722434 - in
/forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher:
impl/helper/AXIOMXPathCreate.java transformation/DispatcherTransformer.java
Author: thorsten
Date: Tue Dec 2 03:54:20 2008
New Revision: 722434
URL: http://svn.apache.org/viewvc?rev=722434&view=rev
Log:
Adding more javadoc and inline comments to the classes
Modified:
forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/impl/helper/AXIOMXPathCreate.java
forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java
Modified: forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/impl/helper/AXIOMXPathCreate.java
URL: http://svn.apache.org/viewvc/forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/impl/helper/AXIOMXPathCreate.java?rev=722434&r1=722433&r2=722434&view=diff
==============================================================================
--- forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/impl/helper/AXIOMXPathCreate.java (original)
+++ forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/impl/helper/AXIOMXPathCreate.java Tue Dec 2 03:54:20 2008
@@ -31,7 +31,17 @@
import org.jaxen.JaxenException;
/**
- * Issue: WSCOMMONS-389
+ *
+ * Return the Node from the rootNode using the XPath expression path.
+ * If the node does not exist, it is created and then returned. This is a very
+ * simple method for creating new nodes. If the XPath contains selectors ([,,,])
+ * or "*" it is of course not possible to create the new node. So if you use
+ * such XPaths the node must exist beforehand. An simple exception is if the
+ * expression contains attribute test to values (e.g. [@id = 'du' and @select = 'true'])
+ *
+ *
+ * Issue:
+ * WSCOMMONS-389
*
* As soon the above issue is fixed we need to drop this implementation since
* this class will be go into the axiom code base.
Modified: forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java
URL: http://svn.apache.org/viewvc/forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java?rev=722434&r1=722433&r2=722434&view=diff
==============================================================================
--- forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java (original)
+++ forrest/branches/dispatcher_rewrite/plugins/org.apache.forrest.plugin.internal.dispatcher/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java Tue Dec 2 03:54:20 2008
@@ -214,7 +214,17 @@
private OMFactory factory;
private ContractFactory contractRep;
+ /*
+ * Housekeeping variables to indicate the state of processing. Remember SAX is
+ * a stream.
+ */
+ /**
+ * whether or not we need to process the properties
+ */
private boolean insideProperties = false;
+ /**
+ * whether or not we need are in the requested structurer
+ */
private boolean includeNodes = true;
private OMElement root;
@@ -245,16 +255,22 @@
// parameters here
config = new WritableDispatcherBean();
config.setStaxHelper(new StAX());
- allowXml = configuration.getChild("allowXml").getValueAsBoolean(
- false);
+ // are we allowing xml properties?
+ allowXml = configuration.getChild("allowXml").getValueAsBoolean(false);
config.setAllowXmlProperties(allowXml);
+ // set the prefix for the contract resolving
contractUriPrefix = configuration.getChild("contractUriPrefix").getValue(
"cocoon://resolve.contract.");
+ // set the suffix for the contract
config.setContractUriSufix(configuration.getChild("contractUriSufix")
.getValue(""));
+ // what level of xpath support do we want to allow?
xpathSupport = configuration.getChild("xpathSupport").getValue("basic");
+ // Do we want to shrink xml properties that have only a @value?
boolean shrink = configuration.getChild("shrink").getValueAsBoolean(true);
config.setShrink(shrink);
+ // request all factories to be created at this point since it is better to
+ // create them only once
setNewTransformerFactory();
}
@@ -273,31 +289,57 @@
contractUriPrefix = config.getContractUriPrefix();
}
+ /**
+ * Will prepare the factories that we need in further processing
+ *
+ * @throws TransformerFactoryConfigurationError
+ */
private void setNewTransformerFactory()
throws TransformerFactoryConfigurationError {
// Is this the best way to get an instance in cocoon?
TransformerFactory tfactory = TransformerFactory.newInstance();
+ // set the uri resolver the same as this class
tfactory.setURIResolver(this);
+ // we want to set the error handler here to make sure it is intitialized
tfactory.setErrorListener(new TraxErrorHandler(getLogger()));
+ // add the factory to the config
config.setTransFact(tfactory);
+ // get the OM factory
this.factory = OMAbstractFactory.getOMFactory();
+ // get the contract factory
this.contractRep = new ContractFactory(config);
}
- // we do all the heavy stuff later and only prepare the basics here,
- // this enhance the response time while caching.
+ /*
+ * @see
+ * org.apache.cocoon.transformation.AbstractSAXTransformer#setup(org.apache
+ * .cocoon.environment.SourceResolver, java.util.Map, java.lang.String,
+ * org.apache.avalon.framework.parameters.Parameters)
+ */
public void setup(SourceResolver resolver, Map objectModel, String src,
Parameters par) throws ProcessingException, SAXException, IOException {
+ /*
+ * we do all the heavy stuff later and only prepare the basics here, this
+ * enhance the response time while caching.
+ */
+ // setup our super class
super.setup(resolver, objectModel, src, par);
-
+ // get the id of this request
this.requestId = parameters
.getParameter(DISPATCHER_REQUEST_ATTRIBUTE, null);
+ // get the external cache key
this.cacheKey = parameters.getParameter(CACHE_PARAMETER, null);
if (null == this.cacheKey)
getLogger().warn(
"Caching not activated! Declare the CACHE_KEY_PARAMETER="
+ CACHE_PARAMETER + " in your sitemap.");
+ /*
+ * which is the file use to watch for changes (normally the structurer of
+ * the request). As long the file does not change we are using the cache
+ * object.
+ */
this.validityFile = parameters.getParameter(VALIDITY_PARAMETER, null);
+ // do we want to force that is caching is turned off?
this.validityChecking = parameters.getParameter(
VALIDITY_OVERRIDE_PARAMETER, "");
if (requestId == null) {
@@ -306,6 +348,7 @@
getLogger().error(error);
throw new ProcessingException(error);
}
+ // which format we want to process?
this.requestedFormat = parameters.getParameter(Captions.TYPE_ATT, null);
/*
* We need to change now the contract uri prefixes since in cocoon we need
@@ -319,11 +362,13 @@
getLogger().error(error);
throw new ProcessingException(error);
}
+ // add the format to the cache key
this.cacheKey += requestedFormat;
if (null == m_resolver) {
try {
m_resolver = (org.apache.excalibur.source.SourceResolver) manager
.lookup(SourceResolver.ROLE);
+ // add the resolver we use to the dispatcher
resolverDispatcher = new CocoonResolver(m_resolver);
config.setResolver(resolverDispatcher);
} catch (ServiceException e) {
@@ -343,46 +388,68 @@
public void startElement(String uri, String name, String raw, Attributes attr)
throws SAXException {
// Process start element event
- if (Captions.NS.equals(uri)) {
+ // Are we inside of properties? If so we need to record the elements.
+ if (this.insideProperties && this.includeNodes) {
+ // just start the recording
+ startSerializedXMLRecording(null);
+ } else if (Captions.NS.equals(uri)) {
+ // we are in the dispatcher ns
try {
/*
* We are in the dispatcher ns.
*/
getLogger().debug("Starting dispatcher element: " + raw);
- if (Captions.STRUCTURE_ELEMENT.equals(name)) {
+ if (Captions.STRUCTURER_ELEMENT.equals(name)) {
+ // we are in a structurer definition
structurerProcessingStart(attr);
- } else if (Captions.HOOK_ELEMENT.equals(name) && this.includeNodes) {
- hookProcessingStart(name, raw, attr);
- } else if (Captions.CONTRACT_ELEMENT.equals(name) && this.includeNodes) {
- contractProcessingStart(attr);
- } else if (Captions.PROPERTY_ELEMENT.equals(name) && this.includeNodes) {
- this.insideProperties = true;
- propertyProcessingStart(uri, name, raw, attr);
+ }
+ if (this.includeNodes) {
+ if (Captions.HOOK_ELEMENT.equals(name)) {
+ // we are inside a hook element
+ hookProcessingStart(name, raw, attr);
+ } else if (Captions.CONTRACT_ELEMENT.equals(name)) {
+ // we are inside a contract element
+ contractProcessingStart(attr);
+ } else if (Captions.PROPERTY_ELEMENT.equals(name)) {
+ // we are inside a property element
+ this.insideProperties = true;
+ propertyProcessingStart(uri, name, raw, attr);
+ }
}
} catch (Exception e) {
throw new SAXException(e);
}
} else {
- if (!this.insideProperties && this.includeNodes ){
+ if (!this.insideProperties && this.includeNodes) {
super.startElement(uri, name, raw, attr);
}
}
}
-
+
+ /*
+ * @see
+ * org.apache.cocoon.transformation.AbstractSAXTransformer#endElement(java
+ * .lang.String, java.lang.String, java.lang.String)
+ */
public void endElement(String uri, String name, String raw)
- throws SAXException {
+ throws SAXException {
getLogger().debug("Ending element: " + raw);
- if (Captions.NS.equals(uri)){
+ if (Captions.NS.equals(uri)) {
+ // we are in the dispatcher ns
try {
- if (Captions.STRUCTURE_ELEMENT.equals(name)){
+ if (Captions.STRUCTURE_ELEMENT.equals(name)) {
+ // we are in a structurer end element
structurerProcessingEnd(raw);
} else if (Captions.HOOK_ELEMENT.equals(name) && this.includeNodes) {
- //TODO Implement
+ // we are inside a hook end element
+ // FIXME Implement
} else if (Captions.CONTRACT_ELEMENT.equals(name) && this.includeNodes) {
+ // we are inside a contract end element
contractProcessingEnd();
- } else if (Captions.PROPERTY_ELEMENT.equals(name) && this.includeNodes){
- if (allowXml){
+ } else if (Captions.PROPERTY_ELEMENT.equals(name) && this.includeNodes) {
+ // we are inside a property end element
+ if (allowXml) {
String property = null;
try {
super.endElement(uri, name, raw);
@@ -390,33 +457,50 @@
} catch (ProcessingException e) {
throw new SAXException(e);
}
- if (null != property){
+ if (null != property) {
localParams.put(currentProperty, property.getBytes());
}
+ } else {
+ // FIXME Implement
}
}
} catch (ContractException e) {
- throw new SAXException (e);
+ throw new SAXException(e);
} catch (IOException e) {
- throw new SAXException (e);
+ throw new SAXException(e);
} catch (JaxenException e) {
- throw new SAXException (e);
+ throw new SAXException(e);
} catch (XMLStreamException e) {
- throw new SAXException (e);
+ throw new SAXException(e);
}
- }else if (!this.insideProperties && this.includeNodes){
+ } else if (!this.insideProperties && this.includeNodes) {
super.endElement(uri, name, raw);
}
}
- private void contractProcessingEnd() throws ContractException, IOException, JaxenException, XMLStreamException {
+ /**
+ * Will execute the contract and process the result.
+ *
+ * @throws ContractException
+ * @throws IOException
+ * @throws JaxenException
+ * @throws XMLStreamException
+ */
+ private void contractProcessingEnd() throws ContractException, IOException,
+ JaxenException, XMLStreamException {
+ // get the result stream from contract by executing it
InputStream resultStream = contract.execute(dataStream, localParams);
+ // close data stream
StreamHelper.closeStream(dataStream);
+ // add the result of the contract to the overall result set
processContractResult(resultStream, pathNode);
+ // close the result Stream
StreamHelper.closeStream(resultStream);
}
/**
+ * Process the contract result to add it to the overall result set.
+ *
* @param resultStream
* @param pathNode
* @throws XMLStreamException
@@ -425,8 +509,12 @@
@SuppressWarnings("unchecked")
private void processContractResult(InputStream resultStream,
OMElement pathNode) throws XMLStreamException, JaxenException {
- XMLStreamReader contractResultReader = config.getStaxHelper().getReader(resultStream);
+ // get xml stream reader
+ XMLStreamReader contractResultReader = config.getStaxHelper().getReader(
+ resultStream);
+ // get Axiom builder
StAXOMBuilder builder = new StAXOMBuilder(contractResultReader);
+ // get the document element
OMElement content = builder.getDocumentElement();
/*
* For full blown ns support we need to get all ns from the result. This
@@ -438,28 +526,40 @@
OMNamespace space = ns.next();
spaces.add(space);
}
+ // get the different parts of the contract
Iterator<OMElement> parts = content.getChildrenWithName(qIt(
Captions.NS_CONTRACTS, Captions.PART_ELEMENT));
while (parts.hasNext()) {
+ // while we have more parts, get the next part
OMElement part = parts.next();
+ // where do we need to inject it
String xpath = part.getAttributeValue(qIt(Captions.RESULT_XPATH));
+ // get the children of a part. This children needs to be injected in
+ // the result
Iterator<OMNode> children = part.getChildren();
if (xpath == null) {
+ // when we do not have a xpath to inject we will inject it in the
+ // current loaction
while (children.hasNext()) {
OMNode child = (OMNode) children.next();
pathNode.addChild(child);
}
} else {
+ // lookup the node where we want to inject the result part
xpath = PATH_PREFIX + xpath;
// we need to feed the xpathSelector with the ns we may have
AXIOMXPathCreate xpathSelector = new AXIOMXPathCreate(xpath);
-
+ // add all namespaces that are known to the selector
for (OMNamespace space : spaces) {
xpathSelector
.addNamespace(space.getPrefix(), space.getNamespaceURI());
}
+ // request the final inject point (node which will be used to inject the
+ // result)
OMElement injectionPoint = (OMElement) xpathSelector.selectSingleNode(
root, true);
+ // now iterate through the children of the result part and append the
+ // content to the injection point
while (children.hasNext()) {
OMNode child = (OMNode) children.next();
injectionPoint.addChild(child);
@@ -468,55 +568,88 @@
}
}
}
+
/**
+ * Helper method to create a qname
+ *
* @param name
- * @return
+ * the element name
+ * @return a qualified qname
*/
private QName qIt(String name) {
return new QName(name);
}
+
/**
+ * Helper method to create a qname
+ *
* @param name
+ * the element name
* @param uri
- * @return
+ * the ns
+ * @return a qualified qname
*/
- private QName qIt(String uri,String name) {
- return new QName(uri,name);
+ private QName qIt(String uri, String name) {
+ return new QName(uri, name);
}
+
+ /**
+ * Finish the processing of the structurer
+ *
+ * @param raw
+ */
private void structurerProcessingEnd(String raw) {
- if(includeNodes){
-
+ if (includeNodes) {
+ // FIXME: implement
}
-
+
}
+ /**
+ * Start the processing of the properties including setting the correct state
+ * for the next event round
+ *
+ * @param uri
+ * @param name
+ * @param raw
+ * @param attr
+ * @throws SAXException
+ */
private void propertyProcessingStart(String uri, String name, String raw,
Attributes attr) throws SAXException {
-
- String id = null , value = null;
+ // determine the name and a possible value
+ String id = null, value = null;
for (int i = 0; i < attr.getLength(); i++) {
String localName = attr.getLocalName(i);
String localValue = attr.getValue(i);
- if (Captions.NAME_ATT.equals(localName)){
+ if (Captions.NAME_ATT.equals(localName)) {
id = localValue;
- }else if(Captions.VALUE_ATT.equals(localName)){
+ } else if (Captions.VALUE_ATT.equals(localName)) {
value = localValue;
}
}
-
- if (allowXml){
+ // if we allow xml properties we will just record them
+ if (allowXml) {
// just start the recording
startSerializedXMLRecording(null);
super.startElement(uri, name, raw, attr);
currentProperty = id;
- }else{
- if (id!=null && value!= null){
+ } else {
+ // if we do not allow xml we will use a simple key/value approach
+ if (id != null && value != null) {
localParams.put(id, new String(value));
}
}
}
+ /**
+ * Start the processing of the contract this includes to resolve the data
+ * stream and the actual contract.
+ *
+ * @param attr
+ * @throws SAXException
+ */
private void contractProcessingStart(Attributes attr) throws SAXException {
String name = "", data = null;
try {
@@ -524,18 +657,22 @@
String localName = attr.getLocalName(i);
String value = attr.getValue(i);
if (Captions.NAME_ATT.equals(localName)) {
+ // get the name of the contract
name = value;
} else if (Captions.DATA_ATT.equals(localName)) {
+ // see whether we have a defined dataUri
data = value;
}
}
dataStream = null;
if (null != data && !data.equals("")) {
+ // try resoolving the dataUri
dataStream = resolverDispatcher.resolve(data);
}
+ // get the contract
contract = contractRep.resolve(name);
+ // prepare empty properties map
localParams = new HashMap<String, Object>(map);
-
} catch (Exception e) {
String error = DispatcherException.ERROR_500 + "\n"
+ "component: ContractBean" + "\n"
@@ -547,6 +684,14 @@
}
+ /**
+ * Start the processing of the hooks. Actually we just create a element in the
+ * result model with the same name and attributes as the incoming event.
+ *
+ * @param name
+ * @param raw
+ * @param attr
+ */
private void hookProcessingStart(String name, String raw, Attributes attr) {
OMElement element = factory.createOMElement(name, Captions.NS, "forrest");
for (int i = 0; i < attr.getLength(); i++) {
@@ -572,9 +717,14 @@
for (int i = 0; i < attr.getLength(); i++) {
String localName = attr.getLocalName(i);
String value = attr.getValue(i);
+ // determine what type (format) we have on the structurer
if (localName.equals(Captions.TYPE_ATT)) {
m_type = value;
}
+ /*
+ * Determine whether we have a hooks path attribute. If so it determines
+ * the smallest common path (e.g. <code>/html/body</code>)
+ */
if (localName.equals(Captions.HOOKS_ATT)) {
// adding the default path
boolean startsWithRoot = "/".equals(String.valueOf(value.charAt(0)));
@@ -586,20 +736,25 @@
path += value;
}
}
+ // are we in the format that have been requested?
if (requestedFormat.equals(m_type)) {
try {
// need to get the properties for this uri
map = new HashMap<String, Object>();
+ /*
+ * the properties are provided by a match in cocoon and are generated
+ * individually for each request
+ */
String propertyURI = "cocoon://" + requestId + ".props";
// get the source representation of the propertyURI
Source propsSource = m_resolver.resolveURI(propertyURI);
if (propsSource != null) {
- // get the stream
+ // get an input stream from the properties
InputStream stream = new BufferedInputStream(propsSource
.getInputStream());
/*
* we need either just the bytes of the stream (if we allow xml
- * properties) or we need to process it extracting the properties.
+ * properties) or we need to process it: extracting the properties.
*/
if (config.isAllowXmlProperties()) {
// get the bytes from the stream
@@ -610,12 +765,13 @@
*/
map.put(DEFAULT_VARIABLES, properties);
} else {
- // extract the properties of the in coming stream
+ // extract the properties of the incoming stream
XMLProperties.parseProperties(stream, map);
}
// release source - you need to ALWAYS do this!
release(propsSource);
}
+ // creating in/out stream objects
BufferedInputStream stream = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
/*
@@ -623,10 +779,20 @@
* need to strip the root element again.
*/
OMDocument doc = factory.createOMDocument();
+ // creating the root node for the xml document
root = factory.createOMElement(PATH_PREFIX, null);
+ // adding root element to the document (much like in DOM)
doc.addChild(root);
- AXIOMXPathCreate xpath = new AXIOMXPathCreate("/"+PATH_PREFIX + path);
+ /*
+ * request a axiom xpath resolver that will return a axiom element for a
+ * given xpath expression. If the node does not exist, it is created and
+ * then returned.
+ */
+ AXIOMXPathCreate xpath = new AXIOMXPathCreate("/" + PATH_PREFIX + path);
+ // get the node (if it does not exist, create it)
pathNode = (OMElement) xpath.selectSingleNode(root, true);
+ // we need to set the status variable, indicating we need process the
+ // children.
this.includeNodes = true;
} catch (Exception e) {
throw new DispatcherException(e);