Java tutorial
/******************************************************************************* * Copyright (C) 2007 The University of Manchester * * Modifications to the initial code base are copyright of their * respective authors, or their employers as appropriate. * * 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 ******************************************************************************/ package net.sf.taverna.t2.activities.wsdl; import java.io.IOException; import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.wsdl.WSDLException; import javax.xml.parsers.ParserConfigurationException; import net.sf.taverna.t2.reference.ReferenceService; import net.sf.taverna.t2.reference.ReferenceServiceException; import net.sf.taverna.t2.reference.T2Reference; import net.sf.taverna.t2.security.credentialmanager.CredentialManager; import net.sf.taverna.t2.workflowmodel.OutputPort; import net.sf.taverna.t2.workflowmodel.health.RemoteHealthChecker; import net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity; import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException; import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityOutputPort; import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivityCallback; import net.sf.taverna.wsdl.parser.TypeDescriptor; import net.sf.taverna.wsdl.parser.UnknownOperationException; import net.sf.taverna.wsdl.parser.WSDLParser; import org.apache.log4j.Logger; import org.xml.sax.SAXException; import com.fasterxml.jackson.databind.JsonNode; /** * An asynchronous Activity that is concerned with WSDL based web-services. * <p> * The activity is configured according to the WSDL location and the operation.<br> * The ports are defined dynamically according to the WSDL specification, and in * addition an output<br> * port <em>attachmentList</em> is added to represent any attachements that are * returned by the webservice. * </p> * * @author Stuart Owen * @author Stian Soiland-Reyes */ public class WSDLActivity extends AbstractAsynchronousActivity<JsonNode> implements InputPortTypeDescriptorActivity, OutputPortTypeDescriptorActivity { public static final String URI = "http://ns.taverna.org.uk/2010/activity/wsdl"; public static final String ENDPOINT_REFERENCE = "EndpointReference"; private JsonNode configurationBean; private WSDLParser parser; // private Map<String, Integer> outputDepth = new HashMap<String, Integer>(); private boolean isWsrfService = false; // private String endpointReferenceInputPortName; private CredentialManager credentialManager; public WSDLActivity(CredentialManager credentialManager) { this.credentialManager = credentialManager; } public boolean isWsrfService() { return isWsrfService; } private static Logger logger = Logger.getLogger(WSDLActivity.class); /** * Configures the activity according to the information passed by the * configuration bean.<br> * During this process the WSDL is parsed to determine the input and output * ports. * * @param bean * the {@link WSDLActivityConfigurationBean} configuration bean */ @Override public void configure(JsonNode bean) throws ActivityConfigurationException { this.configurationBean = bean; try { parseWSDL(); } catch (Exception ex) { throw new ActivityConfigurationException( "Unable to parse the WSDL " + bean.get("operation").get("wsdl").textValue(), ex); } } @Override public JsonNode getConfiguration() { return configurationBean; } /* * (non-Javadoc) * * @seenet.sf.taverna.t2.activities.wsdl.InputPortTypeDescriptorActivity# * getTypeDescriptorForInputPort(java.lang.String) */ public TypeDescriptor getTypeDescriptorForInputPort(String portName) throws UnknownOperationException, IOException { List<TypeDescriptor> inputDescriptors = parser .getOperationInputParameters(configurationBean.get("operation").get("name").textValue()); TypeDescriptor result = null; for (TypeDescriptor descriptor : inputDescriptors) { if (descriptor.getName().equals(portName)) { result = descriptor; break; } } return result; } /* * (non-Javadoc) * * @seenet.sf.taverna.t2.activities.wsdl.InputPortTypeDescriptorActivity# * getTypeDescriptorsForInputPorts() */ public Map<String, TypeDescriptor> getTypeDescriptorsForInputPorts() throws UnknownOperationException, IOException { Map<String, TypeDescriptor> descriptors = new HashMap<String, TypeDescriptor>(); List<TypeDescriptor> inputDescriptors = parser .getOperationInputParameters(configurationBean.get("operation").get("name").textValue()); for (TypeDescriptor descriptor : inputDescriptors) { descriptors.put(descriptor.getName(), descriptor); } return descriptors; } /* * (non-Javadoc) * * @seenet.sf.taverna.t2.activities.wsdl.OutputPortTypeDescriptorActivity# * getTypeDescriptorForOutputPort(java.lang.String) */ public TypeDescriptor getTypeDescriptorForOutputPort(String portName) throws UnknownOperationException, IOException { TypeDescriptor result = null; List<TypeDescriptor> outputDescriptors = parser .getOperationOutputParameters(configurationBean.get("operation").get("name").textValue()); for (TypeDescriptor descriptor : outputDescriptors) { if (descriptor.getName().equals(portName)) { result = descriptor; break; } } return result; } /* * (non-Javadoc) * * @seenet.sf.taverna.t2.activities.wsdl.OutputPortTypeDescriptorActivity# * getTypeDescriptorsForOutputPorts() */ public Map<String, TypeDescriptor> getTypeDescriptorsForOutputPorts() throws UnknownOperationException, IOException { Map<String, TypeDescriptor> descriptors = new HashMap<String, TypeDescriptor>(); List<TypeDescriptor> inputDescriptors = parser .getOperationOutputParameters(configurationBean.get("operation").get("name").textValue()); for (TypeDescriptor descriptor : inputDescriptors) { descriptors.put(descriptor.getName(), descriptor); } return descriptors; } private void parseWSDL() throws ParserConfigurationException, WSDLException, IOException, SAXException, UnknownOperationException { String wsdlLocation = configurationBean.get("operation").get("wsdl").textValue(); URLConnection connection = null; try { URL wsdlURL = new URL(wsdlLocation); connection = wsdlURL.openConnection(); connection.setConnectTimeout(RemoteHealthChecker.getTimeoutInSeconds() * 1000); connection.connect(); } catch (MalformedURLException e) { throw new IOException("Malformed URL", e); } catch (SocketTimeoutException e) { throw new IOException("Timeout", e); } catch (IOException e) { throw e; } finally { if ((connection != null) && (connection.getInputStream() != null)) { connection.getInputStream().close(); } } parser = new WSDLParser(wsdlLocation); isWsrfService = parser.isWsrfService(); } @Override public void executeAsynch(final Map<String, T2Reference> data, final AsynchronousActivityCallback callback) { callback.requestRun(new Runnable() { public void run() { ReferenceService referenceService = callback.getContext().getReferenceService(); Map<String, T2Reference> outputData = new HashMap<String, T2Reference>(); Map<String, Object> invokerInputMap = new HashMap<String, Object>(); String endpointReferenceInputPortName = getEndpointReferenceInputPortName(); try { String endpointReference = null; for (String key : data.keySet()) { Object renderIdentifier = referenceService.renderIdentifier(data.get(key), String.class, callback.getContext()); if (isWsrfService() && key.equals(endpointReferenceInputPortName)) { endpointReference = (String) renderIdentifier; } else { invokerInputMap.put(key, renderIdentifier); } } List<String> outputNames = new ArrayList<String>(); for (OutputPort port : getOutputPorts()) { outputNames.add(port.getName()); } T2WSDLSOAPInvoker invoker = new T2WSDLSOAPInvoker(parser, configurationBean.get("operation").get("name").textValue(), outputNames, endpointReference, credentialManager); Map<String, Object> invokerOutputMap = invoker.invoke(invokerInputMap, configurationBean); for (String outputName : invokerOutputMap.keySet()) { Object value = invokerOutputMap.get(outputName); if (value != null) { Integer depth = getOutputPortDepth(outputName); if (depth != null) { outputData.put(outputName, referenceService.register(value, depth, true, callback.getContext())); } else { logger.info("Skipping unknown output port :" + outputName); // // TODO what should the depth be in this case? // outputData.put(outputName, referenceService // .register(value, 0, true, callback // .getContext())); } } } callback.receiveResult(outputData, new int[0]); } catch (ReferenceServiceException e) { logger.error("Error finding the input data for " + getConfiguration().get("operation"), e); callback.fail("Unable to find input data", e); return; } catch (Exception e) { logger.error("Error invoking WSDL service " + getConfiguration().get("operation"), e); callback.fail("An error occurred invoking the WSDL service", e); return; } } }); } private Integer getOutputPortDepth(String portName) { for (ActivityOutputPort outputPort : getOutputPorts()) { if (outputPort.getName().equals(portName)) { return outputPort.getDepth(); } } return null; } private String getEndpointReferenceInputPortName() { String endpointReferenceInputPortName = null; if (parser.isWsrfService()) { Set<String> inputPorts = new HashSet<>(); try { List<TypeDescriptor> inputDescriptors = parser .getOperationInputParameters(configurationBean.get("operation").get("name").textValue()); for (TypeDescriptor descriptor : inputDescriptors) { inputPorts.add(descriptor.getName()); } } catch (UnknownOperationException | IOException e) { } // Make sure the port name is unique endpointReferenceInputPortName = WSDLActivity.ENDPOINT_REFERENCE; int counter = 0; while (inputPorts.contains(endpointReferenceInputPortName)) { endpointReferenceInputPortName = WSDLActivity.ENDPOINT_REFERENCE + counter++; } } return endpointReferenceInputPortName; } }