diff options
author | Reinier Zwitserloot <reinier@tipit.to> | 2009-11-25 07:32:49 +0100 |
---|---|---|
committer | Reinier Zwitserloot <reinier@tipit.to> | 2009-11-25 07:32:49 +0100 |
commit | 1a0e611a9c5e1ee518670647ce1a44beae559b44 (patch) | |
tree | e5ef8f671bc6688f486e874d4e2e1a7813e4f0b2 /src/installer/lombok | |
parent | 7fd947ea40c25dad9ee543ebc4b92de9a2e05efc (diff) | |
download | lombok-1a0e611a9c5e1ee518670647ce1a44beae559b44.tar.gz lombok-1a0e611a9c5e1ee518670647ce1a44beae559b44.tar.bz2 lombok-1a0e611a9c5e1ee518670647ce1a44beae559b44.zip |
Refactored the source folders.
Diffstat (limited to 'src/installer/lombok')
-rw-r--r-- | src/installer/lombok/installer/AppleNativeLook.java | 43 | ||||
-rw-r--r-- | src/installer/lombok/installer/EclipseFinder.java | 325 | ||||
-rw-r--r-- | src/installer/lombok/installer/EclipseLocation.java | 474 | ||||
-rw-r--r-- | src/installer/lombok/installer/Installer.java | 895 | ||||
-rw-r--r-- | src/installer/lombok/installer/WindowsDriveInfo-i386.dll | bin | 0 -> 14472 bytes | |||
-rw-r--r-- | src/installer/lombok/installer/WindowsDriveInfo-x86_64.dll | bin | 0 -> 66806 bytes | |||
-rw-r--r-- | src/installer/lombok/installer/WindowsDriveInfo.java | 127 | ||||
-rw-r--r-- | src/installer/lombok/installer/loading.gif | bin | 0 -> 2248 bytes | |||
-rw-r--r-- | src/installer/lombok/installer/lombok.png | bin | 0 -> 24994 bytes | |||
-rw-r--r-- | src/installer/lombok/installer/lombok.svg | 181 | ||||
-rw-r--r-- | src/installer/lombok/installer/lombokIcon.png | bin | 0 -> 788 bytes | |||
-rw-r--r-- | src/installer/lombok/installer/lombokText.png | bin | 0 -> 3055 bytes | |||
-rw-r--r-- | src/installer/lombok/installer/lombokText.svg | 67 | ||||
-rw-r--r-- | src/installer/lombok/installer/package-info.java | 28 |
14 files changed, 2140 insertions, 0 deletions
diff --git a/src/installer/lombok/installer/AppleNativeLook.java b/src/installer/lombok/installer/AppleNativeLook.java new file mode 100644 index 00000000..6e64032e --- /dev/null +++ b/src/installer/lombok/installer/AppleNativeLook.java @@ -0,0 +1,43 @@ +/* + * 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.Image; +import java.awt.image.BufferedImage; + +import javax.imageio.ImageIO; + +/** + * 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 Exception { + Class<?> appClass = Class.forName("com.apple.eawt.Application"); + Object app = appClass.getMethod("getApplication").invoke(null); + appClass.getMethod("removeAboutMenuItem").invoke(app); + appClass.getMethod("removePreferencesMenuItem").invoke(app); + + BufferedImage image = ImageIO.read(AppleNativeLook.class.getResource("lombokIcon.png")); + appClass.getMethod("setDockIconImage", Image.class).invoke(app, image); + } +} diff --git a/src/installer/lombok/installer/EclipseFinder.java b/src/installer/lombok/installer/EclipseFinder.java new file mode 100644 index 00000000..8e45852c --- /dev/null +++ b/src/installer/lombok/installer/EclipseFinder.java @@ -0,0 +1,325 @@ +/* + * 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; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import lombok.Lombok; +import lombok.core.Version; +import lombok.installer.EclipseLocation.NotAnEclipseException; + +/** 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$"); + 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); + } + } + + private static final AtomicBoolean windowsDriveInfoLibLoaded = new AtomicBoolean(false); + private static void loadWindowsDriveInfoLib() throws IOException { + if (!windowsDriveInfoLibLoaded.compareAndSet(false, true)) return; + + final String prefix = "lombok-" + Version.getVersion() + "-"; + + File temp = File.createTempFile("lombok", ".mark"); + File dll1 = new File(temp.getParentFile(), prefix + "WindowsDriveInfo-i386.dll"); + File dll2 = new File(temp.getParentFile(), prefix + "WindowsDriveInfo-x86_64.dll"); + temp.delete(); + dll1.deleteOnExit(); + dll2.deleteOnExit(); + try { + if (unpackDLL("WindowsDriveInfo-i386.dll", dll1)) { + System.load(dll1.getAbsolutePath()); + return; + } + } catch (Throwable ignore) {} + + try { + if (unpackDLL("WindowsDriveInfo-x86_64.dll", dll2)) { + System.load(dll2.getAbsolutePath()); + } + } catch (Throwable ignore) {} + } + + private static boolean unpackDLL(String dllName, File target) throws IOException { + InputStream in = EclipseFinder.class.getResourceAsStream(dllName); + try { + try { + FileOutputStream out = new FileOutputStream(target); + try { + byte[] b = new byte[32000]; + while (true) { + int r = in.read(b); + if (r == -1) break; + out.write(b, 0, r); + } + } finally { + out.close(); + } + } catch (IOException e) { + //Fall through - if there is a file named lombok-WindowsDriveInfo-arch.dll, we'll try it. + return target.exists() && target.canRead(); + } + } finally { + in.close(); + } + + return true; + } + + /** + * Returns all drive letters on windows, regardless of what kind of drive is represented. + * + * @return A List of drive letters, such as ["A", "C", "D", "X"]. + */ + static List<String> getDrivesOnWindows() throws Throwable { + loadWindowsDriveInfoLib(); + + List<String> drives = new ArrayList<String>(); + + WindowsDriveInfo info = new WindowsDriveInfo(); + for (String drive : info.getLogicalDrives()) { + if (info.isFixedDisk(drive)) drives.add(drive); + } + + return drives; + } + + /** + * Returns a list of paths of Eclipse installations. + * Eclipse installations are found by checking for the existence of 'eclipse.exe' in the following locations: + * <ul> + * <li>X:\*Program Files*\*Eclipse*</li> + * <li>X:\*Eclipse*</li> + * </ul> + * + * Where 'X' is tried for all local disk drives, unless there's a problem calling fsutil, in which case only + * C: is tried. + */ + private static void findEclipseOnWindows(List<EclipseLocation> locations, List<NotAnEclipseException> problems) { + List<String> driveLetters = asList("C"); + try { + driveLetters = getDrivesOnWindows(); + } catch (Throwable ignore) { + ignore.printStackTrace(); + } + + //Various try/catch/ignore statements are in this for loop. Weird conditions on the disk can cause exceptions, + //such as an unformatted drive causing a NullPointerException on listFiles. Best action is almost invariably to just + //continue onwards. + for (String letter : driveLetters) { + try { + File f = new File(letter + ":\\"); + for (File dir : f.listFiles()) { + if (!dir.isDirectory()) continue; + try { + if (dir.getName().toLowerCase().contains("eclipse")) { + String eclipseLocation = findEclipseOnWindows1(dir); + if (eclipseLocation != null) { + try { + locations.add(EclipseLocation.create(eclipseLocation)); + } catch (NotAnEclipseException e) { + problems.add(e); + } + } + } + } catch (Exception ignore) {} + + try { + 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) { + try { + locations.add(EclipseLocation.create(eclipseLocation)); + } catch (NotAnEclipseException e) { + problems.add(e); + } + } + } + } + } + } catch (Exception ignore) {} + } + } catch (Exception ignore) {} + } + } + + /** 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.getAbsolutePath(); + return null; + } + + /** + * Calls the OS-dependent 'find Eclipse' routine. If the local OS doesn't have a routine written for it, + * null is returned. + * + * @param locations + * List of valid eclipse locations - provide an empty list; this + * method will fill it. + * @param problems + * List of eclipse locations that seem to contain half-baked + * eclipses that can't be installed. Provide an empty list; this + * method will fill it. + */ + static void findEclipses(List<EclipseLocation> locations, List<NotAnEclipseException> problems) { + switch (getOS()) { + case WINDOWS: + findEclipseOnWindows(locations, problems); + break; + case MAC_OS_X: + findEclipseOnMac(locations, problems); + break; + default: + case UNIX: + findEclipseOnUnix(locations, problems); + break; + } + } + + static enum OS { + MAC_OS_X, WINDOWS, UNIX; + } + + static OS getOS() { + String prop = System.getProperty("os.name", "").toLowerCase(); + if (prop.matches("^.*\\bmac\\b.*$")) return OS.MAC_OS_X; + if (prop.matches("^.*\\bdarwin\\b.*$")) return OS.MAC_OS_X; + if (prop.matches("^.*\\bwin(dows)\\b.*$")) return OS.WINDOWS; + + return OS.UNIX; + } + + /** + * 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 a couple of likely locations on linux. */ + private static void findEclipseOnUnix(List<EclipseLocation> locations, List<NotAnEclipseException> problems) { + List<String> guesses = new ArrayList<String>(); + + File d; + + d = new File("/usr/bin/eclipse"); + if (d.exists()) guesses.add(d.getPath()); + d = new File("/usr/local/bin/eclipse"); + if (d.exists()) guesses.add(d.getPath()); + d = new File(System.getProperty("user.home", "."), "bin/eclipse"); + if (d.exists()) guesses.add(d.getPath()); + + findEclipseInSubDir("/usr/local/share", guesses); + findEclipseInSubDir("/usr/local", guesses); + findEclipseInSubDir("/usr/share", guesses); + findEclipseInSubDir(System.getProperty("user.home", "."), guesses); + + for (String guess : guesses) { + try { + locations.add(EclipseLocation.create(guess)); + } catch (NotAnEclipseException e) { + problems.add(e); + } + } + } + + private static void findEclipseInSubDir(String dir, List<String> guesses) { + File d = new File(dir); + if (!d.isDirectory()) return; + for (File f : d.listFiles()) { + if (f.isDirectory() && f.getName().toLowerCase().contains("eclipse")) { + File possible = new File(f, "eclipse"); + if (possible.exists()) guesses.add(possible.getAbsolutePath()); + } + } + } + + /** + * Scans /Applications for any folder named 'Eclipse' + */ + private static void findEclipseOnMac(List<EclipseLocation> locations, List<NotAnEclipseException> problems) { + 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. + try { + locations.add(EclipseLocation.create("/Applications")); + } catch (NotAnEclipseException e) { + problems.add(e); + } + } + if (dir.getName().toLowerCase().contains("eclipse")) { + if (new File(dir, "Eclipse.app").exists()) { + try { + locations.add(EclipseLocation.create(dir.toString())); + } catch (NotAnEclipseException e) { + problems.add(e); + } + } + } + } + } +} diff --git a/src/installer/lombok/installer/EclipseLocation.java b/src/installer/lombok/installer/EclipseLocation.java new file mode 100644 index 00000000..c43c5042 --- /dev/null +++ b/src/installer/lombok/installer/EclipseLocation.java @@ -0,0 +1,474 @@ +/* + * 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; +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.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +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; + + 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 String name; + private final File eclipseIniPath; + 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. + */ + static final class NotAnEclipseException extends Exception { + private static final long serialVersionUID = 1L; + + public NotAnEclipseException(String message, Throwable cause) { + super(message, cause); + } + + /** + * 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); + } + } + + private EclipseLocation(String nameOfLocation, File pathToEclipseIni) throws NotAnEclipseException { + this.name = nameOfLocation; + this.eclipseIniPath = pathToEclipseIni; + try { + this.hasLombok = checkForLombok(eclipseIniPath); + } catch (IOException e) { + throw new NotAnEclipseException( + "I can't read the configuration file of the Eclipse installed at " + name + "\n" + + "You may need to run this installer with root privileges if you want to modify that Eclipse.", e); + } + } + + private static final List<String> eclipseExecutableNames = Collections.unmodifiableList(Arrays.asList( + "eclipse.app", "eclipse.exe", "eclipse")); + + /** + * Create a new EclipseLocation by pointing at either the directory contain the Eclipse executable, or the executable itself, + * or an eclipse.ini file. + * + * @throws NotAnEclipseException + * If this isn't an Eclipse executable or a directory with an + * Eclipse executable. + */ + public static EclipseLocation create(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); + if (p.isDirectory()) { + for (String possibleExeName : eclipseExecutableNames) { + File f = new File(p, possibleExeName); + if (f.exists()) return findEclipseIniFromExe(f, 0); + } + + File f = new File(p, "eclipse.ini"); + if (f.exists()) return new EclipseLocation(getFilePath(p), f); + } + + if (p.isFile()) { + if (p.getName().equalsIgnoreCase("eclipse.ini")) { + return new EclipseLocation(getFilePath(p.getParentFile()), p); + } + + if (eclipseExecutableNames.contains(p.getName().toLowerCase())) { + return findEclipseIniFromExe(p, 0); + } + } + + throw new NotAnEclipseException("This path does not appear to contain an Eclipse installation: " + p, null); + } + + private static EclipseLocation findEclipseIniFromExe(File exePath, int loopCounter) throws NotAnEclipseException { + /* Try looking for eclipse.ini as sibling to the executable */ { + File ini = new File(exePath.getParentFile(), "eclipse.ini"); + if (ini.isFile()) return new EclipseLocation(getFilePath(exePath), ini); + } + + /* Try looking for Eclipse/app/Contents/MacOS/eclipse.ini as sibling to executable; this works on Mac OS X. */ { + File ini = new File(exePath.getParentFile(), "Eclipse.app/Contents/MacOS/eclipse.ini"); + if (ini.isFile()) return new EclipseLocation(getFilePath(exePath), ini); + } + + /* If executable is a soft link, follow it and retry. */ { + if (loopCounter < 50) { + try { + String oPath = exePath.getAbsolutePath(); + String nPath = exePath.getCanonicalPath(); + if (!oPath.equals(nPath)) try { + return findEclipseIniFromExe(new File(nPath), loopCounter + 1); + } catch (NotAnEclipseException ignore) { + // Unlinking didn't help find an eclipse, so continue. + } + } catch (IOException ignore) { /* okay, that didn't work, assume it isn't a soft link then. */ } + } + } + + /* If executable is a linux LSB-style path, then look in the usual places that package managers like apt-get use.*/ { + String path = exePath.getAbsolutePath(); + try { + path = exePath.getCanonicalPath(); + } catch (IOException ignore) { /* We'll stick with getAbsolutePath()'s result then. */ } + + if (path.equals("/usr/bin/eclipse") || path.equals("/bin/eclipse") || path.equals("/usr/local/bin/eclipse")) { + File ini = new File("/usr/lib/eclipse/eclipse.ini"); + if (ini.isFile()) return new EclipseLocation(path, ini); + ini = new File("/usr/local/lib/eclipse/eclipse.ini"); + if (ini.isFile()) return new EclipseLocation(path, ini); + ini = new File("/usr/local/etc/eclipse/eclipse.ini"); + if (ini.isFile()) return new EclipseLocation(path, ini); + ini = new File("/etc/eclipse.ini"); + if (ini.isFile()) return new EclipseLocation(path, ini); + } + } + + /* If we get this far, we lose. */ + throw new NotAnEclipseException("This path does not appear to contain an eclipse installation: " + exePath, null); + } + + public static String getFilePath(File p) { + try { + return p.getCanonicalPath(); + } catch (IOException e) { + String x = p.getAbsolutePath(); + return x == null ? p.getPath() : x; + } + } + + @Override public int hashCode() { + return eclipseIniPath.hashCode(); + } + + @Override public boolean equals(Object o) { + if (!(o instanceof EclipseLocation)) return false; + return ((EclipseLocation)o).eclipseIniPath.equals(eclipseIniPath); + } + + /** + * Returns the name of this location; generally the path to the eclipse executable. + * + * Executables: "eclipse.exe" (Windows), "Eclipse.app" (Mac OS X), "eclipse" (Linux and other unixes). + */ + String getName() { + return name; + } + + /** + * @return true if the Eclipse installation has been instrumented with lombok. + */ + boolean hasLombok() { + return hasLombok; + } + + 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 checkForLombok(File iniFile) throws IOException { + 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(); + } + } + + /** Thrown when uninstalling lombok fails. */ + static class UninstallException extends Exception { + private static final long serialVersionUID = 1L; + + public UninstallException(String message, Throwable cause) { + super(message, cause); + } + } + + /** Returns directories that may contain lombok.jar files that need to be deleted. */ + private List<File> getUninstallDirs() { + List<File> result = new ArrayList<File>(); + File x = new File(name); + if (!x.isDirectory()) x = x.getParentFile(); + if (x.isDirectory()) result.add(x); + result.add(eclipseIniPath.getParentFile()); + return result; + } + + /** + * 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 : getUninstallDirs()) { + File lombokJar = new File(dir, "lombok.jar"); + if (lombokJar.exists()) { + if (!lombokJar.delete()) throw new UninstallException( + "Can't delete " + lombokJar.getAbsolutePath() + generateWriteErrorMessage(), null); + } + + /* legacy code - lombok at one point used to have a separate jar for the eclipse agent. + * Leave this code in to delete it for those upgrading from an old version. */ { + File agentJar = new File(dir, "lombok.eclipse.agent.jar"); + if (agentJar.exists()) { + if (!agentJar.delete()) throw new UninstallException( + "Can't delete " + agentJar.getAbsolutePath() + generateWriteErrorMessage(), null); + } + } + } + + StringBuilder newContents = new StringBuilder(); + if (eclipseIniPath.exists()) { + try { + FileInputStream fis = new FileInputStream(eclipseIniPath); + 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; + /* legacy code -see previous comment that starts with 'legacy' */ { + 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(eclipseIniPath); + try { + fos.write(newContents.toString().getBytes()); + } finally { + fos.close(); + } + } catch (IOException e) { + throw new UninstallException("Cannot uninstall lombok from " + name + generateWriteErrorMessage(), e); + } + } + } + + /** Thrown when installing lombok fails. */ + static class InstallException extends Exception { + private static final long serialVersionUID = 1L; + + public InstallException(String message, Throwable cause) { + super(message, cause); + } + } + + private static String generateWriteErrorMessage() { + String osSpecificError; + + switch (EclipseFinder.getOS()) { + default: + case MAC_OS_X: + case UNIX: + osSpecificError = ":\nStart terminal, go to the directory with lombok.jar, and run: sudo java -jar lombok.jar"; + break; + case WINDOWS: + osSpecificError = ":\nStart a new cmd (dos box) with admin privileges, go to the directory with lombok.jar, and run: java -jar lombok.jar"; + break; + } + + return ", probably because this installer does not have the access rights.\n" + + "Try re-running the installer with administrative privileges" + osSpecificError; + } + + /** + * 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 { + // For whatever reason, relative paths in your eclipse.ini file don't work on linux, but only for -javaagent. + // If someone knows how to fix this, please do so, as this current hack solution (putting the absolute path + // to the jar files in your eclipse.ini) means you can't move your eclipse around on linux without lombok + // breaking it. NB: rerunning lombok.jar installer and hitting 'update' will fix it if you do that. + boolean fullPathRequired = EclipseFinder.getOS() == EclipseFinder.OS.UNIX; + + boolean installSucceeded = false; + StringBuilder newContents = new StringBuilder(); + //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(eclipseIniPath.getParentFile(), "lombok.jar"); + + File ourJar = EclipseFinder.findOurJar(); + byte[] b = new byte[524288]; + boolean readSucceeded = true; + try { + FileOutputStream out = new FileOutputStream(lombokJar); + try { + readSucceeded = false; + InputStream in = new FileInputStream(ourJar); + try { + while (true) { + int r = in.read(b); + if (r == -1) break; + if (r > 0) readSucceeded = true; + out.write(b, 0, r); + } + } finally { + in.close(); + } + } finally { + out.close(); + } + } catch (IOException e) { + try { + lombokJar.delete(); + } catch (Throwable ignore) { /* Nothing we can do about that. */ } + if (!readSucceeded) throw new InstallException( + "I can't read my own jar file. I think you've found a bug in this installer!\nI suggest you restart it " + + "and use the 'what do I do' link, to manually install lombok. Also, tell us about this at:\n" + + "http://groups.google.com/group/project-lombok - Thanks!", e); + throw new InstallException("I can't write to your Eclipse directory at " + name + generateWriteErrorMessage(), e); + } + + /* legacy - delete lombok.eclipse.agent.jar if its there, which lombok no longer uses. */ { + new File(lombokJar.getParentFile(), "lombok.eclipse.agent.jar").delete(); + } + + try { + FileInputStream fis = new FileInputStream(eclipseIniPath); + 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; + /* legacy code -see previous comment that starts with 'legacy' */ { + 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(); + } + + String fullPathToLombok = fullPathRequired ? (lombokJar.getParentFile().getCanonicalPath() + File.separator) : ""; + + newContents.append(String.format( + "-javaagent:%slombok.jar", fullPathToLombok)).append(OS_NEWLINE); + newContents.append(String.format( + "-Xbootclasspath/a:%slombok.jar", fullPathToLombok)).append(OS_NEWLINE); + + FileOutputStream fos = new FileOutputStream(eclipseIniPath); + try { + fos.write(newContents.toString().getBytes()); + } finally { + fos.close(); + } + installSucceeded = true; + } catch (IOException e) { + throw new InstallException("Cannot install lombok at " + name + generateWriteErrorMessage(), e); + } finally { + if (!installSucceeded) try { + lombokJar.delete(); + } catch (Throwable ignore) {} + } + + if (!installSucceeded) { + throw new InstallException("I can't find the eclipse.ini file. Is this a real Eclipse installation?", null); + } + } +} diff --git a/src/installer/lombok/installer/Installer.java b/src/installer/lombok/installer/Installer.java new file mode 100644 index 00000000..e1da5d31 --- /dev/null +++ b/src/installer/lombok/installer/Installer.java @@ -0,0 +1,895 @@ +/* + * 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; +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; +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Toolkit; +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.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.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; + +/** + * 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; + + private JComponent loadingExpl; + + private Component javacArea; + private Component eclipseArea; + private Component uninstallArea; + private Component howIWorkArea; + + private Box uninstallBox; + private List<EclipseLocation> toUninstall; + + private JHyperLink uninstallButton; + private JLabel uninstallPlaceholder; + private JButton installButton; + + public static void main(String[] args) { + if (args.length > 0 && (args[0].equals("install") || args[0].equals("uninstall"))) { + boolean uninstall = args[0].equals("uninstall"); + if (args.length < 3 || !args[1].equals("eclipse")) { + System.err.printf("Run java -jar lombok.jar %1$s eclipse path/to/eclipse/executable (or 'auto' to %1$s to all auto-discovered eclipse locations)\n", uninstall ? "uninstall" : "install"); + System.exit(1); + } + String path = args[2]; + try { + final List<EclipseLocation> locations = new ArrayList<EclipseLocation>(); + final List<NotAnEclipseException> problems = new ArrayList<NotAnEclipseException>(); + if (path.equals("auto")) { + EclipseFinder.findEclipses(locations, problems); + } else { + locations.add(EclipseLocation.create(path)); + } + int validLocations = locations.size(); + for (EclipseLocation loc : locations) { + try { + if (uninstall) { + loc.uninstall(); + } else { + loc.install(); + } + System.out.printf("Lombok %s %s: %s\n", uninstall ? "uninstalled" : "installed", uninstall ? "from" : "to", loc.getName()); + } catch (InstallException e) { + System.err.printf("Installation at %s failed:\n", loc.getName()); + System.err.println(e.getMessage()); + validLocations--; + } catch (UninstallException e) { + System.err.printf("Uninstall at %s failed:\n", loc.getName()); + System.err.println(e.getMessage()); + validLocations--; + } + } + for (NotAnEclipseException problem : problems) { + System.err.println("WARNING: " + problem.getMessage()); + } + if (validLocations == 0) { + System.err.println("WARNING: Zero valid locations found; so nothing was done."); + } + System.exit(0); + } catch (NotAnEclipseException e) { + System.err.println("Not a valid eclipse location:"); + System.err.println(e.getMessage()); + System.exit(2); + } + } + + if (args.length > 0 && args[0].equals("uninstall")) { + if (args.length < 3 || !args[1].equals("eclipse")) { + System.err.println("Run java -jar lombok.jar uninstall eclipse path/to/eclipse/executable (or 'auto' to uninstall all auto-discovered eclipse locations)"); + System.exit(1); + } + String path = args[2]; + try { + EclipseLocation loc = EclipseLocation.create(path); + loc.uninstall(); + System.out.println("Uninstalled from: " + loc.getName()); + System.exit(0); + } catch (NotAnEclipseException e) { + System.err.println("Not a valid eclipse location:"); + System.err.println(e.getMessage()); + System.exit(2); + } catch (UninstallException e) { + System.err.println("Uninstall failed:"); + System.err.println(e.getMessage()); + System.exit(1); + } + } + + 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 { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception ignore) {} + + new Installer().show(); + } catch (HeadlessException e) { + printHeadlessInfo(); + } + } + }); + } catch (HeadlessException e) { + printHeadlessInfo(); + } + } + + /** + * 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," + + "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\n\n\n" + + "If for whatever reason you can't run the graphical installer but you do want to install lombok into eclipse," + + "start this jar with the following syntax:\n\n" + + " java -jar lombok.jar install eclipse path/to/your/eclipse/executable", Version.getVersion(), ABOUT_LOMBOK_URL); + } + + /** + * Creates a new installer that starts out invisible. + * Call the {@link #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); + appWindow.setResizable(false); + appWindow.setIconImage(Toolkit.getDefaultToolkit().getImage(Installer.class.getResource("lombokIcon.png"))); + + 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() { + @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); + } + }); + } + + 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); + + constraints.gridy = 1; + constraints.insets = new Insets(8, 0, 0, 16); + container.add(new JLabel(String.format(HOW_I_WORK_EXPLANATION, File.pathSeparator)), constraints); + + Box buttonBar = Box.createHorizontalBox(); + JButton backButton = new JButton("Okay - Good to know!"); + buttonBar.add(Box.createHorizontalGlue()); + buttonBar.add(backButton); + + 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); + + 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; + constraints.insets = new Insets(8, 0, 0, 16); + + container.add(new JLabel(JAVAC_TITLE), constraints); + + constraints.gridy = 1; + constraints.weightx = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + container.add(new JLabel(JAVAC_EXPLANATION), constraints); + + JLabel example = new JLabel(JAVAC_EXAMPLE); + + constraints.gridy = 2; + container.add(example, constraints); + return container; + } + + private Component buildEclipseArea() { + JPanel container = new JPanel(); + + container.setLayout(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.WEST; + + constraints.insets = new Insets(8, 0, 0, 16); + container.add(new JLabel(ECLIPSE_TITLE), constraints); + + constraints.gridy = 1; + container.add(new JLabel(ECLIPSE_EXPLANATION), constraints); + + constraints.gridy = 2; + loadingExpl = Box.createHorizontalBox(); + loadingExpl.add(new JLabel(new ImageIcon(Installer.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); + eclipsesListScroll.getViewport().setBackground(Color.WHITE); + container.add(eclipsesListScroll, constraints); + + Thread findEclipsesThread = new Thread() { + @Override public void run() { + try { + final List<EclipseLocation> locations = new ArrayList<EclipseLocation>(); + final List<NotAnEclipseException> problems = new ArrayList<NotAnEclipseException>(); + EclipseFinder.findEclipses(locations, problems); + + 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); + + if (locations.size() + problems.size() == 0) { + 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) { + 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) { + final String exeName = EclipseFinder.getEclipseExecutableName(); + String file = null; + + 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 fileName) { + if (exeName.equalsIgnoreCase(fileName)) return true; + if (new File(dir, fileName).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(exeName)) return true; + if (f.getName().equalsIgnoreCase("eclipse.ini")) 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: + file = chooser.getSelectedFile().getAbsolutePath(); + } + } + + if (file != null) { + try { + eclipsesList.addEclipse(EclipseLocation.create(file)); + } 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; + JHyperLink showMe = new JHyperLink("Show me what this installer will do to my Eclipse installation."); + container.add(showMe, constraints); + showMe.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + showWhatIDo(); + } + }); + + constraints.gridy = 6; + uninstallButton = new JHyperLink("Uninstall lombok from selected Eclipse installations."); + uninstallPlaceholder = new JLabel("<html> </html>"); + 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-enabled.", "No Selection", JOptionPane.WARNING_MESSAGE); + return; + } + + + uninstall(locationsToUninstall); + } + }); + container.add(uninstallButton, constraints); + uninstallPlaceholder.setVisible(false); + container.add(uninstallPlaceholder, constraints); + + + return container; + } + + private void showWhatIDo() { + javacArea.setVisible(false); + eclipseArea.setVisible(false); + howIWorkArea.setVisible(true); + appWindow.pack(); + } + + private void uninstall(List<EclipseLocation> locations) { + javacArea.setVisible(false); + eclipseArea.setVisible(false); + + uninstallBox.removeAll(); + uninstallBox.add(Box.createRigidArea(new Dimension(1, 16))); + for (EclipseLocation location : locations) { + JLabel label = new JLabel(location.getName()); + label.setFont(label.getFont().deriveFont(Font.BOLD)); + uninstallBox.add(label); + } + uninstallBox.add(Box.createRigidArea(new Dimension(1, 16))); + + toUninstall = locations; + uninstallArea.setVisible(true); + appWindow.pack(); + } + + private void install(final List<EclipseLocation> toInstall) { + JPanel spinner = new JPanel(); + spinner.setOpaque(true); + spinner.setLayout(new FlowLayout()); + spinner.add(new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/loading.gif")))); + appWindow.setContentPane(spinner); + + final AtomicReference<Boolean> success = new AtomicReference<Boolean>(true); + + new Thread() { + @Override public void run() { + for (EclipseLocation loc : toInstall) { + try { + loc.install(); + } catch (final InstallException e) { + success.set(false); + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { + JOptionPane.showMessageDialog(appWindow, + e.getMessage(), "Install Problem", JOptionPane.ERROR_MESSAGE); + } + }); + } catch (Exception e2) { + //Shouldn't happen. + throw new RuntimeException(e2); + } + } + } + + if (success.get()) SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { + JOptionPane.showMessageDialog(appWindow, + "<html>Lombok has been installed on the selected Eclipse installations.<br>" + + "Don't forget to add <code>lombok.jar</code> to your projects, and restart your eclipse!<br>" + + "If you start eclipse with a custom -vm parameter, you'll need to add:<br>" + + "<code>-vmargs -Xbootclasspath/a:lombok.jar -javaagent:lombok.jar</code><br>" + + "as parameter as well.</html>", "Install successful", + JOptionPane.INFORMATION_MESSAGE); + appWindow.setVisible(false); + System.exit(0); + } + }); + + if (!success.get()) SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { + System.exit(0); + } + }); + } + }.start(); + } + + private void doUninstall() { + JPanel spinner = new JPanel(); + spinner.setOpaque(true); + spinner.setLayout(new FlowLayout()); + spinner.add(new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/loading.gif")))); + + appWindow.setContentPane(spinner); + + final AtomicReference<Boolean> success = new AtomicReference<Boolean>(true); + new Thread() { + @Override public void run() { + for (EclipseLocation loc : toUninstall) { + try { + loc.uninstall(); + } catch (final UninstallException e) { + success.set(false); + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { + JOptionPane.showMessageDialog(appWindow, + e.getMessage(), "Uninstall Problem", JOptionPane.ERROR_MESSAGE); + } + }); + } catch (Exception e2) { + //Shouldn't happen. + throw new RuntimeException(e2); + } + } + } + + if (success.get()) SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { + JOptionPane.showMessageDialog(appWindow, "Lombok has been removed from the selected Eclipse installations.", "Uninstall successful", JOptionPane.INFORMATION_MESSAGE); + appWindow.setVisible(false); + System.exit(0); + } + }); + } + }.start(); + } + + private EclipsesList eclipsesList = new EclipsesList(); + + private static class JHyperLink extends JButton { + private static final long serialVersionUID = 1L; + + public JHyperLink(String text) { + super(); + setFont(getFont().deriveFont(Collections.singletonMap(TextAttribute.UNDERLINE, 1))); + setText(text); + setBorder(null); + setContentAreaFilled(false); + setForeground(Color.BLUE); + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + setMargin(new Insets(0, 0, 0, 0)); + } + } + + void selectedLomboksChanged(List<EclipseLocation> selectedEclipses) { + boolean uninstallAvailable = false; + boolean installAvailable = false; + for (EclipseLocation loc : selectedEclipses) { + if (loc.hasLombok()) uninstallAvailable = true; + installAvailable = true; + } + + uninstallButton.setVisible(uninstallAvailable); + uninstallPlaceholder.setVisible(!uninstallAvailable); + installButton.setEnabled(installAvailable); + } + + private class EclipsesList extends JPanel implements Scrollable { + private static final long serialVersionUID = 1L; + + List<EclipseLocation> locations = new ArrayList<EclipseLocation>(); + + EclipsesList() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + setBackground(Color.WHITE); + } + + List<EclipseLocation> getSelectedEclipses() { + List<EclipseLocation> list = new ArrayList<EclipseLocation>(); + for (EclipseLocation loc : locations) if (loc.selected) list.add(loc); + return list; + } + + void fireSelectionChange() { + selectedLomboksChanged(getSelectedEclipses()); + } + + void addEclipse(final EclipseLocation location) { + if (locations.contains(location)) return; + Box box = Box.createHorizontalBox(); + box.setBackground(Color.WHITE); + final JCheckBox checkbox = new JCheckBox(location.getName()); + checkbox.setBackground(Color.WHITE); + box.add(checkbox); + checkbox.setSelected(true); + checkbox.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + location.selected = checkbox.isSelected(); + fireSelectionChange(); + } + }); + + if (location.hasLombok()) { + box.add(new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/lombokIcon.png")))); + } + box.add(Box.createHorizontalGlue()); + locations.add(location); + add(box); + getParent().doLayout(); + fireSelectionChange(); + } + + @Override public Dimension getPreferredScrollableViewportSize() { + return new Dimension(1, 100); + } + + @Override public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { + return 12; + } + + @Override public boolean getScrollableTracksViewportHeight() { + return false; + } + + @Override public boolean getScrollableTracksViewportWidth() { + return true; + } + + @Override public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + return 1; + } + } + + private void buildChrome(Container appWindowContainer) { + JLabel leftGraphic = new JLabel(new ImageIcon(Installer.class.getResource("/lombok/installer/lombok.png"))); + + GridBagConstraints constraints = new GridBagConstraints(); + + appWindowContainer.setLayout(new GridBagLayout()); + + constraints.gridheight = 3; + constraints.gridwidth = 1; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.insets = new Insets(8, 8, 8, 8); + appWindowContainer.add(leftGraphic, constraints); + constraints.insets = new Insets(0, 0, 0, 0); + + constraints.gridx++; + constraints.gridy++; + constraints.gridheight = 1; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.ipadx = 16; + constraints.ipady = 14; + appWindowContainer.add(javacArea, constraints); + + constraints.gridy++; + appWindowContainer.add(eclipseArea, constraints); + + appWindowContainer.add(uninstallArea, constraints); + + appWindowContainer.add(howIWorkArea, constraints); + + constraints.gridy++; + constraints.gridwidth = 2; + constraints.gridx = 0; + constraints.weightx = 0; + constraints.weighty = 0; + constraints.ipadx = 0; + constraints.ipady = 0; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.anchor = GridBagConstraints.SOUTHEAST; + constraints.insets = new Insets(0, 16, 8, 8); + Box buttonBar = Box.createHorizontalBox(); + JButton quitButton = new JButton("Quit Installer"); + quitButton.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { + appWindow.setVisible(false); + System.exit(0); + } + }); + final JHyperLink hyperlink = new JHyperLink(ABOUT_LOMBOK_URL.toString()); + hyperlink.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent event) { + hyperlink.setForeground(new Color(85, 145, 90)); + try { + //java.awt.Desktop doesn't exist in 1.5. + 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) { + Runtime rt = Runtime.getRuntime(); + try { + 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); + break; + case MAC_OS_X: + rt.exec("open " + ABOUT_LOMBOK_URL.toString()); + break; + default: + case UNIX: + rt.exec("firefox " + ABOUT_LOMBOK_URL.toString()); + break; + } + } catch (Exception e2) { + JOptionPane.showMessageDialog(appWindow, + "Well, this is embarrassing. I don't know how to open a webbrowser.\n" + + "I guess you'll have to open it. Browse to:\n" + + "http://projectlombok.org for more information about Lombok.", + "I'm embarrassed", JOptionPane.INFORMATION_MESSAGE); + } + } + } + }); + buttonBar.add(hyperlink); + buttonBar.add(Box.createRigidArea(new Dimension(16, 1))); + buttonBar.add(new JLabel("<html><font size=\"-1\">v" + Version.getVersion() + "</font></html>")); + + buttonBar.add(Box.createHorizontalGlue()); + buttonBar.add(quitButton); + 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 = + "<html><font size=\"+1\"><b><i>Eclipse</i></b></font></html>"; + + private static final String ECLIPSE_EXPLANATION = + "<html>Lombok can update your Eclipse to fully support all Lombok features.<br>" + + "Select Eclipse installations below and hit 'Install/Update'.</html>"; + + private static final String ECLIPSE_LOADING_EXPLANATION = + "Scanning your drives for Eclipse installations..."; + + private static final String JAVAC_TITLE = + "<html><font size=\"+1\"><b><i>Javac</i></b></font> (and tools that invoke javac such as <i>ant</i> and <i>maven</i>)</html>"; + + private static final String JAVAC_EXPLANATION = + "<html>Lombok works 'out of the box' with javac.<br>Just make sure the lombok.jar is in your classpath when you compile."; + + private static final String JAVAC_EXAMPLE = + "<html>Example: <code>javac -cp lombok.jar MyCode.java</code></html>"; + + private static final String UNINSTALL_TITLE = + "<html><font size=\"+1\"><b><i>Uninstall</i></b></font></html>"; + + private static final String UNINSTALL_EXPLANATION = + "<html>Uninstall Lombok from the following Eclipse Installations?</html>"; + + private static final String HOW_I_WORK_TITLE = + "<html><font size=\"+1\"><b><i>What this installer does</i></b></font></html>"; + + private static final String HOW_I_WORK_EXPLANATION = + "<html><ol>" + + "<li>First, I copy myself (lombok.jar) to your Eclipse install directory.</li>" + + "<li>Then, I edit the eclipse.ini file to add the following two entries:<br>" + + "<pre>-Xbootclasspath/a:lombok.jar<br>" + + "-javaagent:lombok.jar</pre></li></ol>" + + "<br>" + + "That's all there is to it. Note that on Mac OS X, eclipse.ini is hidden in<br>" + + "<code>Eclipse.app%1$sContents%1$sMacOS</code> so that's where I place the jar files.</html>"; +} diff --git a/src/installer/lombok/installer/WindowsDriveInfo-i386.dll b/src/installer/lombok/installer/WindowsDriveInfo-i386.dll Binary files differnew file mode 100644 index 00000000..eb7fa49a --- /dev/null +++ b/src/installer/lombok/installer/WindowsDriveInfo-i386.dll diff --git a/src/installer/lombok/installer/WindowsDriveInfo-x86_64.dll b/src/installer/lombok/installer/WindowsDriveInfo-x86_64.dll Binary files differnew file mode 100644 index 00000000..0b7c9a83 --- /dev/null +++ b/src/installer/lombok/installer/WindowsDriveInfo-x86_64.dll diff --git a/src/installer/lombok/installer/WindowsDriveInfo.java b/src/installer/lombok/installer/WindowsDriveInfo.java new file mode 100644 index 00000000..41a6b17e --- /dev/null +++ b/src/installer/lombok/installer/WindowsDriveInfo.java @@ -0,0 +1,127 @@ +/* + * 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.util.ArrayList; +import java.util.List; + +/** + * This class uses native calls on windows to figure out all drives, + * and, for each drive, if its a harddisk or something else. + * + * The output is essentially equivalent to running windows executable: + * <pre>fsutil fsinfo drives</pre> + * and + * <pre>fsutil fsinfo drivetype C:</pre> + * + * except that (A) fsutil requires privileges, (B) someone might have moved + * it out of the path or some such, and (C) its output is internationalized, + * so unless you want to include a table of how to say "Fixed Disk" in 300 + * languages, this really is a superior solution. + * <p> + * To compile it, you'll need windows, as well as MinGW: + * http://sourceforge.net/projects/mingw/files/ + * <p> + * Fetch gcc 4.0.4+, you don't need anything extra. Toss /c/mingw/bin in + * your git bash prompt's path (/etc/profile) and then run: + * + * $ gcc -c \ + -I "/c/Program Files/Java/jdk1.6.0_14/include" \ + -I "/c/Program Files/Java/jdk1.6.0_14/include/win32" \ + -D__int64="long long" lombok_installer_WindowsDriveInfo.c + * + * $ dllwrap.exe --add-stdcall-alias \ + -o WindowsDriveInfo-i386.dll \ + lombok_installer_WindowsDriveInfo.o + * + * You may get a warning along the lines of "Creating an export definition". + * This is expected behaviour. + * + * <p> + * Now download MinGW-w64 to build the 64-bit version of the dll (you thought you were done, weren't you?) + * from: http://sourceforge.net/projects/mingw-w64/files/ + * (under toolchains targetting Win64 / Release for GCC 4.4.0 (or later) / the version for your OS.) + * + * Then, do this all over again, but this time with the x86_64-w64-mingw32-gcc and + * x86_64-w64-mingw32-dllwrap versions that are part of the MinGW-w64 distribution. + * Name the dll 'WindowsDriveInfo-x86_64.dll'. + * + * Both the 32-bit and 64-bit DLLs that this produces have been checked into the git repository + * under src/lombok/installer so you won't need to build them again unless you make some changes to + * the code in the winsrc directory. + */ +public class WindowsDriveInfo { + /** + * Return a list of all available drive letters, such as ["A", "C", "D"]. + */ + public List<String> getLogicalDrives() { + int flags = getLogicalDrives0(); + + List<String> letters = new ArrayList<String>(); + for (int i = 0; i < 26; i++) { + if ((flags & (1 << i)) != 0) letters.add(Character.toString((char)('A' + i))); + } + + return letters; + } + + /** + * Calls kernel32's GetLogicalDrives, which returns an int containing + * flags; bit 0 corresponds to drive A, bit 25 to drive Z. on = disk exists. + */ + private native int getLogicalDrives0(); + + /** + * Feed it a drive letter (such as 'A') to see if it is a fixed disk. + */ + public boolean isFixedDisk(String letter) { + if (letter.length() != 1) throw new IllegalArgumentException("Supply 1 letter, not: " + letter); + char drive = Character.toUpperCase(letter.charAt(0)); + if (drive < 'A' || drive > 'Z') throw new IllegalArgumentException( + "A drive is indicated by a letter, so A-Z inclusive. Not " + drive); + return getDriveType(drive + ":\\") == 3L; + } + + /** + * Mirror of kernel32's GetDriveTypeA. You must pass in 'A:\\' - + * so including both a colon and a backslash! + * + * 0 = error + * 1 = doesn't exist + * 2 = removable drive + * 3 = fixed disk + * 4 = remote (network) disk + * 5 = cd-rom + * 6 = ram disk + */ + private native int getDriveType(String name); + + public static void main(String[] args) { + System.loadLibrary("WindowsDriveInfo"); + WindowsDriveInfo info = new WindowsDriveInfo(); + + for (String letter : info.getLogicalDrives()) { + System.out.printf("Drive %s: - %s\n", letter, + info.isFixedDisk(letter) ? "Fixed Disk" : "Not Fixed Disk"); + } + } +} diff --git a/src/installer/lombok/installer/loading.gif b/src/installer/lombok/installer/loading.gif Binary files differnew file mode 100644 index 00000000..b9fc304a --- /dev/null +++ b/src/installer/lombok/installer/loading.gif diff --git a/src/installer/lombok/installer/lombok.png b/src/installer/lombok/installer/lombok.png Binary files differnew file mode 100644 index 00000000..d4efde04 --- /dev/null +++ b/src/installer/lombok/installer/lombok.png diff --git a/src/installer/lombok/installer/lombok.svg b/src/installer/lombok/installer/lombok.svg new file mode 100644 index 00000000..0d561aea --- /dev/null +++ b/src/installer/lombok/installer/lombok.svg @@ -0,0 +1,181 @@ +<?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/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="720" + height="256" + id="svg2809" + sodipodi:version="0.32" + inkscape:version="0.46" + version="1.0" + sodipodi:docname="Peperoni.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs2811"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2817" /> + </defs> + <sodipodi:namedview + id="base" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.98994949" + inkscape:cx="404.16677" + inkscape:cy="196.96954" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1280" + inkscape:window-height="904" + inkscape:window-x="-4" + inkscape:window-y="-4" /> + <metadata + id="metadata2814"> + <rdf:RDF> + <cc:Work + rdf:about=""> + + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-68.690412,-361.67592)"> + <g + style="display:inline" + id="g8198" + transform="matrix(1.4248201,0.1395229,-0.1500716,1.3983461,160.45389,-461.25789)"> + <path + sodipodi:nodetypes="cccccccccccccccccccccc" + id="path7056" + d="M 93.681663,642.08699 L 81.559832,655.72405 L 70.953231,677.44233 L 72.973535,706.73675 L 98.732426,730.47535 L 135.09792,735.5261 L 168.43295,734.01087 L 199.49514,720.37382 L 260.35683,709.26214 L 328.79467,702.69615 L 351.27057,699.66569 L 434.10307,706.23168 L 465.92287,704.71645 L 494.71222,703.7063 L 501.53075,698.90808 L 501.27822,688.04893 L 488.6513,679.96771 L 394.20205,646.1276 L 311.36954,628.95501 L 223.48627,620.87379 L 140.90629,628.44994 L 93.681663,642.08699 z" + style="fill:#622819;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + + <path + sodipodi:nodetypes="ccccccccccccccccccccc" + id="path4133" + d="M 232.56696,623.89286 L 147.77232,629.61607 L 191.55994,630.13901 L 247.24726,636.90381 L 193.08716,634.57713 L 148.63497,634.83828 L 109.70889,640.35941 L 92.160714,646.14286 L 75.004464,672.39286 L 73.973214,703.70536 L 102.25446,729.95536 L 153.78571,732.98661 L 227.53571,710.76786 L 350.75446,697.64286 L 433.59821,704.70536 L 490.16071,701.67411 L 497.22321,695.61161 L 494.19196,685.51786 L 417.44196,656.23661 L 328.53571,634.01786 L 232.56696,623.89286 z" + style="fill:#b23b23;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + sodipodi:nodetypes="cccccccccccccccccccccccccccccc" + id="path5116" + d="M 102.01542,659.51212 L 117.92532,656.73421 L 123.48116,666.33065 L 134.59284,660.77482 L 149.74513,656.22913 L 136.10807,663.80527 L 132.57254,672.39157 L 138.12838,677.44233 L 152.77559,679.96771 L 168.93803,676.93726 L 148.2299,688.55401 L 139.13853,689.56416 L 137.11822,701.18092 L 126.51162,713.80782 L 132.06746,724.41443 L 139.6436,726.93981 L 128.02685,727.44488 L 116.91517,715.82813 L 105.80349,714.81798 L 97.217197,719.36366 L 102.26796,710.27229 L 89.641053,702.69615 L 86.105519,690.06924 L 80.54968,679.96771 L 80.54968,671.88649 L 88.378362,681.23041 L 89.388514,669.36111 L 94.313008,661.02735 L 101.13154,648.14791 L 102.01542,659.51212 z" + style="opacity:0.5;fill:#76140e;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + id="path7063" + d="M 170.35714,628.57143 L 225.35714,626.42857 L 289.64285,632.85715 L 324.28571,638.92857 L 254.64285,632.85715 L 201.78571,629.64286 L 170.35714,628.57143 z" + style="opacity:0.5;fill:#f5cfce;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccccccccccc" + id="path7065" + d="M 111.13075,653.29059 L 132.33216,642.9746 L 188.38383,638.59697 L 294.36063,641.41822 L 352.13548,649.71389 L 403.48175,662.65243 L 351.95691,655.2623 L 294.00349,648.9436 L 219.93315,645.02553 L 138.00529,647.64284 L 111.13075,653.29059 z" + style="opacity:0.65;fill:#f5cfce;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" /> + <g + id="g7195"> + <path + style="fill:#7c8f11;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 87.857143,673.57143 L 97.5,665 L 101.07143,656.07143 L 112.14286,661.07143 L 127.14286,669.64286 L 141.07143,670.00001 L 136.42857,686.07143 L 136.42857,698.57143 L 136.78571,711.42857 L 120.35714,715.35714 L 107.14286,726.07143 L 102.85714,717.14286 L 91.785714,708.57143 L 81.071428,705.35715 L 83.571428,691.07143 L 79.285714,679.28572 L 87.857143,673.57143 z" + id="path7067" /> + <g + id="g7188"> + <path + sodipodi:nodetypes="ccccc" + id="path7186" + d="M 102.96317,716.26763 L 107.54899,723.42044 L 118.24139,716.08913 L 107.75203,720.8537 L 102.96317,716.26763 z" + style="fill:#626e28;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" /> + <path + sodipodi:nodetypes="ccccc" + id="path7184" + d="M 134.61975,687.20372 L 139.6134,671.96557 L 121.44201,669.94176 L 137.02204,673.00191 L 134.61975,687.20372 z" + style="opacity:0.85;fill:#626e28;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" /> + + <path + sodipodi:nodetypes="ccccc" + id="path7182" + d="M 113.00055,663.41369 L 103.07121,660.21836 L 97.878976,670.80219 L 103.11895,663.00885 L 113.00055,663.41369 z" + style="opacity:0.75;fill:#626e28;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" /> + <path + id="path7180" + d="M 124.77374,713.72385 L 135.27853,709.55732 L 135.22118,694.14433 L 133.5153,708.85426 L 124.77374,713.72385 z" + style="opacity:0.9;fill:#626e28;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" /> + <path + sodipodi:nodetypes="cccccc" + id="path7178" + d="M 93.346449,670.33792 L 89.083939,677.49039 L 84.107143,703.03572 L 98.571429,710.53571 L 86.25,702.32143 L 93.346449,670.33792 z" + style="fill:#626e28;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + <path + style="fill:#4c551f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 102.01037,673.90149 L 111.04259,673.65316 L 113.59948,668.62761 L 112.75953,664.10715 L 115.90934,669.94608 L 114.60963,675.40831 L 122.04984,682.38577 L 127.11825,681.31985 L 132.78792,674.7275 L 130.26806,683.39173 L 123.3838,687.15457 L 122.45598,693.99946 L 127.74547,698.63991 L 134.76015,699.32493 L 126.69828,700.20251 L 120.36164,698.39576 L 120.34022,704.03658 L 119.51736,707.59013 L 123.89164,711.72121 L 119.86814,710.34986 L 114.11689,715.13871 L 109.28719,716.64553 L 106.21012,712.06452 L 101.21021,714.56889 L 104.74021,710.06523 L 101.92803,703.84539 L 92.680284,699.70584 L 94.660804,684.6376 L 102.01037,673.90149 z" + id="path7140" + sodipodi:nodetypes="ccccccccccccccccccccccccccccc" /> + </g> + <g + id="g7217"> + <path + style="fill:#748804;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 110.71429,675.89286 L 119.28571,684.82143 L 120.53571,696.07143 L 113.92857,702.32143 L 105,703.39286 L 90.357143,700.17857 L 63.114938,697.69652 L 40.829403,689.60479 L 17.678571,664.28572 L 19.107142,624.46429 L 50.714286,601.96429 L 93.989847,617.23478 L 94.353336,623.08059 L 87.696519,628.47208 L 52.240029,617.80856 L 36.507794,629.66824 L 32.512691,650.73223 L 46.071429,670.35715 L 61.768856,674.86739 L 84.284813,673.31672 L 110.71429,675.89286 z" + id="path7144" + sodipodi:nodetypes="ccccccccccccccccccccc" /> + <path + style="opacity:0.5;fill:#544d25;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" + d="M 19.941964,623.86161 L 19.098214,624.45536 L 17.691964,664.29911 L 40.816964,689.61161 L 63.129464,697.70536 L 90.348214,700.17411 L 105.00446,703.39286 L 113.94196,702.33036 L 120.53571,696.08036 L 119.28571,684.83036 L 115.41071,680.79911 L 117.50446,689.64286 L 113.94196,697.48661 L 79.629464,694.64286 L 45.723214,686.79911 L 22.848214,661.42411 L 19.941964,623.86161 z" + id="path7151" /> + + <path + style="opacity:0.75;fill:#544d25;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" + d="M 66.772321,617.12946 L 48.558036,614.63393 L 34.28125,627.14732 L 34.441964,640.58036 L 36.504464,629.67411 L 52.254464,617.79911 L 87.691964,628.48661 L 88.691964,627.67411 L 66.772321,617.12946 z" + id="path7158" + sodipodi:nodetypes="ccccccccc" /> + <path + style="opacity:0.5;fill:#dbd4ac;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" + d="M 34.254464,653.23661 L 40.910714,669.86161 L 55.035714,676.42411 L 101.00446,676.92411 L 111.97393,679.56149 L 115.98438,687.67857 L 114.53571,679.86161 L 110.72321,675.89286 L 84.285714,673.33036 L 61.754464,674.86161 L 46.066964,670.36161 L 34.254464,653.23661 z" + id="path7167" + sodipodi:nodetypes="cccccccccccc" /> + <path + style="opacity:0.5;fill:#dbd4ac;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" + d="M 50.723214,601.95536 L 20.410714,623.51786 L 25.723214,622.14286 L 44.098214,608.20536 L 53.941964,604.45536 L 89.473214,617.67411 L 92.316964,622.48661 L 89.160714,627.29911 L 94.348214,623.08036 L 94.004464,617.23661 L 50.723214,601.95536 z" + id="path7174" /> + <path + style="opacity:0.19959992;fill:#ede8c7;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" + d="M 29.362243,653.61621 L 28.049844,631.79912 L 35.071204,620.33609 L 45.073313,613.06741 L 62.525298,611.10202 L 87.466768,624.95988 L 63.410075,609.25123 L 43.307335,610.88104 L 25.325211,627.5252 L 25.726456,652.73228 L 42.393695,679.04205 L 73.325818,681.39721 L 108.01767,688.31438 L 75.307884,679.02475 L 43.738547,676.92791 L 29.362243,653.61621 z" + id="path7176" + sodipodi:nodetypes="cccccccccccccccc" /> + </g> + <path + sodipodi:nodetypes="ccccccc" + id="path7225" + d="M 168.69547,724.75894 L 235.87062,693.94929 L 296.98485,696.97975 L 371.23106,685.36299 L 300.52038,700.51528 L 238.90108,702.53558 L 168.69547,724.75894 z" + style="fill:#803311;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccccccc" + id="path8196" + d="M 395.47472,693.94929 L 437.64859,700.26274 L 478.81231,696.72721 L 484.87322,686.87822 L 482.60038,699.50513 L 433.60798,703.04067 L 395.47472,693.94929 z" + style="fill:#803311;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + </g> + +</svg> diff --git a/src/installer/lombok/installer/lombokIcon.png b/src/installer/lombok/installer/lombokIcon.png Binary files differnew file mode 100644 index 00000000..48fd4307 --- /dev/null +++ b/src/installer/lombok/installer/lombokIcon.png diff --git a/src/installer/lombok/installer/lombokText.png b/src/installer/lombok/installer/lombokText.png Binary files differnew file mode 100644 index 00000000..279746cb --- /dev/null +++ b/src/installer/lombok/installer/lombokText.png diff --git a/src/installer/lombok/installer/lombokText.svg b/src/installer/lombok/installer/lombokText.svg new file mode 100644 index 00000000..9fd2f73b --- /dev/null +++ b/src/installer/lombok/installer/lombokText.svg @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="425.0675" + height="56.760002" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="lombokText.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <metadata + id="metadata2527"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + inkscape:window-height="713" + inkscape:window-width="640" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + showgrid="false" + inkscape:zoom="1" + inkscape:cx="194.15432" + inkscape:cy="205" + inkscape:window-x="365" + inkscape:window-y="58" + inkscape:current-layer="svg2" /> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 100 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="500 : 100 : 1" + inkscape:persp3d-origin="250 : 66.666667 : 1" + id="perspective2529" /> + </defs> + <g + id="layer1" + transform="translate(-31.89625,-66.299366)"> + <path + d="M 31.89625,123.05937 L 31.89625,66.299366 L 41.35625,66.299366 L 41.35625,115.13937 L 84.36625,115.13937 L 84.36625,123.05937 L 31.89625,123.05937 M 98.808906,87.529366 C 98.808897,83.276072 99.615562,80.379409 101.22891,78.839366 C 102.84223,77.226078 105.84889,76.419413 110.24891,76.419366 L 143.90891,76.419366 C 148.30885,76.419413 151.31551,77.226078 152.92891,78.839366 C 154.54217,80.379409 155.34884,83.276072 155.34891,87.529366 L 155.34891,112.05937 C 155.34884,116.31271 154.54217,119.20937 152.92891,120.74937 C 151.31551,122.28937 148.30885,123.05937 143.90891,123.05937 L 110.24891,123.05937 C 105.77556,123.05937 102.73223,122.32603 101.11891,120.85937 C 99.578896,119.31937 98.808897,116.38604 98.808906,112.05937 L 98.808906,87.529366 M 107.60891,116.01937 L 146.54891,116.01937 L 146.54891,83.349366 L 107.60891,83.349366 L 107.60891,116.01937 M 182.78875,85.109366 L 183.00875,91.599366 L 183.00875,123.05937 L 175.74875,123.05937 L 175.74875,76.419366 L 183.00875,76.419366 L 206.21875,106.66937 L 227.55875,76.419366 L 235.69875,76.419366 L 235.69875,123.05937 L 227.55875,123.05937 L 227.55875,91.599366 C 227.55869,89.326066 227.74202,87.162735 228.10875,85.109366 C 227.08202,88.042734 226.05536,90.206065 225.02875,91.599366 L 207.09875,115.68937 L 204.78875,115.68937 L 186.19875,91.819366 C 184.8054,90.059399 183.66873,87.822734 182.78875,85.109366 M 257.38937,123.05937 L 257.38937,76.419366 L 296.76938,76.419366 C 303.58932,76.419413 306.99931,79.462743 306.99937,85.549366 L 306.99937,90.939366 C 306.99931,95.632727 304.28598,98.309391 298.85938,98.969366 C 304.50598,99.556056 307.32931,102.56272 307.32938,107.98937 L 307.32938,113.92937 C 307.32931,120.01604 302.81932,123.05937 293.79937,123.05937 L 257.38937,123.05937 M 298.19938,91.489366 L 298.19938,87.089366 C 298.19932,84.522738 296.54933,83.239406 293.24937,83.239366 L 266.18937,83.239366 L 266.18937,95.229366 L 293.24937,95.229366 C 295.08266,95.229394 296.36599,95.009394 297.09938,94.569366 C 297.83266,94.056062 298.19932,93.029396 298.19938,91.489366 M 266.18937,102.04937 L 266.18937,116.23937 L 293.24937,116.23937 C 295.22933,116.23937 296.58599,115.87271 297.31937,115.13937 C 298.12599,114.33271 298.52932,112.93938 298.52938,110.95937 L 298.52938,107.32937 C 298.52932,103.80939 296.76932,102.04939 293.24937,102.04937 L 266.18937,102.04937 M 325.68391,87.529366 C 325.6839,83.276072 326.49056,80.379409 328.10391,78.839366 C 329.71723,77.226078 332.72389,76.419413 337.12391,76.419366 L 370.78391,76.419366 C 375.18385,76.419413 378.19051,77.226078 379.80391,78.839366 C 381.41717,80.379409 382.22384,83.276072 382.22391,87.529366 L 382.22391,112.05937 C 382.22384,116.31271 381.41717,119.20937 379.80391,120.74937 C 378.19051,122.28937 375.18385,123.05937 370.78391,123.05937 L 337.12391,123.05937 C 332.65056,123.05937 329.60723,122.32603 327.99391,120.85937 C 326.4539,119.31937 325.6839,116.38604 325.68391,112.05937 L 325.68391,87.529366 M 334.48391,116.01937 L 373.42391,116.01937 L 373.42391,83.349366 L 334.48391,83.349366 L 334.48391,116.01937 M 402.62375,123.05937 L 402.62375,76.419366 L 411.42375,76.419366 L 411.42375,96.439366 L 440.90375,76.419366 L 453.11375,76.419366 L 418.68375,98.969366 L 456.96375,123.05937 L 442.55375,123.05937 L 411.42375,102.15937 L 411.42375,123.05937 L 402.62375,123.05937" + id="flowRoot2383" + style="font-size:110px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bank Gothic;-inkscape-font-specification:Bank Gothic" /> + </g> +</svg> diff --git a/src/installer/lombok/installer/package-info.java b/src/installer/lombok/installer/package-info.java new file mode 100644 index 00000000..14b329b4 --- /dev/null +++ b/src/installer/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; |