aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java
diff options
context:
space:
mode:
Diffstat (limited to 'netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java')
-rw-r--r--netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java319
1 files changed, 319 insertions, 0 deletions
diff --git a/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java b/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java
new file mode 100644
index 0000000..95ccb1e
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java
@@ -0,0 +1,319 @@
+// 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.runtime;
+
+import java.awt.Window;
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+
+import javax.swing.event.EventListenerList;
+
+import sun.awt.AppContext;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.PropertyDesc;
+import net.sourceforge.jnlp.SecurityDesc;
+import net.sourceforge.jnlp.ShortcutDesc;
+import net.sourceforge.jnlp.event.ApplicationEvent;
+import net.sourceforge.jnlp.event.ApplicationListener;
+import net.sourceforge.jnlp.security.SecurityWarningDialog.AccessType;
+import net.sourceforge.jnlp.services.ServiceUtil;
+import net.sourceforge.jnlp.util.WeakList;
+import net.sourceforge.jnlp.util.XDesktopEntry;
+
+/**
+ * Represents a running instance of an application described in a
+ * JNLPFile. This class provides a way to track the application's
+ * resources and destroy the application.<p>
+ *
+ * @author <a href="mailto:[email protected]">Jon A. Maxwell (JAM)</a> - initial author
+ * @version $Revision: 1.15 $
+ */
+public class ApplicationInstance {
+
+ // todo: should attempt to unload the environment variables
+ // installed by the application.
+
+
+ /** the file */
+ private JNLPFile file;
+
+ /** the thread group */
+ private ThreadGroup group;
+
+ /** the classloader */
+ private ClassLoader loader;
+
+ /**
+ * Every application/applet gets its own AppContext. This allows us to do
+ * things like have two different look and feels for two different applets
+ * (running in the same VM), allows untrusted programs to manipulate the
+ * event queue (safely) and (possibly) more.<p>
+ *
+ * It is set to the AppContext which created this ApplicationInstance
+ */
+ private AppContext appContext;
+
+ /** whether the application has stopped running */
+ private boolean stopped = false;
+
+ /** weak list of windows opened by the application */
+ private WeakList weakWindows = new WeakList();
+
+ /** list of application listeners */
+ private EventListenerList listeners = new EventListenerList();
+
+ /** whether or not this application is signed */
+ private boolean isSigned = false;
+
+ /**
+ * Create an application instance for the file. This should be done in the
+ * appropriate {@link ThreadGroup} only.
+ */
+ public ApplicationInstance(JNLPFile file, ThreadGroup group, ClassLoader loader) {
+ this.file = file;
+ this.group = group;
+ this.loader = loader;
+ this.isSigned = ((JNLPClassLoader) loader).getSigning();
+ this.appContext = AppContext.getAppContext();
+ }
+
+ /**
+ * Add an Application listener
+ */
+ public void addApplicationListener(ApplicationListener listener) {
+ listeners.add(ApplicationListener.class, listener);
+ }
+
+ /**
+ * Remove an Application Listener
+ */
+ public void removeApplicationListener(ApplicationListener listener) {
+ listeners.remove(ApplicationListener.class, listener);
+ }
+
+ /**
+ * Notify listeners that the application has been terminated.
+ */
+ protected void fireDestroyed() {
+ Object list[] = listeners.getListenerList();
+ ApplicationEvent event = null;
+
+ for (int i=list.length-1; i>0; i-=2) { // last to first required
+ if (event == null)
+ event = new ApplicationEvent(this);
+
+ ((ApplicationListener)list[i]).applicationDestroyed(event);
+ }
+ }
+
+ /**
+ * Initialize the application's environment (installs
+ * environment variables, etc).
+ */
+ public void initialize() {
+ installEnvironment();
+
+ //Fixme: -Should check whether a desktop entry already exists for
+ // for this jnlp file, and do nothing if it exists.
+ // -If no href is specified in the jnlp tag, it should
+ // default to using the one passed in as an argument.
+ addMenuAndDesktopEntries();
+ }
+
+ /**
+ * Creates menu and desktop entries if required by the jnlp file
+ */
+
+ private void addMenuAndDesktopEntries() {
+ XDesktopEntry entry = new XDesktopEntry(file);
+ ShortcutDesc sd = file.getInformation().getShortcut();
+
+ if (sd != null && sd.onDesktop()) {
+ if (ServiceUtil.checkAccess(this, AccessType.CREATE_DESTKOP_SHORTCUT)) {
+ entry.createDesktopShortcut();
+ }
+ }
+
+ if (sd != null && sd.getMenu() != null) {
+ /*
+ * Sun's WebStart implementation doesnt seem to do anything under GNOME
+ */
+ if (JNLPRuntime.isDebug()) {
+ System.err.println("ApplicationInstance.addMenuAndDesktopEntries():"
+ + " Adding menu entries NOT IMPLEMENTED");
+ }
+ }
+
+ }
+
+ /**
+ * Releases the application's resources before it is collected.
+ * Only collectable if classloader and thread group are
+ * also collectable so basically is almost never called (an
+ * application would have to close its windows and exit its
+ * threads but not call System.exit).
+ */
+ public void finalize() {
+ destroy();
+ }
+
+ /**
+ * Install the environment variables.
+ */
+ void installEnvironment() {
+ final PropertyDesc props[] = file.getResources().getProperties();
+
+ CodeSource cs = new CodeSource((URL) null, (java.security.cert.Certificate [])null);
+
+ JNLPClassLoader loader = (JNLPClassLoader) this.loader;
+ SecurityDesc s = loader.getSecurity();
+
+ ProtectionDomain pd = new ProtectionDomain(cs, s.getPermissions(), null, null);
+
+ // Add to hashmap
+ AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] {pd});
+
+ PrivilegedAction installProps = new PrivilegedAction() {
+ public Object run() {
+ for (int i=0; i < props.length; i++) {
+ System.setProperty(props[i].getKey(), props[i].getValue());
+ }
+
+ return null;
+ }
+ };
+ AccessController.doPrivileged(installProps, acc);
+ }
+
+ /**
+ * Returns the JNLP file for this task.
+ */
+ public JNLPFile getJNLPFile() {
+ return file;
+ }
+
+ /**
+ * Returns the application title.
+ */
+ public String getTitle() {
+ return file.getTitle();
+ }
+
+ /**
+ * Returns whether the application is running.
+ */
+ public boolean isRunning() {
+ return !stopped;
+ }
+
+ /**
+ * Stop the application and destroy its resources.
+ */
+ public void destroy() {
+ if (stopped)
+ return;
+
+ try {
+ // destroy resources
+ for (int i=0; i < weakWindows.size(); i++) {
+ Window w = (Window) weakWindows.get(i);
+ if (w != null)
+ w.dispose();
+ }
+
+ weakWindows.clear();
+
+ // interrupt threads
+ Thread threads[] = new Thread[ group.activeCount() * 2 ];
+ int nthreads = group.enumerate(threads);
+ for (int i=0; i < nthreads; i++) {
+ if (JNLPRuntime.isDebug())
+ System.out.println("Interrupt thread: "+threads[i]);
+
+ threads[i].interrupt();
+ }
+
+ // then stop
+ Thread.currentThread().yield();
+ nthreads = group.enumerate(threads);
+ for (int i=0; i < nthreads; i++) {
+ if (JNLPRuntime.isDebug())
+ System.out.println("Stop thread: "+threads[i]);
+
+ threads[i].stop();
+ }
+
+ // then destroy - except Thread.destroy() not implemented in jdk
+
+ }
+ finally {
+ stopped = true;
+ fireDestroyed();
+ }
+ }
+
+ /**
+ * Returns the thread group.
+ *
+ * @throws IllegalStateException if the app is not running
+ */
+ public ThreadGroup getThreadGroup() throws IllegalStateException {
+ if (stopped)
+ throw new IllegalStateException();
+
+ return group;
+ }
+
+ /**
+ * Returns the classloader.
+ *
+ * @throws IllegalStateException if the app is not running
+ */
+ public ClassLoader getClassLoader() throws IllegalStateException {
+ if (stopped)
+ throw new IllegalStateException();
+
+ return loader;
+ }
+
+ /**
+ * Adds a window that this application opened. When the
+ * application is disposed, these windows will also be disposed.
+ */
+ protected void addWindow(Window window) {
+ weakWindows.add(window);
+ weakWindows.trimToSize();
+ }
+
+ /**
+ * Returns whether or not this jar is signed.
+ */
+ public boolean isSigned() {
+ return isSigned;
+ }
+
+ public AppContext getAppContext() {
+ return appContext;
+ }
+
+}