/* *******************************************************************
* Copyright (c) 2000-2001 Xerox Corporation,
* 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Xerox/PARC initial implementation
* ******************************************************************/
package $installer$.org.aspectj;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
/**
* Invoke the Installer gui. There are two ways to run without GUI by passing parameters to main:
*
* - pass
-text {pathToPropertiesFile}
:
*
*
* - pass
-to {pathToTargetDir}
:
*
* - "-to".equals(arg[0])
* - arg[1] is the path to a writable install directory.
*
*
*/
public class Main {
public static void main(String[] args) {
Options.loadArgs(args);
boolean hasGui = true;
Properties properties = new Properties();
InputStream istream = null;
try {
istream = Main.class.getResourceAsStream(Installer.RESOURCE_DIR + "/properties.txt");
if (istream == null) {
System.err.println("unable to load properties.txt using Main.class - exiting");
Main.exit(-1);
}
properties.load(istream);
// when running outside GUI, load values into properties
// so that property-value resolution works
// (otherwise, could just set values below).
// XXX not sure if this indirection is actually needed.
if (null != Options.textProperties) {
istream.close();
istream = new FileInputStream(Options.textProperties);
properties.load(istream);
hasGui = false;
} else if (null != Options.targetDir) {
String path = null;
try {
path = Options.targetDir.getCanonicalPath();
} catch (IOException e) {
path = Options.targetDir.getAbsolutePath();
}
String javaPath = ConfigureLauncherPane.getDefaultJavaHomeLocation();
if (null == javaPath) {
System.err.println("using GUI - unable to find java");
} else {
properties.setProperty("output.dir", path);
properties.setProperty("context.javaPath", javaPath);
hasGui = false;
}
}
} catch (IOException ioe) {
handleException(ioe);
} finally {
if (null != istream) {
try {
istream.close();
} catch (IOException e) {
} // ignore
}
}
try {
String className = (String) properties.get("installer.main.class");
//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
Installer installer = (Installer) Class.forName(className).newInstance();
InstallContext installerContext = new InstallContext(properties);
installerContext.setHasGui(hasGui);
installer.setContext(installerContext);
if (installerContext.hasGui()) { // let context force whether or not to run gui
installer.runGUI();
} else {
// set output dir and java path in context after minimal validation
String propName = "output.dir";
String propValue = properties.getProperty(propName);
if (null == propValue) {
throw new Exception("expecting property " + propName);
}
String outputDirName = propValue;
propName = "context.javaPath";
propValue = properties.getProperty(propName);
if (null == propValue) {
throw new Exception("expecting property " + propName);
}
String javaPath = propValue;
File outputDir = new File(outputDirName);
if (!outputDir.isDirectory()) {
throw new Exception("not a dir outputDirName: " + outputDirName + " dir: " + outputDir);
}
if (!outputDir.canWrite()) {
throw new Exception("cannot write outputDirName: " + outputDirName + " dir: " + outputDir);
}
InstallContext context = installer.getContext(); // todo: why not use installerContext?
context.setOutputDir(outputDir);
context.javaPath = new File(javaPath);
// todo: check javaPath for ... bin/java? lib/rt.jar?
if (!outputDir.isDirectory() || !outputDir.canRead()) {
throw new Exception("invalid javaPath: " + javaPath);
}
// directly set context and run
WizardPane.setContext(installerContext);
installer.run();
}
} catch (Exception e) {
handleException(e);
}
}
public static void handleException(Throwable e) {
System.out.println("internal error: " + e.toString());
e.printStackTrace();
Main.exit(-1);
}
/** indirection for System.exit - todo apply cleanup here as necessary */
public static void exit(int value) {
System.exit(value);
}
} // class Main
class Options {
public static boolean verbose = false;
public static String textProperties = null;
public static File targetDir = null;
public static boolean forceError1 = false;
public static boolean forceError2 = false;
public static boolean forceHandConfigure = false;
public static void loadArgs(String[] args) {
if (args == null) {
return;
}
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg == null) {
continue;
}
if (arg.equals("-verbose")) {
verbose = true;
} else if (arg.equals("-forceError1")) {
forceError1 = true;
} else if (arg.equals("-forceError2")) {
forceError2 = true;
} else if (arg.equals("-forceHandConfigure")) {
forceHandConfigure = true;
} else if (arg.equals("-text")) {
if (i + 1 < args.length) {
textProperties = args[++i];
}
} else if (arg.equals("-to")) {
String next = "no argument";
if (i + 1 < args.length) {
next = args[++i];
File targDir = new File(next);
if (targDir.isDirectory() && targDir.canWrite()) {
targetDir = targDir;
}
}
if (null == targetDir) {
System.err.println("invalid -to dir: " + next);
}
}
}
}
}
/** tools installer installs the entire 1.1+ distribution */
class ToolsInstaller extends Installer {
public String getTitle() {
return "Installer for AspectJ(TM)";
}
public String getPrefix() {
return "tools";
}
public String getReadmeFilename() {
return "README-AspectJ.html";
}
public ToolsInstaller() {
InstallPane installPane = new InstallPane(true);
setInstallPane(installPane);
panes = new WizardPane[] { new IntroPane(), new ConfigureLauncherPane(), new LocationPane(), installPane, new FinishPane() };
}
}
class DocsInstaller extends Installer {
public String getTitle() {
return "AspectJ(TM) Documentation and Examples Installer";
}
public String getPrefix() {
return "docs";
}
public DocsInstaller() {
InstallPane installPane = new InstallPane(false);
setInstallPane(installPane);
panes = new WizardPane[] { new IntroPane(), new LocationPane(), installPane, new FinishPane() };
}
}
class AJDEForJBuilderInstaller extends Installer {
public String getTitle() {
return "AspectJ(TM) Support for JBuilder";
}
public String getPrefix() {
return "ajdeForJBuilder";
}
public AJDEForJBuilderInstaller() {
InstallPane installPane = new InstallPane(false);
setInstallPane(installPane);
panes = new WizardPane[] { new IntroPane(), new LocationPane() {
public String getDefaultLocation() {
if (context.onWindows()) {
// check some default locations
String[] paths = { "c:\\JBuilder6\\lib\\ext", "c:\\apps\\JBuilder6\\lib\\ext",
"c:\\Program Files\\JBuilder6\\lib\\ext" };
int pathIndex = 0;
for (; pathIndex < paths.length; pathIndex++) {
if (new File(paths[pathIndex]).exists()) {
return paths[pathIndex];
}
}
return "c:\\JBuilder6\\lib\\ext";
} else {
return "/usr/JBuilder6/lib/ext";
}
}
/**
* Make sure that the old jar file gets removed.
*/
public void verify() {
File jbuilder = new File(location.getText() + "/../../lib/jbuilder.jar");
if (!jbuilder.exists() && hasGui()) {
int ret = JOptionPane.showConfirmDialog(frame, "The location you specified does not seem to be a "
+ "valid JBuilder install directory." + " Continue?", "Confirm Install", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (ret != JOptionPane.YES_OPTION) {
Main.exit(-1);
} else {
// do nothing
}
}
File oldFile = new File(location.getText() + "/ajbuilder.jar");
if (oldFile.exists() && hasGui()) {
int ret = JOptionPane.showConfirmDialog(frame,
"This old version of AJDE for JBuilder (\"ajbuilder.jar\") exists"
+ " and must be removed from the install directory." + " OK to delete?", "Confirm Delete",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (ret != JOptionPane.YES_OPTION) {
Main.exit(-1);
} else {
oldFile.delete();
}
}
}
}, installPane, new FinishPane() };
}
}
class AJDEForForteInstaller extends Installer {
public String getTitle() {
return "AspectJ(TM) Support for Forte 4J";
}
public String getPrefix() {
return "ajdeForForte";
}
private String installLoc = "";
public AJDEForForteInstaller() {
InstallPane installPane = new InstallPane(false);
setInstallPane(installPane);
panes = new WizardPane[] { new IntroPane(), new LocationPane() {
public String getDefaultLocation() {
if (context.onWindows()) {
// check some default locations
String[] paths = { "c:\\forte4j\\modules", "c:\\apps\\forte4j\\modules", "c:\\Program Files\\forte4j\\modules" };
int pathIndex = 0;
for (; pathIndex < paths.length; pathIndex++) {
if (new File(paths[pathIndex]).exists()) {
return paths[pathIndex];
}
}
return "c:\\forte4j\\modules";
} else {
return "/usr/forte4j/modules";
}
}
public void verify() {
File forte = new File(location.getText() + "/../lib/openide.jar");
installLoc = location.getText();
if (!forte.exists() && hasGui()) {
int ret = JOptionPane.showConfirmDialog(frame, "The location you specified does not seem to be a "
+ "valid Forte install directory." + " Continue?", "Confirm Install", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (ret != JOptionPane.YES_OPTION) {
Main.exit(-1);
} else {
// do nothing
}
}
}
}, installPane, new FinishPane() {
public void finalActions() { // todo verify dir ../lib/ext exists?
// !!! this should be done with two install locations, not by moving a file
new File(installLoc + "/../lib/ext/aspectjrt.jar").delete();
new File(installLoc + "/aspectjrt.jar").renameTo(new File((installLoc + "/../lib/ext/aspectjrt.jar")));
new File(installLoc + "/aspectjrt.jar").delete();
}
} };
}
}
class SrcInstaller extends Installer {
public String getTitle() {
return "AspectJ(TM) Compiler and Core Tools Sources Installer";
}
public String getPrefix() {
return "sources";
}
public SrcInstaller() {
InstallPane installPane = new InstallPane(false);
setInstallPane(installPane);
panes = new WizardPane[] { new IntroPane(), new LocationPane(), installPane, new FinishPane() };
}
}
abstract class Installer {
static final String EXIT_MESSAGE = "Are you sure you want to cancel the installation?";
static final String EXIT_TITLE = "Exiting installer";
/**
* relative directory in jar from package $installer$.org.aspectj for loading resources - todo must be tracked during build
*/
public static final String RESOURCE_DIR = "resources";
JFrame frame;
InstallContext context;
/** special pane that actually does the installation */
InstallPane installPane;
public Installer() {
}
protected void setInstallPane(InstallPane installPane) {
this.installPane = installPane;
}
public InstallPane getInstallPane() {
return installPane;
}
/** directly run the install pane, if any */
public void run() {
if (null != installPane) {
installPane.run();
}
}
public abstract String getPrefix();
public String getReadmeFilename() {
return "README-" + getPrefix().toUpperCase() + ".html";
}
public void setContext(InstallContext context) {
this.context = context;
context.installer = this;
}
public InstallContext getContext() {
return context;
}
public String getTitle() {
return "AspectJ(TM) Installer";
}
public int getWidth() {
return 640;
}
public int getHeight() {
return 460;
}
protected WizardPane[] panes = new WizardPane[0];
public WizardPane[] getPanes() {
return panes;
}
public int findPaneIndex(WizardPane pane) {
for (int i = 0; i < panes.length; i++) {
if (panes[i] == pane) {
return i;
}
}
return -1;
}
Component header, footer, body;
public void runGUI() {
frame = new JFrame(getTitle());
WindowListener wl = new WindowAdapter() {
public void windowClosing(WindowEvent arg0) {
Main.exit(-1); // -1 unless exiting through done button
}
};
frame.addWindowListener(wl);
if (Options.forceError1) {
throw new RuntimeException("forced error1 for testing purposes");
}
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) (size.getWidth() - getWidth()) / 2;
int y = (int) (size.getHeight() - getHeight()) / 2;
//include a few sanity checks on starting position
if (x < 0) {
x = 0;
}
if (x > 600) {
x = 600;
}
if (y < 0) {
y = 0;
}
if (y > 400) {
y = 400;
}
frame.setLocation(x, y);
frame.setSize(getWidth(), getHeight());
moveToPane(getPanes()[0]);
frame.setVisible(true);
}
public void moveToPane(WizardPane pane) {
WizardPane.setContext(this.context);
Dimension size = frame.getContentPane().getSize();
JPanel contents = new JPanel();
contents.setLayout(new BorderLayout());
header = makeHeader();
contents.add(header, BorderLayout.NORTH);
body = pane.getPanel();
contents.add(body, BorderLayout.CENTER);
footer = pane.getButtons();
contents.add(footer, BorderLayout.SOUTH);
contents.revalidate();
contents.setSize(size);
frame.setContentPane(contents);
//XXX deal with threading here?
pane.run();
}
public Icon loadImage(String name) {
return new javax.swing.ImageIcon(this.getClass().getResource(name));
}
public Component makeHeader() {
return new JLabel(loadImage(Installer.RESOURCE_DIR + "/aspectjBanner.gif"));
}
public ActionListener makeNextAction(final WizardPane pane) {
int nextPaneIndex = findPaneIndex(pane) + 1;
if (nextPaneIndex >= getPanes().length) {
return null;
}
final WizardPane nextPane = getPanes()[nextPaneIndex];
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
pane.finish();
moveToPane(nextPane);
}
};
}
public ActionListener makeBackAction(final WizardPane pane) {
int nextPaneIndex = findPaneIndex(pane) - 1;
if (nextPaneIndex < 0) {
return null;
}
final WizardPane nextPane = getPanes()[nextPaneIndex];
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
moveToPane(nextPane);
}
};
}
public ActionListener makeCancelAction(WizardPane pane) {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
int ret = JOptionPane.showConfirmDialog(frame, EXIT_MESSAGE, EXIT_TITLE, JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (ret == JOptionPane.YES_OPTION) {
Main.exit(-1);
}
}
};
}
public ActionListener makeFinishAction(WizardPane pane) {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
Main.exit(0);
}
};
}
}
// willing to go up to 3 levels deep to find either jre or jdk
// jre\[*\]lib\ext
// jdk*\lib\tools.jar
/*****
* final static int MAX_DEPTH = 4; public static void findPaths(String prefix, File currentDir, int currentDepth) { if (currentDepth
* > MAX_DEPTH) return; if (!currentDir.exists() || !currentDir.isDirectory()) return; File [] files = currentDir.listFiles(); if
* (files == null) return; for (int i=0; i");
int stopIndex = text.indexOf("");
if (startIndex == -1 || stopIndex == -1) {
return text;
}
stopIndex += 7;
return text.substring(0, startIndex) + text.substring(stopIndex);
}
static String styleHeader = "";/*
*