wiki:Client/Development/SendingSubmissions

Sending a submission (Java)

Sending a submission to the server is done by providing a set of options (including things like which parser is to be used and how the directory structure will look like) and a ZIP file containing the files to be compared using the specified directory structure.

Let's have a look at the Option object first:

Attribute Type Description
languageStringProgramming language. See getServerInfo response for available languages.
minimumMatchLengthintMinimum match length in tokens. A smaller value increases the sensitivity of the comparison.If set to 0 or below, a language specific default value is used.
suffixesString[]List of case sensitive file suffixes (e.g. {".c", ".C"}) (default: language specific, if empty)
readSubdirsbooleanIf true, also looks at files in subdirectories.
pathToFilesStringLook in directories /*/<pathToFiles/> for files (default: <root-dir/>/*, if null or "")
basecodeDirStringName of directory containing the basecode (common framework) (null or "", if unused)
storeMatchesStringThis can be either the number of matches being saved (default is 20, if null or "") or the minimum similarity percentage to be saved as a match (with a trailing "%")
clustertypeStringDefines the type of clustering. Possible values: null or "" : no clustering (default) or "min" or "avr" or "max"
countryLangStringCountry language the result files will be written in. See getServerInfo response for available country languages.
titleStringTitle describing the submission and being displayed in the result files.
originalDirStringString to be displayed in the result files as the directory where the source code comes from.

Now we have to create the ZIP file with the correct directory structure. With the provided ZipUtil? class you just have to provide a Vector<File> object, the base directory and a destination file. To create a proper Vector<File> object matching the used options we use the following code:

    /**
     * Options for JPlag specified by the command line
     */
    private Option option = new Option();

    /**
     * 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;

    /**
     * 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() 

With this code we can now create the ZIP file as follows:

        Vector submissionFiles = collectFiles();
        if(submissionFiles == null) return null;
        
        File zipfile = null;
        FileInputStream input = null;   // only for parts version
        String submissionID = null;
        
        try {
            zipfile = File.createTempFile("jplagtmp",".zip");
            ZipUtil.zipFilesTo(submissionFiles, option.getOriginalDir(),
                zipfile);

Now there are two ways to upload the submission onto the server:

  1. The ZIP file can be uploaded in 80 kB parts with startSubmissionUpload and continueSubmissionUpload, which allows aborting and showing the progress of the upload during the upload, but blows up the data transferred by a factor of 1.34 because of Base64 encoding. Probably best option for user clients. For this version the rest of the code above would look like this:
                    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;
    
  2. The ZIP file can be uploaded in one single part with compareSource using a MimeMultipart? object without the ability to abort or show progress, but without any blow up. Probably best option for batch servers. If you want to use this version, the code will look like this:
                    FileDataSource fds = new FileDataSource(zipfile);
                    MimeMultipart mmp = new MimeMultipart();
                    MimeBodyPart mbp = new MimeBodyPart();
                    mbp.setDataHandler(new DataHandler(fds));
                    mbp.setFileName(zipfile.getName());
                    mmp.addBodyPart(mbp);
                    
                    submissionID = stub.compareSource(option, mmp);
                    zipfile.delete();
                }
                catch(Exception e) {
                    System.out.println();
                    checkException(e);
                    if(zipfile != null) zipfile.delete();
                    return null;
                }
                return submissionID;
    

Next: Waiting for a result

Last modified 5 years ago Last modified on Dec 7, 2012 11:13:42 AM