aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@tipit.to>2009-07-05 21:47:24 +0200
committerReinier Zwitserloot <reinier@tipit.to>2009-07-05 21:48:24 +0200
commita9fe617303f9726794451eaf2c517a8ec57f3faf (patch)
tree86444b4e19a7f79e66fd13b0371d349a806af41f
parent1f8a907187cbdeacc0947d3cc00d251640882a54 (diff)
downloadlombok-a9fe617303f9726794451eaf2c517a8ec57f3faf.tar.gz
lombok-a9fe617303f9726794451eaf2c517a8ec57f3faf.tar.bz2
lombok-a9fe617303f9726794451eaf2c517a8ec57f3faf.zip
Final touches on the installer:
- some bug fixes for linux - renamed InstallerWindow to Installer - Apple-specific prettification added (dock icon, app name) - more documentation. Also, I started added an open source licence to all files.
-rw-r--r--LICENCE19
-rw-r--r--README2
-rw-r--r--build.xml23
-rw-r--r--src/lombok/installer/AppleNativeLook.java41
-rw-r--r--src/lombok/installer/EclipseFinder.java132
-rw-r--r--src/lombok/installer/EclipseLocation.java116
-rw-r--r--src/lombok/installer/Installer.java (renamed from src/lombok/installer/InstallerWindow.java)176
-rw-r--r--src/lombok/installer/lombok.svg5
-rw-r--r--src/lombok/installer/package-info.java28
9 files changed, 466 insertions, 76 deletions
diff --git a/LICENCE b/LICENCE
new file mode 100644
index 00000000..c370acef
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,19 @@
+Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README b/README
index afb7c4bd..c900d849 100644
--- a/README
+++ b/README
@@ -2,7 +2,7 @@ projectlombok makes java a spicier language by adding 'handlers' that know how t
Using lombok is made as simple as possible, and aims to work on all major java IDEs as well as javac itself.
-projectlombok is open source under the Creative Commons - free to share, free to remix, provided you attribute the authors licence, as shown here: http://creativecommons.org/licenses/by/3.0/us/
+See LICENCE for the project lombok licence.
Project Authors:
diff --git a/build.xml b/build.xml
index 588dd8af..f285fe7e 100644
--- a/build.xml
+++ b/build.xml
@@ -1,3 +1,24 @@
+<!--
+ Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+-->
<project name="lombok" default="dist">
<property name="build.compiler" value="javac1.6" />
<path id="lombok.deps.path">
@@ -98,7 +119,7 @@
<fileset dir="dist" includes="lombok.eclipse.agent.jar" />
<manifest>
- <attribute name="Main-Class" value="lombok.installer.InstallerWindow" />
+ <attribute name="Main-Class" value="lombok.installer.Installer" />
</manifest>
</jar>
<copy file="dist/lombok-${lombok.version}.jar" tofile="dist/lombok.jar" />
diff --git a/src/lombok/installer/AppleNativeLook.java b/src/lombok/installer/AppleNativeLook.java
new file mode 100644
index 00000000..1d3cfff7
--- /dev/null
+++ b/src/lombok/installer/AppleNativeLook.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.installer;
+
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import com.apple.eawt.Application;
+
+/**
+ * Mac OS X specific code to gussy up the GUI a little bit, mostly with a nice dock icon. Well, nicer than
+ * the standard icon, at any rate.
+ */
+class AppleNativeLook {
+ public static void go() throws IOException {
+ Application app = Application.getApplication();
+ app.removeAboutMenuItem();
+ app.removePreferencesMenuItem();
+ app.setDockIconImage(ImageIO.read(AppleNativeLook.class.getResource("lombokIcon.png")));
+ }
+}
diff --git a/src/lombok/installer/EclipseFinder.java b/src/lombok/installer/EclipseFinder.java
index 1ca82440..3c966359 100644
--- a/src/lombok/installer/EclipseFinder.java
+++ b/src/lombok/installer/EclipseFinder.java
@@ -1,3 +1,24 @@
+/*
+ * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
package lombok.installer;
import static java.util.Arrays.asList;
@@ -18,8 +39,17 @@ import java.util.regex.Pattern;
import lombok.Lombok;
-public class EclipseFinder {
- public static File findOurJar() {
+/** Utility class for doing various OS-specific operations related to finding eclipse installations. */
+class EclipseFinder {
+ private EclipseFinder() {
+ //Prevent instantiation.
+ }
+
+ /**
+ * Returns a File object pointing to our own jar file. Will obviously fail if the installer was started via
+ * a jar that wasn't accessed via the file-system, or if its started via e.g. unpacking the jar.
+ */
+ static File findOurJar() {
try {
URI uri = EclipseFinder.class.getResource("/" + EclipseFinder.class.getName().replace('.', '/') + ".class").toURI();
Pattern p = Pattern.compile("^jar:file:([^\\!]+)\\!.*\\.class$");
@@ -33,7 +63,15 @@ public class EclipseFinder {
}
}
- public static List<String> getDrivesOnWindows() throws IOException {
+ /**
+ * Returns all drive letters on windows, regardless of what kind of drive is represented.
+ *
+ * Relies on the 'fsutil.exe' program. I have no idea if you can call it without triggering a gazillion
+ * security warnings on Vista. I did a cursory test on an out-of-the-box Windows XP and that seems to work.
+ *
+ * @return A List of drive letters, such as ["A", "C", "D", "X"].
+ */
+ static List<String> getDrivesOnWindows() throws IOException {
ProcessBuilder builder = new ProcessBuilder("c:\\windows\\system32\\fsutil.exe", "fsinfo", "drives");
builder.redirectErrorStream(true);
Process process = builder.start();
@@ -58,7 +96,12 @@ public class EclipseFinder {
return drives;
}
- public static boolean isLocalDriveOnWindows(String driveLetter) {
+ /**
+ * @return true if the letter represents a local fixed disk, false if its a disk drive, optical drive,
+ * USB stick, network drive, or any other kind of drive. Substed (virtual) drives that are an alias to
+ * a directory on a local disk cause a 'return true', but this is intentional.
+ */
+ 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 + ":");
@@ -78,7 +121,19 @@ public class EclipseFinder {
}
}
- public static List<String> findEclipseOnWindows() {
+ /**
+ * Returns a list of paths of eclipse installations.
+ * Eclipse installations are found by checking for the existence of 'eclipse.exe' in the following locations:
+ *
+ * X:\*Program Files*\*Eclipse*
+ * X:\*Eclipse*
+ *
+ * Where 'X' is tried for all local disk drives, unless there's a problem calling fsutil, in which case only
+ * C: is tried.
+ *
+ * @return A List of directories that contain 'eclipse.exe'.
+ */
+ static List<String> findEclipseOnWindows() {
List<String> eclipses = new ArrayList<String>();
List<String> driveLetters = asList("C");
@@ -109,34 +164,71 @@ public class EclipseFinder {
return eclipses;
}
+ /** Checks if the provided directory contains 'eclipse.exe', and if so, returns the directory, otherwise null. */
private static String findEclipseOnWindows1(File dir) {
- if ( new File(dir, "eclipse.exe").isFile() ) return dir.toString();
+ if ( new File(dir, "eclipse.exe").isFile() ) return dir.getAbsolutePath();
return null;
}
- public static void main(String[] args) throws Exception {
- System.out.println(findEclipses());
+ /**
+ * Calls the OS-dependent 'find eclipse' routine. If the local OS doesn't have a routine written for it,
+ * null is returned.
+ *
+ * @return List of directories that contain the eclipse executable.
+ */
+ static List<String> findEclipses() {
+ switch ( getOS() ) {
+ case WINDOWS:
+ return findEclipseOnWindows();
+ case MAC_OS_X:
+ return findEclipseOnMac();
+ default:
+ case UNIX:
+ return null;
+ }
}
- 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;
+ static enum OS {
+ MAC_OS_X, WINDOWS, UNIX;
}
- 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";
+ static OS getOS() {
+ String prop = System.getProperty("os.name", "").toLowerCase();
+ if ( prop.matches("^.*\\bmac\\b.*$") ) return OS.MAC_OS_X;
+ if ( prop.matches("^.*\\bwin(dows)\\b.*$") ) return OS.WINDOWS;
- return "eclipse";
+ return OS.UNIX;
}
- public static List<String> findEclipseOnMac() {
+ /**
+ * Returns the proper name of the executable for the local OS.
+ *
+ * @return 'Eclipse.app' on OS X, 'eclipse.exe' on Windows, and 'eclipse' on other OSes.
+ */
+ static String getEclipseExecutableName() {
+ switch ( getOS() ) {
+ case WINDOWS:
+ return "eclipse.exe";
+ case MAC_OS_X:
+ return "Eclipse.app";
+ default:
+ case UNIX:
+ return "eclipse";
+ }
+ }
+
+ /**
+ * Scans /Applications for any folder named 'Eclipse'
+ */
+ static List<String> findEclipseOnMac() {
List<String> eclipses = new ArrayList<String>();
for ( File dir : new File("/Applications").listFiles() ) {
+ if ( !dir.isDirectory() ) continue;
+ if ( dir.getName().toLowerCase().equals("eclipse.app") ) {
+ //This would be kind of an unorthodox eclipse installation, but if eclipse ever
+ //moves to this more maclike installation concept, our installer can still handle it.
+ eclipses.add("/Applications");
+ }
if ( dir.getName().toLowerCase().contains("eclipse") ) {
if ( new File(dir, "Eclipse.app").exists() ) eclipses.add(dir.toString());
}
diff --git a/src/lombok/installer/EclipseLocation.java b/src/lombok/installer/EclipseLocation.java
index 400b5606..66bba5b8 100644
--- a/src/lombok/installer/EclipseLocation.java
+++ b/src/lombok/installer/EclipseLocation.java
@@ -1,3 +1,24 @@
+/*
+ * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
package lombok.installer;
import java.io.BufferedReader;
@@ -7,6 +28,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.jar.JarFile;
@@ -17,6 +39,11 @@ import java.util.zip.ZipEntry;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
+/**
+ * Represents an eclipse installation.
+ * An instance can figure out if an eclipse installation has been lombok-ified, and can
+ * install and uninstall lombok from the eclipse installation.
+ */
final class EclipseLocation {
private static final String OS_NEWLINE;
@@ -30,8 +57,14 @@ final class EclipseLocation {
private final File path;
private volatile boolean hasLombok;
+
+ /** Toggling the 'selected' checkbox in the GUI is tracked via this boolean */
boolean selected = true;
+ /**
+ * Thrown when creating a new EclipseLocation with a path object that doesn't, in fact,
+ * point at an eclipse installation.
+ */
final class NotAnEclipseException extends Exception {
private static final long serialVersionUID = 1L;
@@ -39,11 +72,19 @@ final class EclipseLocation {
super(message, cause);
}
- public void showDialog(JFrame appWindow) {
+ /**
+ * Renders a message dialog with information about what went wrong.
+ */
+ void showDialog(JFrame appWindow) {
JOptionPane.showMessageDialog(appWindow, getMessage(), "Cannot configure eclipse installation", JOptionPane.WARNING_MESSAGE);
}
}
+ /**
+ * Create a new EclipseLocation by pointing at either the directory contain the eclipse executable, or the executable itself.
+ *
+ * @throws NotAnEclipseException If this isn't an eclipse executable or a directory with an eclipse executable.
+ */
EclipseLocation(String path) throws NotAnEclipseException {
if ( path == null ) throw new NullPointerException("path");
File p = new File(path);
@@ -59,6 +100,10 @@ final class EclipseLocation {
}
}
+ if ( !p.exists() || !p.getName().equalsIgnoreCase(execName) ) {
+ throw new NotAnEclipseException("This path does not appear to contain an eclipse installation: " + p, null);
+ }
+
this.path = p;
try {
this.hasLombok = checkForLombok();
@@ -69,23 +114,35 @@ final class EclipseLocation {
}
}
- public int hashCode() {
+ @Override public int hashCode() {
return path.hashCode();
}
- public boolean equals(Object o) {
+ @Override public boolean equals(Object o) {
if ( !(o instanceof EclipseLocation) ) return false;
return ((EclipseLocation)o).path.equals(path);
}
- public String getPath() {
+ /**
+ * Returns the absolute path to the eclipse executable.
+ *
+ * Executables: "eclipse.exe" (Windows), "Eclipse.app" (Mac OS X), "eclipse" (Linux and other unixes).
+ */
+ String getPath() {
return path.getAbsolutePath();
}
- public boolean hasLombok() {
+ /**
+ * @return true if the eclipse installation has been instrumented with lombok.
+ */
+ boolean hasLombok() {
return hasLombok;
}
+ /**
+ * Returns the various directories that can contain the 'eclipse.ini' file.
+ * Returns multiple directories because there are a few different ways eclipse is packaged.
+ */
private List<File> getTargetDirs() {
return Arrays.asList(path.getParentFile(), new File(new File(path, "Contents"), "MacOS"));
}
@@ -121,7 +178,8 @@ final class EclipseLocation {
}
}
- public class UninstallException extends Exception {
+ /** Thrown when uninstalling lombok fails. */
+ class UninstallException extends Exception {
private static final long serialVersionUID = 1L;
public UninstallException(String message, Throwable cause) {
@@ -129,7 +187,15 @@ final class EclipseLocation {
}
}
- public void uninstall() throws UninstallException {
+ /**
+ * Uninstalls lombok from this location.
+ * It's a no-op if lombok wasn't there in the first place,
+ * and it will remove a half-succeeded lombok installation as well.
+ *
+ * @throws UninstallException If there's an obvious I/O problem that is preventing installation.
+ * bugs in the uninstall code will probably throw other exceptions; this is intentional.
+ */
+ void uninstall() throws UninstallException {
for ( File dir : getTargetDirs() ) {
File lombokJar = new File(dir, "lombok.jar");
if ( lombokJar.exists() ) {
@@ -194,7 +260,8 @@ final class EclipseLocation {
}
}
- public class InstallException extends Exception {
+ /** Thrown when installing lombok fails. */
+ class InstallException extends Exception {
private static final long serialVersionUID = 1L;
public InstallException(String message, Throwable cause) {
@@ -202,18 +269,31 @@ final class EclipseLocation {
}
}
- public void install() throws InstallException {
+ /**
+ * Install lombok into the eclipse at this location.
+ * If lombok is already there, it is overwritten neatly (upgrade mode).
+ *
+ * @throws InstallException If there's an obvious I/O problem that is preventing installation.
+ * bugs in the install code will probably throw other exceptions; this is intentional.
+ */
+ void install() throws InstallException {
+ List<File> failedDirs = new ArrayList<File>();
+
+ boolean installSucceeded = false;
for ( File dir : getTargetDirs() ) {
File iniFile = new File(dir, "eclipse.ini");
StringBuilder newContents = new StringBuilder();
- if ( iniFile.exists() ) {
+ if ( !iniFile.exists() ) failedDirs.add(dir);
+ else {
+ //If 'installSucceeded' is true here, something very weird is going on, but instrumenting all of them
+ //is no less bad than aborting, and this situation should be rare to the point of non-existence.
+
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);
@@ -297,7 +377,6 @@ final class EclipseLocation {
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);
@@ -309,5 +388,18 @@ final class EclipseLocation {
}
}
}
+
+ if ( !installSucceeded ) {
+ throw new InstallException("I can't find the eclipse.ini file. Is this a real eclipse installation?", null);
+ }
+
+ for ( File dir : failedDirs ) {
+ //If we're updating the old installation might have worked by putting the lombok jars in a different place.
+ //We'll delete these old files.
+ try {
+ new File(dir, "lombok.jar").delete();
+ new File(dir, "lombok.eclipse.agent.jar").delete();
+ } catch ( Throwable ignore ) {}
+ }
}
}
diff --git a/src/lombok/installer/InstallerWindow.java b/src/lombok/installer/Installer.java
index a0911c26..5d644868 100644
--- a/src/lombok/installer/InstallerWindow.java
+++ b/src/lombok/installer/Installer.java
@@ -1,3 +1,24 @@
+/*
+ * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
package lombok.installer;
import java.awt.Color;
@@ -5,6 +26,7 @@ import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
+import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
@@ -16,6 +38,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.TextAttribute;
import java.io.File;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
@@ -37,14 +60,22 @@ import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;
import lombok.core.Version;
+import lombok.installer.EclipseFinder.OS;
import lombok.installer.EclipseLocation.InstallException;
import lombok.installer.EclipseLocation.NotAnEclipseException;
import lombok.installer.EclipseLocation.UninstallException;
-public class InstallerWindow {
+/**
+ * The lombok installer proper.
+ * Uses swing to show a simple GUI that can add and remove the java agent to eclipse installations.
+ * Also offers info on what this installer does in case people want to instrument their eclipse manually,
+ * and looks in some common places on Mac OS X and Windows.
+ */
+public class Installer {
private static final URI ABOUT_LOMBOK_URL = URI.create("http://projectlombok.org");
private JFrame appWindow;
@@ -57,15 +88,26 @@ public class InstallerWindow {
private Component howIWorkArea;
private Box uninstallBox;
-
private List<EclipseLocation> toUninstall;
+ private JHyperLink uninstallButton;
+ private JButton installButton;
+
public static void main(String[] args) {
+ if ( EclipseFinder.getOS() == OS.MAC_OS_X ) {
+ System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Lombok Installer");
+ System.setProperty("com.apple.macos.use-file-dialog-packages", "true");
+ }
+
try {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
- new InstallerWindow().show();
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch ( Exception ignore ) {}
+
+ new Installer().show();
} catch ( HeadlessException e ) {
printHeadlessInfo();
}
@@ -76,6 +118,11 @@ public class InstallerWindow {
}
}
+ /**
+ * If run in headless mode, the installer can't show its fancy GUI. There's little point in running
+ * the installer without a GUI environment, as eclipse doesn't run in headless mode either, so
+ * we'll make do with showing some basic info on Lombok as well as instructions for using lombok with javac.
+ */
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," +
@@ -87,7 +134,11 @@ public class InstallerWindow {
" java -cp lombok.jar MyCode.java", Version.getVersion(), ABOUT_LOMBOK_URL);
}
- public InstallerWindow() {
+ /**
+ * Creates a new installer that starts out invisible.
+ * Call the {@see #show()} method on a freshly created installer to render it.
+ */
+ public Installer() {
appWindow = new JFrame(String.format("Project Lombok v%s - Installer", Version.getVersion()));
appWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
@@ -111,6 +162,7 @@ public class InstallerWindow {
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
JOptionPane.showMessageDialog(appWindow, "There was a problem during the installation process:\n" + t, "Uh Oh!", JOptionPane.ERROR_MESSAGE);
+ t.printStackTrace();
System.exit(1);
}
});
@@ -250,7 +302,7 @@ public class InstallerWindow {
constraints.gridy = 2;
loadingExpl = Box.createHorizontalBox();
- loadingExpl.add(new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/loading.gif"))));
+ loadingExpl.add(new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/loading.gif"))));
loadingExpl.add(new JLabel(ECLIPSE_LOADING_EXPLANATION));
container.add(loadingExpl, constraints);
@@ -270,10 +322,12 @@ public class InstallerWindow {
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);
+ if ( eclipses != null ) {
+ for ( String eclipse : eclipses ) try {
+ locations.add(new EclipseLocation(eclipse));
+ } catch ( NotAnEclipseException e ) {
+ problems.add(e);
+ }
}
SwingUtilities.invokeLater(new Runnable() {
@@ -291,6 +345,13 @@ public class InstallerWindow {
}
loadingExpl.setVisible(false);
+
+ if ( eclipses == null ) {
+ JOptionPane.showMessageDialog(appWindow,
+ "I don't know how to automatically find eclipse installations on this platform.\n" +
+ "Please use the 'Specify Eclipse Location...' button to manually point out the\n" +
+ "location of your eclipse installation to me. Thanks!", "Can't find eclipse", JOptionPane.INFORMATION_MESSAGE);
+ }
}
});
} catch ( Throwable t ) {
@@ -306,38 +367,59 @@ public class InstallerWindow {
buttonBar.add(specifyEclipseLocationButton);
specifyEclipseLocationButton.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent event) {
- JFileChooser chooser = new JFileChooser();
+ final String name = EclipseFinder.getEclipseExecutableName();
+ String file = null;
- 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;
+ if ( EclipseFinder.getOS() == OS.MAC_OS_X ) {
+ FileDialog chooser = new FileDialog(appWindow);
+ chooser.setMode(FileDialog.LOAD);
+ chooser.setFilenameFilter(new FilenameFilter() {
+ @Override public boolean accept(File dir, String name) {
+ if ( name.equalsIgnoreCase(name) ) return true;
+ if ( new File(dir, name).isDirectory() ) return true;
+
+ return false;
+ }
+ });
+
+ chooser.setVisible(true);
+ file = new File(chooser.getDirectory(), chooser.getFile()).getAbsolutePath();
+ } else {
+ JFileChooser chooser = new JFileChooser();
+
+ chooser.setAcceptAllFileFilterUsed(false);
+ chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ chooser.setFileFilter(new FileFilter() {
+ @Override public boolean accept(File f) {
+ if ( f.getName().equalsIgnoreCase(name) ) return true;
+ if ( f.isDirectory() ) return true;
+
+ return false;
+ }
- return false;
- }
+ @Override public String getDescription() {
+ return "Eclipse Installation";
+ }
+ });
- @Override public String getDescription() {
- return "Eclipse Installation";
+ switch ( chooser.showDialog(appWindow, "Select") ) {
+ case JFileChooser.APPROVE_OPTION:
+ file = chooser.getSelectedFile().getAbsolutePath();
}
- });
+ }
- switch ( chooser.showDialog(appWindow, "Select") ) {
- case JFileChooser.APPROVE_OPTION:
+ if ( file != null ) {
try {
- try {
- eclipsesList.addEclipse(new EclipseLocation(chooser.getSelectedFile().getAbsolutePath()));
- } catch ( NotAnEclipseException e ) {
- e.showDialog(appWindow);
- }
+ eclipsesList.addEclipse(new EclipseLocation(file));
+ } catch ( NotAnEclipseException e ) {
+ e.showDialog(appWindow);
} catch ( Throwable t ) {
handleException(t);
}
}
}
});
+
buttonBar.add(Box.createHorizontalGlue());
installButton = new JButton("Install / Update");
buttonBar.add(installButton);
@@ -420,7 +502,7 @@ public class InstallerWindow {
JPanel spinner = new JPanel();
spinner.setOpaque(true);
spinner.setLayout(new FlowLayout());
- spinner.add(new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/loading.gif"))));
+ spinner.add(new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/loading.gif"))));
appWindow.setContentPane(spinner);
final AtomicReference<Boolean> success = new AtomicReference<Boolean>(true);
@@ -461,7 +543,7 @@ public class InstallerWindow {
JPanel spinner = new JPanel();
spinner.setOpaque(true);
spinner.setLayout(new FlowLayout());
- spinner.add(new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/loading.gif"))));
+ spinner.add(new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/loading.gif"))));
appWindow.setContentPane(spinner);
@@ -562,7 +644,7 @@ public class InstallerWindow {
});
if ( location.hasLombok() ) {
- box.add(new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/lombokIcon.png"))));
+ box.add(new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/lombokIcon.png"))));
}
box.add(Box.createHorizontalGlue());
locations.add(location);
@@ -593,8 +675,8 @@ public class InstallerWindow {
};
private void buildChrome(Container appWindowContainer) {
- JLabel leftGraphic = new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/lombok.png")));
- JLabel topGraphic = new JLabel(new ImageIcon(InstallerWindow.class.getResource("/lombok/installer/lombokText.png")));
+ JLabel leftGraphic = new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/lombok.png")));
+ JLabel topGraphic = new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/lombokText.png")));
GridBagConstraints constraints = new GridBagConstraints();
@@ -656,20 +738,24 @@ public class InstallerWindow {
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);
} catch ( Exception e ) {
- String os = System.getProperty("os.name").toLowerCase();
Runtime rt = Runtime.getRuntime();
try {
- if ( os.indexOf( "win" ) > -1 ) {
+ switch ( EclipseFinder.getOS() ) {
+ case WINDOWS:
String[] cmd = new String[4];
cmd[0] = "cmd.exe";
cmd[1] = "/C";
cmd[2] = "start";
cmd[3] = ABOUT_LOMBOK_URL.toString();
rt.exec(cmd);
- } else if ( os.indexOf( "mac" ) >= 0 ) {
+ break;
+ case MAC_OS_X:
rt.exec( "open " + ABOUT_LOMBOK_URL.toString());
- } else {
+ break;
+ default:
+ case UNIX:
rt.exec("firefox " + ABOUT_LOMBOK_URL.toString());
+ break;
}
} catch ( Exception e2 ) {
JOptionPane.showMessageDialog(appWindow,
@@ -690,8 +776,18 @@ public class InstallerWindow {
appWindow.add(buttonBar, constraints);
}
+ /**
+ * Makes the installer window visible.
+ */
public void show() {
appWindow.setVisible(true);
+ if ( EclipseFinder.getOS() == OS.MAC_OS_X ) {
+ try {
+ AppleNativeLook.go();
+ } catch ( Throwable ignore ) {
+ //We're just prettying up the app. If it fails, meh.
+ }
+ }
}
private static final String ECLIPSE_TITLE =
@@ -733,8 +829,4 @@ public class InstallerWindow {
"<br>" +
"That's all there is to it. Note that on Mac OS X, eclipse.ini is hidden in<br>" +
"<code>Eclipse.app/Contents/MacOS</code> so that's where I place the jar files.</html>";
-
- private JHyperLink uninstallButton;
-
- private JButton installButton;
}
diff --git a/src/lombok/installer/lombok.svg b/src/lombok/installer/lombok.svg
index b28e1cbe..0d561aea 100644
--- a/src/lombok/installer/lombok.svg
+++ b/src/lombok/installer/lombok.svg
@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+This vector art image is part of the public domain. It has been updated from:
+http://www.clker.com/clipart-pepper.html
+-->
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
diff --git a/src/lombok/installer/package-info.java b/src/lombok/installer/package-info.java
new file mode 100644
index 00000000..a40330e5
--- /dev/null
+++ b/src/lombok/installer/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2009 Reinier Zwitserloot and Roel Spilker.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * This package contains the lombok installer. It explains to any user that double-clicks the lombok.jar what
+ * lombok is about, and has the ability to instrument (or remove existing Lombok instrumentation) from any
+ * eclipse installation. This package also contains the graphics uses in the installer in SVG format.
+ */
+package lombok.installer;