Author: jstrachan Date: Tue May 1 06:14:40 2007 New Revision: 534059 URL: http://svn.apache.org/viewvc?view=rev&rev=534059 Log: Added an XSLT processor and refactored the XPath and XSLT code into an xml package Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DomResultHandler.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/InvalidXPathExpression.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/MessageVariableResolver.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/ResultHandler.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StreamResultHandler.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StringResultHandler.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java (with props) activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/package.html (with props) Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java Tue May 1 06:14:40 2007 @@ -0,0 +1,98 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.xpath.XPathFactory; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * An implementation of {@link NamespaceContext} which uses a simple Map where + * the keys are the prefixes and the values are the URIs + * + * @version $Revision: $ + */ +public class DefaultNamespaceContext implements NamespaceContext { + + private final Map map; + private final NamespaceContext parent; + + public DefaultNamespaceContext() { + this(XPathFactory.newInstance()); + } + + public DefaultNamespaceContext(XPathFactory factory) { + this.parent = factory.newXPath().getNamespaceContext(); + this.map = new HashMap(); + } + + public DefaultNamespaceContext(NamespaceContext parent, Map map) { + this.parent = parent; + this.map = map; + } + + /** + * A helper method to make it easy to create newly populated instances + */ + public DefaultNamespaceContext add(String prefix, String uri) { + map.put(prefix, uri); + return this; + } + + public String getNamespaceURI(String prefix) { + String answer = (String) map.get(prefix); + if (answer == null && parent != null) { + return parent.getNamespaceURI(prefix); + } + return answer; + } + + public String getPrefix(String namespaceURI) { + for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) { + Map.Entry entry = (Map.Entry) iter.next(); + if (namespaceURI.equals(entry.getValue())) { + return (String) entry.getKey(); + } + } + if (parent != null) { + return parent.getPrefix(namespaceURI); + } + return null; + } + + public Iterator getPrefixes(String namespaceURI) { + Set set = new HashSet(); + for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) { + Map.Entry entry = (Map.Entry) iter.next(); + if (namespaceURI.equals(entry.getValue())) { + set.add(entry.getKey()); + } + } + if (parent != null) { + Iterator iter = parent.getPrefixes(namespaceURI); + while (iter.hasNext()) { + set.add(iter.next()); + } + } + return set.iterator(); + } +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DefaultNamespaceContext.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DomResultHandler.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DomResultHandler.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DomResultHandler.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DomResultHandler.java Tue May 1 06:14:40 2007 @@ -0,0 +1,40 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import org.apache.camel.Message; + +import javax.xml.transform.Result; +import javax.xml.transform.dom.DOMResult; + +/** + * Uses DOM to handle results of the transformation + * + * @version $Revision: 1.1 $ + */ +public class DomResultHandler implements ResultHandler { + private DOMResult result = new DOMResult(); + + public Result getResult() { + return result; + } + + public void setBody(Message in) { + in.setBody(result.getNode()); + } +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/DomResultHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/InvalidXPathExpression.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/InvalidXPathExpression.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/InvalidXPathExpression.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/InvalidXPathExpression.java Tue May 1 06:14:40 2007 @@ -0,0 +1,40 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import org.apache.camel.RuntimeExpressionException; + +import javax.xml.xpath.XPathException; + +/** + * An exception thrown if am XPath expression could not be parsed or evaluated + * + * @version $Revision: 521180 $ + */ +public class InvalidXPathExpression extends RuntimeExpressionException { + private final String xpath; + + public InvalidXPathExpression(String xpath, XPathException e) { + super("Invalid xpath: " + xpath + ". Reason: " + e, e); + this.xpath = xpath; + } + + public String getXpath() { + return xpath; + } +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/InvalidXPathExpression.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/MessageVariableResolver.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/MessageVariableResolver.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/MessageVariableResolver.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/MessageVariableResolver.java Tue May 1 06:14:40 2007 @@ -0,0 +1,101 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.xml.namespace.QName; +import javax.xml.xpath.XPathVariableResolver; +import java.util.HashMap; +import java.util.Map; + +/** + * A variable resolver for XPath expressions which support properties on the messge, exchange as well + * as making system properties and environment properties available. + * + * @version $Revision: 521692 $ + */ +public class MessageVariableResolver implements XPathVariableResolver { + public static final String SYSTEM_PROPERTIES_NAMESPACE = "http://camel.apache.org/xml/variables/system-properties"; + public static final String ENVIRONMENT_VARIABLES = "http://camel.apache.org/xml/variables/environment-variables"; + public static final String EXCHANGE_PROPERTY = "http://camel.apache.org/xml/variables/exchange-property"; + public static final String IN_HEADER = "http://camel.apache.org/xml/variables/in-header"; + public static final String OUT_HEADER = "http://camel.apache.org/xml/variables/out-header"; + + private static final transient Log log = LogFactory.getLog(MessageVariableResolver.class); + + private Exchange exchange; + private Map variables = new HashMap(); + + public Exchange getExchange() { + return exchange; + } + + public void setExchange(Exchange exchange) { + this.exchange = exchange; + } + + public Object resolveVariable(QName name) { + String uri = name.getNamespaceURI(); + String localPart = name.getLocalPart(); + Object answer = null; + + if (uri == null || uri.length() == 0) { + answer = variables.get(localPart); + if (answer == null) { + Message message = exchange.getIn(); + if (message != null) { + answer = message.getHeader(localPart); + } + if (answer == null) { + answer = exchange.getProperty(localPart); + } + } + } + else if (uri.equals(SYSTEM_PROPERTIES_NAMESPACE)) { + try { + answer = System.getProperty(localPart); + } + catch (Exception e) { + log.debug("Security exception evaluating system property: " + localPart + ". Reason: " + e, e); + } + } + else if (uri.equals(ENVIRONMENT_VARIABLES)) { + answer = System.getenv().get(localPart); + } + else if (uri.equals(EXCHANGE_PROPERTY)) { + answer = exchange.getProperty(localPart); + } + else if (uri.equals(IN_HEADER)) { + answer = exchange.getIn().getHeader(localPart); + } + else if (uri.equals(OUT_HEADER)) { + answer = exchange.getOut().getHeader(localPart); + } + + // TODO support exposing CamelContext properties/resources via XPath? + return answer; + } + + public void addVariable(String localPart, Object value) { + variables.put(localPart, value); + } +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/MessageVariableResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/ResultHandler.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/ResultHandler.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/ResultHandler.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/ResultHandler.java Tue May 1 06:14:40 2007 @@ -0,0 +1,33 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import org.apache.camel.Message; + +import javax.xml.transform.Result; + +/** + * A strategy for handling XSLT results + * + * @version $Revision: 1.1 $ + */ +public interface ResultHandler { + Result getResult(); + + void setBody(Message in); +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/ResultHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StreamResultHandler.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StreamResultHandler.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StreamResultHandler.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StreamResultHandler.java Tue May 1 06:14:40 2007 @@ -0,0 +1,42 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import org.apache.camel.Message; + +import javax.xml.transform.Result; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayOutputStream; + +/** + * Processes the XSLT result as a byte[] + * + * @version $Revision: 1.1 $ + */ +public class StreamResultHandler implements ResultHandler { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + StreamResult result = new StreamResult(buffer); + + public Result getResult() { + return result; + } + + public void setBody(Message in) { + in.setBody(buffer.toByteArray()); + } +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StreamResultHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StringResultHandler.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StringResultHandler.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StringResultHandler.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StringResultHandler.java Tue May 1 06:14:40 2007 @@ -0,0 +1,42 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import org.apache.camel.Message; + +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.Result; +import java.io.StringWriter; + +/** + * Processes the XSLT result as a String + * + * @version $Revision: 1.1 $ + */ +public class StringResultHandler implements ResultHandler { + StringWriter buffer = new StringWriter(); + StreamResult result = new StreamResult(buffer); + + public Result getResult() { + return result; + } + + public void setBody(Message in) { + in.setBody(buffer.toString()); + } +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/StringResultHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java Tue May 1 06:14:40 2007 @@ -0,0 +1,316 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import static org.apache.camel.converter.ObjectConverter.toBoolean; +import org.apache.camel.Exchange; +import org.apache.camel.Expression; +import org.apache.camel.Predicate; +import org.apache.camel.RuntimeExpressionException; +import org.apache.camel.Message; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +import javax.xml.namespace.QName; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathFactoryConfigurationException; +import javax.xml.xpath.XPathFunctionResolver; +import java.io.StringReader; + +/** + * Creates an XPath expression builder + * + * @version $Revision: 531854 $ + */ +public class XPathBuilder implements Expression, Predicate { + private final String text; + private XPathFactory xpathFactory; + private Class documentType = Document.class; + private QName resultType = null; + private String objectModelUri = null; + private DefaultNamespaceContext namespaceContext; + private XPathFunctionResolver functionResolver; + private XPathExpression expression; + private MessageVariableResolver variableResolver = new MessageVariableResolver(); + + public static XPathBuilder xpath(String text) { + return new XPathBuilder(text); + } + + public XPathBuilder(String text) { + this.text = text; + } + + @Override + public String toString() { + return "XPath: " + text; + } + + public boolean matches(E exchange) { + Object booleanResult = evaluateAs(exchange, XPathConstants.BOOLEAN); + return toBoolean(booleanResult); + } + + public void assertMatches(String text, E exchange) throws AssertionError { + Object booleanResult = evaluateAs(exchange, XPathConstants.BOOLEAN); + if (!toBoolean(booleanResult)) { + throw new AssertionError(this + " failed on " + exchange + " as returned <" + booleanResult + ">"); + } + } + + public Object evaluate(E exchange) { + return evaluateAs(exchange, resultType); + } + + + // Builder methods + //------------------------------------------------------------------------- + + /** + * Sets the expression result type to boolean + * + * @return the current builder + */ + public XPathBuilder booleanResult() { + resultType = XPathConstants.BOOLEAN; + return this; + } + + /** + * Sets the expression result type to boolean + * + * @return the current builder + */ + public XPathBuilder nodeResult() { + resultType = XPathConstants.NODE; + return this; + } + + /** + * Sets the expression result type to boolean + * + * @return the current builder + */ + public XPathBuilder nodeSetResult() { + resultType = XPathConstants.NODESET; + return this; + } + + /** + * Sets the expression result type to boolean + * + * @return the current builder + */ + public XPathBuilder numberResult() { + resultType = XPathConstants.NUMBER; + return this; + } + + /** + * Sets the expression result type to boolean + * + * @return the current builder + */ + public XPathBuilder stringResult() { + resultType = XPathConstants.STRING; + return this; + } + + /** + * Sets the object model URI to use + * + * @return the current builder + */ + public XPathBuilder objectModel(String uri) { + this.objectModelUri = uri; + return this; + } + + /** + * Sets the {@link XPathFunctionResolver} instance to use on these XPath expressions + * + * @return the current builder + */ + public XPathBuilder functionResolver(XPathFunctionResolver functionResolver) { + this.functionResolver = functionResolver; + return this; + } + + /** + * Registers the namespace prefix and URI with the builder so that the prefix can be used in XPath expressions + * + * @param prefix is the namespace prefix that can be used in the XPath expressions + * @param uri is the namespace URI to which the prefix refers + * @return the current builder + */ + public XPathBuilder namespace(String prefix, String uri) { + getNamespaceContext().add(prefix, uri); + return this; + } + + /** + * Registers a variable (in the global namespace) which can be referred to from XPath expressions + */ + public XPathBuilder variable(String name, Object value) { + variableResolver.addVariable(name, value); + return this; + } + + + // Properties + //------------------------------------------------------------------------- + public XPathFactory getXPathFactory() throws XPathFactoryConfigurationException { + if (xpathFactory == null) { + if (objectModelUri != null) { + xpathFactory = XPathFactory.newInstance(objectModelUri); + } + xpathFactory = XPathFactory.newInstance(); + } + return xpathFactory; + } + + public void setXPathFactory(XPathFactory xpathFactory) { + this.xpathFactory = xpathFactory; + } + + public Class getDocumentType() { + return documentType; + } + + public void setDocumentType(Class documentType) { + this.documentType = documentType; + } + + public String getText() { + return text; + } + + public QName getResultType() { + return resultType; + } + + public DefaultNamespaceContext getNamespaceContext() { + if (namespaceContext == null) { + try { + namespaceContext = new DefaultNamespaceContext(getXPathFactory()); + } + catch (XPathFactoryConfigurationException e) { + throw new RuntimeExpressionException(e); + } + } + return namespaceContext; + } + + public void setNamespaceContext(DefaultNamespaceContext namespaceContext) { + this.namespaceContext = namespaceContext; + } + + public XPathFunctionResolver getFunctionResolver() { + return functionResolver; + } + + public void setFunctionResolver(XPathFunctionResolver functionResolver) { + this.functionResolver = functionResolver; + } + + public XPathExpression getExpression() throws XPathFactoryConfigurationException, XPathExpressionException { + if (expression == null) { + expression = createXPathExpression(); + } + return expression; + } + + // Implementation methods + //------------------------------------------------------------------------- + + + /** + * Evaluates the expression as the given result type + */ + protected synchronized Object evaluateAs(E exchange, QName resultType) { + variableResolver.setExchange(exchange); + try { + Object document = getDocument(exchange); + if (resultType != null) { + if (document instanceof InputSource) { + InputSource inputSource = (InputSource) document; + return getExpression().evaluate(inputSource, resultType); + } + else { + return getExpression().evaluate(document, resultType); + } + } + else { + if (document instanceof InputSource) { + InputSource inputSource = (InputSource) document; + return getExpression().evaluate(inputSource); + } + else { + return getExpression().evaluate(document); + } + } + } + catch (XPathExpressionException e) { + throw new InvalidXPathExpression(getText(), e); + } + catch (XPathFactoryConfigurationException e) { + throw new InvalidXPathExpression(getText(), e); + } + } + + protected XPathExpression createXPathExpression() throws XPathExpressionException, XPathFactoryConfigurationException { + XPath xPath = getXPathFactory().newXPath(); + + // lets now clear any factory references to avoid keeping them around + xpathFactory = null; + + xPath.setNamespaceContext(getNamespaceContext()); + xPath.setXPathVariableResolver(variableResolver); + if (functionResolver != null) { + xPath.setXPathFunctionResolver(functionResolver); + } + return xPath.compile(text); + } + + /** + * Strategy method to extract the document from the exchange + */ + protected Object getDocument(E exchange) { + Message in = exchange.getIn(); + Class type = getDocumentType(); + Object answer = null; + if (type != null) { + answer = in.getBody(type); + } + if (answer == null) { + answer = in.getBody(); + } + + // lets try coerce some common types into something JAXP can deal with + if (answer instanceof String) { + answer = new InputSource(new StringReader(answer.toString())); + } + return answer; + } + + +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java Tue May 1 06:14:40 2007 @@ -0,0 +1,230 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.camel.builder.xml; + +import org.apache.camel.Exchange; +import org.apache.camel.ExpectedBodyTypeException; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.RuntimeTransformException; +import org.apache.camel.converter.jaxp.XmlConverter; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.stream.StreamSource; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.io.File; + +/** + * Creates a Processor + * which performs an XSLT transformation of the IN message body + * + * @version $Revision: 531854 $ + */ +public class XsltBuilder implements Processor { + private Map parameters = new HashMap(); + private XmlConverter converter = new XmlConverter(); + private Transformer transformer; + private ResultHandler resultHandler = new DomResultHandler(); + private boolean failOnNullBody = true; + + public XsltBuilder() { + } + + public XsltBuilder(Transformer transformer) { + this.transformer = transformer; + } + + @Override + public String toString() { + return "XSLT[" + transformer + "]"; + } + + public synchronized void process(E exchange) { + Transformer transformer = getTransformer(); + if (transformer == null) { + throw new IllegalArgumentException("No transformer configured!"); + } + configureTransformer(transformer, exchange); + Source source = getSource(exchange); + Result result = resultHandler.getResult(); + transform(transformer, source, result); + resultHandler.setBody(exchange.getIn()); + } + + // Builder methods + //------------------------------------------------------------------------- + + /** + * Creates an XSLT processor using the given transformer instance + */ + public static XsltBuilder xslt(Transformer transformer) { + return new XsltBuilder(transformer); + } + + /** + * Creates an XSLT processor using the given XSLT source + */ + public static XsltBuilder xslt(Source xslt) throws TransformerConfigurationException { + XsltBuilder answer = new XsltBuilder(); + answer.setTransformerSource(xslt); + return answer; + } + + /** + * Creates an XSLT processor using the given XSLT source + */ + public static XsltBuilder xslt(File xslt) throws TransformerConfigurationException { + return xslt(new StreamSource(xslt)); + } + + /** + * Sets the output as being a byte[] + */ + public XsltBuilder outputBytes() { + setResultHandler(new StreamResultHandler()); + return this; + } + + /** + * Sets the output as being a String + */ + public XsltBuilder outputString() { + setResultHandler(new StringResultHandler()); + return this; + } + + /** + * Sets the output as being a DOM + */ + public XsltBuilder outputDOM() { + setResultHandler(new DomResultHandler()); + return this; + } + + public XsltBuilder parameter(String name, Object value) { + parameters.put(name, value); + return this; + } + + + // Properties + //------------------------------------------------------------------------- + + public Map getParameters() { + return parameters; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public Transformer getTransformer() { + return transformer; + } + + public void setTransformer(Transformer transformer) { + this.transformer = transformer; + } + + public boolean isFailOnNullBody() { + return failOnNullBody; + } + + public void setFailOnNullBody(boolean failOnNullBody) { + this.failOnNullBody = failOnNullBody; + } + + public ResultHandler getResultHandler() { + return resultHandler; + } + + public void setResultHandler(ResultHandler resultHandler) { + this.resultHandler = resultHandler; + } + + public void setTransformerSource(Source source) throws TransformerConfigurationException { + setTransformer(converter.getTransformerFactory().newTransformer(source)); + } + + + // Implementation methods + // ------------------------------------------------------------------------- + + /** + * Converts the inbound body to a {@link Source} + */ + protected Source getSource(E exchange) { + Message in = exchange.getIn(); + Source source = in.getBody(Source.class); + if (source == null) { + if (isFailOnNullBody()) { + throw new ExpectedBodyTypeException(exchange, Source.class); + } + else { + try { + source = converter.toSource(converter.createDocument()); + } + catch (ParserConfigurationException e) { + throw new RuntimeTransformException(e); + } + } + } + return source; + } + + /** + * Performs the transformation, wrapping any thrown exceptions + */ + protected void transform(Transformer transformer, Source source, Result result) { + try { + transformer.transform(source, result); + } + catch (TransformerException e) { + throw new RuntimeTransformException(e); + } + } + + /** + * Configures the transformerwith exchange specific parameters + */ + protected void configureTransformer(Transformer transformer, Exchange exchange) { + transformer.clearParameters(); + + addParameters(transformer, exchange.getProperties()); + addParameters(transformer, exchange.getIn().getHeaders()); + addParameters(transformer, getParameters()); + + transformer.setParameter("exchange", exchange); + transformer.setParameter("in", exchange.getIn()); + transformer.setParameter("out", exchange.getOut()); + } + + protected void addParameters(Transformer transformer, Map map) { + Set> propertyEntries = map.entrySet(); + for (Map.Entry entry : propertyEntries) { + transformer.setParameter(entry.getKey(), entry.getValue()); + } + } +} Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java ------------------------------------------------------------------------------ svn:eol-style = native Added: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/package.html URL: http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/package.html?view=auto&rev=534059 ============================================================================== --- activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/package.html (added) +++ activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/package.html Tue May 1 06:14:40 2007 @@ -0,0 +1,27 @@ + + + + + + +Support for XPath based Expressions +and Predicates as well as +an XSLT processor + + + Propchange: activemq/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/package.html ------------------------------------------------------------------------------ svn:eol-style = native