/* * 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.ext; import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMNode; import org.apache.synapse.Command; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseLog; import org.apache.synapse.commons.util.PropertyHelper; import org.apache.synapse.mediators.AbstractMediator; import org.apache.synapse.mediators.eip.EIPUtils; import org.apache.synapse.util.xpath.SynapseXPath; import org.jaxen.JaxenException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; /** * This mediator will use the specified command object and execute the command after setting * the properties specified to it through the configuraiton. The specified command object may or * may not implement the Command interface. If the Command object has not implemented the Command * interface then this will use reflection to find a method called execute() and execute it. * * @see org.apache.synapse.Command interface */ public class POJOCommandMediator extends AbstractMediator { /** * This will hold the command object to be executed */ private Class command = null; /** * 'static' properties whose values are constant and does not depend * on the current message (i.e. and XPath over it) */ private final Map<String, Object> staticSetterProperties = new HashMap<String, Object>(); /** * 'dynamic' properties whose values are dynamically evaluated before each * invocation of the command, by evaluating an XPath against the current message */ private final Map<String, SynapseXPath> messageSetterProperties = new HashMap<String, SynapseXPath>(); /** * 'dynamic' properties whose values are dynamically evaluated before each * invocation of the command, by getting a property from the message context */ private final Map<String, String> contextSetterProperties = new HashMap<String, String>(); /** * 'context' properties whose values are set back to the message context as message * context properties */ private final Map<String, String> contextGetterProperties = new HashMap<String, String>(); /** * 'messsage' properties whose values are set back to the current message, from the command * and as specified by the XPATH */ private final Map<String, SynapseXPath> messageGetterProperties = new HashMap<String, SynapseXPath>(); /** * Implements the mediate method of the Mediator interface. This method will instantiate * a new instance of the POJO class, set all specified properties from the current runtime * state (and message context) and call the execute method of the Command object. * * @param synCtx - Synapse MessageContext to be mediated * @return boolean true since this will not stop exection chain */ public boolean mediate(MessageContext synCtx) { if (synCtx.getEnvironment().isDebuggerEnabled()) { if (super.divertMediationRoute(synCtx)) { return true; } } SynapseLog synLog = getLog(synCtx); if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Start : POJOCommand mediator"); if (synLog.isTraceTraceEnabled()) { synLog.traceTrace("Message : " + synCtx.getEnvelope()); } } if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Creating a new instance of POJO class : " + command.getClass()); } Object commandObject = null; try { // instantiate a new command object each time commandObject = command.newInstance(); } catch (Exception e) { handleException("Error creating an instance of the POJO command class : " + command.getClass(), e, synCtx); } synLog.traceOrDebug("Instance created, setting static and dynamic properties"); // then set the static/constant properties first for (String name : staticSetterProperties.keySet()) { PropertyHelper.setInstanceProperty(name, staticSetterProperties.get(name), commandObject); } // now set the any dynamic properties from the message context properties for (String name : contextSetterProperties.keySet()) { PropertyHelper.setInstanceProperty(name, synCtx.getProperty(contextSetterProperties.get(name)), commandObject); } // now set the any dynamic properties evaluating XPath's on the current message for (String name : messageSetterProperties.keySet()) { SynapseXPath xpath = messageSetterProperties.get(name); String value = xpath.stringValueOf(synCtx); PropertyHelper.setInstanceProperty(name, value, commandObject); } synLog.traceOrDebug("POJO initialized successfully, invoking the execute() method"); // then call the execute method if the Command interface is implemented if (commandObject instanceof Command) { try { ((Command) commandObject).execute(); } catch (Exception e) { handleException("Error invoking POJO command class : " + command.getClass(), e, synCtx); } } else { try { Method exeMethod = command.getMethod("execute"); exeMethod.invoke(commandObject); } catch (NoSuchMethodException e) { handleException("Cannot locate an execute() method on POJO class : " + command.getClass(), e, synCtx); } catch (Exception e) { handleException("Error invoking the execute() method on POJO class : " + command.getClass(), e, synCtx); } } // then set the context properties back to the messageContext from the command for (String name : contextGetterProperties.keySet()) { synCtx.setProperty(contextGetterProperties.get(name), getInstanceProperty(name, commandObject, synCtx)); } // now set the any message properties evaluating XPath's on the current message back // to the message from the command for (String name : messageGetterProperties.keySet()) { SynapseXPath xpath = messageGetterProperties.get(name); Object resultValue = getInstanceProperty(name, commandObject, synCtx); try { List list = EIPUtils.getMatchingElements(synCtx.getEnvelope(), xpath); if (list.size() > 0) { Object o = list.get(0); if (resultValue instanceof String) { OMAbstractFactory.getOMFactory().createOMText( ((OMNode) o).getParent(), (String) resultValue); ((OMNode) o).detach(); } else if (resultValue instanceof OMNode) { ((OMNode) o).insertSiblingAfter((OMNode) resultValue); ((OMNode) o).detach(); } } else { if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Unable to set the message property " + resultValue + "back to the message : Specified element by the xpath " + xpath + " can not be found"); } } } catch (JaxenException e) { handleException("Unable to set the command property " + name + " back to the message", e, synCtx); } } synLog.traceOrDebug("End : POJOCommand mediator"); return true; } /** * Find and invoke the getter method with the name of form getXXX and returns the value given * on the POJO object * * @param name name of the getter field * @param obj POJO instance * @param synCtx current message * @return object representing the value of the getter method */ private Object getInstanceProperty(String name, Object obj, MessageContext synCtx) { String mName = "get" + Character.toUpperCase(name.charAt(0)) + name.substring(1); try { Method[] methods = obj.getClass().getMethods(); for (Method method : methods) { if (mName.equals(method.getName())) { return method.invoke(obj); } } } catch(InvocationTargetException e) { handleException("Unable to get the command property '" + name + "' back to the message", e, synCtx); } catch(IllegalAccessException e){ handleException("Unable to get the command property '" + name + "' back to the message", e, synCtx); } return null; } public Class getCommand() { return command; } public void setCommand(Class command) { this.command = command; } public void addStaticSetterProperty(String name, Object value) { this.staticSetterProperties.put(name, value); } public void addMessageSetterProperty(String name, SynapseXPath xpath) { this.messageSetterProperties.put(name, xpath); } public void addContextSetterProperty(String name, String ctxName) { this.contextSetterProperties.put(name, ctxName); } public void addContextGetterProperty(String name, String value) { this.contextGetterProperties.put(name, value); } public void addMessageGetterProperty(String name, SynapseXPath xpath) { this.messageGetterProperties.put(name, xpath); } public Map<String, Object> getStaticSetterProperties() { return this.staticSetterProperties; } public Map<String, SynapseXPath> getMessageSetterProperties() { return this.messageSetterProperties; } public Map<String, String> getContextSetterProperties() { return this.contextSetterProperties; } public Map<String, String> getContextGetterProperties() { return this.contextGetterProperties; } public Map<String, SynapseXPath> getMessageGetterProperties() { return this.messageGetterProperties; } }