diff options
| author | Reinier Zwitserloot <reinier@tipit.to> | 2009-07-05 00:49:54 +0200 |
|---|---|---|
| committer | Reinier Zwitserloot <reinier@tipit.to> | 2009-07-05 00:49:54 +0200 |
| commit | e7492d444cace44a39d94853512c31a9b95d930d (patch) | |
| tree | c245e78ba3b328f255c1584f0702c04251d6dd4f | |
| parent | 938d4bb9f231722b2f55b71a05ecf9c3878119aa (diff) | |
| download | lombok-e7492d444cace44a39d94853512c31a9b95d930d.tar.gz lombok-e7492d444cace44a39d94853512c31a9b95d930d.tar.bz2 lombok-e7492d444cace44a39d94853512c31a9b95d930d.zip | |
W00t - written an installer that should work on linux (sort of), windows, and Mac OS X. Bumped the version number to celebrate, and changed build to roll the agent.jar into the main jar, and
change the executable class from the minimal help that was there to the installer. That minimal help thing (ShowUserHelp.java) is now gone.
| -rw-r--r-- | build.xml | 23 | ||||
| -rw-r--r-- | src/lombok/core/ShowUserHelp.java | 32 | ||||
| -rw-r--r-- | src/lombok/core/Version.java | 2 | ||||
| -rw-r--r-- | src/lombok/installer/EclipseFinder.java | 146 | ||||
| -rw-r--r-- | src/lombok/installer/EclipseLocation.java | 313 | ||||
| -rw-r--r-- | src/lombok/installer/InstallerWindow.java | 732 | ||||
| -rw-r--r-- | src/lombok/installer/loading.gif | bin | 0 -> 2248 bytes | |||
| -rw-r--r-- | src/lombok/installer/lombokIcon.png | bin | 0 -> 863 bytes | |||
| -rw-r--r-- | src/lombok/installer/lombokText.png | bin | 0 -> 3055 bytes | |||
| -rw-r--r-- | src/lombok/installer/lombokText.svg | 58 |
10 files changed, 1242 insertions, 64 deletions
@@ -40,6 +40,14 @@ <classpath refid="lombok.deps.path" /> <classpath refid="lombok.libs.path" /> </javac> + <copy todir="build/lombok"> + <fileset dir="src"> + <exclude name="**/*.java" /> + <exclude name="**/*.class" /> + <exclude name="**/*.svg" /> + </fileset> + </copy> + <mkdir dir="build/lombok/META-INF" /> <mkdir dir="build/lombok/META-INF/services" /> <echo file="build/lombok/META-INF/services/javax.annotation.processing.Processor">lombok.javac.apt.Processor</echo> @@ -78,18 +86,21 @@ <target name="dist" depends="clean, compile, getVersion, unpackLibs"> <mkdir dir="dist" /> - <jar basedir="build/lombok" destfile="dist/lombok-${lombok.version}.jar"> - <manifest> - <attribute name="Main-Class" value="lombok.core.ShowUserHelp" /> - </manifest> - </jar> <jar basedir="build/eclipse.agent" destfile="dist/lombok.eclipse.agent-${lombok.version}.jar"> <manifest> <attribute name="Premain-Class" value="lombok.eclipse.agent.EclipsePatcher" /> <attribute name="Can-Redefine-Classes" value="true" /> </manifest> </jar> - <copy file="dist/lombok-${lombok.version}.jar" tofile="dist/lombok.jar" /> <copy file="dist/lombok.eclipse.agent-${lombok.version}.jar" tofile="dist/lombok.eclipse.agent.jar" /> + <jar destfile="dist/lombok-${lombok.version}.jar"> + <fileset dir="build/lombok" /> + <fileset dir="dist" includes="lombok.eclipse.agent.jar" /> + + <manifest> + <attribute name="Main-Class" value="lombok.installer.InstallerWindow" /> + </manifest> + </jar> + <copy file="dist/lombok-${lombok.version}.jar" tofile="dist/lombok.jar" /> </target> </project> diff --git a/src/lombok/core/ShowUserHelp.java b/src/lombok/core/ShowUserHelp.java deleted file mode 100644 index 443de833..00000000 --- a/src/lombok/core/ShowUserHelp.java +++ /dev/null @@ -1,32 +0,0 @@ -package lombok.core; - -import java.net.URI; - -/** - * This class is used as main class for the lombok jar; this way, if the jar is run as java app, the user is pointed - * at documentation about lombok. - */ -public class ShowUserHelp { - private static final URI ABOUT_LOMBOK_URL = URI.create("http://wiki.github.com/rzwitserloot/lombok"); - - public static void main(String[] args) { - boolean browserOpened = false; - try { - //java.awt.Desktop doesn't exist in 1.5, and for IDE's sakes, we may want to work in java1.5 someday, so... - Object desktop = Class.forName("java.awt.Desktop").getMethod("getDesktop").invoke(null); - Class.forName("java.awt.Desktop").getMethod("browse", URI.class).invoke(desktop, ABOUT_LOMBOK_URL); - browserOpened = true; - } catch ( Exception ignore ) {} - - String version = Version.getVersion(); - final String nextStep = browserOpened ? "See your browser window" : - String.format("Browse to %s", ABOUT_LOMBOK_URL); - - System.out.printf("About lombok v%s\n" + - "Lombok makes java better by providing very spicy additions to the Java programming language," + - "such as using @Getter to automatically generate a getter method for any field.\n\n%s" + - " for more information about the lombok project, and how to" + - "install it into your programming environment. If you are just using javac (the java compiler)," + - "just use this jar, no further steps needed.", version, nextStep); - } -} diff --git a/src/lombok/core/Version.java b/src/lombok/core/Version.java index eff6b151..cb349aaf 100644 --- a/src/lombok/core/Version.java +++ b/src/lombok/core/Version.java @@ -1,7 +1,7 @@ package lombok.core; public class Version { - private static final String VERSION = "0.3.5"; + private static final String VERSION = "0.4"; private Version() { //Prevent instantiation diff --git a/src/lombok/installer/EclipseFinder.java b/src/lombok/installer/EclipseFinder.java new file mode 100644 index 00000000..1ca82440 --- /dev/null +++ b/src/lombok/installer/EclipseFinder.java @@ -0,0 +1,146 @@ +package lombok.installer; + +import static java.util.Arrays.asList; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import lombok.Lombok; + +public class EclipseFinder { + public static File findOurJar() { + try { + URI uri = EclipseFinder.class.getResource("/" + EclipseFinder.class.getName().replace('.', '/') + ".class").toURI(); + Pattern p = Pattern.compile("^jar:file:([^\\!]+)\\!.*\\.class$"); + System.out.println(uri.toString()); + Matcher m = p.matcher(uri.toString()); + if ( !m.matches() ) return new File("lombok.jar"); + String rawUri = m.group(1); + return new File(URLDecoder.decode(rawUri, Charset.defaultCharset().name())); + } catch ( Exception e ) { + throw Lombok.sneakyThrow(e); + } + } + + public static List<String> getDrivesOnWindows() throws IOException { + ProcessBuilder builder = new ProcessBuilder("c:\\windows\\system32\\fsutil.exe", "fsinfo", "drives"); + builder.redirectErrorStream(true); + Process process = builder.start(); + InputStream in = process.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(in, "ISO-8859-1")); + + List<String> drives = new ArrayList<String>(); + + String line; + while ( (line = br.readLine()) != null ) { + if ( line.startsWith("Drives: ") ) { + line = line.substring(8); + for ( String driveLetter : line.split("\\:\\\\\\s*") ) drives.add(driveLetter.trim()); + } + } + + Iterator<String> it = drives.iterator(); + while ( it.hasNext() ) { + if ( !isLocalDriveOnWindows(it.next()) ) it.remove(); + } + + return drives; + } + + public static boolean isLocalDriveOnWindows(String driveLetter) { + if ( driveLetter == null || driveLetter.length() == 0 ) return false; + try { + ProcessBuilder builder = new ProcessBuilder("c:\\windows\\system32\\fsutil.exe", "fsinfo", "drivetype", driveLetter + ":"); + builder.redirectErrorStream(true); + Process process = builder.start(); + InputStream in = process.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(in, "ISO-8859-1")); + + String line; + while ( (line = br.readLine()) != null ) { + if ( line.substring(5).equalsIgnoreCase("Fixed Drive") ) return true; + } + + return false; + } catch ( Exception e ) { + return false; + } + } + + public static List<String> findEclipseOnWindows() { + List<String> eclipses = new ArrayList<String>(); + List<String> driveLetters = asList("C"); + + try { + driveLetters = getDrivesOnWindows(); + } catch ( IOException ignore ) {} + + for ( String letter : driveLetters ) { + File f = new File(letter + ":\\"); + for ( File dir : f.listFiles() ) { + if ( !dir.isDirectory() ) continue; + if ( dir.getName().toLowerCase().contains("eclipse") ) { + String eclipseLocation = findEclipseOnWindows1(dir); + if ( eclipseLocation != null ) eclipses.add(eclipseLocation); + } + if ( dir.getName().toLowerCase().contains("program files") ) { + for ( File dir2 : dir.listFiles() ) { + if ( !dir2.isDirectory() ) continue; + if ( dir.getName().toLowerCase().contains("eclipse") ) { + String eclipseLocation = findEclipseOnWindows1(dir); + if ( eclipseLocation != null ) eclipses.add(eclipseLocation); + } + } + } + } + } + + return eclipses; + } + + private static String findEclipseOnWindows1(File dir) { + if ( new File(dir, "eclipse.exe").isFile() ) return dir.toString(); + return null; + } + + public static void main(String[] args) throws Exception { + System.out.println(findEclipses()); + } + + public static List<String> findEclipses() { + String prop = System.getProperty("os.name", ""); + if ( prop.equalsIgnoreCase("Mac OS X") ) return findEclipseOnMac(); + if ( prop.equalsIgnoreCase("Windows XP") ) return findEclipseOnWindows(); + + return null; + } + + public static String getEclipseExecutableName() { + String prop = System.getProperty("os.name", ""); + if ( prop.equalsIgnoreCase("Mac OS X") ) return "Eclipse.app"; + if ( prop.equalsIgnoreCase("Windows XP") ) return "eclipse.exe"; + + return "eclipse"; + } + + public static List<String> findEclipseOnMac() { + List<String> eclipses = new ArrayList<String>(); + for ( File dir : new File("/Applications").listFiles() ) { + if ( dir.getName().toLowerCase().contains("eclipse") ) { + if ( new File(dir, "Eclipse.app").exists() ) eclipses.add(dir.toString()); + } + } + return eclipses; + } +} diff --git a/src/lombok/installer/EclipseLocation.java b/src/lombok/installer/EclipseLocation.java new file mode 100644 index 00000000..400b5606 --- /dev/null +++ b/src/lombok/installer/EclipseLocation.java @@ -0,0 +1,313 @@ +package lombok.installer; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.List; +import java.util.jar.JarFile; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; + +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +final class EclipseLocation { + private static final String OS_NEWLINE; + + static { + String os = System.getProperty("os.name", ""); + + if ( "Mac OS".equals(os) ) OS_NEWLINE = "\r"; + else if ( os.toLowerCase().contains("windows") ) OS_NEWLINE = "\r\n"; + else OS_NEWLINE = "\n"; + } + + private final File path; + private volatile boolean hasLombok; + boolean selected = true; + + final class NotAnEclipseException extends Exception { + private static final long serialVersionUID = 1L; + + public NotAnEclipseException(String message, Throwable cause) { + super(message, cause); + } + + public void showDialog(JFrame appWindow) { + JOptionPane.showMessageDialog(appWindow, getMessage(), "Cannot configure eclipse installation", JOptionPane.WARNING_MESSAGE); + } + } + + EclipseLocation(String path) throws NotAnEclipseException { + if ( path == null ) throw new NullPointerException("path"); + File p = new File(path); + if ( !p.exists() ) throw new NotAnEclipseException("File does not exist: " + path, null); + + final String execName = EclipseFinder.getEclipseExecutableName(); + if ( p.isDirectory() ) { + for ( File f : p.listFiles() ) { + if ( f.getName().equalsIgnoreCase(execName) ) { + p = f; + break; + } + } + } + + this.path = p; + try { + this.hasLombok = checkForLombok(); + } catch ( IOException e ) { + throw new NotAnEclipseException( + "I can't read the configuration file of the eclipse installed at " + this.path.getAbsolutePath() + "\n" + + "You may need to run this installer with root privileges if you want to modify that eclipse.", e); + } + } + + public int hashCode() { + return path.hashCode(); + } + + public boolean equals(Object o) { + if ( !(o instanceof EclipseLocation) ) return false; + return ((EclipseLocation)o).path.equals(path); + } + + public String getPath() { + return path.getAbsolutePath(); + } + + public boolean hasLombok() { + return hasLombok; + } + + private List<File> getTargetDirs() { + return Arrays.asList(path.getParentFile(), new File(new File(path, "Contents"), "MacOS")); + } + + private boolean checkForLombok() throws IOException { + for ( File targetDir : getTargetDirs() ) { + if ( checkForLombok0(targetDir) ) return true; + } + + return false; + } + + private final Pattern JAVA_AGENT_LINE_MATCHER = Pattern.compile( + "^\\-javaagent\\:.*lombok.*\\.jar$", Pattern.CASE_INSENSITIVE); + + private final Pattern BOOTCLASSPATH_LINE_MATCHER = Pattern.compile( + "^\\-Xbootclasspath\\/a\\:(.*lombok.*\\.jar.*)$", Pattern.CASE_INSENSITIVE); + + private boolean checkForLombok0(File dir) throws IOException { + File iniFile = new File(dir, "eclipse.ini"); + if ( !iniFile.exists() ) return false; + FileInputStream fis = new FileInputStream(iniFile); + try { + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line; + while ( (line = br.readLine()) != null ) { + if ( JAVA_AGENT_LINE_MATCHER.matcher(line.trim()).matches() ) return true; + } + + return false; + } finally { + fis.close(); + } + } + + public class UninstallException extends Exception { + private static final long serialVersionUID = 1L; + + public UninstallException(String message, Throwable cause) { + super(message, cause); + } + } + + public void uninstall() throws UninstallException { + for ( File dir : getTargetDirs() ) { + File lombokJar = new File(dir, "lombok.jar"); + if ( lombokJar.exists() ) { + if ( !lombokJar.delete() ) throw new UninstallException( + "Can't delete " + lombokJar.getAbsolutePath() + + " - perhaps the installer does not have the access rights to do so.", + null); + } + + File agentJar = new File(dir, "lombok.eclipse.agent.jar"); + if ( agentJar.exists() ) { + if ( !agentJar.delete() ) throw new UninstallException( + "Can't delete " + agentJar.getAbsolutePath() + + " - perhaps the installer does not have the access rights to do so.", + null); + } + + File iniFile = new File(dir, "eclipse.ini"); + StringBuilder newContents = new StringBuilder(); + if ( iniFile.exists() ) { + try { + FileInputStream fis = new FileInputStream(iniFile); + try { + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line; + while ( (line = br.readLine()) != null ) { + if ( JAVA_AGENT_LINE_MATCHER.matcher(line).matches() ) continue; + Matcher m = BOOTCLASSPATH_LINE_MATCHER.matcher(line); + if ( m.matches() ) { + StringBuilder elemBuilder = new StringBuilder(); + elemBuilder.append("-Xbootclasspath/a:"); + boolean first = true; + for ( String elem : m.group(1).split(Pattern.quote(File.pathSeparator)) ) { + if ( elem.toLowerCase().endsWith("lombok.jar") ) continue; + if ( elem.toLowerCase().endsWith("lombok.eclipse.agent.jar") ) continue; + if ( first ) first = false; + else elemBuilder.append(File.pathSeparator); + elemBuilder.append(elem); + } + if ( !first ) newContents.append(elemBuilder.toString()).append(OS_NEWLINE); + continue; + } + + newContents.append(line).append(OS_NEWLINE); + } + + } finally { + fis.close(); + } + + FileOutputStream fos = new FileOutputStream(iniFile); + try { + fos.write(newContents.toString().getBytes()); + } finally { + fos.close(); + } + } catch ( IOException e ) { + throw new UninstallException("Cannot uninstall lombok from " + path.getAbsolutePath() + + " probably because this installer does not have the access rights to do so.", e); + } + } + } + } + + public class InstallException extends Exception { + private static final long serialVersionUID = 1L; + + public InstallException(String message, Throwable cause) { + super(message, cause); + } + } + + public void install() throws InstallException { + for ( File dir : getTargetDirs() ) { + File iniFile = new File(dir, "eclipse.ini"); + StringBuilder newContents = new StringBuilder(); + if ( iniFile.exists() ) { + File lombokJar = new File(iniFile.getParentFile(), "lombok.jar"); + File agentJar = new File(iniFile.getParentFile(), "lombok.eclipse.agent.jar"); + + File ourJar = EclipseFinder.findOurJar(); + byte[] b = new byte[524288]; + boolean readSucceeded = false; + boolean installSucceeded = false; + try { + JarFile jar = new JarFile(ourJar); + + try { + ZipEntry entry = jar.getEntry("lombok.eclipse.agent.jar"); + InputStream in = jar.getInputStream(entry); + FileOutputStream out = new FileOutputStream(agentJar); + try { + while ( true ) { + int r = in.read(b); + if ( r == -1 ) break; + readSucceeded = true; + out.write(b, 0, r); + } + } finally { + out.close(); + } + } finally { + jar.close(); + + } + + FileOutputStream out = new FileOutputStream(lombokJar); + InputStream in = new FileInputStream(ourJar); + try { + while ( true ) { + int r = in.read(b); + if ( r == -1 ) break; + out.write(b, 0, r); + } + } finally { + out.close(); + } + } catch ( IOException e ) { + try { + lombokJar.delete(); + agentJar.delete(); + } catch ( Throwable ignore ) {} + if ( !readSucceeded ) throw new InstallException("I can't read my own jar file. I think you've found a bug in this installer! I suggest you restart it " + + "and use the 'what do I do' link, to manually install lombok. And tell us about this. Thanks!", e); + throw new InstallException("I can't write to your eclipse directory, probably because this installer does not have the access rights.", e); + } + + try { + FileInputStream fis = new FileInputStream(iniFile); + try { + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line; + while ( (line = br.readLine()) != null ) { + if ( JAVA_AGENT_LINE_MATCHER.matcher(line).matches() ) continue; + Matcher m = BOOTCLASSPATH_LINE_MATCHER.matcher(line); + if ( m.matches() ) { + StringBuilder elemBuilder = new StringBuilder(); + elemBuilder.append("-Xbootclasspath/a:"); + boolean first = true; + for ( String elem : m.group(1).split(Pattern.quote(File.pathSeparator)) ) { + if ( elem.toLowerCase().endsWith("lombok.jar") ) continue; + if ( elem.toLowerCase().endsWith("lombok.eclipse.agent.jar") ) continue; + if ( first ) first = false; + else elemBuilder.append(File.pathSeparator); + elemBuilder.append(elem); + } + if ( !first ) newContents.append(elemBuilder.toString()).append(OS_NEWLINE); + continue; + } + + newContents.append(line).append(OS_NEWLINE); + } + + } finally { + fis.close(); + } + + newContents.append("-javaagent:lombok.jar").append(OS_NEWLINE); + newContents.append("-Xbootclasspath/a:lombok.jar" + File.pathSeparator + "lombok.eclipse.agent.jar").append(OS_NEWLINE); + + FileOutputStream fos = new FileOutputStream(iniFile); + try { + fos.write(newContents.toString().getBytes()); + } finally { + fos.close(); + } + installSucceeded = true; + + } catch ( IOException e ) { + throw new InstallException("Cannot install lombok at " + path.getAbsolutePath() + + " probably because this installer does not have the access rights to do so.", e); + } finally { + if ( !installSucceeded ) try { + lombokJar.delete(); + agentJar.delete(); + } catch ( Throwable ignore ) {} + } + } + } + } +} diff --git a/src/lombok/installer/InstallerWindow.java b/src/lombok/installer/InstallerWindow.java index 7db465be..a0911c26 100644 --- a/src/lombok/installer/InstallerWindow.java +++ b/src/lombok/installer/InstallerWindow.java @@ -1,48 +1,740 @@ package lombok.installer; -import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.font.TextAttribute; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import javax.swing.Box; +import javax.swing.BoxLayout; import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.Scrollable; import javax.swing.SwingUtilities; +import javax.swing.filechooser.FileFilter; import lombok.core.Version; +import lombok.installer.EclipseLocation.InstallException; +import lombok.installer.EclipseLocation.NotAnEclipseException; +import lombok.installer.EclipseLocation.UninstallException; public class InstallerWindow { - private JFrame jFrame; - private JLabel mainText; - private JLabel leftGraphic, topGraphic; + private static final URI ABOUT_LOMBOK_URL = URI.create("http://projectlombok.org"); + + private JFrame appWindow; + + private JComponent loadingExpl; + + private Component javacArea; + private Component eclipseArea; + private Component uninstallArea; + private Component howIWorkArea; + + private Box uninstallBox; + + private List<EclipseLocation> toUninstall; public static void main(String[] args) { + try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + new InstallerWindow().show(); + } catch ( HeadlessException e ) { + printHeadlessInfo(); + } + } + }); + } catch ( HeadlessException e ) { + printHeadlessInfo(); + } + } + + private static void printHeadlessInfo() { + System.out.printf("About lombok v%s\n" + + "Lombok makes java better by providing very spicy additions to the Java programming language," + + "such as using @Getter to automatically generate a getter method for any field.\n\n" + + "Browse to %s for more information. To install lombok on eclipse, re-run this jar file on a " + + "graphical computer system - this message is being shown because your terminal is not graphics capable." + + "If you are just using 'javac' or a tool that calls on javac, no installation is neccessary; just " + + "make sure lombok.jar is in the classpath when you compile. Example:\n\n" + + " java -cp lombok.jar MyCode.java", Version.getVersion(), ABOUT_LOMBOK_URL); + } + + public InstallerWindow() { + appWindow = new JFrame(String.format("Project Lombok v%s - Installer", Version.getVersion())); + + appWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + appWindow.setResizable(false); + + try { + javacArea = buildJavacArea(); + eclipseArea = buildEclipseArea(); + uninstallArea = buildUninstallArea(); + uninstallArea.setVisible(false); + howIWorkArea = buildHowIWorkArea(); + howIWorkArea.setVisible(false); + buildChrome(appWindow.getContentPane()); + appWindow.pack(); + } catch ( Throwable t ) { + handleException(t); + } + } + + private void handleException(final Throwable t) { SwingUtilities.invokeLater(new Runnable() { - public void run() { - new InstallerWindow().show(); + @Override public void run() { + JOptionPane.showMessageDialog(appWindow, "There was a problem during the installation process:\n" + t, "Uh Oh!", JOptionPane.ERROR_MESSAGE); + System.exit(1); } }); } - public InstallerWindow() { - jFrame = new JFrame(String.format("Project Lombok v%s - Installer", Version.getVersion())); + private Component buildHowIWorkArea() { + JPanel container = new JPanel(); + + container.setLayout(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.WEST; + + container.add(new JLabel(HOW_I_WORK_TITLE), constraints); - //We want to offer an undo feature when the user cancels in the middle of an operation. - jFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + constraints.gridy = 1; + constraints.insets = new Insets(8, 0, 0, 16); + container.add(new JLabel(HOW_I_WORK_EXPLANATION), constraints); - leftGraphic = new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/lombok.png"))); - topGraphic = new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/lombokText.png"))); - mainText = new JLabel("Explanatory stuff goes here."); + Box buttonBar = Box.createHorizontalBox(); + JButton backButton = new JButton("Okay - Good to know!"); + buttonBar.add(Box.createHorizontalGlue()); + buttonBar.add(backButton); - jFrame.setLayout(new BorderLayout()); - jFrame.add(leftGraphic, BorderLayout.WEST); - jFrame.add(topGraphic, BorderLayout.NORTH); - jFrame.add(mainText, BorderLayout.CENTER); + backButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + howIWorkArea.setVisible(false); + javacArea.setVisible(true); + eclipseArea.setVisible(true); + appWindow.pack(); + } + }); + constraints.gridy = 2; + container.add(buttonBar, constraints); - jFrame.pack(); - System.out.println("WE SHOULD BE UP"); + return container; + } + + private Component buildUninstallArea() { + JPanel container = new JPanel(); + + container.setLayout(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.WEST; + + container.add(new JLabel(UNINSTALL_TITLE), constraints); + + constraints.gridy = 1; + constraints.insets = new Insets(8, 0, 0, 16); + container.add(new JLabel(UNINSTALL_EXPLANATION), constraints); + + uninstallBox = Box.createVerticalBox(); + constraints.gridy = 2; + constraints.fill = GridBagConstraints.HORIZONTAL; + container.add(uninstallBox, constraints); + + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridy = 3; + container.add(new JLabel("Are you sure?"), constraints); + + Box buttonBar = Box.createHorizontalBox(); + JButton noButton = new JButton("No - Don't uninstall"); + buttonBar.add(noButton); + buttonBar.add(Box.createHorizontalGlue()); + JButton yesButton = new JButton("Yes - uninstall Lombok"); + buttonBar.add(yesButton); + + noButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + uninstallArea.setVisible(false); + javacArea.setVisible(true); + eclipseArea.setVisible(true); + appWindow.pack(); + } + }); + + yesButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + doUninstall(); + } + }); + + constraints.gridy = 4; + container.add(buttonBar, constraints); + + return container; + } + + private Component buildJavacArea() { + JPanel container = new JPanel(); + + container.setLayout(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.WEST; + + container.add(new JLabel(JAVAC_TITLE), constraints); + + constraints.gridy = 1; + constraints.insets = new Insets(8, 0, 0, 16); + container.add(new JLabel(JAVAC_EXPLANATION), constraints); + + JLabel example = new JLabel(JAVAC_EXAMPLE); + + constraints.gridy = 2; + constraints.insets = new Insets(8, 0, 0, 16); + container.add(example, constraints); + return container; + } + + private Component buildEclipseArea() throws IOException { + // "Or:" [I'll tell you where eclipse is] [Tell me how to install lombok manually] + + //Mode 2 (manual): + // Replace the entirety of the content (javac+eclipse) with an explanation about what to do: + // - copy lombok.jar to your eclipse directory. + // - jar xvf lombok.jar lombok.eclipse.agent.jar + // - edit eclipse.ini with: + // -javaagent:../../../lombok.eclipse.agent.jar + // -Xbootclasspath/a:../../../lombok.eclipse.agent.jar:../../../lombok.jar + + //Mode 3 (let me choose): + // pop up a file chooser. Make sure we don't care what you pick - eclipse.ini, eclipse.exe, eclipse.app, or dir. + // empty the list, remove the spinner and the [let me find eclipse on my own] button, and put the chosen + // eclipse in the list. + + JPanel container = new JPanel(); + + container.setLayout(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.WEST; + + container.add(new JLabel(ECLIPSE_TITLE), constraints); + + constraints.gridy = 1; + constraints.insets = new Insets(8, 0, 0, 16); + container.add(new JLabel(ECLIPSE_EXPLANATION), constraints); + + constraints.gridy = 2; + loadingExpl = Box.createHorizontalBox(); + loadingExpl.add(new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/loading.gif")))); + loadingExpl.add(new JLabel(ECLIPSE_LOADING_EXPLANATION)); + container.add(loadingExpl, constraints); + + constraints.weightx = 1.0; + constraints.gridy = 3; + constraints.fill = GridBagConstraints.HORIZONTAL; + eclipsesList = new EclipsesList(); + + JScrollPane eclipsesListScroll = new JScrollPane(eclipsesList); + eclipsesListScroll.setBackground(Color.WHITE); + container.add(eclipsesListScroll, constraints); + + Thread findEclipsesThread = new Thread() { + @Override public void run() { + try { + final List<String> eclipses = EclipseFinder.findEclipses(); + final List<EclipseLocation> locations = new ArrayList<EclipseLocation>(); + final List<NotAnEclipseException> problems = new ArrayList<NotAnEclipseException>(); + + for ( String eclipse : eclipses ) try { + locations.add(new EclipseLocation(eclipse)); + } catch ( NotAnEclipseException e ) { + problems.add(e); + } + + SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { + for ( EclipseLocation location : locations ) { + try { + eclipsesList.addEclipse(location); + } catch ( Throwable t ) { + handleException(t); + } + } + + for ( NotAnEclipseException problem : problems ) { + problem.showDialog(appWindow); + } + + loadingExpl.setVisible(false); + } + }); + } catch ( Throwable t ) { + handleException(t); + } + } + }; + + findEclipsesThread.start(); + + Box buttonBar = Box.createHorizontalBox(); + JButton specifyEclipseLocationButton = new JButton("Specify eclipse location..."); + buttonBar.add(specifyEclipseLocationButton); + specifyEclipseLocationButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent event) { + JFileChooser chooser = new JFileChooser(); + + chooser.setAcceptAllFileFilterUsed(false); + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + chooser.setFileFilter(new FileFilter() { + private final String name = EclipseFinder.getEclipseExecutableName(); + @Override public boolean accept(File f) { + if ( f.getName().equalsIgnoreCase(name) ) return true; + if ( f.isDirectory() ) return true; + + return false; + } + + @Override public String getDescription() { + return "Eclipse Installation"; + } + }); + + switch ( chooser.showDialog(appWindow, "Select") ) { + case JFileChooser.APPROVE_OPTION: + try { + try { + eclipsesList.addEclipse(new EclipseLocation(chooser.getSelectedFile().getAbsolutePath())); + } catch ( NotAnEclipseException e ) { + e.showDialog(appWindow); + } + } catch ( Throwable t ) { + handleException(t); + } + } + } + }); + buttonBar.add(Box.createHorizontalGlue()); + installButton = new JButton("Install / Update"); + buttonBar.add(installButton); + + installButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + List<EclipseLocation> locationsToInstall = new ArrayList<EclipseLocation>(eclipsesList.getSelectedEclipses()); + if ( locationsToInstall.isEmpty() ) { + JOptionPane.showMessageDialog(appWindow, "You haven't selected any eclipse installations!.", "No Selection", JOptionPane.WARNING_MESSAGE); + return; + } + + install(locationsToInstall); + } + }); + + constraints.gridy = 4; + constraints.weightx = 0; + container.add(buttonBar, constraints); + + constraints.gridy = 5; + constraints.fill = GridBagConstraints.NONE; + uninstallButton = new JHyperLink("Uninstall lombok from selected eclipse installations."); + uninstallButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + List<EclipseLocation> locationsToUninstall = new ArrayList<EclipseLocation>(); + for ( EclipseLocation location : eclipsesList.getSelectedEclipses() ) { + if ( location.hasLombok() ) locationsToUninstall.add(location); + } + + if ( locationsToUninstall.isEmpty() ) { + JOptionPane.showMessageDialog(appWindow, "You haven't selected any eclipse installations that have been lombok-ena |
