Просмотр исходного кода

Initial commit: webservice client tutorial

Mathias Landhäußer 11 лет назад
Родитель
Сommit
089619b57b

+ 27 - 0
jplag.webServiceClientTutorial/build.properties.template

@@ -0,0 +1,27 @@
+<!--
+	Copy this template to "build.properties" and make the needed modifications
+    for your system there. The build.xml will need it.
+  -->
+
+	<!--
+		the clientlibs folder must contain the following libraries:
+		
+		JWSDP 2.0:
+			fastinfoset/lib:
+				- FastInfoset.jar
+			jaxrpc/lib:
+				- jaxrpc-api.jar
+				- jaxrpc-imp.jar
+				- jaxrpc-spi.jar
+			jwsdp-shared/lib:
+				- activation.jar
+				- mail.jar
+			saaj/lib:
+				- saaj-api.jar
+				- saaj-impl.jar
+			sjsxp/lib:
+				- jsr173_api.jar
+				- sjsxp.jar
+	 -->	
+
+  	<property name="clientlibs" value="<path to clientlibs folder>" />

+ 220 - 0
jplag.webServiceClientTutorial/build.xml

@@ -0,0 +1,220 @@
+<?xml version = '1.0'?>
+<!DOCTYPE project [ 
+	<!ENTITY buildProbs SYSTEM "./build.properties">
+	<!ENTITY wscompile SYSTEM "./wscompile-config.xml">
+ ]>
+<project basedir="." name="jplagTutorial" default="cnj-client">
+	&buildProbs;  
+    <property name="compile.debug" value="true" />
+	
+	<path id="app.classpath">
+		<fileset dir="${clientlibs}"/>
+  	</path>
+	
+	<path id="client.classpath">
+		<path refid="app.classpath" />
+		<pathelement location="${basedir}/classes"/>
+	</path>  
+	
+	<!-- Generate the JPlag stub -->
+
+	<target name="prepare-client">
+		<mkdir dir="${basedir}/classes" />
+		<mkdir dir="${basedir}/connectclasses" />
+		<mkdir dir="${basedir}/dist" />
+	</target>
+
+	<target name="prepare-wscompile" depends="prepare-client">
+		<javac destdir="${basedir}/classes"
+			   includes="util/wscompileSSLLauncher.java" srcdir="${basedir}"
+			   debug="${compile.debug}">
+			<classpath refid="app.classpath" />
+		</javac>
+		&wscompile;
+	</target>
+
+	<target name="compile-client-handler" depends="prepare-client">
+		<javac destdir="${basedir}/classes"
+			   includes="util/JPlagClientAccessHandler.java"
+			   srcdir="${basedir}" debug="${compile.debug}">
+			<classpath refid="client.classpath" />
+		</javac>
+	</target>
+	
+	<target name="generate-client" depends="compile-client-handler, prepare-wscompile">
+		<wscompile base="${basedir}/classes" features="wsi"
+				config="${basedir}/config-client.xml" xPrintStackTrace="true"
+				keep="true" sourcebase="${basedir}/.."
+				client="true" verbose="true">
+			<classpath>
+				<path refid="client.classpath" />
+			</classpath>
+		</wscompile>
+	</target>
+	
+	<!-- Create the ExampleConnect application -->
+
+	<target name="compile-exampleconnect" depends="prepare-client">
+		<available file="${basedir}/jplagClient" type="dir" property="client-built"/>
+		<fail unless="client-built">
+JPlag stub is not built yet!
+			
+Please call 'generate-client' first!
+		</fail>
+		
+		<javac destdir="${basedir}/connectclasses" srcdir="${basedir}"
+			   includes="ExampleConnect.java jplagClient/*.java"
+			   debug="${compile.debug}" deprecation="on">
+			<classpath refid="client.classpath" />
+		</javac>
+	</target>
+	
+	<target name="jar-exampleconnect">
+		<jar destfile="${basedir}/dist/exampleConnect.jar">
+			<zipfileset dir="${basedir}/classes"
+				includes="jplagTutorial/util/JPlagClientAccessHandler.class" />
+			<zipfileset dir="${basedir}/connectclasses"
+				excludes="jplagTutorial/util/*.class" />
+			<zipfileset src="${clientlibs}/jaxrpc-api.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/jaxrpc-impl.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/jaxrpc-spi.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/activation.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/mail.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/saaj-api.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/saaj-impl.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/jsr173_api.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/sjsxp.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/FastInfoset.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<manifest>
+				<attribute name="Main-Class"
+					value="jplagTutorial.ExampleConnect" />
+			</manifest>
+		</jar>
+	</target>
+	
+	<target name="cnj-exampleconnect"
+			depends="compile-exampleconnect, jar-exampleconnect"/>
+	
+	<!-- Create the ExampleClient application -->
+
+	<target name="compile-client" depends="prepare-client">
+		<available file="${basedir}/jplagClient" type="dir" property="client-built"/>
+		<fail unless="client-built">
+JPlag stub is not built yet!
+			
+Please call 'generate-client' first!
+		</fail>
+		
+		<javac destdir="${basedir}/classes" srcdir="${basedir}"
+				debug="${compile.debug}" deprecation="on">
+			<classpath refid="client.classpath" />
+		</javac>
+	</target>
+	
+	<!--
+		Generates a jar file including all needed libraries. As the resulting
+		file is over 3 MB, this isn't very useful for an application which gets
+		updated regularly, as this would require the whole file to be downloaded
+		again, instead of only the real application.
+		The advantage is, that you only need to supply one single file, which
+		is fully functional (except for the JRE of course).
+		Note: Use "java -jar dist/exampleClient.jar" to start the application.
+			It will show you, which parameters are required.		
+		Note: The 'excludes="META-INF/WEBSTART.*"' is only needed, if the
+			libraries have been signed, because, if these files exist in the
+			final jar file, the program will abort with a SecurityException.
+	-->
+	
+	<target name="jar-client">
+		<jar destfile="${basedir}/dist/exampleClient.jar">
+			<zipfileset dir="${basedir}/classes"
+				excludes="jplagTutorial/util/wscompile*.class" />
+			<zipfileset src="${clientlibs}/jaxrpc-api.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/jaxrpc-impl.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/jaxrpc-spi.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/activation.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/mail.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/saaj-api.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/saaj-impl.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/jsr173_api.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/sjsxp.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<zipfileset src="${clientlibs}/FastInfoset.jar" includes="**/*"
+				excludes="META-INF/WEBSTART.*" />
+			<manifest>
+				<attribute name="Main-Class"
+					value="jplagTutorial.ExampleClient" />
+			</manifest>
+		</jar>
+	</target>
+
+	<target name="cnj-client" depends="compile-client, jar-client"/>
+	
+<!--
+	If you want to use create a Web Start application with this, you'll have
+	to sign your jar as well as the libraries you provide with the same key.
+	The key may either be a correct key from a certification authority or a
+	self-created key. You can create a self-created by invoking something like
+	the following command on your shell prompt:
+		keytool -genkey -keystore jplagClient -alias webstart
+		
+	This jar can also be used for a command line version, if you provide a
+	bat file and a sh file to call the application with the correct classpath.
+	Of course you'll also have to provide the libraries.
+-->        
+	
+	<target name="jar-webstart" depends="compile-client">
+		<jar destfile="${basedir}/dist/exampleClient.jar">
+			<zipfileset dir="${basedir}/classes" excludes="util/*.class" />
+		</jar>
+		<signjar keystore="jplagClient.key" alias="webstart"
+				storepass="your_keystore_password">
+			<fileset dir="${basedir}/dist" includes="*.jar" />
+		</signjar>
+	</target>
+	
+	<!--
+		Signs all libraries in the ${clientlibs} folder	with the current
+		jplagClient.key. These libraries can then be copied to the server
+		to be used for a Web Start application
+	-->
+	
+	<target name="signlibs">
+    	<signjar keystore="jplagClient.key" alias="webstart"
+    			storepass="your_keystore_password">
+	  		<fileset dir="${clientlibs}" includes="*.jar" />
+    	</signjar>
+	</target>
+	
+
+	<target name="run-client">
+		<java fork="true" classpathref="client.classpath"
+			  classname="jplagTutorial.ExampleClient" />
+	</target>
+	
+	<target name="cnr-client" depends="compile-client, run-client"/>
+	
+	<target name="clean">
+		<delete dir="${basedir}/classes" />
+		<delete dir="${basedir}/dist" />
+	</target>
+</project>
+

+ 18 - 0
jplag.webServiceClientTutorial/config-client.xml

@@ -0,0 +1,18 @@
+<?xml version = '1.0' encoding = 'UTF-8'?>
+<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
+    <wsdl xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"
+    	  packageName="jplagTutorial.jplagClient"
+          location="https://www.ipd.kit.edu/jplag/JPlagService.wsdl" >
+<!--		  location="https://localhost:8443/JPlagService/service?WSDL" > -->
+<!--          location="https://swt.ira.uka.de:2222/JPlagService/service?WSDL" >-->
+        <handlerChains xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
+            <chain xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"
+            	   runAt="client" >
+                <handler xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"
+                		 className="jplagTutorial.util.JPlagClientAccessHandler" />
+<!--                <handler xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"
+                		 className="atujplag.util.LoggingHandler" /> -->
+            </chain>
+        </handlerChains>
+    </wsdl>
+</configuration>

+ 889 - 0
jplag.webServiceClientTutorial/src/main/java/jplagTutorial/ExampleClient.java

@@ -0,0 +1,889 @@
+package jplagTutorial;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.X509Certificate;
+
+import java.rmi.RemoteException;
+import com.sun.xml.rpc.client.ClientTransportException;
+import com.sun.xml.rpc.util.exception.JAXRPCExceptionBase;
+
+import javax.xml.rpc.handler.Handler;
+import javax.xml.rpc.handler.HandlerChain;
+
+import jplagTutorial.jplagClient.*;
+import jplagTutorial.util.JPlagClientAccessHandler;
+import jplagTutorial.util.ZipUtil;
+
+public class ExampleClient {
+    /*
+     * Status constants
+     */
+    public static final int JPLAG_UPLOADING = 0;
+    public static final int JPLAG_INQUEUE = 50;
+    public static final int JPLAG_PARSING = 100;
+    public static final int JPLAG_COMPARING = 200;
+    public static final int JPLAG_GENRESULT = 230;
+    public static final int JPLAG_PACKRESULT = 250;
+    public static final int JPLAG_DONE = 300;
+    public static final int JPLAG_ERROR = 400;
+    
+    /*
+     * Login data
+     */
+    private String username = null;
+    private String password = null;
+    
+    /**
+     * Options for JPlag specified by the command line
+     */
+    private Option option = new Option();
+    
+    /**
+     * Name of directory where the result pages will be stored
+     */
+    private String resultDirName = "result";
+    
+    /**
+     * True, if the user wants to get a list of his submissions on the server
+     */
+    private boolean listSubmissions = false;
+    
+    /**
+     * The number of the submission to be downloaded plus 1 or 0
+     */
+    private int downloadResultNumber = 0;
+    
+    /**
+     * The number of the submission to be cancelled plus 1 or 0
+     */
+    private int cancelSubmissionNumber = 0;
+
+    /**
+     * Suffix array generated from the suffix option or the language info
+     * suffix array
+     */
+    private String[] suffixes = null;
+
+    /**
+     * Filename filter used by collectInDir()
+     */
+    private FilenameFilter subdirFileFilter = null;
+    
+    /**
+     * Current position of progress bar
+     */
+    private int progressPos;
+    
+    /**
+     * Maximum position of progress bar
+     */
+    private int progressMax;
+    
+    /**
+     * The stub for the JPlag Web Service
+     */
+    private JPlagTyp_Stub stub = null;
+    
+    /**
+     * Helper function to easily evaluate web service related exceptions
+     * @param e Exception thrown by a stub method
+     */
+    public static void checkException(Exception e) {
+        if(e instanceof JPlagException) {
+            JPlagException je = (JPlagException) e;
+            System.out.println("JPlagException: " + je.getDescription()
+                + "\n" + je.getRepair());
+        }
+        else if(e instanceof RemoteException) {
+            RemoteException re = (RemoteException) e;
+            Throwable cause = re.getCause();
+            if(cause != null && cause instanceof ClientTransportException) {
+                cause = ((JAXRPCExceptionBase) cause).getLinkedException();
+                if(cause != null) {
+                    System.out.println("Connection exception: "
+                        + cause.getMessage());
+                    return;
+                }
+            }
+            System.out.println("Unexpected RemoteException: "
+                + re.getMessage());
+            re.printStackTrace();
+        }
+        else {
+            System.out.println("Unexpected Exception: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+    
+    /**
+     * Initializes the JPlag stub, by installing an all-trusting trust manager
+     * for the SSL connection to the server, instantiating a stub object and
+     * setting username and password
+     * @return True, if username and password have been set
+     */
+    private boolean initJPlagStub() {
+        /*
+         * Create a trust manager that does not validate certificate chains
+         */
+        TrustManager[] trustAllCerts = new TrustManager[] {
+            new X509TrustManager() {
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+                public void checkClientTrusted(X509Certificate[] certs,
+                        String authType) {}
+                public void checkServerTrusted(X509Certificate[] certs,
+                        String authType) {}
+            }
+        };
+        
+        /*
+         * Install the all-trusting trust manager
+         */
+        try {
+            SSLContext sc = SSLContext.getInstance("SSL");
+            sc.init(null, trustAllCerts, new java.security.SecureRandom());
+            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+        } catch (Exception e) {
+            System.out.println("Warning: Unable to install all-trusting trust "
+                + "manager! SSL connection may not work!");
+        }
+        
+        /*
+         * Get JPlag client stub 
+         */
+        stub = (JPlagTyp_Stub) (new JPlagService_Impl()
+                .getJPlagServicePort());
+                
+        /*
+         * Search for the JPlagClientAccessHandler in the handler chain
+         */
+        HandlerChain handlerchain = stub._getHandlerChain();
+        Iterator handlers = handlerchain.iterator();
+        JPlagClientAccessHandler accessHandler = null;
+        while(handlers.hasNext()) {
+            Handler handler = (Handler) handlers.next();
+            if(handler instanceof JPlagClientAccessHandler) {
+                accessHandler = (JPlagClientAccessHandler)handler;
+                break;
+            }
+        }
+        
+        if(accessHandler == null) {
+            System.out.println("Unable to find access handler! Cannot set "
+                + "username and password!");
+            return false;
+        }
+        
+        /*
+         * Initialize access handler
+         */
+        accessHandler.setUserPassObjects(username, password);
+        
+        return true;
+    }
+
+    /**
+     * Accepts directories and files with one of the given suffixes
+     */
+    private class RecursiveFilenameFilter implements FilenameFilter {
+        public boolean accept(File dir, String name) {
+            if(new File(dir, name).isDirectory()) return true;
+            
+            for(int i=0; i<suffixes.length; i++) {
+                if(name.endsWith(suffixes[i]))
+                    return true;
+            }
+            return false;
+        }
+    }
+    
+    /**
+     * Only accepts files with one of the given suffixes
+     */
+    private class NonRecursiveFilenameFilter implements FilenameFilter {
+        public boolean accept(@SuppressWarnings("unused") File dir,
+                String name)
+        {
+            for(int i=0; i<suffixes.length; i++) {
+                if(name.endsWith(suffixes[i]))
+                    return true;
+            }
+            return false;
+        }
+    }
+        
+    /**
+     * Collects all valid files inside a directory. If subdirFileFilter also
+     * accepts directories, subdirectories are included in the search
+     * @param colfiles Vector receiving the found files
+     * @param dir The directory which will be searched
+     */
+    private void collectInDir(Vector<File> colfiles, File dir) {
+        if(!dir.exists()) return;
+        
+        File[] files = dir.listFiles(subdirFileFilter);
+        
+        for(int i=0; i<files.length; i++) {
+            if(files[i].isDirectory()) {
+                collectInDir(colfiles, files[i]);
+            }
+            else colfiles.add(files[i]);
+        }
+    }
+    
+    /**
+     * Collects all valid files according to the set options
+     * @return A Vector object of all valid files
+     */
+    private Vector<File> collectFiles() {
+        Vector<File> colfiles = new Vector<File>();
+        
+        File[] files = new File(option.getOriginalDir()).listFiles(
+            new RecursiveFilenameFilter());
+        
+        if(files == null) {
+            System.out.println("\"" + option.getOriginalDir()
+                + "\" is not a directory or an I/O error occurred!");
+            return null;
+        }
+        
+        if(option.isReadSubdirs())
+            subdirFileFilter = new RecursiveFilenameFilter();
+        else
+            subdirFileFilter = new NonRecursiveFilenameFilter();
+        
+        for(int i=0; i<files.length; i++) {
+            if(files[i].isDirectory()) {
+                if(option.getPathToFiles()!=null)
+                    collectInDir(colfiles, new File(files[i],
+                        option.getPathToFiles()));
+                else
+                    collectInDir(colfiles, files[i]);
+            }
+            else colfiles.add(files[i]);
+        }
+        
+        if(colfiles.size() <= 1) {
+            System.out.println("\"" + option.getOriginalDir()
+                + "\" didn't contain at least two files\n"
+                + "suitable for the specified options!");
+            return null;
+        }
+        return colfiles;
+    }
+    
+    /**
+     * Creates a temporary zip file containing all files specified by the Option
+     * object and sends it to the server in 80 kB parts
+     * @return The submissionID string or null, if there was an error
+     */
+    private String sendSubmission() {
+        Vector<File> submissionFiles = collectFiles();
+        if(submissionFiles == null) return null;
+        
+        File zipfile = null;
+        FileInputStream input = null;
+        String submissionID = null;
+        
+        try {
+            zipfile = File.createTempFile("jplagtmp",".zip");
+            ZipUtil.zipFilesTo(submissionFiles, option.getOriginalDir(),
+                zipfile);
+
+            input = new FileInputStream(zipfile);
+            
+            int filesize = (int) zipfile.length();
+            int sentsize = 0;
+            int partsize = (filesize<81920) ? filesize : 81920;
+            
+            byte[] data = new byte[partsize];
+            input.read(data);
+            
+            initProgressBar(filesize);
+            
+            StartSubmissionUploadParams params =
+                new StartSubmissionUploadParams(option, filesize, data);
+            
+            submissionID = stub.startSubmissionUpload(params);
+            
+            sentsize += partsize;
+            while(sentsize<filesize-partsize) {
+                setProgressBarValue(sentsize);
+                input.read(data);
+                stub.continueSubmissionUpload(data);
+                sentsize += partsize;
+            }
+            if(sentsize!=filesize) {   // transfer last part
+                setProgressBarValue(sentsize);
+                data = new byte[filesize-sentsize];
+                input.read(data);
+                stub.continueSubmissionUpload(data);
+                sentsize = filesize;
+            }
+            setProgressBarValue(sentsize);
+            input.close();
+            zipfile.delete();
+        }
+        catch(Exception e) {
+            System.out.println();
+            checkException(e);
+            if(input != null) {
+                try { input.close(); } catch(Exception ex) {}
+            }
+            if(zipfile != null) zipfile.delete();
+            return null;
+        }
+        return submissionID;
+    }
+    
+    /**
+     * Retrieves the status of the given submission
+     * @param submissionID submission ID identifying the submission
+     * @return The according status object or null on error
+     */
+    private Status getStatus(String submissionID) {
+        Status status;
+        try {
+            status = stub.getStatus(submissionID);
+        }
+        catch(Exception e) {
+            checkException(e);
+            return null;
+        }
+        return status;
+    }
+    
+    /**
+     * Waits until either the submission has been finished or an error occurred
+     * @param submissionID String identifying the submission
+     * @return True, if the submission has been completed successfully
+     */
+    private boolean waitForResult(String submissionID) {
+        Status status;
+        try {
+            while(true) {
+                status = stub.getStatus(submissionID);
+                
+                /*
+                 * Here you could print out more details about the status of
+                 * the submission, but it's left out here... 
+                 */
+                
+                if(status.getState() >= JPLAG_DONE) break;
+                Thread.sleep(10000);    // wait 10 seconds
+                System.out.print(".");  // tell user something's happening
+            }
+            if(status.getState() >= JPLAG_ERROR) {
+                /*
+                 * An error occurred: Print out error message and acknowledge
+                 * error by cancelling the submission
+                 */
+                System.out.println("\nSome error occurred: "
+                    + status.getReport());
+                stub.cancelSubmission(submissionID);
+                return false;
+            }
+        }
+        catch(Exception e) {
+            checkException(e);
+            return false;
+        }
+        return true;
+    }
+    
+    /**
+     * Downloads and unzips the result
+     * @param submissionID The submission id String
+     * @return True on success
+     */
+    private boolean receiveResult(String submissionID) {
+        File zipfile = null;
+        FileOutputStream output = null;
+        
+        try {
+            File resultDir = new File(resultDirName);
+            if(!resultDir.exists()) resultDir.mkdirs();
+            zipfile = File.createTempFile("jplagtmpresult",".zip");
+            
+            output = new FileOutputStream(zipfile);
+
+            StartResultDownloadData srdd = stub.startResultDownload(
+                submissionID);
+
+            int filesize = srdd.getFilesize();
+            int loadedsize = srdd.getData().length;
+
+            initProgressBar(srdd.getFilesize());
+            output.write(srdd.getData());
+            setProgressBarValue(loadedsize);
+            
+            while(loadedsize<filesize) {
+                byte[] data = stub.continueResultDownload(0);
+                output.write(data);
+                loadedsize += data.length;
+                setProgressBarValue(loadedsize);
+            }
+            output.close();
+            
+            /*
+             * Unzip result archive and delete the zip file
+             */
+            
+            ZipUtil.unzip(zipfile, resultDir);
+            zipfile.delete();
+        }
+        catch(Exception e) {
+            if(output != null) {
+                try { output.close(); } catch(Exception ex) {}
+            }
+            if(zipfile != null) zipfile.delete();
+            checkException(e);
+            return false;
+        }            
+            
+        return true;
+    }
+    
+    /**
+     * Cancels the submission identified by submissionID
+     * @param submissionID The submission id string
+     * @return True on success
+     */
+    private boolean cancelSubmission(String submissionID) {
+        try {
+            stub.cancelSubmission(submissionID);
+        }
+        catch(Exception e) {
+            checkException(e);
+            return false;
+        }
+        return true;
+    }
+    
+    /**
+     * Checks the current options for validity using the information provided
+     * by the ServerInfo object and fills remaining empty fields with defaults.
+     * If "-l ?" or "-cl ?" is used, a list of valid languages respectively
+     * country languages is printed and false is returned.
+     * @param info ServerInfo object
+     * @return True, if all options are legal
+     */
+    private boolean checkOptions(ServerInfo info) {
+        LanguageInfo[] languages = info.getLanguageInfos();
+        String[] countryLangs = info.getCountryLanguages();
+        int i;
+        
+        if(option.getLanguage() == null) {
+            i = 0;
+            option.setLanguage(languages[0].getName());
+            System.out.println("Using default language: "
+                + languages[0].getName());
+        }
+        else {
+            for(i=0; i<languages.length; i++) {
+                if(option.getLanguage().equals(languages[i].getName())) break;
+            }
+            if(i==languages.length) {
+                if(!option.getLanguage().equals("?"))
+                    System.out.println("Unknown language: \""
+                        + option.getLanguage() + "\"");
+                System.out.println("\nAvailable languages:");
+                for(i=0; i<languages.length; i++) {
+                    System.out.println(" - \"" + languages[i].getName()
+                        + "\"" + (i==0 ? " (default language)\n" : "\n")
+                        + "   default minimum match length = "
+                        + languages[i].getDefMinMatchLen()
+                        + "\n   default suffixes: "
+                        + arrayToString(languages[i].getSuffixes()));
+                }
+                return false;
+            }
+        }
+        if(suffixes == null) {
+            suffixes = languages[i].getSuffixes();
+            System.out.println("Using default suffixes: "
+                + arrayToString(suffixes));
+        }
+        
+        if(option.getTitle() == null) 
+            option.setTitle("submission-"
+                + new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
+        
+        if(option.getCountryLang() == null)
+            option.setCountryLang("en");
+        else {
+            for(i=0; i<countryLangs.length; i++) {
+                if(option.getCountryLang().equals(countryLangs[i])) break;
+            }
+            if(i==countryLangs.length) {
+                if(!option.getCountryLang().equals("?"))
+                    System.out.println("Unknown country language: \""
+                        + option.getCountryLang() + "\"");
+                System.out.println("\nAvailable country languages:");
+                for(i=0; i<countryLangs.length; i++) {
+                    System.out.println(" - \"" + countryLangs[i]
+                        + (i==0 ? "\" (default)" : "\""));
+                }
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * Parses the arguments and sets the appropriate attributes
+     * @param args Array of argument strings
+     * @return True, if no error was noticed like missing login data
+     */
+    private boolean parseArguments(String[] args) {
+        boolean requestDetails = false;
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-user") && i+1<args.length) {
+                i++;
+                username = args[i];
+            }
+            else if(args[i].equals("-pass") && i+1<args.length) {
+                i++;
+                password = args[i];
+            }
+            else if(args[i].equals("-l") && i+1<args.length) {
+                i++;
+                option.setLanguage(args[i]);
+                if(args[i].equals("?")) requestDetails = true;
+            }
+            else if(args[i].equals("-cl") && i+1<args.length) {
+                i++;
+                option.setCountryLang(args[i]);
+                if(args[i].equals("?")) requestDetails = true;
+            }
+            else if(args[i].equals("-s")) {
+                option.setReadSubdirs(true);
+            }
+            else if(args[i].equals("-S") && i+1<args.length) {
+                i++;
+                option.setPathToFiles(args[i]);
+            }
+            else if(args[i].equals("-p") && i+1<args.length) {
+                i++;
+                suffixes = args[i].split(",");
+                option.setSuffixes(suffixes);
+            }
+            else if(args[i].equals("-t") && i+1<args.length) {
+                i++;
+                try {
+                    option.setMinimumMatchLength(Integer.parseInt(args[i]));
+                }
+                catch(NumberFormatException e) {
+                    System.out.println("Illegal minimum match length: "
+                        + args[i] + "\nMust be an integer!");
+                    return false;
+                }
+            }
+            else if(args[i].equals("-m") && i+1<args.length) {
+                i++;
+                option.setStoreMatches(args[i]);
+            }
+            else if(args[i].equals("-bc") && i+1<args.length) {
+                i++;
+                option.setBasecodeDir(args[i]);
+            }
+            else if(args[i].equals("-r") && i+1<args.length) {
+                i++;
+                resultDirName = args[i];
+            }
+            else if(args[i].equals("-title") && i+1<args.length) {
+                i++;
+                option.setTitle(args[i]);
+            }
+            else if(args[i].equals("-list")) {
+                listSubmissions = true;
+            }
+            else if(args[i].equals("-download")) {
+                if(i+1<args.length && Character.isDigit(args[i+1].charAt(0))) {
+                    // isDigit is true => positive value
+                    i++;
+                    try {
+                        downloadResultNumber = Integer.parseInt(args[i]);
+                    }
+                    catch(NumberFormatException e) {
+                        System.out.println("Illegal download number: "
+                            + args[i] + "\nMust be an positive integer!");
+                        return false;
+                    }
+                }
+                else downloadResultNumber = 1;
+            }
+            else if(args[i].equals("-cancel")) {
+                if(i+1<args.length && Character.isDigit(args[i+1].charAt(0))) {
+                    // isDigit is true => positive value
+                    i++;
+                    try {
+                        cancelSubmissionNumber = Integer.parseInt(args[i]);
+                    }
+                    catch(NumberFormatException e) {
+                        System.out.println("Illegal cancel number: "
+                            + args[i] + "\nMust be an positive integer!");
+                        return false;
+                    }
+                }
+                else cancelSubmissionNumber = 1;
+            }
+            else if(args[i].startsWith("-")) {
+                System.out.println("Unknown option: " + args[i]);
+                return false;
+            }
+            else
+            {
+                if(option.getOriginalDir() != null) {
+                    System.out.println("The rootdir has already been defined "
+                        + "as \"" + option.getOriginalDir() + "\"!");
+                    return false;
+                }
+                option.setOriginalDir(args[i]);
+            }
+        }
+        boolean valid = true;
+        if(username == null) {
+            System.out.println("Username is missing!");
+            valid = false;
+        }
+        if(password == null) {
+            System.out.println("Password is missing!");
+            valid = false;
+        }
+        if(!requestDetails && !listSubmissions && downloadResultNumber == 0
+                && cancelSubmissionNumber == 0
+                && option.getOriginalDir() == null) {
+            System.out.println("You must specify either a \"root-dir\", the "
+                + "\"-list\", the \"-download\"\nor the \"-cancel\" option!");
+            valid = false;
+        }
+        return valid;
+    }
+    
+    /**
+     * Initializes a text progress bar
+     */
+    public void initProgressBar(int max) {
+        progressMax = max;
+        progressPos = 0;
+        System.out.println(
+            "0%----------+----------50%-----------+--------100%");
+    }
+    
+    /**
+     * Sets the current value of the progress bar updating the current position
+     * The progress may only increase, not decrease!
+     */
+    public void setProgressBarValue(int val) {
+        int pos = (val*50)/progressMax;
+        if(pos <= progressPos) return;
+        
+        System.out.print("##################################################"
+            .substring(progressPos, pos));
+        progressPos = pos;
+    }
+    
+    /**
+     * Prints out how to use the program
+     */
+    public static void printUsage() {
+        System.out.println(
+            "\nUsage: ExampleClient [options] (<root-dir> | -list | -download [<n>]\n"
+            + "                                | -cancel [<n>])\n"
+            + "<root-dir> The directory which contains all programs\n"
+            + "Options are:\n"
+            + " -user <username>  Sets the username (required).\n"
+            + " -pass <password>  Sets the password (required).\n"
+            + " -l <language>     (Language) Programming language.\n"
+            + "                   (\"-l ?\" for supported and default languages.\n"
+            + "                   Also lists default suffixes and minimum match length)\n"
+            + " -S <dir>          Look in directories <root-dir>/*/<dir> for programs.\n"
+            + "                   (default: <root-dir>/*)\n"
+            + " -s                (Subdirs) Look at files in subdirs, too. (default: disabled)\n"
+            + " -p <suffixes>     <suffixes> is a comma-separated list of filename suffixes\n"
+            + "                   to be included. (default: language specific)\n"
+            + " -t <n>            (Token) Set the minimum match length in tokens.\n"
+            + "                   A smaller <n> increases the sensitivity of the comparison.\n"
+            + " -m <n>            (Matches) Number of matches that will be saved. (default:20)\n"
+            + " -m <p>%           Saves all matches with more than <p>% average similitarity.\n"
+            + " -bc <dir>         Name of the directory containing the basecode\n"
+            + "                   (common framework).\n"
+            + " -r <dir>          (Result) Name of directory where the result pages will\n"
+            + "                   be stored. (default: result)\n"
+            + " -title <title>    Title of this submission (default: submission-<date>)\n"
+            + " -cl <locale>      (Country language) Language the result files will\n"
+            + "                   be written in.\n"
+            + "                   (\"-cl ?\" for supported country languages and default)\n"
+            + " -list             Lists all submissions on the server belonging to the user.\n"
+            + " -download [<n>]   Downloads the <n>-th submission from server.\n"
+            + "                   The <n>-th submission must be \"done\".\n"
+            + "                   All non required options except \"-r <dir>\" will be ignored.\n"
+            + " -cancel [<n>]     Cancels the <n>-th submission on server.\n"
+            + "                   All non required options will be ignored.\n");
+    }
+    
+    /**
+     * Concatenates the string representations of objects in an array
+     * @param array Object array
+     * @return Comma-separated list of string representations of those objects
+     */
+    private String arrayToString(Object[] array) {
+        String str = "";
+        for(int i=0; i<array.length; i++) {
+            str += array[i].toString();
+            if(i!=array.length-1) str += ",";
+        }
+        return str;
+    }
+    
+    /**
+     * The main routine
+     * @param args Array of command line parameters
+     */
+    public void run(String[] args) {
+        if(args.length == 0 || !parseArguments(args)) {
+            printUsage();
+            return;
+        }
+        
+        if(!initJPlagStub()) {
+            System.out.println("Unable to initialize JPlag stub!");
+            return;
+        }
+        
+        /*
+         * Get a ServerInfo object
+         */
+        
+        ServerInfo info;
+        try {
+            info = stub.getServerInfo();
+        }
+        catch(Exception e) {
+            checkException(e);
+            return;
+        }
+        
+        /*
+         * Check for submissions on server by looking at submissions field
+         * in the ServerInfo object
+         */ 
+        
+        Submission[] subs = info.getSubmissions();
+        
+        if(subs.length > 0) {
+            System.out.println("\nSubmissions on server with states:\n");
+            for(int i=0; i<subs.length; i++) {
+                System.out.println(" " + (i+1) + ". \"" + subs[i].getTitle()
+                    + "\" on " + subs[i].getDate());
+                String stateString = "";
+                switch(subs[i].getLastState()) {
+                    case JPLAG_UPLOADING: // can not occur in this application
+                        stateString = "uploading";
+                        break;
+                    case JPLAG_INQUEUE: stateString = "in queue"; break;
+                    case JPLAG_PARSING: stateString = "parsing"; break;
+                    case JPLAG_COMPARING: stateString = "comparing"; break;
+                    case JPLAG_GENRESULT:
+                        stateString = "generating result files";
+                        break;
+                    case JPLAG_PACKRESULT:
+                        stateString = "packing result files";
+                        break;
+                    case JPLAG_DONE: stateString = "done"; break;
+                    default: {
+                        // an error occurred, so get more details
+                        Status status = getStatus(subs[i].getSubmissionID());
+                        if(status == null)
+                            stateString = "unable to retrieve status";
+                        else
+                            stateString = status.getReport();
+                    }
+                }
+                System.out.println("    (" + stateString + ")");
+            }
+            
+            if(listSubmissions) return;
+            
+            /*
+             * If "-download" is used, download the n-th submission
+             */
+            if(downloadResultNumber != 0) {
+                if(downloadResultNumber > subs.length) {
+                    System.out.println("Illegal download number!\n"
+                        + "There are only " + subs.length + " submissions!");
+                    return;
+                }
+                Submission sub = subs[downloadResultNumber-1];
+                if(sub.getLastState() != 300) {
+                    System.out.println("Illegal download number!\n"
+                        + "You can only download results for successfully"
+                        + " finished submissions!");
+                    return;
+                }
+                System.out.print("Downloading \"" + sub.getTitle()
+                    + "\"...");
+                if(!receiveResult(sub.getSubmissionID())) return;
+                System.out.println(" completed.\nThe result files are available"
+                    + " in \"" + resultDirName + "\"");
+                return;
+            }
+            
+            /*
+             * If "-cancel" is used, cancel the n-th submission
+             */
+            if(cancelSubmissionNumber != 0) {
+                if(cancelSubmissionNumber > subs.length) {
+                    System.out.println("Illegal cancel number!\n"
+                        + "There are only " + subs.length + " submissions!");
+                    return;
+                }
+                Submission sub = subs[cancelSubmissionNumber-1];
+                System.out.print("Cancelling \"" + sub.getTitle()
+                    + "\"...");
+                if(!cancelSubmission(sub.getSubmissionID())) return;
+                System.out.println(" completed.\n");
+                return;
+            }
+        }
+        else if(downloadResultNumber != 0 || cancelSubmissionNumber != 0
+                || listSubmissions) {
+            System.out.println("\nCurrently there are no submissions on the "
+                + "server for this user!");
+            return;
+        }
+
+        if(!checkOptions(info)) return;
+        
+        System.out.println("\nSending files...");
+        String submissionID = sendSubmission();
+        if(submissionID == null) return;
+        
+        System.out.print("\n\nWaiting for result...");
+        if(!waitForResult(submissionID)) return;
+        
+        System.out.println(" result available.\n\nDownloading...");
+        if(!receiveResult(submissionID)) return;
+        
+        System.out.println("\n\nThe result files are available in \""
+            + resultDirName + "\"");
+    }
+    
+    public static void main(String[] args) {
+        new ExampleClient().run(args);
+    }
+}

+ 178 - 0
jplag.webServiceClientTutorial/src/main/java/jplagTutorial/ExampleConnect.java

@@ -0,0 +1,178 @@
+package jplagTutorial;
+
+import java.rmi.RemoteException;
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.xml.rpc.handler.Handler;
+import javax.xml.rpc.handler.HandlerChain;
+
+import com.sun.xml.rpc.client.ClientTransportException;
+import com.sun.xml.rpc.util.exception.JAXRPCExceptionBase;
+
+import jplagTutorial.util.JPlagClientAccessHandler;
+import jplagTutorial.jplagClient.JPlagException;
+import jplagTutorial.jplagClient.JPlagService_Impl;
+import jplagTutorial.jplagClient.JPlagTyp_Stub;
+import jplagTutorial.jplagClient.LanguageInfo;
+import jplagTutorial.jplagClient.ServerInfo;
+import jplagTutorial.jplagClient.Submission;
+import jplagTutorial.jplagClient.UserInfo;
+
+public class ExampleConnect {
+    /**
+     * Helper function to easily evaluate web service related exceptions
+     * @param e Exception thrown by a stub method
+     */
+    public static void checkException(Exception e) {
+        if(e instanceof JPlagException) {
+            JPlagException je = (JPlagException) e;
+            System.out.println("JPlagException: " + je.getDescription()
+                + "\n" + je.getRepair());
+        }
+        else if(e instanceof RemoteException) {
+            RemoteException re = (RemoteException) e;
+            Throwable cause = re.getCause();
+            if(cause != null && cause instanceof ClientTransportException) {
+                cause = ((JAXRPCExceptionBase) cause).getLinkedException();
+                if(cause != null) {
+                    System.out.println("Connection exception: "
+                        + cause.getMessage());
+                    return;
+                }
+            }
+            System.out.println("Unexpected RemoteException: "
+                + re.getMessage());
+            re.printStackTrace();
+        }
+        else {
+            System.out.println("Unexpected Exception: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+    
+    public static void main(String[] args) {
+        String username = null, password = null;
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-user") && i+1<args.length) {
+                i++;
+                username = args[i];
+            }
+            else if(args[i].equals("-pass") && i+1<args.length) {
+                i++;
+                password = args[i];
+            }
+        }
+        if(username == null || password == null) {
+            System.out.println("Usage: ExampleConnect [options]\n"
+                + "Options are:\n"
+                + " -user <username>      Sets the username (required)\n"
+                + " -pass <password>      Sets the password (required)\n");
+            return;
+        }
+        
+        // Create a trust manager that does not validate certificate chains
+        TrustManager[] trustAllCerts = new TrustManager[] {
+            new X509TrustManager() {
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+                public void checkClientTrusted(X509Certificate[] certs,
+                        String authType) {
+                }
+                public void checkServerTrusted(X509Certificate[] certs,
+                        String authType) {
+                }
+            }
+        };
+        
+        // Install the all-trusting trust manager
+        try {
+            SSLContext sc = SSLContext.getInstance("SSL");
+            sc.init(null, trustAllCerts, new java.security.SecureRandom());
+            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+        } catch (Exception e) {
+            System.out.println("Warning: Unable to install all-trusting trust "
+                + "manager! SSL connection may not work!");
+        }
+        
+        // Get JPlag client stub
+        
+        JPlagTyp_Stub stub = (JPlagTyp_Stub) (new JPlagService_Impl()
+                .getJPlagServicePort());
+                
+        // Search for the JPlagClientAccessHandler in the handler chain
+
+        HandlerChain handlerchain = stub._getHandlerChain();
+        Iterator handlers = handlerchain.iterator();
+        JPlagClientAccessHandler accessHandler = null;
+        while(handlers.hasNext()) {
+            Handler handler = (Handler) handlers.next();
+            if(handler instanceof JPlagClientAccessHandler) {
+                accessHandler = (JPlagClientAccessHandler) handler;
+                break;
+            }
+        }
+        
+        if(accessHandler == null) {
+            System.out.println("Unable to find access handler!");
+            return;
+        }
+        
+        // Initialize access handler
+        
+        accessHandler.setUserPassObjects(username, password);
+        
+        // Get ServerInfo and print out some infos
+        
+        ServerInfo info;
+        
+        try {
+            info = stub.getServerInfo();
+        } catch(Exception e) {
+            checkException(e);
+            return;
+        }
+        
+        UserInfo userinfo = info.getUserInfo();
+        System.out.println("User info:\n Email: " + userinfo.getEmail()
+            + "\n Alternative email: " + userinfo.getEmailSecond()
+            + "\n Homepage: " + userinfo.getHomepage());
+        
+        System.out.println("\nAvailable languages:");
+        LanguageInfo[] languages = info.getLanguageInfos();
+        for(int i=0; i<languages.length; i++) {
+            System.out.print(" - \"" + languages[i].getName()
+                + "\"\n   default minimum match length = "
+                + languages[i].getDefMinMatchLen()
+                + "\n   default suffixes: ");
+            String[] suffixes = languages[i].getSuffixes();
+            for(int j=0; j<suffixes.length; j++) {
+                System.out.print(suffixes[j]
+                    + ((j==suffixes.length-1) ? "\n" : ", "));
+            }
+        }
+
+        System.out.println("\nAvailable country languages:");
+        String[] countryLangs = info.getCountryLanguages();
+        for(int i=0; i<countryLangs.length; i++)
+            System.out.println(" - \"" + countryLangs[i] + "\"");
+        
+        Submission[] subs = info.getSubmissions();
+        if(subs.length == 0) {
+            System.out.println("\nCurrently there are no submissions on the "
+                + "server for this user!");
+        }
+        else {
+            System.out.println("\nAvailable submissions with states:\n");
+            for(int i=0; i<subs.length; i++) {
+                System.out.println(" - \"" + subs[i].getTitle() + "\" ("
+                    + subs[i].getLastState() + ")");
+            }
+        }
+    }
+}

+ 112 - 0
jplag.webServiceClientTutorial/src/main/java/jplagTutorial/util/JPlagClientAccessHandler.java

@@ -0,0 +1,112 @@
+/*
+ * Created on 15.03.2005
+ * 
+ * For more information about SOAP headers see:
+ *   http://java.sun.com/webservices/docs/1.3/tutorial/doc/JAXRPC7.html#wp122942
+ */
+package jplagTutorial.util;
+
+import javax.xml.namespace.QName;
+import javax.xml.rpc.handler.GenericHandler;
+import javax.xml.rpc.handler.HandlerInfo;
+import javax.xml.rpc.handler.MessageContext;
+import javax.xml.rpc.handler.soap.SOAPMessageContext;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPEnvelope;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPHeader;
+import javax.xml.soap.SOAPHeaderElement;
+import javax.xml.soap.SOAPMessage;
+
+/**
+ * @author Moritz Kroll
+ */
+public class JPlagClientAccessHandler extends GenericHandler {
+    public static final int compatibilityLevel = 4;
+	protected HandlerInfo info=null;
+	
+	/*
+	 * Access information used to build up the Access header element
+	 */
+	
+	protected String username=null;
+	protected String password=null;
+
+	/**
+	 * Return the headers given by the info HandlerInfo object
+	 */
+	public QName[] getHeaders() {
+		return info.getHeaders();
+	}
+
+	/**
+	 * Save the HandlerInfo object
+	 */
+	public void init(HandlerInfo arg) {
+		info=arg;
+	}
+	
+	/**
+	 * Used to set the username and password
+	 * Use something like the following to access this function:
+	 * 
+	 * 	private JPlagClientAccessHandler accessHandler=null;
+	 * 
+	 * 	[...]
+	 * 
+	 * 		HandlerChain handlerchain=stub._getHandlerChain();
+	 *		Iterator handlers=handlerchain.iterator();
+	 *		while(handlers.hasNext())
+	 *		{
+	 *			Handler handler=(Handler) handlers.next();
+	 *			if(handler instanceof JPlagClientAccessHandler)
+	 *			{
+	 *				accessHandler=((JPlagClientAccessHandler)handler);
+	 *				break;
+	 *			}
+	 *		}
+	 *		if(accessHandler!=null)
+	 *		{
+	 *			accessHandler.setUserPassObjects(getJUsernameField().getText(),
+	 *				getJPasswordField().getText());
+	 *		}
+	 */
+	public void setUserPassObjects(String username, String password) {
+		this.username=username;
+		this.password=password;
+	}
+	
+	/**
+	 * Adds an "Access" element to the SOAP header
+	 */
+	public boolean handleRequest(MessageContext msgct) {
+		if(msgct instanceof SOAPMessageContext) {
+			SOAPMessageContext smsgct=(SOAPMessageContext) msgct;
+			try	{
+				SOAPMessage msg=smsgct.getMessage();
+				SOAPEnvelope envelope=msg.getSOAPPart().getEnvelope();
+				SOAPHeader header=msg.getSOAPHeader();
+				
+				if(header==null)
+					header=envelope.addHeader(); // add an header if non exists
+				
+				SOAPHeaderElement accessElement=header.addHeaderElement(
+						envelope.createName("Access","ns0",
+								"http://www.ipd.uni-karlsruhe.de/jplag/types"));
+				SOAPElement usernameelem=accessElement.addChildElement(
+                        "username");
+				usernameelem.addTextNode(username);
+				SOAPElement passwordelem=accessElement.addChildElement(
+                        "password");
+				passwordelem.addTextNode(password);
+                SOAPElement compatelem=accessElement.addChildElement(
+                        "compatLevel");
+                compatelem.addTextNode(compatibilityLevel+"");
+			} catch (SOAPException x) {
+				System.out.println("Unable to create access SOAP header!");
+				x.printStackTrace();
+			}
+		}
+		return true;
+	}
+}

+ 221 - 0
jplag.webServiceClientTutorial/src/main/java/jplagTutorial/util/ZipUtil.java

@@ -0,0 +1,221 @@
+/*
+ * Created on 10.02.2005
+ */
+package jplagTutorial.util;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+public class ZipUtil {
+    /**
+     * Zips the given directory "dir" into a zip file in "dest"
+     * @param dir File denoting the directory to be zipped
+     * @param dest Name of the directory where the zipped file will be stored,
+     *   which will be named dir.getName()+".zip"
+     * @return zipped file
+     */
+    public static File zip(File dir, String dest) {
+        File zippedFile = new File(dest + "/" + dir.getName() + ".zip");
+        zipTo(dir, zippedFile);
+        return zippedFile;
+    }
+
+    /**
+     * Zips the given directory "dir" into the zip file "destFile".
+     * If "destFile" already exists, it will be overwritten
+     * @param dir Directory to be zipped
+     * @param destFile Destination file
+     */
+    public static void zipTo(File dir, File destFile) {
+        FileOutputStream ops = null;
+        ZipOutputStream zos = null;
+        try {
+            ops = new FileOutputStream(destFile);
+            zos = new ZipOutputStream(ops);
+            zipDir(dir, zos, "");
+        } catch(FileNotFoundException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if(zos != null)
+                    zos.close();
+                else if(ops != null)
+                    ops.close();
+            } catch(IOException e) {
+                e.printStackTrace();
+            }            
+        }
+    }
+
+    /**
+     * Recursively zips all files in "dir" and its subdirectories into the given
+     * ZipOutputStream "zos" using the given path prefix for their names
+     */
+    private static void zipDir(File dir, ZipOutputStream zos, String prefix) {
+        File[] entries = dir.listFiles();
+        for(int i = 0; i < entries.length; i++) {
+            if(entries[i].isDirectory()) {
+                // generate directory entry
+                ZipEntry zi = new ZipEntry(prefix + "/" + entries[i].getName()
+                        + "/");
+                try {
+                    zos.putNextEntry(zi);
+                    zos.closeEntry();
+                } catch(IOException ioex) {
+                    ioex.printStackTrace();
+                }
+                zipDir(entries[i], zos, prefix + "/" + entries[i].getName());
+            } else {
+                FileInputStream fis = null;
+                try {
+                    fis = new FileInputStream(entries[i]);
+                    ZipEntry zi = new ZipEntry(prefix + "/"
+                            + entries[i].getName());
+                    zos.putNextEntry(zi);
+                    copystream(fis, zos);
+                    zos.closeEntry();
+                } catch(FileNotFoundException ex) {
+                    ex.printStackTrace();
+                } catch(IOException ioex) {
+                    ioex.printStackTrace();
+                } finally {
+                    try {
+                        if(fis != null)
+                            fis.close();
+                    } catch(Exception e) {}
+                }
+            }
+        }
+    }
+    
+    /**
+     * Zips all files in "fileVector" to the zipfile "destFile".
+     * The pathnames of all files in fileVector must start with baseDir!
+     * @param fileVector Files to be zipped
+     * @param baseDir Root directory for this zip file
+     * @param destFile Destination file
+     */
+    public static void zipFilesTo(Vector<File> fileVector, String baseDir,
+            File destFile) {
+        FileOutputStream ops = null;
+        ZipOutputStream zos = null;
+        int basedirlen = baseDir.length();
+        if(!baseDir.endsWith(File.separator)) basedirlen++;
+        try {
+            ops = new FileOutputStream(destFile);
+            zos = new ZipOutputStream(ops);
+            
+            Iterator<File> iter = fileVector.iterator();
+            while(iter.hasNext()) {
+                File file = iter.next();
+                FileInputStream fis = null;
+                try {
+                    fis = new FileInputStream(file);
+                    String name = file.getPath().substring(basedirlen);
+                    name = name.replace('\\', '/'); // Zip uses '/' as separator
+                    ZipEntry zi = new ZipEntry(name);
+                    zos.putNextEntry(zi);
+                    copystream(fis, zos);
+                    zos.closeEntry();
+                } catch(FileNotFoundException e) {
+                    e.printStackTrace();
+                } catch(IOException e) {
+                    e.printStackTrace();
+                } finally {
+                    try {
+                        if(fis != null)
+                            fis.close();
+                    } catch(Exception e) {}
+                }
+            }
+        } catch(FileNotFoundException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if(zos != null)
+                    zos.close();
+                else if(ops != null)
+                    ops.close();
+            } catch(IOException e) {
+                e.printStackTrace();
+            }            
+        }
+    }
+
+    /**
+     * Unzips the zip file "file" into the directory "dest"
+     * @param file The zip file
+     * @param destDir Directory where the content of the zip file will be saved
+     */
+    public static void unzip(File file, File destDir) {
+        destDir.mkdir();
+        try {
+            ZipFile zipFile = new ZipFile(file);
+            Enumeration entries = zipFile.entries();
+            while(entries.hasMoreElements()) {
+                ZipEntry ze = (ZipEntry) entries.nextElement();
+                if(ze.isDirectory())
+                    (new File(destDir, ze.getName())).mkdir();
+                else {
+                    // make sure directories exist in case the client
+                    // didn't provide directory entries!
+
+                    File f = new File(destDir, ze.getName());
+                    (new File(f.getParent())).mkdirs();
+
+                    FileOutputStream fos = null;
+                    BufferedOutputStream bos = null;
+                    InputStream in = null;
+                    try {
+                        fos = new FileOutputStream(f);
+                        bos = new BufferedOutputStream(fos);
+                        in = zipFile.getInputStream(ze);
+                        copystream(in, bos);
+                    } finally {
+                        if(bos != null)
+                            bos.close();
+                        else if(fos != null)
+                            fos.close();
+                        if(in != null)
+                            in.close();
+                    }
+                }
+            }
+        } catch(IOException ioex) {
+            ioex.printStackTrace();
+        }
+    }
+
+    /**
+     * Copies the input stream to the output stream using a 1 kB buffer
+     * @throws IOException
+     */
+    private static void copystream(InputStream in, OutputStream out)
+            throws IOException
+    {
+        byte[] buffer = new byte[1024];
+        int len;
+
+        while((len = in.read(buffer)) >= 0)
+            out.write(buffer, 0, len);
+    }
+    
+    public static void main(String[] args) {
+        // zip(new File("/home/bikiri/Desktop/jplag-old"),
+        // "/home/bikiri/Desktop");
+        unzip(new File("/home/bikiri/Desktop/emma.zip"),
+            new File("/home/bikiri/Desktop","unzipresult"));
+    }
+}

+ 40 - 0
jplag.webServiceClientTutorial/src/main/java/jplagTutorial/util/wscompileSSLLauncher.java

@@ -0,0 +1,40 @@
+package jplagTutorial.util;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import com.sun.xml.rpc.tools.ant.Wscompile;
+
+/**
+ * @author Moritz Kroll
+ */
+public class wscompileSSLLauncher extends Wscompile {
+	public wscompileSSLLauncher() {
+		super();
+        
+		// Create a trust manager that does not validate certificate chains
+	    TrustManager[] trustAllCerts = new TrustManager[]{
+	        new X509TrustManager() {
+	            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+	                return null;
+	            }
+	            public void checkClientTrusted(
+	                java.security.cert.X509Certificate[] certs, String authType) {
+	            }
+	            public void checkServerTrusted(
+	                java.security.cert.X509Certificate[] certs, String authType) {
+	            }
+	        }
+	    };
+	    
+	    // Install the all-trusting trust manager
+	    try {
+	        SSLContext sc = SSLContext.getInstance("SSL");
+	        sc.init(null, trustAllCerts, new java.security.SecureRandom());
+	        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+	    } catch (Exception e) {
+	    }
+	}
+}

+ 8 - 0
jplag.webServiceClientTutorial/wscompile-config.xml

@@ -0,0 +1,8 @@
+<!-- Sets up a wscompile task which allows untrusted certificates
+     to be used for SSL -->
+<taskdef name="wscompile" classname="jplagTutorial.util.wscompileSSLLauncher">
+	<classpath>
+		<path refid="client.classpath" />
+		<pathelement path="${basedir}/classes/util"/>
+	</classpath>
+</taskdef>