package org.freeplane.core.util; import java.awt.Window; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import java.util.HashSet; import java.util.Locale; import java.util.Properties; import java.util.Set; import javax.swing.JFrame; import org.freeplane.core.resources.ResourceController; import org.freeplane.core.ui.MenuBuilder; import org.freeplane.features.mode.Controller; /** * Provides methods and constants which are dependend on the underlying java version * * @author robert.ladstaetter */ public class Compat { public static final String JAVA_VERSION = System.getProperty("java.version"); public static final String VERSION_1_6_0 = "1.6.0"; private static enum OS { MAC, WINDOWS, OTHER }; private static OS os = null; public static final Set<String> executableExtensions = new HashSet<String>(Arrays.asList(new String[] { "exe", "com", "vbs", "bat", "lnk", "cmd" })); public static boolean isWindowsExecutable(final URI link) { if (link == null || !"file".equalsIgnoreCase(link.getScheme())) { return false; } return isWindowsOS() && executableExtensions.contains(FileUtils.getExtension(link.toString())); } public static URL fileToUrl(final File pFile) throws MalformedURLException { return pFile.toURI().toURL(); } public static boolean isLowerJdk(final String version) { return JAVA_VERSION.compareTo(version) < 0; } public static boolean isMacOsX() { Compat.initOS(); return os.equals(OS.MAC); } private static void initOS() { if (os == null) { String osProperty; try { osProperty = System.getProperty("os.name"); } catch (final SecurityException e) { osProperty = ""; } String debugOsName; try { debugOsName = System.getProperty("freeplane.debug.os.name", ""); } catch (final SecurityException e) { debugOsName = ""; } if (osProperty.startsWith("Mac OS") || debugOsName.startsWith("Mac")) { os = OS.MAC; return; } if (osProperty.startsWith("Windows") || debugOsName.startsWith("Windows")) { os = OS.WINDOWS; return; } os = OS.OTHER; } } public static boolean isWindowsOS() { Compat.initOS(); return os.equals(OS.WINDOWS); } /** * This is a correction of a method getFile of a class URL. Namely, on * Windows it returned file paths like /C: etc., which are not valid on * Windows. This correction is heuristic to a great extend. One of the * reasons is that file: something every browser and every system uses * slightly differently. */ private static String urlGetFile(final URL url) { if( !url.getProtocol().equals("file")) return null; //DOCEAR - decode url before use it as a string String fileName = sun.net.www.ParseUtil.decode(url.toString()).replaceFirst("^file:", ""); final String osNameStart = System.getProperty("os.name").substring(0, 3); if (osNameStart.equals("Win") && url.getProtocol().equals("file")) { fileName = fileName.replace('/', File.separatorChar); return (fileName.indexOf(':') >= 0) ? fileName.replaceFirst("^\\\\*", "") : fileName; } else { return fileName; } } public static File urlToFile(final URL pUrl) throws URISyntaxException { final String path = Compat.urlGetFile(pUrl); if(path != null) return new File(path); else return null; } public static void macAppChanges() { if (!Compat.isMacOsX()) { return; } try { final Class<?> macChanges = Controller.class.getClassLoader().loadClass( "org.freeplane.plugin.macos.MacChanges"); final Method method = macChanges.getMethod("apply", Controller.class); method.invoke(null, Controller.getCurrentController()); } catch (final Exception e) { e.printStackTrace(); } } public static void macMenuChanges() { if (!Compat.isMacOsX()) { return; } final Controller controller = Controller.getCurrentController(); final Set<String> modes = controller .getModes(); for (final String mode : modes) { final MenuBuilder builder = controller.getModeController(mode).getUserInputListenerFactory() .getMenuBuilder(); final String[] keys = { "MB_ToggleMenubarAction", "MP_ToggleMenubarAction", "MB_QuitAction", "MB_PropertyAction", "MB_AboutAction" }; for (final String key : keys) { if (builder.contains(key)) { builder.removeElement(key); } } } } final private static String PREVIEW_DIR=File.separatorChar + "1.2.x"; public static String getFreeplaneUserDirectory() { Properties freeplaneProperties = new Properties(); try { freeplaneProperties.load(Compat.class.getClassLoader().getResourceAsStream(ResourceController.FREEPLANE_PROPERTIES)); } catch (IOException e) { LogUtils.warn(e); } String applicationName = freeplaneProperties.getProperty("ApplicationName", "freeplane").toLowerCase(Locale.ENGLISH); String userFpDir = null; if(applicationName.equalsIgnoreCase("freeplane")){ userFpDir = System.getProperty("org.freeplane.userfpdir"); } else if(System.getProperty("org.freeplane.userfpdir") != null && System.getProperty("org.freeplane.userfpdir").endsWith("Data")){ userFpDir = System.getProperty("org.freeplane.userfpdir") + File.separator + freeplaneProperties.getProperty("ApplicationName", "Freeplane"); } else if(System.getenv("APPDATA") != null && System.getenv("APPDATA").length() > 0){ userFpDir = System.getenv("APPDATA") + File.separator + freeplaneProperties.getProperty("ApplicationName", "Freeplane"); } if(userFpDir == null){ userFpDir = System.getProperty("user.home")+ File.separator + "." + applicationName; } //DOCEAR: #121: do not use freeplane's version in path names if(PREVIEW_DIR != null && applicationName.equalsIgnoreCase("freeplane")) return userFpDir + PREVIEW_DIR; return userFpDir; } static public String smbUri2unc(final URI uri) { String uriString; uriString = ("//" + uri.getHost() + uri.getPath()) .replace('/', '\\'); final String fragment = uri.getFragment(); if(fragment != null) uriString = uriString + '#' + fragment; return uriString; } static public boolean isPlainEvent(final MouseEvent e) { final int modifiers = getModifiers(e); return modifiers == 0; } private static int getModifiers(final MouseEvent e) { return e.getModifiersEx() & (InputEvent.CTRL_DOWN_MASK | InputEvent.META_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK ); } static public boolean isCtrlEvent(final MouseEvent e) { return isExtendedCtrlEvent(e, 0); } public static boolean isCtrlShiftEvent(MouseEvent e) { return isExtendedCtrlEvent(e, InputEvent.SHIFT_DOWN_MASK); } public static boolean isCtrlAltEvent(MouseEvent e) { return isExtendedCtrlEvent(e, InputEvent.ALT_DOWN_MASK); } static private boolean isExtendedCtrlEvent(final MouseEvent e, int otherModifiers) { final int modifiers = getModifiers(e); if (isMacOsX()) return modifiers == (InputEvent.META_DOWN_MASK | otherModifiers); return modifiers == (InputEvent.CTRL_DOWN_MASK|otherModifiers); } public static boolean isShiftEvent(MouseEvent e) { final int modifiers = getModifiers(e); return modifiers == InputEvent.SHIFT_DOWN_MASK; } public static void macAppFullScreen(JFrame frame) { if (!isMacOsX()) return; try { Class<?> util = Class.forName("com.apple.eawt.FullScreenUtilities"); Class<?> params[] = new Class[]{Window.class, Boolean.TYPE}; Method method = util.getMethod("setWindowCanFullScreen", params); method.invoke(util, frame, true); } catch(ClassNotFoundException e) { } catch (Exception e) { LogUtils.warn("OS X Fullscreen FAIL", e); } } }