blob: 5dd9e73996fc12adf6a5535249dae388ef868f0c [file] [log] [blame]
package org.apache.chainsaw.ant;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
/**
* This Ant task creates the necessary .bat and .sh files required to run Chainsaw
* on the commandline. This task was created because it was getting VERY annoying
* to constantly maintain 2 script files as the Jar file names kept changing during
* the log4j 1.3 alpha stage, and as we (the Chainsaw developers) added dependencies
* as we added functionality.
*
* This task takes and outputLocation as a , and a set of FileSets which form the
* basis of the classpath that is required to run Chainsaw.
*
* @author psmith
*
*/
public class CreateShellScripts extends Task {
private String outputLocation;
private Vector fileSets = new Vector();
private String scriptType="";
private Collection KNOWN_SCRIPT_TYPES = Arrays.asList(new String[] {"shell", "webstart"});
public String getOutputLocation() {
return outputLocation;
}
public void setOutputLocation(String outputLocation) {
this.outputLocation = outputLocation;
}
public void execute() throws BuildException {
super.execute();
if(getScriptType().length()==0) {
throw new BuildException("scriptType property has not been set");
}else if (!KNOWN_SCRIPT_TYPES.contains(getScriptType())) {
throw new BuildException("scriptType '"+ getScriptType() + "' is not one of then known types: " + KNOWN_SCRIPT_TYPES);
}
File outputLocationDir = new File(getOutputLocation());
if(!outputLocationDir.exists()) {
log("Creating director(ies) ->" + getOutputLocation());
outputLocationDir.mkdirs();
}
Collection filenames = getFilenames();
try {
if (getScriptType().equals("shell")) {
createUnixShellScript(outputLocationDir, filenames);
createBatShellScript(outputLocationDir, filenames);
}else {
createJNLP(outputLocationDir, filenames);
}
} catch (Exception e) {
e.printStackTrace();
throw new BuildException("Failed to create Scripts",e);
}
}
/**
* Creates a JNLP file for launching Chainsaw
* @param outputLocationDir
* @param filenames
* @throws IOException
*/
private void createJNLP(File outputLocationDir, Collection filenames) throws IOException {
// String templateName = CreateShellScripts.class.getPackage().toString().replace('.', '/')+"/chainsawWebStart.jnlp";
// log("Using JNLP template: " + templateName);
BufferedReader reader = new BufferedReader(new FileReader(new File("packaging/chainsawWebStart.jnlp")));
// convert the file to a String
StringBuffer buf = new StringBuffer(1024);
String line;
while((line=reader.readLine())!=null) {
buf.append(line).append("\n");
}
StringBuffer jarBuf = new StringBuffer();
/**
* Good one Sun! For some stupid reason, we MUST list the jar that contains the main-class
* FIRST. Why? Why? WHYYYYYYYYYYYYYYYYYY?
*
* So, we sort a copied list and make sure that the chainsaw jar is first.
*/
List list = new ArrayList(filenames);
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
if(o1.toString().toLowerCase().indexOf("chainsaw")>-1) {
return -1;
}else if(o2.toString().toLowerCase().indexOf("chainsaw")>-1) {
return 1;
}else {
return 0;
}
}});
for (Iterator iter = list.iterator(); iter.hasNext();) {
String jar = (String) iter.next();
jarBuf.append("\t<jar href=\"lib/"+jar + "\"/>\n");
}
// now replace the bits we want
int jarStringLocation = buf.indexOf("@JARS@");
buf.replace(jarStringLocation, jarStringLocation + 6, jarBuf.toString());
File jnlp = new File(outputLocationDir, "chainsawWebStart.jnlp");
Writer writer = new FileWriter(jnlp);
writer.write(buf.toString());
writer.close();
}
public void addFileSet(FileSet fileSet) {
fileSets.add(fileSet);
}
private void createBatShellScript(File outputLocationDir, Collection filenames) throws IOException {
File unixScript = new File(outputLocationDir, "chainsaw.bat");
log("Creating Windows .bat script: " + unixScript.getAbsolutePath());
Writer writer = new FileWriter(unixScript);
writeExecutionLine(filenames, writer, ';');
writer.close();
}
private void createUnixShellScript(File outputLocationDir, Collection fileNames) throws IOException {
File unixScript = new File(outputLocationDir, "chainsaw.sh");
log("Creating Unix script: " + unixScript.getAbsolutePath());
Writer writer = new FileWriter(unixScript);
writer.write("#!/bin/sh\n");
writeExecutionLine(fileNames, writer, ':');
writer.close();
}
private void writeExecutionLine(Collection fileNames, Writer writer, char jarSeparator) throws IOException {
writer.write("java -classpath ");
for (Iterator iter = fileNames.iterator(); iter.hasNext();) {
String fileName = (String) iter.next();
writer.write(fileName);
if(iter.hasNext()) {
writer.write(jarSeparator);
}
}
writer.write(" org.apache.log4j.chainsaw.LogUI" );
writer.write("\n");
}
private Collection getFilenames() {
List jars = new ArrayList();
for (Iterator iter = fileSets.iterator(); iter.hasNext();) {
FileSet fileSet = (FileSet) iter.next();
DirectoryScanner ds = fileSet.getDirectoryScanner(getProject()); // 3
String[] includedFiles = ds.getIncludedFiles();
for (int i = 0; i < includedFiles.length; i++) {
String filename = includedFiles[i].replace('\\', '/'); // 4
filename = filename.substring(filename.lastIndexOf("/") + 1);
// if (foundLocation==null && file.equals(filename)) {
// File base = ds.getBasedir(); // 5
// File found = new File(base, includedFiles[i]);
// foundLocation = found.getAbsolutePath();
// }
jars.add(filename);
}
}
return jars;
}
public String getScriptType() {
return scriptType;
}
public void setScriptType(String scriptType) {
this.scriptType = scriptType.toLowerCase();
}
}