| /* |
| * Copyright (C) 2003 The University of Manchester |
| * |
| * Modifications to the initial code base are copyright of their |
| * respective authors, or their employers as appropriate. Authorship |
| * of the modifications may be determined from the ChangeLog placed at |
| * the end of this file. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public License |
| * as published by the Free Software Foundation; either version 2.1 of |
| * the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
| * USA. |
| * |
| **************************************************************** |
| * Source code information |
| * ----------------------- |
| * Filename $RCSfile: WSDLSOAPInvoker.java,v $ |
| * Revision $Revision: 1.7 $ |
| * Release status $State: Exp $ |
| * Last modified on $Date: 2008/08/28 19:39:28 $ |
| * by $Author: stain $ |
| * Created on 07-Apr-2006 |
| *****************************************************************/ |
| package net.sf.taverna.wsdl.soap; |
| |
| import java.io.BufferedInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.activation.DataHandler; |
| import javax.wsdl.WSDLException; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.rpc.ServiceException; |
| import javax.xml.soap.SOAPException; |
| |
| import net.sf.taverna.wsdl.parser.UnknownOperationException; |
| import net.sf.taverna.wsdl.parser.WSDLParser; |
| |
| import org.apache.axis.AxisFault; |
| import org.apache.axis.EngineConfiguration; |
| import org.apache.axis.attachments.AttachmentPart; |
| import org.apache.axis.client.Call; |
| import org.apache.axis.message.SOAPBodyElement; |
| import org.apache.axis.message.SOAPEnvelope; |
| import org.apache.axis.message.SOAPHeaderElement; |
| import org.apache.axis.transport.http.HTTPTransport; |
| import org.apache.log4j.Logger; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * Invoke SOAP based webservices |
| * |
| * @author Stuart Owen |
| * |
| */ |
| @SuppressWarnings("unchecked") |
| public class WSDLSOAPInvoker { |
| |
| private static final String ATTACHMENT_LIST = "attachmentList"; |
| private BodyBuilderFactory bodyBuilderFactory = BodyBuilderFactory.instance(); |
| private WSDLParser parser; |
| private String operationName; |
| private List<String> outputNames; |
| |
| private static Logger logger = Logger.getLogger(WSDLSOAPInvoker.class); |
| |
| public WSDLSOAPInvoker(WSDLParser parser, String operationName, |
| List<String> outputNames) { |
| this.parser = parser; |
| this.operationName = operationName; |
| this.outputNames = outputNames; |
| } |
| |
| protected String getOperationName() { |
| return operationName; |
| } |
| |
| protected WSDLParser getParser() { |
| return parser; |
| } |
| |
| protected List<String> getOutputNames() { |
| return outputNames; |
| } |
| |
| |
| /** |
| * Invokes the webservice with the supplied input Map, and returns a Map |
| * containing the outputs, mapped against their output names. |
| * |
| * @param inputMap |
| * @return |
| * @throws Exception |
| */ |
| public Map<String, Object> invoke(Map inputMap) throws Exception { |
| return invoke(inputMap, (EngineConfiguration)null); |
| } |
| |
| /** |
| * Invokes the webservice with the supplied input Map and axis engine configuration, |
| * and returns a Map containing the outputs, mapped against their output names. |
| */ |
| public Map<String, Object> invoke(Map inputMap, EngineConfiguration config) |
| throws Exception { |
| |
| Call call = getCall(config); |
| return invoke(inputMap, call); |
| } |
| |
| /** |
| * Invokes the webservice with the supplied input Map and preconfigured axis call, |
| * and returns a Map containing the outputs, mapped against their output names. |
| */ |
| public Map<String, Object> invoke(Map inputMap, Call call) |
| throws Exception { |
| |
| call.setTimeout(getTimeout()); |
| |
| SOAPEnvelope requestEnv = makeRequestEnvelope(inputMap); |
| // logger.info("Invoking service with SOAP envelope:\n"+requestEnv); |
| |
| SOAPEnvelope responseEnv = invokeCall(call, requestEnv); |
| |
| // logger.info("Received SOAP response:\n"+responseEnv); |
| |
| Map<String, Object> result; |
| if (responseEnv == null) { |
| if (outputNames.size() == 1 |
| && outputNames.get(0).equals(ATTACHMENT_LIST)) { |
| // Could be axis 2 service with no output (TAV-617) |
| result = new HashMap<String, Object>(); |
| } else { |
| throw new IllegalStateException( |
| "Missing expected outputs from service"); |
| } |
| } else { |
| List response = responseEnv.getBodyElements(); |
| // logger.info("SOAP response was:" + response); |
| SOAPResponseParser parser = SOAPResponseParserFactory |
| .instance() |
| .create( |
| response, |
| getUse(), |
| getStyle(), |
| this.parser |
| .getOperationOutputParameters(operationName)); |
| result = parser.parse(response); |
| } |
| |
| result.put(ATTACHMENT_LIST, extractAttachments(call)); |
| |
| return result; |
| } |
| |
| protected SOAPEnvelope makeRequestEnvelope(Map inputMap) |
| throws UnknownOperationException, IOException, WSDLException, |
| ParserConfigurationException, SOAPException, SAXException { |
| |
| SOAPEnvelope requestEnv = new SOAPEnvelope(); |
| for (SOAPHeaderElement headerElement : makeSoapHeaders()) { |
| requestEnv.addHeader(headerElement); |
| } |
| requestEnv.addBodyElement(makeSoapBody(inputMap)); |
| return requestEnv; |
| } |
| |
| protected List<SOAPHeaderElement> makeSoapHeaders() { |
| return Collections.emptyList(); |
| } |
| |
| protected SOAPBodyElement makeSoapBody(Map inputMap) |
| throws UnknownOperationException, IOException, WSDLException, |
| ParserConfigurationException, SOAPException, SAXException { |
| BodyBuilder builder = bodyBuilderFactory.create(parser, |
| operationName, |
| parser.getOperationInputParameters(operationName)); |
| return builder.build(inputMap); |
| } |
| |
| protected SOAPEnvelope invokeCall(Call call, SOAPEnvelope requestEnv) throws AxisFault { |
| return call.invoke(requestEnv); |
| } |
| |
| /** |
| * Reads the property taverna.wsdl.timeout, default to 5 minutes if missing. |
| * |
| * @return |
| */ |
| protected Integer getTimeout() { |
| int result = 300000; |
| String minutesStr = System.getProperty("taverna.wsdl.timeout"); |
| |
| if (minutesStr == null) { |
| // using default of 5 minutes |
| return result; |
| } |
| try { |
| int minutes = Integer.parseInt(minutesStr.trim()); |
| result = minutes * 1000 * 60; |
| } catch (NumberFormatException e) { |
| logger.error("Non-integer timeout", e); |
| return result; |
| } |
| return result; |
| } |
| |
| protected String getStyle() { |
| return parser.getStyle(); |
| } |
| |
| protected String getUse() throws UnknownOperationException { |
| return parser.getUse(operationName); |
| } |
| |
| /** |
| * Returns an axis based Call, initialised for the operation that needs to |
| * be invoked |
| * |
| * @return |
| * @throws ServiceException |
| * @throws UnknownOperationException |
| * @throws MalformedURLException |
| * @throws WSDLException |
| * @throws WSIFException |
| */ |
| protected Call getCall(EngineConfiguration config) throws ServiceException, UnknownOperationException, MalformedURLException { |
| |
| org.apache.axis.client.Service service; |
| if (config==null) { |
| service = new org.apache.axis.client.Service(); |
| } |
| else { |
| service = new org.apache.axis.client.Service(config); |
| } |
| |
| Call call = new Call(service); |
| |
| call.setTransport(new HTTPTransport()); |
| call.setTargetEndpointAddress(parser.getOperationEndpointLocations(operationName).get(0)); |
| //result.setPortName(parser.getPortType(operationName).getQName()); |
| //result.setOperation(operationName); |
| |
| String use = parser.getUse(operationName); |
| call.setUseSOAPAction(true); |
| call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, |
| Boolean.FALSE); |
| call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, |
| Boolean.FALSE); |
| call |
| .setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS); |
| |
| if (parser.getSOAPActionURI(operationName)!=null) { |
| call.setSOAPActionURI(parser.getSOAPActionURI(operationName)); |
| } |
| |
| if (use.equalsIgnoreCase("literal")) { |
| call.setEncodingStyle(null); |
| } |
| return call; |
| } |
| |
| |
| /** |
| * Exctracts any attachments that result from invoking the service, and |
| * returns them as a List wrapped within a DataThing |
| * |
| * @param axisCall |
| * @return |
| * @throws SOAPException |
| * @throws IOException |
| */ |
| protected List extractAttachments(Call axisCall) |
| throws SOAPException, IOException { |
| List attachmentList = new ArrayList(); |
| if (axisCall.getResponseMessage() != null |
| && axisCall.getResponseMessage().getAttachments() != null) { |
| for (Iterator i = axisCall.getResponseMessage().getAttachments(); i |
| .hasNext();) { |
| AttachmentPart ap = (AttachmentPart) i.next(); |
| DataHandler dh = ap.getDataHandler(); |
| BufferedInputStream bis = new BufferedInputStream(dh |
| .getInputStream()); |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| int c; |
| while ((c = bis.read()) != -1) { |
| bos.write(c); |
| } |
| bis.close(); |
| bos.close(); |
| String mimeType = dh.getContentType(); |
| if (mimeType.matches(".*image.*") |
| || mimeType.matches(".*octet.*") |
| || mimeType.matches(".*audio.*") |
| || mimeType.matches(".*application/zip.*")) { |
| attachmentList.add(bos.toByteArray()); |
| } else { |
| attachmentList.add(new String(bos.toByteArray())); |
| } |
| } |
| } |
| |
| return attachmentList; |
| } |
| |
| |
| } |