001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.synapse.mediators.xquery;
020:
021: import net.sf.saxon.javax.xml.xquery.XQItemType;
022: import org.apache.axiom.om.OMElement;
023: import org.apache.axiom.om.OMNode;
024: import org.apache.axiom.om.OMText;
025: import org.apache.axiom.om.xpath.AXIOMXPath;
026: import org.apache.axiom.soap.SOAP11Constants;
027: import org.apache.axiom.soap.SOAP12Constants;
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.apache.synapse.MessageContext;
031: import org.apache.synapse.SynapseException;
032: import org.apache.synapse.config.Entry;
033: import org.apache.synapse.util.xpath.SynapseXPath;
034: import org.jaxen.JaxenException;
035:
036: import javax.xml.namespace.QName;
037: import java.util.List;
038:
039: /**
040: * The value of the custom variable will be evaluated dynamically.
041: * The value is computed by extracting the data from the XML document which will lookup through the
042: * key or the current SOAP message.
043: */
044:
045: public class MediatorCustomVariable extends MediatorVariable {
046:
047: private static final Log log = LogFactory
048: .getLog(MediatorCustomVariable.class);
049:
050: /**
051: * The XPath expression which yeilds the element from given XMLDocument
052: */
053: private AXIOMXPath expression;
054:
055: /**
056: * The key to lookup the xml document from registry
057: */
058: private String regKey;
059:
060: /**
061: * The default XPath which yeilds the first child of the SOAP Envelop
062: */
063: // public static final String DEFAULT_XPATH = "//s11:Envelope/s11:Body/child::*[position()=1] | " +
064: // "//s12:Envelope/s12:Body/child::*[position()=1]";
065: public static final String DEFAULT_XPATH = "s11:Body/child::*[position()=1] | "
066: + "s12:Body/child::*[position()=1]";
067:
068: /**
069: * Lock used to ensure thread-safe lookup of the object from the registry
070: */
071: private final Object resourceLock = new Object();
072:
073: public MediatorCustomVariable(QName name) {
074: super (name);
075: // create the default XPath
076: try {
077: this .expression = new AXIOMXPath(DEFAULT_XPATH);
078: this .expression.addNamespace("s11",
079: SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
080: this .expression.addNamespace("s12",
081: SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
082: } catch (JaxenException e) {
083: handleException("Error creating source XPath expression", e);
084: }
085:
086: }
087:
088: /**
089: * To assign a value to variable dynamically
090: *
091: * @param synCtx The current message context
092: */
093: public boolean evaluateValue(MessageContext synCtx) {
094:
095: if (this .regKey == null) { // get the node from the current message payload
096: this .value = evaluate(synCtx.getEnvelope());
097: return true;
098: } else {
099: //Load the XML document from the registry
100: boolean reLoad = false;
101: boolean hasValueChanged = false;
102: Entry dp = synCtx.getConfiguration().getEntryDefinition(
103: this .regKey);
104: // if the key refers to a dynamic resource
105: if (dp != null && dp.isDynamic()) {
106: if (!dp.isCached() || dp.isExpired()) {
107: reLoad = true;
108: }
109: }
110: synchronized (resourceLock) {
111: if (reLoad || this .value == null) {
112: hasValueChanged = true;
113: Object o = synCtx.getEntry(this .regKey);
114: if (o != null) {
115: if (!DEFAULT_XPATH
116: .equals(expression.toString())) {
117: this .value = evaluate(o);
118: } else {
119: this .value = o;
120: }
121: }
122: }
123: }
124: return hasValueChanged;
125: }
126: }
127:
128: /**
129: * Return the object to be used for the variable value
130: *
131: * @param source The source on which will be evaluated the XPath expression
132: * @return Return the OMNode to be used for the variable value
133: */
134: private Object evaluate(Object source) {
135: try {
136: Object result = expression.evaluate(source);
137: if (result instanceof List && !((List) result).isEmpty()) {
138: result = ((List) result).get(0); // Always fetches *only* the first
139: }
140: if (result instanceof OMNode) {
141: //if the type is not document-node(), then get the text value of the node
142: if (this .getType() != XQItemType.XQITEMKIND_DOCUMENT
143: && this .getType() != XQItemType.XQITEMKIND_DOCUMENT_ELEMENT
144: && this .getType() != XQItemType.XQITEMKIND_ELEMENT) {
145:
146: int nodeType = ((OMNode) result).getType();
147: if (nodeType == OMNode.TEXT_NODE) {
148: return ((OMText) result).getText();
149: } else if (nodeType == OMNode.ELEMENT_NODE) {
150: return ((OMElement) result).getText();
151: }
152: }
153: return result;
154: } else {
155: return result;
156: }
157: } catch (JaxenException e) {
158: handleException("Error evaluating XPath " + expression
159: + " on message" + source);
160: }
161: return null;
162: }
163:
164: private void handleException(String msg, Exception e) {
165: log.error(msg, e);
166: throw new SynapseException(msg, e);
167: }
168:
169: private void handleException(String msg) {
170: log.error(msg);
171: throw new SynapseException(msg);
172: }
173:
174: public void setExpression(AXIOMXPath expression) {
175: this .expression = expression;
176: }
177:
178: public void setRegKey(String regKey) {
179: this .regKey = regKey;
180: }
181:
182: public String getRegKey() {
183: return regKey;
184: }
185:
186: public AXIOMXPath getExpression() {
187: return expression;
188: }
189: }
|