/* * Copyright (c) 2012, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * Licensed 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.wso2.carbon.humantask.core.integration.utils; import org.apache.axis2.AxisFault; import org.apache.axis2.client.OperationClient; import org.apache.axis2.client.Options; import org.apache.axis2.client.ServiceClient; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.MessageContext; import org.apache.axis2.context.ServiceContext; import org.apache.axis2.context.ServiceGroupContext; import org.apache.axis2.description.AxisOperation; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.AxisServiceGroup; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.bpel.common.CollectionsX; import javax.wsdl.*; import javax.wsdl.extensions.http.HTTPAddress; import javax.wsdl.extensions.soap.SOAPAddress; import javax.wsdl.extensions.soap.SOAPOperation; import javax.wsdl.extensions.soap12.SOAP12Address; import javax.wsdl.extensions.soap12.SOAP12Operation; import javax.xml.namespace.QName; /** * This class contains utility functions used by HumanTask Axis integration Layer to create, * and configure AxisServices. */ public final class AxisServiceUtils { private static Log log = LogFactory.getLog(AxisServiceUtils.class); public static final String WS_ADDRESSING_NS = "http://www.w3.org/2005/08/addressing"; public static final String WS_ADDRESSING_NS2 = "http://www.w3.org/2006/05/addressing/wsdl"; public static final String WS_ADDRESSING_NS3 = "http://www.w3.org/2006/02/addressing/wsdl"; public static final String WS_ADDRESSING_NS4 = "http://schemas.xmlsoap.org/ws/2004/08/addressing"; private AxisServiceUtils() { } public static void invokeService(ServiceInvocationContext partnerInvocationContext, ConfigurationContext configContext) throws AxisFault { //TODO check for one-way MessageContext mctx = partnerInvocationContext.getInMessageContext(); OperationClient opClient = getOperationClient(partnerInvocationContext, configContext); mctx.getOptions().setParent(opClient.getOptions()); /* Else we assume that the epr is not changed by the process. In this case there's a limitation we cannot invoke the epr in the wsdl (by assigning that epr by partnerlink assign) if there is a endpoint configuration available for that particular service */ opClient.addMessageContext(mctx); Options operationOptions = opClient.getOptions(); if (partnerInvocationContext.getUep().isAddressingEnabled()) { //Currently we set the action manually, but this should be handled by // addressing module it-self? String action = getAction(partnerInvocationContext); if (log.isDebugEnabled()) { log.debug("Soap action: " + action); } operationOptions.setAction(action); //TODO set replyto as well //operationOptions.setReplyTo(mctx.getReplyTo()); } operationOptions.setTo(partnerInvocationContext.getUep()); opClient.execute(true); } private static OperationClient getOperationClient(ServiceInvocationContext partnerMessageContext, ConfigurationContext clientConfigCtx) throws AxisFault { AxisService anonymousService = AnonymousServiceFactory.getAnonymousService(partnerMessageContext.getService(), partnerMessageContext.getPort(), clientConfigCtx.getAxisConfiguration(), partnerMessageContext.getCaller()); anonymousService.engageModule(clientConfigCtx.getAxisConfiguration().getModule("UEPModule")); anonymousService.getParent().addParameter( "hiddenService", "true"); ServiceGroupContext sgc = new ServiceGroupContext( clientConfigCtx, (AxisServiceGroup) anonymousService.getParent()); ServiceContext serviceCtx = sgc.getServiceContext(anonymousService); // get a reference to the DYNAMIC operation of the Anonymous Axis2 service AxisOperation axisAnonymousOperation = anonymousService.getOperation( partnerMessageContext.isTwoWay() ? ServiceClient.ANON_OUT_IN_OP : ServiceClient.ANON_OUT_ONLY_OP); Options clientOptions = cloneOptions(partnerMessageContext.getInMessageContext().getOptions()); clientOptions.setExceptionToBeThrownOnSOAPFault(false); /* This value doesn't overrideend point config. */ clientOptions.setTimeOutInMilliSeconds(60000); return axisAnonymousOperation.createClient(serviceCtx, clientOptions); } /** * Extracts the action to be used for the given operation. It first checks to see * if a value is specified using WS-Addressing in the portType, it then falls back onto * getting it from the SOAP Binding. * * @param partnerMessageContext BPELMessageContext * @return The action value for the specified operation */ public static String getAction(ServiceInvocationContext partnerMessageContext) { String action = getWSAInputAction(partnerMessageContext); if (action == null || "".equals(action)) { action = getSoapAction(partnerMessageContext); } return action; } /** * Attempts to extract the WS-Addressing "Action" attribute value from the operation definition. * When WS-Addressing is being used by a service provider, the "Action" is specified in the * portType->operation instead of the SOAP binding->operation. * * @param partnerMessageContext BPELMessageContext * @return the SOAPAction value if one is specified, otherwise empty string */ public static String getWSAInputAction(ServiceInvocationContext partnerMessageContext) { BindingOperation bop = partnerMessageContext.getWsdlBindingForCurrentMessageFlow() .getBindingOperation(partnerMessageContext.getOperationName(), null, null); if (bop == null) { return ""; } Input input = bop.getOperation().getInput(); if (input != null) { Object action = input.getExtensionAttribute(new QName(WS_ADDRESSING_NS, "Action")); if (action instanceof String) { return ((String) action); } action = input.getExtensionAttribute(new QName(WS_ADDRESSING_NS2, "Action")); if (action instanceof String) { return ((String) action); } action = input.getExtensionAttribute(new QName(WS_ADDRESSING_NS3, "Action")); if (action instanceof String) { return ((String) action); } action = input.getExtensionAttribute(new QName(WS_ADDRESSING_NS4, "Action")); if (action instanceof QName) { return ((QName) action).getLocalPart(); } } return ""; } /** * Attempts to extract the SOAP Action is defined in the WSDL document. * * @param partnerMessageContext BPELMessageContext * @return the SOAPAction value if one is specified, otherwise empty string */ public static String getSoapAction(ServiceInvocationContext partnerMessageContext) { BindingOperation bop = partnerMessageContext.getWsdlBindingForCurrentMessageFlow(). getBindingOperation(partnerMessageContext.getOperationName(), null, null); if (bop == null) { return ""; } if (partnerMessageContext.isSoap12()) { for (SOAP12Operation soapOp : CollectionsX.filter(bop.getExtensibilityElements(), SOAP12Operation.class)) { return soapOp.getSoapActionURI(); } } else { for (SOAPOperation soapOp : CollectionsX.filter(bop.getExtensibilityElements(), SOAPOperation.class)) { return soapOp.getSoapActionURI(); } } return ""; } /** * Clones the given {@link org.apache.axis2.client.Options} object. This is not a deep copy * because this will be called for each and every message going out from synapse. The parent * of the cloning options object is kept as a reference. * * @param options clonning object * @return clonned Options object */ public static Options cloneOptions(Options options) { // create new options object and set the parent Options clonedOptions = new Options(options.getParent()); // copy general options clonedOptions.setCallTransportCleanup(options.isCallTransportCleanup()); clonedOptions.setExceptionToBeThrownOnSOAPFault(options.isExceptionToBeThrownOnSOAPFault()); clonedOptions.setManageSession(options.isManageSession()); clonedOptions.setSoapVersionURI(options.getSoapVersionURI()); clonedOptions.setTimeOutInMilliSeconds(options.getTimeOutInMilliSeconds()); clonedOptions.setUseSeparateListener(options.isUseSeparateListener()); // copy transport related options clonedOptions.setListener(options.getListener()); clonedOptions.setTransportIn(options.getTransportIn()); clonedOptions.setTransportInProtocol(options.getTransportInProtocol()); clonedOptions.setTransportOut(clonedOptions.getTransportOut()); // copy username and password options clonedOptions.setUserName(options.getUserName()); clonedOptions.setPassword(options.getPassword()); // cloen the property set of the current options object for (Object o : options.getProperties().keySet()) { String key = (String) o; clonedOptions.setProperty(key, options.getProperty(key)); } return clonedOptions; } /** * Get the EPR of this service from the WSDL. * * @param wsdlDef WSDL Definition * @param serviceName service name * @param portName port name * @return XML representation of the EPR */ public static String getEPRfromWSDL( final Definition wsdlDef, final QName serviceName, final String portName) { Service serviceDef = wsdlDef.getService(serviceName); if (serviceDef != null) { Port portDef = serviceDef.getPort(portName); if (portDef != null) { for (Object extElmt : portDef.getExtensibilityElements()) { if (extElmt instanceof SOAPAddress) { return ((SOAPAddress) extElmt).getLocationURI(); } else if (extElmt instanceof HTTPAddress) { return ((HTTPAddress) extElmt).getLocationURI(); } else if (extElmt instanceof SOAP12Address) { return ((SOAP12Address) extElmt).getLocationURI(); } } } } return null; } }