/*
* 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.startup.tasks;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.engine.AxisEngine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.ManagedLifecycle;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseException;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.core.axis2.Axis2SynapseEnvironment;
import org.apache.synapse.mediators.MediatorFaultHandler;
import org.apache.synapse.mediators.base.SequenceMediator;
import org.apache.synapse.task.Task;
import org.apache.synapse.util.PayloadHelper;
import javax.xml.stream.XMLStreamException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Injects a Message into a named sequence or a proxy service configured in the Synapse
* mediation engine. By default this task implementation will inject messages into the
* main sequence.
*/
public class MessageInjector implements Task, ManagedLifecycle {
/**
* Holds the logger for logging purposes
*/
private Log log = LogFactory.getLog(MessageInjector.class);
/**
* Holds the Message to be injected
*/
private OMElement message = null;
/**
* Holds the to address for the message to be injected
*/
private String to = null;
/**
* Could be one of either "soap11" | "soap12" | "pox" | "get"
*/
private String format = null;
/**
* SOAPAction of the message to be set, in case of the format is soap11
*/
private String soapAction = null;
/**
* Holds the SynapseEnv to which the message will be injected
*/
private SynapseEnvironment synapseEnvironment;
public final static String SOAP11_FORMAT = "soap11";
public final static String SOAP12_FORMAT = "soap12";
public final static String POX_FORMAT = "pox";
public final static String GET_FORMAT = "get";
private final static String INJECT_TO_PROXY = "proxy";
private final static String INJECT_TO_SEQUENCE = "sequence";
private final static String INJECT_TO_MAIN_SEQ = "main";
/**
* Artifact type which message should be injected
* Could be one of "proxy" | "sequence" | "main"
*/
private String injectTo = INJECT_TO_MAIN_SEQ;
/**
* Name of the sequence which message should be injected
*/
private String sequenceName = null;
/**
* Name of the proxy service which message should be injected
*/
private String proxyName = null;
/**
* Registry path for message to inject
*/
private String registryKey = null;
/**
* Store additional properties required at the runtime
*/
private Map<String, Object> runtimeProperties = null;
/**
* Initializes the Injector
*
* @param se
* SynapseEnvironment of synapse
*/
public void init(SynapseEnvironment se) {
synapseEnvironment = se;
runtimeProperties = new HashMap<String, Object>();
}
/**
* Set the message to be injected
*
* @param elem
* OMElement describing the message
*/
public void setMessage(OMElement elem) {
log.debug("set message " + elem.toString());
message = elem;
}
/**
* Set the to address of the message to be injected
*
* @param url
* String containing the to address
*/
public void setTo(String url) {
to = url;
}
/**
* Sets the format of the message
*
* @param format could be one of either "soap11" | "soap12" | "pox" | "get"
*/
public void setFormat(String format) {
this.format = format;
}
/**
* Sets the SOAPAction and valid only when the format is given as soap11
*
* @param soapAction SOAPAction header value to be set
*/
public void setSoapAction(String soapAction) {
this.soapAction = soapAction;
}
/**
* Artifact type which message should be injected
* @param injectTo Could be one of "proxy" | "sequence" | "main"
*/
public void setInjectTo(String injectTo) {
this.injectTo = injectTo;
}
/**
* Set name of the sequence which message should be injected
* @param sequenceName sequence name
*/
public void setSequenceName(String sequenceName) {
this.sequenceName = sequenceName;
}
/**
* Set name of the proxy service which message should be injected
* @param proxyName proxy service name
*/
public void setProxyName(String proxyName) {
this.proxyName = proxyName;
}
public String getRegistryKey() {
return registryKey;
}
public void setRegistryKey(String registryKey) {
this.registryKey = registryKey;
}
/**
* Set a property to be used at runtime. These properties will get inserted in message context created
* at here
*
* @param key Key of the property
* @param value Value of the property
*/
public void addRuntimeProperty(String key, Object value) {
if (runtimeProperties.get(key) != null && log.isDebugEnabled()) {
log.debug("Key :" + key + " will be override.");
}
runtimeProperties.put(key, value);
}
/**
* Get a property stored for runtime use
*
* @param key Key of the property to retrieve
* @return Value of the property. If property does not exists, this will throw NullPointerException
*/
public Object getRuntimeProperty(String key) throws NullPointerException {
return runtimeProperties.get(key);
}
/**
* This will be invoked by the scheduler to inject the message
* in to the SynapseEnvironment
*/
public void execute() {
if (log.isDebugEnabled()) {
log.debug("execute");
}
if (synapseEnvironment == null) {
handleError("Synapse Environment not set");
return;
}
if(synapseEnvironment.getTaskManager() != null && !synapseEnvironment.getTaskManager().isInitialized()){
log.warn("Task Manager not initialized. Not executing the cycle");
return;
}
if (message == null && registryKey == null) {
handleError("message or registry-key not set");
return;
}
if (INJECT_TO_PROXY.equalsIgnoreCase(injectTo)) {
if (proxyName == null || proxyName.equals("")) {
handleError("Proxy service name not specified");
}
// Prepare axis2 message context
org.apache.axis2.context.MessageContext axis2MsgCtx =
new org.apache.axis2.context.MessageContext();
ConfigurationContext configurationContext = ((Axis2SynapseEnvironment) synapseEnvironment).
getAxis2ConfigurationContext();
axis2MsgCtx.setConfigurationContext(configurationContext);
axis2MsgCtx.setIncomingTransportName(Constants.TRANSPORT_LOCAL);
axis2MsgCtx.setServerSide(true);
axis2MsgCtx.setMessageID(UIDGenerator.generateURNString());
try {
AxisService axisService = configurationContext.getAxisConfiguration().
getService(proxyName);
if (axisService == null) {
handleError("Proxy Service: " + proxyName + " not found");
}
axis2MsgCtx.setAxisService(axisService);
} catch (AxisFault axisFault) {
handleError("Error occurred while attempting to find the Proxy Service");
}
if (to != null) {
axis2MsgCtx.setTo(new EndpointReference(to));
}
SOAPEnvelope envelope = null;
if (format == null) {
envelope = OMAbstractFactory.getSOAP12Factory().createSOAPEnvelope();
} else if (SOAP11_FORMAT.equalsIgnoreCase(format)) {
envelope = OMAbstractFactory.getSOAP11Factory().createSOAPEnvelope();
} else if (SOAP12_FORMAT.equalsIgnoreCase(format)) {
envelope = OMAbstractFactory.getSOAP12Factory().createSOAPEnvelope();
} else if (POX_FORMAT.equalsIgnoreCase(format)) {
envelope = OMAbstractFactory.getSOAP12Factory().createSOAPEnvelope();
axis2MsgCtx.setDoingREST(true);
} else if (GET_FORMAT.equalsIgnoreCase(format)) {
envelope = OMAbstractFactory.getSOAP12Factory().createSOAPEnvelope();
axis2MsgCtx.setDoingREST(true);
axis2MsgCtx.setProperty(Constants.Configuration.HTTP_METHOD,
Constants.Configuration.HTTP_METHOD_GET);
} else {
handleError("incorrect format specified");
}
try {
PayloadHelper.setXMLPayload(envelope, message.cloneOMElement());
axis2MsgCtx.setEnvelope(envelope);
} catch (AxisFault axisFault) {
handleError("Error in setting the message payload : " + message);
}
if (soapAction != null) {
axis2MsgCtx.setSoapAction(soapAction);
}
try {
if (log.isDebugEnabled()) {
log.debug("injecting message to proxy service : " + proxyName);
}
AxisEngine.receive(axis2MsgCtx);
} catch (AxisFault axisFault) {
handleError("Error occurred while invoking proxy service : " + proxyName);
}
} else {
MessageContext mc = synapseEnvironment.createMessageContext();
mc.setMessageID(UIDGenerator.generateURNString());
mc.pushFaultHandler(new MediatorFaultHandler(mc.getFaultSequence()));
if (to != null) {
mc.setTo(new EndpointReference(to));
}
if (registryKey == null) {
if (format == null) {
PayloadHelper.setXMLPayload(mc, message.cloneOMElement());
} else {
try {
if (SOAP11_FORMAT.equalsIgnoreCase(format)) {
mc.setEnvelope(OMAbstractFactory.getSOAP11Factory().createSOAPEnvelope());
} else if (SOAP12_FORMAT.equalsIgnoreCase(format)) {
mc.setEnvelope(OMAbstractFactory.getSOAP12Factory().createSOAPEnvelope());
} else if (POX_FORMAT.equalsIgnoreCase(format)) {
mc.setDoingPOX(true);
} else if (GET_FORMAT.equalsIgnoreCase(format)) {
mc.setDoingGET(true);
}
PayloadHelper.setXMLPayload(mc, message.cloneOMElement());
} catch (AxisFault axisFault) {
handleError("Error in setting the message payload : " + message);
}
}
} else {
Object entry = mc.getEntry(registryKey);
if (entry == null) {
handleError("Key " + registryKey + " not found ");
}
String text = "";
if (entry instanceof OMElement) {
OMElement e = (OMElement) entry;
removeIndentations(e);
text = e.toString();
} else if (entry instanceof OMText) {
text = ((OMText) entry).getText();
} else if (entry instanceof String) {
text = (String) entry;
}
OMElement omXML = null;
try {
omXML = AXIOMUtil.stringToOM(text);
if (format == null) {
PayloadHelper.setXMLPayload(mc, omXML);
} else {
if (SOAP11_FORMAT.equalsIgnoreCase(format)) {
mc.setEnvelope(OMAbstractFactory.getSOAP11Factory().createSOAPEnvelope());
} else if (SOAP12_FORMAT.equalsIgnoreCase(format)) {
mc.setEnvelope(OMAbstractFactory.getSOAP12Factory().createSOAPEnvelope());
} else if (POX_FORMAT.equalsIgnoreCase(format)) {
mc.setDoingPOX(true);
} else if (GET_FORMAT.equalsIgnoreCase(format)) {
mc.setDoingGET(true);
}
PayloadHelper.setXMLPayload(mc, omXML);
}
} catch (XMLStreamException e) {
handleError("Error parsing XML for JSON conversion, please check your property values return valid XML");
} catch (AxisFault axisFault) {
handleError("Error in setting the message payload : " + omXML);
}
}
if (soapAction != null) {
mc.setSoapAction(soapAction);
}
// Adding runtime properties to SynapseMessageContext, if exists
if (runtimeProperties != null && runtimeProperties.size()>0) {
for (Map.Entry<String, Object> entry : runtimeProperties.entrySet()) {
mc.setProperty(entry.getKey(), entry.getValue());
}
}
if (INJECT_TO_SEQUENCE.equalsIgnoreCase(injectTo)) {
if (sequenceName == null || sequenceName.equals("")) {
handleError("Sequence name not specified");
}
SequenceMediator seq = (SequenceMediator) synapseEnvironment.getSynapseConfiguration().
getSequence(sequenceName);
if (seq != null) {
if (log.isDebugEnabled()) {
log.debug("injecting message to sequence : " + sequenceName);
}
mc.pushFaultHandler(new MediatorFaultHandler(mc.getFaultSequence()));
synapseEnvironment.injectAsync(mc, seq);
} else {
handleError("Sequence: " + sequenceName + " not found");
}
} else {
if (log.isDebugEnabled()) {
log.debug("injecting message to main sequence");
}
synapseEnvironment.injectMessage(mc);
}
}
}
/**
* Destroys the Injector
*/
public void destroy() {
}
/**
* Log the error and throws a SynapseException
* @param msg the log message
*/
private void handleError(String msg) {
log.error(msg);
throw new SynapseException(msg);
}
/**
* Helper function to remove indentations.
* @param element
*/
private void removeIndentations(OMElement element) {
List<OMText> removables = new ArrayList<OMText>();
removeIndentations(element, removables);
for (OMText node : removables) {
node.detach();
}
}
/**
* Helper function to remove indentations.
* @param element
* @param removables
*/
private void removeIndentations(OMElement element, List<OMText> removables) {
Iterator children = element.getChildren();
while (children.hasNext()) {
Object next = children.next();
if (next instanceof OMText) {
OMText text = (OMText) next;
if (text.getText().trim().equals("")) {
removables.add(text);
}
} else if (next instanceof OMElement) {
removeIndentations((OMElement) next, removables);
}
}
}
}