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 | |
| parent | 7fd947ea40c25dad9ee543ebc4b92de9a2e05efc (diff) | |
| download | lombok-1a0e611a9c5e1ee518670647ce1a44beae559b44.tar.gz lombok-1a0e611a9c5e1ee518670647ce1a44beae559b44.tar.bz2 lombok-1a0e611a9c5e1ee518670647ce1a44beae559b44.zip | |
Refactored the source folders.
Diffstat (limited to 'src/installer')
| -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.HeadlessExcepti |
