diff options
Diffstat (limited to 'netx/jogamp/plugin/jnlp/NetxApplet3Panel.java')
-rw-r--r-- | netx/jogamp/plugin/jnlp/NetxApplet3Panel.java | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/netx/jogamp/plugin/jnlp/NetxApplet3Panel.java b/netx/jogamp/plugin/jnlp/NetxApplet3Panel.java new file mode 100644 index 0000000..875dc5a --- /dev/null +++ b/netx/jogamp/plugin/jnlp/NetxApplet3Panel.java @@ -0,0 +1,230 @@ +/* + * Copyright 2012 Red Hat, Inc. + * This file is part of IcedTea, http://icedtea.classpath.org + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package jogamp.plugin.jnlp; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import jogamp.applet.App3Context; +import jogamp.applet.Applet3Panel; +import jogamp.plugin.jnlp.runtime.Applet3Instance; +import net.sourceforge.jnlp.Launcher; +import net.sourceforge.jnlp.PluginBridge; +import net.sourceforge.jnlp.PluginParameters; +import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.splashscreen.SplashController; +import net.sourceforge.jnlp.splashscreen.SplashPanel; +import net.sourceforge.jnlp.splashscreen.SplashUtils; +import net.sourceforge.jnlp.util.logging.OutputController; + +import com.jogamp.plugin.applet.Applet3Context; + +/** + * This panel calls into netx to run an applet, and pipes the display + * into a panel from the icedtea-web browser plugin. + * + * @author Francis Kung <[email protected]> + */ +public class NetxApplet3Panel extends Applet3Panel implements SplashController { + private final PluginParameters pluginParameters; + private PluginBridge bridge = null; + private Applet3Instance appInst = null; + private SplashController splashController; + /** The plugin .. */ + private Applet3Context upstreamContext = null; + private volatile boolean initialized; + + // We use this so that we can create exactly one thread group + // for all panels with the same uKey. + private static final Map<String, ThreadGroup> uKeyToTG = + new HashMap<String, ThreadGroup>(); + private static final Object TGMapMutex = new Object(); + + // This map is actually a set (unfortunately there is no ConcurrentSet + // in java.util.concurrent). If KEY is in this map, then we know that + // an app context has been created for the panel that has uKey.equals(KEY), + // so we avoid creating it a second time for panels with the same uKey. + // Because it's a set, only the keys matter. However, we can't insert + // null values in because if we did, we couldn't use null checks to see + // if a key was absent before a putIfAbsent. + private static final ConcurrentMap<String, Boolean> appContextCreated = + new ConcurrentHashMap<String, Boolean>(); + + public NetxApplet3Panel(long nativeWindowHandle, int width, int height, URL documentURL, PluginParameters params) { + super(nativeWindowHandle, width, height, documentURL, params.getUnderlyingHashtable()); + + this.pluginParameters = params; + this.initialized = false; + + String uniqueKey = params.getUniqueKey(getCodeBase()); + synchronized(TGMapMutex) { + if (!uKeyToTG.containsKey(uniqueKey)) { + ThreadGroup tg = new ThreadGroup(Launcher.getMainGroup(), this.documentURL.toString()); + uKeyToTG.put(uniqueKey, tg); + } + } + } + + @Override + protected void showAppletException(Throwable t) { + /* + * Log any exceptions thrown while loading, initializing, starting, + * and stopping the applet. + */ + OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, t); //new logger + super.showAppletException(t); + } + + //Overriding to use Netx classloader. You might need to relax visibility + //in sun.applet.AppletPanel for runLoader(). + @Override + protected void runLoader() { + + try { + bridge = new PluginBridge(baseURL, + getDocumentBase(), + getJarFiles(), + getCode(), + getWidth(), + getHeight(), + pluginParameters); + + doInit = true; + dispatchAppletEvent(APPLET_LOADING, null); + status = APPLET_LOAD; + + App3Launcher l = new App3Launcher(false); + + // May throw LaunchException: + appInst = (Applet3Instance) l.launch(bridge); + applet = appInst.getApplet(); + + if (applet != null) { + // Stick it in the frame + showAppletStatus("loaded"); + } + } catch (Exception e) { + status = APPLET_ERROR; + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); + replaceSplash(SplashUtils.getErrorSplashScreen(getWidth(), getHeight(), e)); + } finally { + // PR1157: This needs to occur even in the case of an exception + // so that the applet's event listeners are signaled. + // Once PluginAppletViewer.AppletEventListener is signaled PluginAppletViewer can properly stop waiting + // in PluginAppletViewer.waitForAppletInit + this.initialized = true; + dispatchAppletEvent(APPLET_LOADING_COMPLETED, null); + } + } + + /** + * Creates a new Thread (in a new applet-specific ThreadGroup) for running + * the applet + */ + // Reminder: Relax visibility in sun.applet.AppletPanel + @Override + public synchronized void createAppletThread() { + // initialize JNLPRuntime in the main threadgroup + synchronized (JNLPRuntime.initMutex) { + //The custom NetX Policy and SecurityManager are set here. + if (!JNLPRuntime.isInitialized()) { + OutputController.getLogger().log("initializing JNLPRuntime..."); + + JNLPRuntime.initialize(false); + } else { + OutputController.getLogger().log("JNLPRuntime already initialized"); + } + } + + handler = new Thread(getThreadGroup(), this, "NetxPanelThread@" + this.documentURL); + handler.start(); + } + + public final void setAppletContext(Applet3Context ctx) { + upstreamContext = ctx; + } + + @Override + protected final Applet3Context getAppletContext() { + if( null != upstreamContext ) { + return upstreamContext; + } else { + return appInst.getAppletEnvironment(); + } + } + + @Override + public ClassLoader getAppletClassLoader() { + return appInst.getClassLoader(); + } + + public boolean isInitialized() { + return initialized; + } + + public ThreadGroup getThreadGroup() { + synchronized(TGMapMutex) { + return uKeyToTG.get(pluginParameters.getUniqueKey(getCodeBase())); + } + } + + public void createNewAppContext() { + if (Thread.currentThread().getThreadGroup() != getThreadGroup()) { + throw new RuntimeException("createNewAppContext called from the wrong thread."); + } + // only create a new context if one hasn't already been created for the + // applets with this unique key. + if (null == appContextCreated.putIfAbsent(pluginParameters.getUniqueKey(getCodeBase()), Boolean.TRUE)) { + App3Context.createAppContext(); // FIXME: Really ? + // SunToolkit.createNewAppContext(); + } + } + + public void setAppletViewerFrame(SplashController framePanel) { + splashController=framePanel; + } + + @Override + public void removeSplash() { + splashController.removeSplash(); + } + + @Override + public void replaceSplash(SplashPanel r) { + splashController.replaceSplash(r); + } + + @Override + public int getSplashWidth() { + return splashController.getSplashWidth(); + } + + @Override + public int getSplashHeigth() { + return splashController.getSplashHeigth(); + } + +} |