/* Copyright 2013 Nationale-Nederlanden 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 nl.nn.adapterframework.http; import java.io.IOException; import java.util.Map; import javax.servlet.http.HttpServletResponse; import nl.nn.adapterframework.configuration.ConfigurationException; import nl.nn.adapterframework.configuration.ConfigurationWarnings; import nl.nn.adapterframework.core.SenderException; import nl.nn.adapterframework.parameters.Parameter; import nl.nn.adapterframework.parameters.ParameterResolutionContext; import nl.nn.adapterframework.parameters.ParameterValueList; import nl.nn.adapterframework.soap.SoapWrapper; import nl.nn.adapterframework.util.CredentialFactory; import nl.nn.adapterframework.util.Misc; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.URI; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; /** * Sender that sends a message via a WebService. * * <p><b>Configuration:</b> * <table border="1"> * <tr><th>attributes</th><th>description</th><th>default</th></tr> * <tr><td>classname</td><td>nl.nn.adapterframework.http.HttpSender</td><td> </td></tr> * <tr><td>{@link #setName(String) name}</td><td>name of the sender</td><td> </td></tr> * <tr><td>{@link #setUrl(String) url}</td><td>URL or base of URL to be used </td><td> </td></tr> * <tr><td>{@link #setUrlParam(String) urlParam}</td><td>parameter that is used to obtain url; overrides url-attribute.</td><td>url</td></tr> * <tr><td>{@link #setContentType(String) contentType}</td><td>content-type of the request, only for POST methods</td><td>text/xml; charset=UTF-8</td></tr> * <tr><td>{@link #setSoap(boolean) soap}</td><td>when <code>true</code>, messages sent are put in a SOAP envelope and the SOAP envelope is removed from received messages (SOAP envelope will not be visible to the pipeline)</td><td><code>true</code></td></tr> * <tr><td>{@link #setSoapAction(String) soapAction}</td><td>the SOAPActionUri to be set in the requestheader</td><td> </td></tr> * <tr><td>{@link #setSoapActionURI(String) soapActionURI}</td><td>deprecated: Please use soapAction instead</td><td> </td></tr> * <tr><td>{@link #setSoapActionParam(String) soapActionParam}</td><td>parameter to obtain the SOAPActionUri</td><td> </td></tr> * <tr><td>{@link #setSoapActionURIParam(String) soapActionURIParam}</td><td>deprecated: Please use soapActionParam instead</td><td> </td></tr> * <tr><td>{@link #setEncodingStyle(String) encodingStyle}</td><td>the encodingStyle to be set in the messageheader</td><td> </td></tr> * <tr><td>{@link #setEncodingStyleURI(String) encodingStyleURI}</td><td>deprecated: Please use encodingStyle instead</td><td> </td></tr> * <tr><td>{@link #setServiceNamespace(String) serviceNamespace}</td><td>the namespace of the message sent. Identifies the service to be called. May be overriden by an actual namespace setting in the message to be sent</td><td> </td></tr> * <tr><td>{@link #setServiceNamespaceURI(String) serviceNamespaceURI}</td><td>deprecated: Please use serviceNamespace instead</td><td> </td></tr> * <tr><td>{@link #setServiceNamespaceParam(String) serviceNamespaceParam}</td><td>arameter to obtain the serviceNamespace</td><td> </td></tr> * <tr><td>{@link #setServiceNamespaceURIParam(String) serviceNamespaceURIParam}</td><td>deprecated: Please use serviceNamespaceParam instead</td><td> </td></tr> * <tr><td>{@link #setNamespaceDefs(String) namespaceDefs}</td><td>namespace defintions to be added in the soap envelope tag. Must be in the form of a comma or space separated list of <code>prefix=namespaceuri</code>-definitions</td><td> </td></tr> * <tr><td>{@link #setThrowApplicationFaults(boolean) throwApplicationFaults}</td><td>controls whether soap faults generated by the application generate an exception, or are treated as 'normal' messages</td><td>true</td></tr> * <tr><td>{@link #setTimeout(int) timeout}</td><td>timeout ih ms of obtaining a connection/result. 0 means no timeout</td><td>10000</td></tr> * <tr><td>{@link #setMaxConnections(int) maxConnections}</td><td>the maximum number of concurrent connections</td><td>2</td></tr> * <tr><td>{@link #setAuthAlias(String) authAlias}</td><td>alias used to obtain credentials for authentication to host</td><td> </td></tr> * <tr><td>{@link #setUserName(String) userName}</td><td>username used in authentication to host</td><td> </td></tr> * <tr><td>{@link #setPassword(String) password}</td><td> </td><td> </td></tr> * <tr><td>{@link #setProxyHost(String) proxyHost}</td><td> </td><td> </td></tr> * <tr><td>{@link #setProxyPort(int) proxyPort}</td><td> </td><td>80</td></tr> * <tr><td>{@link #setProxyAuthAlias(String) proxyAuthAlias}</td><td>alias used to obtain credentials for authentication to proxy</td><td> </td></tr> * <tr><td>{@link #setProxyUserName(String) proxyUserName}</td><td> </td><td> </td></tr> * <tr><td>{@link #setProxyPassword(String) proxyPassword}</td><td> </td><td> </td></tr> * <tr><td>{@link #setProxyRealm(String) proxyRealm}</td><td> </td><td> </td></tr> * <tr><td>{@link #setKeystoreType(String) keystoreType}</td><td> </td><td>pkcs12</td></tr> * <tr><td>{@link #setKeyManagerAlgorithm(String) keyManagerAlgorithm}</td><td> </td><td></td></tr> * <tr><td>{@link #setCertificate(String) certificate}</td><td>resource URL to certificate to be used for authentication</td><td> </td></tr> * <tr><td>{@link #setCertificatePassword(String) certificatePassword}</td><td> </td><td> </td></tr> * <tr><td>{@link #setCertificateAuthAlias(String) certificateAuthAlias}</td><td>alias used to obtain certificate password</td><td> </td></tr> * <tr><td>{@link #setTruststore(String) truststore}</td><td>resource URL to truststore to be used for authentication</td><td> </td></tr> * <tr><td>{@link #setTruststorePassword(String) truststorePassword}</td><td> </td><td> </td></tr> * <tr><td>{@link #setTruststoreAuthAlias(String) truststoreAuthAlias}</td><td>alias used to obtain truststore password</td><td> </td></tr> * <tr><td>{@link #setTruststoreType(String) truststoreType}</td><td> </td><td>jks</td></tr> * <tr><td>{@link #setTrustManagerAlgorithm(String) trustManagerAlgorithm}</td><td> </td><td></td></tr> * <tr><td>{@link #setAllowSelfSignedCertificates(boolean) allowSelfSignedCertificates}</td><td>when true, self signed certificates are accepted</td><td>false</td></tr> * <tr><td>{@link #setFollowRedirects(boolean) followRedirects}</td><td>when true, a redirect request will be honoured, e.g. to switch to https</td><td>true</td></tr> * <tr><td>{@link #setVerifyHostname(boolean) verifyHostname}</td><td>when true, the hostname in the certificate will be checked against the actual hostname</td><td>true</td></tr> * <tr><td>{@link #setJdk13Compatibility(boolean) jdk13Compatibility}</td><td>enables the use of certificates on JDK 1.3.x. The SUN reference implementation JSSE 1.0.3 is included for convenience</td><td>false</td></tr> * <tr><td>{@link #setStaleChecking(boolean) staleChecking}</td><td>controls whether connections checked to be stale, i.e. appear open, but are not.</td><td>true</td></tr> * <tr><td>{@link #setWssAuthAlias(String) wssAuthAlias}</td><td>alias used to obtain credentials for authentication to Web Services Security</td><td> </td></tr> * <tr><td>{@link #setWssUserName(String) wssUserName}</td><td> </td><td> </td></tr> * <tr><td>{@link #setWssPassword(String) wssPassword}</td><td> </td><td> </td></tr> * </table> * </p> * * @author Gerrit van Brakel * @since 4.2c */ public class WebServiceSender extends HttpSender { private boolean soap = true; private String soapAction = ""; private String soapActionParam = "soapAction"; private String encodingStyle=null; private String serviceNamespace=null; private String serviceNamespaceParam="serviceNamespace"; private String namespaceDefs = null; private boolean throwApplicationFaults=true; private String wssAuthAlias; private String wssUserName; private String wssPassword; private SoapWrapper soapWrapper; private CredentialFactory wsscf=null; private Parameter soapActionParameter; private Parameter serviceNamespaceURIParameter; public String getLogPrefix() { return "WebServiceSender ["+getName()+"] to ["+getPhysicalDestinationName()+"] "; } public WebServiceSender() { super(); setMethodType("POST"); setContentType("text/xml;charset="+Misc.DEFAULT_INPUT_STREAM_ENCODING); } @Override public void configure() throws ConfigurationException { super.configure(); if (isSoap()) { //ConfigurationWarnings configWarnings = ConfigurationWarnings.getInstance(); //String msg = getLogPrefix()+"the use of attribute soap=true has been deprecated. Please change to SoapWrapperPipe"; //configWarnings.add(log, msg); } soapWrapper=SoapWrapper.getInstance(); if (paramList!=null && StringUtils.isNotEmpty(getSoapActionParam())) { soapActionParameter=paramList.findParameter(getSoapActionParam()); serviceNamespaceURIParameter=paramList.findParameter(getServiceNamespaceParam()); addParameterToSkip(soapActionParameter); addParameterToSkip(serviceNamespaceURIParameter); } if (StringUtils.isNotEmpty(getWssAuthAlias()) || StringUtils.isNotEmpty(getWssUserName())) { wsscf = new CredentialFactory(getWssAuthAlias(), getWssUserName(), getWssPassword()); log.debug(getLogPrefix()+"created CredentialFactory for username=["+wsscf.getUsername()+"]"); } } @Override protected HttpMethod getMethod(URI uri, String message, ParameterValueList parameters, Map<String, String> headersParamsMap) throws SenderException { String serviceNamespaceURI; if (serviceNamespaceURIParameter!=null) { serviceNamespaceURI=parameters.getParameterValue(getServiceNamespaceParam()).asStringValue(getServiceNamespace()); } else { serviceNamespaceURI=getServiceNamespace(); } String soapActionURI; if (soapActionParameter!=null) { soapActionURI=parameters.getParameterValue(getSoapActionParam()).asStringValue(getSoapAction()); } else { soapActionURI=getSoapAction(); } String soapmsg; if (isSoap()) { soapmsg = soapWrapper.putInEnvelope(message, getEncodingStyle(),serviceNamespaceURI, null, getNamespaceDefs()); } else { soapmsg = message; } if (wsscf!=null) { soapmsg = soapWrapper.signMessage(soapmsg,wsscf.getUsername(),wsscf.getPassword()); } if (log.isDebugEnabled()) log.debug(getLogPrefix()+"SOAPMSG [" + soapmsg + "]"); HttpMethod method = super.getMethod(uri, soapmsg, parameters, headersParamsMap); if (log.isDebugEnabled()) log.debug(getLogPrefix()+"setting Content-Type and SOAPAction header ["+soapActionURI+"]"); method.addRequestHeader("SOAPAction",soapActionURI); return method; } @Override public String extractResult(HttpMethod httpmethod, ParameterResolutionContext prc, HttpServletResponse response, String fileName) throws SenderException, IOException { String httpResult; try { httpResult = super.extractResult(httpmethod, prc, response, fileName); } catch (SenderException e) { soapWrapper.checkForSoapFault(getResponseBodyAsString(httpmethod), e); throw e; } if (isThrowApplicationFaults()) { soapWrapper.checkForSoapFault(httpResult, null); } try { if (isSoap()) { return soapWrapper.getBody(httpResult); } else { return httpResult; } } catch (Exception e) { throw new SenderException("cannot retrieve result message",e); } } public String toString() { return ToStringBuilder.reflectionToString(this); } public void setSoap(boolean b) { soap = b; } public boolean isSoap() { return soap; } /** * @deprecated please use setSoapAction() instead */ public void setSoapActionURI(String soapAction) { ConfigurationWarnings.getInstance().add(log, getLogPrefix()+" the attribute 'soapActionURI' has been renamed 'soapAction'"); setSoapAction(soapAction); } /** * @deprecated please use setSoapActionParam instead */ public void setSoapActionURIParam(String soapActionParam) { ConfigurationWarnings.getInstance().add(log, getLogPrefix()+" the attribute 'soapActionURIParam' has been renamed 'soapActionParam'"); setSoapActionParam(soapActionParam); } public String getSoapAction() { return soapAction; } public void setSoapAction(String soapAction) { this.soapAction = soapAction; } public String getSoapActionParam() { return soapActionParam; } public void setSoapActionParam(String soapActionParam) { this.soapActionParam = soapActionParam; } public void setEncodingStyleURI(String encodingStyle) { ConfigurationWarnings.getInstance().add(log, getLogPrefix()+" the attribute 'encodingStyleURI' has been renamed 'encodingStyle'"); setEncodingStyle(encodingStyle); } public void setEncodingStyle(String encodingStyle) { this.encodingStyle = encodingStyle; } public String getEncodingStyle() { return encodingStyle; } public void setThrowApplicationFaults(boolean b) { throwApplicationFaults = b; } public boolean isThrowApplicationFaults() { return throwApplicationFaults; } public void setServiceNamespaceURI(String serviceNamespace) { ConfigurationWarnings.getInstance().add(log, getLogPrefix()+" the attribute 'serviceNamespaceURI' has been renamed 'serviceNamespace'"); setServiceNamespace(serviceNamespace); } public void setServiceNamespace(String serviceNamespace) { this.serviceNamespace = serviceNamespace; } public String getServiceNamespace() { return serviceNamespace; } public void setServiceNamespaceURIParam(String serviceNamespaceParam) { ConfigurationWarnings.getInstance().add(log, getLogPrefix()+" the attribute 'serviceNamespaceURIParam' has been renamed 'serviceNamespaceParam'"); setServiceNamespaceParam(serviceNamespaceParam); } public void setServiceNamespaceParam(String serviceNamespaceParam) { this.serviceNamespaceParam = serviceNamespaceParam; } public String getServiceNamespaceParam() { return serviceNamespaceParam; } public void setNamespaceDefs(String namespaceDefs) { this.namespaceDefs = namespaceDefs; } public String getNamespaceDefs() { return namespaceDefs; } public void setWssUserName(String string) { wssUserName = string; } public String getWssUserName() { return wssUserName; } public void setWssPassword(String string) { wssPassword = string; } public String getWssPassword() { return wssPassword; } public void setWssAuthAlias(String string) { wssAuthAlias = string; } public String getWssAuthAlias() { return wssAuthAlias; } }