blob: ba74df8ede6abe0a58066b9d185ab7e07ddc11e7 [file] [log] [blame]
/*
* 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.transform;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.addressing.RelatesTo;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.SynapseLog;
import org.apache.synapse.config.xml.XMLConfigConstants;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
import org.apache.synapse.util.xpath.SynapseXPath;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The header mediator is able to set a given value as a SOAP header, or remove a given
* header from the current message instance. This supports the headers currently
* supported by the HeaderType class. If an expression is supplied, its runtime value
* is evaluated using the current message. Unless the action is set to remove, the
* default behavior of this mediator is to set a header value.
*/
public class HeaderMediator extends AbstractMediator {
public static final int ACTION_SET = 0;
public static final int ACTION_REMOVE = 1;
/** The qName of the header @see HeaderType */
private QName qName = null;
/** The literal value to be set as the header (if one was specified) */
private String value = null;
/** Set the header (ACTION_SET) or remove it (ACTION_REMOVE). Defaults to ACTION_SET */
private int action = ACTION_SET;
/** Optional embedded XML content of the header element */
private List<OMElement> embeddedXmlContent = new ArrayList<OMElement>();
/** An expression which should be evaluated, and the result set as the header value */
private SynapseXPath expression = null;
/** The scope that decides which header should be updated: SOAP or Transport. */
private String scope = null;
/**
* Sets/Removes a SOAP header on the current message
*
* @param synCtx the current message which is altered as necessary
* @return true always
*/
public boolean mediate(MessageContext synCtx) {
SynapseLog synLog = getLog(synCtx);
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Start : Header mediator");
if (synLog.isTraceTraceEnabled()) {
synLog.traceTrace("Message : " + synCtx.getEnvelope());
}
}
if (XMLConfigConstants.HEADER_SCOPE_TRANSPORT.equals(scope)) {
alterTransportHeader(synCtx);
} else {
alterSOAPOrKnownHeader(synCtx);
}
synLog.traceOrDebug("End : Header mediator");
return true;
}
private void alterSOAPOrKnownHeader(MessageContext synCtx) {
SynapseLog synLog = getLog(synCtx);
if (action == ACTION_SET) {
String value = (getExpression() == null ? getValue() : expression.stringValueOf(synCtx));
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Setting header : " + qName + " to : " + value);
}
if (!isImplicit() &&
(qName.getNamespaceURI() == null || "".equals(qName.getNamespaceURI()))) {
// is this a "well known" Synapse header?
if (SynapseConstants.HEADER_TO.equals(qName.getLocalPart())) {
synCtx.setTo(new EndpointReference(value));
} else if (SynapseConstants.HEADER_FROM.equals(qName.getLocalPart())) {
synCtx.setFrom(new EndpointReference(value));
} else if (SynapseConstants.HEADER_ACTION.equals(qName.getLocalPart())) {
synCtx.setWSAAction(value);
} else if (SynapseConstants.HEADER_FAULT.equals(qName.getLocalPart())) {
synCtx.setFaultTo(new EndpointReference(value));
} else if (SynapseConstants.HEADER_REPLY_TO.equals(qName.getLocalPart())) {
synCtx.setReplyTo(new EndpointReference(value));
} else if (SynapseConstants.HEADER_RELATES_TO.equals(qName.getLocalPart())) {
synCtx.setRelatesTo(new RelatesTo[] { new RelatesTo(value) });
} else {
addCustomHeader(synCtx, value);
}
} else {
addCustomHeader(synCtx, value);
}
} else {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Removing Header : " + qName);
}
if (qName.getNamespaceURI() == null || "".equals(qName.getNamespaceURI())) {
// is this a "well known" Synapse header?
if (SynapseConstants.HEADER_TO.equals(qName.getLocalPart())) {
synCtx.setTo(null);
} else if (SynapseConstants.HEADER_FROM.equals(qName.getLocalPart())) {
synCtx.setFrom(null);
} else if (SynapseConstants.HEADER_ACTION.equals(qName.getLocalPart())) {
synCtx.setWSAAction(null);
} else if (SynapseConstants.HEADER_FAULT.equals(qName.getLocalPart())) {
synCtx.setFaultTo(null);
} else if (SynapseConstants.HEADER_REPLY_TO.equals(qName.getLocalPart())) {
synCtx.setReplyTo(null);
} else if (SynapseConstants.HEADER_RELATES_TO.equals(qName.getLocalPart())) {
synCtx.setRelatesTo(null);
} else {
SOAPEnvelope envelope = synCtx.getEnvelope();
if (envelope != null) {
SOAPHeader header = envelope.getHeader();
if (header != null) {
removeFromHeaderList(header.
getHeaderBlocksWithNSURI(""));
}
}
}
} else {
SOAPEnvelope envelope = synCtx.getEnvelope();
if (envelope != null) {
SOAPHeader header = envelope.getHeader();
if (header != null) {
removeFromHeaderList(header.
getHeaderBlocksWithNSURI(qName.getNamespaceURI()));
}
}
}
}
}
private void alterTransportHeader(MessageContext synCtx) {
SynapseLog synLog = getLog(synCtx);
String headerName = qName.getLocalPart();
String value = (getExpression() == null ? getValue() : expression.stringValueOf(synCtx));
if (action == ACTION_SET) {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Setting Transport header : " + headerName + " to : " + value);
}
//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(headerName, value);
} else if (headers == null) {
Map headersMap = new HashMap();
headersMap.put(headerName, value);
axis2MessageCtx.setProperty(
org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS, headersMap);
}
} else {
if (synLog.isTraceOrDebugEnabled()) {
synLog.traceOrDebug("Removing Transport Header : " + qName);
}
// 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(headerName);
} else {
synLog.traceOrDebug("No transport headers found");
}
}
}
private void addCustomHeader(MessageContext synCtx, String value) {
SOAPEnvelope env = synCtx.getEnvelope();
if (env == null) {
return;
}
SOAPFactory fac = (SOAPFactory) env.getOMFactory();
SOAPHeader header = env.getOrCreateHeader();
if (!isImplicit()) {
SOAPHeaderBlock hb = header.addHeaderBlock(qName.getLocalPart(),
fac.createOMNamespace(qName.getNamespaceURI(), qName.getPrefix()));
hb.setText(value);
} else if (hasEmbeddedXml()) {
for (OMElement e : embeddedXmlContent) {
// Don't attach the original OMElement here.
// If another mediator down the line, changes the OM, we are in trouble.
header.addChild(e.cloneOMElement());
}
}
}
private void removeFromHeaderList(List headersList) {
if (headersList == null || headersList.isEmpty()) {
return;
}
for (Object o : headersList) {
if (o instanceof SOAPHeaderBlock) {
SOAPHeaderBlock header = (SOAPHeaderBlock) o;
if (header.getLocalName().equals(qName.getLocalPart())) {
header.detach();
}
} else if (o instanceof OMElement) {
OMElement omElem = (OMElement) o;
if (omElem.getLocalName().equals(qName.getLocalPart())) {
omElem.detach();
}
}
}
}
public List<OMElement> getEmbeddedXml() {
return embeddedXmlContent;
}
public void addEmbeddedXml(OMElement element) {
if (element != null && !embeddedXmlContent.contains(element)) {
embeddedXmlContent.add(element);
}
}
public boolean hasEmbeddedXml() {
return !embeddedXmlContent.isEmpty();
}
public boolean isImplicit() {
return getQName() == null;
}
public int getAction() {
return action;
}
public void setAction(int action) {
this.action = action;
}
public QName getQName() {
return qName;
}
public void setQName(QName qName) {
this.qName = qName;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public SynapseXPath getExpression() {
return expression;
}
public void setExpression(SynapseXPath expression) {
this.expression = expression;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
@Override
public boolean isContentAware() {
if (XMLConfigConstants.SCOPE_TRANSPORT.equals(scope)) {
return false;
} else {
return true;
}
}
}