Copy "pure Java" web services example to the CVS.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Mon, 29 Sep 2008 16:44:18 +0000 (16:44 +0000)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Mon, 29 Sep 2008 16:44:18 +0000 (16:44 +0000)
org.glite.lb.client/examples/webservices/java/Makefile [new file with mode: 0644]
org.glite.lb.client/examples/webservices/java/README [new file with mode: 0644]
org.glite.lb.client/examples/webservices/java/src/ExampleSSLSocketFactory.java [new file with mode: 0644]
org.glite.lb.client/examples/webservices/java/src/LBClientExample.java [new file with mode: 0644]
org.glite.lb.client/examples/webservices/java/src/MyX509KeyManager.java [new file with mode: 0644]
org.glite.lb.client/examples/webservices/java/src/MyX509TrustManager.java [new file with mode: 0644]
org.glite.lb.client/examples/webservices/java/src/log4j.properties [new file with mode: 0644]

diff --git a/org.glite.lb.client/examples/webservices/java/Makefile b/org.glite.lb.client/examples/webservices/java/Makefile
new file mode 100644 (file)
index 0000000..4a24541
--- /dev/null
@@ -0,0 +1,27 @@
+CLASSPATH:=${shell echo `find lib -type f | tr '\n' ':'`build}
+
+all: wsdl build
+
+wsdl: build/org/glite/wsdl/services/lb/stubs
+
+build: build/org/glite/wsdl/services/lb/example
+
+run:
+       if test -z "${FILE}" -o -z "${PASS}"; then echo 'Specify FILE and PASS variables.'; exit 1; fi
+       java -classpath $(CLASSPATH) org.glite.wsdl.services.lb.example.LBClientExample ${FILE} ${PASS} ${ENDPOINT}
+
+clean:
+       rm -rvf build/
+
+build/org/glite/wsdl/services/lb/stubs:
+       java -classpath $(CLASSPATH) org.apache.axis.wsdl.WSDL2Java -v \
+         --buildFile \
+         --package org.glite.wsdl.services.lb.stubs \
+         --output build \
+         http://egee.cesnet.cz/cms/export/sites/egee/en/WSDL/HEAD/LB.wsdl
+
+build/org/glite/wsdl/services/lb/example:
+       -mkdir build
+       javac -classpath $(CLASSPATH) -d build src/*.java build/org/glite/wsdl/services/lb/{stubs,stubs/holders}/*.java
+
+.PHONY: all wsdl run clean
diff --git a/org.glite.lb.client/examples/webservices/java/README b/org.glite.lb.client/examples/webservices/java/README
new file mode 100644 (file)
index 0000000..0af4d6b
--- /dev/null
@@ -0,0 +1,28 @@
+How to build
+============
+
+1) copy following files to lib/ directory:
+
+axis-ant.jar
+axis.jar
+commons-discovery-0.2.jar
+commons-logging-1.0.4.jar
+jaxrpc.jar
+log4j.properties
+log4j-1.2.13.jar
+saaj.jar
+wsdl4j-1.5.1.jar
+
+2) generate source stubs and build the example by:
+
+  make
+
+
+Launch
+======
+
+  make run FILE=file.p12 PASS=passphrase ENDPOINT=https://host:9003
+
+or:
+
+  java -cp `find lib -type f | tr '\n' ':'`:build org.glite.wsdl.services.lb.example.LBClientExample <file.p12> <passphrase> https://host:9003
diff --git a/org.glite.lb.client/examples/webservices/java/src/ExampleSSLSocketFactory.java b/org.glite.lb.client/examples/webservices/java/src/ExampleSSLSocketFactory.java
new file mode 100644 (file)
index 0000000..f06b6ad
--- /dev/null
@@ -0,0 +1,108 @@
+package org.glite.wsdl.services.lb.example;
+
+import org.apache.axis.components.net.BooleanHolder;
+import org.apache.axis.components.net.DefaultSocketFactory;
+import org.apache.axis.components.net.SecureSocketFactory;
+import org.apache.log4j.Logger;
+
+import javax.net.ssl.*;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Hashtable;
+
+/**
+ * Factory for SSLSockets for Axis, which creates sockets for SSLv3 connection.
+ * Globus SSL libraries don't support SSLv2 initial packet, so SSLv2Hello protocol
+ * on SSLSocket must be disabled.
+ *
+ * @author Martin Kuba makub@ics.muni.cz
+ */
+public class ExampleSSLSocketFactory extends DefaultSocketFactory implements SecureSocketFactory {
+
+    static Logger log = Logger.getLogger(ExampleSSLSocketFactory.class);
+
+    static Certificate[] cChain = null;
+    static PrivateKey pKey = null;
+    static X509Certificate[] certAuths = null;
+
+    static void registerForAxis(Certificate[] certs, PrivateKey privateKey, X509Certificate[] certificateAuthorities) {
+        log.debug("registering as Axis SecureSocketFactory");
+        cChain = certs;
+        pKey = privateKey;
+        certAuths = certificateAuthorities;
+        System.setProperty("org.apache.axis.components.net.SecureSocketFactory", ExampleSSLSocketFactory.class.getName());
+    }
+
+    protected SSLSocketFactory sslFactory = null;
+
+    public ExampleSSLSocketFactory(Hashtable attributes) throws Exception {
+        super(attributes);
+        SSLContext sctx = SSLContext.getInstance("SSL");
+        KeyManager[] myKeys = new KeyManager[]{new MyX509KeyManager(cChain, pKey)};
+        TrustManager[] myTrust = new TrustManager[]{new MyX509TrustManager(certAuths)};
+        //init SSLContext with our keymanager and trustmanager, and default random device
+        sctx.init(myKeys, myTrust, null);
+        if (log.isDebugEnabled()) {
+            log.debug("attributes: " + attributes);
+            log.debug("SSLContext.provider: " + sctx.getProvider().getInfo());
+        }
+        sslFactory = sctx.getSocketFactory();
+    }
+
+
+    public Socket create(String host, int port, StringBuffer otherHeaders, BooleanHolder useFullURL) throws IOException, SocketException {
+       int i;
+
+        log.debug("create(" + host + ":" + port + ")");
+        //create SSL socket
+        SSLSocket socket = (SSLSocket) sslFactory.createSocket();
+        //enable only SSLv3
+        socket.setEnabledProtocols(new String[]{"SSLv3"});   //  SSLv2Hello, SSLv3,TLSv1
+        //enable only ciphers without RC4 (some bug, probably in older globus)
+        String[] ciphers = socket.getEnabledCipherSuites();
+        ArrayList al = new ArrayList(ciphers.length);
+        for (i = 0; i < ciphers.length; i++) {
+            if (ciphers[i].indexOf("RC4") == -1) al.add(ciphers[i]);
+        }
+        socket.setEnabledCipherSuites((String [])al.toArray(new String[al.size()]));
+        //connect as client
+        socket.setUseClientMode(true);
+        socket.setSoTimeout(30000); //read timeout
+        socket.connect(new InetSocketAddress(host, port), 3000); //connect timeout
+        //create or join a SSL session
+        SSLSession sess = socket.getSession();
+        if (sess == null) {
+            log.debug("sess is null");
+            return socket;
+        }
+
+        if (log.isDebugEnabled()) {
+            //print all we know
+            byte[] id = sess.getId();
+            StringBuffer sb = new StringBuffer(id.length * 2);
+            for (i = 0; i < id.length; i++) {
+                sb.append(Integer.toHexString(id[i] < 0 ? 256 - id[i] : id[i]));
+            }
+            log.debug("SSLSession.id = " + sb.toString());
+//            log.debug("peerHost:Port = " + sess.getPeerHost() + ":" + sess.getPeerPort());
+            log.debug("cipherSuite   = " + sess.getCipherSuite());
+            log.debug("protocol      = " + sess.getProtocol());
+//            log.debug("isValid       = " + sess.isValid());
+            log.debug("creationTime    = " + (new Date(sess.getCreationTime())));
+            log.debug("lastAccessedTime= " + (new Date(sess.getLastAccessedTime())));
+//            log.debug("applicationBufferSize= " + sess.getApplicationBufferSize());
+//            log.debug("packetBufferSize= " + sess.getPacketBufferSize());
+//            log.debug("localPrincipal= " + sess.getLocalPrincipal());
+//            log.debug("peerPrincipal= " + sess.getPeerPrincipal());
+        }
+        return socket;
+    }
+
+}
diff --git a/org.glite.lb.client/examples/webservices/java/src/LBClientExample.java b/org.glite.lb.client/examples/webservices/java/src/LBClientExample.java
new file mode 100644 (file)
index 0000000..07d4fcc
--- /dev/null
@@ -0,0 +1,79 @@
+package org.glite.wsdl.services.lb.example;
+
+import org.apache.log4j.Logger;
+import org.glite.wsdl.services.lb.stubs.LoggingAndBookkeepingPortType;
+import org.glite.wsdl.services.lb.stubs.LoggingAndBookkeeping_ServiceLocator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+
+/**
+ * Example client of LoggingAndBookkeeping web service. Please note that the client depends
+ * only on Axis and Log4j libraries, it uses cryptography included in the JDK.
+ *
+ * @author Martin Kuba makub@ics.muni.cz
+ * @version $Id$
+ */
+public class LBClientExample {
+    static Logger log = Logger.getLogger(LBClientExample.class);
+
+    public static void main(String[] args) throws Exception {
+        if(args.length<2) {
+            System.out.println("usage: java LBClientExample <keystore.p12> <password> [<url>]");
+            System.exit(-1);
+        }
+        File keyfile = new File(args[0]);
+        String password = args[1];
+        URL url = new URL("https://localhost:9003/");
+        if(args.length==3) {
+            url = new URL(args[2]);
+        }
+
+        //read in a keystore file
+        KeyStore ks = readKeyStoreFile(keyfile, password);
+        //find key alias (name)
+        String alias = null;
+        for (Enumeration en = ks.aliases(); en.hasMoreElements();) {
+            alias = (String)en.nextElement();
+            if (ks.isKeyEntry(alias)) break;
+            else alias = null;
+        }
+        if (alias == null) throw new RuntimeException("the keystore contains no keys");
+        //get my private key and certificates
+        Certificate[] certs = ks.getCertificateChain(alias);
+        PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());
+        //use my CA as the only trusted certificate authority
+        X509Certificate[] trustedCertAuths = new X509Certificate[]{(X509Certificate) certs[certs.length - 1]};
+
+        //register our SSL handling
+        ExampleSSLSocketFactory.registerForAxis(certs, key, trustedCertAuths);
+
+        //get client stub
+        LoggingAndBookkeepingPortType lb = new LoggingAndBookkeeping_ServiceLocator().getLoggingAndBookkeeping(url);
+
+        //call the service
+        String version = lb.getVersion(null);
+        System.out.println("LB version: " + version);
+    }
+
+    public static KeyStore readKeyStoreFile(File ksfile, String password) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
+        String kstype;
+        if (ksfile.getName().endsWith("ks")) kstype = "JKS";
+        else if (ksfile.getName().endsWith(".p12")) kstype = "PKCS12";
+        else throw new IOException("Only JKS (*ks) and PKCS12 (*.p12) files are supported ");
+        KeyStore store = KeyStore.getInstance(kstype);
+        store.load(new FileInputStream(ksfile), password != null ? password.toCharArray() : null);
+        return store;
+    }
+
+}
diff --git a/org.glite.lb.client/examples/webservices/java/src/MyX509KeyManager.java b/org.glite.lb.client/examples/webservices/java/src/MyX509KeyManager.java
new file mode 100644 (file)
index 0000000..96e4a40
--- /dev/null
@@ -0,0 +1,64 @@
+package org.glite.wsdl.services.lb.example;
+
+import org.apache.log4j.Logger;
+
+import javax.net.ssl.X509KeyManager;
+import java.net.Socket;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+/**
+ * Implementation of  X509KeyManager, which always returns one pair of a private key and certificate chain.
+ */
+public class MyX509KeyManager implements X509KeyManager {
+    static Logger log = Logger.getLogger(MyX509KeyManager.class);
+    private final X509Certificate[] certChain;
+    private final PrivateKey key;
+
+    public MyX509KeyManager(Certificate[] cchain, PrivateKey key) {
+        this.certChain = new X509Certificate[cchain.length];
+        System.arraycopy(cchain, 0, this.certChain, 0, cchain.length);
+        this.key = key;
+    }
+
+    //not used
+    public String[] getClientAliases(String string, Principal[] principals) {
+        log.debug("getClientAliases()");
+        return null;
+    }
+
+
+    // Intented to be implemented by GUI for user interaction, but we have only one key.
+    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
+        if (log.isDebugEnabled()) {
+            log.debug("chooseClientAlias()");
+            for (int i = 0; i < keyType.length; i++) log.debug("keyType[" + i + "]=" + keyType[i]);
+            for (int i = 0; i < issuers.length; i++) log.debug("issuers[" + i + "]=" + issuers[i]);
+        }
+        return "thealias";
+    }
+
+    //not used on a client
+    public String[] getServerAliases(String string, Principal[] principals) {
+        log.debug("getServerAliases()");
+        return null;
+    }
+
+    //not used on a client
+    public String chooseServerAlias(String string, Principal[] principals, Socket socket) {
+        log.debug("chooseServerAlias()");
+        return null;
+    }
+
+    public X509Certificate[] getCertificateChain(String alias) {
+        log.debug("getCertificateChain()");
+        return certChain;
+    }
+
+    public PrivateKey getPrivateKey(String alias) {
+        log.debug("getPrivateKey()");
+        return key;
+    }
+}
diff --git a/org.glite.lb.client/examples/webservices/java/src/MyX509TrustManager.java b/org.glite.lb.client/examples/webservices/java/src/MyX509TrustManager.java
new file mode 100644 (file)
index 0000000..c88f96f
--- /dev/null
@@ -0,0 +1,83 @@
+package org.glite.wsdl.services.lb.example;
+
+import org.apache.log4j.Logger;
+
+import javax.net.ssl.X509TrustManager;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.*;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Simple trust manager validating server certificates against supplied trusted CAs.
+ *
+ * @author Martin Kuba makub@ics.muni.cz
+ * @version $Id$
+ */
+public class MyX509TrustManager implements X509TrustManager {
+    static Logger log = Logger.getLogger(MyX509TrustManager.class);
+    private final X509Certificate[] certificateAuthorities;
+    private final Set trustAnchors;
+
+    /**
+     * Creates an instance with supplied trusted root CAs.
+     * @param certificateAuthorities
+     */
+    public MyX509TrustManager(X509Certificate[] certificateAuthorities) {
+        int i;
+
+        this.certificateAuthorities = certificateAuthorities;
+        this.trustAnchors = new HashSet();
+        for (i = 0; i < certificateAuthorities.length; i++) {
+            this.trustAnchors.add(new TrustAnchor(certificateAuthorities[i], null));
+        }
+    }
+
+    //not used on a client
+    public X509Certificate[] getAcceptedIssuers() {
+        log.debug("getAcceptedIssuers()");
+        return this.certificateAuthorities;
+    }
+
+    //not used on a client
+    public void checkClientTrusted(X509Certificate[] certs, String authType) {
+        log.debug("checkClientTrusted()");
+    }
+
+    /**
+     * Validates certificate chain sent by a server against trusted CAs.
+     * @param certs
+     * @param authType
+     * @throws CertificateException
+     */
+    public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
+        if (log.isDebugEnabled()) {
+            log.debug("checkServerTrusted(certs: "+ certs.length + ", authType=" + authType+")");
+            for (int i = 0; i < certs.length; i++) {
+                log.debug("cert[" + i + "]=" + certs[i].getSubjectX500Principal().toString());
+            }
+        }
+        //validate server certificate
+        try {
+            PKIXParameters pkixParameters = new PKIXParameters(this.trustAnchors);
+            pkixParameters.setRevocationEnabled(false);
+            CertificateFactory certFact = CertificateFactory.getInstance("X.509");
+            CertPath path = certFact.generateCertPath(Arrays.asList(certs));
+            CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX");
+            certPathValidator.validate(path, pkixParameters);
+        } catch (NoSuchAlgorithmException e) {
+            log.error(e.getMessage(), e);
+        } catch (InvalidAlgorithmParameterException e) {
+            log.error(e.getMessage(), e);
+        } catch (CertPathValidatorException e) {
+            CertificateException ce;
+            log.error(e.getMessage(), e);
+            ce = new CertificateException(e.getMessage());
+            ce.setStackTrace(e.getStackTrace());
+            throw ce;
+        }
+        log.debug("server is trusted");
+    }
+}
diff --git a/org.glite.lb.client/examples/webservices/java/src/log4j.properties b/org.glite.lb.client/examples/webservices/java/src/log4j.properties
new file mode 100644 (file)
index 0000000..cfdcee3
--- /dev/null
@@ -0,0 +1,30 @@
+# Set root category priority to INFO and its only appender to CONSOLE.
+# names CONSOLE, R, F are arbitrary
+log4j.rootCategory=INFO, CONSOLE
+
+# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
+log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
+log4j.logger.org.apache.axis.utils.JavaUtils=FATAL
+log4j.logger.org.glite.wsdl.services.lb=DEBUG
+
+# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+#viz http://logging.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
+# %d - date
+# %t - thread
+# %p - priority
+# %c{1} - category (jmeno loggeru) s poctem zobrazovanych casti oddelenych teckou
+# %m - message
+# %n - line separator
+log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %-5p %c{1} - %m%n
+
+log4j.appender.F=org.apache.log4j.FileAppender
+log4j.appender.F.File=txt.log
+log4j.appender.F.layout=org.apache.log4j.PatternLayout
+log4j.appender.F.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
+
+log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.R.File=xml.log
+log4j.appender.R.layout=org.apache.log4j.xml.XMLLayout
+log4j.appender.R.DatePattern='.'yyyy-MM-dd