diff options
Diffstat (limited to 'netx/net/sourceforge/jnlp/util')
-rw-r--r-- | netx/net/sourceforge/jnlp/util/FileUtils.java | 159 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/util/PropertiesFile.java | 146 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/util/Reflect.java | 146 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/util/WeakList.java | 126 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/util/XDesktopEntry.java | 213 |
5 files changed, 790 insertions, 0 deletions
diff --git a/netx/net/sourceforge/jnlp/util/FileUtils.java b/netx/net/sourceforge/jnlp/util/FileUtils.java new file mode 100644 index 0000000..aa1c316 --- /dev/null +++ b/netx/net/sourceforge/jnlp/util/FileUtils.java @@ -0,0 +1,159 @@ +// Copyright (C) 2009 Red Hat, Inc. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +package net.sourceforge.jnlp.util; + +import java.io.File; +import java.io.IOException; + +import net.sourceforge.jnlp.runtime.JNLPRuntime; + +/** + * This class contains a few file-related utility functions. + * + * @author Omair Majid + */ + +public final class FileUtils { + + /** + * list of characters not allowed in filenames + */ + private static final char INVALID_CHARS[] = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' }; + + private static final char SANITIZED_CHAR = '_'; + + /** + * Clean up a string by removing characters that can't appear in a local + * file name. + * + * @param path + * the path to sanitize + * @return a sanitized version of the input which is suitable for using as a + * file path + */ + public static String sanitizePath(String path) { + + for (int i = 0; i < INVALID_CHARS.length; i++) + if (INVALID_CHARS[i] != File.separatorChar) + if (-1 != path.indexOf(INVALID_CHARS[i])) + path = path.replace(INVALID_CHARS[i], SANITIZED_CHAR); + + return path; + } + + /** + * Given an input, return a sanitized form of the input suitable for use as + * a file/directory name + * + * @param input + * @return a sanitized version of the input + */ + public static String sanitizeFileName(String filename) { + + for (int i = 0; i < INVALID_CHARS.length; i++) + if (-1 != filename.indexOf(INVALID_CHARS[i])) + filename = filename.replace(INVALID_CHARS[i], SANITIZED_CHAR); + + return filename; + } + + /** + * Returns a String that is suitable for using in GUI elements for + * displaying (long) paths to users. + * + * @param path a path that should be shortened + * @return a shortened path suitable for displaying to the user + */ + public static String displayablePath(String path) { + final int DEFAULT_LENGTH = 40; + return displayablePath(path, DEFAULT_LENGTH); + } + + /** + * Return a String that is suitable for using in GUI elements for displaying + * paths to users. If the path is longer than visibleChars, it is truncated + * in a display-friendly way + * + * @param path a path that should be shorted + * @param visibleChars the maximum number of characters that path should fit + * into. Also the length of the returned string + * @return a shortened path that contains limited number of chars + */ + public static String displayablePath(String path, int visibleChars) { + /* + * use a very simple method: prefix + "..." + suffix + * + * where prefix is the beginning part of path (as much as we can squeeze in) + * and suffix is the end path of path + */ + + if (path == null || path.length() <= visibleChars) { + return path; + } + + final String OMITTED = "..."; + final int OMITTED_LENGTH = OMITTED.length(); + final int MIN_PREFIX_LENGTH = 4; + final int MIN_SUFFIX_LENGTH = 4; + /* + * we want to show things other than OMITTED. if we have too few for + * suffix and prefix, then just return as much as we can of the filename + */ + if (visibleChars < (OMITTED_LENGTH + MIN_PREFIX_LENGTH + MIN_SUFFIX_LENGTH)) { + return path.substring(path.length() - visibleChars); + } + + int affixLength = (visibleChars - OMITTED_LENGTH)/2; + String prefix = path.substring(0, affixLength); + String suffix = path.substring(path.length() - affixLength); + + return prefix + OMITTED + suffix; + } + + /** + * Recursively delete everything under a directory. Works on either files or + * directories + * + * @param file the file object representing what to delete. Can be either a + * file or a directory. + * @param base the directory under which the file and its subdirectories must be located + * @throws IOException on an io exception or if trying to delete something + * outside the base + */ + public static void recursiveDelete(File file, File base) throws IOException { + if (JNLPRuntime.isDebug()) { + System.err.println("Deleting: " + file); + } + + if (!(file.getCanonicalPath().startsWith(base.getCanonicalPath()))) { + throw new IOException("Trying to delete a file outside Netx's basedir: " + + file.getCanonicalPath()); + } + + if (file.isDirectory()) { + File[] children = file.listFiles(); + for (int i = 0; i < children.length; i++) { + recursiveDelete(children[i], base); + } + } + if (!file.delete()) { + throw new IOException("Unable to delete file: " + file); + } + + } + +} diff --git a/netx/net/sourceforge/jnlp/util/PropertiesFile.java b/netx/net/sourceforge/jnlp/util/PropertiesFile.java new file mode 100644 index 0000000..80a7ec2 --- /dev/null +++ b/netx/net/sourceforge/jnlp/util/PropertiesFile.java @@ -0,0 +1,146 @@ +// Copyright (C) 2001-2003 Jon A. Maxwell (JAM) +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +package net.sourceforge.jnlp.util; + +import java.io.*; +import java.net.*; +import java.util.*; + +import net.sourceforge.jnlp.*; + +/** + * A properties object backed by a specified file without throwing + * exceptions. The properties are automatically loaded from the + * file when the first property is requested, but the save method + * must be called before changes are saved to the file.<p> + * + * This class does not report IO exceptions.<p> + * + * @author <a href="mailto:[email protected]">Jon A. Maxwell (JAM)</a> - initial author + * @version $Revision: 1.4 $ + */ +public class PropertiesFile extends Properties { + + /** the file to save to */ + File file; + + /** the header string */ + String header = "netx file"; + + /** lazy loaded on getProperty */ + boolean loaded = false; + + + /** + * Create a properties object backed by the specified file. + * + * @param file the file to save and load to + */ + public PropertiesFile(File file) { + this.file = file; + } + + /** + * Create a properties object backed by the specified file. + * + * @param file the file to save and load to + * @param header the file header + */ + public PropertiesFile(File file, String header) { + this.file = file; + this.header = header; + } + + /** + * Returns the value of the specified key, or null if the key + * does not exist. + */ + public String getProperty(String key) { + if (!loaded) + load(); + + return super.getProperty(key); + } + + /** + * Returns the value of the specified key, or the default value + * if the key does not exist. + */ + public String getProperty(String key, String defaultValue) { + if (!loaded) + load(); + + return super.getProperty(key, defaultValue); + } + + /** + * Sets the value for the specified key. + * + * @return the previous value + */ + public Object setProperty(String key, String value) { + if (!loaded) + load(); + + return super.setProperty(key, value); + } + + /** + * Returns the file backing this properties object. + */ + public File getStoreFile() { + return file; + } + + /** + * Ensures that the file backing these properties has been + * loaded; call this method before calling any method defined by + * a superclass. + */ + public void load() { + loaded = true; + + try { + if (!file.exists()) + return; + + InputStream s = new FileInputStream(file); + load(s); + } + catch (IOException ex) { + // eat + } + } + + /** + * Saves the properties to the file. + */ + public void store() { + if (!loaded) + return; // nothing could have changed so save unnecessary load/save + + try { + OutputStream s = new FileOutputStream(file); + store(s, header); + } + catch (IOException ex) { + // eat + } + } + +} diff --git a/netx/net/sourceforge/jnlp/util/Reflect.java b/netx/net/sourceforge/jnlp/util/Reflect.java new file mode 100644 index 0000000..2b1301c --- /dev/null +++ b/netx/net/sourceforge/jnlp/util/Reflect.java @@ -0,0 +1,146 @@ +// Copyright (C) 2003 Jon A. Maxwell (JAM) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +package net.sourceforge.jnlp.util; + +import java.util.*; +import java.lang.reflect.*; + + +/** + * Provides simply, convenient methods to invoke methods by + * name. This class is used to consolidate reflection needed to + * access methods specific to Sun's JVM or to remain backward + * compatible while supporting method in newer JVMs.<p> + * + * Most methods of this class invoke the first method on the + * specified object that matches the name and number of + * parameters. The type of the parameters are not considered, so + * do not attempt to use this class to invoke overloaded + * methods.<p> + * + * Instances of this class are not synchronized.<p> + * + * @author <a href="mailto:[email protected]">Jon A. Maxwell (JAM)</a> - initial author + * @version $Revision: 1.1 $ + */ +public class Reflect { + + // todo: check non-null parameter types, try to send to proper + // method if overloaded ones exist on the target object + + // todo: optimize slightly using hashtable of Methods + + private boolean accessible; + + private static Object zero[] = new Object[0]; + + + /** + * Create a new Reflect instance. + */ + public Reflect() { + // + } + + /** + * Create a new Reflect instance. + * + * @param accessible whether to bypass access permissions + */ + public Reflect(boolean accessible) { + this.accessible = accessible; + } + + /** + * Invoke a zero-parameter static method by name. + */ + public Object invokeStatic(String className, String method) { + return invokeStatic(className, method, zero); + } + + /** + * Invoke the static method using the specified parameters. + */ + public Object invokeStatic(String className, String method, Object args[]) { + try { + Class c = Class.forName(className, true, Reflect.class.getClassLoader()); + + Method m = getMethod(c, method, args); + if (m.isAccessible() != accessible) + m.setAccessible(accessible); + + return m.invoke(null, args); + } + catch (Exception ex) { // eat + return null; + } + } + + /** + * Invoke a zero-parameter method by name on the specified + * object. + */ + public Object invoke(Object object, String method) { + return invoke(object, method, zero); + } + + /** + * Invoke a method by name with the specified parameters. + * + * @return the result of the method, or null on exception. + */ + public Object invoke(Object object, String method, Object args[]) { + try { + Method m = getMethod(object.getClass(), method, args); + if (m.isAccessible() != accessible) + m.setAccessible(accessible); + + return m.invoke(object, args); + } + catch (Exception ex) { // eat + ex.printStackTrace(); + return null; + } + } + + /** + * Return the Method matching the specified name and number of + * arguments. + */ + public Method getMethod(Class type, String method, Object args[]) { + try { + for (Class c = type; c != null; c = c.getSuperclass()) { + Method methods[] = c.getMethods(); + + for (int i=0; i < methods.length; i++) { + if (methods[i].getName().equals(method)) { + Class parameters[] = methods[i].getParameterTypes(); + + if (parameters.length == args.length) + return methods[i]; + } + } + } + } + catch (Exception ex) { // eat + ex.printStackTrace(); + } + + return null; + } + +} diff --git a/netx/net/sourceforge/jnlp/util/WeakList.java b/netx/net/sourceforge/jnlp/util/WeakList.java new file mode 100644 index 0000000..b8b205e --- /dev/null +++ b/netx/net/sourceforge/jnlp/util/WeakList.java @@ -0,0 +1,126 @@ +// Copyright (C) 2002-2003 Jon A. Maxwell (JAM) +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +package net.sourceforge.jnlp.util; + +import java.lang.ref.*; +import java.util.*; + + +/** + * This list stores objects automatically using weak references. + * Objects are added and removed from the list as normal, but may + * turn to null at any point (ie, indexOf(x) followed by get(x) + * may return null). The weak references are only removed when + * the trimToSize method is called so that the indices remain + * constant otherwise.<p> + * + * @author <a href="mailto:[email protected]">Jon A. Maxwell (JAM)</a> - initial author + * @version $Revision: 1.3 $ + */ +public class WeakList extends AbstractList { + + /* list of weak references */ + private ArrayList refs = new ArrayList(); + + + /** + * Create a weak random-access list. + */ + public WeakList() { + } + + /** + * Extract the hard reference out of a weak reference. + */ + private Object deref(Object o) { + if (o != null && o instanceof WeakReference) + return ((WeakReference)o).get(); + else + return null; + } + + /** + * Returns the object at the specified index, or null if the + * object has been collected. + */ + public Object get(int index) { + return deref(refs.get(index)); + } + + /** + * Returns the size of the list, including already collected + * objects. + */ + public int size() { + return refs.size(); + } + + /** + * Sets the object at the specified position and returns the + * previous object at that position or null if it was already + * collected. + */ + public Object set(int index, Object element) { + return deref(refs.set(index, new WeakReference(element))); + } + + /** + * Inserts the object at the specified position in the list. + * Automatically creates a weak reference to the object. + */ + public void add(int index, Object element) { + refs.add(index, new WeakReference(element)); + } + + /** + * Removes the object at the specified position and returns it + * or returns null if it was already collected. + */ + public Object remove(int index) { + return deref(refs.remove(index)); + } + + /** + * Returns a list of hard references to the objects. The + * returned list does not include the collected elements, so its + * indices do not necessarily correlate with those of this list. + */ + public List hardList() { + List result = new ArrayList(); + + for (int i=0; i < size(); i++) { + Object tmp = get(i); + + if (tmp != null) + result.add(tmp); + } + + return result; + } + + /** + * Compacts the list by removing references to collected + * objects. + */ + public void trimToSize() { + for (int i=size(); i-->0;) + if (get(i)==null) + remove(i); + } + +} diff --git a/netx/net/sourceforge/jnlp/util/XDesktopEntry.java b/netx/net/sourceforge/jnlp/util/XDesktopEntry.java new file mode 100644 index 0000000..8527fed --- /dev/null +++ b/netx/net/sourceforge/jnlp/util/XDesktopEntry.java @@ -0,0 +1,213 @@ +// Copyright (C) 2009 Red Hat, Inc. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +package net.sourceforge.jnlp.util; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.StringReader; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Arrays; + +import net.sourceforge.jnlp.IconDesc; +import net.sourceforge.jnlp.JNLPFile; +import net.sourceforge.jnlp.StreamEater; +import net.sourceforge.jnlp.cache.CacheUtil; +import net.sourceforge.jnlp.cache.UpdatePolicy; +import net.sourceforge.jnlp.runtime.JNLPRuntime; + +/** + * This class builds a (freedesktop.org) desktop entry out of a {@link JNLPFile} + * . This entry can be used to install desktop shortcuts. See xdg-desktop-icon + * (1) and http://standards.freedesktop.org/desktop-entry-spec/latest/ for more + * information + * + * @author Omair Majid + * + */ +public class XDesktopEntry { + + public static final String JAVA_ICON_NAME = "java.png"; + + private JNLPFile file = null; + private int iconSize = -1; + private String iconLocation = null; + + private int[] VALID_ICON_SIZES = new int[] { 16, 22, 32, 48, 64, 128 }; + + /** + * Create a XDesktopEntry for the given JNLP file + * + * @param file a {@link JNLPFile} that indicates the application to launch + */ + public XDesktopEntry(JNLPFile file) { + this.file = file; + + /* looks like a good initial value */ + iconSize = VALID_ICON_SIZES[2]; + } + + /** + * Returns the contents of the {@link XDesktopEntry} through the + * {@link Reader} interface. + */ + public Reader getContentsAsReader() { + + String pathToJavaws = System.getProperty("java.home") + File.separator + "bin" + + File.separator + "javaws"; + File cacheFile = CacheUtil.urlToPath(file.getSourceLocation(), "cache"); + + String fileContents = "[Desktop Entry]\n"; + fileContents += "Version=1.0\n"; + fileContents += "Name=" + file.getTitle() + "\n"; + fileContents += "GenericName=Java Web Start Application\n"; + fileContents += "Comment=" + file.getInformation().getDescription() + "\n"; + fileContents += "Type=Application\n"; + if (iconLocation != null) { + fileContents += "Icon=" + iconLocation + "\n"; + } else { + fileContents += "Icon=" + JAVA_ICON_NAME + "\n"; + + } + if (file.getInformation().getVendor() != null) { + fileContents += "Vendor=" + file.getInformation().getVendor() + "\n"; + } + + //Shortcut executes the jnlp from cache and system preferred java.. + fileContents += "Exec=" + "javaws" + " \"" + cacheFile.getAbsolutePath() + "\"\n"; + + return new StringReader(fileContents); + + } + + /** + * Get the size of the icon (in pixels) for the desktop shortcut + */ + public int getIconSize() { + return iconSize; + } + + /** + * Set the icon size to use for the desktop shortcut + * + * @param size the size (in pixels) of the icon to use. Commonly used sizes + * are of 16, 22, 32, 48, 64 and 128 + */ + public void setIconSize(int size) { + iconSize = size; + } + + /** + * Create a desktop shortcut for this desktop entry + */ + public void createDesktopShortcut() { + try { + cacheIcon(); + installDesktopLauncher(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Install this XDesktopEntry into the user's desktop as a launcher + */ + private void installDesktopLauncher() { + File shortcutFile = new File(JNLPRuntime.TMP_DIR + File.separator + + FileUtils.sanitizeFileName(file.getTitle()) + ".desktop"); + try { + + /* + * Write out a Java String (UTF-16) as a UTF-8 file + */ + + OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(shortcutFile), + Charset.forName("UTF-8")); + Reader reader = getContentsAsReader(); + + char[] buffer = new char[1024]; + int ret = 0; + while (-1 != (ret = reader.read(buffer))) { + writer.write(buffer, 0, ret); + } + + reader.close(); + writer.close(); + + /* + * Install the desktop entry + */ + + String[] execString = new String[] { "xdg-desktop-icon", "install", "--novendor", + shortcutFile.getCanonicalPath() }; + if (JNLPRuntime.isDebug()) { + System.err.println("Execing: " + Arrays.toString(execString)); + } + Process installer = Runtime.getRuntime().exec(execString); + new StreamEater(installer.getInputStream()).start(); + new StreamEater(installer.getErrorStream()).start(); + + try { + installer.waitFor(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (!shortcutFile.delete()) { + throw new IOException("Unable to delete temporary file:" + shortcutFile); + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Cache the icon for the desktop entry + */ + private void cacheIcon() { + + URL iconLocation = file.getInformation().getIconLocation(IconDesc.SHORTCUT, iconSize, + iconSize); + + if (iconLocation == null) { + iconLocation = file.getInformation().getIconLocation(IconDesc.DEFAULT, iconSize, + iconSize); + } + + if (iconLocation != null) { + String location = CacheUtil.getCachedResource(iconLocation, null, UpdatePolicy.SESSION) + .toString(); + if (!location.startsWith("file:")) { + throw new RuntimeException("Unable to cache icon"); + } + + this.iconLocation = location.substring("file:".length()); + + if (JNLPRuntime.isDebug()) { + System.err.println("Cached desktop shortcut icon: " + this.iconLocation); + } + } + } + +} |