/*
* Milyn - Copyright (C) 2006 - 2010
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License (version 2.1) as published by the Free Software
* Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details:
* http://www.gnu.org/licenses/lgpl.txt
*/
package org.milyn.test.ant;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import java.io.*;
/**
* AntRunner test utility.
*
* <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public class AntRunner {
private Project project = new Project();
/**
* Public constructor.
* <p/>
* The <code>antScript</code> parameter is a filename on the classpath,
* relative to the caller Class. AntRunner (<code>this</code>) uses the
* current Thread's {@link Thread#getStackTrace Stack Trace}
* to determine the calling Class.
*
* @param antScript The Ant script to be executed. Classpath resource relative
* to the caller Class.
* @param properties Optional Ant properties.
* @throws IOException Error reading Ant Script.
*/
public AntRunner(String antScript, String... properties) throws IOException {
StackTraceElement[] thisStack = Thread.currentThread().getStackTrace();
for(int i = 0; i < thisStack.length; i++) {
StackTraceElement stackFrame = thisStack[i];
if(stackFrame.getClassName().equals(getClass().getName())) {
StackTraceElement callerStackFrame = thisStack[i + 1];
try {
Class callerClass = Class.forName(callerStackFrame.getClassName());
InputStream antScriptStream = callerClass.getResourceAsStream(antScript);
if(antScriptStream == null) {
throw new RuntimeException("Unable resolve Ant Script resource '" + antScript + "' relative to caller class '" + callerClass.getName() + "'.");
}
configureProject(antScriptStream, properties);
return;
} catch (ClassNotFoundException e) {
throw new RuntimeException("Unexpected Exception: Unable resolve caller Class '" + callerStackFrame.getClassName() + "' for AntRunner on current Thread.");
}
}
}
throw new RuntimeException("Unexpected Exception: Unable resolve caller Class for AntRunner on current Thread.");
}
/**
* Public constructor.
*
* @param antScript The Ant script to be executed.
* @param properties Optional Ant properties.
* @throws IOException Error reading Ant Script.
*/
public AntRunner(InputStream antScript, String... properties) throws IOException {
configureProject(antScript, properties);
}
/**
* Run a target on the Ant Script.
* @param target The target to run.
* @return <code>this</code> class instance.
*/
public AntRunner run(String target) {
if(target == null) {
throw new IllegalArgumentException("null 'target' argument.");
}
project.executeTarget(target);
return this;
}
private void configureProject(InputStream antScript, String[] properties) throws IOException {
if(antScript == null) {
throw new IllegalArgumentException("null 'antScript' argument.");
}
try {
project.init();
DefaultLogger antLogger = new DefaultLogger();
antLogger.setErrorPrintStream(System.err);
antLogger.setOutputPrintStream(System.out);
antLogger.setMessageOutputLevel(Project.MSG_INFO);
project.addBuildListener(antLogger);
project.setBaseDir(new File("./"));
File executeScript = new File("./target/ant-exec.xml");
FileOutputStream fileOs = new FileOutputStream(executeScript);
try {
byte[] readBuf = new byte[254];
int readCount = 0;
while((readCount = antScript.read(readBuf)) != -1) {
fileOs.write(readBuf, 0, readCount);
}
} finally {
fileOs.flush();
fileOs.close();
}
ProjectHelper.configureProject(project, executeScript);
if(properties != null) {
for(String property : properties) {
int eqIndex = property.indexOf('=');
if(eqIndex == -1 || eqIndex + 1 == property.length()) {
throw new RuntimeException("Invalid AntRunner property '" + property + "'. No value.");
}
String key = property.substring(0, eqIndex);
String value = property.substring(eqIndex + 1, property.length());
project.setProperty(key, value);
}
}
} finally {
antScript.close();
}
}
}