aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net/sourceforge/jnlp/services
diff options
context:
space:
mode:
Diffstat (limited to 'netx/net/sourceforge/jnlp/services')
-rw-r--r--netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java49
-rw-r--r--netx/net/sourceforge/jnlp/services/InstanceExistsException.java35
-rw-r--r--netx/net/sourceforge/jnlp/services/ServiceUtil.java293
-rw-r--r--netx/net/sourceforge/jnlp/services/SingleInstanceLock.java194
-rw-r--r--netx/net/sourceforge/jnlp/services/XBasicService.java232
-rw-r--r--netx/net/sourceforge/jnlp/services/XClipboardService.java81
-rw-r--r--netx/net/sourceforge/jnlp/services/XDownloadService.java179
-rw-r--r--netx/net/sourceforge/jnlp/services/XExtendedService.java56
-rw-r--r--netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java121
-rw-r--r--netx/net/sourceforge/jnlp/services/XFileContents.java121
-rw-r--r--netx/net/sourceforge/jnlp/services/XFileOpenService.java113
-rw-r--r--netx/net/sourceforge/jnlp/services/XFileSaveService.java140
-rw-r--r--netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java203
-rw-r--r--netx/net/sourceforge/jnlp/services/XPersistenceService.java177
-rw-r--r--netx/net/sourceforge/jnlp/services/XPrintService.java123
-rw-r--r--netx/net/sourceforge/jnlp/services/XServiceManagerStub.java106
-rw-r--r--netx/net/sourceforge/jnlp/services/XSingleInstanceService.java236
-rw-r--r--netx/net/sourceforge/jnlp/services/package.html29
18 files changed, 2488 insertions, 0 deletions
diff --git a/netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java b/netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java
new file mode 100644
index 0000000..c4b57b2
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java
@@ -0,0 +1,49 @@
+// 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.services;
+
+import javax.jnlp.SingleInstanceService;
+
+import net.sourceforge.jnlp.JNLPFile;
+
+/**
+ * Extends SingleInstanceService to provide a few additional methods that are
+ * required to initialize SingleInstanceService and check things. These methods
+ * are not exposed publicly
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ *
+ */
+interface ExtendedSingleInstanceService extends SingleInstanceService {
+
+ /**
+ * Check if the instance identified by this jnlp file is already running
+ *
+ * @param jnlpFile The JNLPFile that specifies the application
+ *
+ * @throws InstanceExistsException if an instance of this application
+ * already exists
+ *
+ */
+ void checkSingleInstanceRunning(JNLPFile jnlpFile);
+
+ /**
+ * Start a single instance service based on the current application
+ */
+ void initializeSingleInstance();
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/InstanceExistsException.java b/netx/net/sourceforge/jnlp/services/InstanceExistsException.java
new file mode 100644
index 0000000..5de2ff5
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/InstanceExistsException.java
@@ -0,0 +1,35 @@
+// 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.services;
+
+/**
+ *
+ * This class represents an exception indicating that an application instance
+ * already exists for this jnlp file
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ *
+ */
+public class InstanceExistsException extends RuntimeException {
+
+ private static final long serialVersionUID = 7950552292795498272L;
+
+ public InstanceExistsException(String message) {
+ super(message);
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/ServiceUtil.java b/netx/net/sourceforge/jnlp/services/ServiceUtil.java
new file mode 100644
index 0000000..b6f7682
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/ServiceUtil.java
@@ -0,0 +1,293 @@
+// 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.services;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import javax.jnlp.BasicService;
+import javax.jnlp.ClipboardService;
+import javax.jnlp.DownloadService;
+import javax.jnlp.ExtensionInstallerService;
+import javax.jnlp.FileOpenService;
+import javax.jnlp.FileSaveService;
+import javax.jnlp.PersistenceService;
+import javax.jnlp.PrintService;
+import javax.jnlp.ServiceManager;
+import javax.jnlp.SingleInstanceService;
+import javax.jnlp.UnavailableServiceException;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.runtime.ApplicationInstance;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.SecurityWarningDialog;
+
+/**
+ * Provides static methods to interact useful for using the JNLP
+ * services.<p>
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ * @version $Revision: 1.8 $
+ */
+public class ServiceUtil {
+
+ private static String R(String key) {
+ return JNLPRuntime.getMessage(key);
+ }
+
+ /**
+ * Returns the BasicService reference, or null if the service is
+ * unavailable.
+ */
+ public static BasicService getBasicService() {
+ return (BasicService) getService("javax.jnlp.BasicService");
+ }
+
+ /**
+ * Returns the ClipboardService reference, or null if the service is
+ * unavailable.
+ */
+ public static ClipboardService getClipboardService() {
+ return (ClipboardService) getService("javax.jnlp.ClipboardService");
+ }
+
+ /**
+ * Returns the DownloadService reference, or null if the service is
+ * unavailable.
+ */
+ public static DownloadService getDownloadService() {
+ return (DownloadService) getService("javax.jnlp.DownloadService");
+ }
+
+ /**
+ * Returns the ExtensionInstallerService reference, or null if the service is
+ * unavailable.
+ */
+ public static ExtensionInstallerService getExtensionInstallerService() {
+ return (ExtensionInstallerService) getService("javax.jnlp.ExtensionInstallerService");
+ }
+
+ /**
+ * Returns the FileOpenService reference, or null if the service is
+ * unavailable.
+ */
+ public static FileOpenService getFileOpenService() {
+ return (FileOpenService) getService("javax.jnlp.FileOpenService");
+ }
+
+ /**
+ * Returns the FileSaveService reference, or null if the service is
+ * unavailable.
+ */
+ public static FileSaveService getFileSaveService() {
+ return (FileSaveService) getService("javax.jnlp.FileSaveService");
+ }
+
+ /**
+ * Returns the PersistenceService reference, or null if the service is
+ * unavailable.
+ */
+ public static PersistenceService getPersistenceService() {
+ return (PersistenceService) getService("javax.jnlp.PersistenceService");
+ }
+
+ /**
+ * Returns the PrintService reference, or null if the service is
+ * unavailable.
+ */
+ public static PrintService getPrintService() {
+ return (PrintService) getService("javax.jnlp.PrintService");
+ }
+
+ /**
+ * Returns the SingleInstanceService reference, or null if the service is
+ * unavailable.
+ */
+ public static SingleInstanceService getSingleInstanceService() {
+ return (SingleInstanceService) getService("javax.jnlp.SingleInstanceService");
+ }
+
+ /**
+ * Checks that this application (represented by the jnlp) isnt already running
+ * @param jnlpFile the {@link JNLPFile} that specifies the application
+ *
+ * @throws InstanceExistsException if an instance of this application already exists
+ */
+ public static void checkExistingSingleInstance(JNLPFile jnlpFile) {
+ ExtendedSingleInstanceService esis = (ExtendedSingleInstanceService) getSingleInstanceService();
+ esis.checkSingleInstanceRunning(jnlpFile);
+ }
+
+ /**
+ * Returns the service, or null instead of an UnavailableServiceException
+ */
+ private static Object getService(String name) {
+ try {
+ return ServiceManager.lookup(name);
+ }
+ catch (UnavailableServiceException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * Creates a Proxy object implementing the specified interface
+ * when makes all calls in the security context of the system
+ * classes (ie, AllPermissions). This means that the services
+ * must be more than extremely careful in the operations they
+ * perform.
+ */
+ static Object createPrivilegedProxy(Class iface, final Object receiver) {
+ return java.lang.reflect.Proxy.newProxyInstance(XServiceManagerStub.class.getClassLoader(),
+ new Class[] { iface },
+ new PrivilegedHandler(receiver));
+ }
+
+ /**
+ * calls the object's method using privileged access
+ */
+ private static class PrivilegedHandler implements InvocationHandler {
+ private final Object receiver;
+
+ PrivilegedHandler(Object receiver) {
+ this.receiver = receiver;
+ }
+
+ public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
+ if (JNLPRuntime.isDebug()) {
+ System.err.println("call privileged method: "+method.getName());
+ if (args != null)
+ for (int i=0; i < args.length; i++)
+ System.err.println(" arg: "+args[i]);
+ }
+
+ PrivilegedExceptionAction invoker = new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return method.invoke(receiver, args);
+ }
+ };
+
+ try {
+ Object result = AccessController.doPrivileged(invoker);
+
+ if (JNLPRuntime.isDebug())
+ System.err.println(" result: "+result);
+
+ return result;
+ } catch (PrivilegedActionException e) {
+ // Any exceptions thrown by the actual methods are wrapped by a
+ // InvocationTargetException, which is further wrapped by the
+ // PrivilegedActionException. Lets unwrap them to make the
+ // proxy transparent to the callers
+ if (e.getCause() instanceof InvocationTargetException) {
+ throw e.getCause().getCause();
+ } else {
+ throw e.getCause();
+ }
+ }
+
+ }
+ };
+
+ /**
+ * Returns whether the app requesting a service is signed. If the app is
+ * unsigned, the user is prompted with a dialog asking if the action
+ * should be allowed.
+ * @param type the type of access being requested
+ * @param extras extra Strings (usually) that are passed to the dialog for
+ * message formatting.
+ * @return true if the access was granted, false otherwise.
+ */
+ public static boolean checkAccess(SecurityWarningDialog.AccessType type,
+ Object... extras) {
+ return checkAccess(null, type, extras);
+ }
+
+ /**
+ * Returns whether the app requesting a service has the right permissions.
+ * If it doesn't, user is prompted for permissions.
+ *
+ * @param app the application which is requesting the check. If null, the current
+ * application is used.
+ * @param type the type of access being requested
+ * @param extras extra Strings (usually) that are passed to the dialog for
+ * message formatting.
+ * @return true if the access was granted, false otherwise.
+ */
+ public static boolean checkAccess(ApplicationInstance app,
+ SecurityWarningDialog.AccessType type,
+ Object... extras) {
+
+ if (app == null)
+ app = JNLPRuntime.getApplication();
+
+ boolean codeTrusted = true;
+
+ StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+
+ for (int i=0; i < stack.length; i++) {
+
+ Class c = null;
+
+ try {
+ c = Class.forName(stack[i].getClassName());
+ } catch (Exception e1) {
+ try {
+ c = Class.forName(stack[i].getClassName(), false, app.getClassLoader());
+ } catch (Exception e2) {
+ System.err.println(e2.getMessage());
+ }
+ }
+
+ // Everything up to the desired class/method must be trusted
+ if (c == null || // class not found
+ ( c.getProtectionDomain().getCodeSource() != null && // class is not in bootclasspath
+ c.getProtectionDomain().getCodeSource().getCodeSigners() == null) // class is trusted
+ ) {
+ codeTrusted = false;
+ }
+ }
+
+ if (!codeTrusted) {
+ final SecurityWarningDialog.AccessType tmpType = type;
+ final Object[] tmpExtras = extras;
+ final ApplicationInstance tmpApp = app;
+
+ //We need to do this to allow proper icon loading for unsigned
+ //applets, otherwise permissions won't be granted to load icons
+ //from resources.jar.
+ Boolean b = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ boolean b = SecurityWarningDialog.showAccessWarningDialog(tmpType,
+ tmpApp.getJNLPFile(), tmpExtras);
+ return new Boolean(b);
+ }
+ });
+
+ return b.booleanValue();
+ }
+
+ return true; //allow
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java b/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java
new file mode 100644
index 0000000..5108642
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java
@@ -0,0 +1,194 @@
+// 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.services;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.BindException;
+import java.net.ServerSocket;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * This class represents a Lock for single instance jnlp applications
+ *
+ * The lock is per-session, per user.
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ */
+class SingleInstanceLock {
+
+ JNLPFile jnlpFile;
+ File lockFile = null;
+
+ public static final int INVALID_PORT = Integer.MIN_VALUE;
+
+ int port = INVALID_PORT;
+
+ /**
+ * Create an object to manage the instance lock for the specified JNLP file.
+ *
+ * @param jnlpFile the jnlpfile to create the lock for
+ */
+ public SingleInstanceLock(JNLPFile jnlpFile) {
+ this.jnlpFile = jnlpFile;
+ lockFile = getLockFile();
+
+ }
+
+ /**
+ * Create/overwrite the instance lock for the jnlp file.
+ *
+ * @param localPort the network port for the lock
+ * @throws IOException on any io problems
+ */
+ public void createWithPort(int localPort) throws IOException {
+
+ BufferedWriter lockFileWriter = new BufferedWriter(new FileWriter(lockFile, false));
+ lockFileWriter.write(String.valueOf(localPort));
+ lockFileWriter.newLine();
+ lockFileWriter.flush();
+ lockFileWriter.close();
+
+ }
+
+ /**
+ * Returns true if the lock if valid. That is, the lock exists, and port it
+ * points to is listening for incoming messages.
+ */
+ public boolean isValid() {
+ return (exists() && getPort() != INVALID_PORT && !isPortFree(getPort()));
+ }
+
+ /**
+ * Returns the port in this lock file.
+ */
+ public int getPort() {
+ if (!exists()) {
+ return INVALID_PORT;
+ }
+
+ try {
+ parseFile();
+ } catch (NumberFormatException e) {
+ port = INVALID_PORT;
+ } catch (IOException e) {
+ port = INVALID_PORT;
+ }
+ return port;
+
+ }
+
+ /**
+ * Returns true if the lock file already exists.
+ */
+ private boolean exists() {
+ return lockFile.exists();
+ }
+
+ /**
+ * Returns true if the port is free.
+ */
+ private boolean isPortFree(int port) {
+ try {
+ ServerSocket socket = new ServerSocket(port);
+ socket.close();
+ return true;
+ } catch (BindException e) {
+ return false;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Return a file object that represents the lock file. The lock file itself
+ * may or may not exist.
+ */
+ private File getLockFile() {
+ File baseDir = new File(JNLPRuntime.LOCKS_DIR);
+
+ if (!baseDir.isDirectory() && !baseDir.mkdirs()) {
+ throw new RuntimeException(R("RNoLockDir", baseDir));
+ }
+ String lockFileName = getLockFileName();
+ File applicationLockFile = new File(baseDir, lockFileName);
+ return applicationLockFile;
+ }
+
+ /**
+ * Returns the name of the lock file.
+ */
+ private String getLockFileName() {
+ String initialName = "";
+
+ if (jnlpFile.getSourceLocation() != null) {
+ initialName = initialName + jnlpFile.getSourceLocation();
+ } else {
+ initialName = initialName + jnlpFile.getFileLocation();
+ }
+
+ if (jnlpFile.getFileVersion() != null) {
+ initialName = initialName + jnlpFile.getFileVersion().toString();
+ }
+
+ initialName = initialName + getCurrentDisplay();
+ return FileUtils.sanitizeFileName(initialName);
+
+ }
+
+ /**
+ * Parse the lock file.
+ *
+ * @throws NumberFormatException
+ * @throws IOException
+ */
+ private void parseFile() throws NumberFormatException, IOException {
+ BufferedReader lockFileReader = new BufferedReader(new FileReader(lockFile));
+ int port = Integer.valueOf(lockFileReader.readLine());
+ lockFileReader.close();
+ this.port = port;
+ }
+
+ /**
+ * Returns a string identifying this display.
+ *
+ * Implementation note: On systems with X support, this is the DISPLAY
+ * variable
+ *
+ * @return a string that is guaranteed to be not null.
+ */
+ private String getCurrentDisplay() {
+ String display = System.getenv("DISPLAY");
+ return (display == null) ? "" : display;
+ }
+
+ private static String R(String key) {
+ return JNLPRuntime.getMessage(key);
+ }
+
+ private static String R(String key, Object param) {
+ return JNLPRuntime.getMessage(key, new Object[] { param });
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XBasicService.java b/netx/net/sourceforge/jnlp/services/XBasicService.java
new file mode 100644
index 0000000..a7ef906
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XBasicService.java
@@ -0,0 +1,232 @@
+// Copyright (C) 2001 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.services;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.jnlp.BasicService;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import net.sourceforge.jnlp.InformationDesc;
+import net.sourceforge.jnlp.JARDesc;
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.Launcher;
+import net.sourceforge.jnlp.runtime.ApplicationInstance;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.util.PropertiesFile;
+
+/**
+ * The BasicService JNLP service.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.10 $
+ */
+class XBasicService implements BasicService {
+
+ /** command used to exec the native browser */
+ private String command = null;
+
+ /** whether the command was loaded / prompted for */
+ private boolean initialized = false;
+
+
+ protected XBasicService() {
+ }
+
+ /**
+ * Returns the codebase of the application, applet, or
+ * installer. If the codebase was not specified in the JNLP
+ * element then the main JAR's location is returned. If no main
+ * JAR was specified then the location of the JAR containing the
+ * main class is returned.
+ */
+ public URL getCodeBase() {
+ ApplicationInstance app = JNLPRuntime.getApplication();
+
+ if (app != null) {
+ JNLPFile file = app.getJNLPFile();
+
+ // return the codebase.
+ if (file.getCodeBase() != null)
+ return file.getCodeBase();
+
+ // else return the main JAR's URL.
+ JARDesc mainJar = file.getResources().getMainJAR();
+ if (mainJar != null)
+ return mainJar.getLocation();
+
+ // else find JAR where main class was defined.
+ //
+ // JNLPFile file = app.getJNLPFile();
+ // String mainClass = file.getLaunchInfo().getMainClass()+".class";
+ // URL jarUrl = app.getClassLoader().getResource(mainClass);
+ // go through list of JARDesc to find one matching jarUrl
+ }
+
+ return null;
+ }
+
+ /**
+ * Return true if the Environment is Offline
+ */
+ public boolean isOffline() {
+
+ URL url = findFirstURLFromJNLPFile();
+
+ try {
+ url.openConnection().getInputStream().close();
+ return false;
+ } catch (IOException exception) {
+ return true;
+ }
+ }
+
+ /**
+ * Return the first URL from the jnlp file
+ * Or a default URL if no url found in JNLP file
+ */
+ private URL findFirstURLFromJNLPFile() {
+
+ ApplicationInstance app = JNLPRuntime.getApplication();
+
+ if (app != null) {
+ JNLPFile jnlpFile = app.getJNLPFile();
+
+ URL sourceURL = jnlpFile.getSourceLocation();
+ if (sourceURL != null) {
+ return sourceURL;
+ }
+
+ URL codeBaseURL = jnlpFile.getCodeBase();
+ if (codeBaseURL != null) {
+ return codeBaseURL;
+ }
+
+ InformationDesc informationDesc = jnlpFile.getInformation();
+ URL homePage = informationDesc.getHomepage();
+ if (homePage != null) {
+ return homePage;
+ }
+
+ JARDesc[] jarDescs = jnlpFile.getResources().getJARs();
+ for (JARDesc jarDesc: jarDescs) {
+ return jarDesc.getLocation();
+ }
+ }
+
+ // this section is only reached if the jnlp file has no jars.
+ // that doesnt seem very likely.
+ URL arbitraryURL;
+ try {
+ arbitraryURL = new URL("http://icedtea.classpath.org");
+ } catch (MalformedURLException malformedURL) {
+ throw new RuntimeException(malformedURL);
+ }
+
+ return arbitraryURL;
+ }
+
+ /**
+ * Return true if a Web Browser is Supported
+ */
+ public boolean isWebBrowserSupported() {
+ initialize();
+
+ return command != null;
+ }
+
+ /**
+ * Show a document.
+ *
+ * @return whether the document was opened
+ */
+ public boolean showDocument(URL url) {
+ initialize();
+
+ if (url.toString().endsWith(".jnlp")) {
+ try {
+ new Launcher().launchExternal(url);
+ return true;
+ }
+ catch (Exception ex) {
+ return false;
+ }
+ }
+
+ if (command != null) {
+ try {
+ // this is bogus because the command may require options;
+ // should use a StreamTokenizer or similar to get tokens
+ // outside of quotes.
+ Runtime.getRuntime().exec(command + " " + url.toString());
+ //Runtime.getRuntime().exec(new String[]{command,url.toString()});
+
+ return true;
+ }
+ catch(IOException ex){
+ if (JNLPRuntime.isDebug())
+ ex.printStackTrace();
+ }
+ }
+
+ return false;
+ }
+
+ private void initialize() {
+ if (initialized)
+ return;
+ initialized = true;
+
+ if(isWindows()) {
+ command = "rundll32 url.dll,FileProtocolHandler ";
+ }
+ else {
+ PropertiesFile props = JNLPRuntime.getProperties();
+ command = props.getProperty("browser.command");
+
+ if(command == null) { // prompt & store
+ command = promptForCommand(null);
+
+ if(command != null) {
+ props.setProperty("browser.command", command);
+ props.store();
+ }
+ }
+ }
+ }
+
+ private boolean isWindows() {
+ String os = System.getProperty("os.name");
+ if(os != null && os.startsWith("Windows"))
+ return true;
+ else
+ return false;
+ }
+
+ private String promptForCommand(String cmd) {
+ return JOptionPane.showInputDialog(new JPanel(),
+ "Browser Location:",
+ "Specify Browser Location",
+ JOptionPane.PLAIN_MESSAGE
+ );
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XClipboardService.java b/netx/net/sourceforge/jnlp/services/XClipboardService.java
new file mode 100644
index 0000000..860d859
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XClipboardService.java
@@ -0,0 +1,81 @@
+/* XClipboardService.java
+ Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea 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, version 2.
+
+IcedTea 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 IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.services;
+
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.security.SecurityWarningDialog;
+
+import java.awt.datatransfer.Transferable;
+import java.awt.Toolkit;
+
+/**
+ * The ClipboardService JNLP service.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+class XClipboardService implements ClipboardService {
+
+ protected XClipboardService() {
+ }
+
+ /**
+ * Returns the contents of the system clipboard.
+ */
+ public java.awt.datatransfer.Transferable getContents(){
+
+ if (ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.CLIPBOARD_READ)) {
+ Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
+ return (Transferable) ServiceUtil.createPrivilegedProxy(
+ Transferable.class, t);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the contents of the system clipboard.
+ */
+ public void setContents(java.awt.datatransfer.Transferable contents) {
+ if (ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.CLIPBOARD_WRITE)) {
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
+ contents, null);
+ }
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XDownloadService.java b/netx/net/sourceforge/jnlp/services/XDownloadService.java
new file mode 100644
index 0000000..174071a
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XDownloadService.java
@@ -0,0 +1,179 @@
+// 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.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.ref.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+
+/**
+ * The DownloadService JNLP service.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+class XDownloadService implements DownloadService {
+
+ protected XDownloadService() {
+ }
+
+ // comments copied from DownloadService interface
+
+ /**
+ * Returns a listener that will automatically display download
+ * progress to the user.
+ */
+ public DownloadServiceListener getDefaultProgressWindow() {
+ return null;
+ }
+
+ /**
+ * Returns whether the part in an extension (specified by the
+ * url and version) is cached locally.
+ */
+ public boolean isExtensionPartCached(URL ref, String version, String part) {
+ return true;
+ }
+
+ /**
+ * Returns whether the parts in an extension (specified by the
+ * url and version) are cached locally.
+ */
+ public boolean isExtensionPartCached(URL ref, String version, String[] parts) {
+ return true;
+ }
+
+ /**
+ * Returns whether the part of the calling application is cached
+ * locally. If called by code specified by an extension
+ * descriptor, the specified part refers to the extension not
+ * the application.
+ */
+ public boolean isPartCached(String part) {
+ return true;
+ }
+
+ /**
+ * Returns whether all of the parts of the calling application
+ * are cached locally. If called by code in an extension, the
+ * part refers the the part of the extension not the
+ * application.
+ */
+ public boolean isPartCached(String[] parts) {
+ return true;
+ }
+
+ /**
+ * Returns whether the resource is cached locally. This method
+ * only returns true if the resource is specified by the calling
+ * application or extension.
+ */
+ public boolean isResourceCached(URL ref, String version) {
+ return true;
+ }
+
+ /**
+ * Downloads the parts of an extension.
+ *
+ * @throws IOException
+ */
+ public void loadExtensionPart(URL ref, String version, String[] parts, DownloadServiceListener progress) throws IOException {
+ }
+
+ /**
+ * Downloads a part of an extension.
+ *
+ * @throws IOException
+ */
+ public void loadExtensionPart(URL ref, String version, String part, DownloadServiceListener progress) throws IOException {
+ }
+
+ /**
+ * Downloads the parts.
+ *
+ * @throws IOException
+ */
+ public void loadPart(String[] parts, DownloadServiceListener progress) throws IOException {
+ }
+
+ /**
+ * Downloads the part.
+ *
+ * @throws IOException
+ */
+ public void loadPart(String part, DownloadServiceListener progress) throws IOException {
+ }
+
+ /**
+ * Downloads a resource.
+ *
+ * @throws IOException
+ */
+ public void loadResource(URL ref, String version, DownloadServiceListener progress) throws IOException {
+ }
+
+ /**
+ * Notify the system that an extension's part is no longer
+ * important to cache.
+ *
+ * @throws IOException
+ */
+ public void removeExtensionPart(URL ref, String version, String part) throws IOException {
+ }
+
+ /**
+ * Notify the system that an extension's parts are no longer
+ * important to cache.
+ *
+ * @throws IOException
+ */
+ public void removeExtensionPart(URL ref, String version, String[] parts) throws IOException {
+ }
+
+ /**
+ * Notifies the system that a part is no longer important to
+ * cache.
+ *
+ * @throws IOException
+ */
+ public void removePart(String part) throws IOException {
+ }
+
+ /**
+ * Notifies the system that the parts is no longer important to
+ * cache.
+ *
+ * @throws IOException
+ */
+ public void removePart(String[] parts) throws IOException {
+ }
+
+ /**
+ * Notifies the system that the resource is no longer important
+ * to cache.
+ *
+ * @throws IOException
+ */
+ public void removeResource(URL ref, String version) throws IOException {
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XExtendedService.java b/netx/net/sourceforge/jnlp/services/XExtendedService.java
new file mode 100644
index 0000000..9eafba5
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XExtendedService.java
@@ -0,0 +1,56 @@
+// 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.services;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.jnlp.ExtendedService;
+import javax.jnlp.FileContents;
+
+import net.sourceforge.jnlp.security.SecurityWarningDialog;
+
+/**
+ * Implementation of ExtendedService
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ *
+ */
+public class XExtendedService implements ExtendedService {
+
+ public FileContents openFile(File file) throws IOException {
+
+ /* FIXME: this opens a file with read/write mode, not just read or write */
+ if (ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.READ_FILE,
+ new Object[]{ file.getAbsolutePath() })) {
+ return (FileContents) ServiceUtil.createPrivilegedProxy(FileContents.class,
+ new XFileContents(file));
+ } else {
+ return null;
+ }
+
+ }
+
+ public FileContents[] openFiles(File[] files) throws IOException {
+ FileContents[] contents = new FileContents[files.length];
+ for (int i = 0; i < files.length; i++) {
+ contents[i] = openFile(files[i]);
+ }
+ return contents;
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java b/netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java
new file mode 100644
index 0000000..7fea6bb
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java
@@ -0,0 +1,121 @@
+// 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.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.ref.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+
+/**
+ * The ExtensionInstallerService JNLP service.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+class XExtensionInstallerService implements ExtensionInstallerService {
+
+ protected XExtensionInstallerService() {
+ }
+
+ /**
+ *
+ */
+ public URL getExtensionLocation() {
+ return null;
+ }
+
+ /**
+ *
+ */
+ public String getExtensionVersion() {
+ return null;
+ }
+
+ /**
+ *
+ */
+ public String getInstalledJRE(java.net.URL url, java.lang.String version) {
+ return null;
+ }
+
+ /**
+ *
+ */
+ public String getInstallPath() {
+ return null;
+ }
+
+ /**
+ *
+ */
+ public void hideProgressBar() {
+ }
+
+ /**
+ *
+ */
+ public void hideStatusWindow() {
+ }
+
+ /**
+ *
+ */
+ public void installFailed() {
+ }
+
+ /**
+ *
+ */
+ public void installSucceeded(boolean needsReboot) {
+ }
+
+ /**
+ *
+ */
+ public void setHeading(java.lang.String heading) {
+ }
+
+ /**
+ *
+ */
+ public void setJREInfo(java.lang.String platformVersion, java.lang.String jrePath) {
+ }
+
+ /**
+ *
+ */
+ public void setNativeLibraryInfo(java.lang.String path) {
+ }
+
+ /**
+ *
+ */
+ public void setStatus(java.lang.String status) {
+ }
+
+ /**
+ *
+ */
+ public void updateProgress(int value) {
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XFileContents.java b/netx/net/sourceforge/jnlp/services/XFileContents.java
new file mode 100644
index 0000000..c7b331a
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XFileContents.java
@@ -0,0 +1,121 @@
+// 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.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.ref.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * File contents.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+class XFileContents implements FileContents {
+
+ /** the file */
+ private File file;
+
+ /**
+ * Create a file contents implementation for the file.
+ */
+ protected XFileContents(File file) {
+ this.file = file;
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public boolean canRead() throws IOException {
+ return file.canRead();
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public boolean canWrite() throws IOException {
+ return file.canWrite();
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream(file);
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public long getLength() throws IOException {
+ return file.length();
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public long getMaxLength() throws IOException {
+ return Long.MAX_VALUE;
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public String getName() throws IOException {
+ return file.getName();
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public OutputStream getOutputStream(boolean overwrite) throws IOException {
+ // file.getPath compatible with pre-1.4 JREs
+ return new FileOutputStream(file.getPath(), !overwrite);
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public JNLPRandomAccessFile getRandomAccessFile(String mode) throws IOException {
+ return new XJNLPRandomAccessFile(file, mode);
+ }
+
+ /**
+ *
+ * @throws IOException if an I/O exception occurs.
+ */
+ public long setMaxLength(long maxlength) throws IOException {
+ return maxlength;
+ }
+
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XFileOpenService.java b/netx/net/sourceforge/jnlp/services/XFileOpenService.java
new file mode 100644
index 0000000..8f2c110
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XFileOpenService.java
@@ -0,0 +1,113 @@
+/* XFileOpenService.java
+ Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea 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, version 2.
+
+IcedTea 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 IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.ref.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.runtime.*;
+import net.sourceforge.jnlp.security.SecurityWarningDialog;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import java.security.*;
+
+/**
+ * The FileOpenService JNLP service.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+class XFileOpenService implements FileOpenService {
+
+ protected XFileOpenService() {
+ }
+
+ /**
+ * Prompts the user to select a single file.
+ */
+ public FileContents openFileDialog (java.lang.String pathHint,
+ java.lang.String[] extensions) throws java.io.IOException {
+
+ if (ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.READ_FILE)) {
+
+ //open a file dialog here, let the user choose the file.
+ JFileChooser chooser = new JFileChooser();
+ int chosen = chooser.showOpenDialog(null);
+ if (chosen == JFileChooser.APPROVE_OPTION) {
+ return (FileContents) ServiceUtil.createPrivilegedProxy(
+ FileContents.class,
+ new XFileContents(chooser.getSelectedFile()));
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Prompts the user to select one or more files.
+ */
+ public FileContents[] openMultiFileDialog (java.lang.String pathHint,
+ java.lang.String[] extensions) throws java.io.IOException {
+
+ if (ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.WRITE_FILE)) {
+ JFileChooser chooser = new JFileChooser();
+ chooser.setMultiSelectionEnabled(true);
+ int chosen = chooser.showOpenDialog(null);
+
+ if (chosen == JFileChooser.APPROVE_OPTION) {
+ File[] files = chooser.getSelectedFiles();
+ int length = files.length;
+ XFileContents[] xfiles = new XFileContents[length];
+ for (int i = 0; i < length; i++)
+ xfiles[i] = new XFileContents(files[i]);
+ return (FileContents[]) ServiceUtil.createPrivilegedProxy(
+ FileContents.class, xfiles);
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/services/XFileSaveService.java b/netx/net/sourceforge/jnlp/services/XFileSaveService.java
new file mode 100644
index 0000000..d3fbe2e
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XFileSaveService.java
@@ -0,0 +1,140 @@
+/* XFileSaveService.java
+ Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea 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, version 2.
+
+IcedTea 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 IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.ref.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.security.*;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import java.security.*;
+
+/**
+ * The FileSaveService JNLP service.
+ *
+ * @author <a href="mailto:jsumali@redhat.com">Joshua Sumali</a>
+ */
+class XFileSaveService implements FileSaveService {
+
+ protected XFileSaveService() {
+ }
+
+ /**
+ * Prompts the user to save a file.
+ */
+ public FileContents saveFileDialog(java.lang.String pathHint,
+ java.lang.String[] extensions, java.io.InputStream stream,
+ java.lang.String name) throws java.io.IOException {
+
+ if (ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.WRITE_FILE)) {
+ JFileChooser chooser = new JFileChooser();
+ int chosen = chooser.showSaveDialog(null);
+
+ if (chosen == JFileChooser.APPROVE_OPTION) {
+ writeToFile(stream, chooser.getSelectedFile());
+ return (FileContents) ServiceUtil.createPrivilegedProxy(
+ FileContents.class,
+ new XFileContents(chooser.getSelectedFile()));
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Prompts the user to save a file, with an optional pre-set filename.
+ */
+ public FileContents saveAsFileDialog(java.lang.String pathHint,
+ java.lang.String[] extensions, FileContents contents) throws java.io.IOException {
+
+ if (ServiceUtil.checkAccess(SecurityWarningDialog.AccessType.WRITE_FILE)) {
+ JFileChooser chooser = new JFileChooser();
+ chooser.setSelectedFile(new File(contents.getName()));
+ int chosen = chooser.showSaveDialog(null);
+
+ if (chosen == JFileChooser.APPROVE_OPTION) {
+ writeToFile(contents.getInputStream(),
+ chooser.getSelectedFile());
+
+ return (FileContents) ServiceUtil.createPrivilegedProxy(
+ FileContents.class,
+ new XFileContents(chooser.getSelectedFile()));
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Writes actual file to disk.
+ */
+ private void writeToFile(InputStream stream, File file) throws IOException {
+ if (!file.createNewFile()) { //file exists
+ boolean replace = (JOptionPane.showConfirmDialog(null,
+ file.getAbsolutePath() + " already exists.\n"
+ +"Do you want to replace it?",
+ "Warning - File Exists", JOptionPane.YES_NO_OPTION) == 0);
+ if (!replace)
+ return;
+ } else {
+ file.createNewFile();
+ }
+
+ if (file.canWrite()) {
+ FileOutputStream out = new FileOutputStream(file);
+ byte[] b = new byte[256];
+ int read = 0;
+ while ((read = stream.read(b)) > 0)
+ out.write(b, 0, read);
+ out.flush();
+ out.close();
+ } else {
+ throw new IOException("Unable to open file for writing");
+ }
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java b/netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java
new file mode 100644
index 0000000..8e97743
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java
@@ -0,0 +1,203 @@
+/* XJNLPRandomAccessFile.java
+ Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea 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, version 2.
+
+IcedTea 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 IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+package net.sourceforge.jnlp.services;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import javax.jnlp.JNLPRandomAccessFile;
+
+public class XJNLPRandomAccessFile implements JNLPRandomAccessFile {
+
+ private RandomAccessFile raf;
+
+ public XJNLPRandomAccessFile(File file, String mode) throws IOException {
+ raf = new RandomAccessFile(file, mode);
+
+ }
+
+ public void close() throws IOException {
+ raf.close();
+ }
+
+ public long getFilePointer() throws IOException {
+ return raf.getFilePointer();
+ }
+
+ public long length() throws IOException {
+ return raf.length();
+ }
+
+ public int read() throws IOException {
+ return raf.read();
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ return raf.read(b, off, len);
+ }
+
+ public int read(byte[] b) throws IOException {
+ return raf.read(b);
+ }
+
+ public boolean readBoolean() throws IOException {
+ return raf.readBoolean();
+ }
+
+ public byte readByte() throws IOException {
+ return raf.readByte();
+ }
+
+ public char readChar() throws IOException {
+ return raf.readChar();
+ }
+
+ public double readDouble() throws IOException {
+ return raf.readDouble();
+ }
+
+ public float readFloat() throws IOException {
+ return raf.readFloat();
+ }
+
+ public void readFully(byte[] b) throws IOException {
+ raf.readFully(b);
+ }
+
+ public void readFully(byte[] b, int off, int len) throws IOException {
+ raf.readFully(b, off, len);
+ }
+
+ public int readInt() throws IOException {
+ return raf.readInt();
+ }
+
+ public String readLine() throws IOException {
+ return raf.readLine();
+ }
+
+ public long readLong() throws IOException {
+ return raf.readLong();
+ }
+
+ public short readShort() throws IOException {
+ return raf.readShort();
+ }
+
+ public String readUTF() throws IOException {
+ return raf.readUTF();
+ }
+
+ public int readUnsignedByte() throws IOException {
+ return raf.readUnsignedByte();
+ }
+
+ public int readUnsignedShort() throws IOException {
+ return raf.readUnsignedShort();
+ }
+
+ public void seek(long pos) throws IOException {
+ raf.seek(pos);
+ }
+
+ public void setLength(long newLength) throws IOException {
+ raf.setLength(newLength);
+ }
+
+ public int skipBytes(int n) throws IOException {
+ return raf.skipBytes(n);
+ }
+
+ public void write(int b) throws IOException {
+ raf.write(b);
+
+ }
+
+ public void write(byte[] b) throws IOException {
+ raf.write(b);
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException {
+ raf.write(b, off, len);
+ }
+
+ public void writeBoolean(boolean v) throws IOException {
+ raf.writeBoolean(v);
+ }
+
+ public void writeByte(int v) throws IOException {
+ raf.writeByte(v);
+ }
+
+ public void writeBytes(String s) throws IOException {
+ raf.writeBytes(s);
+ }
+
+ public void writeChar(int v) throws IOException {
+ raf.writeChar(v);
+ }
+
+ public void writeChars(String s) throws IOException {
+ raf.writeChars(s);
+ }
+
+ public void writeDouble(double v) throws IOException {
+ raf.writeDouble(v);
+ }
+
+ public void writeFloat(float v) throws IOException {
+ raf.writeFloat(v);
+ }
+
+ public void writeInt(int v) throws IOException {
+ raf.writeInt(v);
+ }
+
+ public void writeLong(long v) throws IOException {
+ raf.writeLong(v);
+ }
+
+ public void writeShort(int v) throws IOException {
+ raf.writeShort(v);
+ }
+
+ public void writeUTF(String str) throws IOException {
+ raf.writeUTF(str);
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XPersistenceService.java b/netx/net/sourceforge/jnlp/services/XPersistenceService.java
new file mode 100644
index 0000000..db45163
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XPersistenceService.java
@@ -0,0 +1,177 @@
+// 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.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.ref.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+import net.sourceforge.jnlp.cache.*;
+import net.sourceforge.jnlp.runtime.*;
+
+/**
+ * The BasicService JNLP service.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.7 $
+ */
+class XPersistenceService implements PersistenceService {
+
+ // todo: recheck delete, etc to make sure security is tight
+
+ protected XPersistenceService() {
+ }
+
+ /**
+ * Checks whether the application has access to URL area
+ * requested. If the method returns normally then the specified
+ * location can be accessed by the current application.
+ *
+ * @throws MalformedURLException if the application cannot access the location
+ */
+ protected void checkLocation(URL location) throws MalformedURLException {
+ ApplicationInstance app = JNLPRuntime.getApplication();
+ if (app == null)
+ throw new MalformedURLException("Cannot determine the current application.");
+
+ URL source = app.getJNLPFile().getCodeBase();
+
+ if (!source.getHost().equalsIgnoreCase(location.getHost()))
+ throw new MalformedURLException("Cannot access data from a different host.");
+
+ // test for above codebase, not perfect but works for now
+
+ String requestPath = location.getFile();
+ if (-1 != requestPath.lastIndexOf("/"))
+ requestPath = requestPath.substring(0, requestPath.lastIndexOf("/"));
+ else
+ requestPath = "";
+
+ if (JNLPRuntime.isDebug()) {
+ System.out.println("codebase path: "+source.getFile());
+ System.out.println("request path: "+requestPath);
+ }
+
+ if (!source.getFile().startsWith(requestPath))
+ throw new MalformedURLException("Cannot access data below source URL path.");
+ }
+
+ /**
+ * Converts a URL into a file in the persistence store.
+ *
+ * @return the file
+ */
+ protected File toCacheFile(URL location) throws MalformedURLException {
+ return CacheUtil.urlToPath(location, "pcache");
+ }
+
+ /**
+ *
+ * @return the maximum size of storage that got granted, in bytes
+ * @throws MalformedURLException if the application cannot access the location
+ */
+ public long create(URL location, long maxsize) throws MalformedURLException, IOException {
+ checkLocation(location);
+
+ File file = toCacheFile(location);
+ file.getParentFile().mkdirs();
+
+ if (!file.createNewFile())
+ throw new IOException("File already exists.");
+
+ return maxsize;
+ }
+
+ /**
+ *
+ * @throws MalformedURLException if the application cannot access the location
+ */
+ public void delete(URL location) throws MalformedURLException, IOException {
+ checkLocation(location);
+
+ toCacheFile(location).delete();
+ }
+
+ /**
+ *
+ * @throws MalformedURLException if the application cannot access the location
+ */
+ public FileContents get(URL location) throws MalformedURLException, IOException, FileNotFoundException {
+ checkLocation(location);
+
+ File file = toCacheFile(location);
+ if (!file.exists())
+ throw new FileNotFoundException("Persistence store for "
+ + location.toString() + " is not found.");
+ file.getParentFile().mkdirs();
+
+ return (FileContents) ServiceUtil.createPrivilegedProxy(FileContents.class, new XFileContents(file));
+ }
+
+ /**
+ *
+ * @throws MalformedURLException if the application cannot access the location
+ */
+ public String[] getNames(URL location) throws MalformedURLException, IOException {
+ checkLocation(location);
+
+
+ File file = toCacheFile(location);
+ if (!file.isDirectory())
+ return new String[0];
+
+ List result = new ArrayList();
+
+ // check whether this is right: only add files and not directories.
+ File entries[] = file.listFiles();
+ for (int i=0; i < entries.length; i++)
+ if (entries[i].isFile())
+ result.add(entries[i].getName());
+
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ /**
+ *
+ * @throws MalformedURLException if the application cannot access the location
+ */
+ public int getTag(URL location) throws MalformedURLException, IOException {
+ checkLocation(location);
+
+ // todo: actually implement tags
+
+ if (toCacheFile(location).exists())
+ return PersistenceService.CACHED;
+
+ return PersistenceService.CACHED;
+ }
+
+ /**
+ *
+ * @throws MalformedURLException if the application cannot access the location
+ */
+ public void setTag(URL location, int tag) throws MalformedURLException, IOException {
+ checkLocation(location);
+
+ // todo: actually implement tags
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XPrintService.java b/netx/net/sourceforge/jnlp/services/XPrintService.java
new file mode 100644
index 0000000..f2f75dd
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XPrintService.java
@@ -0,0 +1,123 @@
+/* XPrintService.java
+ Copyright (C) 2008 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea 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, version 2.
+
+IcedTea 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 IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package net.sourceforge.jnlp.services;
+
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+
+import javax.jnlp.*;
+import javax.swing.JOptionPane;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+public class XPrintService implements PrintService {
+
+ // If pj is null, then we do not have a printer to use.
+ private PrinterJob pj;
+
+ public XPrintService() {
+ pj = PrinterJob.getPrinterJob();
+ }
+
+ public PageFormat getDefaultPage() {
+ if (pj != null)
+ return pj.defaultPage();
+ else {
+ showWarning();
+ return new PageFormat(); // might not have default settings.
+ }
+ }
+
+ public PageFormat showPageFormatDialog(PageFormat page) {
+ if (pj != null)
+ return pj.pageDialog(page);
+ else {
+ showWarning();
+ return page;
+ }
+
+ }
+
+ public boolean print(Pageable document) {
+ if (pj != null) {
+ pj.setPageable(document);
+ if (pj.printDialog()) {
+ try {
+ pj.print();
+ return true;
+ } catch(PrinterException pe) {
+ System.err.println("Could not print: " + pe);
+ return false;
+ }
+ }
+ } else
+ showWarning();
+
+ return false;
+ }
+
+ public boolean print(Printable painter) {
+ if (pj != null) {
+ pj.setPrintable(painter);
+ if (pj.printDialog()) {
+ try {
+ pj.print();
+ return true;
+ } catch(PrinterException pe) {
+ System.err.println("Could not print: " + pe);
+ return false;
+ }
+
+ }
+ } else
+ showWarning();
+
+ return false;
+ }
+
+ private void showWarning() {
+ JOptionPane.showMessageDialog(null,
+ "Unable to find a default printer.",
+ "Warning",
+ JOptionPane.WARNING_MESSAGE);
+ System.err.println("Unable to print: Unable to find default printer.");
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/services/XServiceManagerStub.java b/netx/net/sourceforge/jnlp/services/XServiceManagerStub.java
new file mode 100644
index 0000000..756b412
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XServiceManagerStub.java
@@ -0,0 +1,106 @@
+// 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.services;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.ref.*;
+import java.lang.reflect.*;
+import java.security.*;
+import javax.jnlp.*;
+
+import net.sourceforge.jnlp.*;
+
+/**
+ * Lookup table for services.
+ *
+ * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.6 $
+ */
+public class XServiceManagerStub implements ServiceManagerStub {
+
+ // todo: only include ExtensionInstallerService if an installer
+ // is getting the service, otherwise return null.
+
+ // todo: fix services to do their own privileged actions that
+ // run less code in the secure environment (or avoid privileged
+ // actions by giving permission to the code source).
+
+ private static String serviceNames[] = {
+ "javax.jnlp.BasicService", // required
+ "javax.jnlp.DownloadService", // required
+ "javax.jnlp.ExtendedService",
+ "javax.jnlp.ExtensionInstallerService", // required
+ "javax.jnlp.PersistenceService",
+ "javax.jnlp.FileOpenService",
+ "javax.jnlp.FileSaveService",
+ "javax.jnlp.ClipboardService",
+ "javax.jnlp.PrintService",
+ "javax.jnlp.SingleInstanceService"
+ };
+
+ private static Object services[] = {
+ ServiceUtil.createPrivilegedProxy(BasicService.class, new XBasicService()),
+ ServiceUtil.createPrivilegedProxy(DownloadService.class, new XDownloadService()),
+ ServiceUtil.createPrivilegedProxy(ExtendedService.class, new XExtendedService()),
+ ServiceUtil.createPrivilegedProxy(ExtensionInstallerService.class, new XExtensionInstallerService()),
+ ServiceUtil.createPrivilegedProxy(PersistenceService.class, new XPersistenceService()),
+ ServiceUtil.createPrivilegedProxy(FileOpenService.class, new XFileOpenService()),
+ ServiceUtil.createPrivilegedProxy(FileSaveService.class, new XFileSaveService()),
+ ServiceUtil.createPrivilegedProxy(ClipboardService.class, new XClipboardService()),
+ ServiceUtil.createPrivilegedProxy(PrintService.class, new XPrintService()),
+ ServiceUtil.createPrivilegedProxy(ExtendedSingleInstanceService.class, new XSingleInstanceService())
+ };
+
+
+ public XServiceManagerStub() {
+ }
+
+ /**
+ * Returns the service names.
+ */
+ public String[] getServiceNames() {
+ // make sure it is a copy because we might be returning to
+ // code we don't own.
+ String result[] = new String[serviceNames.length];
+ System.arraycopy(serviceNames, 0, result, 0, serviceNames.length);
+
+ return result;
+ }
+
+ /**
+ * Returns the service.
+ *
+ * @throws UnavailableServiceException if service is not available
+ */
+ public Object lookup(String name) throws UnavailableServiceException {
+ // exact match
+ for (int i=0; i < serviceNames.length; i++)
+ if (serviceNames[i].equals(name))
+ return services[i];
+
+ // substring match
+ for (int i=0; i < serviceNames.length; i++)
+ if (-1 != serviceNames[i].indexOf(name))
+ return services[i];
+
+ throw new UnavailableServiceException(""+name);
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/XSingleInstanceService.java b/netx/net/sourceforge/jnlp/services/XSingleInstanceService.java
new file mode 100644
index 0000000..1a40794
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/XSingleInstanceService.java
@@ -0,0 +1,236 @@
+// 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.services;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.jnlp.SingleInstanceListener;
+import javax.management.InstanceAlreadyExistsException;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * This class implements SingleInstanceService
+ *
+ * @author <a href="mailto:omajid@redhat.com">Omair Majid</a>
+ */
+public class XSingleInstanceService implements ExtendedSingleInstanceService {
+
+ boolean initialized = false;
+ List<SingleInstanceListener> listeners = new LinkedList<SingleInstanceListener>();
+
+ /**
+ * Implements a server that listens for arguments from new instances of this
+ * application
+ *
+ */
+ class SingleInstanceServer implements Runnable {
+
+ SingleInstanceLock lockFile = null;
+
+ public SingleInstanceServer(SingleInstanceLock lockFile) {
+ this.lockFile = lockFile;
+ }
+
+ public void run() {
+ ServerSocket listeningSocket = null;
+ try {
+ listeningSocket = new ServerSocket(0);
+ lockFile.createWithPort(listeningSocket.getLocalPort());
+
+ if (JNLPRuntime.isDebug()) {
+ System.out.println("Starting SingleInstanceServer on port" + listeningSocket);
+ }
+
+ while (true) {
+ try {
+ Socket communicationSocket = listeningSocket.accept();
+ ObjectInputStream ois = new ObjectInputStream(communicationSocket
+ .getInputStream());
+ String[] arguments = (String[]) ois.readObject();
+ notifySingleInstanceListeners(arguments);
+ } catch (Exception exception) {
+ // not much to do here...
+ exception.printStackTrace();
+ }
+
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (listeningSocket != null) {
+ try {
+ listeningSocket.close();
+ } catch (IOException e) {
+ // Give up.
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a new XSingleInstanceService
+ */
+ protected XSingleInstanceService() {
+ }
+
+ /**
+ * Initialize the new SingleInstanceService
+ *
+ * @throws InstanceAlreadyExistsException if the instance already exists
+ */
+ public void initializeSingleInstance() {
+ if (!initialized) {
+ // this is called after the application has started. so safe to use
+ // JNLPRuntime.getApplication()
+ checkSingleInstanceRunning(JNLPRuntime.getApplication().getJNLPFile());
+ initialized = true;
+ SingleInstanceLock lockFile;
+ JNLPFile jnlpFile = JNLPRuntime.getApplication().getJNLPFile();
+ lockFile = new SingleInstanceLock(jnlpFile);
+ if (!lockFile.isValid()) {
+ startListeningServer(lockFile);
+ }
+ }
+
+ }
+
+ /**
+ * Check if another instance of this application is already running
+ *
+ * @param jnlpFile The {@link JNLPFile} that specifies the application
+ *
+ * @throws InstanceExistsException if an instance of this application
+ * already exists
+ */
+ public void checkSingleInstanceRunning(JNLPFile jnlpFile) {
+ SingleInstanceLock lockFile = new SingleInstanceLock(jnlpFile);
+ if (lockFile.isValid()) {
+ int port = lockFile.getPort();
+ if (JNLPRuntime.isDebug()) {
+ System.out.println("Lock file is valid (port=" + port + "). Exiting.");
+ }
+ try {
+ sendProgramArgumentsToExistingApplication(port, jnlpFile.getApplication()
+ .getArguments());
+ throw new InstanceExistsException(String.valueOf(port));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Start the listening server to accept arguments from new instances of
+ * applications
+ *
+ * @param lockFile
+ * the {@link SingleInstanceLock} that the server should use
+ */
+ private void startListeningServer(SingleInstanceLock lockFile) {
+ SingleInstanceServer server = new SingleInstanceServer(lockFile);
+ Thread serverThread = new Thread(server);
+ /*
+ * mark as daemon so the JVM can shutdown if the server is the only
+ * thread running
+ */
+ serverThread.setDaemon(true);
+ serverThread.start();
+ }
+
+ /**
+ * Send the arguments for this application to the main instance
+ *
+ * @param port the port at which the SingleInstanceServer is listening at
+ * @param arguments the new arguments
+ * @throws IOException on any io exception
+ */
+ private void sendProgramArgumentsToExistingApplication(int port, String[] arguments)
+ throws IOException {
+ try {
+ Socket serverCommunicationSocket = new Socket((String) null, port);
+ ObjectOutputStream argumentStream = new ObjectOutputStream(serverCommunicationSocket
+ .getOutputStream());
+ argumentStream.writeObject(arguments);
+ argumentStream.close();
+ serverCommunicationSocket.close();
+
+ } catch (UnknownHostException unknownHost) {
+ if (JNLPRuntime.isDebug()) {
+ System.out.println("Unable to find localhost");
+ }
+ throw new RuntimeException(unknownHost);
+ }
+ }
+
+ /**
+ * Notify any SingleInstanceListener with new arguments
+ *
+ * @param arguments the new arguments to the application
+ */
+ private void notifySingleInstanceListeners(String[] arguments) {
+ for (SingleInstanceListener listener : listeners) {
+ // TODO this proxy is privileged. should i worry about security in
+ // methods being called?
+ listener.newActivation(arguments);
+ }
+ }
+
+ /**
+ * Add the specified SingleInstanceListener
+ *
+ * @throws InstanceExistsException, which is likely to terminate the
+ * application but not guaranteed to
+ */
+ public void addSingleInstanceListener(SingleInstanceListener sil) {
+ initializeSingleInstance();
+
+ if (sil == null) {
+ return;
+ }
+
+ listeners.add(sil);
+ }
+
+ /**
+ * Remove the specified SingleInstanceListener
+ *
+ * @throws InstanceExistsException if an instance of this single instance
+ * application already exists
+ *
+ */
+ public void removeSingleInstanceListener(SingleInstanceListener sil) {
+ initializeSingleInstance();
+
+ if (sil == null) {
+ return;
+ }
+
+ listeners.remove(sil);
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/services/package.html b/netx/net/sourceforge/jnlp/services/package.html
new file mode 100644
index 0000000..413b6f6
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/services/package.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+This package contains the classes that implement the standard
+services defined by the JNLP specification.
+
+<h2>Package Specification</h2>
+
+<ul>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/download-spec.html">JNLP specification</a>
+</ul>
+
+<h2>Related Documentation</h2>
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+<li><a target="_top" href="http://jnlp.sourceforge.net/netx/">Netx JNLP Client</a>
+<li><a target="_top" href="http://java.sun.com/products/javawebstart/">Java Web Start JNLP Client</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
+
+