Java tutorial
/* * 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.ode.bpel.rtrep.v1.xpath10.jaxp; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.transform.TransformerFactory; 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 org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ode.bpel.common.FaultException; import org.apache.ode.bpel.rtrep.common.ConfigurationException; import org.apache.ode.bpel.rtrep.v1.EvaluationContext; import org.apache.ode.bpel.rtrep.v1.ExpressionLanguageRuntime; import org.apache.ode.bpel.rtrep.v1.OExpression; import org.apache.ode.bpel.rtrep.v1.xpath10.OXPath10Expression; import org.apache.ode.utils.DOMUtils; import org.apache.ode.utils.ISO8601DateParser; import org.apache.ode.utils.xsd.Duration; import org.apache.ode.utils.xsl.XslTransformHandler; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; /** * JAXP based XPath 1.0 Expression Language run-time subsytem. */ public class JaxpXPath10ExpressionRuntime implements ExpressionLanguageRuntime { /** Class-level logger. */ private static final Log __log = LogFactory.getLog(JaxpXPath10ExpressionRuntime.class); public void initialize(Map properties) throws ConfigurationException { TransformerFactory trsf = TransformerFactory.newInstance(); __log.debug("JAXP runtime: TransformerFactory impl = " + trsf.getClass()); XslTransformHandler.getInstance().setTransformerFactory(trsf); } public String evaluateAsString(OExpression cexp, EvaluationContext ctx) throws FaultException { return (String) evaluate(cexp, ctx, XPathConstants.STRING); } public boolean evaluateAsBoolean(OExpression cexp, EvaluationContext ctx) throws FaultException { return (Boolean) evaluate(cexp, ctx, XPathConstants.BOOLEAN); } public Number evaluateAsNumber(OExpression cexp, EvaluationContext ctx) throws FaultException { return (Number) evaluate(cexp, ctx, XPathConstants.NUMBER); } public List evaluate(OExpression cexp, EvaluationContext ctx) throws FaultException { List result; Object someRes = null; try { someRes = evaluate(cexp, ctx, XPathConstants.NODESET); } catch (FaultException ex) { try { // JDK implementation of evaluation seems to be more strict about result types than Saxon: // basic return types are not converted to lists automatically. // this simulates Saxon behaviour: get a string result and put it in a list. List resultList = new ArrayList(1); resultList.add(evaluateAsString(cexp, ctx)); someRes = resultList; } catch (Exception ex2) { // re-throw original exception if workaround does not work. throw ex; } } if (someRes instanceof List) { result = (List) someRes; __log.debug("Returned list of size " + result.size()); if ((result.size() == 1) && !(result.get(0) instanceof Node)) { // Dealing with a Java class Object simpleType = result.get(0); // Dates get a separate treatment as we don't want to call toString on them String textVal; if (simpleType instanceof Date) textVal = ISO8601DateParser.format((Date) simpleType); else textVal = simpleType.toString(); // Wrapping in a document Document d = DOMUtils.newDocument(); // Giving our node a parent just in case it's an LValue expression Element wrapper = d.createElement("wrapper"); Text text = d.createTextNode(textVal); wrapper.appendChild(text); d.appendChild(wrapper); result = Collections.singletonList(text); } } else if (someRes instanceof NodeList) { NodeList retVal = (NodeList) someRes; __log.debug("Returned node list of size " + retVal.getLength()); result = new ArrayList(retVal.getLength()); for (int m = 0; m < retVal.getLength(); ++m) { Node val = retVal.item(m); if (val.getNodeType() == Node.DOCUMENT_NODE) val = ((Document) val).getDocumentElement(); result.add(val); } } else { result = null; } return result; } public Node evaluateNode(OExpression cexp, EvaluationContext ctx) throws FaultException { List retVal = evaluate(cexp, ctx); if (retVal.size() == 0) throw new FaultException(cexp.getOwner().constants.qnSelectionFailure, "No results for expression: " + cexp); if (retVal.size() > 1) throw new FaultException(cexp.getOwner().constants.qnSelectionFailure, "Multiple results for expression: " + cexp); return (Node) retVal.get(0); } public Calendar evaluateAsDate(OExpression cexp, EvaluationContext context) throws FaultException { List literal = DOMUtils.toList(evaluate(cexp, context, XPathConstants.NODESET)); if (literal.size() == 0) throw new FaultException(cexp.getOwner().constants.qnSelectionFailure, "No results for expression: " + cexp); if (literal.size() > 1) throw new FaultException(cexp.getOwner().constants.qnSelectionFailure, "Multiple results for expression: " + cexp); Object date = literal.get(0); if (date instanceof Calendar) return (Calendar) date; if (date instanceof Date) { Calendar cal = Calendar.getInstance(); cal.setTime((Date) date); return cal; } if (date instanceof Element) date = ((Element) date).getTextContent(); try { return ISO8601DateParser.parseCal(date.toString()); } catch (Exception ex) { String errmsg = "Invalid date format: " + literal; __log.error(errmsg); throw new FaultException(cexp.getOwner().constants.qnInvalidExpressionValue, errmsg); } } public Duration evaluateAsDuration(OExpression cexp, EvaluationContext context) throws FaultException { String literal = this.evaluateAsString(cexp, context); try { return new Duration(literal); } catch (Exception ex) { String errmsg = "Invalid duration: " + literal; __log.error(errmsg, ex); throw new FaultException(cexp.getOwner().constants.qnInvalidExpressionValue, errmsg); } } private Object evaluate(OExpression cexp, EvaluationContext ctx, QName type) throws FaultException { try { OXPath10Expression oxpath = (OXPath10Expression) cexp; __log.debug("JAXP runtime: evaluating " + oxpath.xpath); // use default XPath implementation XPathFactory xpf = XPathFactory.newInstance(); __log.debug("JAXP runtime: XPathFactory impl = " + xpf.getClass()); XPath xpe = xpf.newXPath(); xpe.setXPathFunctionResolver(new JaxpFunctionResolver(ctx, oxpath)); xpe.setXPathVariableResolver(new JaxpVariableResolver(ctx, oxpath)); xpe.setNamespaceContext(oxpath.namespaceCtx); XPathExpression expr = xpe.compile(((OXPath10Expression) cexp).xpath); Object evalResult = expr .evaluate(ctx.getRootNode() == null ? DOMUtils.newDocument() : ctx.getRootNode(), type); if (evalResult != null && __log.isDebugEnabled()) { __log.debug("Expression " + cexp.toString() + " generated result " + evalResult + " - type=" + evalResult.getClass().getName()); if (ctx.getRootNode() != null) __log.debug("Was using context node " + DOMUtils.domToString(ctx.getRootNode())); } return evalResult; } catch (XPathExpressionException e) { // Extracting the real cause from all this wrapping isn't a simple task Throwable cause = e.getCause() != null ? e.getCause() : e; throw new FaultException(cexp.getOwner().constants.qnSubLanguageExecutionFault, cause.getMessage(), cause); } catch (WrappedFaultException wre) { __log.debug("Could not evaluate expression because of ", wre); throw (FaultException) wre.getCause(); } catch (Throwable t) { __log.debug("Could not evaluate expression because of ", t); throw new FaultException(cexp.getOwner().constants.qnSubLanguageExecutionFault, t.getMessage(), t); } } }