/* * 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.synapse.util.xpath; import org.apache.axiom.soap.SOAPEnvelope; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseConstants; import org.apache.synapse.core.axis2.Axis2MessageContext; import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.description.AxisBindingOperation; import org.apache.axis2.description.WSDL2Constants; import org.apache.axis2.description.WSDL20DefaultValueHolder; import org.apache.axis2.Constants; import org.apache.axis2.transport.http.util.URIEncoderDecoder; import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.Log; import org.apache.synapse.mediators.template.TemplateContext; import org.apache.synapse.util.xpath.ext.XpathExtensionUtil; import org.jaxen.JaxenException; import org.jaxen.UnresolvableException; import org.jaxen.VariableContext; import java.util.Map; import java.io.UnsupportedEncodingException; import java.util.Stack; /** * Jaxen variable context for the XPath variables implicitly exposed by Synapse. * It exposes the following variables: * <dl> * <dt><tt>body</tt></dt> * <dd>The SOAP 1.1 or 1.2 body element.</dd> * <dt><tt>header</tt></dt> * <dd>The SOAP 1.1 or 1.2 header element.</dd> * </dl> */ public class SynapseXPathVariableContext implements VariableContext { private static final Log log = LogFactory.getLog(SynapseXPathVariableContext.class); /** Parent variable context */ private final VariableContext parent; /** MessageContext to be used for the variable resolution */ private final MessageContext synCtx; /** SOAPEnvelope to be used for the variable resolution */ private final SOAPEnvelope env; /** * <p>Initializes the <code>SynapseVariableContext</code> with the specified context</p> * * @param parent the parent variable context * @param synCtx context to be initialized for the variable resolution */ public SynapseXPathVariableContext(VariableContext parent, MessageContext synCtx) { this.parent = parent; this.synCtx = synCtx; this.env = synCtx.getEnvelope(); } /** * <p>Initializes the <code>SynapseVariableContext</code> with the specified envelope</p> * * @param parent the parent variable context * @param env envelope to be initialized for the variable resolution */ public SynapseXPathVariableContext(VariableContext parent, SOAPEnvelope env) { this.parent = parent; this.synCtx = null; this.env = env; } /** * <p>Initializes the <code>SynapseVariableContext</code> with the specified envelope</p> * * @param parent the parent variable context * @param synCtx Synapse Message context to be initialized for the variable resolution * @param env envelope to be initialized for the variable resolution */ public SynapseXPathVariableContext(VariableContext parent, MessageContext synCtx, SOAPEnvelope env) { this.parent = parent; this.synCtx = synCtx; this.env = env; } /** * Gets the variable values resolved from the context. This includes the * <dl> * <dt><tt>body</tt></dt> * <dd>The SOAP 1.1 or 1.2 body element.</dd> * <dt><tt>header</tt></dt> * <dd>The SOAP 1.1 or 1.2 header element.</dd> * </dl> * and the following variable prefixes * <dl> * <dt><tt>ctx</tt></dt> * <dd>Prefix for Synapse MessageContext properties</dd> * <dt><tt>axis2</tt></dt> * <dd>Prefix for Axis2 MessageContext properties</dd> * <dt><tt>trp</tt></dt> * <dd>Prefix for the transport headers</dd> * </dl> * If the variable is unknown, this method attempts to resolve it using * the parent variable context. * * @param namespaceURI namespaces for the variable resolution * @param prefix string prefix for the variable resolution * @param localName string local name for the variable resolution * @return Resolved variable value * @throws UnresolvableException if the variable specified does not found */ public Object getVariableValue(String namespaceURI, String prefix, String localName) throws UnresolvableException { if (namespaceURI == null) { if (env != null) { if (SynapseXPathConstants.SOAP_BODY_VARIABLE.equals(localName)) { return env.getBody(); } else if (SynapseXPathConstants.SOAP_HEADER_VARIABLE.equals(localName)) { return env.getHeader(); } else if (SynapseXPathConstants.SOAP_ENVELOPE_VARIABLE.equals(localName)) { return env; } } if (prefix != null && !"".equals(prefix) && synCtx != null) { if (SynapseXPathConstants.MESSAGE_CONTEXT_VARIABLE_PREFIX.equals(prefix)) { return synCtx.getProperty(localName); } else if (SynapseXPathConstants.AXIS2_CONTEXT_VARIABLE_PREFIX.equals(prefix)) { return ((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty(localName); } else if (SynapseXPathConstants.FUNC_CONTEXT_VARIABLE_PREFIX.equals(prefix)) { Stack<TemplateContext> functionStack = (Stack) synCtx.getProperty(SynapseConstants.SYNAPSE__FUNCTION__STACK); TemplateContext topCtxt = functionStack.peek(); if (topCtxt != null) { Object result = topCtxt.getParameterValue(localName); if (result != null && result instanceof SynapseXPath && env != null) { SynapseXPath expression = (SynapseXPath) topCtxt.getParameterValue(localName); try { return expression.evaluate(env); } catch (JaxenException e) { return null; } } else { return result; } } } else if (SynapseXPathConstants.TRANSPORT_VARIABLE_PREFIX.equals(prefix)) { org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext(); Object headers = axis2MessageContext.getProperty( org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); if (headers != null && headers instanceof Map) { Map headersMap = (Map) headers; return headersMap.get(localName); } else { return null; } } else if (SynapseXPathConstants.URL_VARIABLE_PREFIX.equals(prefix)) { EndpointReference toEPR = synCtx.getTo(); if (toEPR != null) { String completeURL = toEPR.getAddress(); AxisBindingOperation axisBindingOperation = (AxisBindingOperation) ((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty( Constants.AXIS_BINDING_OPERATION); String queryParameterSeparator = null; if (axisBindingOperation != null) { queryParameterSeparator = (String) axisBindingOperation.getProperty( WSDL2Constants.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR); } if (queryParameterSeparator == null) { queryParameterSeparator = WSDL20DefaultValueHolder. ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR_DEFAULT; } int i = completeURL.indexOf("?"); if (i > -1) { String queryString = completeURL.substring(i + 1); if (queryString != null && !queryString.equals("")) { String params[] = queryString.split(queryParameterSeparator); if (params == null || params.length == 0) { return ""; } for (String param : params) { String temp[] = param.split("="); if (temp != null && temp.length >= 1) { if (temp[0].equalsIgnoreCase(localName)) { try { return temp.length > 1 ? URIEncoderDecoder.decode(temp[1]) : ""; } catch (UnsupportedEncodingException e) { String msg = "Couldn't decode the URL parameter " + "value " + temp[1] + " with name " + localName; log.error(msg, e); throw new UnresolvableException( msg + e.getMessage()); } } } } } } } return ""; } else if (SynapseXPathConstants.OPERATION_SCOPE_VARIABLE_PREFIX.equals(prefix)) { Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx; return axis2smc.getAxis2MessageContext().getOperationContext().getProperty(localName); } else if (SynapseXPathConstants.SYSTEM_SCOPE_VARIABLE_PREFIX.equals(prefix)) { String propVal = System.getProperty(localName); if (propVal != null) { return propVal; } else { return ""; } } else { Object o = synCtx.getProperty(prefix); if (o instanceof Map) { Object valueObject = ((Map) o).get(localName); if (valueObject != null) { return valueObject.toString(); } } } } } //try resolving using available custom extensions Object obj = XpathExtensionUtil.resolveVariableContext( synCtx,namespaceURI,prefix,localName); if (obj != null) { return obj; } return parent.getVariableValue(namespaceURI, prefix, localName); } }