Java tutorial
/** * Marmoset: a student project snapshot, submission, testing and code review * system developed by the Univ. of Maryland, College Park * * Developed as part of Jaime Spacco's Ph.D. thesis work, continuing effort led * by William Pugh. See http://marmoset.cs.umd.edu/ * * Copyright 2005 - 2011, Univ. of Maryland * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * */ /* * Created on Jan 21, 2005 */ package edu.umd.cs.buildServer.builder; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Node; import org.dom4j.io.SAXReader; import edu.umd.cs.buildServer.BuilderException; import edu.umd.cs.marmoset.utilities.ZipExtractorException; /** * SubmissionExtractor for Java submissions. * * @author David Hovemeyer */ public class JavaSubmissionExtractor extends SubmissionExtractor { // Constants private static final String SRC_ENTRY_XPATH = "/classpath/classpathentry[@kind='src']"; // Fields private String classpathFile; // Eclipse .classpath file private List<Pattern> excludedSourceFileList; /** * Constructor. * * @param zipFile * the submission zipfile * @param directory * directory to extract the submission into * @param buildServerLog * the buildserver's Log * @throws BuilderException */ public JavaSubmissionExtractor(File zipFile, File directory, Logger buildServerLog) throws ZipExtractorException { super(zipFile, directory, buildServerLog); this.classpathFile = null; this.excludedSourceFileList = new LinkedList<Pattern>(); } /** * Add a regex pattern specifying source file(s) to exclude. * * @param pattern * exclusion regex pattern */ public void addExcludedSourceFilePattern(String pattern) { try { Pattern regex = Pattern.compile(pattern); excludedSourceFileList.add(regex); } catch (PatternSyntaxException e) { getLog().warn("Could not compile source file exclusion pattern " + pattern, e); } } /* * (non-Javadoc) * * @see * edu.umd.cs.buildServer.ZipExtractor#successfulFileExtraction(java.lang * .String, java.lang.String) */ @Override protected void successfulFileExtraction(String entryName, String fileName) { super.successfulFileExtraction(entryName, fileName); if (fileName.equals(".classpath")) { classpathFile = fileName; } } /* * (non-Javadoc) * * @see * edu.umd.cs.buildServer.SubmissionExtractor#isSourceFile(java.lang.String) */ @Override protected boolean isSourceFile(String fileName) { return fileName.endsWith(".java"); } /* * (non-Javadoc) * * @see * edu.umd.cs.buildServer.SubmissionExtractor#pruneSourceFileList(java.util * .List) */ @Override protected void pruneSourceFileList(List<String> sourceFileList) { // Apply exclusion patterns, if any if (excludedSourceFileList.size() > 0) { outer: for (Iterator<String> i = sourceFileList.iterator(); i.hasNext();) { String sourceFile = i.next(); for (Iterator<Pattern> j = excludedSourceFileList.iterator(); j.hasNext();) { Pattern regex = j.next(); Matcher m = regex.matcher(sourceFile); if (m.matches()) { i.remove(); continue outer; } } } } if (classpathFile == null) return; // The submission contained a .classpath file. // Try to read it so we can find out the sourcepath // and remove all entries that aren't on the sourcepath // from the source files list. try { List<String> sourcePath = new LinkedList<String>(); InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(new File(getDirectory(), classpathFile))); SAXReader reader = new SAXReader(); Document document = reader.read(in); for (Iterator<?> i = document.selectNodes(SRC_ENTRY_XPATH).iterator(); i.hasNext();) { Node node = (Node) i.next(); String srcPathEntry = node.valueOf("@path"); if (!srcPathEntry.equals("") && !srcPathEntry.endsWith("/")) srcPathEntry += "/"; sourcePath.add(srcPathEntry); } if (!allSourcePathsExist(sourcePath)) return; // Remove all files that don't begin with a valid source path // element from the source file list for (Iterator<String> i = sourceFileList.iterator(); i.hasNext();) { String sourceFile = i.next(); if (!isOnSourcePath(sourceFile, sourcePath)) { // Source file wasn't on the source path i.remove(); } } } finally { try { if (in != null) in.close(); } catch (IOException ignore) { // Ignore } } } catch (IOException e) { getLog().warn("Could not read .classpath file in submission zipfile", e); } catch (DocumentException e) { getLog().warn("Could not read .classpath file in submission zipfile", e); } } /** * Ensures that all of the source paths exist. Strives to handle web-based * submissions better, specifically when students submit their source * outside of a "src" directory but include an Eclipse .classpath file that * references the non-existent source file. * * @param sourcePath * list of the source paths * @return true if all of source paths in the given list exist; false if at * least one of the source paths does not exist */ private boolean allSourcePathsExist(List<String> sourcePath) { for (Iterator<String> ii = sourcePath.iterator(); ii.hasNext();) { String dirName = ii.next(); File dir = new File(getDirectory().getAbsolutePath() + "/" + dirName); if (!dir.exists()) return false; } return true; } /** * Determine whether given source file is on the source path. * * @param sourceFile * the source file * @param sourcePath * the source path * @return true if source file is on the source path, false otherwise */ private boolean isOnSourcePath(String sourceFile, List<String> sourcePath) { for (Iterator<String> j = sourcePath.iterator(); j.hasNext();) { String srcPathEntry = j.next(); if (sourceFile.startsWith(srcPathEntry)) return true; } return false; } public static void main(String[] args) throws Exception { if (args.length != 3) { System.err.println( "Usage: " + JavaSubmissionExtractor.class.getName() + " <zipfile> <directory> <project root>"); System.exit(1); } File zipFile = new File(args[0]).getAbsoluteFile(); File directory = new File(args[1]).getAbsoluteFile(); String projectRoot = args[2]; Logger log = Logger.getLogger(SubmissionExtractor.class); SubmissionExtractor extractor = new JavaSubmissionExtractor(zipFile, directory, log); extractor.setProjectRoot(projectRoot); extractor.extract(); List<String> sourceFileList = extractor.getSourceFileList(); System.out.println("Source files:"); for (Iterator<String> i = sourceFileList.iterator(); i.hasNext();) { System.out.println("\t" + i.next()); } } /* * (non-Javadoc) * * @see * edu.umd.cs.buildServer.SubmissionExtractor#transformFileName(java.lang * .String) */ @Override protected String transformFileName(String entryName) { String filename = super.transformFileName(entryName); // If a source file isn't in a src directory, put it into a src // directory! if (filename.endsWith(".java") && !filename.startsWith("src")) filename = "src/" + filename; return filename; } @Override protected boolean shouldExtract(String entryName) { if (entryName.contains(".clover")) return false; return super.shouldExtract(entryName); } }