Sebastian Stenzel 7 years ago
parent
commit
8c55946cf0

+ 4 - 7
main/launcher/src/main/java/org/cryptomator/launcher/FileOpenRequestHandler.java

@@ -13,7 +13,6 @@ import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.util.concurrent.BlockingQueue;
 
-import org.apache.commons.lang3.SystemUtils;
 import org.cryptomator.ui.util.EawtApplicationWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -25,13 +24,11 @@ class FileOpenRequestHandler {
 
 	public FileOpenRequestHandler(BlockingQueue<Path> fileOpenRequests) {
 		this.fileOpenRequests = fileOpenRequests;
-		if (SystemUtils.IS_OS_MAC_OSX) {
-			EawtApplicationWrapper.getApplication().ifPresent(app -> {
-				app.setOpenFileHandler(files -> {
-					files.stream().map(File::toPath).forEach(fileOpenRequests::add);
-				});
+		EawtApplicationWrapper.getApplication().ifPresent(app -> {
+			app.setOpenFileHandler(files -> {
+				files.stream().map(File::toPath).forEach(fileOpenRequests::add);
 			});
-		}
+		});
 	}
 
 	public void handleLaunchArgs(String[] args) {

+ 40 - 18
main/ui/src/main/java/org/cryptomator/ui/util/EawtApplicationWrapper.java

@@ -12,7 +12,10 @@ import java.lang.reflect.Proxy;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Consumer;
+import java.util.function.Function;
 
+import org.apache.commons.lang3.SystemUtils;
+import org.cryptomator.common.SupplierThrowingException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -31,7 +34,13 @@ public class EawtApplicationWrapper {
 		this.application = applicationClass.getMethod("getApplication").invoke(null);
 	}
 
+	/**
+	 * @return A wrapper for com.apple.ewat.Application if the current OS is macOS and the class is available in this JVM.
+	 */
 	public static Optional<EawtApplicationWrapper> getApplication() {
+		if (!SystemUtils.IS_OS_MAC_OSX) {
+			return Optional.empty();
+		}
 		try {
 			return Optional.of(new EawtApplicationWrapper());
 		} catch (ReflectiveOperationException e) {
@@ -50,15 +59,12 @@ public class EawtApplicationWrapper {
 		try {
 			Class<?> openFilesEventClass = Class.forName("com.apple.eawt.AppEvent$OpenFilesEvent");
 			Method getFiles = openFilesEventClass.getMethod("getFiles");
-			setOpenFileHandler(newMethodSpecificInvocationHandler("openFiles", args -> {
-				try {
-					Object openFilesEvent = args[0];
-					@SuppressWarnings("unchecked")
-					List<File> files = (List<File>) getFiles.invoke(openFilesEvent);
-					handler.accept(files);
-				} catch (ReflectiveOperationException e) {
-					LOG.error("Error invoking openFileHandler.", e);
-				}
+			setOpenFileHandler(methodSpecificInvocationHandler("openFiles", args -> {
+				Object openFilesEvent = args[0];
+				assert openFilesEventClass.isInstance(openFilesEvent);
+				@SuppressWarnings("unchecked")
+				List<File> files = (List<File>) uncheckedReflectiveOperation(() -> getFiles.invoke(openFilesEvent));
+				handler.accept(files);
 				return null;
 			}));
 		} catch (ReflectiveOperationException e) {
@@ -75,7 +81,7 @@ public class EawtApplicationWrapper {
 
 	public void setPreferencesHandler(Runnable handler) {
 		try {
-			setPreferencesHandler(newMethodSpecificInvocationHandler("handlePreferences", args -> {
+			setPreferencesHandler(methodSpecificInvocationHandler("handlePreferences", args -> {
 				handler.run();
 				return null;
 			}));
@@ -84,22 +90,38 @@ public class EawtApplicationWrapper {
 		}
 	}
 
-	@FunctionalInterface
-	private static interface MethodSpecificInvocationHandler {
-		Object invoke(Object[] args);
-	}
-
-	private static InvocationHandler newMethodSpecificInvocationHandler(String methodName, MethodSpecificInvocationHandler handler) {
+	private static InvocationHandler methodSpecificInvocationHandler(String methodName, Function<Object[], Object> handler) {
 		return new InvocationHandler() {
 			@Override
 			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 				if (method.getName().equals(methodName)) {
-					return handler.invoke(args);
+					return handler.apply(args);
 				} else {
-					return null;
+					throw new UnsupportedOperationException("Unexpected invocation " + method.getName() + ", expected " + methodName);
 				}
 			}
 		};
 	}
 
+	/**
+	 * Wraps {@link ReflectiveOperationException}s as {@link UncheckedReflectiveOperationException}.
+	 * 
+	 * @param operation Invokation throwing an ReflectiveOperationException
+	 * @return Result returned by <code>operation</code>
+	 * @throws UncheckedReflectiveOperationException in case <code>operation</code> throws an ReflectiveOperationException.
+	 */
+	private static <T> T uncheckedReflectiveOperation(SupplierThrowingException<T, ReflectiveOperationException> operation) throws UncheckedReflectiveOperationException {
+		try {
+			return operation.get();
+		} catch (ReflectiveOperationException e) {
+			throw new UncheckedReflectiveOperationException(e);
+		}
+	}
+
+	private static class UncheckedReflectiveOperationException extends RuntimeException {
+		public UncheckedReflectiveOperationException(ReflectiveOperationException cause) {
+			super(cause);
+		}
+	}
+
 }