import weka.core.Utils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Vector;
/**
* Generates a setup file for <a href="http://www.jrsoftware.org/isdl.php"
* target="_blank">Inno Setup</a> and copies also all the necessary files to
* the output.
*
* @author FracPete (fracpete at waikato dot ac dot nz)
* @version $Revision: 1.1 $
*/
public class GenerateSetup {
/** the templates directory */
public final static String TEMPLATES = "templates";
/** the batch file for JRE */
public final static String JRE_BATCH = "RunJREInstaller.bat";
/** the version */
protected String mVersion = "";
/** the input directory */
protected String mInputDir = "";
/** the output directory */
protected String mOutputDir = "";
/** the directory for Weka */
protected String mDir = "";
/** the link in the Start Program */
protected String mLink = "";
/** the jre file */
protected String mJRE = "";
/** whether to clear the output dir before generating */
protected boolean mClear = false;
/** whether to generate the scripts only */
protected boolean mScriptOnly = false;
/**
* initializes the setup generator
*/
public GenerateSetup() {
super();
}
/**
* sets the version number
*
* @param value the version number
*/
public void setVersion(String value) {
mVersion = value;
}
/**
* sets the input directory
*
* @param value the dir
*/
public void setInputDir(String value) {
mInputDir = value;
}
/**
* sets the output directory
*
* @param value the dir
*/
public void setOutputDir(String value) {
mOutputDir = value;
}
/**
* sets the directory for Weka used in the setup
*
* @param value the dir
*/
public void setDir(String value) {
mDir = value;
}
/**
* sets the name of the link
*
* @param value the name
*/
public void setLink(String value) {
mLink = value;
}
/**
* sets the JRE filename
*
* @param value the filename
*/
public void setJRE(String value) {
mJRE = value;
}
/**
* sets whether to clear the output directory first
*
* @param value true if output directory is cleared first
*/
public void setClear(boolean value) {
mClear = value;
}
/**
* sets whether to generate the inno script only
*
* @param value if true, only the inno script will be generated
*/
public void setScriptOnly(boolean value) {
mScriptOnly = value;
}
/**
* Copies src file to dst file.
* If the dst file does not exist, it is created.
* Taken from here: http://javaalmanac.com/egs/java.io/CopyFile.html
*
* @param src the source file
* @param dst the destination file
* @throws Exception if something goes wrong
*/
protected void copy(File src, File dst) throws IOException {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
/**
* lists the files in a directory as array.
* Taken from here: http://www.bigbold.com/snippets/posts/show/1875
*
* @param directory the directory to search
* @param filter an optional filter
* @param recurse if true then we recurse into sub-dirs
* @return the files
*/
protected static File[] listFilesAsArray(File directory,
FilenameFilter filter, boolean recurse) {
Collection<File> files = listFiles(directory, filter, recurse);
File[] arr = new File[files.size()];
return files.toArray(arr);
}
/**
* lists the files in a directory.
* Taken from here: http://www.bigbold.com/snippets/posts/show/1875
*
* @param directory the directory to search
* @param filter an optional filter
* @param recurse if true then we recurse into sub-dirs
* @return the files
*/
protected static Collection<File> listFiles(File directory,
FilenameFilter filter, boolean recurse) {
// List of files / directories
Vector<File> files = new Vector<File>();
// Get files / directories in the directory
File[] entries = directory.listFiles();
// Go over entries
for (File entry : entries) {
// If there is no filter or the filter accepts the
// file / directory, add it to the list
if (filter == null || filter.accept(directory, entry.getName())) {
files.add(entry);
}
// If the file is a directory and the recurse flag
// is set, recurse into the directory
if (recurse && entry.isDirectory()) {
files.addAll(listFiles(entry, filter, recurse));
}
}
// Return collection of files
return files;
}
/**
* returns only directories from the collection
*
* @param list the list with files and dirs
* @return contains only dirs
*/
protected static Collection<File> getDirectories(Collection<File> list) {
Vector<File> result;
result = new Vector<File>();
for (File file : list) {
if (file.isDirectory())
result.add(file);
}
return result;
}
/**
* writes the given vector to the specified file
*
* @param content the content to write
* @param filename the file to write to
* @return if writing was successful
*/
protected static boolean writeToFile(Vector content, String filename) {
StringBuffer contentStr;
int i;
contentStr = new StringBuffer();
for (i = 0; i < content.size(); i++)
contentStr.append(content.get(i).toString() + "\n");
return writeToFile(contentStr.toString(), filename);
}
/**
* writes the given content to the specified file
*
* @param content the content to write
* @param filename the file to write to
* @return if writing was successful
*/
protected static boolean writeToFile(String content, String filename) {
BufferedWriter writer;
boolean result;
File file;
result = true;
try {
// do we need to create dir?
file = new File(filename);
if (!file.getParentFile().exists())
file.getParentFile().mkdirs();
// content
writer = new BufferedWriter(new FileWriter(file));
writer.write(content);
writer.flush();
writer.close();
}
catch (Exception e) {
e.printStackTrace();
result = false;
}
return result;
}
/**
* removes the input directory from the given filename
*
* @param filename the file to work on
* @return the filename without the input dir
*/
protected String removeInputDir(String filename) {
File inputDir;
File inFile;
inputDir = new File(mInputDir);
inFile = new File(filename);
return inFile.getPath().substring(inputDir.getPath().length());
}
/**
* moves the given file from the input dir to the output dir.
*
* @param filename the filename in the input dir to process
* @return the file as it should appear in the output dir
*/
protected String inputToOutput(String filename) {
File outputDir;
File outFile;
outputDir = new File(mOutputDir);
outFile = new File(outputDir.getPath() + "\\" + removeInputDir(filename));
return outFile.getPath();
}
/**
* checks whether the directory contains any files at all
*
* @return true if at least one file is found
*/
protected boolean containsFiles(File dir) {
boolean result;
File[] list;
int i;
result = false;
list = dir.listFiles();
for (i = 0; i < list.length; i++) {
if (!list[i].isDirectory()) {
result = true;
break;
}
}
return result;
}
/**
* removes the files in the output directory, if necessary
*
* @return true if the removal was successful or not necessary
*/
protected boolean clear() {
boolean result;
File output;
Collection<File> files;
result = true;
output = new File(mOutputDir);
if (output.exists() && output.isDirectory()) {
// delete files
files = listFiles(output, null, true);
for (File file : files) {
if (file.isDirectory())
continue;
else
file.delete();
}
// delete dirs
files = listFiles(output, null, true);
for (File file : files)
file.delete();
}
return result;
}
/**
* copies all the files
*
* @return true if copying was successful
*/
protected boolean copyFiles() {
Collection<File> files;
boolean result;
File outFile;
String prefix;
result = true;
try {
prefix = mOutputDir + "/" + new File(mOutputDir).getName();
files = listFiles(new File(mInputDir), null, true);
for (File file : files) {
outFile = new File(prefix + "/" + removeInputDir(file.getPath()));
if (file.isDirectory()) {
if (!outFile.exists())
outFile.mkdirs();
}
else {
if (!outFile.getParentFile().exists())
outFile.getParentFile().mkdirs();
copy(file, outFile);
}
}
}
catch (Exception e) {
e.printStackTrace();
result = false;
}
return result;
}
/**
* copies the JRE
*
* @return true if copying was successful
*/
protected boolean copyJRE() {
File file;
boolean result;
result = true;
try {
file = new File(mJRE);
copy(file, new File(mOutputDir + "/" + file.getName()));
}
catch (Exception e) {
e.printStackTrace();
result = false;
}
return result;
}
/**
* copies all the templates
*
* @return true if copying was successful
*/
protected boolean copyTemplates() {
Collection<File> files;
boolean result;
result = true;
try {
files = listFiles(new File(TEMPLATES), null, false);
for (File file : files)
copy(file, new File(mOutputDir + "/" + file.getName()));
}
catch (Exception e) {
e.printStackTrace();
result = false;
}
return result;
}
/**
* generates the batch file for installing the JRE
*
* @return true if generation was successful
*/
protected boolean generateJreFile() {
Vector setup;
setup = new Vector();
setup.add(new File(mJRE).getName());
setup.add("del " + new File(mJRE).getName());
// write file
return writeToFile(setup, mOutputDir + "/" + JRE_BATCH);
}
/**
* generates the setup file
*
* @return true if generation was successful
*/
protected boolean generateSetupFile() {
Vector setup;
Collection<File> files;
// generate file
setup = new Vector();
setup.add("; -- Setup for Weka " + mVersion + " --");
// Setup
setup.add("");
setup.add("[Setup]");
setup.add("AppName=WEKA");
setup.add("AppVerName=WEKA " + mVersion);
setup.add("DefaultDirName={pf}\\" + mDir);
setup.add("DefaultGroupName=WEKA");
setup.add("ChangesAssociations=yes");
setup.add("LicenseFile=" + new File(mOutputDir).getName() + "\\COPYING");
if (mJRE.length() != 0)
setup.add("MessagesFile=DEFAULT.JRE.ISL");
else
setup.add("MessagesFile=DEFAULT.ISL");
// Dirs
setup.add("");
setup.add("[Dirs]");
files = listFiles(new File(mInputDir), null, true);
for (File file : files) {
if (!file.isDirectory())
continue;
setup.add("Name: \"{app}" + removeInputDir(file.getPath()) + "\"");
}
// Files
setup.add("");
setup.add("[Files]");
setup.add(
"Source: \"" + new File(mOutputDir).getName() + "\\*\"; "
+ "DestDir: \"{app}\"");
files = listFiles(new File(mInputDir), null, true);
for (File file : files) {
if (!file.isDirectory() || !containsFiles(file))
continue;
setup.add(
"Source: \"" + new File(mOutputDir).getName()
+ removeInputDir(file.getPath()) + "\\*\"; "
+ "DestDir: \"{app}" + removeInputDir(file.getPath()) + "\"");
}
if (mJRE.length() != 0) {
setup.add("Source: \"" + new File(mJRE).getName() + "\"; DestDir: \"{app}\"");
setup.add("Source: \"RunJREInstaller.bat\"; DestDir: \"{app}\"");
}
setup.add("Source: \"RunWeka.bat\"; DestDir: \"{app}\"");
setup.add("Source: \"weka.ico\"; DestDir: \"{app}\"");
// Icons
setup.add("");
setup.add("[Icons]");
setup.add("Name: \"{group}\\" + mLink + "\"; Filename: \"{app}\\RunWeka.bat\"; WorkingDir: \"{app}\"; IconFilename: \"{app}\\weka.ico\"");
setup.add("Name: \"{group}\\Explorer Guide\"; Filename: \"{app}\\ExplorerGuide.pdf\"");
setup.add("Name: \"{group}\\Package Documentation\"; Filename: \"{app}\\doc\\index.html\"");
setup.add("Name: \"{group}\\Uninstall\"; Filename: \"{app}\\unins000.exe\"");
// Run
if (mJRE.length() != 0) {
setup.add("");
setup.add("[Run]");
setup.add("FileName: \"{app}\\RunJREInstaller.bat\"; WorkingDir: \"{app}\"");
}
// Registry
setup.add("");
setup.add("[Registry]");
setup.add("Root: HKCR; Subkey: \".arff\"; ValueType: string; ValueName: \"\"; ValueData: \"ARFFDataFile\"; Flags: uninsdeletevalue");
setup.add("Root: HKCR; Subkey: \"ARFFDataFile\"; ValueType: string; ValueName: \"\"; ValueData: \"ARFF Data File\"; Flags: uninsdeletekey");
setup.add("Root: HKCR; Subkey: \"ARFFDataFile\\DefaultIcon\"; ValueType: string; ValueName: \"\"; ValueData: \"{app}\\weka.ico\"");
setup.add("Root: HKCR; Subkey: \"ARFFDataFile\\shell\\open\\command\"; ValueType: string; ValueName: \"\"; ValueData: \"\"\"java.exe\"\" \"\"-cp\"\" \"\"{app}\\weka.jar\"\" \"\"weka.gui.explorer.Explorer\"\" \"\"%1\"\"\"");
// write file
if (mJRE.length() != 0)
return writeToFile(setup, mOutputDir + "/" + mDir + "jre.iss");
else
return writeToFile(setup, mOutputDir + "/" + mDir + ".iss");
}
/**
* generates the output
*
* @return true if generation was successful
*/
public boolean execute() {
boolean result;
result = true;
if (!mScriptOnly) {
if (mClear)
result = clear();
if (result)
result = copyFiles();
if (result)
result = copyTemplates();
if (result && (mJRE.length() != 0)) {
result = copyJRE();
if (result)
result = generateJreFile();
}
}
if (result)
result = generateSetupFile();
return result;
}
/**
* runs the generator with the necessary parameters.
*
* @param args the commandline parameters
* @throws Exception if something goes wrong
*/
public static void main(String[] args) throws Exception {
GenerateSetup generator;
generator = new GenerateSetup();
generator.setVersion(Utils.getOption("version", args));
generator.setInputDir(Utils.getOption("input-dir", args));
generator.setOutputDir(Utils.getOption("output-dir", args));
generator.setDir(Utils.getOption("dir", args));
generator.setLink(Utils.getOption("link", args));
generator.setJRE(Utils.getOption("jre", args));
generator.setClear(Utils.getFlag("clear", args));
generator.setScriptOnly(Utils.getFlag("scriptonly", args));
System.out.println("Result = " + generator.execute());
}
}