| /* |
| * 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.mediators.builtin; |
| |
| import org.apache.http.protocol.HTTP; |
| import org.apache.synapse.MessageContext; |
| import org.apache.synapse.SynapseLog; |
| import org.apache.synapse.SynapseException; |
| import org.apache.synapse.config.xml.XMLConfigConstants; |
| import org.apache.synapse.config.SynapseConfigUtils; |
| import org.apache.synapse.core.axis2.Axis2MessageContext; |
| import org.apache.synapse.mediators.AbstractMediator; |
| import org.apache.synapse.util.xpath.SynapseXPath; |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axis2.util.JavaUtils; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.regex.Pattern; |
| import java.util.regex.Matcher; |
| |
| /** |
| * The property mediator would save(or remove) a named property as a local property of |
| * the Synapse Message Context or as a property of the Axis2 Message Context or |
| * as a Transport Header. |
| * Properties set this way could be extracted through the XPath extension function |
| * "synapse:get-property(scope,prop-name)" |
| */ |
| |
| public class PropertyMediator extends AbstractMediator { |
| |
| /** The Name of the property */ |
| private String name = null; |
| /** The Value to be set */ |
| private Object value = null; |
| /** The data type of the value */ |
| private String type = null; |
| /** The XML value to be set */ |
| private OMElement valueElement = null; |
| /** The XPath expr. to get value */ |
| private SynapseXPath expression = null; |
| /** The scope for which decide properties where to go*/ |
| private String scope = null; |
| /** The Action - set or remove */ |
| public static final int ACTION_SET = 0; |
| public static final int ACTION_REMOVE = 1; |
| /** Set the property (ACTION_SET) or remove it (ACTION_REMOVE). Defaults to ACTION_SET */ |
| private int action = ACTION_SET; |
| |
| /** Regular expression pattern to be evaluated over the property value. |
| * Resulting match string will be applied to the property */ |
| private Pattern pattern; |
| |
| /** A pattern can be matched to several parts of the value. Which one to choose.*/ |
| private int group = 0; |
| |
| /** |
| * Sets a property into the current (local) Synapse Context or into the Axis Message Context |
| * or into Transports Header and removes above properties from the corresponding locations. |
| * |
| * @param synCtx the message context |
| * @return true always |
| */ |
| public boolean mediate(MessageContext synCtx) { |
| |
| SynapseLog synLog = getLog(synCtx); |
| |
| if (synLog.isTraceOrDebugEnabled()) { |
| synLog.traceOrDebug("Start : Property mediator"); |
| |
| if (synLog.isTraceTraceEnabled()) { |
| synLog.traceTrace("Message : " + synCtx.getEnvelope()); |
| } |
| } |
| |
| if (action == ACTION_SET) { |
| |
| Object resultValue = getResultValue(synCtx); |
| |
| // if the result value is a String we can apply a reguar expression to |
| // choose part of it |
| if (resultValue instanceof String && pattern != null) { |
| resultValue = getMatchedValue((String) resultValue, synLog); |
| } |
| |
| if (synLog.isTraceOrDebugEnabled()) { |
| synLog.traceOrDebug("Setting property : " + name + " at scope : " + |
| (scope == null ? "default" : scope) + " to : " + resultValue + " (i.e. " + |
| (value != null ? "constant : " + value : |
| "result of expression : " + expression) + ")"); |
| } |
| |
| if (scope == null || XMLConfigConstants.SCOPE_DEFAULT.equals(scope)) { |
| //Setting property into the Synapse Context |
| synCtx.setProperty(name, resultValue); |
| |
| } else if (XMLConfigConstants.SCOPE_AXIS2.equals(scope) |
| && synCtx instanceof Axis2MessageContext) { |
| //Setting property into the Axis2 Message Context |
| Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx; |
| org.apache.axis2.context.MessageContext axis2MessageCtx = |
| axis2smc.getAxis2MessageContext(); |
| axis2MessageCtx.setProperty(name, resultValue); |
| |
| } else if (XMLConfigConstants.SCOPE_CLIENT.equals(scope) |
| && synCtx instanceof Axis2MessageContext) { |
| //Setting property into the Axis2 Message Context client options |
| Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx; |
| org.apache.axis2.context.MessageContext axis2MessageCtx = |
| axis2smc.getAxis2MessageContext(); |
| axis2MessageCtx.getOptions().setProperty(name, resultValue); |
| |
| } else if (XMLConfigConstants.SCOPE_TRANSPORT.equals(scope) |
| && synCtx instanceof Axis2MessageContext) { |
| //Setting Transport Headers |
| Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx; |
| org.apache.axis2.context.MessageContext axis2MessageCtx = |
| axis2smc.getAxis2MessageContext(); |
| Object headers = axis2MessageCtx.getProperty( |
| org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); |
| |
| if (headers != null && headers instanceof Map) { |
| Map headersMap = (Map) headers; |
| headersMap.put(name, resultValue); |
| } |
| if (headers == null) { |
| Map headersMap = new HashMap(); |
| headersMap.put(name, resultValue); |
| axis2MessageCtx.setProperty( |
| org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS, |
| headersMap); |
| } |
| } |
| |
| } else { |
| if (synLog.isTraceOrDebugEnabled()) { |
| synLog.traceOrDebug("Removing property : " + name + |
| " (scope:" + (scope == null ? "default" : scope) + ")"); |
| } |
| |
| if (scope == null || XMLConfigConstants.SCOPE_DEFAULT.equals(scope)) { |
| //Removing property from the Synapse Context |
| Set pros = synCtx.getPropertyKeySet(); |
| if (pros != null) { |
| pros.remove(name); |
| } |
| |
| } else if ((XMLConfigConstants.SCOPE_AXIS2.equals(scope) || |
| XMLConfigConstants.SCOPE_CLIENT.equals(scope)) |
| && synCtx instanceof Axis2MessageContext) { |
| |
| //Removing property from the Axis2 Message Context |
| Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx; |
| org.apache.axis2.context.MessageContext axis2MessageCtx = |
| axis2smc.getAxis2MessageContext(); |
| axis2MessageCtx.removeProperty(name); |
| |
| } else if (XMLConfigConstants.SCOPE_TRANSPORT.equals(scope) |
| && synCtx instanceof Axis2MessageContext) { |
| // Removing transport headers |
| Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx; |
| org.apache.axis2.context.MessageContext axis2MessageCtx = |
| axis2smc.getAxis2MessageContext(); |
| Object headers = axis2MessageCtx.getProperty( |
| org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); |
| if (headers != null && headers instanceof Map) { |
| Map headersMap = (Map) headers; |
| headersMap.remove(name); |
| } else { |
| synLog.traceOrDebug("No transport headers found for the message"); |
| } |
| } |
| } |
| synLog.traceOrDebug("End : Property mediator"); |
| return true; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public Object getValue() { |
| return value; |
| } |
| |
| public void setValue(String value) { |
| setValue(value, null); |
| } |
| |
| /** |
| * Set the value to be set by this property mediator and the data type |
| * to be used when setting the value. Accepted type names are defined in |
| * XMLConfigConstants.DATA_TYPES enumeration. Passing null as the type |
| * implies that 'STRING' type should be used. |
| * |
| * @param value the value to be set as a string |
| * @param type the type name |
| */ |
| public void setValue(String value, String type) { |
| this.type = type; |
| // Convert the value into specified type |
| this.value = convertValue(value, type); |
| } |
| |
| public String getType() { |
| return type; |
| } |
| |
| public OMElement getValueElement() { |
| return valueElement; |
| } |
| |
| public void setValueElement(OMElement valueElement) { |
| this.valueElement = valueElement; |
| } |
| |
| public SynapseXPath getExpression() { |
| return expression; |
| } |
| |
| public void setExpression(SynapseXPath expression) { |
| setExpression(expression, null); |
| } |
| |
| public void setExpression(SynapseXPath expression, String type) { |
| this.expression = expression; |
| // Save the type information for now |
| // We need to convert the result of the expression into this type during mediation |
| // A null type would imply 'STRING' type |
| this.type = type; |
| } |
| |
| public String getScope() { |
| return scope; |
| } |
| |
| public void setScope(String scope) { |
| this.scope = scope; |
| } |
| |
| public int getAction() { |
| return action; |
| } |
| |
| public void setAction(int action) { |
| this.action = action; |
| } |
| |
| public Pattern getPattern() { |
| return pattern; |
| } |
| |
| public void setPattern(Pattern pattern) { |
| this.pattern = pattern; |
| } |
| |
| public int getGroup() { |
| return group; |
| } |
| |
| public void setGroup(int group) { |
| this.group = group; |
| } |
| |
| private Object getResultValue(MessageContext synCtx) { |
| if (value != null) { |
| return value; |
| } else if (valueElement != null) { |
| // Need to take a clone of the element, otherwise same reference is shared across all the requests |
| return valueElement.cloneOMElement(); |
| } else { |
| return convertValue(expression.stringValueOf(synCtx), type); |
| } |
| } |
| |
| private Object convertValue(String value, String type) { |
| if (type == null) { |
| // If no type is set we simply return the string value |
| return value; |
| } |
| |
| try { |
| XMLConfigConstants.DATA_TYPES dataType = XMLConfigConstants.DATA_TYPES.valueOf(type); |
| switch (dataType) { |
| case BOOLEAN : return JavaUtils.isTrueExplicitly(value); |
| case DOUBLE : return Double.parseDouble(value); |
| case FLOAT : return Float.parseFloat(value); |
| case INTEGER : return Integer.parseInt(value); |
| case LONG : return Long.parseLong(value); |
| case OM : return SynapseConfigUtils.stringToOM(value); |
| case SHORT : return Short.parseShort(value); |
| default : return value; |
| } |
| } catch (IllegalArgumentException e) { |
| String msg = "Unknown type : " + type + " for the property mediator or the " + |
| "property value cannot be converted into the specified type."; |
| log.error(msg, e); |
| throw new SynapseException(msg, e); |
| } |
| } |
| |
| /** |
| * Apply the Regular expression on to the String value and choose the matching group. |
| * If a matching not found same string passed in to this method will be returned. |
| * If a pattern is not specified same String passed to this method will be retured. |
| * |
| * @param value String value against the regular expression is matched |
| * @param synLog log |
| * @return the matched string group |
| */ |
| private String getMatchedValue(String value, SynapseLog synLog) { |
| |
| String matchedValue = value; |
| // if we cannot find a match set the value to empty string |
| Matcher matcher = pattern.matcher(value); |
| if (matcher.matches()) { |
| |
| if (matcher.groupCount() >= group) { |
| matchedValue = matcher.group(group); |
| } else { |
| if (synLog.isTraceOrDebugEnabled()) { |
| String msg = "Failed to get a match for regx : " + |
| pattern.toString() + " with the property value :" + |
| value + " for group :" + group; |
| synLog.traceOrDebug(msg); |
| } |
| } |
| |
| } else { |
| if (synLog.isTraceOrDebugEnabled()) { |
| String msg = "Unable to find a match for regx : " + |
| pattern.toString() + " with the property value :" + value; |
| synLog.traceOrDebug(msg); |
| } |
| matchedValue = ""; //if not matched ideally should return empty string |
| } |
| |
| return matchedValue; |
| } |
| |
| @Override |
| public boolean isContentAware() { |
| if (expression != null) { |
| return expression.isContentAware(); |
| } |
| |
| boolean contentAware = false; |
| if (XMLConfigConstants.SCOPE_AXIS2.equals(scope)) { |
| //the logic will determine the content-aware true |
| if (org.apache.axis2.Constants.Configuration.MESSAGE_TYPE.equals(name)) { |
| contentAware = true; |
| } |
| |
| } else if (XMLConfigConstants.SCOPE_TRANSPORT.equals(scope)) { |
| //the logic will determine the content-aware true |
| if (HTTP.CONTENT_ENCODING.equals(name)) { |
| contentAware = true; |
| } |
| } |
| return contentAware; |
| } |
| } |