package org.vpac.grisu.client.control; import java.net.URL; import java.util.Arrays; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.commons.ssl.HttpSecureProtocol; import org.apache.commons.ssl.TrustMaterial; import org.apache.log4j.Logger; import org.codehaus.xfire.XFireRuntimeException; import org.codehaus.xfire.client.Client; import org.codehaus.xfire.client.XFireProxyFactory; import org.codehaus.xfire.fault.XFireFault; import org.codehaus.xfire.service.Service; import org.codehaus.xfire.service.binding.ObjectServiceFactory; import org.codehaus.xfire.transport.http.CommonsHttpMessageSender; import org.codehaus.xfire.transport.http.HttpTransport; import org.vpac.grisu.control.ServiceInterface; import org.vpac.grisu.control.ServiceInterfaceCreator; import org.vpac.grisu.control.exceptions.NoValidCredentialException; import org.vpac.grisu.control.exceptions.ServiceInterfaceException; import org.vpac.grisu.settings.CaCertManager; import org.vpac.grisu.settings.ClientPropertiesManager; public class EnunciateXFireServiceInterfaceCreator implements ServiceInterfaceCreator { static final Logger myLogger = Logger .getLogger(EnunciateXFireServiceInterfaceCreator.class.getName()); public static String DEFAULT_SERVICE_INTERFACE = "https://grisu.vpac.org/grisu-ws/services/grisu"; public boolean canHandleUrl(String url) { if (url != null) { return url.startsWith("http"); } else { return false; } } public ServiceInterface create(String interfaceUrl, String username, char[] password, String myProxyServer, String myProxyPort, Object[] otherOptions) throws ServiceInterfaceException { String httpProxy = null; int httpProxyPort = -1; String httpProxyUsername = null; char[] httpProxyPassword = null; if (otherOptions == null && otherOptions.length == 4) { try { httpProxy = (String) otherOptions[0]; httpProxyPort = (Integer) otherOptions[1]; httpProxyUsername = (String) otherOptions[2]; httpProxyPassword = (char[]) otherOptions[3]; } catch (final ClassCastException cce) { throw new ServiceInterfaceException( "Could not create serviceInterface: " + cce.getLocalizedMessage(), cce); } } // Technique similar to // http://juliusdavies.ca/commons-ssl/TrustExample.java.html HttpSecureProtocol protocolSocketFactory; try { protocolSocketFactory = new HttpSecureProtocol(); TrustMaterial trustMaterial = null; // "/thecertificate.cer" can be PEM or DER (raw ASN.1). Can even // be several PEM certificates in one file. String cacertFilename = System.getProperty("grisu.cacert"); URL cacertURL = null; try { if (cacertFilename != null && !"".equals(cacertFilename)) { cacertURL = EnunciateXFireServiceInterfaceCreator.class .getResource("/" + cacertFilename); if (cacertURL != null) { myLogger.debug("Using cacert " + cacertFilename + " as configured in the -D option."); } } } catch (final Exception e) { // doesn't matter myLogger.debug("Couldn't find specified cacert. Using default one."); } if (cacertURL == null) { cacertFilename = new CaCertManager() .getCaCertNameForServiceInterfaceUrl(interfaceUrl); if (cacertFilename != null && cacertFilename.length() > 0) { myLogger.debug("Found url in map. Trying to use this cacert file: " + cacertFilename); cacertURL = EnunciateXFireServiceInterfaceCreator.class .getResource("/" + cacertFilename); if (cacertURL == null) { myLogger.debug("Didn't find cacert. Using the default one."); // use the default one cacertURL = EnunciateXFireServiceInterfaceCreator.class .getResource("/cacert.pem"); } else { myLogger.debug("Found cacert. Using it. Good."); } } else { myLogger.debug("Didn't find any configuration for a special cacert. Using the default one."); // use the default one cacertURL = EnunciateXFireServiceInterfaceCreator.class .getResource("/cacert.pem"); } } trustMaterial = new TrustMaterial(cacertURL); // We can use setTrustMaterial() instead of addTrustMaterial() // if we want to remove // HttpSecureProtocol's default trust of TrustMaterial.CACERTS. protocolSocketFactory.addTrustMaterial(trustMaterial); // Maybe we want to turn off CN validation (not recommended!): protocolSocketFactory.setCheckHostname(false); final Protocol protocol = new Protocol("https", (ProtocolSocketFactory) protocolSocketFactory, 443); Protocol.registerProtocol("https", protocol); } catch (final Exception e1) { // TODO Auto-generated catch block // e1.printStackTrace(); throw new ServiceInterfaceException( "Unspecified error while trying to establish secure connection.", e1); } final Service serviceModel = new ObjectServiceFactory().create( ServiceInterface.class, null, "http://api.grisu.arcs.org.au/", null); final XFireProxyFactory serviceFactory = new XFireProxyFactory(); ServiceInterface serviceInterface = null; try { serviceInterface = (ServiceInterface) serviceFactory.create( serviceModel, interfaceUrl); final Client client = Client.getInstance(serviceInterface); // timeout final Long timeout = ClientPropertiesManager .getConnectionTimeoutInMS(); client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, timeout.toString()); // enable file transfer for bigger files client.setProperty(HttpTransport.CHUNKING_ENABLED, "true"); client.setProperty("mtom-enabled", "true"); // client.addOutHandler(new ClientAuthenticationHandler(username, // new String(password), myProxyServer, myProxyPort)); if (httpProxy != null && !"".equals(httpProxy) && httpProxyPort > 0) { client.setProperty(CommonsHttpMessageSender.HTTP_PROXY_HOST, httpProxy); client.setProperty(CommonsHttpMessageSender.HTTP_PROXY_PORT, new Integer(httpProxyPort).toString()); if (httpProxyUsername != null && !"".equals(httpProxyUsername) && httpProxyPassword != null) { client.setProperty( CommonsHttpMessageSender.HTTP_PROXY_USER, httpProxyUsername); client.setProperty( CommonsHttpMessageSender.HTTP_PROXY_PASS, new String(httpProxyPassword)); Arrays.fill(httpProxyPassword, 'x'); } client.setProperty( CommonsHttpMessageSender.DISABLE_PROXY_UTILS, true); } } catch (final Exception e) { // e.printStackTrace(); throw new ServiceInterfaceException( "Unspecified error while connecting to web service.", e); } try { serviceInterface.login(username, new String(password)); } catch (final NoValidCredentialException e) { // TODO Auto-generated catch block // e.printStackTrace(); throw new ServiceInterfaceException( "Could not create & upload proxy to the myproxy server. Probably because of a wrong private key passphrase or network problems.", e); } catch (final Exception e1) { // e1.printStackTrace(); if (e1.getCause() != null) { if (e1.getCause().getCause() instanceof com.ctc.wstx.exc.WstxUnexpectedCharException) { throw new ServiceInterfaceException( "Remote web service seems to be down.", e1); } else if (e1.getCause().getCause() != null && e1.getCause().getCause().getCause() != null && e1.getCause().getCause().getCause() instanceof java.net.UnknownHostException) { throw new ServiceInterfaceException( "Can't connect to host: " + e1.getCause().getCause().getCause() .getLocalizedMessage(), e1); } else if (e1.getCause() instanceof XFireFault) { // e1.getCause().printStackTrace(); throw new ServiceInterfaceException( "Probably because of a wrong password or the MyProxy credentials you want to use are expired/do not exist.", e1); } } throw new ServiceInterfaceException( "Unspecified error while login to web service.", e1); } Arrays.fill(password, 'x'); try { if (!serviceInterface.getInterfaceInfo("VERSION").equals( ServiceInterface.INTERFACE_VERSION)) { throw new ServiceInterfaceException( "Remote Grisu service publishes interface version: " + serviceInterface.getInterfaceInfo("VERSION") + ". This client only supports version " + ServiceInterface.INTERFACE_VERSION + ". Please download a new version of the Grisu client from http://grisu.arcs.org.au", null); } } catch (final XFireRuntimeException xfre) { throw new ServiceInterfaceException( "Remote Grisu service doesn't publish interface version which means it's outdated." + "Please tell your administrator to update it.", xfre); } return serviceInterface; } }