NIHVIVO-222 First step at coding the Java-based SeleniumRunner.
This commit is contained in:
parent
a8cfc10b2e
commit
72ee86f0a7
8 changed files with 769 additions and 0 deletions
|
@ -0,0 +1,167 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A harness that runs a system-level command.
|
||||
* </p>
|
||||
* <p>
|
||||
* No provision is made for standard input.
|
||||
* </p>
|
||||
* <p>
|
||||
* The standard output and standard error streams are asynchronously read, so
|
||||
* the sub-process will not block on full buffers. Warning: if either of these
|
||||
* streams contain more data than can fit into a String, then we will have a
|
||||
* problem.
|
||||
* </p>
|
||||
*
|
||||
* @author jblake
|
||||
*/
|
||||
public class CommandRunner {
|
||||
|
||||
private int returnCode;
|
||||
private String stdOut = "";
|
||||
private String stdErr = "";
|
||||
private File workingDirectory;
|
||||
|
||||
/* Gets informed of output as it arrives. Never null. */
|
||||
private final Logger logger;
|
||||
|
||||
private final Map<String, String> environmentAdditions = new HashMap<String, String>();
|
||||
|
||||
public CommandRunner(SeleniumRunnerParameters parms) {
|
||||
this.logger = parms.getLogger();
|
||||
}
|
||||
|
||||
/** Set the directory that the command will run in. */
|
||||
public void setWorkingDirectory(File workingDirectory) {
|
||||
this.workingDirectory = workingDirectory;
|
||||
}
|
||||
|
||||
/** Add (or replace) any environment variable. */
|
||||
public void setEnvironmentVariable(String key, String value) {
|
||||
this.environmentAdditions.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param command
|
||||
* a list containing the operating system program and its
|
||||
* arguments. See
|
||||
* {@link java.lang.ProcessBuilder#ProcessBuilder(List)}.
|
||||
*/
|
||||
public void run(List<String> command) throws CommandRunnerException {
|
||||
logger.subProcessStart(command);
|
||||
try {
|
||||
ProcessBuilder builder = new ProcessBuilder(command);
|
||||
|
||||
if (workingDirectory != null) {
|
||||
builder.directory(workingDirectory);
|
||||
}
|
||||
|
||||
if (!environmentAdditions.isEmpty()) {
|
||||
builder.environment().putAll(this.environmentAdditions);
|
||||
}
|
||||
|
||||
Process process = builder.start();
|
||||
StreamEater outputEater = new StreamEater(process.getInputStream(),
|
||||
false);
|
||||
StreamEater errorEater = new StreamEater(process.getErrorStream(),
|
||||
true);
|
||||
|
||||
this.returnCode = process.waitFor();
|
||||
|
||||
outputEater.join();
|
||||
this.stdOut = outputEater.getContents();
|
||||
|
||||
errorEater.join();
|
||||
this.stdErr = errorEater.getContents();
|
||||
} catch (IOException e) {
|
||||
throw new CommandRunnerException(
|
||||
"Exception when handling sub-process:", e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new CommandRunnerException(
|
||||
"Exception when handling sub-process:", e);
|
||||
}
|
||||
logger.subProcessStop(command);
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public String getStdErr() {
|
||||
return stdErr;
|
||||
}
|
||||
|
||||
public String getStdOut() {
|
||||
return stdOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* A thread that reads an InputStream until it reaches end of file, then
|
||||
* closes the stream. Designated as error stream or not, so it can tell the
|
||||
* logger.
|
||||
*/
|
||||
private class StreamEater extends Thread {
|
||||
private final InputStream stream;
|
||||
private final boolean isError;
|
||||
|
||||
private final StringWriter contents = new StringWriter();
|
||||
|
||||
private final byte[] buffer = new byte[4096];
|
||||
|
||||
public StreamEater(InputStream stream, boolean isError) {
|
||||
this.stream = stream;
|
||||
this.isError = isError;
|
||||
this.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int howMany = 0;
|
||||
while (true) {
|
||||
howMany = stream.read(buffer);
|
||||
if (howMany > 0) {
|
||||
String string = new String(buffer, 0, howMany);
|
||||
contents.write(string);
|
||||
|
||||
if (isError) {
|
||||
logger.subProcessErrout(string);
|
||||
} else {
|
||||
logger.subProcessStdout(string);
|
||||
}
|
||||
} else if (howMany == 0) {
|
||||
Thread.yield();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getContents() {
|
||||
return contents.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
/**
|
||||
* Indicates a problem with the attempt to run a command in a sub-process.
|
||||
*/
|
||||
public class CommandRunnerException extends Exception {
|
||||
|
||||
public CommandRunnerException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CommandRunnerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CommandRunnerException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public CommandRunnerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
public class Logger {
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
|
||||
"yyyy-MM-dd HH:mm:ss.SSS");
|
||||
|
||||
private final Writer writer;
|
||||
|
||||
public Logger(PrintStream out) {
|
||||
this.writer = new OutputStreamWriter(out);
|
||||
}
|
||||
|
||||
public Logger(File logFile) throws IOException {
|
||||
this.writer = new FileWriter(logFile);
|
||||
}
|
||||
|
||||
public void runStarted() {
|
||||
log("Run started.");
|
||||
}
|
||||
|
||||
public void runStopped() {
|
||||
log("Run stopped.");
|
||||
}
|
||||
|
||||
public void subProcessStart(List<String> command) {
|
||||
log("Subprocess started: " + command);
|
||||
}
|
||||
|
||||
public void subProcessStdout(String string) {
|
||||
logRawText(string);
|
||||
}
|
||||
|
||||
public void subProcessErrout(String string) {
|
||||
logRawText(string);
|
||||
}
|
||||
|
||||
public void subProcessStop(List<String> command) {
|
||||
log("Subprocess stopped: " + command);
|
||||
}
|
||||
|
||||
public void suiteStarted(File suiteDir) {
|
||||
log("Suite started: " + suiteDir.getName());
|
||||
}
|
||||
|
||||
public void suiteFailed(File suiteDir, IOException e) {
|
||||
log("Suite failed: " + suiteDir.getName());
|
||||
log(e);
|
||||
}
|
||||
|
||||
public void suiteStopped(File suiteDir) {
|
||||
log("Suite stopped: " + suiteDir.getName());
|
||||
}
|
||||
|
||||
public void cleanUploadStart(File uploadDirectory) {
|
||||
log("Upload cleaning started: " + uploadDirectory.getPath());
|
||||
}
|
||||
|
||||
public void cleanUploadFailed(File uploadDirectory, IOException e) {
|
||||
log("Upload cleaning failed: " + uploadDirectory.getPath());
|
||||
log(e);
|
||||
}
|
||||
|
||||
public void cleanUploadStop(File uploadDirectory) {
|
||||
log("Upload cleaning stopped: " + uploadDirectory.getPath());
|
||||
}
|
||||
|
||||
private void logRawText(String rawText) {
|
||||
try {
|
||||
writer.write(rawText);
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void log(String message) {
|
||||
try {
|
||||
writer.write(timeStamp() + " " + message + "\n");
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void log(Throwable t) {
|
||||
try {
|
||||
t.printStackTrace(new PrintWriter(writer));
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the current date and time to a string for the log.
|
||||
*/
|
||||
private String timeStamp() {
|
||||
return DATE_FORMAT.format(new Date());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
public class ModelCleaner {
|
||||
|
||||
/**
|
||||
* @param parms
|
||||
*/
|
||||
public ModelCleaner(SeleniumRunnerParameters parms) {
|
||||
// TODO Auto-generated constructor stub
|
||||
throw new RuntimeException("ModelCleaner Constructor not implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void clean() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new RuntimeException("ModelCleaner.clean() not implemented.");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Run the Selenium test suites. Provide the properties file and perhaps an
|
||||
* "interactive" flag.
|
||||
*/
|
||||
public class SeleniumRunner {
|
||||
private final SeleniumRunnerParameters parms;
|
||||
private final Logger logger;
|
||||
private final UploadAreaCleaner uploadCleaner;
|
||||
private final ModelCleaner modelCleaner;
|
||||
private final SuiteRunner suiteRunner;
|
||||
|
||||
public SeleniumRunner(SeleniumRunnerParameters parms) {
|
||||
this.parms = parms;
|
||||
this.logger = parms.getLogger();
|
||||
this.uploadCleaner = new UploadAreaCleaner(parms);
|
||||
this.modelCleaner = new ModelCleaner(parms);
|
||||
this.suiteRunner = new SuiteRunner(parms);
|
||||
}
|
||||
|
||||
public void runSelectedSuites() {
|
||||
logger.runStarted();
|
||||
for (File suiteDir : parms.getSelectedSuites()) {
|
||||
logger.suiteStarted(suiteDir);
|
||||
try {
|
||||
if (parms.isCleanModel()) {
|
||||
modelCleaner.clean();
|
||||
}
|
||||
if (parms.isCleanUploads()) {
|
||||
uploadCleaner.clean();
|
||||
}
|
||||
suiteRunner.runSuite(suiteDir);
|
||||
} catch (IOException e) {
|
||||
logger.suiteFailed(suiteDir, e);
|
||||
}
|
||||
logger.suiteStopped(suiteDir);
|
||||
}
|
||||
logger.runStopped();
|
||||
}
|
||||
|
||||
private static void selectAllSuites(SeleniumRunnerParameters parms) {
|
||||
List<File> suites = new ArrayList<File>();
|
||||
for (File parentDir : parms.getSuiteParentDirectories()) {
|
||||
suites.addAll(parms.findSuiteDirs(parentDir));
|
||||
}
|
||||
parms.setSelectedSuites(suites);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
SeleniumRunnerParameters parms = null;
|
||||
boolean interactive = false;
|
||||
|
||||
if ((args.length != 1) && (args.length != 2)) {
|
||||
usage("Wrong number of arguments.");
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
if (!"interactive".equalsIgnoreCase(args[1])) {
|
||||
usage("Invalid argument '" + args[1] + "'");
|
||||
}
|
||||
interactive = true;
|
||||
}
|
||||
|
||||
try {
|
||||
parms = new SeleniumRunnerParameters(args[0]);
|
||||
} catch (IOException e) {
|
||||
usage("Can't read properties file: " + e);
|
||||
}
|
||||
|
||||
if (interactive) {
|
||||
// TODO hook up the GUI.
|
||||
throw new RuntimeException("interactive mode not implemented.");
|
||||
} else {
|
||||
// Run all of the suites.
|
||||
// For each suite, clean the model and the upload area.
|
||||
selectAllSuites(parms);
|
||||
parms.setCleanModel(true);
|
||||
parms.setCleanUploads(true);
|
||||
SeleniumRunner runner = new SeleniumRunner(parms);
|
||||
runner.runSelectedSuites();
|
||||
}
|
||||
}
|
||||
|
||||
private static void usage(String message) {
|
||||
System.out.println(message);
|
||||
System.out.println("Usage is: SeleniumRunner <parameters_file> "
|
||||
+ "[\"interactive\"]");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Holds the runtime parameters that are read from the properties file, perhaps
|
||||
* with modifications from the GUI if we are running interactively.
|
||||
*/
|
||||
public class SeleniumRunnerParameters {
|
||||
private static final String PROP_OUTPUT_DIRECTORY = "output_directory";
|
||||
private static final String PROP_UPLOAD_DIRECTORY = "upload_directory";
|
||||
private static final String PROP_SUITE_DIRECTORIES = "suite_parent_directories";
|
||||
|
||||
private static final String LOGFILE_NAME = "log_file.txt";
|
||||
|
||||
private final File uploadDirectory;
|
||||
private final File outputDirectory;
|
||||
private final File logFile;
|
||||
|
||||
private final Collection<File> suiteParentDirectories;
|
||||
|
||||
private Collection<File> selectedSuites = Collections.emptySet();
|
||||
private boolean cleanModel = true;
|
||||
private boolean cleanUploads = true;
|
||||
private Logger logger = new Logger(System.out);
|
||||
|
||||
/**
|
||||
* Read the required properties from the property file, and do some checks
|
||||
* on them.
|
||||
*/
|
||||
public SeleniumRunnerParameters(String propertiesFilepath)
|
||||
throws IOException {
|
||||
Reader propsReader = null;
|
||||
try {
|
||||
propsReader = new FileReader(new File(propertiesFilepath));
|
||||
Properties props = new Properties();
|
||||
props.load(propsReader);
|
||||
|
||||
this.uploadDirectory = checkReadWriteDirectory(props,
|
||||
PROP_UPLOAD_DIRECTORY);
|
||||
this.outputDirectory = checkReadWriteDirectory(props,
|
||||
PROP_OUTPUT_DIRECTORY);
|
||||
this.logFile = new File(this.outputDirectory, LOGFILE_NAME);
|
||||
this.logger = new Logger(this.logFile);
|
||||
|
||||
this.suiteParentDirectories = checkSuiteParentDirectories(props);
|
||||
|
||||
} finally {
|
||||
if (propsReader != null) {
|
||||
try {
|
||||
propsReader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that there is a property for the output directory, and that it
|
||||
* points to a valid directory.
|
||||
*/
|
||||
private File checkReadWriteDirectory(Properties props, String key) {
|
||||
String value = getRequiredProperty(props, key);
|
||||
|
||||
File dir = new File(value);
|
||||
|
||||
if (!dir.exists()) {
|
||||
throw new IllegalArgumentException("Directory " + key + " '"
|
||||
+ value + "' does not exist.");
|
||||
}
|
||||
|
||||
if (!dir.isDirectory()) {
|
||||
throw new IllegalArgumentException("Directory " + key + " '"
|
||||
+ value + "' is not a directory.");
|
||||
}
|
||||
|
||||
if (!dir.canRead()) {
|
||||
throw new IllegalArgumentException("Directory " + key + " '"
|
||||
+ value + "' is not readable.");
|
||||
}
|
||||
|
||||
if (!dir.canWrite()) {
|
||||
throw new IllegalArgumentException("Directory " + key + " '"
|
||||
+ value + "' is not writeable.");
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the property for the suite directories and ensure that each one is
|
||||
* indeed a readable directory.
|
||||
*/
|
||||
private Collection<File> checkSuiteParentDirectories(Properties props) {
|
||||
String value = getRequiredProperty(props, PROP_SUITE_DIRECTORIES);
|
||||
|
||||
List<File> dirs = new ArrayList<File>();
|
||||
String[] paths = value.split("[:;]");
|
||||
for (String path : paths) {
|
||||
File dir = new File(path.trim());
|
||||
|
||||
if (!dir.exists()) {
|
||||
throw new IllegalArgumentException("Suite directory '"
|
||||
+ dir.getPath() + "' does not exist.");
|
||||
}
|
||||
if (!dir.isDirectory()) {
|
||||
throw new IllegalArgumentException("Suite directory '"
|
||||
+ dir.getPath() + "' is not a directory.");
|
||||
}
|
||||
if (!dir.canRead()) {
|
||||
throw new IllegalArgumentException("Suite directory '"
|
||||
+ dir.getPath() + "' is not readable.");
|
||||
}
|
||||
}
|
||||
return dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for this property. If there isn't one, or if it's empty,
|
||||
* complain.
|
||||
*/
|
||||
private String getRequiredProperty(Properties props, String key) {
|
||||
String value = props.getProperty(key);
|
||||
if ((value == null) || (value.trim().length() == 0)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Property file must provide a value for '" + key + "'");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public void setLogger(Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public File getUploadDirectory() {
|
||||
return uploadDirectory;
|
||||
}
|
||||
|
||||
public Collection<File> getSuiteParentDirectories() {
|
||||
return suiteParentDirectories;
|
||||
}
|
||||
|
||||
public void setSelectedSuites(Collection<File> selectedSuites) {
|
||||
this.selectedSuites = selectedSuites;
|
||||
}
|
||||
|
||||
public Collection<File> getSelectedSuites() {
|
||||
return new ArrayList<File>(this.selectedSuites);
|
||||
}
|
||||
|
||||
public boolean isCleanModel() {
|
||||
return cleanModel;
|
||||
}
|
||||
|
||||
public void setCleanModel(boolean cleanModel) {
|
||||
this.cleanModel = cleanModel;
|
||||
}
|
||||
|
||||
public boolean isCleanUploads() {
|
||||
return cleanUploads;
|
||||
}
|
||||
|
||||
public void setCleanUploads(boolean cleanUploads) {
|
||||
this.cleanUploads = cleanUploads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look inside this parent directory and find any suite directories. You can
|
||||
* recognize a suite directory because it contains a file named Suite.html.
|
||||
*/
|
||||
public Collection<File> findSuiteDirs(File parentDir) {
|
||||
return Arrays.asList(parentDir.listFiles(new FileFilter() {
|
||||
public boolean accept(File pathname) {
|
||||
if (!pathname.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
File suiteFile = new File(pathname, "Suite.html");
|
||||
if (suiteFile.exists()) {
|
||||
return true;
|
||||
} else {
|
||||
logger.subProcessErrout("Warning: suite file '" + suiteFile.getPath()
|
||||
+ "' does not exist.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
public class SuiteRunner {
|
||||
|
||||
/**
|
||||
* @param parms
|
||||
*/
|
||||
public SuiteRunner(SeleniumRunnerParameters parms) {
|
||||
// TODO Auto-generated constructor stub
|
||||
throw new RuntimeException("SuiteRunner Constructor not implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param suiteDir
|
||||
*/
|
||||
public void runSuite(File suiteDir) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new RuntimeException("SuiteRunner.runSuite() not implemented.");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Clean out the file upload area, so the next suite will start with no uploads.
|
||||
*/
|
||||
public class UploadAreaCleaner {
|
||||
private final SeleniumRunnerParameters parms;
|
||||
private final Logger logger;
|
||||
|
||||
public UploadAreaCleaner(SeleniumRunnerParameters parms) {
|
||||
this.parms = parms;
|
||||
this.logger = parms.getLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all of the directories and files in the upload directory. Don't
|
||||
* delete the upload directory itself.
|
||||
*/
|
||||
public void clean() throws IOException {
|
||||
File uploadDirectory = parms.getUploadDirectory();
|
||||
if (!uploadDirectory.isDirectory()) {
|
||||
throw new IllegalArgumentException("'" + uploadDirectory.getPath()
|
||||
+ "' is not a directory.");
|
||||
}
|
||||
|
||||
logger.cleanUploadStart(uploadDirectory);
|
||||
|
||||
try {
|
||||
for (File file : uploadDirectory.listFiles()) {
|
||||
if (file.isFile()) {
|
||||
deleteFile(file);
|
||||
} else {
|
||||
purgeDirectoryRecursively(uploadDirectory);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.cleanUploadFailed(uploadDirectory, e);
|
||||
throw e;
|
||||
} finally {
|
||||
logger.cleanUploadStop(uploadDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all of the files in a directory, any sub-directories, and the
|
||||
* directory itself.
|
||||
*/
|
||||
protected static void purgeDirectoryRecursively(File directory)
|
||||
throws IOException {
|
||||
File[] files = directory.listFiles();
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
purgeDirectoryRecursively(file);
|
||||
} else {
|
||||
deleteFile(file);
|
||||
}
|
||||
}
|
||||
deleteFile(directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file, either before or after the test. If it can't be deleted,
|
||||
* complain.
|
||||
*/
|
||||
protected static void deleteFile(File file) throws IOException {
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we were unable to delete the file, is it because it's a non-empty
|
||||
* directory?
|
||||
*/
|
||||
if (!file.isDirectory()) {
|
||||
final StringBuffer message = new StringBuffer(
|
||||
"Can't delete directory '" + file.getPath() + "'\n");
|
||||
file.listFiles(new FileFilter() {
|
||||
public boolean accept(File pathname) {
|
||||
message.append(" contains file '" + pathname + "'\n");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
throw new IOException(message.toString().trim());
|
||||
} else {
|
||||
throw new IOException("Unable to delete file '" + file.getPath()
|
||||
+ "'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue