From d02bbf6261cb82e3f254f2a033024f6da8f9f38f Mon Sep 17 00:00:00 2001 From: rgra Date: Fri, 25 Mar 2016 19:47:08 +0100 Subject: Patch for renaming fields with Getter/Setter/Data in eclipse. --- .../lombok/eclipse/agent/EclipsePatcher.java | 20 ++++++++++ .../lombok/launch/PatchFixesHider.java | 46 ++++++++++++++++++++++ 2 files changed, 66 insertions(+) (limited to 'src') diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java index 7c538b6f..336204a2 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java +++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java @@ -28,6 +28,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; + import lombok.core.AgentLauncher; import lombok.patcher.Hook; import lombok.patcher.MethodTarget; @@ -108,10 +110,28 @@ public class EclipsePatcher implements AgentLauncher.AgentLaunchable { patchLombokizeAST(sm); patchEcjTransformers(sm, ecjOnly); patchExtensionMethod(sm, ecjOnly); + patchRenameField(sm); if (reloadExistingClasses) sm.reloadClasses(instrumentation); } + private static void patchRenameField(ScriptManager sm) { + /* RefactoringSearchEngine.search will not return results when renaming field and Data Annotation is present. Return a fake Element to make checks pass */ + sm.addScript(ScriptBuilder.wrapMethodCall() + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor", "checkAccessorDeclarations", "org.eclipse.ltk.core.refactoring.RefactoringStatus", "org.eclipse.core.runtime.IProgressMonitor", "org.eclipse.jdt.core.IMethod")) + .methodToWrap(new Hook("org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine", "search", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "org.eclipse.jdt.core.search.SearchPattern","org.eclipse.jdt.core.search.IJavaSearchScope","org.eclipse.core.runtime.IProgressMonitor","org.eclipse.ltk.core.refactoring.RefactoringStatus")) + .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "createFakeSearchResult", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "java.lang.Object")) + .requestExtra(StackRequest.THIS) + .transplant().build()); + + /* Filter search results which are Generated and based on Fields, e.g. Generated getters/setters */ + sm.addScript(ScriptBuilder.wrapMethodCall() + .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor", "addAccessorOccurrences", "void", "org.eclipse.core.runtime.IProgressMonitor", "org.eclipse.jdt.core.IMethod", "java.lang.String","java.lang.String","org.eclipse.ltk.core.refactoring.RefactoringStatus")) + .methodToWrap(new Hook("org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup", "getSearchResults", "org.eclipse.jdt.core.search.SearchMatch[]")) + .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGenerated", "org.eclipse.jdt.core.search.SearchMatch[]", "org.eclipse.jdt.core.search.SearchMatch[]")) + .transplant().build()); + } + private static void patchExtractInterface(ScriptManager sm) { /* Fix sourceEnding for generated nodes to avoid null pointer */ sm.addScript(ScriptBuilder.wrapMethodCall() diff --git a/src/eclipseAgent/lombok/launch/PatchFixesHider.java b/src/eclipseAgent/lombok/launch/PatchFixesHider.java index fae06900..b1d73352 100644 --- a/src/eclipseAgent/lombok/launch/PatchFixesHider.java +++ b/src/eclipseAgent/lombok/launch/PatchFixesHider.java @@ -36,11 +36,13 @@ import lombok.eclipse.EclipseAugments; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IAnnotatable; import org.eclipse.jdt.core.IAnnotation; +import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.search.SearchMatch; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; @@ -55,9 +57,11 @@ import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; +import org.eclipse.jdt.internal.core.SourceField; import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent; import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent; import org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner; +import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; /** These contain a mix of the following: @@ -565,6 +569,48 @@ final class PatchFixesHider { return result.size() == methods.length ? methods : result.toArray(new IMethod[result.size()]); } + public static SearchMatch[] removeGenerated(SearchMatch[] returnValue) { + List result = new ArrayList(); + for (int j = 0; j < returnValue.length; j++) { + SearchMatch searchResult = returnValue[j]; + if (searchResult.getElement() instanceof IField) { + IField field = (IField) searchResult.getElement(); + + // can not check for value=lombok because annotation is + // not fully resolved + IAnnotation annotation = field.getAnnotation("Generated"); + if (annotation != null) { + // Method generated at field location, skip + continue; + } + + } + result.add(searchResult); + } + return result.toArray(new SearchMatch[result.size()]); + } + + public static SearchResultGroup[] createFakeSearchResult(SearchResultGroup[] returnValue, + Object/* + * org.eclipse.jdt.internal.corext.refactoring.rename. + * RenameFieldProcessor + */ processor) throws Exception { + if (returnValue == null || returnValue.length == 0) { + // if no matches were found, check if Data annotation is present on the class + Field declaredField = processor.getClass().getDeclaredField("fField"); + if (declaredField != null) { + declaredField.setAccessible(true); + SourceField fField = (SourceField) declaredField.get(processor); + IAnnotation dataAnnotation = fField.getDeclaringType().getAnnotation("Data"); + if (dataAnnotation != null) { + // add fake item, to make refactoring checks pass + return new SearchResultGroup[] {new SearchResultGroup(null, new SearchMatch[1])}; + } + } + } + return returnValue; + } + public static SimpleName[] removeGeneratedSimpleNames(SimpleName[] in) throws Exception { Field f = SimpleName.class.getField("$isGenerated"); -- cgit From 89aa4de4fabccf7065041ce270c25aeda2726ab0 Mon Sep 17 00:00:00 2001 From: Dave Brosius Date: Mon, 12 Dec 2016 20:23:17 -0500 Subject: add missing printf anchor --- src/core/lombok/core/configuration/ConfigurationApp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/lombok/core/configuration/ConfigurationApp.java b/src/core/lombok/core/configuration/ConfigurationApp.java index e441b4de..0a44a6c4 100644 --- a/src/core/lombok/core/configuration/ConfigurationApp.java +++ b/src/core/lombok/core/configuration/ConfigurationApp.java @@ -198,7 +198,7 @@ public class ConfigurationApp extends LombokApp { if (paths.size() == 1) { if (!(argsPaths.size() == 1)) out.printf("Configuration for '%s'.%n%n", paths.iterator().next()); } else { - out.printf("Configuration for:%n", paths.iterator().next()); + out.printf("Configuration for: %s%n", paths.iterator().next()); for (String path : paths) out.printf("- %s%n", path); out.println(); } -- cgit From f6c2b19260d90c59ea2f24652df0fbbd810ea461 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Tue, 13 Dec 2016 15:38:23 +0100 Subject: Simplify the registration of Eclipse-like IDEs, remove code duplication --- src/installer/lombok/installer/IdeFinder.java | 144 -------- src/installer/lombok/installer/IdeLocation.java | 7 +- .../lombok/installer/IdeLocationProvider.java | 22 +- src/installer/lombok/installer/Installer.java | 17 +- src/installer/lombok/installer/InstallerGUI.java | 10 +- src/installer/lombok/installer/OsUtils.java | 137 ++++++++ .../lombok/installer/eclipse/EclipseFinder.java | 246 ------------- .../lombok/installer/eclipse/EclipseLocation.java | 382 --------------------- .../installer/eclipse/EclipseLocationProvider.java | 149 +------- .../eclipse/EclipseProductDescriptor.java | 41 +++ .../installer/eclipse/EclipseProductLocation.java | 377 ++++++++++++++++++++ .../eclipse/EclipseProductLocationProvider.java | 324 +++++++++++++++++ .../lombok/installer/eclipse/JbdsFinder.java | 70 ---- .../lombok/installer/eclipse/JbdsLocation.java | 45 --- .../installer/eclipse/JbdsLocationProvider.java | 49 +-- .../lombok/installer/eclipse/MyEclipseFinder.java | 69 ---- .../installer/eclipse/MyEclipseLocation.java | 45 --- .../eclipse/MyEclipseLocationProvider.java | 52 +-- .../lombok/installer/eclipse/RhdsFinder.java | 70 ---- .../lombok/installer/eclipse/RhdsLocation.java | 45 --- .../installer/eclipse/RhdsLocationProvider.java | 49 +-- .../lombok/installer/eclipse/STSFinder.java | 70 ---- .../lombok/installer/eclipse/STSLocation.java | 45 --- .../installer/eclipse/STSLocationProvider.java | 48 +-- .../eclipse/StandardProductDescriptor.java | 158 +++++++++ 25 files changed, 1130 insertions(+), 1541 deletions(-) delete mode 100644 src/installer/lombok/installer/IdeFinder.java create mode 100644 src/installer/lombok/installer/OsUtils.java delete mode 100644 src/installer/lombok/installer/eclipse/EclipseFinder.java delete mode 100644 src/installer/lombok/installer/eclipse/EclipseLocation.java create mode 100644 src/installer/lombok/installer/eclipse/EclipseProductDescriptor.java create mode 100644 src/installer/lombok/installer/eclipse/EclipseProductLocation.java create mode 100644 src/installer/lombok/installer/eclipse/EclipseProductLocationProvider.java delete mode 100644 src/installer/lombok/installer/eclipse/JbdsFinder.java delete mode 100644 src/installer/lombok/installer/eclipse/JbdsLocation.java delete mode 100644 src/installer/lombok/installer/eclipse/MyEclipseFinder.java delete mode 100644 src/installer/lombok/installer/eclipse/MyEclipseLocation.java delete mode 100644 src/installer/lombok/installer/eclipse/RhdsFinder.java delete mode 100644 src/installer/lombok/installer/eclipse/RhdsLocation.java delete mode 100644 src/installer/lombok/installer/eclipse/STSFinder.java delete mode 100644 src/installer/lombok/installer/eclipse/STSLocation.java create mode 100644 src/installer/lombok/installer/eclipse/StandardProductDescriptor.java (limited to 'src') diff --git a/src/installer/lombok/installer/IdeFinder.java b/src/installer/lombok/installer/IdeFinder.java deleted file mode 100644 index f68a0e4c..00000000 --- a/src/installer/lombok/installer/IdeFinder.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2009-2011 The Project Lombok Authors. - * - * 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.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import lombok.core.Version; - -/** - * Implement and provide this class to add auto-finding a certain brand of IDEs to the lombok installer. - */ -public abstract class IdeFinder { - 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 = IdeFinder.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 that represent fixed disks. - * - * Floppy drives, optical drives, USB sticks, and network drives should all be excluded. - * - * @return A List of drive letters, such as ["C", "D", "X"]. - */ - public static List getDrivesOnWindows() throws Throwable { - loadWindowsDriveInfoLib(); - - List drives = new ArrayList(); - - WindowsDriveInfo info = new WindowsDriveInfo(); - for (String drive : info.getLogicalDrives()) { - if (info.isFixedDisk(drive)) drives.add(drive); - } - - return drives; - } - - public static enum OS { - MAC_OS_X("\n"), WINDOWS("\r\n"), UNIX("\n"); - - private final String lineEnding; - - OS(String lineEnding) { - this.lineEnding = lineEnding; - } - - public String getLineEnding() { - return lineEnding; - } - } - - public 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|32|64)?\\b.*$")) return OS.WINDOWS; - - return OS.UNIX; - } - - /** - * Look for installations of your IDE in the usual places. - * - * @param locations Add to this list any valid locations that you found. - * @param problems - * Add to this list any locations that look like installations, - * but have problems that prevent you from installing/uninstalling from them. DONT add to this list - * any common locations that have no installation at all - only add near misses. - */ - public abstract void findIdes(List locations, List problems); -} diff --git a/src/installer/lombok/installer/IdeLocation.java b/src/installer/lombok/installer/IdeLocation.java index 4e3a7e41..c3853867 100644 --- a/src/installer/lombok/installer/IdeLocation.java +++ b/src/installer/lombok/installer/IdeLocation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2014 The Project Lombok Authors. + * Copyright (C) 2009-2016 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,6 @@ import java.io.File; import java.io.IOException; import java.net.URL; -import lombok.installer.eclipse.EclipseFinder; import lombok.patcher.ClassRootFinder; /** @@ -46,7 +45,7 @@ public abstract class IdeLocation { * a jar that wasn't accessed via the file-system, or if its started via e.g. unpacking the jar. */ public static File findOurJar() { - return new File(ClassRootFinder.findClassRootOfClass(IdeFinder.class)); + return new File(ClassRootFinder.findClassRootOfClass(OsUtils.class)); } @Override public String toString() { @@ -70,7 +69,7 @@ public abstract class IdeLocation { private static final String LEGAL_PATH_CHARS_WINDOWS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/:\\ "; public static String escapePath(String path) { StringBuilder out = new StringBuilder(); - String legalChars = IdeFinder.getOS() == EclipseFinder.OS.UNIX ? LEGAL_PATH_CHARS : LEGAL_PATH_CHARS_WINDOWS; + String legalChars = OsUtils.getOS() == OsUtils.OS.UNIX ? LEGAL_PATH_CHARS : LEGAL_PATH_CHARS_WINDOWS; for (char c : path.toCharArray()) { if (legalChars.indexOf(c) == -1) out.append('\\'); out.append(c); diff --git a/src/installer/lombok/installer/IdeLocationProvider.java b/src/installer/lombok/installer/IdeLocationProvider.java index 933a5989..c4b64141 100644 --- a/src/installer/lombok/installer/IdeLocationProvider.java +++ b/src/installer/lombok/installer/IdeLocationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Project Lombok Authors. + * Copyright (C) 2009-2016 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,20 +21,30 @@ */ package lombok.installer; +import java.util.List; import java.util.regex.Pattern; -import lombok.installer.IdeFinder.OS; - public interface IdeLocationProvider { /** * @throws CorruptedIdeLocationException * Only throw this exception if the location seems like a proper installation except there's something wrong with it. * Do not throw it (just return {@code null}) if there's nothing there or it looks absolutely nothing like your IDE. */ - public abstract IdeLocation create(String path) throws CorruptedIdeLocationException; + IdeLocation create(String path) throws CorruptedIdeLocationException; + + /** + * Return the usual name of the IDE executable or other obvious marker of an IDE installation on the current platform. + */ + Pattern getLocationSelectors(); /** - * Return the usual name of the IDE executable or other obvious marker of an IDE installation on the provided platform. + * Look for installations of your IDE in the usual places. + * + * @param locations Add to this list any valid locations that you found. + * @param problems + * Add to this list any locations that look like installations, + * but have problems that prevent you from installing/uninstalling from them. DONT add to this list + * any common locations that have no installation at all - only add near misses. */ - public abstract Pattern getLocationSelectors(OS os); + void findIdes(List locations, List problems); } diff --git a/src/installer/lombok/installer/Installer.java b/src/installer/lombok/installer/Installer.java index 7ae01d7a..94cc1a45 100644 --- a/src/installer/lombok/installer/Installer.java +++ b/src/installer/lombok/installer/Installer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 The Project Lombok Authors. + * Copyright (C) 2009-2016 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,7 @@ import lombok.Lombok; import lombok.core.LombokApp; import lombok.core.SpiLoadUtil; import lombok.core.Version; -import lombok.installer.IdeFinder.OS; +import lombok.installer.OsUtils.OS; import lombok.patcher.ClassRootFinder; import org.mangosdk.spi.ProviderFor; @@ -72,10 +72,9 @@ public class Installer { } static List getIdeExecutableNames() { - OS os = IdeFinder.getOS(); List list = new ArrayList(); for (IdeLocationProvider provider : locationProviders) { - Pattern p = provider.getLocationSelectors(os); + Pattern p = provider.getLocationSelectors(); if (p != null) list.add(p); } return list; @@ -91,12 +90,8 @@ public class Installer { } static void autoDiscover(List locations, List problems) { - try { - for (IdeFinder finder : SpiLoadUtil.findServices(IdeFinder.class)) { - finder.findIdes(locations, problems); - } - } catch (IOException e) { - throw Lombok.sneakyThrow(e); + for (IdeLocationProvider provider : locationProviders) { + provider.findIdes(locations, problems); } } @@ -160,7 +155,7 @@ public class Installer { } private static int guiInstaller() { - if (IdeFinder.getOS() == OS.MAC_OS_X) { + if (OsUtils.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"); } diff --git a/src/installer/lombok/installer/InstallerGUI.java b/src/installer/lombok/installer/InstallerGUI.java index 6b8a58ab..ebdf2035 100644 --- a/src/installer/lombok/installer/InstallerGUI.java +++ b/src/installer/lombok/installer/InstallerGUI.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 The Project Lombok Authors. + * Copyright (C) 2009-2016 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -67,7 +67,7 @@ import javax.swing.SwingUtilities; import javax.swing.filechooser.FileFilter; import lombok.core.Version; -import lombok.installer.IdeFinder.OS; +import lombok.installer.OsUtils.OS; /** * The lombok GUI installer. @@ -313,7 +313,7 @@ public class InstallerGUI { final List exeNames = Installer.getIdeExecutableNames(); String file = null; - if (IdeFinder.getOS() == OS.MAC_OS_X) { + if (OsUtils.getOS() == OS.MAC_OS_X) { FileDialog chooser = new FileDialog(appWindow); chooser.setMode(FileDialog.LOAD); @@ -740,7 +740,7 @@ public class InstallerGUI { } catch (Exception e) { Runtime rt = Runtime.getRuntime(); try { - switch (IdeFinder.getOS()) { + switch (OsUtils.getOS()) { case WINDOWS: String[] cmd = new String[4]; cmd[0] = "cmd.exe"; @@ -781,7 +781,7 @@ public class InstallerGUI { */ public void show() { appWindow.setVisible(true); - if (IdeFinder.getOS() == OS.MAC_OS_X) { + if (OsUtils.getOS() == OS.MAC_OS_X) { try { AppleNativeLook.go(); } catch (Throwable ignore) { diff --git a/src/installer/lombok/installer/OsUtils.java b/src/installer/lombok/installer/OsUtils.java new file mode 100644 index 00000000..2da7de09 --- /dev/null +++ b/src/installer/lombok/installer/OsUtils.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2009-2016 The Project Lombok Authors. + * + * 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.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import lombok.core.Version; + +/** + * Implement and provide this class to add auto-finding a certain brand of IDEs to the lombok installer. + */ +public final class OsUtils { + private static final AtomicBoolean windowsDriveInfoLibLoaded = new AtomicBoolean(false); + + private OsUtils() { + // Prevent instantiation + } + + 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 = OsUtils.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 that represent fixed disks. + * + * Floppy drives, optical drives, USB sticks, and network drives should all be excluded. + * + * @return A List of drive letters, such as ["C", "D", "X"]. + */ + public static List getDrivesOnWindows() throws Throwable { + loadWindowsDriveInfoLib(); + + List drives = new ArrayList(); + + WindowsDriveInfo info = new WindowsDriveInfo(); + for (String drive : info.getLogicalDrives()) { + if (info.isFixedDisk(drive)) drives.add(drive); + } + + return drives; + } + + public static enum OS { + MAC_OS_X("\n"), WINDOWS("\r\n"), UNIX("\n"); + + private final String lineEnding; + + OS(String lineEnding) { + this.lineEnding = lineEnding; + } + + public String getLineEnding() { + return lineEnding; + } + } + + public 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|32|64)?\\b.*$")) return OS.WINDOWS; + + return OS.UNIX; + } +} diff --git a/src/installer/lombok/installer/eclipse/EclipseFinder.java b/src/installer/lombok/installer/eclipse/EclipseFinder.java deleted file mode 100644 index 8a1a689a..00000000 --- a/src/installer/lombok/installer/eclipse/EclipseFinder.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2009-2011 The Project Lombok Authors. - * - * 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.eclipse; - -import static java.util.Arrays.asList; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import lombok.installer.IdeFinder; -import lombok.installer.IdeLocation; -import lombok.installer.CorruptedIdeLocationException; - -import org.mangosdk.spi.ProviderFor; - -@ProviderFor(IdeFinder.class) -public class EclipseFinder extends IdeFinder { - /** should be lowercase! */ - protected String getDirName() { - return "eclipse"; - } - - protected String getWindowsExecutableName() { - return "eclipse.exe"; - } - - protected String getUnixExecutableName() { - return "eclipse"; - } - - protected String getMacExecutableName() { - return "Eclipse.app"; - } - - protected IdeLocation createLocation(String guess) throws CorruptedIdeLocationException { - return new EclipseLocationProvider().create0(guess); - } - - protected List getSourceDirsOnWindows() { - return Arrays.asList("\\", "\\Program Files", "\\Program Files (x86)", System.getProperty("user.home", ".")); - } - - /** - * Returns a list of paths of Eclipse installations. - * - * The search process works by scanning for each 'source dir' for either an eclipse installation or a folder containing the text returned - * by getDirName(). If such a folder is found, this process is applied recursively. On windows, this process is run on each drive letter - * which represents a physical hard disk. If the native windows API call to determine these drive letters fails, only 'C:' is checked. - */ - private List getSourceDirsOnWindowsWithDriveLetters() { - List driveLetters = asList("C"); - try { - driveLetters = getDrivesOnWindows(); - } catch (Throwable ignore) { - ignore.printStackTrace(); - } - List sourceDirs = new ArrayList(); - for (String letter : driveLetters) { - for (String possibleSource : getSourceDirsOnWindows()) { - if (!isDriveSpecificOnWindows(possibleSource)) { - sourceDirs.add(letter + ":" + possibleSource); - } - } - } - for (String possibleSource : getSourceDirsOnWindows()) { - if (isDriveSpecificOnWindows(possibleSource)) sourceDirs.add(possibleSource); - } - - return sourceDirs; - } - - public boolean isDriveSpecificOnWindows(String path) { - return path.length() > 1 && path.charAt(1) == ':'; - } - - protected List getSourceDirsOnMac() { - return Arrays.asList("/Applications", System.getProperty("user.home", ".")); - } - - protected List getSourceDirsOnUnix() { - return Arrays.asList(System.getProperty("user.home", ".")); - } - - private List transformToFiles(List fileNames) { - List files = new ArrayList(); - for (String fileName : fileNames) { - files.add(new File(fileName)); - } - return files; - } - - private List getFlatSourceLocationsOnUnix() { - List dirs = new ArrayList(); - dirs.add(new File("/usr/bin/")); - dirs.add(new File("/usr/local/bin/")); - dirs.add(new File(System.getProperty("user.home", "."), "bin/")); - return dirs; - } - - private List getNestedSourceLocationOnUnix() { - List dirs = new ArrayList(); - dirs.add(new File("/usr/local/share")); - dirs.add(new File("/usr/local")); - dirs.add(new File("/usr/share")); - return dirs; - } - - /** - * 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. - */ - @Override - public void findIdes(List locations, List problems) { - switch (getOS()) { - case WINDOWS: - new WindowsFinder().findEclipse(locations, problems); - break; - case MAC_OS_X: - new MacFinder().findEclipse(locations, problems); - break; - default: - case UNIX: - new UnixFinder().findEclipse(locations, problems); - break; - } - } - - private class UnixFinder extends DirectoryFinder { - UnixFinder() { - super(getNestedSourceLocationOnUnix(), getFlatSourceLocationsOnUnix()); - } - - @Override protected String findEclipseOnPlatform(File dir) { - File possible = new File(dir, getUnixExecutableName()); - return (possible.exists()) ? possible.getAbsolutePath() : null; - } - } - - private class WindowsFinder extends DirectoryFinder { - WindowsFinder() { - super(transformToFiles(getSourceDirsOnWindowsWithDriveLetters()), Collections.emptyList()); - } - - /** Checks if the provided directory contains 'eclipse.exe', and if so, returns the directory, otherwise null. */ - @Override - protected String findEclipseOnPlatform(File dir) { - File possible = new File(dir, getWindowsExecutableName()); - return (possible.isFile()) ? dir.getAbsolutePath() : null; - } - } - - private class MacFinder extends DirectoryFinder { - MacFinder() { - super(transformToFiles(getSourceDirsOnMac()), Collections.emptyList()); - } - - protected String findEclipseOnPlatform(File dir) { - if (dir.getName().toLowerCase().equals(getMacExecutableName().toLowerCase())) return dir.getParent(); - if (dir.getName().toLowerCase().contains(getDirName())) { - if (new File(dir, getMacExecutableName()).exists()) return dir.toString(); - } - return null; - } - } - - private abstract class DirectoryFinder { - private final List flatSourceDirs; - private final List nestedSourceDirs; - - DirectoryFinder(List nestedSourceDirs, List flatSourceDirs) { - this.nestedSourceDirs = nestedSourceDirs; - this.flatSourceDirs = flatSourceDirs; - } - - public void findEclipse(List locations, List problems) { - for (File dir : nestedSourceDirs) recurseDirectory(locations, problems, dir); - for (File dir : flatSourceDirs) findEclipse(locations, problems, dir); - } - - protected abstract String findEclipseOnPlatform(File dir); - - protected void recurseDirectory(List locations, List problems, File dir) { - recurseDirectory0(locations, problems, dir, 0); - } - - private void recurseDirectory0(List locations, List problems, File f, int loopCounter) { - //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. - File[] listFiles = f.listFiles(); - if (listFiles == null) return; - - for (File dir : listFiles) { - if (!dir.isDirectory()) continue; - try { - if (dir.getName().toLowerCase().contains(getDirName())) { - findEclipse(locations, problems, dir); - if (loopCounter < 50) recurseDirectory0(locations, problems, dir, loopCounter + 1); - } - } catch (Exception ignore) {} - } - } - - private void findEclipse(List locations, List problems, File dir) { - String eclipseLocation = findEclipseOnPlatform(dir); - if (eclipseLocation != null) { - try { - IdeLocation newLocation = createLocation(eclipseLocation); - if (newLocation != null) locations.add(newLocation); - } catch (CorruptedIdeLocationException e) { - problems.add(e); - } - } - } - } -} diff --git a/src/installer/lombok/installer/eclipse/EclipseLocation.java b/src/installer/lombok/installer/eclipse/EclipseLocation.java deleted file mode 100644 index 6c63c48d..00000000 --- a/src/installer/lombok/installer/eclipse/EclipseLocation.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2009-2012 The Project Lombok Authors. - * - * 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.eclipse; - -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.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import lombok.installer.CorruptedIdeLocationException; -import lombok.installer.IdeFinder; -import lombok.installer.IdeLocation; -import lombok.installer.InstallException; -import lombok.installer.Installer; -import lombok.installer.UninstallException; - -/** - * 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. - */ -public class EclipseLocation extends IdeLocation { - private final String name; - private final File eclipseIniPath; - private final String pathToLombokJarPrefix; - private volatile boolean hasLombok; - - private static final String OS_NEWLINE = IdeFinder.getOS().getLineEnding(); - - protected String getTypeName() { - return "eclipse"; - } - - protected String getIniFileName() { - return "eclipse.ini"; - } - - EclipseLocation(String nameOfLocation, File pathToEclipseIni) throws CorruptedIdeLocationException { - this.name = nameOfLocation; - this.eclipseIniPath = pathToEclipseIni; - File p1 = pathToEclipseIni.getParentFile(); - File p2 = p1 == null ? null : p1.getParentFile(); - File p3 = p2 == null ? null : p2.getParentFile(); - if (p1 != null && p1.getName().equals("Eclipse") && p2 != null && p2.getName().equals("Contents") && p3 != null && p3.getName().endsWith(".app")) { - this.pathToLombokJarPrefix = "../Eclipse/"; - } else { - this.pathToLombokJarPrefix = ""; - } - - try { - this.hasLombok = checkForLombok(eclipseIniPath); - } catch (IOException e) { - throw new CorruptedIdeLocationException( - "I can't read the configuration file of the " + getTypeName() + " installed at " + name + "\n" + - "You may need to run this installer with root privileges if you want to modify that " + getTypeName() + ".", getTypeName(), e); - } - } - - @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. - */ - @Override - public String getName() { - return name; - } - - /** - * @return true if the Eclipse installation has been instrumented with lombok. - */ - @Override - public 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()) { - br.close(); - return true; - } - } - - br.close(); - return false; - } finally { - fis.close(); - } - } - - /** Returns directories that may contain lombok.jar files that need to be deleted. */ - private List getUninstallDirs() { - List result = new ArrayList(); - 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. - */ - @Override - public void uninstall() throws UninstallException { - final List lombokJarsForWhichCantDeleteSelf = new ArrayList(); - 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); - } - br.close(); - } 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); - } - } - - for (File dir : getUninstallDirs()) { - File lombokJar = new File(dir, "lombok.jar"); - if (lombokJar.exists()) { - if (!lombokJar.delete()) { - if (IdeFinder.getOS() == IdeFinder.OS.WINDOWS && Installer.isSelf(lombokJar.getAbsolutePath())) { - lombokJarsForWhichCantDeleteSelf.add(lombokJar); - } else { - 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()) { - agentJar.delete(); - } - } - } - - if (!lombokJarsForWhichCantDeleteSelf.isEmpty()) { - throw new UninstallException(true, String.format( - "lombok.jar cannot delete itself on windows.\nHowever, lombok has been uncoupled from your %s.\n" + - "You can safely delete this jar file. You can find it at:\n%s", - getTypeName(), lombokJarsForWhichCantDeleteSelf.get(0).getAbsolutePath()), null); - } - } - - private static String generateWriteErrorMessage() { - String osSpecificError; - - switch (IdeFinder.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. - */ - @Override - public String 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 = IdeFinder.getOS() == EclipseFinder.OS.UNIX || System.getProperty("lombok.installer.fullpath") != null; - - boolean installSucceeded = false; - StringBuilder newContents = new StringBuilder(); - - File lombokJar = new File(eclipseIniPath.getParentFile(), "lombok.jar"); - - /* No need to copy lombok.jar to itself, obviously. On windows this would generate an error so we check for this. */ - if (!Installer.isSelf(lombokJar.getAbsolutePath())) { - File ourJar = 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 " + getTypeName() + " 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); - } - br.close(); - } finally { - fis.close(); - } - - String pathPrefix; - if (fullPathRequired) { - pathPrefix = lombokJar.getParentFile().getCanonicalPath() + File.separator; - } else { - pathPrefix = pathToLombokJarPrefix; - } - - newContents.append(String.format( - "-javaagent:%s", escapePath(pathPrefix + "lombok.jar"))).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 " + getIniFileName() + " file. Is this a real " + getTypeName() + " installation?", null); - } - - return "If you start " + getTypeName() + " with a custom -vm parameter, you'll need to add:
" + - "-vmargs -javaagent:lombok.jar
as parameter as well."; - } - - @Override public URL getIdeIcon() { - return EclipseLocation.class.getResource("eclipse.png"); - } -} diff --git a/src/installer/lombok/installer/eclipse/EclipseLocationProvider.java b/src/installer/lombok/installer/eclipse/EclipseLocationProvider.java index 29716a1f..fa2ce958 100644 --- a/src/installer/lombok/installer/eclipse/EclipseLocationProvider.java +++ b/src/installer/lombok/installer/eclipse/EclipseLocationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011 The Project Lombok Authors. + * Copyright (C) 2009-2016 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,145 +21,24 @@ */ package lombok.installer.eclipse; -import static lombok.installer.IdeLocation.canonical; +import java.util.Collections; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.regex.Pattern; - -import lombok.installer.IdeLocation; import lombok.installer.IdeLocationProvider; -import lombok.installer.CorruptedIdeLocationException; -import lombok.installer.IdeFinder.OS; import org.mangosdk.spi.ProviderFor; @ProviderFor(IdeLocationProvider.class) -public class EclipseLocationProvider implements IdeLocationProvider { - @Override public IdeLocation create(String path) throws CorruptedIdeLocationException { - return create0(path); - } - - protected List getEclipseExecutableNames() { - return Arrays.asList("eclipse.app", "eclipse.exe", "eclipse"); - } - - protected String getIniName() { - return "eclipse.ini"; - } - - protected IdeLocation makeLocation(String name, File ini) throws CorruptedIdeLocationException { - return new EclipseLocation(name, ini); - } - - protected String getMacAppName() { - return "Eclipse.app"; - } - - protected String getUnixAppName() { - return "eclipse"; - } - - /** - * Create a new EclipseLocation by pointing at either the directory contains the Eclipse executable, or the executable itself, - * or an eclipse.ini file. - * - * @throws NotAnIdeLocationException - * If this isn't an Eclipse executable or a directory with an - * Eclipse executable. - */ - protected IdeLocation create0(String path) throws CorruptedIdeLocationException { - if (path == null) throw new NullPointerException("path"); - File p = new File(path); - - if (!p.exists()) return null; - if (p.isDirectory()) { - for (String possibleExeName : getEclipseExecutableNames()) { - File f = new File(p, possibleExeName); - if (f.exists()) return findEclipseIniFromExe(f, 0); - } - - File f = new File(p, getIniName()); - if (f.exists()) return new EclipseLocation(canonical(p), f); - } - - if (p.isFile()) { - if (p.getName().equalsIgnoreCase(getIniName())) { - return new EclipseLocation(canonical(p.getParentFile()), p); - } - } - - if (getEclipseExecutableNames().contains(p.getName().toLowerCase())) { - return findEclipseIniFromExe(p, 0); - } - - return null; - } - - private IdeLocation findEclipseIniFromExe(File exePath, int loopCounter) throws CorruptedIdeLocationException { - /* Try looking for eclipse.ini as sibling to the executable */ { - File ini = new File(exePath.getParentFile(), getIniName()); - if (ini.isFile()) return makeLocation(canonical(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(), getMacAppName() + "/Contents/MacOS/" + getIniName()); - if (ini.isFile()) return makeLocation(canonical(exePath), ini); - } - - /* Starting with Eclipse Mars (with the oomph installer), the structure has changed, and it's now at Eclipse.app/Contents/Eclipse/eclipse.ini*/ { - File ini = new File(exePath.getParentFile(), getMacAppName() + "/Contents/Eclipse/" + getIniName()); - if (ini.isFile()) return makeLocation(canonical(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 { - IdeLocation loc = findEclipseIniFromExe(new File(nPath), loopCounter + 1); - if (loc != null) return loc; - } catch (CorruptedIdeLocationException 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/" + getUnixAppName()) || path.equals("/bin/" + getUnixAppName()) || path.equals("/usr/local/bin/" + getUnixAppName())) { - File ini = new File("/usr/lib/" + getUnixAppName() + "/" + getIniName()); - if (ini.isFile()) return makeLocation(path, ini); - ini = new File("/usr/local/lib/" + getUnixAppName() + "/" + getIniName()); - if (ini.isFile()) return makeLocation(path, ini); - ini = new File("/usr/local/etc/" + getUnixAppName() + "/" + getIniName()); - if (ini.isFile()) return makeLocation(path, ini); - ini = new File("/etc/" + getIniName()); - if (ini.isFile()) return makeLocation(path, ini); - } - } - - /* If we get this far, we lose. */ - return null; - } - - @Override public Pattern getLocationSelectors(OS os) { - switch (os) { - case MAC_OS_X: - return Pattern.compile("^(eclipse|eclipse\\.ini|eclipse\\.app)$", Pattern.CASE_INSENSITIVE); - case WINDOWS: - return Pattern.compile("^(eclipse\\.exe|eclipse\\.ini)$", Pattern.CASE_INSENSITIVE); - default: - case UNIX: - return Pattern.compile("^(eclipse|eclipse\\.ini)$", Pattern.CASE_INSENSITIVE); - } +public class EclipseLocationProvider extends EclipseProductLocationProvider { + + private static final EclipseProductDescriptor ECLIPSE = new StandardProductDescriptor( + "Eclipse", + "eclipse", + "eclipse", + EclipseLocationProvider.class.getResource("eclipse.png"), + Collections.emptySet() + ); + + public EclipseLocationProvider() { + super(ECLIPSE); } } diff --git a/src/installer/lombok/installer/eclipse/EclipseProductDescriptor.java b/src/installer/lombok/installer/eclipse/EclipseProductDescriptor.java new file mode 100644 index 00000000..8f736a57 --- /dev/null +++ b/src/installer/lombok/installer/eclipse/EclipseProductDescriptor.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 The Project Lombok Authors. + * + * 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.eclipse; + +import java.net.URL; +import java.util.List; +import java.util.regex.Pattern; + +public interface EclipseProductDescriptor { + String getProductName(); + String getWindowsExecutableName(); + String getUnixAppName(); + String getMacAppName(); + String getDirectoryName(); + List getExecutableNames(); + List getSourceDirsOnWindows(); + List getSourceDirsOnMac(); + List getSourceDirsOnUnix(); + String getIniFileName(); + Pattern getLocationSelectors(); + URL getIdeIcon(); +} \ No newline at end of file diff --git a/src/installer/lombok/installer/eclipse/EclipseProductLocation.java b/src/installer/lombok/installer/eclipse/EclipseProductLocation.java new file mode 100644 index 00000000..886e3e85 --- /dev/null +++ b/src/installer/lombok/installer/eclipse/EclipseProductLocation.java @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2009-2016 The Project Lombok Authors. + * + * 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.eclipse; + +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.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import lombok.installer.CorruptedIdeLocationException; +import lombok.installer.OsUtils; +import lombok.installer.IdeLocation; +import lombok.installer.InstallException; +import lombok.installer.Installer; +import lombok.installer.UninstallException; + +/** + * 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. + */ +public final class EclipseProductLocation extends IdeLocation { + + private static final String OS_NEWLINE = OsUtils.getOS().getLineEnding(); + + private final EclipseProductDescriptor descriptor; + private final String name; + private final File eclipseIniPath; + private final String pathToLombokJarPrefix; + private final boolean hasLombok; + + EclipseProductLocation(EclipseProductDescriptor descriptor, String nameOfLocation, File pathToEclipseIni) throws CorruptedIdeLocationException { + this.descriptor = descriptor; + this.name = nameOfLocation; + this.eclipseIniPath = pathToEclipseIni; + File p1 = pathToEclipseIni.getParentFile(); + File p2 = p1 == null ? null : p1.getParentFile(); + File p3 = p2 == null ? null : p2.getParentFile(); + if (p1 != null && p1.getName().equals("Eclipse") && p2 != null && p2.getName().equals("Contents") && p3 != null && p3.getName().endsWith(".app")) { + this.pathToLombokJarPrefix = "../Eclipse/"; + } else { + this.pathToLombokJarPrefix = ""; + } + + try { + this.hasLombok = checkForLombok(eclipseIniPath); + } catch (IOException e) { + throw new CorruptedIdeLocationException( + "I can't read the configuration file of the " + descriptor.getProductName() + " installed at " + name + "\n" + + "You may need to run this installer with root privileges if you want to modify that " + descriptor.getProductName() + ".", descriptor.getProductName(), e); + } + } + + @Override public int hashCode() { + return eclipseIniPath.hashCode(); + } + + @Override public boolean equals(Object o) { + if (!(o instanceof EclipseProductLocation)) return false; + return ((EclipseProductLocation)o).eclipseIniPath.equals(eclipseIniPath); + } + + /** + * Returns the name of this location; generally the path to the eclipse executable. + */ + @Override + public String getName() { + return name; + } + + /** + * @return true if the Eclipse installation has been instrumen