| /* |
| * 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.runtime; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.ode.bpel.common.FaultException; |
| import org.apache.ode.bpel.evt.PartnerLinkModificationEvent; |
| import org.apache.ode.bpel.evt.ScopeEvent; |
| import org.apache.ode.bpel.evt.VariableModificationEvent; |
| import org.apache.ode.bpel.explang.EvaluationContext; |
| import org.apache.ode.bpel.explang.EvaluationException; |
| import org.apache.ode.bpel.obj.OAssign; |
| import org.apache.ode.bpel.obj.OAssign.DirectRef; |
| import org.apache.ode.bpel.obj.OAssign.LValueExpression; |
| import org.apache.ode.bpel.obj.OAssign.PropertyRef; |
| import org.apache.ode.bpel.obj.OAssign.VariableRef; |
| import org.apache.ode.bpel.obj.OElementVarType; |
| import org.apache.ode.bpel.obj.OExpression; |
| import org.apache.ode.bpel.obj.OLink; |
| import org.apache.ode.bpel.obj.OMessageVarType; |
| import org.apache.ode.bpel.obj.OMessageVarType.Part; |
| import org.apache.ode.bpel.obj.OProcess.OProperty; |
| import org.apache.ode.bpel.obj.OScope; |
| import org.apache.ode.bpel.obj.OScope.Variable; |
| import org.apache.ode.bpel.runtime.channels.FaultData; |
| import org.apache.ode.utils.DOMUtils; |
| import org.apache.ode.utils.Namespaces; |
| import org.apache.ode.utils.msg.MessageBundle; |
| import org.apache.ode.bpel.evar.ExternalVariableModuleException; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Text; |
| import org.xml.sax.SAXException; |
| |
| import javax.xml.namespace.QName; |
| |
| import java.io.IOException; |
| import java.net.URI; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Assign activity run-time template. |
| */ |
| class ASSIGN extends ACTIVITY { |
| private static final long serialVersionUID = 1L; |
| |
| private static final Log __log = LogFactory.getLog(ASSIGN.class); |
| |
| private static final ASSIGNMessages __msgs = MessageBundle |
| .getMessages(ASSIGNMessages.class); |
| |
| public ASSIGN(ActivityInfo self, ScopeFrame scopeFrame, LinkFrame linkFrame) { |
| super(self, scopeFrame, linkFrame); |
| } |
| |
| public void run() { |
| OAssign oassign = getOAsssign(); |
| |
| FaultData faultData = null; |
| |
| for (OAssign.Copy aCopy : oassign.getCopy()) { |
| try { |
| copy(aCopy); |
| } catch (FaultException fault) { |
| if (aCopy.isIgnoreMissingFromData()) { |
| if (fault.getQName().equals(getOAsssign().getOwner().getConstants().getQnSelectionFailure()) && |
| (fault.getCause() != null && "ignoreMissingFromData".equals(fault.getCause().getMessage()))) { |
| continue; |
| } |
| } |
| if (aCopy.isIgnoreUninitializedFromVariable()) { |
| if (fault.getQName().equals(getOAsssign().getOwner().getConstants().getQnUninitializedVariable()) && |
| (fault.getCause() == null || !"throwUninitializedToVariable".equals(fault.getCause().getMessage()))) { |
| continue; |
| } |
| } |
| faultData = createFault(fault.getQName(), aCopy, fault |
| .getMessage()); |
| break; |
| } catch (ExternalVariableModuleException e) { |
| __log.error("Exception while initializing external variable", e); |
| _self.parent.failure(e.toString(), null); |
| return; |
| } |
| } |
| |
| if (faultData != null) { |
| __log.info("Assignment Fault: " + faultData.getFaultName() |
| + ",lineNo=" + faultData.getFaultLineNo() |
| + ",faultExplanation=" + faultData.getExplanation()); |
| _self.parent.completed(faultData, CompensationHandler.emptySet()); |
| } else { |
| _self.parent.completed(null, CompensationHandler.emptySet()); |
| } |
| } |
| |
| protected Log log() { |
| return __log; |
| } |
| |
| private OAssign getOAsssign() { |
| return (OAssign) _self.o; |
| } |
| |
| private Node evalLValue(OAssign.LValue to) throws FaultException, ExternalVariableModuleException { |
| final BpelRuntimeContext napi = getBpelRuntimeContext(); |
| Node lval = null; |
| if (!(to instanceof OAssign.PartnerLinkRef)) { |
| VariableInstance lvar; |
| try { |
| lvar = _scopeFrame.resolve(to.getVariable()); |
| } catch (RuntimeException e) { |
| __log.error("iid: " + getBpelRuntimeContext().getPid() + " error evaluating lvalue"); |
| throw new FaultException(getOAsssign().getOwner().getConstants().getQnSelectionFailure(), e.getMessage()); |
| } |
| if (lvar == null) { |
| String msg = __msgs.msgEvalException(to.toString(), "Could not resolve variable in current scope"); |
| if (__log.isDebugEnabled()) __log.debug(to + ": " + msg); |
| throw new FaultException(getOAsssign().getOwner().getConstants().getQnSelectionFailure(), msg); |
| } |
| if (!napi.isVariableInitialized(lvar)) { |
| Document doc = DOMUtils.newDocument(); |
| Node val = to.getVariable().getType().newInstance(doc); |
| if (val.getNodeType() == Node.TEXT_NODE) { |
| Element tempwrapper = doc.createElementNS(null, "temporary-simple-type-wrapper"); |
| doc.appendChild(tempwrapper); |
| tempwrapper.appendChild(val); |
| val = tempwrapper; |
| } else doc.appendChild(val); |
| // Only external variables need to be initialized, others are new and going to be overwtitten |
| if (lvar.declaration.getExtVar() != null) lval = initializeVariable(lvar, val); |
| else lval = val; |
| } else |
| lval = fetchVariableData(lvar, true); |
| } |
| return lval; |
| } |
| |
| /** |
| * Get the r-value. There are several possibilities: |
| * <ul> |
| * <li>a message is selected - an element representing the whole message is |
| * returned.</li> |
| * <li>a (element) message part is selected - the element is returned. |
| * </li> |
| * <li>a (typed) message part is select - a wrapper element is returned. |
| * </li> |
| * <li>an attribute is selected - an attribute node is returned. </li> |
| * <li>a text node/string expression is selected - a text node is returned. |
| * </li> |
| * </ul> |
| * |
| * @param from |
| * |
| * @return Either {@link Element}, {@link org.w3c.dom.Text}, or |
| * {@link org.w3c.dom.Attr} node representing the r-value. |
| * |
| * @throws FaultException |
| * DOCUMENTME |
| * @throws UnsupportedOperationException |
| * DOCUMENTME |
| * @throws IllegalStateException |
| * DOCUMENTME |
| */ |
| private Node evalRValue(OAssign.RValue from) throws FaultException, ExternalVariableModuleException { |
| if (__log.isDebugEnabled()) |
| __log.debug("Evaluating FROM expression \"" + from + "\"."); |
| |
| Node retVal; |
| if (from instanceof DirectRef) { |
| OAssign.DirectRef dref = (OAssign.DirectRef) from; |
| sendVariableReadEvent(_scopeFrame.resolve(dref.getVariable())); |
| Node data = fetchVariableData( |
| _scopeFrame.resolve(dref.getVariable()), false); |
| retVal = DOMUtils.findChildByName((Element)data, dref.getElName()); |
| } else if (from instanceof OAssign.VariableRef) { |
| OAssign.VariableRef varRef = (OAssign.VariableRef) from; |
| sendVariableReadEvent(_scopeFrame.resolve(varRef.getVariable())); |
| Node data = fetchVariableData(_scopeFrame.resolve(varRef.getVariable()), false); |
| retVal = evalQuery(data, varRef.getPart() != null ? varRef.getPart() : varRef.getHeaderPart(), varRef.getLocation(), getEvaluationContext()); |
| } else if (from instanceof OAssign.PropertyRef) { |
| OAssign.PropertyRef propRef = (OAssign.PropertyRef) from; |
| sendVariableReadEvent(_scopeFrame.resolve(propRef.getVariable())); |
| Node data = fetchVariableData(_scopeFrame.resolve(propRef.getVariable()), false); |
| retVal = evalQuery(data, propRef.getPropertyAlias().getPart(), |
| propRef.getPropertyAlias().getLocation(), getEvaluationContext()); |
| } else if (from instanceof OAssign.PartnerLinkRef) { |
| OAssign.PartnerLinkRef pLinkRef = (OAssign.PartnerLinkRef) from; |
| PartnerLinkInstance pLink = _scopeFrame.resolve(pLinkRef.getPartnerLink()); |
| Node tempVal =pLinkRef.isIsMyEndpointReference() ? |
| getBpelRuntimeContext().fetchMyRoleEndpointReferenceData(pLink) |
| : getBpelRuntimeContext().fetchPartnerRoleEndpointReferenceData(pLink); |
| if (__log.isDebugEnabled()) |
| __log.debug("RValue is a partner link, corresponding endpoint " |
| + tempVal.getClass().getName() + " has value " + DOMUtils.domToString(tempVal)); |
| retVal = tempVal; |
| } else if (from instanceof OAssign.Expression) { |
| List<Node> l; |
| OExpression expr = ((OAssign.Expression) from).getExpression(); |
| try { |
| l = getBpelRuntimeContext().getExpLangRuntime().evaluate(expr, getEvaluationContext()); |
| if (l.size() == 0 || l.get(0) == null || !(l.get(0) instanceof Element)) { |
| if (__log.isTraceEnabled()) { |
| __log.trace("evalRValue: OAssign.Expression: eval reult not Element or node=null"); |
| } |
| } else { |
| Element element = (Element)l.get(0); |
| for (Map.Entry<String, String> entry : DOMUtils.getMyNSContext(element).toMap().entrySet()) { |
| String key = entry.getKey(); |
| String value = entry.getValue(); |
| if (entry.getKey() == null || entry.getKey().length() == 0) { |
| element.setAttributeNS(DOMUtils.NS_URI_XMLNS, "xmlns", value); |
| } else { |
| element.setAttributeNS(DOMUtils.NS_URI_XMLNS, "xmlns:" + key, value); |
| } |
| } |
| } |
| } catch (EvaluationException e) { |
| String msg = __msgs.msgEvalException(from.toString(), e.getMessage()); |
| if (__log.isDebugEnabled()) __log.debug(from + ": " + msg); |
| if (e.getCause() instanceof FaultException) throw (FaultException)e.getCause(); |
| throw new FaultException(getOAsssign().getOwner().getConstants().getQnSelectionFailure(), msg); |
| } |
| if (l.size() == 0) { |
| String msg = __msgs.msgRValueNoNodesSelected(expr.toString()); |
| if (__log.isDebugEnabled()) __log.debug(from + ": " + msg); |
| throw new FaultException(getOAsssign().getOwner().getConstants().getQnSelectionFailure(), msg, new Throwable("ignoreMissingFromData")); |
| } else if (l.size() > 1) { |
| String msg = __msgs.msgRValueMultipleNodesSelected(expr.toString()); |
| if (__log.isDebugEnabled()) __log.debug(from + ": " + msg); |
| throw new FaultException(getOAsssign().getOwner().getConstants().getQnSelectionFailure(), msg); |
| } |
| retVal = (Node) l.get(0); |
| } else if (from instanceof OAssign.Literal) { |
| String literal = ((OAssign.Literal) from).getXmlLiteral(); |
| Element literalRoot; |
| try { |
| literalRoot = DOMUtils.stringToDOM(literal); |
| } catch (Exception e) { |
| throw new RuntimeException("XML literal parsing failed " + literal, e); |
| } |
| assert literalRoot.getLocalName().equals("literal"); |
| // We'd like a single text node... |
| |
| literalRoot.normalize(); |
| retVal = literalRoot.getFirstChild(); |
| |
| // Adjust for whitespace before an element. |
| if (retVal != null && retVal.getNodeType() == Node.TEXT_NODE |
| && retVal.getTextContent().trim().length() == 0 |
| && retVal.getNextSibling() != null) { |
| retVal = retVal.getNextSibling(); |
| } |
| |
| if (retVal == null) { |
| // Special case, no children --> empty TII |
| retVal = literalRoot.getOwnerDocument().createTextNode(""); |
| } else if (retVal.getNodeType() == Node.ELEMENT_NODE) { |
| // Make sure there is no more elements. |
| Node x = retVal.getNextSibling(); |
| while (x != null) { |
| if (x.getNodeType() == Node.ELEMENT_NODE) { |
| String msg = __msgs.msgLiteralContainsMultipleEIIs(); |
| if (__log.isDebugEnabled()) |
| __log.debug(from + ": " + msg); |
| throw new FaultException( |
| getOAsssign().getOwner().getConstants().getQnSelectionFailure(), |
| msg); |
| |
| } |
| x = x.getNextSibling(); |
| } |
| } else if (retVal.getNodeType() == Node.TEXT_NODE) { |
| // Make sure there are no elements following this text node. |
| Node x = retVal.getNextSibling(); |
| while (x != null) { |
| if (x.getNodeType() == Node.ELEMENT_NODE) { |
| String msg = __msgs.msgLiteralContainsMixedContent(); |
| if (__log.isDebugEnabled()) |
| __log.debug(from + ": " + msg); |
| throw new FaultException( |
| getOAsssign().getOwner().getConstants().getQnSelectionFailure(), |
| msg); |
| |
| } |
| x = x.getNextSibling(); |
| } |
| |
| } |
| |
| if (retVal == null) { |
| String msg = __msgs.msgLiteralMustContainTIIorEII(); |
| if (__log.isDebugEnabled()) |
| __log.debug(from + ": " + msg); |
| throw new FaultException( |
| getOAsssign().getOwner().getConstants().getQnSelectionFailure(), |
| msg); |
| } |
| } else { |
| String msg = __msgs |
| .msgInternalError("Unknown RVALUE type: " + from); |
| if (__log.isErrorEnabled()) |
| __log.error(from + ": " + msg); |
| throw new FaultException( |
| getOAsssign().getOwner().getConstants().getQnSelectionFailure(), msg); |
| } |
| |
| // Now verify we got something. |
| if (retVal == null) { |
| String msg = __msgs.msgEmptyRValue(); |
| if (__log.isDebugEnabled()) |
| __log.debug(from + ": " + msg); |
| throw new FaultException( |
| getOAsssign().getOwner().getConstants().getQnSelectionFailure(), msg); |
| } |
| |
| // Now check that we got the right thing. |
| switch (retVal.getNodeType()) { |
| case Node.TEXT_NODE: |
| case Node.ATTRIBUTE_NODE: |
| case Node.ELEMENT_NODE: |
| case Node.CDATA_SECTION_NODE: |
| break; |
| default: |
| String msg = __msgs.msgInvalidRValue(); |
| if (__log.isDebugEnabled()) |
| __log.debug(from + ": " + msg); |
| |
| throw new FaultException( |
| getOAsssign().getOwner().getConstants().getQnSelectionFailure(), msg); |
| |
| } |
| |
| return retVal; |
| } |
| |
| private void copy(OAssign.Copy ocopy) throws FaultException, ExternalVariableModuleException { |
| |
| if (__log.isDebugEnabled()) |
| __log.debug("Assign.copy(" + ocopy + ")"); |
| |
| ScopeEvent se; |
| |
| // Check for message to message - copy, we can do this efficiently in |
| // the database. |
| if ((ocopy.getTo() instanceof VariableRef && ((VariableRef) ocopy.getTo()) |
| .isMessageRef()) |
| || (ocopy.getFrom() instanceof VariableRef && ((VariableRef) ocopy.getFrom()) |
| .isMessageRef())) { |
| |
| if ((ocopy.getTo() instanceof VariableRef && ((VariableRef) ocopy.getTo()) |
| .isMessageRef()) |
| && ocopy.getFrom() instanceof VariableRef |
| && ((VariableRef) ocopy.getFrom()).isMessageRef()) { |
| |
| final VariableInstance lval = _scopeFrame.resolve(ocopy.getTo() |
| .getVariable()); |
| final VariableInstance rval = _scopeFrame |
| .resolve(((VariableRef) ocopy.getFrom()).getVariable()); |
| Element lvalue = (Element) fetchVariableData(rval, false); |
| initializeVariable(lval, lvalue); |
| se = new VariableModificationEvent(lval.declaration.getName()); |
| ((VariableModificationEvent)se).setNewValue(lvalue); |
| } else { |
| // This really should have been caught by the compiler. |
| __log |
| .fatal("Message/Non-Message Assignment, should be caught by compiler:" |
| + ocopy); |
| throw new FaultException( |
| ocopy.getOwner().getConstants().getQnSelectionFailure(), |
| "Message/Non-Message Assignment: " + ocopy); |
| } |
| } else { |
| // Conventional Assignment logic. |
| Node rvalue = evalRValue(ocopy.getFrom()); |
| Node lvalue = evalLValue(ocopy.getTo()); |
| if (__log.isDebugEnabled()) { |
| __log.debug("lvalue after eval " + lvalue); |
| if (lvalue != null) __log.debug("content " + DOMUtils.domToString(lvalue)); |
| } |
| |
| // Get a pointer within the lvalue. |
| Node lvaluePtr = lvalue; |
| boolean headerAssign = false; |
| if (ocopy.getTo() instanceof OAssign.DirectRef) { |
| DirectRef dref = ((DirectRef) ocopy.getTo()); |
| Element el = DOMUtils.findChildByName((Element)lvalue, dref.getElName()); |
| if (el == null) { |
| el = (Element) ((Element)lvalue).appendChild(lvalue.getOwnerDocument() |
| .createElementNS(dref.getElName().getNamespaceURI(), dref.getElName().getLocalPart())); |
| } |
| lvaluePtr = el; |
| } else if (ocopy.getTo() instanceof OAssign.VariableRef) { |
| VariableRef varRef = ((VariableRef) ocopy.getTo()); |
| if (varRef.getHeaderPart() != null) headerAssign = true; |
| lvaluePtr = evalQuery(lvalue, varRef.getPart() != null ? varRef.getPart() : varRef.getHeaderPart(), varRef.getLocation(), |
| new EvaluationContextProxy(varRef.getVariable(), lvalue)); |
| } else if (ocopy.getTo() instanceof OAssign.PropertyRef) { |
| PropertyRef propRef = ((PropertyRef) ocopy.getTo()); |
| lvaluePtr = evalQuery(lvalue, propRef.getPropertyAlias().getPart(), |
| propRef.getPropertyAlias().getLocation(), |
| new EvaluationContextProxy(propRef.getVariable(), |
| lvalue)); |
| } else if (ocopy.getTo() instanceof OAssign.LValueExpression) { |
| LValueExpression lexpr = (LValueExpression) ocopy.getTo(); |
| lexpr.setInsertMissingToData(ocopy.isInsertMissingToData()); |
| lvaluePtr = evalQuery(lvalue, null, lexpr.getExpression(), |
| new EvaluationContextProxy(lexpr.getVariable(), lvalue)); |
| if (__log.isDebugEnabled()) |
| __log.debug("lvaluePtr expr res " + lvaluePtr); |
| } |
| |
| // For partner link assignmenent, the whole content is assigned. |
| if (ocopy.getTo() instanceof OAssign.PartnerLinkRef) { |
| OAssign.PartnerLinkRef pLinkRef = ((OAssign.PartnerLinkRef) ocopy.getTo()); |
| PartnerLinkInstance plval = _scopeFrame |
| .resolve(pLinkRef.getPartnerLink()); |
| replaceEndpointRefence(plval, rvalue); |
| se = new PartnerLinkModificationEvent(((OAssign.PartnerLinkRef) ocopy.getTo()).getPartnerLink().getName()); |
| } else { |
| // Sneakily converting the EPR if it's not the format expected by the lvalue |
| if (ocopy.getFrom() instanceof OAssign.PartnerLinkRef) { |
| rvalue = getBpelRuntimeContext().convertEndpointReference((Element)rvalue, lvaluePtr); |
| if (rvalue.getNodeType() == Node.DOCUMENT_NODE) |
| rvalue = ((Document)rvalue).getDocumentElement(); |
| } |
| |
| Node parentNode = lvaluePtr.getParentNode(); |
| if (headerAssign && parentNode != null && "message".equals(parentNode.getNodeName()) && rvalue.getNodeType()==Node.ELEMENT_NODE ) { |
| lvalue = copyInto((Element)lvalue, (Element) lvaluePtr, (Element) rvalue); |
| } else if (rvalue.getNodeType() == Node.ELEMENT_NODE && lvaluePtr.getNodeType() == Node.ELEMENT_NODE) { |
| lvalue = replaceElement((Element)lvalue, (Element) lvaluePtr, (Element) rvalue, |
| ocopy.isKeepSrcElementName()); |
| } else { |
| lvalue = replaceContent(lvalue, lvaluePtr, rvalue.getTextContent()); |
| } |
| final VariableInstance lval = _scopeFrame.resolve(ocopy.getTo().getVariable()); |
| if (__log.isDebugEnabled()) |
| __log.debug("ASSIGN Writing variable '" + lval.declaration.getName() + |
| "' value '" + DOMUtils.domToString(lvalue) +"'"); |
| commitChanges(lval, lvalue); |
| se = new VariableModificationEvent(lval.declaration.getName()); |
| ((VariableModificationEvent)se).setNewValue(lvalue); |
| } |
| } |
| |
| if (ocopy.getDebugInfo() != null) |
| se.setLineNo(ocopy.getDebugInfo().getStartLine()); |
| sendEvent(se); |
| } |
| |
| @Override |
| Node fetchVariableData(VariableInstance variable, boolean forWriting) |
| throws FaultException { |
| try { |
| return super.fetchVariableData(variable, forWriting); |
| } catch (FaultException fe) { |
| if (forWriting) { |
| fe = new FaultException(fe.getQName(), fe.getMessage(), new Throwable("throwUninitializedToVariable")); |
| } |
| throw fe; |
| } |
| } |
| |
| private void replaceEndpointRefence(PartnerLinkInstance plval, Node rvalue) throws FaultException { |
| if (rvalue.getNodeType() == Node.ATTRIBUTE_NODE){ |
| rvalue = rvalue.getOwnerDocument().createTextNode(((Attr) rvalue).getValue()); |
| } |
| // Eventually wrapping with service-ref element if we've been directly assigned some |
| // value that isn't wrapped. |
| if (rvalue.getNodeType() == Node.TEXT_NODE || |
| (rvalue.getNodeType() == Node.ELEMENT_NODE && !rvalue.getLocalName().equals("service-ref"))) { |
| Document doc = DOMUtils.newDocument(); |
| Element serviceRef = doc.createElementNS(Namespaces.WSBPEL2_0_FINAL_SERVREF, "service-ref"); |
| doc.appendChild(serviceRef); |
| serviceRef.appendChild(doc.importNode(rvalue, true)); |
| rvalue = serviceRef; |
| } |
| |
| getBpelRuntimeContext().writeEndpointReference(plval, (Element)rvalue); |
| } |
| |
| private Element replaceElement(Element lval, Element ptr, Element src, |
| boolean keepSrcElement) { |
| Document doc = ptr.getOwnerDocument(); |
| Node parent = ptr.getParentNode(); |
| if (keepSrcElement) { |
| Element replacement = (Element)doc.importNode(src, true); |
| parent.replaceChild(replacement, ptr); |
| return (lval == ptr) ? replacement : lval; |
| } |
| |
| Element replacement = doc.createElementNS(ptr.getNamespaceURI(), ptr.getTagName()); |
| NodeList nl = src.getChildNodes(); |
| for (int i = 0; i < nl.getLength(); ++i) |
| replacement.appendChild(doc.importNode(nl.item(i), true)); |
| copyAttributes(doc, ptr, replacement); |
| copyAttributes(doc, src, replacement); |
| parent.replaceChild(replacement, ptr); |
| DOMUtils.copyNSContext(ptr, replacement); |
| |
| return (lval == ptr) ? replacement : lval; |
| } |
| |
| private void copyAttributes(Document doc, Element original, |
| Element replacement) { |
| NamedNodeMap attrs = original.getAttributes(); |
| for (int i = 0; i < attrs.getLength(); ++i) { |
| Attr attr = (Attr)attrs.item(i); |
| replacement.setAttributeNodeNS((Attr)doc.importNode(attr, true)); |
| } |
| } |
| |
| private Element copyInto(Element lval, Element ptr, Element src) { |
| ptr.appendChild(ptr.getOwnerDocument().importNode(src, true)); |
| return lval; |
| } |
| |
| /** |
| * isInsert flag desginates this as an 'element' type insertion, which |
| * requires insert the actual element value, rather than it's children |
| * |
| * @return |
| * @throws FaultException |
| */ |
| private Node replaceContent(Node lvalue, Node lvaluePtr, String rvalue) |
| throws FaultException { |
| Document d = lvaluePtr.getOwnerDocument(); |
| |
| if (__log.isDebugEnabled()) { |
| __log.debug("lvaluePtr type " + lvaluePtr.getNodeType()); |
| __log.debug("lvaluePtr " + DOMUtils.domToString(lvaluePtr)); |
| __log.debug("lvalue " + lvalue); |
| __log.debug("rvalue " + rvalue); |
| } |
| |
| switch (lvaluePtr.getNodeType()) { |
| case Node.ELEMENT_NODE: |
| |
| // Remove all the children. |
| while (lvaluePtr.hasChildNodes()) |
| lvaluePtr.removeChild(lvaluePtr.getFirstChild()); |
| |
| // Append a new text node. |
| lvaluePtr.appendChild(d.createTextNode(rvalue)); |
| |
| // If lvalue is a text, removing all lvaluePtr children had just removed it |
| // so we need to rebuild it as a child of lvaluePtr |
| if (lvalue instanceof Text) |
| lvalue = lvaluePtr.getFirstChild(); |
| break; |
| |
| case Node.TEXT_NODE: |
| |
| Node newval = d.createTextNode(rvalue); |
| // Replace ourselves . |
| lvaluePtr.getParentNode().replaceChild(newval, lvaluePtr); |
| |
| // A little kludge, let our caller know that the root element has changed. |
| // (used for assignment to a simple typed variable) |
| if (lvalue.getNodeType() == Node.ELEMENT_NODE) { |
| // No children, adding an empty text children to point to |
| if (lvalue.getFirstChild() == null) { |
| Text txt = lvalue.getOwnerDocument().createTextNode(""); |
| lvalue.appendChild(txt); |
| } |
| if (lvalue.getFirstChild().getNodeType() == Node.TEXT_NODE) |
| lvalue = lvalue.getFirstChild(); |
| } |
| if (lvalue.getNodeType() == Node.TEXT_NODE && ((Text) lvalue).getWholeText().equals( |
| ((Text) lvaluePtr).getWholeText())) |
| lvalue = lvaluePtr = newval; |
| break; |
| |
| case Node.ATTRIBUTE_NODE: |
| |
| ((Attr) lvaluePtr).setValue(rvalue); |
| break; |
| |
| default: |
| // This could occur if the expression language selects something |
| // like |
| // a PI or a CDATA. |
| String msg = __msgs.msgInvalidLValue(); |
| if (__log.isDebugEnabled()) |
| __log.debug(lvaluePtr + ": " + msg); |
| throw new FaultException( |
| getOAsssign().getOwner().getConstants().getQnSelectionFailure(), msg); |
| } |
| |
| return lvalue; |
| } |
| |
| private Node evalQuery(Node data, OMessageVarType.Part part, |
| OExpression expression, EvaluationContext ec) throws FaultException { |
| assert data != null; |
| |
| if (part != null) { |
| QName partName = new QName(null, part.getName()); |
| Node qualLVal = DOMUtils.findChildByName((Element) data, partName); |
| if (part.getType() instanceof OElementVarType) { |
| QName elName = ((OElementVarType) part.getType()).getElementType(); |
| qualLVal = DOMUtils.findChildByName((Element) qualLVal, elName); |
| } else if (part.getType() == null) { |
| // Special case of header parts never referenced in the WSDL def |
| if (qualLVal != null && qualLVal.getNodeType() == Node.ELEMENT_NODE |
| && ((Element)qualLVal).getAttribute("headerPart") != null |
| && DOMUtils.getTextContent(qualLVal) == null) |
| qualLVal = DOMUtils.getFirstChildElement((Element) qualLVal); |
| // The needed part isn't there, dynamically creating it |
| if (qualLVal == null) { |
| qualLVal = data.getOwnerDocument().createElementNS(null, part.getName()); |
| ((Element)qualLVal).setAttribute("headerPart", "true"); |
| data.appendChild(qualLVal); |
| } |
| } |
| data = qualLVal; |
| } |
| |
| if (expression != null) { |
| // Neat little trick.... |
| try { |
| data = ec.evaluateQuery(data, expression); |
| } catch (EvaluationException e) { |
| String msg = __msgs.msgEvalException(expression.toString(), e.getMessage()); |
| if (__log.isDebugEnabled()) __log.debug(expression + ": " + msg); |
| if (e.getCause() instanceof FaultException) throw (FaultException)e.getCause(); |
| throw new FaultException(getOAsssign().getOwner().getConstants().getQnSubLanguageExecutionFault(), msg); |
| } |
| } |
| |
| return data; |
| } |
| |
| private class EvaluationContextProxy implements EvaluationContext { |
| |
| private Variable _var; |
| |
| private Node _varNode; |
| |
| private Node _rootNode; |
| |
| private EvaluationContext _ctx; |
| |
| |
| private EvaluationContextProxy(Variable var, Node varNode) { |
| _var = var; |
| _varNode = varNode; |
| _ctx = getEvaluationContext(); |
| } |
| |
| public Node readVariable(OScope.Variable variable, OMessageVarType.Part part) throws FaultException { |
| if (variable.getName().equals(_var.getName())) { |
| if (part == null) return _varNode; |
| return _ctx.getPartData((Element)_varNode, part); |
| |
| } else |
| return _ctx.readVariable(variable, part); |
| |
| } /** |
| * @see org.apache.ode.bpel.explang.EvaluationContext#readMessageProperty(org.apache.ode.bpel.obj.OScope.Variable, |
| * org.apache.ode.bpel.obj.OProcess.OProperty) |
| */ |
| public String readMessageProperty(Variable variable, OProperty property) |
| throws FaultException { |
| return _ctx.readMessageProperty(variable, property); |
| } |
| |
| /** |
| * @see org.apache.ode.bpel.explang.EvaluationContext#isLinkActive(org.apache.ode.bpel.obj.OLink) |
| */ |
| public boolean isLinkActive(OLink olink) throws FaultException { |
| return _ctx.isLinkActive(olink); |
| } |
| |
| /** |
| * @see org.apache.ode.bpel.explang.EvaluationContext#getRootNode() |
| */ |
| public Node getRootNode() { |
| return _rootNode; |
| } |
| |
| /** |
| * @see org.apache.ode.bpel.explang.EvaluationContext#evaluateQuery(org.w3c.dom.Node, |
| * org.apache.ode.bpel.obj.OExpression) |
| */ |
| public Node evaluateQuery(Node root, OExpression expr) |
| throws FaultException { |
| _rootNode = root; |
| try { |
| return getBpelRuntimeContext().getExpLangRuntime() |
| .evaluateNode(expr, this); |
| } catch (org.apache.ode.bpel.explang.EvaluationException e) { |
| throw new FaultException(expr.getOwner().getConstants().getQnSubLanguageExecutionFault(), e); |
| } |
| } |
| |
| public Node getPartData(Element message, Part part) throws FaultException { |
| return _ctx.getPartData(message,part); |
| } |
| |
| public Long getProcessId() { |
| return _ctx.getProcessId(); |
| } |
| |
| public boolean narrowTypes() { |
| return false; |
| } |
| |
| public URI getBaseResourceURI() { |
| return _ctx.getBaseResourceURI(); |
| } |
| |
| public Node getPropertyValue(QName propertyName) { |
| return _ctx.getPropertyValue(propertyName); |
| } |
| |
| public QName getProcessQName() { |
| return _ctx.getProcessQName(); |
| } |
| |
| public Date getCurrentEventDateTime() { |
| return Calendar.getInstance().getTime(); |
| } |
| } |
| |
| } |