Mercurial > hg > release > icedtea6-1.3
changeset 1051:f9d81fd1466d
Merging with latest from main repo
author | Deepak Bhole <dbhole@redhat.com> |
---|---|
date | Wed, 24 Sep 2008 11:44:16 -0400 |
parents | 30567fe7d579 (diff) d2579e023b0e (current diff) |
children | 098f7819fe90 |
files | ChangeLog Makefile.am |
diffstat | 37 files changed, 4606 insertions(+), 4166 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Sep 22 10:39:01 2008 -0400 +++ b/ChangeLog Wed Sep 24 11:44:16 2008 -0400 @@ -1,11 +1,63 @@ +2008-09-23 Deepak Bhole <dbhole@redhat.com> + * IcedTeaPlugin.cc: Updated to call new plugin main class. Add function to + correctly recognize JS context. + * Makefile.am: Update to create new IcedTeaPlugin.jar + * patches/icedtea-liveconnect.patch: Update patch and remove all new .java + files + * plugin/icedtea/java/src/main/netscape/javascript/JSException.java: Moved + out of rt/ overlay. + * plugin/icedtea/java/src/main/netscape/javascript/JSObject.java: Same. + * plugin/icedtea/java/src/main/netscape/javascript/JSProxy.java: Same. + * plugin/icedtea/java/src/main/netscape/javascript/JSRunnable.java: Same. + * plugin/icedtea/java/src/main/netscape/javascript/JSUtil.java: Same. + * plugin/icedtea/org/classpath/icedtea/plugin/GetMemberPluginCallRequest.java: + Moved out of icedtea-liveconnect.patch and refactored. + * plugin/icedtea/org/classpath/icedtea/plugin/GetWindowPluginCallRequest.java: + Same. + * plugin/icedtea/org/classpath/icedtea/plugin/PluginAppletSecurityContext.java: + Same. + * plugin/icedtea/org/classpath/icedtea/plugin/PluginCallRequestFactoryImpl.java: + Same. + * plugin/icedtea/org/classpath/icedtea/plugin/PluginMain.java: Same. + * plugin/icedtea/org/classpath/icedtea/plugin/PluginMessageConsumer.java: + Same. + * plugin/icedtea/org/classpath/icedtea/plugin/PluginMessageHandlerWorker.java: + Same. + * plugin/icedtea/org/classpath/icedtea/plugin/PluginObjectStore.java: + Same. + * plugin/icedtea/org/classpath/icedtea/plugin/PluginStreamHandlerImpl.java: + Same. + * plugin/icedtea/org/classpath/icedtea/plugin/RequestQueue.java: Same. + * plugin/icedtea/org/classpath/icedtea/plugin/TestEnv.java: Same. + * plugin/icedtea/org/classpath/icedtea/plugin/VoidPluginCallRequest.java: + Same. + * plugin/icedtea/sun/applet/AppletSecurityContext.java: Same. + * plugin/icedtea/sun/applet/AppletSecurityContextManager.java: Same. + * plugin/icedtea/sun/applet/PluginAppletViewer.java: Same. + * plugin/icedtea/sun/applet/PluginCallRequest.java: Same. + * plugin/icedtea/sun/applet/PluginCallRequestFactory.java: Same. + * plugin/icedtea/sun/applet/PluginClassLoader.java: Same. + * plugin/icedtea/sun/applet/PluginDebug.java: Same. + * plugin/icedtea/sun/applet/PluginException.java: Same. + * plugin/icedtea/sun/applet/PluginStreamHandler.java: Same. + * rt/net/sourceforge/jnlp/Launcher.java: Print exception trace if launch + fails. + * rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Set ServiceManagerStub + before SecurityManager is set. + * rt/netscape/javascript/JSException.java: Move to plugin/icedtea dir. + * rt/netscape/javascript/JSObject.java: Same. + * rt/netscape/javascript/JSProxy.java: Same. + * rt/netscape/javascript/JSRunnable.java: Same. + * rt/netscape/javascript/JSUtil.java: Same. + 2008-09-22 Lillian Angel <langel@redhat.com> - DJ Lucas <dj@linuxfromscratch.org> - - * Makefile.am: Added new env var JAR_ACCEPTS_STDIN_LIST. - * acinclude.m4: Added check to determine whether jar supports - stdin file args. - * patches/icedtea-ecj.patch: Updated patch. - * AUTHORS: Added DJ Lucas. + DJ Lucas <dj@linuxfromscratch.org> + + * Makefile.am: Added new env var JAR_ACCEPTS_STDIN_LIST. + * acinclude.m4: Added check to determine whether jar supports + stdin file args. + * patches/icedtea-ecj.patch: Updated patch. + * AUTHORS: Added DJ Lucas. 2008-09-18 Lillian Angel <langel@redhat.com>
--- a/IcedTeaPlugin.cc Mon Sep 22 10:39:01 2008 -0400 +++ b/IcedTeaPlugin.cc Wed Sep 24 11:44:16 2008 -0400 @@ -244,6 +244,7 @@ static GError* channel_error = NULL; // Fully-qualified appletviewer executable. static char* appletviewer_executable = NULL; +static char* extra_jars = NULL; static char* libjvm_so = NULL; class IcedTeaPluginFactory; @@ -313,7 +314,10 @@ // FIXME: create index from security context. #define MESSAGE_CREATE(reference) \ const char* addr; \ + char context[16]; \ GetCurrentPageAddress(&addr); \ + GetCurrentContextAddr(context); \ + printf("Addr: %s , Context: %s\n", addr, context);\ \ nsCString message ("context "); \ message.AppendInt (0); \ @@ -1149,7 +1153,8 @@ int IncrementContextCounter(); void DecrementContextCounter(); - void GetCurrentPageAddress(const char **addr); + nsresult GetCurrentContextAddr(char *addr); + nsresult GetCurrentPageAddress(const char **addr); int contextCounter; }; @@ -3184,9 +3189,9 @@ PLUGIN_CHECK_RETURN ("init process", result); // FIXME: hard-coded port number. - char const* args[5] = { "-Xdebug", "-Xnoagent", "-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n", "sun.applet.PluginMain", "50007" }; + char const* args[8] = { "-classpath", extra_jars, "-Xdebug", "-Xnoagent", "-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n", "org.classpath.icedtea.plugin.PluginMain", "50007" }; // char const* args[2] = { "sun.applet.PluginMain", "50007" }; - result = applet_viewer_process->Run (PR_FALSE, args, 5, nsnull); + result = applet_viewer_process->Run (PR_FALSE, args, 8, nsnull); PLUGIN_CHECK_RETURN ("run process", result); // start processing thread @@ -3763,6 +3768,7 @@ #include <nsIPrincipal.h> #include <nsIScriptSecurityManager.h> #include <nsIURI.h> +#include <xpcjsid.h> IcedTeaJNIEnv::IcedTeaJNIEnv (IcedTeaPluginFactory* factory) : factory (factory) @@ -3801,17 +3807,69 @@ PR_ExitMonitor(contextCounterPRMonitor); } -void +#include <nsIJSContextStack.h> + +nsresult +IcedTeaJNIEnv::GetCurrentContextAddr(char *addr) +{ + PLUGIN_TRACE_JNIENV (); + + // Get JSContext from stack. + nsCOMPtr<nsIJSContextStack> mJSContextStack(do_GetService("@mozilla.org/js/xpc/ContextStack;1")); + if (mJSContextStack) { + JSContext *cx; + if (NS_FAILED(mJSContextStack->Peek(&cx))) + return NS_ERROR_FAILURE; + + printf("Context1: %p\n", cx); + + // address cannot be more than 8 bytes (8 bytes = 64 bits) + sprintf(addr, "%p", cx); + + printf("Context2: %s\n", addr); + } + + return NS_OK; +} + +nsresult IcedTeaJNIEnv::GetCurrentPageAddress(const char **addr) { + + PLUGIN_TRACE_JNIENV (); + nsIPrincipal *prin; nsCOMPtr<nsIScriptSecurityManager> sec_man(do_GetService("@mozilla.org/scriptsecuritymanager;1")); - sec_man->GetSubjectPrincipal(&prin); + if (sec_man) { + + PRBool isEnabled = PR_FALSE; + sec_man->IsCapabilityEnabled("UniversalBrowserRead", &isEnabled); + + if (isEnabled == PR_FALSE) { + printf("UniversalBrowserRead is NOT enabled\n"); + } else { + printf("UniversalBrowserRead IS enabled\n"); + } + + sec_man->IsCapabilityEnabled("UniversalBrowserWrite", &isEnabled); + + if (isEnabled == PR_FALSE) { + printf("UniversalBrowserWrite is NOT enabled\n"); + } else { + printf("UniversalBrowserWrite IS enabled\n"); + } + } + + if (sec_man) + { + sec_man->GetSubjectPrincipal(&prin); + } else { + return NS_ERROR_FAILURE; + } if (prin) { - nsIURI *uri; prin->GetURI(&uri); @@ -3820,8 +3878,19 @@ nsCAutoString str; uri->GetSpec(str); NS_CStringGetData(str, addr); + } else { + return NS_ERROR_FAILURE; } + } else { + return NS_ERROR_FAILURE; } + + + nsCOMPtr<nsIJSID> js_id(do_GetService("@mozilla.org/js/xpc/ID;1")); + printf("JS ID is: %s\n", js_id->GetID()->ToString()); + + return NS_OK; + } NS_IMETHODIMP @@ -4846,15 +4915,24 @@ return NS_ERROR_OUT_OF_MEMORY; } nsCString executable (dirname (filename)); + nsCString jar(dirname (filename)); + nsCString extrajars(""); free (filename); filename = NULL; //executableString += nsCString ("/../../bin/pluginappletviewer"); executable += nsCString ("/../../bin/java"); + extrajars += jar; + extrajars += nsCString("/IcedTeaPlugin.jar"); + extrajars += ":"; + extrajars += jar; + extrajars += nsCString("/rt.jar"); + //executable += nsCString ("/client/libjvm.so"); // Never freed. appletviewer_executable = strdup (executable.get ()); + extra_jars = strdup (extrajars.get ()); //libjvm_so = strdup (executable.get ()); if (!appletviewer_executable) { @@ -4862,6 +4940,12 @@ return NS_ERROR_OUT_OF_MEMORY; } + if (!extra_jars) + { + PLUGIN_ERROR ("Failed to create plugin jar name."); + return NS_ERROR_OUT_OF_MEMORY; + } + if (factory_created == PR_TRUE) { // wait for factory to initialize
--- a/Makefile.am Mon Sep 22 10:39:01 2008 -0400 +++ b/Makefile.am Wed Sep 24 11:44:16 2008 -0400 @@ -12,15 +12,15 @@ if ENABLE_LIVECONNECT ICEDTEAPLUGIN_CLEAN = clean-IcedTeaPlugin ICEDTEAPLUGIN_TARGET = IcedTeaPlugin.so +ICEDTEAPLUGIN_JAR = IcedTeaPlugin.jar PLUGIN_PATCH = patches/icedtea-liveconnect.patch -EXCLUDE_LIVECONNECT = -LIVECONNECT_DIR = -C lib/rt netscape +LIVECONNECT = $(abs_top_srcdir)/plugin/icedtea/ else ICEDTEAPLUGIN_CLEAN = ICEDTEAPLUGIN_TARGET = +ICEDTEAPLUGIN_JAR = PLUGIN_PATCH = patches/icedtea-plugin.patch -EXCLUDE_LIVECONNECT = | grep -v 'netscape/javascript' -LIVECONNECT_DIR = +LIVECONNECT = if ENABLE_PLUGIN GCJWEBPLUGIN_CLEAN = clean-gcjwebplugin GCJWEBPLUGIN_TARGET = gcjwebplugin.so @@ -586,6 +586,9 @@ echo WARNING make clean-patch before retrying a fix ; \ false; \ fi +if ENABLE_LIVECONNECT + cp -a plugin/icedtea/sun/applet/*java openjdk/jdk/src/share/classes/sun/applet/ +endif clean-patch: rm -f stamps/patch.stamp @@ -604,6 +607,10 @@ if ! test x$${all_patches_ok} = "xyes" ; then \ echo "WARNING Not all patches reverted cleanly" ; \ fi + for file in plugin/icedtea/sun/applet/*java ; \ + do \ + rm -f openjdk/jdk/src/share/classes/sun/applet/`basename $file` ; \ + done ; stamps/patch-fsg.stamp: stamps/extract.stamp mkdir -p stamps ; \ @@ -895,7 +902,7 @@ stamps/icedtea.stamp: stamps/bootstrap-directory-symlink.stamp \ stamps/hotspot-tools.stamp stamps/plugs.stamp \ stamps/ports.stamp stamps/patch.stamp stamps/overlay.stamp \ - $(GCJWEBPLUGIN_TARGET) $(ICEDTEAPLUGIN_TARGET) \ + $(GCJWEBPLUGIN_TARGET) $(ICEDTEAPLUGIN_TARGET) $(ICEDTEAPLUGIN_JAR) \ extra-lib/about.jar stamps/cacao.stamp stamps/visualvm.stamp $(MAKE) \ $(ICEDTEA_ENV) \ @@ -906,6 +913,10 @@ $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) cp -pPRf IcedTeaPlugin.so \ $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) + cp -pPRf IcedTeaPlugin.jar \ + $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/ + cp -pPRf IcedTeaPlugin.jar \ + $(BUILD_OUTPUT_DIR)/j2re-image/lib/ else if ENABLE_PLUGIN cp -pPRf gcjwebplugin.so \ @@ -946,7 +957,7 @@ stamps/icedtea-debug.stamp: stamps/bootstrap-directory-symlink.stamp \ stamps/hotspot-tools.stamp stamps/plugs.stamp \ stamps/ports.stamp stamps/patch.stamp stamps/overlay.stamp \ - $(GCJWEBPLUGIN_TARGET) $(ICEDTEAPLUGIN_TARGET) \ + $(GCJWEBPLUGIN_TARGET) $(ICEDTEAPLUGIN_TARGET) $(ICEDTEAPLUGIN_JAR) \ extra-lib/about.jar stamps/cacao.stamp $(MAKE) \ $(ICEDTEA_ENV) \ @@ -957,6 +968,10 @@ $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib/$(INSTALL_ARCH_DIR) cp -pPRf IcedTeaPlugin.so \ $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/$(INSTALL_ARCH_DIR) + cp -pPRf IcedTeaPlugin.jar \ + $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib/ + cp -pPRf IcedTeaPlugin.jar \ + $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/ else if ENABLE_PLUGIN cp -pPRf gcjwebplugin.so \ @@ -1188,8 +1203,7 @@ # rt-closed.jar class files. rt-source-files.txt: stamps/extract.stamp stamps/copy-source-files.stamp - find $(abs_top_srcdir)/rt $(abs_top_builddir)/rt -name '*.java' \ - $(EXCLUDE_LIVECONNECT) \ + find $(abs_top_srcdir)/rt $(abs_top_builddir)/rt $(LIVECONNECT) -name '*.java' \ | sort -u > $@ stamps/rt-class-files.stamp: rt-source-files.txt @@ -1224,10 +1238,10 @@ if ! test -d $(ICEDTEA_BOOT_DIR) ; \ then \ $(JAR) cf $@ -C lib/rt com -C lib/rt java \ - -C lib/rt javax -C lib/rt net $(LIVECONNECT_DIR) -C lib/rt sun ; \ + -C lib/rt javax -C lib/rt net -C lib/rt sun ; \ else \ $(ICEDTEA_BOOT_DIR)/bin/jar cf $@ -C lib/rt com -C lib/rt java \ - -C lib/rt javax -C lib/rt net $(LIVECONNECT_DIR) -C lib/rt sun ; \ + -C lib/rt javax -C lib/rt net -C lib/rt sun ; \ fi if test -d bootstrap/ecj/jre/lib ; \ then \ @@ -1303,6 +1317,7 @@ $(GTK_CFLAGS) \ $(XULRUNNER_CFLAGS) \ -fPIC -c -o $@ $< + IcedTeaPlugin.so: IcedTeaPlugin.o $(CXX) $(CXXFLAGS) \ $< \ @@ -1310,6 +1325,20 @@ $(XULRUNNER_LIBS) \ -shared -o $@ +# icedtea plugin jar for java-side classes +IcedTeaPlugin.jar: + mkdir -p $(BUILD_OUTPUT_DIR)/plugin/icedtea/classes + (cd plugin/icedtea/; \ + $(ICEDTEA_BOOT_DIR)/bin/javac -g \ + -d ../../$(BUILD_OUTPUT_DIR)/plugin/icedtea/classes \ + -bootclasspath $(ICEDTEA_BOOT_DIR)/jre/lib/rt.jar \ + netscape/javascript/*.java org/classpath/icedtea/plugin/*.java \ + ) + + $(JAR) cf $@ \ + -C $(BUILD_OUTPUT_DIR)/plugin/icedtea/classes org/classpath/icedtea/plugin \ + -C $(BUILD_OUTPUT_DIR)/plugin/icedtea/classes netscape/javascript + clean-IcedTeaPlugin: rm -f IcedTeaPlugin.o rm -f IcedTeaPlugin.so
--- a/patches/icedtea-liveconnect.patch Mon Sep 22 10:39:01 2008 -0400 +++ b/patches/icedtea-liveconnect.patch Wed Sep 24 11:44:16 2008 -0400 @@ -1,6 +1,6 @@ diff -urN openjdk.orig/jdk/make/sun/Makefile openjdk/jdk/make/sun/Makefile --- openjdk.orig/jdk/make/sun/Makefile 2008-07-10 15:54:44.000000000 -0400 -+++ openjdk/jdk/make/sun/Makefile 2008-09-15 16:21:47.000000000 -0400 ++++ openjdk/jdk/make/sun/Makefile 2008-09-18 14:28:41.000000000 -0400 @@ -66,6 +66,7 @@ $(HEADLESS_SUBDIR) $(DGA_SUBDIR) \ font jpeg cmm applet rmi beans $(JDBC_SUBDIR) \ @@ -11,7 +11,7 @@ all build clean clobber:: diff -urN openjdk.orig/jdk/make/sun/Makefile.orig openjdk/jdk/make/sun/Makefile.orig --- openjdk.orig/jdk/make/sun/Makefile.orig 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/make/sun/Makefile.orig 2008-09-15 16:21:47.000000000 -0400 ++++ openjdk/jdk/make/sun/Makefile.orig 2008-09-18 14:28:41.000000000 -0400 @@ -0,0 +1,73 @@ +# +# Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -88,7 +88,7 @@ + diff -urN openjdk.orig/jdk/make/sun/plugin/Makefile openjdk/jdk/make/sun/plugin/Makefile --- openjdk.orig/jdk/make/sun/plugin/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/make/sun/plugin/Makefile 2008-09-15 16:21:47.000000000 -0400 ++++ openjdk/jdk/make/sun/plugin/Makefile 2008-09-18 14:28:41.000000000 -0400 @@ -0,0 +1,53 @@ +# +# Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -143,3556 +143,3 @@ +JAVA_ARGS = "{ \"sun.applet.PluginMain\" }" +include $(BUILDDIR)/common/Program.gmk + -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java openjdk/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java 2008-09-15 16:22:06.000000000 -0400 -@@ -0,0 +1,72 @@ -+/* GetMemberPluginCallRequest -- represent Java-to-JavaScript requests -+ Copyright (C) 2008 Red Hat -+ -+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; either version 2, or (at your option) -+any later version. -+ -+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 sun.applet; -+ -+class GetMemberPluginCallRequest extends PluginCallRequest { -+ Object object = null; -+ -+ public GetMemberPluginCallRequest(String message, String returnString) { -+ super(message, returnString); -+ System.out.println ("GetMEMBerPLUGINCAlL " + message + " " + returnString); -+ } -+ -+ public void parseReturn(String message) { -+ System.out.println ("GetMEMBerparseReturn GOT: " + message); -+ String[] args = message.split(" "); -+ // FIXME: add thread ID to messages to support multiple -+ // threads using the netscape.javascript package. -+ object = PluginAppletSecurityContext.contexts.get( -+ 0).store.getObject(Integer.parseInt(args[1])); -+ done = true; -+ } -+ -+ /** -+ * Returns whether the given message is serviceable by this object -+ * -+ * @param message The message to service -+ * @return boolean indicating if message is serviceable -+ */ -+ public boolean serviceable(String message) { -+ return message.contains("JavaScriptCall") || -+ message.contains("JavaScriptEval") || -+ message.contains("JavaScriptGetMember") || -+ message.contains("JavaScriptGetSlot") || -+ message.contains("JavaScriptToString"); -+ } -+} -+ -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java openjdk/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java 2008-09-15 16:22:06.000000000 -0400 -@@ -0,0 +1,66 @@ -+/* GetWindowPluginCallRequest -- represent Java-to-JavaScript requests -+ Copyright (C) 2008 Red Hat -+ -+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; either version 2, or (at your option) -+any later version. -+ -+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 sun.applet; -+ -+class GetWindowPluginCallRequest extends PluginCallRequest { -+ // FIXME: look into int vs long JavaScript internal values. -+ int internal; -+ -+ public GetWindowPluginCallRequest(String message, String returnString) { -+ super(message, returnString); -+ } -+ -+ public void parseReturn(String message) { -+ System.out.println ("GetWINDOWparseReturn GOT: " + message); -+ String[] args = message.split(" "); -+ // FIXME: add thread ID to messages to support multiple -+ // threads using the netscape.javascript package. -+ internal = Integer.parseInt(args[1]); -+ done = true; -+ } -+ -+ /** -+ * Returns whether the given message is serviceable by this object -+ * -+ * @param message The message to service -+ * @return boolean indicating if message is serviceable -+ */ -+ public boolean serviceable(String message) { -+ return message.contains("JavaScriptGetWindow"); -+ } -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java openjdk/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java 2008-09-15 16:22:07.000000000 -0400 -@@ -0,0 +1,847 @@ -+/* PluginAppletSecurityContext -- execute plugin JNI messages -+ Copyright (C) 2008 Red Hat -+ -+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; either version 2, or (at your option) -+any later version. -+ -+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 sun.applet; -+ -+import java.lang.reflect.Array; -+import java.lang.reflect.Constructor; -+import java.lang.reflect.Field; -+import java.lang.reflect.Method; -+import java.util.ArrayList; -+import java.util.HashMap; -+import java.util.List; -+import java.util.StringTokenizer; -+ -+class Signature { -+ private String signature; -+ private int currentIndex; -+ private List<Class> typeList; -+ private static final char ARRAY = '['; -+ private static final char OBJECT = 'L'; -+ private static final char SIGNATURE_ENDCLASS = ';'; -+ private static final char SIGNATURE_FUNC = '('; -+ private static final char SIGNATURE_ENDFUNC = ')'; -+ private static final char VOID = 'V'; -+ private static final char BOOLEAN = 'Z'; -+ private static final char BYTE = 'B'; -+ private static final char CHARACTER = 'C'; -+ private static final char SHORT = 'S'; -+ private static final char INTEGER = 'I'; -+ private static final char LONG = 'J'; -+ private static final char FLOAT = 'F'; -+ private static final char DOUBLE = 'D'; -+ -+ private String nextTypeName() { -+ char key = signature.charAt(currentIndex++); -+ -+ switch (key) { -+ case ARRAY: -+ return nextTypeName() + "[]"; -+ -+ case OBJECT: -+ int endClass = signature.indexOf(SIGNATURE_ENDCLASS, currentIndex); -+ String retVal = signature.substring(currentIndex, endClass); -+ retVal = retVal.replace('/', '.'); -+ currentIndex = endClass + 1; -+ return retVal; -+ -+ // FIXME: generated bytecode with classes named after -+ // primitives will not work in this scheme -- those -+ // classes will be incorrectly treated as primitive -+ // types. -+ case VOID: -+ return "void"; -+ case BOOLEAN: -+ return "boolean"; -+ case BYTE: -+ return "byte"; -+ case CHARACTER: -+ return "char"; -+ case SHORT: -+ return "short"; -+ case INTEGER: -+ return "int"; -+ case LONG: -+ return "long"; -+ case FLOAT: -+ return "float"; -+ case DOUBLE: -+ return "double"; -+ -+ case SIGNATURE_ENDFUNC: -+ case SIGNATURE_FUNC: -+ return nextTypeName(); -+ -+ default: -+ throw new IllegalArgumentException( -+ "Invalid JNI signature character '" + key + "'"); -+ } -+ } -+ -+ public Signature(String signature, String src) { -+ this.signature = signature; -+ currentIndex = 0; -+ typeList = new ArrayList<Class>(10); -+ -+ String elem; -+ while (currentIndex < signature.length()) { -+ elem = nextTypeName(); -+ // System.out.println ("NEXT TYPE: " + elem); -+ Class primitive = primitiveNameToType(elem); -+ if (primitive != null) -+ typeList.add(primitive); -+ else { -+ // System.out.println ("HERE1"); -+ int dimsize = 0; -+ int n = elem.indexOf('['); -+ if (n != -1) { -+ // System.out.println ("HERE2"); -+ String arrayType = elem.substring(0, n); -+ dimsize++; -+ n = elem.indexOf('[', n + 1); -+ // System.out.println ("HERE2.5"); -+ while (n != -1) { -+ dimsize++; -+ n = elem.indexOf('[', n + 1); -+ // System.out.println ("HERE2.8"); -+ } -+ int[] dims = new int[dimsize]; -+ primitive = primitiveNameToType(arrayType); -+ // System.out.println ("HERE3"); -+ if (primitive != null) { -+ typeList.add(Array.newInstance(primitive, dims) -+ .getClass()); -+ // System.out.println ("HERE4"); -+ } else -+ typeList.add(Array.newInstance( -+ getClass(arrayType, src), dims).getClass()); -+ } else { -+ typeList.add(getClass(elem, src)); -+ } -+ } -+ } -+ if (typeList.size() == 0) { -+ throw new IllegalArgumentException("Invalid JNI signature '" -+ + signature + "'"); -+ } -+ } -+ -+ public static Class getClass(String name, String src) { -+ -+ Class c = null; -+ -+ try { -+ c = Class.forName(name); -+ } catch (ClassNotFoundException cnfe) { -+ -+ StringTokenizer st = new StringTokenizer(src, ","); -+ -+ while (st.hasMoreTokens()) { -+ -+ String tok = st.nextToken(); -+ System.err.println("Searching for " + name + " at key " + tok); -+ -+ try { -+ c = PluginAppletSecurityContext.classLoaders.get(tok).loadClass(name); -+ } catch (ClassNotFoundException e) { -+ // do nothing .. thrown below -+ } -+ -+ if (c != null) -+ break; -+ } -+ } -+ -+ if (c == null) { -+ throw (new RuntimeException(new ClassNotFoundException("Unable to find class " + name))); -+ } -+ -+ return c; -+ } -+ -+ public static Class primitiveNameToType(String name) { -+ if (name.equals("void")) -+ return Void.TYPE; -+ else if (name.equals("boolean")) -+ return Boolean.TYPE; -+ else if (name.equals("byte")) -+ return Byte.TYPE; -+ else if (name.equals("char")) -+ return Character.TYPE; -+ else if (name.equals("short")) -+ return Short.TYPE; -+ else if (name.equals("int")) -+ return Integer.TYPE; -+ else if (name.equals("long")) -+ return Long.TYPE; -+ else if (name.equals("float")) -+ return Float.TYPE; -+ else if (name.equals("double")) -+ return Double.TYPE; -+ else -+ return null; -+ } -+ -+ public Class[] getClassArray() { -+ return typeList.subList(0, typeList.size() - 1).toArray(new Class[] {}); -+ } -+} -+ -+public class PluginAppletSecurityContext { -+ // Context identifier -> PluginAppletSecurityContext object. -+ // FIXME: make private -+ public static HashMap<Integer, PluginAppletSecurityContext> contexts = new HashMap(); -+ -+ public static HashMap<String, ClassLoader> classLoaders = new HashMap<String, ClassLoader>(); -+ -+ // FIXME: make private -+ public PluginObjectStore store = new PluginObjectStore(); -+ private Throwable throwable = null; -+ private ClassLoader liveconnectLoader = ClassLoader.getSystemClassLoader(); -+ int identifier = 0; -+ -+ static { -+ // FIXME: when should we add each new security context? but how would -+ // we be able to know which context applies to which request from nspr? -+ // the nspr jni functions do not know what applet they are being called -+ // in reference to -+ contexts.put(0, new PluginAppletSecurityContext(0)); -+ } -+ -+ public PluginAppletSecurityContext(int identifier) { -+ this.identifier = identifier; -+ } -+ -+ public static <V> V parseCall(String s, String src, Class<V> c) { -+ if (c == Integer.class) -+ return (V) new Integer(s); -+ else if (c == String.class) -+ return (V) new String(s); -+ else if (c == Signature.class) -+ return (V) new Signature(s, src); -+ else -+ throw new RuntimeException("Unexpected call value."); -+ } -+ -+ public Object parseArgs(String s, Class c) { -+ if (c == Boolean.TYPE || c == Boolean.class) -+ return new Boolean(s); -+ else if (c == Byte.TYPE || c == Byte.class) -+ return new Byte(s); -+ else if (c == Character.TYPE || c == Character.class) { -+ String[] bytes = s.split("_"); -+ int low = Integer.parseInt(bytes[0]); -+ int high = Integer.parseInt(bytes[1]); -+ int full = ((high << 8) & 0x0ff00) | (low & 0x0ff); -+ return new Character((char) full); -+ } else if (c == Short.TYPE || c == Short.class) -+ return new Short(s); -+ else if (c == Integer.TYPE || c == Integer.class) -+ return new Integer(s); -+ else if (c == Long.TYPE || c == Long.class) -+ return new Long(s); -+ else if (c == Float.TYPE || c == Float.class) -+ return new Float(s); -+ else if (c == Double.TYPE || c == Double.class) -+ return new Double(s); -+ else -+ return store.getObject(new Integer(s)); -+ } -+ -+ public static void handleMessage(int identifier, String src, int reference, -+ String message) { -+ contexts.get(identifier).handleMessage(reference, src, message); -+ } -+ -+ public void handleMessage(int reference, String src, String message) { -+ -+ try { -+ if (message.startsWith("FindClass")) { -+ ClassLoader cl = null; -+ Class c = null; -+ cl = liveconnectLoader; -+ String className = message.substring("FindClass".length() + 1) -+ .replace('/', '.'); -+ -+ try { -+ c = cl.loadClass(className); -+ store.reference(c); -+ write(reference, "FindClass " + store.getIdentifier(c)); -+ } catch (ClassNotFoundException cnfe) { -+ write(reference, "FindClass 0"); -+ } -+ -+ } else if (message.startsWith("GetStaticMethodID") -+ || message.startsWith("GetMethodID")) { -+ String[] args = message.split(" "); -+ Integer classID = parseCall(args[1], src, Integer.class); -+ String methodName = parseCall(args[2], src, String.class); -+ Signature signature = parseCall(args[3], src, Signature.class); -+ Object[] a = signature.getClassArray(); -+ -+ Class c = (Class) store.getObject(classID); -+ Method m = null; -+ Constructor cs = null; -+ Object o = null; -+ if (methodName.equals("<init>") -+ || methodName.equals("<clinit>")) { -+ o = cs = c.getConstructor(signature.getClassArray()); -+ store.reference(cs); -+ } else { -+ o = m = c.getMethod(methodName, signature.getClassArray()); -+ store.reference(m); -+ } -+ PluginDebug.debug(o + " has id " + store.getIdentifier(o)); -+ write(reference, args[0] + " " + store.getIdentifier(o)); -+ } else if (message.startsWith("GetStaticFieldID") -+ || message.startsWith("GetFieldID")) { -+ String[] args = message.split(" "); -+ Integer classID = parseCall(args[1], src, Integer.class); -+ String fieldName = parseCall(args[2], src, String.class); -+ Signature signature = parseCall(args[3], src, Signature.class); -+ -+ Class c = (Class) store.getObject(classID); -+ Field f = null; -+ f = c.getField(fieldName); -+ -+ store.reference(f); -+ -+ write(reference, "GetStaticFieldID " + store.getIdentifier(f)); -+ } else if (message.startsWith("GetStaticField")) { -+ String[] args = message.split(" "); -+ String type = parseCall(args[1], src, String.class); -+ Integer classID = parseCall(args[1], src, Integer.class); -+ Integer fieldID = parseCall(args[2], src, Integer.class); -+ -+ Class c = (Class) store.getObject(classID); -+ Field f = (Field) store.getObject(fieldID); -+ -+ Object ret = null; -+ ret = f.get(c); -+ -+ // System.out.println ("FIELD VALUE: " + ret); -+ if (ret == null) { -+ write(reference, "GetStaticField 0"); -+ } else if (f.getType() == Boolean.TYPE -+ || f.getType() == Byte.TYPE -+ || f.getType() == Character.TYPE -+ || f.getType() == Short.TYPE -+ || f.getType() == Integer.TYPE -+ || f.getType() == Long.TYPE -+ || f.getType() == Float.TYPE -+ || f.getType() == Double.TYPE) { -+ write(reference, "GetStaticField " + ret); -+ } else { -+ // Track returned object. -+ store.reference(ret); -+ write(reference, "GetStaticField " -+ + store.getIdentifier(ret)); -+ } -+ } else if (message.startsWith("SetStaticField")) { -+ String[] args = message.split(" "); -+ String type = parseCall(args[1], src, String.class); -+ Integer classID = parseCall(args[2], src, Integer.class); -+ Integer fieldID = parseCall(args[3], src, Integer.class); -+ -+ Object value = null; -+ if (Signature.primitiveNameToType(type) != null) { -+ value = parseArgs(args[4], Signature -+ .primitiveNameToType(type)); -+ // System.out.println ("HERE1: " + value); -+ } else { -+ value = parseArgs(args[3], Object.class); -+ // System.out.println ("HERE2: " + value); -+ } -+ -+ Class c = (Class) store.getObject(classID); -+ Field f = (Field) store.getObject(fieldID); -+ -+ f.set(c, value); -+ -+ write(reference, "SetStaticField"); -+ } else if (message.startsWith("SetField")) { -+ String[] args = message.split(" "); -+ String type = parseCall(args[1], src, String.class); -+ Integer objectID = parseCall(args[2], src, Integer.class); -+ Integer fieldID = parseCall(args[3], src, Integer.class); -+ -+ Object value = null; -+ if (Signature.primitiveNameToType(type) != null) { -+ value = parseArgs(args[4], Signature -+ .primitiveNameToType(type)); -+ // System.out.println ("HERE1: " + value); -+ } else { -+ value = parseArgs(args[3], Object.class); -+ // System.out.println ("HERE2: " + value); -+ } -+ -+ Object o = (Object) store.getObject(objectID); -+ Field f = (Field) store.getObject(fieldID); -+ -+ f.set(o, value); -+ -+ write(reference, "SetField"); -+ } else if (message.startsWith("GetObjectArrayElement")) { -+ String[] args = message.split(" "); -+ Integer arrayID = parseCall(args[1], src, Integer.class); -+ Integer index = parseCall(args[2], src, Integer.class); -+ -+ Object[] o = (Object[]) store.getObject(arrayID); -+ Object ret = null; -+ -+ ret = o[index]; -+ -+ // Track returned object. -+ store.reference(ret); -+ // System.out.println ("array element: " + index + " " + ret); -+ write(reference, "GetObjectArrayElement " -+ + store.getIdentifier(ret)); -+ } else if (message.startsWith("SetObjectArrayElement")) { -+ String[] args = message.split(" "); -+ Integer arrayID = parseCall(args[1], src, Integer.class); -+ Integer index = parseCall(args[2], src, Integer.class); -+ Integer objectID = parseCall(args[3], src, Integer.class); -+ -+ Object[] o = (Object[]) store.getObject(arrayID); -+ Object toSet = (Object) store.getObject(objectID); -+ -+ o[index] = toSet; -+ -+ write(reference, "SetObjectArrayElement"); -+ } else if (message.startsWith("GetArrayLength")) { -+ String[] args = message.split(" "); -+ Integer arrayID = parseCall(args[1], src, Integer.class); -+ -+ System.out.println("ARRAYID: " + arrayID); -+ Object o = (Object) store.getObject(arrayID); -+ int len = 0; -+ len = Array.getLength(o); -+ // System.out.println ("Returning array length: " + len); -+ -+ // System.out.println ("array length: " + o + " " + len); -+ write(reference, "GetArrayLength " + Array.getLength(o)); -+ } else if (message.startsWith("GetField")) { -+ String[] args = message.split(" "); -+ String type = parseCall(args[1], src, String.class); -+ Integer objectID = parseCall(args[1], src, Integer.class); -+ Integer fieldID = parseCall(args[2], src, Integer.class); -+ -+ Object o = (Object) store.getObject(objectID); -+ Field f = (Field) store.getObject(fieldID); -+ -+ Object ret = null; -+ ret = f.get(o); -+ -+ // System.out.println ("FIELD VALUE: " + ret); -+ if (ret == null) { -+ write(reference, "GetField 0"); -+ } else if (f.getType() == Boolean.TYPE -+ || f.getType() == Byte.TYPE -+ || f.getType() == Character.TYPE -+ || f.getType() == Short.TYPE -+ || f.getType() == Integer.TYPE -+ || f.getType() == Long.TYPE -+ || f.getType() == Float.TYPE -+ || f.getType() == Double.TYPE) { -+ write(reference, "GetField " + ret); -+ } else { -+ // Track returned object. -+ store.reference(ret); -+ write(reference, "GetField " + store.getIdentifier(ret)); -+ } -+ } else if (message.startsWith("GetObjectClass")) { -+ int oid = Integer.parseInt(message.substring("GetObjectClass" -+ .length() + 1)); -+ // System.out.println ("GETTING CLASS FOR: " + oid); -+ Class c = store.getObject(oid).getClass(); -+ // System.out.println (" OBJ: " + store.getObject(oid)); -+ // System.out.println (" CLS: " + c); -+ store.reference(c); -+ -+ write(reference, "GetObjectClass " + store.getIdentifier(c)); -+ } else if (message.startsWith("CallStaticMethod")) { -+ String[] args = message.split(" "); -+ Integer classID = parseCall(args[1], src, Integer.class); -+ Integer methodID = parseCall(args[2], src, Integer.class); -+ -+ System.out.println("GETTING: " + methodID); -+ Method m = (Method) store.getObject(methodID); -+ System.out.println("GOT: " + m); -+ Class[] argTypes = m.getParameterTypes(); -+ -+ Object[] arguments = new Object[argTypes.length]; -+ for (int i = 0; i < argTypes.length; i++) { -+ arguments[i] = parseArgs(args[3 + i], argTypes[i]); -+ // System.out.println ("GOT ARG: " + argTypes[i] + " " + -+ // arguments[i]); -+ } -+ -+ // System.out.println ("Calling " + m); -+ Object ret = null; -+ ret = m.invoke(null, arguments); -+ -+ // if (ret != null) -+ // System.out.println ("RETURN VALUE: " + ret + " " + -+ // ret.getClass()); -+ // else -+ // System.out.println ("RETURN VALUE: " + ret); -+ if (ret == null) { -+ write(reference, "CallStaticMethod void"); -+ } else if (m.getReturnType() == Boolean.TYPE -+ || m.getReturnType() == Byte.TYPE -+ || m.getReturnType() == Short.TYPE -+ || m.getReturnType() == Integer.TYPE -+ || m.getReturnType() == Long.TYPE -+ || m.getReturnType() == Float.TYPE -+ || m.getReturnType() == Double.TYPE) { -+ write(reference, "CallStaticMethod " + ret); -+ } else if (m.getReturnType() == Character.TYPE) { -+ char ch = (Character) ret; -+ int high = (((int) ch) >> 8) & 0x0ff; -+ int low = ((int) ch) & 0x0ff; -+ write(reference, "CallStaticMethod " + low + "_" + high); -+ } else { -+ // Track returned object. -+ store.reference(ret); -+ write(reference, "CallStaticMethod " -+ + store.getIdentifier(ret)); -+ } -+ } else if (message.startsWith("CallMethod")) { -+ String[] args = message.split(" "); -+ Integer objectID = parseCall(args[1], src, Integer.class); -+ Integer methodID = parseCall(args[2], src, Integer.class); -+ -+ Object o = (Object) store.getObject(objectID); -+ Method m = (Method) store.getObject(methodID); -+ Class[] argTypes = m.getParameterTypes(); -+ -+ Object[] arguments = new Object[argTypes.length]; -+ for (int i = 0; i < argTypes.length; i++) { -+ arguments[i] = parseArgs(args[3 + i], argTypes[i]); -+ PluginDebug.debug("GOT ARG: " + argTypes[i] + " " -+ + arguments[i]); -+ } -+ -+ String collapsedArgs = ""; -+ for (String s : args) { -+ collapsedArgs += " " + s; -+ } -+ -+ PluginDebug.debug("Calling method " + m + " on object " + o -+ + " with " + arguments); -+ Object ret = null; -+ ret = m.invoke(o, arguments); -+ -+ String retO; -+ if (ret == null) { -+ retO = "null"; -+ } else { -+ retO = ret.getClass().toString(); -+ } -+ -+ PluginDebug.debug("Calling " + m + " on " + o + " with " -+ + collapsedArgs + " and that returned: " + ret -+ + " of type " + retO); -+ -+ if (ret == null) { -+ write(reference, "CallMethod void"); -+ } else if (m.getReturnType() == Boolean.TYPE -+ || m.getReturnType() == Byte.TYPE -+ || m.getReturnType() == Short.TYPE -+ || m.getReturnType() == Integer.TYPE -+ || m.getReturnType() == Long.TYPE -+ || m.getReturnType() == Float.TYPE -+ || m.getReturnType() == Double.TYPE) { -+ write(reference, "CallMethod " + ret); -+ } else if (m.getReturnType() == Character.TYPE) { -+ char ch = (Character) ret; -+ int high = (((int) ch) >> 8) & 0x0ff; -+ int low = ((int) ch) & 0x0ff; -+ write(reference, "CallMethod " + low + "_" + high); -+ } else { -+ // Track returned object. -+ store.reference(ret); -+ write(reference, "CallMethod " + store.getIdentifier(ret)); -+ } -+ } else if (message.startsWith("GetSuperclass")) { -+ String[] args = message.split(" "); -+ Integer classID = parseCall(args[1], src, Integer.class); -+ Class c = null; -+ Class ret = null; -+ -+ c = (Class) store.getObject(classID); -+ ret = c.getSuperclass(); -+ store.reference(ret); -+ -+ write(reference, "GetSuperclass " + store.getIdentifier(ret)); -+ } else if (message.startsWith("IsAssignableFrom")) { -+ String[] args = message.split(" "); -+ Integer classID = parseCall(args[1], src, Integer.class); -+ Integer superclassID = parseCall(args[2], src, Integer.class); -+ -+ boolean result = false; -+ Class clz = (Class) store.getObject(classID); -+ Class sup = (Class) store.getObject(superclassID); -+ -+ result = sup.isAssignableFrom(clz); -+ -+ write(reference, "IsAssignableFrom " + (result ? "1" : "0")); -+ } else if (message.startsWith("IsInstanceOf")) { -+ String[] args = message.split(" "); -+ Integer objectID = parseCall(args[1], src, Integer.class); -+ Integer classID = parseCall(args[2], src, Integer.class); -+ -+ boolean result = false; -+ Object o = (Object) store.getObject(objectID); -+ Class c = (Class) store.getObject(classID); -+ -+ result = c.isInstance(o); -+ -+ write(reference, "IsInstanceOf " + (result ? "1" : "0")); -+ } else if (message.startsWith("GetStringUTFLength")) { -+ String[] args = message.split(" "); -+ Integer stringID = parseCall(args[1], src, Integer.class); -+ -+ String o = null; -+ byte[] b = null; -+ o = (String) store.getObject(stringID); -+ b = o.getBytes("UTF-8"); -+ // System.out.println ("STRING UTF-8 LENGTH: " + o + " " + -+ // b.length); -+ -+ write(reference, "GetStringUTFLength " + o.length()); -+ } else if (message.startsWith("GetStringLength")) { -+ String[] args = message.split(" "); -+ Integer stringID = parseCall(args[1], src, Integer.class); -+ -+ String o = null; -+ byte[] b = null; -+ o = (String) store.getObject(stringID); -+ b = o.getBytes("UTF-16LE"); -+ // System.out.println ("STRING UTF-16 LENGTH: " + o + " " + -+ // b.length); -+ -+ // System.out.println ("Java: GetStringLength " + b.length); -+ write(reference, "GetStringLength " + o.length()); -+ } else if (message.startsWith("GetStringUTFChars")) { -+ String[] args = message.split(" "); -+ Integer stringID = parseCall(args[1], src, Integer.class); -+ -+ String o = null; -+ byte[] b = null; -+ StringBuffer buf = null; -+ o = (String) store.getObject(stringID); -+ b = o.getBytes("UTF-8"); -+ buf = new StringBuffer(b.length * 2); -+ buf.append(b.length); -+ for (int i = 0; i < b.length; i++) -+ buf -+ .append(" " -+ + Integer -+ .toString(((int) b[i]) & 0x0ff, 16)); -+ -+ // System.out.println ("Java: GetStringUTFChars: " + o); -+ // //System.out.println ("String UTF BYTES: " + buf); -+ write(reference, "GetStringUTFChars " + buf); -+ } else if (message.startsWith("GetStringChars")) { -+ String[] args = message.split(" "); -+ Integer stringID = parseCall(args[1], src, Integer.class); -+ -+ String o = null; -+ byte[] b = null; -+ StringBuffer buf = null; -+ o = (String) store.getObject(stringID); -+ // FIXME: LiveConnect uses UCS-2. -+ b = o.getBytes("UTF-16LE"); -+ buf = new StringBuffer(b.length * 2); -+ buf.append(b.length); -+ for (int i = 0; i < b.length; i++) -+ buf -+ .append(" " -+ + Integer -+ .toString(((int) b[i]) & 0x0ff, 16)); -+ -+ System.out.println("Java: GetStringChars: " + o); -+ System.out.println(" String BYTES: " + buf); -+ write(reference, "GetStringChars " + buf); -+ } else if (message.startsWith("NewArray")) { -+ String[] args = message.split(" "); -+ String type = parseCall(args[1], src, String.class); -+ Integer length = parseCall(args[2], src, Integer.class); -+ -+ // System.out.println ("CALLING: NewArray: " + type + " " + -+ // length + " " -+ // + Signature.primitiveNameToType(type)); -+ -+ Object newArray = null; -+ newArray = Array.newInstance(Signature -+ .primitiveNameToType(type), length); -+ -+ store.reference(newArray); -+ write(reference, "NewArray " + store.getIdentifier(newArray)); -+ } else if (message.startsWith("NewObjectArray")) { -+ String[] args = message.split(" "); -+ Integer length = parseCall(args[1], src, Integer.class); -+ Integer classID = parseCall(args[2], src, Integer.class); -+ Integer objectID = parseCall(args[3], src, Integer.class); -+ -+ // System.out.println ("CALLING: NewObjectArray: " + -+ // classID + " " + length + " " -+ // + objectID); -+ -+ Object newArray = null; -+ newArray = Array.newInstance((Class) store.getObject(classID), -+ length); -+ -+ Object[] array = (Object[]) newArray; -+ for (int i = 0; i < array.length; i++) -+ array[i] = store.getObject(objectID); -+ store.reference(newArray); -+ write(reference, "NewObjectArray " -+ + store.getIdentifier(newArray)); -+ } else if (message.startsWith("NewObject")) { -+ String[] args = message.split(" "); -+ Integer classID = parseCall(args[1], src, Integer.class); -+ Integer methodID = parseCall(args[2], src, Integer.class); -+ -+ Constructor m = (Constructor) store.getObject(methodID); -+ Class[] argTypes = m.getParameterTypes(); -+ -+ // System.out.println ("NEWOBJ: HERE1"); -+ Object[] arguments = new Object[argTypes.length]; -+ // System.out.println ("NEWOBJ: HERE2"); -+ for (int i = 0; i < argTypes.length; i++) { -+ arguments[i] = parseArgs(args[3 + i], argTypes[i]); -+ // System.out.println ("NEWOBJ: GOT ARG: " + arguments[i]); -+ } -+ -+ // System.out.println ("NEWOBJ: Calling " + m); -+ Object ret = null; -+ ret = m.newInstance(arguments); -+ -+ // System.out.println ("NEWOBJ: CALLED: " + ret); -+ // System.out.println ("NEWOBJ: CALLED: " + -+ // store.getObject(ret)); -+ store.reference(ret); -+ write(reference, "NewObject " + store.getIdentifier(ret)); -+ } else if (message.startsWith("NewString")) { -+ System.out.println("MESSAGE: " + message); -+ String[] args = message.split(" "); -+ Integer strlength = parseCall(args[1], src, Integer.class); -+ int bytelength = 2 * strlength; -+ byte[] byteArray = new byte[bytelength]; -+ String ret = null; -+ for (int i = 0; i < strlength; i++) { -+ int c = parseCall(args[2 + i], src, Integer.class); -+ System.out.println("char " + i + " " + c); -+ // Low. -+ byteArray[2 * i] = (byte) (c & 0x0ff); -+ // High. -+ byteArray[2 * i + 1] = (byte) ((c >> 8) & 0x0ff); -+ } -+ ret = new String(byteArray, 0, bytelength, "UTF-16LE"); -+ System.out.println("NEWSTRING: " + ret); -+ -+ // System.out.println ("NEWOBJ: CALLED: " + ret); -+ // System.out.println ("NEWOBJ: CALLED: " + -+ // store.getObject(ret)); -+ store.reference(ret); -+ write(reference, "NewString " + store.getIdentifier(ret)); -+ } else if (message.startsWith("NewStringUTF")) { -+ System.out.println("MESSAGE: " + message); -+ String[] args = message.split(" "); -+ byte[] byteArray = new byte[60]; -+ String ret = null; -+ int i = 0; -+ int c = 0; -+ while (((byte) c) != 0) { -+ c = parseCall(args[1 + i], src, Integer.class); -+ byteArray[i] = (byte) c; -+ i++; -+ if (i == byteArray.length) { -+ byte[] newByteArray = new byte[2 * byteArray.length]; -+ System.arraycopy(byteArray, 0, newByteArray, 0, -+ byteArray.length); -+ byteArray = newByteArray; -+ } -+ } -+ byteArray[i] = (byte) 0; -+ ret = new String(byteArray, "UTF-8"); -+ System.out.println("NEWSTRINGUTF: " + ret); -+ -+ store.reference(ret); -+ write(reference, "NewStringUTF " + store.getIdentifier(ret)); -+ } else if (message.startsWith("ExceptionOccurred")) { -+ System.out.println("EXCEPTION: " + throwable); -+ if (throwable != null) -+ store.reference(throwable); -+ write(reference, "ExceptionOccurred " -+ + store.getIdentifier(throwable)); -+ } else if (message.startsWith("ExceptionClear")) { -+ if (throwable != null) -+ store.unreference(store.getIdentifier(throwable)); -+ throwable = null; -+ write(reference, "ExceptionClear"); -+ } else if (message.startsWith("DeleteGlobalRef")) { -+ String[] args = message.split(" "); -+ Integer id = parseCall(args[1], src, Integer.class); -+ store.unreference(id); -+ write(reference, "DeleteGlobalRef"); -+ } else if (message.startsWith("DeleteLocalRef")) { -+ String[] args = message.split(" "); -+ Integer id = parseCall(args[1], src, Integer.class); -+ store.unreference(id); -+ write(reference, "DeleteLocalRef"); -+ } else if (message.startsWith("NewGlobalRef")) { -+ String[] args = message.split(" "); -+ Integer id = parseCall(args[1], src, Integer.class); -+ store.reference(store.getObject(id)); -+ write(reference, "NewGlobalRef " + id); -+ } -+ } catch (Throwable t) { -+ t.printStackTrace(); -+ throwable = t; -+ PluginException p = new PluginException(identifier, reference, t); -+ } -+ } -+ -+ public void write(int reference, String message) { -+ PluginDebug.debug("appletviewer writing " + message); -+ PluginMain.write("context " + identifier + " reference " + reference -+ + " " + message); -+ } -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletViewer.java openjdk/jdk/src/share/classes/sun/applet/PluginAppletViewer.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletViewer.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginAppletViewer.java 2008-09-15 16:22:07.000000000 -0400 -@@ -0,0 +1,1439 @@ -+ /* -+ * Copyright 1995-2004 Sun Microsystems, Inc. All Rights Reserved. -+ * 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. -+ * -+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -+ * CA 95054 USA or visit www.sun.com if you need additional information or -+ * have any questions. -+ */ -+ -+ package sun.applet; -+ -+ import java.util.*; -+ import java.io.*; -+ import java.awt.*; -+ import java.awt.event.*; -+ import java.awt.print.*; -+ import javax.print.attribute.*; -+ import java.applet.*; -+ import java.net.URL; -+ import java.net.MalformedURLException; -+ import java.net.SocketPermission; -+ import sun.misc.Ref; -+ import java.security.AccessController; -+ import java.security.PrivilegedAction; -+ import java.lang.reflect.InvocationTargetException; -+ import java.lang.reflect.Method; -+ import sun.awt.SunToolkit; -+ import sun.awt.AppContext; -+ import sun.awt.X11.*; -+ import java.lang.ref.WeakReference; -+ import net.sourceforge.jnlp.NetxPanel; -+ -+ /** -+ * Lets us construct one using unix-style one shot behaviors -+ */ -+ -+ class PluginAppletViewerFactory -+ { -+ public PluginAppletViewer createAppletViewer(int identifier, -+ long handle, int x, int y, -+ URL doc, Hashtable atts) { -+ PluginAppletViewer pluginappletviewer = new PluginAppletViewer(identifier, handle, x, y, doc, atts, System.out, this); -+ return pluginappletviewer; -+ } -+ -+ public boolean isStandalone() -+ { -+ return false; -+ } -+ } -+ -+ class PluginParseRequest -+ { -+ long handle; -+ String tag; -+ String documentbase; -+ } -+ -+ /* -+ */ -+ // FIXME: declare JSProxy implementation -+ public class PluginAppletViewer extends XEmbeddedFrame -+ implements AppletContext, Printable { -+ /** -+ * Some constants... -+ */ -+ private static String defaultSaveFile = "Applet.ser"; -+ -+ /** -+ * The panel in which the applet is being displayed. -+ */ -+ AppletViewerPanel panel; -+ -+ /** -+ * The status line. -+ */ -+ Label label; -+ -+ /** -+ * output status messages to this stream -+ */ -+ -+ PrintStream statusMsgStream; -+ -+ /** -+ * For cloning -+ */ -+ PluginAppletViewerFactory factory; -+ -+ int identifier; -+ -+ private static HashMap<Integer, PluginParseRequest> requests = new HashMap(); -+ -+ // Instance identifier -> PluginAppletViewer object. -+ private static HashMap<Integer, PluginAppletViewer> applets = new HashMap(); -+ -+ /** -+ * Create the applet viewer -+ */ -+ public PluginAppletViewer(int identifier, long handle, int x, int y, final URL doc, -+ final Hashtable atts, PrintStream statusMsgStream, -+ PluginAppletViewerFactory factory) { -+ super(handle, true); -+ this.factory = factory; -+ this.statusMsgStream = statusMsgStream; -+ this.identifier = identifier; -+ // FIXME: when/where do we remove this? -+ PluginDebug.debug ("PARSING: PUTTING " + identifier + " " + this); -+ applets.put(identifier, this); -+ -+ try { -+ panel = new NetxPanel(doc, atts); -+ AppletViewerPanel.debug("Using NetX panel"); -+ } catch (Exception ex) { -+ AppletViewerPanel.debug("Unable to start NetX applet - defaulting to Sun applet", ex); -+ panel = new AppletViewerPanel(doc, atts); -+ } -+ -+ add("Center", panel); -+ panel.init(); -+ appletPanels.addElement(panel); -+ -+ pack(); -+ setVisible(true); -+ -+ WindowListener windowEventListener = new WindowAdapter() { -+ -+ public void windowClosing(WindowEvent evt) { -+ appletClose(); -+ } -+ -+ public void windowIconified(WindowEvent evt) { -+ appletStop(); -+ } -+ -+ public void windowDeiconified(WindowEvent evt) { -+ appletStart(); -+ } -+ }; -+ -+ class AppletEventListener implements AppletListener -+ { -+ final Frame frame; -+ -+ public AppletEventListener(Frame frame) -+ { -+ this.frame = frame; -+ } -+ -+ public void appletStateChanged(AppletEvent evt) -+ { -+ AppletPanel src = (AppletPanel)evt.getSource(); -+ -+ switch (evt.getID()) { -+ case AppletPanel.APPLET_RESIZE: { -+ if(src != null) { -+ resize(preferredSize()); -+ validate(); -+ } -+ break; -+ } -+ case AppletPanel.APPLET_LOADING_COMPLETED: { -+ Applet a = src.getApplet(); // sun.applet.AppletPanel -+ -+ // Fixed #4754451: Applet can have methods running on main -+ // thread event queue. -+ // -+ // The cause of this bug is that the frame of the applet -+ // is created in main thread group. Thus, when certain -+ // AWT/Swing events are generated, the events will be -+ // dispatched through the wrong event dispatch thread. -+ // -+ // To fix this, we rearrange the AppContext with the frame, -+ // so the proper event queue will be looked up. -+ // -+ // Swing also maintains a Frame list for the AppContext, -+ // so we will have to rearrange it as well. -+ // -+ if (a != null) -+ AppletPanel.changeFrameAppContext(frame, SunToolkit.targetToAppContext(a)); -+ else -+ AppletPanel.changeFrameAppContext(frame, AppContext.getAppContext()); -+ -+ break; -+ } -+ } -+ } -+ }; -+ -+ addWindowListener(windowEventListener); -+ panel.addAppletListener(new AppletEventListener(this)); -+ -+ // Start the applet -+ showStatus(amh.getMessage("status.start")); -+ initEventQueue(); -+ -+ try { -+ write("initialized"); -+ } catch (IOException ioe) { -+ ioe.printStackTrace(); -+ } -+ -+ // Wait for a maximum of 10 seconds for the panel to initialize -+ // (happens in a separate thread) -+ Applet a; -+ int maxSleepTime = 10000; -+ int sleepTime = 0; -+ while ((a = panel.getApplet()) == null && sleepTime < maxSleepTime) { -+ try { -+ Thread.sleep(100); -+ sleepTime += 100; -+ PluginDebug.debug("Waiting for applet to initialize... "); -+ } catch (InterruptedException ie) { -+ // ignore -+ } -+ } -+ -+ // Applet initialized. Find out it's classloader and add it to the list -+ PluginAppletSecurityContext.classLoaders.put(Integer.toString(identifier), a.getClass().getClassLoader()); -+ -+ } -+ -+ /** -+ * Handle an incoming message from the plugin. -+ */ -+ public static void handleMessage(int identifier, int reference, String message) -+ { -+ PluginDebug.debug("PAV handling: " + message); -+ -+ try { -+ if (message.startsWith("tag")) { -+ -+ // tag and handle must both be set before parsing, so we need -+ // synchronization here, as the setting of these variables -+ // may happen in independent threads -+ -+ synchronized(requests) { -+ PluginParseRequest request = requests.get(identifier); -+ if (request == null) { -+ request = new PluginParseRequest(); -+ requests.put(identifier, request); -+ } -+ int index = message.indexOf(' ', "tag".length() + 1); -+ request.documentbase = -+ message.substring("tag".length() + 1, index); -+ request.tag = message.substring(index + 1); -+ PluginDebug.debug ("REQUEST TAG: " + request.tag + " " + -+ Thread.currentThread()); -+ -+ if (request.handle != 0) { -+ PluginDebug.debug ("REQUEST TAG, PARSING " + -+ Thread.currentThread()); -+ PluginAppletViewer.parse -+ (identifier, request.handle, -+ new StringReader(request.tag), -+ new URL(request.documentbase)); -+ requests.remove(identifier); -+ } else { -+ PluginDebug.debug ("REQUEST HANDLE NOT SET: " + request.handle + ". BYPASSING"); -+ } -+ } -+ } else if (message.startsWith("handle")) { -+ synchronized(requests) { -+ PluginParseRequest request = requests.get(identifier); -+ if (request == null) { -+ request = new PluginParseRequest(); -+ requests.put(identifier, request); -+ } -+ request.handle = Long.parseLong -+ (message.substring("handle".length() + 1)); -+ PluginDebug.debug ("REQUEST HANDLE: " + request.handle); -+ if (request.tag != null) { -+ PluginDebug.debug ("REQUEST HANDLE, PARSING " + -+ Thread.currentThread()); -+ PluginAppletViewer.parse -+ (identifier, request.handle, -+ new StringReader(request.tag), -+ new URL(request.documentbase)); -+ requests.remove(identifier); -+ PluginDebug.debug ("REQUEST HANDLE, DONE PARSING " + -+ Thread.currentThread()); -+ } else { -+ PluginDebug.debug ("REQUEST HANDLE NOT SET: " + request.tag + ". BYPASSING"); -+ } -+ } -+ } else { -+ PluginDebug.debug ("HANDLING MESSAGE " + message + " instance " + identifier + " " + Thread.currentThread()); -+ applets.get(identifier).handleMessage(reference, message); -+ } -+ } catch (Exception e) { -+ throw new RuntimeException("Failed to handle message: " + message + " " + -+ Thread.currentThread(), e); -+ } -+ } -+ -+ public void handleMessage(int reference, String message) -+ { -+ if (message.startsWith("width")) { -+ int width = -+ Integer.parseInt(message.substring("width".length() + 1)); -+ panel.setAppletSizeIfNeeded(width, -1); -+ setSize(width, getHeight()); -+ } else if (message.startsWith("height")) { -+ int height = -+ Integer.parseInt(message.substring("height".length() + 1)); -+ panel.setAppletSizeIfNeeded(-1, height); -+ setSize(getWidth(), height); -+ } else if (message.startsWith("destroy")) { -+ dispose(); -+ } else if (message.startsWith("GetJavaObject")) { -+ // FIXME: how do we determine what security context this -+ // object should belong to? -+ Object o; -+ -+ // Wait for a maximum of 10 seconds for the panel to initialize -+ // (happens in a separate thread) -+ int maxSleepTime = 10000; -+ int sleepTime = 0; -+ while ((o = panel.getApplet()) == null && sleepTime < maxSleepTime) { -+ try { -+ Thread.sleep(100); -+ sleepTime += 100; -+ PluginDebug.debug("Waiting for applet to initialize..."); -+ } catch (InterruptedException ie) { -+ // ignore -+ } -+ } -+ -+ System.err.println ("Looking for object " + o + " panel is " + panel.getClass()); -+ PluginAppletSecurityContext.contexts.get(0).store.reference(o); -+ System.err.println ("WRITING 1: " + "context 0 reference " + reference + " GetJavaObject " -+ + PluginAppletSecurityContext.contexts.get(0).store.getIdentifier(o)); -+ PluginMain.write("context 0 reference " + reference + " GetJavaObject " -+ + PluginAppletSecurityContext.contexts.get(0).store.getIdentifier(o)); -+ System.err.println ("WRITING 1 DONE"); -+ } -+ } -+ -+ /** -+ * Send the initial set of events to the appletviewer event queue. -+ * On start-up the current behaviour is to load the applet and call -+ * Applet.init() and Applet.start(). -+ */ -+ private void initEventQueue() { -+ // appletviewer.send.event is an undocumented and unsupported system -+ // property which is used exclusively for testing purposes. -+ String eventList = System.getProperty("appletviewer.send.event"); -+ -+ if (eventList == null) { -+ // Add the standard events onto the event queue. -+ panel.sendEvent(AppletPanel.APPLET_LOAD); -+ panel.sendEvent(AppletPanel.APPLET_INIT); -+ panel.sendEvent(AppletPanel.APPLET_START); -+ } else { -+ // We're testing AppletViewer. Force the specified set of events -+ // onto the event queue, wait for the events to be processed, and -+ // exit. -+ -+ // The list of events that will be executed is provided as a -+ // ","-separated list. No error-checking will be done on the list. -+ String [] events = splitSeparator(",", eventList); -+ -+ for (int i = 0; i < events.length; i++) { -+ System.out.println("Adding event to queue: " + events[i]); -+ if (events[i].equals("dispose")) -+ panel.sendEvent(AppletPanel.APPLET_DISPOSE); -+ else if (events[i].equals("load")) -+ panel.sendEvent(AppletPanel.APPLET_LOAD); -+ else if (events[i].equals("init")) -+ panel.sendEvent(AppletPanel.APPLET_INIT); -+ else if (events[i].equals("start")) -+ panel.sendEvent(AppletPanel.APPLET_START); -+ else if (events[i].equals("stop")) -+ panel.sendEvent(AppletPanel.APPLET_STOP); -+ else if (events[i].equals("destroy")) -+ panel.sendEvent(AppletPanel.APPLET_DESTROY); -+ else if (events[i].equals("quit")) -+ panel.sendEvent(AppletPanel.APPLET_QUIT); -+ else if (events[i].equals("error")) -+ panel.sendEvent(AppletPanel.APPLET_ERROR); -+ else -+ // non-fatal error if we get an unrecognized event -+ System.out.println("Unrecognized event name: " + events[i]); -+ } -+ -+ while (!panel.emptyEventQueue()) ; -+ appletSystemExit(); -+ } -+ } -+ -+ /** -+ * Split a string based on the presence of a specified separator. Returns -+ * an array of arbitrary length. The end of each element in the array is -+ * indicated by the separator of the end of the string. If there is a -+ * separator immediately before the end of the string, the final element -+ * will be empty. None of the strings will contain the separator. Useful -+ * when separating strings such as "foo/bar/bas" using separator "/". -+ * -+ * @param sep The separator. -+ * @param s The string to split. -+ * @return An array of strings. Each string in the array is determined -+ * by the location of the provided sep in the original string, -+ * s. Whitespace not stripped. -+ */ -+ private String [] splitSeparator(String sep, String s) { -+ Vector v = new Vector(); -+ int tokenStart = 0; -+ int tokenEnd = 0; -+ -+ while ((tokenEnd = s.indexOf(sep, tokenStart)) != -1) { -+ v.addElement(s.substring(tokenStart, tokenEnd)); -+ tokenStart = tokenEnd+1; -+ } -+ // Add the final element. -+ v.addElement(s.substring(tokenStart)); -+ -+ String [] retVal = new String[v.size()]; -+ v.copyInto(retVal); -+ return retVal; -+ } -+ -+ /* -+ * Methods for java.applet.AppletContext -+ */ -+ -+ private static Map audioClips = new HashMap(); -+ -+ /** -+ * Get an audio clip. -+ */ -+ public AudioClip getAudioClip(URL url) { -+ checkConnect(url); -+ synchronized (audioClips) { -+ AudioClip clip = (AudioClip)audioClips.get(url); -+ if (clip == null) { -+ audioClips.put(url, clip = new AppletAudioClip(url)); -+ } -+ return clip; -+ } -+ } -+ -+ private static Map imageRefs = new HashMap(); -+ -+ /** -+ * Get an image. -+ */ -+ public Image getImage(URL url) { -+ return getCachedImage(url); -+ } -+ -+ static Image getCachedImage(URL url) { -+ // System.getSecurityManager().checkConnection(url.getHost(), url.getPort()); -+ return (Image)getCachedImageRef(url).get(); -+ } -+ -+ /** -+ * Get an image ref. -+ */ -+ static Ref getCachedImageRef(URL url) { -+ synchronized (imageRefs) { -+ AppletImageRef ref = (AppletImageRef)imageRefs.get(url); -+ if (ref == null) { -+ ref = new AppletImageRef(url); -+ imageRefs.put(url, ref); -+ } -+ return ref; -+ } -+ } -+ -+ /** -+ * Flush the image cache. -+ */ -+ static void flushImageCache() { -+ imageRefs.clear(); -+ } -+ -+ static Vector appletPanels = new Vector(); -+ -+ /** -+ * Get an applet by name. -+ */ -+ public Applet getApplet(String name) { -+ AppletSecurity security = (AppletSecurity)System.getSecurityManager(); -+ name = name.toLowerCase(); -+ SocketPermission panelSp = -+ new SocketPermission(panel.getCodeBase().getHost(), "connect"); -+ for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) { -+ AppletPanel p = (AppletPanel)e.nextElement(); -+ String param = p.getParameter("name"); -+ if (param != null) { -+ param = param.toLowerCase(); -+ } -+ if (name.equals(param) && -+ p.getDocumentBase().equals(panel.getDocumentBase())) { -+ -+ SocketPermission sp = -+ new SocketPermission(p.getCodeBase().getHost(), "connect"); -+ -+ if (panelSp.implies(sp)) { -+ return p.applet; -+ } -+ } -+ } -+ return null; -+ } -+ -+ /** -+ * Return an enumeration of all the accessible -+ * applets on this page. -+ */ -+ public Enumeration getApplets() { -+ AppletSecurity security = (AppletSecurity)System.getSecurityManager(); -+ Vector v = new Vector(); -+ SocketPermission panelSp = -+ new SocketPermission(panel.getCodeBase().getHost(), "connect"); -+ -+ for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) { -+ AppletPanel p = (AppletPanel)e.nextElement(); -+ if (p.getDocumentBase().equals(panel.getDocumentBase())) { -+ -+ SocketPermission sp = -+ new SocketPermission(p.getCodeBase().getHost(), "connect"); -+ if (panelSp.implies(sp)) { -+ v.addElement(p.applet); -+ } -+ } -+ } -+ return v.elements(); -+ } -+ -+ /** -+ * Ignore. -+ */ -+ public void showDocument(URL url) { -+ PluginDebug.debug("Showing document..."); -+ showDocument(url, "_self"); -+ } -+ -+ /** -+ * Ignore. -+ */ -+ public void showDocument(URL url, String target) { -+ try { -+ // FIXME: change to postCallRequest -+ write("url " + url + " " + target); -+ } catch (IOException exception) { -+ // Deliberately ignore IOException. showDocument may be -+ // called from threads other than the main thread after -+ // PluginMain.pluginOutputStream has been closed. -+ } -+ } -+ -+ /** -+ * Show status. -+ */ -+ public void showStatus(String status) { -+ try { -+ // FIXME: change to postCallRequest -+ write("status " + status); -+ } catch (IOException exception) { -+ // Deliberately ignore IOException. showStatus may be -+ // called from threads other than the main thread after -+ // PluginMain.pluginOutputStream has been closed. -+ } -+ } -+ -+ public int getWindow() { -+ System.out.println ("STARTING getWindow"); -+ GetWindowPluginCallRequest request = -+ new GetWindowPluginCallRequest("instance " + identifier + " " + -+ "GetWindow", "JavaScriptGetWindow"); -+ System.out.println ("STARTING postCallRequest"); -+ PluginMain.postCallRequest(request); -+ System.out.println ("STARTING postCallRequest done"); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait request 1"); -+ synchronized(request) { -+ System.out.println ("wait request 2"); -+ while (request.internal == 0) -+ request.wait(); -+ System.out.println ("wait request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ -+ System.out.println ("STARTING getWindow DONE"); -+ return request.internal; -+ } -+ -+ // FIXME: make private, access via reflection. -+ public static Object getMember(int internal, String name) -+ { -+ PluginAppletSecurityContext.contexts.get(0).store.reference(name); -+ int nameID = PluginAppletSecurityContext.contexts.get( -+ 0).store.getIdentifier(name); -+ -+ // Prefix with dummy instance for convenience. -+ GetMemberPluginCallRequest request = -+ new GetMemberPluginCallRequest("instance " + 0 + -+ " GetMember " + internal + -+ " " + nameID, "JavaScriptGetMember"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait getMEM request 1"); -+ synchronized(request) { -+ System.out.println ("wait getMEM request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait getMEM request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" getMember DONE"); -+ return request.object; -+ } -+ -+ public static void setMember(int internal, String name, Object value) { -+ PluginAppletSecurityContext.contexts.get(0).store.reference(name); -+ int nameID = PluginAppletSecurityContext.contexts.get( -+ 0).store.getIdentifier(name); -+ PluginAppletSecurityContext.contexts.get(0).store.reference(value); -+ int valueID = PluginAppletSecurityContext.contexts.get( -+ 0).store.getIdentifier(value); -+ -+ // Prefix with dummy instance for convenience. -+ VoidPluginCallRequest request = -+ new VoidPluginCallRequest("instance " + 0 + -+ " SetMember " + internal + -+ " " + nameID + " " + valueID, "JavaScriptSetMember"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait setMem request: " + request.message); -+ System.out.println ("wait setMem request 1"); -+ synchronized(request) { -+ System.out.println ("wait setMem request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait setMem request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" setMember DONE"); -+ } -+ -+ // FIXME: handle long index as well. -+ public static void setSlot(int internal, int index, Object value) { -+ PluginAppletSecurityContext.contexts.get(0).store.reference(value); -+ int valueID = PluginAppletSecurityContext.contexts.get( -+ 0).store.getIdentifier(value); -+ -+ // Prefix with dummy instance for convenience. -+ VoidPluginCallRequest request = -+ new VoidPluginCallRequest("instance " + 0 + -+ " SetSlot " + internal + -+ " " + index + " " + valueID, "JavaScriptSetSlot"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait setSlot request 1"); -+ synchronized(request) { -+ System.out.println ("wait setSlot request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait setSlot request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" setSlot DONE"); -+ } -+ -+ public static Object getSlot(int internal, int index) -+ { -+ // Prefix with dummy instance for convenience. -+ GetMemberPluginCallRequest request = -+ new GetMemberPluginCallRequest("instance " + 0 + -+ " GetSlot " + internal + -+ " " + index, "JavaScriptGetSlot"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait getSlot request 1"); -+ synchronized(request) { -+ System.out.println ("wait getSlot request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait getSlot request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" getSlot DONE"); -+ return request.object; -+ } -+ -+ public static Object eval(int internal, String s) -+ { -+ PluginAppletSecurityContext.contexts.get(0).store.reference(s); -+ int stringID = PluginAppletSecurityContext.contexts.get( -+ 0).store.getIdentifier(s); -+ // Prefix with dummy instance for convenience. -+ // FIXME: rename GetMemberPluginCallRequest ObjectPluginCallRequest. -+ GetMemberPluginCallRequest request = -+ new GetMemberPluginCallRequest("instance " + 0 + -+ " Eval " + internal + -+ " " + stringID, "JavaScriptEval"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait eval request 1"); -+ synchronized(request) { -+ System.out.println ("wait eval request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait eval request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" getSlot DONE"); -+ return request.object; -+ } -+ -+ public static void removeMember (int internal, String name) { -+ PluginAppletSecurityContext.contexts.get(0).store.reference(name); -+ int nameID = PluginAppletSecurityContext.contexts.get( -+ 0).store.getIdentifier(name); -+ -+ // Prefix with dummy instance for convenience. -+ VoidPluginCallRequest request = -+ new VoidPluginCallRequest("instance " + 0 + -+ " RemoveMember " + internal + -+ " " + nameID, "JavaScriptRemoveMember"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait removeMember request 1"); -+ synchronized(request) { -+ System.out.println ("wait removeMember request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait removeMember request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" RemoveMember DONE"); -+ } -+ -+ public static Object call(int internal, String name, Object args[]) -+ { -+ // FIXME: when is this removed from the object store? -+ // FIXME: reference should return the ID. -+ // FIXME: convenience method for this long line. -+ PluginAppletSecurityContext.contexts.get(0).store.reference(name); -+ int nameID = PluginAppletSecurityContext.contexts.get( -+ 0).store.getIdentifier(name); -+ PluginAppletSecurityContext.contexts.get(0).store.reference(args); -+ int argsID = PluginAppletSecurityContext.contexts.get( -+ 0).store.getIdentifier(args); -+ -+ // Prefix with dummy instance for convenience. -+ GetMemberPluginCallRequest request = -+ new GetMemberPluginCallRequest("instance " + 0 + -+ " Call " + internal + -+ " " + nameID + " " + argsID, "JavaScriptCall"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait call request 1"); -+ synchronized(request) { -+ System.out.println ("wait call request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait call request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" Call DONE"); -+ return request.object; -+ } -+ -+ public static void JavaScriptFinalize(int internal) -+ { -+ // Prefix with dummy instance for convenience. -+ VoidPluginCallRequest request = -+ new VoidPluginCallRequest("instance " + 0 + -+ " Finalize " + internal, "JavaScriptFinalize"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait finalize request 1"); -+ synchronized(request) { -+ System.out.println ("wait finalize request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait finalize request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" finalize DONE"); -+ } -+ -+ public static String javascriptToString(int internal) -+ { -+ // Prefix with dummy instance for convenience. -+ GetMemberPluginCallRequest request = -+ new GetMemberPluginCallRequest("instance " + 0 + -+ " ToString " + internal, "JavaScriptToString"); -+ PluginMain.postCallRequest(request); -+ PluginMain.write(request.message); -+ try { -+ System.out.println ("wait ToString request 1"); -+ synchronized(request) { -+ System.out.println ("wait ToString request 2"); -+ while (request.done == false) -+ request.wait(); -+ System.out.println ("wait ToString request 3"); -+ } -+ } catch (InterruptedException e) { -+ throw new RuntimeException("Interrupted waiting for call request.", -+ e); -+ } -+ System.out.println (" ToString DONE"); -+ return (String) request.object; -+ } -+ -+ // FIXME: make this private and access it from JSObject using -+ // reflection. -+ private void write(String message) throws IOException { -+ System.err.println ("WRITING 2: " + "instance " + identifier + " " + message); -+ PluginMain.write("instance " + identifier + " " + message); -+ System.err.println ("WRITING 2 DONE"); -+ } -+ -+ // FIXME: make this private and access it from JSObject using -+ // reflection. -+ private String read() throws IOException { -+ System.out.println ("READING 1"); -+ String ret = PluginMain.read(); -+ System.out.println ("READING 1 DONE"); -+ return ret; -+ } -+ -+ public void setStream(String key, InputStream stream)throws IOException{ -+ // We do nothing. -+ } -+ -+ public InputStream getStream(String key){ -+ // We do nothing. -+ return null; -+ } -+ -+ public Iterator getStreamKeys(){ -+ // We do nothing. -+ return null; -+ } -+ -+ /** -+ * System parameters. -+ */ -+ static Hashtable systemParam = new Hashtable(); -+ -+ static { -+ systemParam.put("codebase", "codebase"); -+ systemParam.put("code", "code"); -+ systemParam.put("alt", "alt"); -+ systemParam.put("width", "width"); -+ systemParam.put("height", "height"); -+ systemParam.put("align", "align"); -+ systemParam.put("vspace", "vspace"); -+ systemParam.put("hspace", "hspace"); -+ } -+ -+ /** -+ * Print the HTML tag. -+ */ -+ public static void printTag(PrintStream out, Hashtable atts) { -+ out.print("<applet"); -+ -+ String v = (String)atts.get("codebase"); -+ if (v != null) { -+ out.print(" codebase=\"" + v + "\""); -+ } -+ -+ v = (String)atts.get("code"); -+ if (v == null) { -+ v = "applet.class"; -+ } -+ out.print(" code=\"" + v + "\""); -+ v = (String)atts.get("width"); -+ if (v == null) { -+ v = "150"; -+ } -+ out.print(" width=" + v); -+ -+ v = (String)atts.get("height"); -+ if (v == null) { -+ v = "100"; -+ } -+ out.print(" height=" + v); -+ -+ v = (String)atts.get("name"); -+ if (v != null) { -+ out.print(" name=\"" + v + "\""); -+ } -+ out.println(">"); -+ -+ // A very slow sorting algorithm -+ int len = atts.size(); -+ String params[] = new String[len]; -+ len = 0; -+ for (Enumeration e = atts.keys() ; e.hasMoreElements() ;) { -+ String param = (String)e.nextElement(); -+ int i = 0; -+ for (; i < len ; i++) { -+ if (params[i].compareTo(param) >= 0) { -+ break; -+ } -+ } -+ System.arraycopy(params, i, params, i + 1, len - i); -+ params[i] = param; -+ len++; -+ } -+ -+ for (int i = 0 ; i < len ; i++) { -+ String param = params[i]; -+ if (systemParam.get(param) == null) { -+ out.println("<param name=" + param + -+ " value=\"" + atts.get(param) + "\">"); -+ } -+ } -+ out.println("</applet>"); -+ } -+ -+ /** -+ * Make sure the atrributes are uptodate. -+ */ -+ public void updateAtts() { -+ Dimension d = panel.size(); -+ Insets in = panel.insets(); -+ panel.atts.put("width", -+ new Integer(d.width - (in.left + in.right)).toString()); -+ panel.atts.put("height", -+ new Integer(d.height - (in.top + in.bottom)).toString()); -+ } -+ -+ /** -+ * Restart the applet. -+ */ -+ void appletRestart() { -+ panel.sendEvent(AppletPanel.APPLET_STOP); -+ panel.sendEvent(AppletPanel.APPLET_DESTROY); -+ panel.sendEvent(AppletPanel.APPLET_INIT); -+ panel.sendEvent(AppletPanel.APPLET_START); -+ } -+ -+ /** -+ * Reload the applet. -+ */ -+ void appletReload() { -+ panel.sendEvent(AppletPanel.APPLET_STOP); -+ panel.sendEvent(AppletPanel.APPLET_DESTROY); -+ panel.sendEvent(AppletPanel.APPLET_DISPOSE); -+ -+ /** -+ * Fixed #4501142: Classlaoder sharing policy doesn't -+ * take "archive" into account. This will be overridden -+ * by Java Plug-in. [stanleyh] -+ */ -+ AppletPanel.flushClassLoader(panel.getClassLoaderCacheKey()); -+ -+ /* -+ * Make sure we don't have two threads running through the event queue -+ * at the same time. -+ */ -+ try { -+ panel.joinAppletThread(); -+ panel.release(); -+ } catch (InterruptedException e) { -+ return; // abort the reload -+ } -+ -+ panel.createAppletThread(); -+ panel.sendEvent(AppletPanel.APPLET_LOAD); -+ panel.sendEvent(AppletPanel.APPLET_INIT); -+ panel.sendEvent(AppletPanel.APPLET_START); -+ } -+ -+ public int print(Graphics graphics, PageFormat pf, int pageIndex) { -+ return Printable.NO_SUCH_PAGE; -+ } -+ -+ /** -+ * Start the applet. -+ */ -+ void appletStart() { -+ panel.sendEvent(AppletPanel.APPLET_START); -+ } -+ -+ /** -+ * Stop the applet. -+ */ -+ void appletStop() { -+ panel.sendEvent(AppletPanel.APPLET_STOP); -+ } -+ -+ /** -+ * Shutdown a viewer. -+ * Stop, Destroy, Dispose and Quit a viewer -+ */ -+ private void appletShutdown(AppletPanel p) { -+ p.sendEvent(AppletPanel.APPLET_STOP); -+ p.sendEvent(AppletPanel.APPLET_DESTROY); -+ p.sendEvent(AppletPanel.APPLET_DISPOSE); -+ p.sendEvent(AppletPanel.APPLET_QUIT); -+ } -+ -+ /** -+ * Close this viewer. -+ * Stop, Destroy, Dispose and Quit an AppletView, then -+ * reclaim resources and exit the program if this is -+ * the last applet. -+ */ -+ void appletClose() { -+ -+ // The caller thread is event dispatch thread, so -+ // spawn a new thread to avoid blocking the event queue -+ // when calling appletShutdown. -+ // -+ final AppletPanel p = panel; -+ -+ new Thread(new Runnable() -+ { -+ public void run() -+ { -+ appletShutdown(p); -+ appletPanels.removeElement(p); -+ dispose(); -+ -+ if (countApplets() == 0) { -+ appletSystemExit(); -+ } -+ } -+ }).start(); -+ } -+ -+ /** -+ * Exit the program. -+ * Exit from the program (if not stand alone) - do no clean-up -+ */ -+ private void appletSystemExit() { -+ if (factory.isStandalone()) -+ System.exit(0); -+ } -+ -+ /** -+ * How many applets are running? -+ */ -+ -+ public static int countApplets() { -+ return appletPanels.size(); -+ } -+ -+ -+ /** -+ * The current character. -+ */ -+ static int c; -+ -+ /** -+ * Scan spaces. -+ */ -+ public static void skipSpace(Reader in) throws IOException { -+ while ((c >= 0) && -+ ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) { -+ c = in.read(); -+ } -+ } -+ -+ /** -+ * Scan identifier -+ */ -+ public static String scanIdentifier(Reader in) throws IOException { -+ StringBuffer buf = new StringBuffer(); -+ while (true) { -+ if (((c >= 'a') && (c <= 'z')) || -+ ((c >= 'A') && (c <= 'Z')) || -+ ((c >= '0') && (c <= '9')) || (c == '_')) { -+ buf.append((char)c); -+ c = in.read(); -+ } else { -+ return buf.toString(); -+ } -+ } -+ } -+ -+ /** -+ * Scan tag -+ */ -+ public static Hashtable scanTag(Reader in) throws IOException { -+ Hashtable atts = new Hashtable(); -+ skipSpace(in); -+ while (c >= 0 && c != '>') { -+ String att = scanIdentifier(in); -+ String val = ""; -+ skipSpace(in); -+ if (c == '=') { -+ int quote = -1; -+ c = in.read(); -+ skipSpace(in); -+ if ((c == '\'') || (c == '\"')) { -+ quote = c; -+ c = in.read(); -+ } -+ StringBuffer buf = new StringBuffer(); -+ while ((c > 0) && -+ (((quote < 0) && (c != ' ') && (c != '\t') && -+ (c != '\n') && (c != '\r') && (c != '>')) -+ || ((quote >= 0) && (c != quote)))) { -+ buf.append((char)c); -+ c = in.read(); -+ } -+ if (c == quote) { -+ c = in.read(); -+ } -+ skipSpace(in); -+ val = buf.toString(); -+ } -+ System.err.println("PUT " + att + " = '" + val + "'"); -+ if (! val.equals("")) { -+ atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val); -+ } -+ while (true) { -+ if ((c == '>') || (c < 0) || -+ ((c >= 'a') && (c <= 'z')) || -+ ((c >= 'A') && (c <= 'Z')) || -+ ((c >= '0') && (c <= '9')) || (c == '_')) -+ break; -+ c = in.read(); -+ } -+ //skipSpace(in); -+ } -+ return atts; -+ } -+ -+ /* values used for placement of AppletViewer's frames */ -+ private static int x = 0; -+ private static int y = 0; -+ private static final int XDELTA = 30; -+ private static final int YDELTA = XDELTA; -+ -+ static String encoding = null; -+ -+ static private Reader makeReader(InputStream is) { -+ if (encoding != null) { -+ try { -+ return new BufferedReader(new InputStreamReader(is, encoding)); -+ } catch (IOException x) { } -+ } -+ InputStreamReader r = new InputStreamReader(is); -+ encoding = r.getEncoding(); -+ return new BufferedReader(r); -+ } -+ -+ /** -+ * Scan an html file for <applet> tags -+ */ -+ public static void parse(int identifier, long handle, Reader in, URL url, String enc) -+ throws IOException { -+ encoding = enc; -+ parse(identifier, handle, in, url, System.out, new PluginAppletViewerFactory()); -+ } -+ -+ public static void parse(int identifier, long handle, Reader in, URL url) -+ throws IOException { -+ parse(identifier, handle, in, url, System.out, new PluginAppletViewerFactory()); -+ } -+ -+ public static void parse(int identifier, long handle, Reader in, URL url, -+ PrintStream statusMsgStream, -+ PluginAppletViewerFactory factory) -+ throws IOException -+ { -+ // <OBJECT> <EMBED> tag flags -+ boolean isAppletTag = false; -+ boolean isObjectTag = false; -+ boolean isEmbedTag = false; -+ -+ // warning messages -+ String requiresNameWarning = amh.getMessage("parse.warning.requiresname"); -+ String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside"); -+ String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode"); -+ String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight"); -+ String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth"); -+ String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode"); -+ String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight"); -+ String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth"); -+ String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode"); -+ String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight"); -+ String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth"); -+ String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported"); -+ -+ java.net.URLConnection conn = url.openConnection(); -+ /* The original URL may have been redirected - this -+ * sets it to whatever URL/codebase we ended up getting -+ */ -+ url = conn.getURL(); -+ -+ int ydisp = 1; -+ Hashtable atts = null; -+ -+ while(true) { -+ c = in.read(); -+ if (c == -1) -+ break; -+ -+ if (c == '<') { -+ c = in.read(); -+ if (c == '/') { -+ c = in.read(); -+ String nm = scanIdentifier(in); -+ if (nm.equalsIgnoreCase("applet") || -+ nm.equalsIgnoreCase("object") || -+ nm.equalsIgnoreCase("embed")) { -+ -+ // We can't test for a code tag until </OBJECT> -+ // because it is a parameter, not an attribute. -+ if(isObjectTag) { -+ if (atts.get("code") == null && atts.get("object") == null) { -+ statusMsgStream.println(objectRequiresCodeWarning); -+ atts = null; -+ } -+ } -+ -+ if (atts != null) { -+ // XXX 5/18 In general this code just simply -+ // shouldn't be part of parsing. It's presence -+ // causes things to be a little too much of a -+ // hack. -+ factory.createAppletViewer(identifier, handle, x, y, url, atts); -+ x += XDELTA; -+ y += YDELTA; -+ // make sure we don't go too far! -+ Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); -+ if ((x > d.width - 300) || (y > d.height - 300)) { -+ x = 0; -+ y = 2 * ydisp * YDELTA; -+ ydisp++; -+ } -+ } -+ atts = null; -+ isAppletTag = false; -+ isObjectTag = false; -+ isEmbedTag = false; -+ } -+ } -+ else { -+ String nm = scanIdentifier(in); -+ if (nm.equalsIgnoreCase("param")) { -+ Hashtable t = scanTag(in); -+ String att = (String)t.get("name"); -+ if (att == null) { -+ statusMsgStream.println(requiresNameWarning); -+ } else { -+ String val = (String)t.get("value"); -+ if (val == null) { -+ statusMsgStream.println(requiresNameWarning); -+ } else if (atts != null) { -+ atts.put(att.toLowerCase(), val); -+ } else { -+ statusMsgStream.println(paramOutsideWarning); -+ } -+ } -+ } -+ else if (nm.equalsIgnoreCase("applet")) { -+ isAppletTag = true; -+ atts = scanTag(in); -+ -+ // If there is a classid present, transform it to code tag -+ if (atts.get("code") == null && atts.get("classid") != null && -+ ((String) atts.get("classid")).startsWith("java:")) { -+ //skip "java:" -+ atts.put("code", ((String) atts.get("classid")).substring(5)); -+ } -+ -+ if (atts.get("code") == null && atts.get("object") == null) { -+ statusMsgStream.println(appletRequiresCodeWarning); -+ atts = null; -+ } -+ -+ if (atts.get("width") == null) { -+ atts.put("width", "100%"); -+ } -+ -+ if (atts.get("height") == null) { -+ atts.put("height", "100%"); -+ } -+ } -+ else if (nm.equalsIgnoreCase("object")) { -+ isObjectTag = true; -+ atts = scanTag(in); -+ -+ // If there is a classid present, transform it to code tag -+ if (atts.get("code") == null && atts.get("classid") != null && -+ ((String) atts.get("classid")).startsWith("java:")) { -+ //skip "java:" -+ atts.put("code", ((String) atts.get("classid")).substring(5)); -+ } -+ -+ // The <OBJECT> attribute codebase isn't what -+ // we want when not dealing with jars. If its -+ // defined, remove it in that case. -+ if(atts.get("archive") == null && atts.get("codebase") != null) { -+ atts.remove("codebase"); -+ } -+ -+ if (atts.get("width") == null) { -+ atts.put("width", "100%"); -+ } -+ -+ if (atts.get("height") == null) { -+ atts.put("height", "100%"); -+ } -+ } -+ else if (nm.equalsIgnoreCase("embed")) { -+ isEmbedTag = true; -+ atts = scanTag(in); -+ -+ // If there is a classid present, transform it to code tag -+ if (atts.get("code") == null && atts.get("classid") != null && -+ ((String) atts.get("classid")).startsWith("java:")) { -+ //skip "java:" -+ atts.put("code", ((String) atts.get("classid")).substring(5)); -+ } -+ -+ if (atts.get("code") == null && atts.get("object") == null) { -+ statusMsgStream.println(embedRequiresCodeWarning); -+ atts = null; -+ } -+ -+ if (atts.get("width") == null) { -+ atts.put("width", "100%"); -+ } -+ -+ if (atts.get("height") == null) { -+ atts.put("height", "100%"); -+ } -+ } -+ else if (nm.equalsIgnoreCase("app")) { -+ statusMsgStream.println(appNotLongerSupportedWarning); -+ Hashtable atts2 = scanTag(in); -+ nm = (String)atts2.get("class"); -+ if (nm != null) { -+ atts2.remove("class"); -+ atts2.put("code", nm + ".class"); -+ } -+ nm = (String)atts2.get("src"); -+ if (nm != null) { -+ atts2.remove("src"); -+ atts2.put("codebase", nm); -+ } -+ if (atts2.get("width") == null) { -+ atts2.put("width", "100%"); -+ } -+ if (atts2.get("height") == null) { -+ atts2.put("height", "100%"); -+ } -+ printTag(statusMsgStream, atts2); -+ statusMsgStream.println(); -+ } -+ } -+ } -+ } -+ in.close(); -+ } -+ -+ /** -+ * Old main entry point. -+ * -+ * @deprecated -+ */ -+ @Deprecated -+ public static void main(String args[]) throws IOException { -+ PluginMain.main(args); -+ } -+ -+ private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer"); -+ -+ private static void checkConnect(URL url) -+ { -+ SecurityManager security = System.getSecurityManager(); -+ if (security != null) { -+ try { -+ java.security.Permission perm = -+ url.openConnection().getPermission(); -+ if (perm != null) -+ security.checkPermission(perm); -+ else -+ security.checkConnect(url.getHost(), url.getPort()); -+ } catch (java.io.IOException ioe) { -+ security.checkConnect(url.getHost(), url.getPort()); -+ } -+ } -+ } -+ } -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginCallRequest.java openjdk/jdk/src/share/classes/sun/applet/PluginCallRequest.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginCallRequest.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginCallRequest.java 2008-09-15 16:22:07.000000000 -0400 -@@ -0,0 +1,56 @@ -+/* PluginCallRequest -- represent Java-to-JavaScript requests -+ Copyright (C) 2008 Red Hat -+ -+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; either version 2, or (at your option) -+any later version. -+ -+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 sun.applet; -+ -+// FIXME: for each type of request extend a new (anonymous?) -+// PluginCallRequest. -+abstract class PluginCallRequest { -+ String message; -+ String returnString; -+ PluginCallRequest next; -+ boolean done = false; -+ -+ public PluginCallRequest(String message, String returnString) { -+ this.message = message; -+ this.returnString = returnString; -+ } -+ -+ public abstract void parseReturn(String message); -+ -+ public abstract boolean serviceable(String message); -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginDebug.java openjdk/jdk/src/share/classes/sun/applet/PluginDebug.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginDebug.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginDebug.java 2008-09-15 16:21:47.000000000 -0400 -@@ -0,0 +1,13 @@ -+package sun.applet; -+ -+import java.io.*; -+ -+public class PluginDebug { -+ -+ static final boolean DEBUG = true; -+ -+ public static void debug(String message) { -+ if (DEBUG) -+ System.err.println(message); -+ } -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginException.java openjdk/jdk/src/share/classes/sun/applet/PluginException.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginException.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginException.java 2008-09-15 16:22:08.000000000 -0400 -@@ -0,0 +1,14 @@ -+package sun.applet; -+ -+public class PluginException extends Exception { -+ -+ public PluginException (int instance, int reference, Throwable t) { -+ t.printStackTrace(); -+ this.setStackTrace(t.getStackTrace()); -+ -+ PluginAppletSecurityContext.contexts.get(0).store.dump(); -+ -+ String message = "instance " + instance + " reference " + reference + " Error " + t.getMessage(); -+ PluginMain.write(message); -+ } -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginMain.java openjdk/jdk/src/share/classes/sun/applet/PluginMain.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginMain.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginMain.java 2008-09-15 16:22:08.000000000 -0400 -@@ -0,0 +1,533 @@ -+/* -+ * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. -+ * 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. -+ * -+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -+ * CA 95054 USA or visit www.sun.com if you need additional information or -+ * have any questions. -+ */ -+ -+package sun.applet; -+ -+import java.io.*; -+import java.lang.reflect.*; -+import java.net.*; -+import java.nio.charset.Charset; -+import java.util.*; -+ -+import sun.net.www.ParseUtil; -+ -+class RequestQueue { -+ PluginCallRequest head = null; -+ PluginCallRequest tail = null; -+ private int size = 0; -+ -+ void post(PluginCallRequest request) { -+ if (head == null) { -+ head = tail = request; -+ tail.next = null; -+ } else { -+ tail.next = request; -+ tail = request; -+ tail.next = null; -+ } -+ -+ size++; -+ } -+ -+ PluginCallRequest pop() { -+ if (head == null) -+ return null; -+ -+ PluginCallRequest ret = head; -+ head = head.next; -+ ret.next = null; -+ -+ size--; -+ -+ return ret; -+ } -+ -+ int size() { -+ return size; -+ } -+} -+ -+/** -+ * The main entry point into PluginAppletViewer. -+ */ -+public class PluginMain -+{ -+ private static BufferedReader pluginInputReader; -+ private static StreamTokenizer pluginInputTokenizer; -+ private static BufferedWriter pluginOutputWriter; -+ // This is used in init(). Getting rid of this is desirable but depends -+ // on whether the property that uses it is necessary/standard. -+ public static final String theVersion = System.getProperty("java.version"); -+ -+ private static RequestQueue queue = new RequestQueue(); -+ -+ static LinkedList<String> readQueue = new LinkedList<String>(); -+ static LinkedList<String> writeQueue = new LinkedList<String>(); -+ -+ static PluginMessageConsumer consumer; -+ static Boolean shuttingDown = false; -+ -+ static final boolean redirectStreams = false; -+ -+ /** -+ * The main entry point into AppletViewer. -+ */ -+ public static void main(String args[]) -+ throws IOException -+ { -+ -+ if (args.length != 1) { -+ // Indicate to plugin that appletviewer is installed correctly. -+ System.exit(0); -+ } -+ -+ int port = 0; -+ try { -+ port = Integer.parseInt(args[0]); -+ } catch (NumberFormatException e) { -+ System.err.println("Failed to parse port number: " + e); -+ System.exit(1); -+ } -+ -+ if (redirectStreams) { -+ try { -+ File errFile = new File("/tmp/java.stderr"); -+ File outFile = new File("/tmp/java.stdout"); -+ -+ System.setErr(new PrintStream(new FileOutputStream(errFile))); -+ System.setOut(new PrintStream(new FileOutputStream(outFile))); -+ -+ } catch (Exception e) { -+ System.err.println("Unable to redirect streams"); -+ e.printStackTrace(); -+ } -+ } -+ -+ // INSTALL THE SECURITY MANAGER -+ init(); -+ -+ System.err.println("Creating consumer..."); -+ consumer = new PluginMessageConsumer(); -+ -+ beginListening(50007); -+ } -+ -+ public PluginMain() { -+ -+ try { -+ File errFile = new File("/tmp/java.stderr"); -+ File outFile = new File("/tmp/java.stdout"); -+ -+ System.setErr(new PrintStream(new FileOutputStream(errFile))); -+ System.setOut(new PrintStream(new FileOutputStream(outFile))); -+ -+ } catch (Exception e) { -+ System.err.println("Unable to redirect streams"); -+ e.printStackTrace(); -+ } -+ -+ // INSTALL THE SECURITY MANAGER -+ init(); -+ -+ System.err.println("Creating consumer..."); -+ consumer = new PluginMessageConsumer(); -+ -+ beginListening(50007); -+ -+ } -+ -+ private static void beginListening(int port) { -+ /* -+ * Code for TCP/IP communication -+ */ -+ Socket socket = null; -+ -+ try { -+ socket = new Socket("localhost", port); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ } -+ -+ System.err.println("Socket initialized. Proceeding with start()"); -+ -+ try { -+ start(socket.getInputStream(), socket.getOutputStream()); -+ System.err.println("Streams initialized"); -+ } catch (IOException ioe) { -+ ioe.printStackTrace(); -+ } -+ } -+ -+ public static void postMessage(String s) { -+ -+ if (s == null || s.equals("shutdown")) { -+ try { -+ // Close input/output channels to plugin. -+ pluginInputReader.close(); -+ pluginOutputWriter.close(); -+ } catch (IOException exception) { -+ // Deliberately ignore IOException caused by broken -+ // pipe since plugin may have already detached. -+ } -+ PluginAppletSecurityContext.contexts.get(0).store.dump(); -+ System.err.println("APPLETVIEWER: exiting appletviewer"); -+ System.exit(0); -+ } -+ -+ //PluginAppletSecurityContext.contexts.get(0).store.dump(); -+ PluginDebug.debug("Plugin posted: " + s); -+ -+ System.err.println("Consuming " + s); -+ consumer.consume(s); -+ -+ PluginDebug.debug("Added to queue"); -+ } -+ -+ private static void init() { -+ Properties avProps = new Properties(); -+ -+ // ADD OTHER RANDOM PROPERTIES -+ // XXX 5/18 need to revisit why these are here, is there some -+ // standard for what is available? -+ -+ // Standard browser properties -+ avProps.put("browser", "sun.applet.AppletViewer"); -+ avProps.put("browser.version", "1.06"); -+ avProps.put("browser.vendor", "Sun Microsystems Inc."); -+ avProps.put("http.agent", "Java(tm) 2 SDK, Standard Edition v" + theVersion); -+ -+ // Define which packages can be extended by applets -+ // XXX 5/19 probably not needed, not checked in AppletSecurity -+ avProps.put("package.restrict.definition.java", "true"); -+ avProps.put("package.restrict.definition.sun", "true"); -+ -+ // Define which properties can be read by applets. -+ // A property named by "key" can be read only when its twin -+ // property "key.applet" is true. The following ten properties -+ // are open by default. Any other property can be explicitly -+ // opened up by the browser user by calling appletviewer with -+ // -J-Dkey.applet=true -+ avProps.put("java.version.applet", "true"); -+ avProps.put("java.vendor.applet", "true"); -+ avProps.put("java.vendor.url.applet", "true"); -+ avProps.put("java.class.version.applet", "true"); -+ avProps.put("os.name.applet", "true"); -+ avProps.put("os.version.applet", "true"); -+ avProps.put("os.arch.applet", "true"); -+ avProps.put("file.separator.applet", "true"); -+ avProps.put("path.separator.applet", "true"); -+ avProps.put("line.separator.applet", "true"); -+ -+ // Read in the System properties. If something is going to be -+ // over-written, warn about it. -+ Properties sysProps = System.getProperties(); -+ for (Enumeration e = sysProps.propertyNames(); e.hasMoreElements(); ) { -+ String key = (String) e.nextElement(); -+ String val = (String) sysProps.getProperty(key); -+ avProps.setProperty(key, val); -+ } -+ -+ // INSTALL THE PROPERTY LIST -+ System.setProperties(avProps); -+ -+ // Create and install the security manager -+ System.setSecurityManager(new AppletSecurity()); -+ -+ // REMIND: Create and install a socket factory! -+ } -+ -+ public static void handleMessage(String message) throws PluginException{ -+ -+ StringTokenizer st = new StringTokenizer(message, " "); -+ -+ String type = st.nextToken(); -+ int identifier = Integer.parseInt(st.nextToken()); -+ -+ String rest = ""; -+ int reference = -1; -+ String src = null; -+ -+ String potentialReference = st.hasMoreTokens() ? st.nextToken() : ""; -+ -+ // if the next token is reference, read it, else reset "rest" -+ if (potentialReference.equals("reference")) { -+ reference = Integer.parseInt(st.nextToken()); -+ } else { -+ rest += potentialReference + " "; -+ } -+ -+ String potentialSrc = st.hasMoreTokens() ? st.nextToken() : ""; -+ -+ if (potentialSrc.equals("src")) { -+ src = st.nextToken(); -+ } else { -+ rest += potentialSrc + " "; -+ } -+ -+ while (st.hasMoreElements()) { -+ rest += st.nextToken(); -+ rest += " "; -+ } -+ -+ rest = rest.trim(); -+ -+ try { -+ -+ System.err.println("Breakdown -- type: " + type + " identifier: " + identifier + " reference: " + reference + " src: " + src + " rest: " + rest); -+ -+ if (rest.contains("JavaScriptGetWindow") -+ || rest.contains("JavaScriptGetMember") -+ || rest.contains("JavaScriptSetMember") -+ || rest.contains("JavaScriptGetSlot") -+ || rest.contains("JavaScriptSetSlot") -+ || rest.contains("JavaScriptEval") -+ || rest.contains("JavaScriptRemoveMember") -+ || rest.contains("JavaScriptCall") -+ || rest.contains("JavaScriptFinalize") -+ || rest.contains("JavaScriptToString")) { -+ finishCallRequest(rest); -+ return; -+ } -+ -+ if (type.equals("instance")) -+ PluginAppletViewer.handleMessage(identifier, reference, rest); -+ else if (type.equals("context")) { -+ PluginDebug.debug("Sending to PASC: " + identifier + "/" + reference + " and " + rest); -+ PluginAppletSecurityContext.handleMessage(identifier, src, reference, rest); -+ } -+ } catch (Exception e) { -+ throw new PluginException(identifier, reference, e); -+ } -+ } -+ -+ static void start(InputStream inputstream, OutputStream outputstream) -+ throws MalformedURLException, IOException -+ { -+ // Set up input and output pipes. Use UTF-8 encoding. -+ pluginInputReader = -+ new BufferedReader(new InputStreamReader(inputstream, -+ Charset.forName("UTF-8"))); -+ pluginInputTokenizer = new StreamTokenizer(pluginInputReader); -+ pluginInputTokenizer.resetSyntax(); -+ pluginInputTokenizer.whitespaceChars('\u0000', '\u0000'); -+ pluginInputTokenizer.wordChars('\u0001', '\u00FF'); -+ pluginOutputWriter = -+ new BufferedWriter(new OutputStreamWriter -+ (outputstream, Charset.forName("UTF-8"))); -+ -+ -+ Thread listenerThread = new Thread() { -+ -+ public void run() { -+ while (true) { -+ -+ System.err.println("Waiting for data..."); -+ -+ int readChar = -1; -+ // blocking read, discard first character -+ try { -+ readChar = pluginInputReader.read(); -+ } catch (IOException ioe) { -+ // plugin may have detached -+ } -+ -+ // if not disconnected -+ if (readChar != -1) { -+ String s = read(); -+ System.err.println("Got data, consuming " + s); -+ consumer.consume(s); -+ } else { -+ try { -+ // Close input/output channels to plugin. -+ pluginInputReader.close(); -+ pluginOutputWriter.close(); -+ } catch (IOException exception) { -+ // Deliberately ignore IOException caused by broken -+ // pipe since plugin may have already detached. -+ } -+ PluginAppletSecurityContext.contexts.get(0).store.dump(); -+ System.err.println("APPLETVIEWER: exiting appletviewer"); -+ System.exit(0); -+ } -+ } -+ } -+ }; -+ -+ listenerThread.start(); -+ -+/* -+ while(true) { -+ String message = read(); -+ PluginDebug.debug(message); -+ handleMessage(message); -+ // TODO: -+ // write(queue.peek()); -+ } -+*/ -+ } -+ -+ public static void postCallRequest(PluginCallRequest request) { -+ synchronized(queue) { -+ queue.post(request); -+ } -+ } -+ -+ private static void finishCallRequest(String message) { -+ PluginDebug.debug ("DISPATCHCALLREQUESTS 1"); -+ synchronized(queue) { -+ PluginDebug.debug ("DISPATCHCALLREQUESTS 2"); -+ PluginCallRequest request = queue.pop(); -+ -+ // make sure we give the message to the right request -+ // in the queue.. for the love of God, MAKE SURE! -+ -+ // first let's be efficient.. if there was only one -+ // request in queue, we're already set -+ if (queue.size() != 0) { -+ -+ int size = queue.size(); -+ int count = 0; -+ -+ while (!request.serviceable(message)) { -+ -+ // something is very wrong.. we have a message to -+ // process, but no one to service it -+ if (count >= size) { -+ throw new RuntimeException("Unable to find processor for message " + message); -+ } -+ -+ // post request at the end of the queue -+ queue.post(request); -+ -+ // Look at the next request -+ request = queue.pop(); -+ -+ count++; -+ } -+ -+ } -+ -+ PluginDebug.debug ("DISPATCHCALLREQUESTS 3"); -+ if (request != null) { -+ PluginDebug.debug ("DISPATCHCALLREQUESTS 5"); -+ synchronized(request) { -+ request.parseReturn(message); -+ request.notifyAll(); -+ } -+ PluginDebug.debug ("DISPATCHCALLREQUESTS 6"); -+ PluginDebug.debug ("DISPATCHCALLREQUESTS 7"); -+ } -+ } -+ PluginDebug.debug ("DISPATCHCALLREQUESTS 8"); -+ } -+ -+ /** -+ * Write string to plugin. -+ * -+ * @param message the message to write -+ * -+ * @exception IOException if an error occurs -+ */ -+ static void write(String message) -+ { -+ -+ System.err.println(" PIPE: appletviewer wrote: " + message); -+ synchronized(pluginOutputWriter) { -+ try { -+ pluginOutputWriter.write(message, 0, message.length()); -+ pluginOutputWriter.write(0); -+ pluginOutputWriter.flush(); -+ } catch (IOException e) { -+ // if we are shutting down, ignore write failures as -+ // pipe may have closed -+ synchronized(shuttingDown) { -+ if (!shuttingDown) { -+ e.printStackTrace(); -+ } -+ } -+ -+ // either ways, if the pipe is broken, there is nothing -+ // we can do anymore. Don't hang around. -+ System.err.println("Unable to write to PIPE. APPLETVIEWER exiting"); -+ System.exit(1); -+ } -+ } -+ -+ return; -+ /* -+ synchronized(writeQueue) { -+ writeQueue.add(message); -+ System.err.println(" PIPE: appletviewer wrote: " + message); -+ } -+ */ -+ -+ } -+ -+ static boolean messageAvailable() { -+ return writeQueue.size() != 0; -+ } -+ -+ static String getMessage() { -+ synchronized(writeQueue) { -+ String ret = writeQueue.size() > 0 ? writeQueue.poll() : ""; -+ return ret; -+ } -+ } -+ -+ /** -+ * Read string from plugin. -+ * -+ * @return the read string -+ * -+ * @exception IOException if an error occurs -+ */ -+ static String read() -+ { -+ try { -+ pluginInputTokenizer.nextToken(); -+ } catch (IOException e) { -+ throw new RuntimeException(e); -+ } -+ String message = pluginInputTokenizer.sval; -+ PluginDebug.debug(" PIPE: appletviewer read: " + message); -+ if (message == null || message.equals("shutdown")) { -+ synchronized(shuttingDown) { -+ shuttingDown = true; -+ } -+ try { -+ // Close input/output channels to plugin. -+ pluginInputReader.close(); -+ pluginOutputWriter.close(); -+ } catch (IOException exception) { -+ // Deliberately ignore IOException caused by broken -+ // pipe since plugin may have already detached. -+ } -+ PluginAppletSecurityContext.contexts.get(0).store.dump(); -+ System.err.println("APPLETVIEWER: exiting appletviewer"); -+ System.exit(0); -+ } -+ return message; -+ } -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java openjdk/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java 2008-09-15 16:21:47.000000000 -0400 -@@ -0,0 +1,49 @@ -+package sun.applet; -+ -+import java.util.ArrayList; -+ -+class PluginMessageConsumer { -+ -+ int MAX_WORKERS = 3; -+ ArrayList<PluginMessageHandlerWorker> workers = new ArrayList<PluginMessageHandlerWorker>(); -+ -+ public PluginMessageConsumer() { -+ for (int i=0; i < MAX_WORKERS; i++) { -+ System.err.println("Creating worker " + i); -+ PluginMessageHandlerWorker worker = new PluginMessageHandlerWorker(i); -+ worker.start(); -+ workers.add(worker); -+ } -+ } -+ -+ public void consume(String message) { -+ -+ PluginDebug.debug("Consumer received message " + message); -+ -+ synchronized(PluginMain.readQueue) { -+ PluginMain.readQueue.add(message); -+ } -+ -+ PluginDebug.debug("Message " + message + " added to queue. Looking for free worker..."); -+ PluginMessageHandlerWorker worker = getFreeWorker(); -+ worker.interrupt(); -+ } -+ -+ private PluginMessageHandlerWorker getFreeWorker() { -+ -+ // FIXME: Can be made more efficient by having an idle worker pool -+ -+ while (true) { -+ for (PluginMessageHandlerWorker worker: workers) { -+ if (worker.isFree()) { -+ PluginDebug.debug("Found free worker with id " + worker.getWorkerId()); -+ return worker; -+ } -+ } -+ Thread.yield(); -+ } -+ -+ //throw new RuntimeException("Out of message handler workers"); -+ } -+ -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java openjdk/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java 2008-09-15 16:21:47.000000000 -0400 -@@ -0,0 +1,59 @@ -+package sun.applet; -+ -+class PluginMessageHandlerWorker extends Thread { -+ -+ private boolean free = true; -+ private int id; -+ -+ public PluginMessageHandlerWorker(int id) { -+ this.id = id; -+ } -+ -+ public void run() { -+ while (true) { -+ -+ String msg = null; -+ synchronized(PluginMain.readQueue) { -+ if (PluginMain.readQueue.size() > 0) { -+ msg = PluginMain.readQueue.poll(); -+ } -+ } -+ -+ if (msg != null) { -+ free = false; -+ System.err.println("Thread " + id + " picking up " + msg + " from queue..."); -+ -+ try { -+ PluginMain.handleMessage(msg); -+ } catch (PluginException pe) { -+ /* -+ catch the exception and DO NOTHING. The plugin should take over after -+ this error and let the user know. We don't quit because otherwise the -+ exception will spread to the rest of the applets which is a no-no -+ */ -+ } -+ -+ free = true; -+ } else { -+ -+ // Sleep when there is nothing to do -+ try { -+ Thread.sleep(Integer.MAX_VALUE); -+ System.err.println("Consumer thread " + id + " sleeping..."); -+ } catch (InterruptedException ie) { -+ System.err.println("Consumer thread " + id + " woken..."); -+ // nothing.. someone woke us up, see if there -+ // is work to do -+ } -+ } -+ } -+ } -+ -+ public int getWorkerId() { -+ return id; -+ } -+ -+ public boolean isFree() { -+ return free; -+ } -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginObjectStore.java openjdk/jdk/src/share/classes/sun/applet/PluginObjectStore.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/PluginObjectStore.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/PluginObjectStore.java 2008-09-15 16:21:47.000000000 -0400 -@@ -0,0 +1,119 @@ -+/* PluginObjectStore -- manage identifier-to-object mapping -+ Copyright (C) 2008 Red Hat -+ -+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; either version 2, or (at your option) -+any later version. -+ -+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 sun.applet; -+ -+import java.util.*; -+import java.lang.reflect.*; -+import java.io.*; -+ -+public class PluginObjectStore -+{ -+ private static HashMap<Integer, Object> objects = new HashMap(); -+ private static HashMap<Integer, Integer> counts = new HashMap(); -+ private static HashMap<Object, Integer> identifiers = new HashMap(); -+ // FIXME: -+ // -+ // IF uniqueID == MAX_LONG, uniqueID = -+ // 0 && wrapped = true -+ // -+ // if (wrapped), check if -+ // objects.get(uniqueID) returns null -+ // -+ // if yes, use uniqueID, if no, -+ // uniqueID++ and keep checking -+ // or: -+ // stack of available ids: -+ // derefed id -> derefed id -> nextUniqueIdentifier -+ private static int nextUniqueIdentifier = 1; -+ -+ public Object getObject(Integer identifier) { -+ return objects.get(identifier); -+ } -+ -+ public Integer getIdentifier(Object object) { -+ if (object == null) -+ return 0; -+ return identifiers.get(object); -+ } -+ -+ public void reference(Object object) { -+ Integer identifier = identifiers.get(object); -+ if (identifier == null) { -+ objects.put(nextUniqueIdentifier, object); -+ counts.put(nextUniqueIdentifier, 1); -+ identifiers.put(object, nextUniqueIdentifier); -+ System.out.println("JAVA ADDED: " + nextUniqueIdentifier); -+ System.out.println("JAVA REFERENCED: " + nextUniqueIdentifier -+ + " to: 1"); -+ nextUniqueIdentifier++; -+ } else { -+ counts.put(identifier, counts.get(identifier) + 1); -+ System.out.println("JAVA REFERENCED: " + identifier + -+ " to: " + counts.get(identifier)); -+ } -+ } -+ -+ public void unreference(int identifier) { -+ Integer currentCount = counts.get(identifier); -+ if (currentCount == null) -+ System.out.println("ERROR UNREFERENCING: " + identifier); -+ if (currentCount == 1) { -+ System.out.println("JAVA DEREFERENCED: " + identifier -+ + " to: 0"); -+ Object object = objects.get(identifier); -+ objects.remove(identifier); -+ counts.remove(identifier); -+ identifiers.remove(object); -+ System.out.println("JAVA REMOVED: " + identifier); -+ } else { -+ counts.put(identifier, currentCount - 1); -+ System.out.println("JAVA DEREFERENCED: " + -+ identifier + " to: " + -+ counts.get(identifier)); -+ } -+ } -+ -+ public void dump() { -+ Iterator i = objects.keySet().iterator(); -+ while (i.hasNext()) { -+ Object key = i.next(); -+ System.err.println(key + "::" + objects.get(key)); -+ } -+ } -+} -+ -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/TestEnv.java openjdk/jdk/src/share/classes/sun/applet/TestEnv.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/TestEnv.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/TestEnv.java 2008-09-15 16:21:47.000000000 -0400 -@@ -0,0 +1,172 @@ -+/* TestEnv -- test JavaScript-to-Java calls -+ Copyright (C) 2008 Red Hat -+ -+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; either version 2, or (at your option) -+any later version. -+ -+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 sun.applet; -+ -+public class TestEnv -+{ -+ public static int intField = 103; -+ public int intInstanceField = 7822; -+ public String stringField = "hello"; -+ // z <musical G clef> <chinese water> -+ public String complexStringField = "z\uD834\uDD1E\u6C34"; -+ -+ public static void TestIt() { -+ System.out.println("TestIt"); -+ } -+ -+ public static void TestItBool(boolean arg) { -+ System.out.println("TestItBool: " + arg); -+ } -+ -+ public static void TestItByte(byte arg) { -+ System.out.println("TestItByte: " + arg); -+ } -+ -+ public static void TestItChar(char arg) { -+ System.out.println("TestItChar: " + arg); -+ } -+ -+ public static void TestItShort(short arg) { -+ System.out.println("TestItShort: " + arg); -+ } -+ -+ public static void TestItInt(int arg) { -+ System.out.println("TestItInt: " + arg); -+ } -+ -+ public static void TestItLong(long arg) { -+ System.out.println("TestItLong: " + arg); -+ } -+ -+ public static void TestItFloat(float arg) { -+ System.out.println("TestItFloat: " + arg); -+ } -+ -+ public static void TestItDouble(double arg) { -+ System.out.println("TestItDouble: " + arg); -+ } -+ -+ public static void TestItObject(TestEnv arg) { -+ System.out.println("TestItObject: " + arg); -+ } -+ -+ public static void TestItObjectString(String arg) { -+ System.out.println("TestItObjectString: " + arg); -+ } -+ -+ public static void TestItIntArray(int[] arg) { -+ System.out.println("TestItIntArray: " + arg); -+ for (int i = 0; i < arg.length; i++) -+ System.out.println ("ELEMENT: " + i + " " + arg[i]); -+ } -+ -+ public static void TestItObjectArray(String[] arg) { -+ System.out.println("TestItObjectArray: " + arg); -+ for (int i = 0; i < arg.length; i++) -+ System.out.println ("ELEMENT: " + i + " " + arg[i]); -+ } -+ -+ public static void TestItObjectArrayMulti(String[][] arg) { -+ System.out.println("TestItObjectArrayMulti: " + arg); -+ for (int i = 0; i < arg.length; i++) -+ for (int j = 0; j < arg[i].length; j++) -+ System.out.println ("ELEMENT: " + i + " " + j + " " + arg[i][j]); -+ } -+ -+ public static boolean TestItBoolReturnTrue() { -+ return true; -+ } -+ -+ public static boolean TestItBoolReturnFalse() { -+ return false; -+ } -+ -+ public static byte TestItByteReturn() { -+ return (byte) 0xfe; -+ } -+ -+ public static char TestItCharReturn() { -+ return 'K'; -+ } -+ -+ public static char TestItCharUnicodeReturn() { -+ return '\u6C34'; -+ } -+ -+ public static short TestItShortReturn() { -+ return 23; -+ } -+ -+ public static int TestItIntReturn() { -+ return 3445; -+ } -+ -+ public static long TestItLongReturn() { -+ return 3242883; -+ } -+ -+ public static float TestItFloatReturn() { -+ return 9.21E4f; -+ } -+ -+ public static double TestItDoubleReturn() { -+ return 8.33E88; -+ } -+ -+ public static Object TestItObjectReturn() { -+ return new String("Thomas"); -+ } -+ -+ public static int[] TestItIntArrayReturn() { -+ return new int[] { 6, 7, 8 }; -+ } -+ -+ public static String[] TestItObjectArrayReturn() { -+ return new String[] { "Thomas", "Brigitte" }; -+ } -+ -+ public static String[][] TestItObjectArrayMultiReturn() { -+ return new String[][] { {"Thomas", "Brigitte"}, -+ {"Lindsay", "Michael"} }; -+ } -+ -+ public int TestItIntInstance(int arg) { -+ System.out.println("TestItIntInstance: " + this + " " + arg); -+ return 899; -+ } -+} -diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java openjdk/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java ---- openjdk.orig/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java 1969-12-31 19:00:00.000000000 -0500 -+++ openjdk/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java 2008-09-15 16:22:09.000000000 -0400 -@@ -0,0 +1,62 @@ -+/* VoidPluginCallRequest -- represent Java-to-JavaScript requests -+ Copyright (C) 2008 Red Hat -+ -+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; either version 2, or (at your option) -+any later version. -+ -+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 sun.applet; -+ -+class VoidPluginCallRequest extends PluginCallRequest { -+ public VoidPluginCallRequest(String message, String returnString) { -+ super(message, returnString); -+ System.out.println ("VoidPLUGINCAlL " + message + " " + returnString); -+ } -+ -+ public void parseReturn(String message) { -+ done = true; -+ } -+ -+ /** -+ * Returns whether the given message is serviceable by this object -+ * -+ * @param message The message to service -+ * @return boolean indicating if message is serviceable -+ */ -+ public boolean serviceable(String message) { -+ return message.contains("JavaScriptFinalize") || -+ message.contains("JavaScriptRemoveMember") || -+ message.contains("JavaScriptSetMember") || -+ message.contains("JavaScriptSetSlot"); -+ } -+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/netscape/javascript/JSException.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,140 @@ +/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package netscape.javascript; + +/** + * JSException is an exception which is thrown when JavaScript code + * returns an error. + */ + +public +class JSException extends RuntimeException { + public static final int EXCEPTION_TYPE_EMPTY = -1; + public static final int EXCEPTION_TYPE_VOID = 0; + public static final int EXCEPTION_TYPE_OBJECT = 1; + public static final int EXCEPTION_TYPE_FUNCTION = 2; + public static final int EXCEPTION_TYPE_STRING = 3; + public static final int EXCEPTION_TYPE_NUMBER = 4; + public static final int EXCEPTION_TYPE_BOOLEAN = 5; + public static final int EXCEPTION_TYPE_ERROR = 6; + + public String filename; + public int lineno; + public String source; + public int tokenIndex; + public int wrappedExceptionType; + public Object wrappedException; + + /** + * Constructs a JSException without a detail message. + * A detail message is a String that describes this particular exception. + * + * @deprecated Not for public use in future versions. + */ + public JSException() { + super(); + filename = "unknown"; + lineno = 0; + source = ""; + tokenIndex = 0; + wrappedExceptionType = EXCEPTION_TYPE_EMPTY; + } + + /** + * Constructs a JSException with a detail message. + * A detail message is a String that describes this particular exception. + * @param s the detail message + * + * @deprecated Not for public use in future versions. + */ + public JSException(String s) { + super(s); + filename = "unknown"; + lineno = 0; + source = ""; + tokenIndex = 0; + wrappedExceptionType = EXCEPTION_TYPE_EMPTY; + } + + /** + * Constructs a JSException with a wrapped JavaScript exception object. + * This constructor needs to be public so that Java users can throw + * exceptions to JS cleanly. + */ + public JSException(int wrappedExceptionType, Object wrappedException) { + super(); + this.wrappedExceptionType = wrappedExceptionType; + this.wrappedException = wrappedException; + } + + /** + * Constructs a JSException with a detail message and all the + * other info that usually comes with a JavaScript error. + * @param s the detail message + * + * @deprecated Not for public use in future versions. + */ + public JSException(String s, String filename, int lineno, + String source, int tokenIndex) { + super(s); + this.filename = filename; + this.lineno = lineno; + this.source = source; + this.tokenIndex = tokenIndex; + wrappedExceptionType = EXCEPTION_TYPE_EMPTY; + } + + /** + * Instance method getWrappedExceptionType returns the int mapping of the + * type of the wrappedException Object. + */ + public int getWrappedExceptionType() { + return wrappedExceptionType; + } + + /** + * Instance method getWrappedException. + */ + public Object getWrappedException() { + return wrappedException; + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/netscape/javascript/JSObject.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,258 @@ +/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* more doc todo: + * threads + * gc + * + * + */ + +package netscape.javascript; + +import java.applet.Applet; +import java.io.IOException; +import sun.applet.PluginAppletViewer; + +/** + * JSObject allows Java to manipulate objects that are + * defined in JavaScript. + * Values passed from Java to JavaScript are converted as + * follows:<ul> + * <li>JSObject is converted to the original JavaScript object + * <li>Any other Java object is converted to a JavaScript wrapper, + * which can be used to access methods and fields of the java object. + * Converting this wrapper to a string will call the toString method + * on the original object, converting to a number will call the + * doubleValue method if possible and fail otherwise. Converting + * to a boolean will try to call the booleanValue method in the + * same way. + * <li>Java arrays are wrapped with a JavaScript object that understands + * array.length and array[index] + * <li>A Java boolean is converted to a JavaScript boolean + * <li>Java byte, char, short, int, long, float, and double are converted + * to JavaScript numbers + * </ul> + * Values passed from JavaScript to Java are converted as follows:<ul> + * <li>objects which are wrappers around java objects are unwrapped + * <li>other objects are wrapped with a JSObject + * <li>strings, numbers and booleans are converted to String, Double, + * and Boolean objects respectively + * </ul> + * This means that all JavaScript values show up as some kind + * of java.lang.Object in Java. In order to make much use of them, + * you will have to cast them to the appropriate subclass of Object, + * e.g. <code>(String) window.getMember("name");</code> or + * <code>(JSObject) window.getMember("document");</code>. + */ +public final class JSObject { + /* the internal object data */ + private int internal; + private long long_internal; + + /** + * initialize + */ + private static void initClass() { + System.err.println ("JSObject.initClass"); + } + + static { + System.err.println ("JSObject INITIALIZER"); + } + + /** + * it is illegal to construct a JSObject manually + */ + // FIXME: make private! + public JSObject(int jsobj_addr) { + System.err.println ("JSObject int CONSTRUCTOR"); + internal = jsobj_addr; + } + + private JSObject(long jsobj_addr) { + System.err.println ("JSObject long CONSTRUCTOR"); + long_internal = jsobj_addr; + } + + /** + * Retrieves a named member of a JavaScript object. + * Equivalent to "this.<i>name</i>" in JavaScript. + */ + public Object getMember(String name) + { + System.err.println ("JSObject.getMember " + name); + + Object o = PluginAppletViewer.getMember(internal, name); + System.out.println ("JSObject.getMember GOT " + o); + return o; + } + + + /** + * Retrieves an indexed member of a JavaScript object. + * Equivalent to "this[<i>index</i>]" in JavaScript. + */ + // public Object getMember(int index) { return getSlot(index); } + public Object getSlot(int index) + { + System.err.println ("JSObject.getSlot " + index); + + return PluginAppletViewer.getSlot(internal, index); + } + + + /** + * Sets a named member of a JavaScript object. + * Equivalent to "this.<i>name</i> = <i>value</i>" in JavaScript. + */ + public void setMember(String name, Object value) + { + System.err.println ("JSObject.setMember " + name + " " + value); + + PluginAppletViewer.setMember(internal, name, value); + } + + /** + * Sets an indexed member of a JavaScript object. + * Equivalent to "this[<i>index</i>] = <i>value</i>" in JavaScript. + */ + // public void setMember(int index, Object value) { + // setSlot(index, value); + // } + public void setSlot(int index, Object value) + { + System.err.println ("JSObject.setSlot " + index + " " + value); + + PluginAppletViewer.setSlot(internal, index, value); + } + + + // TODO: toString, finalize. + + /** + * Removes a named member of a JavaScript object. + */ + public void removeMember(String name) + { + System.err.println ("JSObject.removeMember " + name); + + PluginAppletViewer.removeMember(internal, name); + } + + + /** + * Calls a JavaScript method. + * Equivalent to "this.<i>methodName</i>(<i>args</i>[0], <i>args</i>[1], ...)" in JavaScript. + */ + public Object call(String methodName, Object args[]) + { + System.err.print ("JSObject.call " + methodName); + for (int i = 0; i < args.length; i++) + System.err.print (" " + args[i]); + System.err.println(""); + return PluginAppletViewer.call(internal, methodName, args); + } + + + /** + * Evaluates a JavaScript expression. The expression is a string + * of JavaScript source code which will be evaluated in the context + * given by "this". + */ + public Object eval(String s) + { + System.err.println("JSObject.eval " + s); + return PluginAppletViewer.eval(internal, s); + } + + + /** + * Converts a JSObject to a String. + */ + public String toString() + { + System.err.println("JSObject.toString"); + return PluginAppletViewer.javascriptToString(internal); + } + + + // should use some sort of identifier rather than String + // is "property" the right word? + // native String[] listProperties(); + + + /** + * get a JSObject for the window containing the given applet + */ + public static JSObject getWindow(Applet applet) + { + System.err.println("JSObject.getWindow"); + // FIXME: handle long case as well. + int internal = 0; + internal = ((PluginAppletViewer) + applet.getAppletContext()).getWindow(); + System.out.println ("GOT IT: " + internal); + return new JSObject(internal); + } + + + /** + * Finalization decrements the reference count on the corresponding + * JavaScript object. + */ + protected void finalize() + { + System.err.println("JSObject.finalize "); + PluginAppletViewer.JavaScriptFinalize(internal); + } + + + /** + * Override java.lang.Object.equals() because identity is not preserved + * with instances of JSObject. + */ + public boolean equals(Object obj) + { + System.err.println("JSObject.equals " + obj); + + return false; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/netscape/javascript/JSProxy.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,58 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * The JSProxy interface allows applets and plugins to + * share javascript contexts. + */ + +package netscape.javascript; +import java.applet.Applet; + +public interface JSProxy { + Object getMember(JSObject jso, String name); + Object getSlot(JSObject jso, int index); + void setMember(JSObject jso, String name, Object value); + void setSlot(JSObject jso, int index, Object value); + void removeMember(JSObject jso, String name); + Object call(JSObject jso, String methodName, Object args[]); + Object eval(JSObject jso, String s); + String toString(JSObject jso); + JSObject getWindow(Applet applet); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/netscape/javascript/JSRunnable.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,70 @@ +/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package netscape.javascript; + +/** + * Runs a JavaScript object with a run() method in a separate thread. + */ +public class JSRunnable implements Runnable { + private JSObject runnable; + + public JSRunnable(JSObject runnable) { + this.runnable = runnable; + synchronized(this) { + new Thread(this).start(); + try { + this.wait(); + } catch (InterruptedException ie) { + } + } + } + + public void run() { + try { + runnable.call("run", null); + synchronized(this) { + notifyAll(); + } + } catch (Throwable t) { + System.err.println(t); + t.printStackTrace(System.err); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/netscape/javascript/JSUtil.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,59 @@ +/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* ** */ + +package netscape.javascript; +import java.io.*; + +public class JSUtil { + + /* Return the stack trace of an exception or error as a String */ + public static String getStackTrace(Throwable t) { + ByteArrayOutputStream captureStream; + PrintWriter p; + + captureStream = new ByteArrayOutputStream(); + p = new PrintWriter(captureStream); + + t.printStackTrace(p); + p.flush(); + + return captureStream.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/GetMemberPluginCallRequest.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,78 @@ +/* GetMemberPluginCallRequest -- represent Java-to-JavaScript requests + Copyright (C) 2008 Red Hat + +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; either version 2, or (at your option) +any later version. + +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 org.classpath.icedtea.plugin; + +import sun.applet.AppletSecurityContextManager; +import sun.applet.PluginCallRequest; + +public class GetMemberPluginCallRequest extends PluginCallRequest { + Object object = null; + + public GetMemberPluginCallRequest(String message, String returnString) { + super(message, returnString); + System.out.println ("GetMEMBerPLUGINCAlL " + message + " " + returnString); + } + + public void parseReturn(String message) { + System.out.println ("GetMEMBerparseReturn GOT: " + message); + String[] args = message.split(" "); + // FIXME: add thread ID to messages to support multiple + // threads using the netscape.javascript package. + object = AppletSecurityContextManager.getSecurityContext(0).getObject(Integer.parseInt(args[1])); + setDone(true); + } + + /** + * Returns whether the given message is serviceable by this object + * + * @param message The message to service + * @return boolean indicating if message is serviceable + */ + public boolean serviceable(String message) { + return message.contains("JavaScriptCall") || + message.contains("JavaScriptEval") || + message.contains("JavaScriptGetMember") || + message.contains("JavaScriptGetSlot") || + message.contains("JavaScriptToString"); + } + + public Object getObject() { + return this.object; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/GetWindowPluginCallRequest.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,76 @@ +/* GetWindowPluginCallRequest -- represent Java-to-JavaScript requests + Copyright (C) 2008 Red Hat + +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; either version 2, or (at your option) +any later version. + +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 org.classpath.icedtea.plugin; + +import java.security.AccessControlContext; +import java.security.ProtectionDomain; + +import sun.applet.PluginCallRequest; + + +public class GetWindowPluginCallRequest extends PluginCallRequest { + // FIXME: look into int vs long JavaScript internal values. + int internal; + + public GetWindowPluginCallRequest(String message, String returnString) { + super(message, returnString); + } + + public void parseReturn(String message) { + System.out.println ("GetWINDOWparseReturn GOT: " + message); + String[] args = message.split(" "); + // FIXME: add thread ID to messages to support multiple + // threads using the netscape.javascript package. + internal = Integer.parseInt(args[1]); + setDone(true); + } + + /** + * Returns whether the given message is serviceable by this object + * + * @param message The message to service + * @return boolean indicating if message is serviceable + */ + public boolean serviceable(String message) { + return message.contains("JavaScriptGetWindow"); + } + + public Integer getObject() { + return this.internal; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/PluginAppletSecurityContext.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,855 @@ +/* PluginAppletSecurityContext -- execute plugin JNI messages + Copyright (C) 2008 Red Hat + +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; either version 2, or (at your option) +any later version. + +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 org.classpath.icedtea.plugin; + +import java.io.FilePermission; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.StringTokenizer; + +import sun.applet.AppletSecurityContext; +import sun.applet.PluginDebug; +import sun.applet.PluginException; + + +class Signature { + private String signature; + private int currentIndex; + private List<Class> typeList; + private static final char ARRAY = '['; + private static final char OBJECT = 'L'; + private static final char SIGNATURE_ENDCLASS = ';'; + private static final char SIGNATURE_FUNC = '('; + private static final char SIGNATURE_ENDFUNC = ')'; + private static final char VOID = 'V'; + private static final char BOOLEAN = 'Z'; + private static final char BYTE = 'B'; + private static final char CHARACTER = 'C'; + private static final char SHORT = 'S'; + private static final char INTEGER = 'I'; + private static final char LONG = 'J'; + private static final char FLOAT = 'F'; + private static final char DOUBLE = 'D'; + + private String nextTypeName() { + char key = signature.charAt(currentIndex++); + + switch (key) { + case ARRAY: + return nextTypeName() + "[]"; + + case OBJECT: + int endClass = signature.indexOf(SIGNATURE_ENDCLASS, currentIndex); + String retVal = signature.substring(currentIndex, endClass); + retVal = retVal.replace('/', '.'); + currentIndex = endClass + 1; + return retVal; + + // FIXME: generated bytecode with classes named after + // primitives will not work in this scheme -- those + // classes will be incorrectly treated as primitive + // types. + case VOID: + return "void"; + case BOOLEAN: + return "boolean"; + case BYTE: + return "byte"; + case CHARACTER: + return "char"; + case SHORT: + return "short"; + case INTEGER: + return "int"; + case LONG: + return "long"; + case FLOAT: + return "float"; + case DOUBLE: + return "double"; + + case SIGNATURE_ENDFUNC: + case SIGNATURE_FUNC: + return nextTypeName(); + + default: + throw new IllegalArgumentException( + "Invalid JNI signature character '" + key + "'"); + } + } + + public Signature(String signature, String src) { + this.signature = signature; + currentIndex = 0; + typeList = new ArrayList<Class>(10); + + String elem; + while (currentIndex < signature.length()) { + elem = nextTypeName(); + // System.out.println ("NEXT TYPE: " + elem); + Class primitive = primitiveNameToType(elem); + if (primitive != null) + typeList.add(primitive); + else { + // System.out.println ("HERE1"); + int dimsize = 0; + int n = elem.indexOf('['); + if (n != -1) { + // System.out.println ("HERE2"); + String arrayType = elem.substring(0, n); + dimsize++; + n = elem.indexOf('[', n + 1); + // System.out.println ("HERE2.5"); + while (n != -1) { + dimsize++; + n = elem.indexOf('[', n + 1); + // System.out.println ("HERE2.8"); + } + int[] dims = new int[dimsize]; + primitive = primitiveNameToType(arrayType); + // System.out.println ("HERE3"); + if (primitive != null) { + typeList.add(Array.newInstance(primitive, dims) + .getClass()); + // System.out.println ("HERE4"); + } else + typeList.add(Array.newInstance( + getClass(arrayType, src), dims).getClass()); + } else { + typeList.add(getClass(elem, src)); + } + } + } + if (typeList.size() == 0) { + throw new IllegalArgumentException("Invalid JNI signature '" + + signature + "'"); + } + } + + public static Class getClass(String name, String src) { + + Class c = null; + + try { + c = Class.forName(name); + } catch (ClassNotFoundException cnfe) { + + StringTokenizer st = new StringTokenizer(src, ","); + + while (st.hasMoreTokens()) { + + String tok = st.nextToken(); + System.err.println("Searching for " + name + " at key " + tok); + + try { + c = PluginAppletSecurityContext.classLoaders.get(tok).loadClass(name); + } catch (ClassNotFoundException e) { + // do nothing .. thrown below + } + + if (c != null) + break; + } + } + + if (c == null) { + throw (new RuntimeException(new ClassNotFoundException("Unable to find class " + name))); + } + + return c; + } + + public static Class primitiveNameToType(String name) { + if (name.equals("void")) + return Void.TYPE; + else if (name.equals("boolean")) + return Boolean.TYPE; + else if (name.equals("byte")) + return Byte.TYPE; + else if (name.equals("char")) + return Character.TYPE; + else if (name.equals("short")) + return Short.TYPE; + else if (name.equals("int")) + return Integer.TYPE; + else if (name.equals("long")) + return Long.TYPE; + else if (name.equals("float")) + return Float.TYPE; + else if (name.equals("double")) + return Double.TYPE; + else + return null; + } + + public Class[] getClassArray() { + return typeList.subList(0, typeList.size() - 1).toArray(new Class[] {}); + } +} + +public class PluginAppletSecurityContext extends AppletSecurityContext { + + public static HashMap<String, ClassLoader> classLoaders = new HashMap<String, ClassLoader>(); + + // FIXME: make private + public PluginObjectStore store = new PluginObjectStore(); + private Throwable throwable = null; + private ClassLoader liveconnectLoader = ClassLoader.getSystemClassLoader(); + int identifier = 0; + + public PluginAppletSecurityContext(int identifier) { + this.identifier = identifier; + } + + private static <V> V parseCall(String s, String src, Class<V> c) { + if (c == Integer.class) + return (V) new Integer(s); + else if (c == String.class) + return (V) new String(s); + else if (c == Signature.class) + return (V) new Signature(s, src); + else + throw new RuntimeException("Unexpected call value."); + } + + private Object parseArgs(String s, Class c) { + if (c == Boolean.TYPE || c == Boolean.class) + return new Boolean(s); + else if (c == Byte.TYPE || c == Byte.class) + return new Byte(s); + else if (c == Character.TYPE || c == Character.class) { + String[] bytes = s.split("_"); + int low = Integer.parseInt(bytes[0]); + int high = Integer.parseInt(bytes[1]); + int full = ((high << 8) & 0x0ff00) | (low & 0x0ff); + return new Character((char) full); + } else if (c == Short.TYPE || c == Short.class) + return new Short(s); + else if (c == Integer.TYPE || c == Integer.class) + return new Integer(s); + else if (c == Long.TYPE || c == Long.class) + return new Long(s); + else if (c == Float.TYPE || c == Float.class) + return new Float(s); + else if (c == Double.TYPE || c == Double.class) + return new Double(s); + else + return store.getObject(new Integer(s)); + } + + public void addClassLoader(String id, ClassLoader cl) { + this.classLoaders.put(id, cl); + } + + public void handleMessage(String src, int reference, String message) { + + try { + if (message.startsWith("FindClass")) { + ClassLoader cl = null; + Class c = null; + cl = liveconnectLoader; + String className = message.substring("FindClass".length() + 1) + .replace('/', '.'); + + try { + c = cl.loadClass(className); + store.reference(c); + write(reference, "FindClass " + store.getIdentifier(c)); + } catch (ClassNotFoundException cnfe) { + write(reference, "FindClass 0"); + } + + } else if (message.startsWith("GetStaticMethodID") + || message.startsWith("GetMethodID")) { + String[] args = message.split(" "); + Integer classID = parseCall(args[1], src, Integer.class); + String methodName = parseCall(args[2], src, String.class); + Signature signature = parseCall(args[3], src, Signature.class); + Object[] a = signature.getClassArray(); + + Class c = (Class) store.getObject(classID); + Method m = null; + Constructor cs = null; + Object o = null; + if (methodName.equals("<init>") + || methodName.equals("<clinit>")) { + o = cs = c.getConstructor(signature.getClassArray()); + store.reference(cs); + } else { + o = m = c.getMethod(methodName, signature.getClassArray()); + store.reference(m); + } + PluginDebug.debug(o + " has id " + store.getIdentifier(o)); + write(reference, args[0] + " " + store.getIdentifier(o)); + } else if (message.startsWith("GetStaticFieldID") + || message.startsWith("GetFieldID")) { + String[] args = message.split(" "); + Integer classID = parseCall(args[1], src, Integer.class); + String fieldName = parseCall(args[2], src, String.class); + Signature signature = parseCall(args[3], src, Signature.class); + + Class c = (Class) store.getObject(classID); + Field f = null; + f = c.getField(fieldName); + + store.reference(f); + + write(reference, "GetStaticFieldID " + store.getIdentifier(f)); + } else if (message.startsWith("GetStaticField")) { + String[] args = message.split(" "); + String type = parseCall(args[1], src, String.class); + Integer classID = parseCall(args[1], src, Integer.class); + Integer fieldID = parseCall(args[2], src, Integer.class); + + Class c = (Class) store.getObject(classID); + Field f = (Field) store.getObject(fieldID); + + Object ret = null; + ret = f.get(c); + + // System.out.println ("FIELD VALUE: " + ret); + if (ret == null) { + write(reference, "GetStaticField 0"); + } else if (f.getType() == Boolean.TYPE + || f.getType() == Byte.TYPE + || f.getType() == Character.TYPE + || f.getType() == Short.TYPE + || f.getType() == Integer.TYPE + || f.getType() == Long.TYPE + || f.getType() == Float.TYPE + || f.getType() == Double.TYPE) { + write(reference, "GetStaticField " + ret); + } else { + // Track returned object. + store.reference(ret); + write(reference, "GetStaticField " + + store.getIdentifier(ret)); + } + } else if (message.startsWith("SetStaticField")) { + String[] args = message.split(" "); + String type = parseCall(args[1], src, String.class); + Integer classID = parseCall(args[2], src, Integer.class); + Integer fieldID = parseCall(args[3], src, Integer.class); + + Object value = null; + if (Signature.primitiveNameToType(type) != null) { + value = parseArgs(args[4], Signature + .primitiveNameToType(type)); + // System.out.println ("HERE1: " + value); + } else { + value = parseArgs(args[3], Object.class); + // System.out.println ("HERE2: " + value); + } + + Class c = (Class) store.getObject(classID); + Field f = (Field) store.getObject(fieldID); + + f.set(c, value); + + write(reference, "SetStaticField"); + } else if (message.startsWith("SetField")) { + String[] args = message.split(" "); + String type = parseCall(args[1], src, String.class); + Integer objectID = parseCall(args[2], src, Integer.class); + Integer fieldID = parseCall(args[3], src, Integer.class); + + Object value = null; + if (Signature.primitiveNameToType(type) != null) { + value = parseArgs(args[4], Signature + .primitiveNameToType(type)); + // System.out.println ("HERE1: " + value); + } else { + value = parseArgs(args[3], Object.class); + // System.out.println ("HERE2: " + value); + } + + Object o = (Object) store.getObject(objectID); + Field f = (Field) store.getObject(fieldID); + + f.set(o, value); + + write(reference, "SetField"); + } else if (message.startsWith("GetObjectArrayElement")) { + String[] args = message.split(" "); + Integer arrayID = parseCall(args[1], src, Integer.class); + Integer index = parseCall(args[2], src, Integer.class); + + Object[] o = (Object[]) store.getObject(arrayID); + Object ret = null; + + ret = o[index]; + + // Track returned object. + store.reference(ret); + // System.out.println ("array element: " + index + " " + ret); + write(reference, "GetObjectArrayElement " + + store.getIdentifier(ret)); + } else if (message.startsWith("SetObjectArrayElement")) { + String[] args = message.split(" "); + Integer arrayID = parseCall(args[1], src, Integer.class); + Integer index = parseCall(args[2], src, Integer.class); + Integer objectID = parseCall(args[3], src, Integer.class); + + Object[] o = (Object[]) store.getObject(arrayID); + Object toSet = (Object) store.getObject(objectID); + + o[index] = toSet; + + write(reference, "SetObjectArrayElement"); + } else if (message.startsWith("GetArrayLength")) { + String[] args = message.split(" "); + Integer arrayID = parseCall(args[1], src, Integer.class); + + System.out.println("ARRAYID: " + arrayID); + Object o = (Object) store.getObject(arrayID); + int len = 0; + len = Array.getLength(o); + // System.out.println ("Returning array length: " + len); + + // System.out.println ("array length: " + o + " " + len); + write(reference, "GetArrayLength " + Array.getLength(o)); + } else if (message.startsWith("GetField")) { + String[] args = message.split(" "); + String type = parseCall(args[1], src, String.class); + Integer objectID = parseCall(args[1], src, Integer.class); + Integer fieldID = parseCall(args[2], src, Integer.class); + + Object o = (Object) store.getObject(objectID); + Field f = (Field) store.getObject(fieldID); + + Object ret = null; + ret = f.get(o); + + // System.out.println ("FIELD VALUE: " + ret); + if (ret == null) { + write(reference, "GetField 0"); + } else if (f.getType() == Boolean.TYPE + || f.getType() == Byte.TYPE + || f.getType() == Character.TYPE + || f.getType() == Short.TYPE + || f.getType() == Integer.TYPE + || f.getType() == Long.TYPE + || f.getType() == Float.TYPE + || f.getType() == Double.TYPE) { + write(reference, "GetField " + ret); + } else { + // Track returned object. + store.reference(ret); + write(reference, "GetField " + store.getIdentifier(ret)); + } + } else if (message.startsWith("GetObjectClass")) { + int oid = Integer.parseInt(message.substring("GetObjectClass" + .length() + 1)); + // System.out.println ("GETTING CLASS FOR: " + oid); + Class c = store.getObject(oid).getClass(); + // System.out.println (" OBJ: " + store.getObject(oid)); + // System.out.println (" CLS: " + c); + store.reference(c); + + write(reference, "GetObjectClass " + store.getIdentifier(c)); + } else if (message.startsWith("CallStaticMethod")) { + String[] args = message.split(" "); + Integer classID = parseCall(args[1], src, Integer.class); + Integer methodID = parseCall(args[2], src, Integer.class); + + System.out.println("GETTING: " + methodID); + Method m = (Method) store.getObject(methodID); + System.out.println("GOT: " + m); + Class[] argTypes = m.getParameterTypes(); + + Object[] arguments = new Object[argTypes.length]; + for (int i = 0; i < argTypes.length; i++) { + arguments[i] = parseArgs(args[3 + i], argTypes[i]); + // System.out.println ("GOT ARG: " + argTypes[i] + " " + + // arguments[i]); + } + + // System.out.println ("Calling " + m); + Object ret = null; + ret = m.invoke(null, arguments); + + // if (ret != null) + // System.out.println ("RETURN VALUE: " + ret + " " + + // ret.getClass()); + // else + // System.out.println ("RETURN VALUE: " + ret); + if (ret == null) { + write(reference, "CallStaticMethod void"); + } else if (m.getReturnType() == Boolean.TYPE + || m.getReturnType() == Byte.TYPE + || m.getReturnType() == Short.TYPE + || m.getReturnType() == Integer.TYPE + || m.getReturnType() == Long.TYPE + || m.getReturnType() == Float.TYPE + || m.getReturnType() == Double.TYPE) { + write(reference, "CallStaticMethod " + ret); + } else if (m.getReturnType() == Character.TYPE) { + char ch = (Character) ret; + int high = (((int) ch) >> 8) & 0x0ff; + int low = ((int) ch) & 0x0ff; + write(reference, "CallStaticMethod " + low + "_" + high); + } else { + // Track returned object. + store.reference(ret); + write(reference, "CallStaticMethod " + + store.getIdentifier(ret)); + } + } else if (message.startsWith("CallMethod")) { + String[] args = message.split(" "); + Integer objectID = parseCall(args[1], src, Integer.class); + Integer methodID = parseCall(args[2], src, Integer.class); + + Object o = (Object) store.getObject(objectID); + Method m = (Method) store.getObject(methodID); + Class[] argTypes = m.getParameterTypes(); + + Object[] arguments = new Object[argTypes.length]; + for (int i = 0; i < argTypes.length; i++) { + arguments[i] = parseArgs(args[3 + i], argTypes[i]); + PluginDebug.debug("GOT ARG: " + argTypes[i] + " " + + arguments[i]); + } + + String collapsedArgs = ""; + for (String s : args) { + collapsedArgs += " " + s; + } + + PluginDebug.debug("Calling method " + m + " on object " + o + + " with " + arguments); + Object ret = null; + ret = m.invoke(o, arguments); + + String retO; + if (ret == null) { + retO = "null"; + } else { + retO = ret.getClass().toString(); + } + + PluginDebug.debug("Calling " + m + " on " + o + " with " + + collapsedArgs + " and that returned: " + ret + + " of type " + retO); + + if (ret == null) { + write(reference, "CallMethod void"); + } else if (m.getReturnType() == Boolean.TYPE + || m.getReturnType() == Byte.TYPE + || m.getReturnType() == Short.TYPE + || m.getReturnType() == Integer.TYPE + || m.getReturnType() == Long.TYPE + || m.getReturnType() == Float.TYPE + || m.getReturnType() == Double.TYPE) { + write(reference, "CallMethod " + ret); + } else if (m.getReturnType() == Character.TYPE) { + char ch = (Character) ret; + int high = (((int) ch) >> 8) & 0x0ff; + int low = ((int) ch) & 0x0ff; + write(reference, "CallMethod " + low + "_" + high); + } else { + // Track returned object. + store.reference(ret); + write(reference, "CallMethod " + store.getIdentifier(ret)); + } + } else if (message.startsWith("GetSuperclass")) { + String[] args = message.split(" "); + Integer classID = parseCall(args[1], src, Integer.class); + Class c = null; + Class ret = null; + + c = (Class) store.getObject(classID); + ret = c.getSuperclass(); + store.reference(ret); + + write(reference, "GetSuperclass " + store.getIdentifier(ret)); + } else if (message.startsWith("IsAssignableFrom")) { + String[] args = message.split(" "); + Integer classID = parseCall(args[1], src, Integer.class); + Integer superclassID = parseCall(args[2], src, Integer.class); + + boolean result = false; + Class clz = (Class) store.getObject(classID); + Class sup = (Class) store.getObject(superclassID); + + result = sup.isAssignableFrom(clz); + + write(reference, "IsAssignableFrom " + (result ? "1" : "0")); + } else if (message.startsWith("IsInstanceOf")) { + String[] args = message.split(" "); + Integer objectID = parseCall(args[1], src, Integer.class); + Integer classID = parseCall(args[2], src, Integer.class); + + boolean result = false; + Object o = (Object) store.getObject(objectID); + Class c = (Class) store.getObject(classID); + + result = c.isInstance(o); + + write(reference, "IsInstanceOf " + (result ? "1" : "0")); + } else if (message.startsWith("GetStringUTFLength")) { + String[] args = message.split(" "); + Integer stringID = parseCall(args[1], src, Integer.class); + + String o = null; + byte[] b = null; + o = (String) store.getObject(stringID); + b = o.getBytes("UTF-8"); + // System.out.println ("STRING UTF-8 LENGTH: " + o + " " + + // b.length); + + write(reference, "GetStringUTFLength " + o.length()); + } else if (message.startsWith("GetStringLength")) { + String[] args = message.split(" "); + Integer stringID = parseCall(args[1], src, Integer.class); + + String o = null; + byte[] b = null; + o = (String) store.getObject(stringID); + b = o.getBytes("UTF-16LE"); + // System.out.println ("STRING UTF-16 LENGTH: " + o + " " + + // b.length); + + // System.out.println ("Java: GetStringLength " + b.length); + write(reference, "GetStringLength " + o.length()); + } else if (message.startsWith("GetStringUTFChars")) { + String[] args = message.split(" "); + Integer stringID = parseCall(args[1], src, Integer.class); + + String o = null; + byte[] b = null; + StringBuffer buf = null; + o = (String) store.getObject(stringID); + b = o.getBytes("UTF-8"); + buf = new StringBuffer(b.length * 2); + buf.append(b.length); + for (int i = 0; i < b.length; i++) + buf + .append(" " + + Integer + .toString(((int) b[i]) & 0x0ff, 16)); + + // System.out.println ("Java: GetStringUTFChars: " + o); + // //System.out.println ("String UTF BYTES: " + buf); + write(reference, "GetStringUTFChars " + buf); + } else if (message.startsWith("GetStringChars")) { + String[] args = message.split(" "); + Integer stringID = parseCall(args[1], src, Integer.class); + + String o = null; + byte[] b = null; + StringBuffer buf = null; + o = (String) store.getObject(stringID); + // FIXME: LiveConnect uses UCS-2. + b = o.getBytes("UTF-16LE"); + buf = new StringBuffer(b.length * 2); + buf.append(b.length); + for (int i = 0; i < b.length; i++) + buf + .append(" " + + Integer + .toString(((int) b[i]) & 0x0ff, 16)); + + System.out.println("Java: GetStringChars: " + o); + System.out.println(" String BYTES: " + buf); + write(reference, "GetStringChars " + buf); + } else if (message.startsWith("NewArray")) { + String[] args = message.split(" "); + String type = parseCall(args[1], src, String.class); + Integer length = parseCall(args[2], src, Integer.class); + + // System.out.println ("CALLING: NewArray: " + type + " " + + // length + " " + // + Signature.primitiveNameToType(type)); + + Object newArray = null; + newArray = Array.newInstance(Signature + .primitiveNameToType(type), length); + + store.reference(newArray); + write(reference, "NewArray " + store.getIdentifier(newArray)); + } else if (message.startsWith("NewObjectArray")) { + String[] args = message.split(" "); + Integer length = parseCall(args[1], src, Integer.class); + Integer classID = parseCall(args[2], src, Integer.class); + Integer objectID = parseCall(args[3], src, Integer.class); + + // System.out.println ("CALLING: NewObjectArray: " + + // classID + " " + length + " " + // + objectID); + + Object newArray = null; + newArray = Array.newInstance((Class) store.getObject(classID), + length); + + Object[] array = (Object[]) newArray; + for (int i = 0; i < array.length; i++) + array[i] = store.getObject(objectID); + store.reference(newArray); + write(reference, "NewObjectArray " + + store.getIdentifier(newArray)); + } else if (message.startsWith("NewObject")) { + String[] args = message.split(" "); + Integer classID = parseCall(args[1], src, Integer.class); + Integer methodID = parseCall(args[2], src, Integer.class); + + final Constructor m = (Constructor) store.getObject(methodID); + Class[] argTypes = m.getParameterTypes(); + + // System.out.println ("NEWOBJ: HERE1"); + final Object[] arguments = new Object[argTypes.length]; + // System.out.println ("NEWOBJ: HERE2"); + for (int i = 0; i < argTypes.length; i++) { + arguments[i] = parseArgs(args[3 + i], argTypes[i]); + // System.out.println ("NEWOBJ: GOT ARG: " + arguments[i]); + } + + Object ret = m.newInstance(arguments); + store.reference(ret); + + write(reference, "NewObject " + store.getIdentifier(ret)); + + } else if (message.startsWith("NewString")) { + System.out.println("MESSAGE: " + message); + String[] args = message.split(" "); + Integer strlength = parseCall(args[1], src, Integer.class); + int bytelength = 2 * strlength; + byte[] byteArray = new byte[bytelength]; + String ret = null; + for (int i = 0; i < strlength; i++) { + int c = parseCall(args[2 + i], src, Integer.class); + System.out.println("char " + i + " " + c); + // Low. + byteArray[2 * i] = (byte) (c & 0x0ff); + // High. + byteArray[2 * i + 1] = (byte) ((c >> 8) & 0x0ff); + } + ret = new String(byteArray, 0, bytelength, "UTF-16LE"); + System.out.println("NEWSTRING: " + ret); + + // System.out.println ("NEWOBJ: CALLED: " + ret); + // System.out.println ("NEWOBJ: CALLED: " + + // store.getObject(ret)); + store.reference(ret); + write(reference, "NewString " + store.getIdentifier(ret)); + } else if (message.startsWith("NewStringUTF")) { + System.out.println("MESSAGE: " + message); + String[] args = message.split(" "); + byte[] byteArray = new byte[60]; + String ret = null; + int i = 0; + int c = 0; + while (((byte) c) != 0) { + c = parseCall(args[1 + i], src, Integer.class); + byteArray[i] = (byte) c; + i++; + if (i == byteArray.length) { + byte[] newByteArray = new byte[2 * byteArray.length]; + System.arraycopy(byteArray, 0, newByteArray, 0, + byteArray.length); + byteArray = newByteArray; + } + } + byteArray[i] = (byte) 0; + ret = new String(byteArray, "UTF-8"); + System.out.println("NEWSTRINGUTF: " + ret); + + store.reference(ret); + write(reference, "NewStringUTF " + store.getIdentifier(ret)); + } else if (message.startsWith("ExceptionOccurred")) { + System.out.println("EXCEPTION: " + throwable); + if (throwable != null) + store.reference(throwable); + write(reference, "ExceptionOccurred " + + store.getIdentifier(throwable)); + } else if (message.startsWith("ExceptionClear")) { + if (throwable != null) + store.unreference(store.getIdentifier(throwable)); + throwable = null; + write(reference, "ExceptionClear"); + } else if (message.startsWith("DeleteGlobalRef")) { + String[] args = message.split(" "); + Integer id = parseCall(args[1], src, Integer.class); + store.unreference(id); + write(reference, "DeleteGlobalRef"); + } else if (message.startsWith("DeleteLocalRef")) { + String[] args = message.split(" "); + Integer id = parseCall(args[1], src, Integer.class); + store.unreference(id); + write(reference, "DeleteLocalRef"); + } else if (message.startsWith("NewGlobalRef")) { + String[] args = message.split(" "); + Integer id = parseCall(args[1], src, Integer.class); + store.reference(store.getObject(id)); + write(reference, "NewGlobalRef " + id); + } + } catch (Throwable t) { + t.printStackTrace(); + throwable = t; + PluginException p = new PluginException(this.streamhandler, identifier, reference, t); + } + } + + private void write(int reference, String message) { + PluginDebug.debug("appletviewer writing " + message); + streamhandler.write("context " + identifier + " reference " + reference + + " " + message); + } + + public void dumpStore() { + store.dump(); + } + + public Object getObject(int identifier) { + return store.getObject(identifier); + } + + public int getIdentifier(Object o) { + return store.getIdentifier(o); + } + + public void store(Object o) { + store.reference(o); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/PluginCallRequestFactoryImpl.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,22 @@ +package org.classpath.icedtea.plugin; + +import sun.applet.PluginCallRequest; +import sun.applet.PluginCallRequestFactory; + +public class PluginCallRequestFactoryImpl implements PluginCallRequestFactory { + + public PluginCallRequest getPluginCallRequest(String id, String message, String returnString) { + + if (id == "member") { + return new GetMemberPluginCallRequest(message, returnString); + } else if (id == "void") { + return new VoidPluginCallRequest(message, returnString); + } else if (id == "window") { + return new GetWindowPluginCallRequest(message, returnString); + } else { + throw new RuntimeException ("Unknown plugin call request type requested from factory"); + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/PluginMain.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,193 @@ +/* + * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * 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. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package org.classpath.icedtea.plugin; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.Socket; +import java.util.Enumeration; +import java.util.Properties; + +import sun.applet.AppletSecurityContext; +import sun.applet.AppletSecurityContextManager; +import sun.applet.PluginAppletViewer; +import sun.applet.PluginStreamHandler; + +/** + * The main entry point into PluginAppletViewer. + */ +public class PluginMain +{ + final boolean redirectStreams = true; + static PluginStreamHandler streamHandler; + + // This is used in init(). Getting rid of this is desirable but depends + // on whether the property that uses it is necessary/standard. + public static final String theVersion = System.getProperty("java.version"); + + private AppletSecurityContext securityContext; + + /** + * The main entry point into AppletViewer. + */ + public static void main(String args[]) + throws IOException + { + + if (args.length != 1) { + // Indicate to plugin that appletviewer is installed correctly. + System.exit(0); + } + + int port = 0; + try { + port = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + System.err.println("Failed to parse port number: " + e); + System.exit(1); + } + + PluginMain pm = new PluginMain(); + + } + + public PluginMain() { + + if (redirectStreams) { + try { + File errFile = new File("/tmp/java.stderr"); + File outFile = new File("/tmp/java.stdout"); + + System.setErr(new PrintStream(new FileOutputStream(errFile))); + System.setOut(new PrintStream(new FileOutputStream(outFile))); + + } catch (Exception e) { + System.err.println("Unable to redirect streams"); + e.printStackTrace(); + } + } + + // INSTALL THE SECURITY MANAGER + init(); + + connect(50007); + + securityContext = new PluginAppletSecurityContext(0); + securityContext.setStreamhandler(streamHandler); + AppletSecurityContextManager.addContext(0, securityContext); + + PluginAppletViewer.setStreamhandler(streamHandler); + PluginAppletViewer.setPluginCallRequestFactory(new PluginCallRequestFactoryImpl()); + + // Streams set. Start processing. + streamHandler.startProcessing(); + } + + public void connect(int port) { + /* + * Code for TCP/IP communication + */ + Socket socket = null; + + try { + socket = new Socket("localhost", port); + } catch (Exception e) { + e.printStackTrace(); + } + + System.err.println("Socket initialized. Proceeding with start()"); + + try { + streamHandler = new PluginStreamHandlerImpl(socket.getInputStream(), socket.getOutputStream()); + System.err.println("Streams initialized"); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + private static void init() { + Properties avProps = new Properties(); + + // ADD OTHER RANDOM PROPERTIES + // XXX 5/18 need to revisit why these are here, is there some + // standard for what is available? + + // Standard browser properties + avProps.put("browser", "sun.applet.AppletViewer"); + avProps.put("browser.version", "1.06"); + avProps.put("browser.vendor", "Sun Microsystems Inc."); + avProps.put("http.agent", "Java(tm) 2 SDK, Standard Edition v" + theVersion); + + // Define which packages can be extended by applets + // XXX 5/19 probably not needed, not checked in AppletSecurity + avProps.put("package.restrict.definition.java", "true"); + avProps.put("package.restrict.definition.sun", "true"); + + // Define which properties can be read by applets. + // A property named by "key" can be read only when its twin + // property "key.applet" is true. The following ten properties + // are open by default. Any other property can be explicitly + // opened up by the browser user by calling appletviewer with + // -J-Dkey.applet=true + avProps.put("java.version.applet", "true"); + avProps.put("java.vendor.applet", "true"); + avProps.put("java.vendor.url.applet", "true"); + avProps.put("java.class.version.applet", "true"); + avProps.put("os.name.applet", "true"); + avProps.put("os.version.applet", "true"); + avProps.put("os.arch.applet", "true"); + avProps.put("file.separator.applet", "true"); + avProps.put("path.separator.applet", "true"); + avProps.put("line.separator.applet", "true"); + + // Read in the System properties. If something is going to be + // over-written, warn about it. + Properties sysProps = System.getProperties(); + for (Enumeration e = sysProps.propertyNames(); e.hasMoreElements(); ) { + String key = (String) e.nextElement(); + String val = (String) sysProps.getProperty(key); + avProps.setProperty(key, val); + } + + // INSTALL THE PROPERTY LIST + System.setProperties(avProps); + + // Create and install the security manager + //System.setSecurityManager(new AppletSecurity()); + + // REMIND: Create and install a socket factory! + } + + static boolean messageAvailable() { + return streamHandler.messageAvailable(); + } + + static String getMessage() { + return streamHandler.getMessage(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/PluginMessageConsumer.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,76 @@ +package org.classpath.icedtea.plugin; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.LinkedList; + +import sun.applet.PluginDebug; +import sun.applet.PluginStreamHandler; + + + +class PluginMessageConsumer { + + int MAX_WORKERS = 3; + LinkedList<String> readQueue = new LinkedList<String>(); + ArrayList<PluginMessageHandlerWorker> workers = new ArrayList<PluginMessageHandlerWorker>(); + PluginStreamHandler streamHandler = null; + + public PluginMessageConsumer(PluginStreamHandler streamHandler) { + + this.streamHandler = streamHandler; + + for (int i=0; i < MAX_WORKERS; i++) { + System.err.println("Creating worker " + i); + PluginMessageHandlerWorker worker = new PluginMessageHandlerWorker(streamHandler, i); + worker.start(); + workers.add(worker); + } + } + + public void consume(String message) { + + PluginDebug.debug("Consumer received message " + message); + + synchronized(readQueue) { + readQueue.add(message); + } + + PluginDebug.debug("Message " + message + " added to queue. Looking for free worker..."); + final PluginMessageHandlerWorker worker = getFreeWorker(); + + synchronized(readQueue) { + if (readQueue.size() > 0) { + worker.setmessage(readQueue.poll()); + } + } + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run () { + worker.interrupt(); + return null; + } + }); + } + + private PluginMessageHandlerWorker getFreeWorker() { + + // FIXME: Can be made more efficient by having an idle worker pool + + while (true) { + for (PluginMessageHandlerWorker worker: workers) { + if (worker.isFree()) { + PluginDebug.debug("Found free worker with id " + worker.getWorkerId()); + // mark it busy before returning + worker.busy(); + return worker; + } + } + Thread.yield(); + } + + //throw new RuntimeException("Out of message handler workers"); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/PluginMessageHandlerWorker.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,79 @@ +package org.classpath.icedtea.plugin; + +import sun.applet.PluginException; +import sun.applet.PluginStreamHandler; + +class PluginMessageHandlerWorker extends Thread { + + private boolean free = true; + private int id; + private String message = null; + PluginStreamHandler streamHandler = null; + + public PluginMessageHandlerWorker(PluginStreamHandler streamHandler, int id) { + this.id = id; + this.streamHandler = streamHandler; + } + + public void setmessage(String message) { + this.message = message; + } + + public void run() { + while (true) { + + if (message != null) { + + // ideally, whoever returns things object should mark it + // busy first, but just in case.. + busy(); + System.err.println("Thread " + id + " picking up " + message + " from queue..."); + + try { + streamHandler.handleMessage(message); + } catch (PluginException pe) { + /* + catch the exception and DO NOTHING. The plugin should take over after + this error and let the user know. We don't quit because otherwise the + exception will spread to the rest of the applets which is a no-no + */ + } + + this.message = null; + } else { + + // Sleep when there is nothing to do + try { + Thread.sleep(Integer.MAX_VALUE); + System.err.println("Consumer thread " + id + " sleeping..."); + } catch (InterruptedException ie) { + System.err.println("Consumer thread " + id + " woken..."); + // nothing.. someone woke us up, see if there + // is work to do + } + } + + // mark ourselves free again + free(); + } + } + + + + public int getWorkerId() { + return id; + } + + public void busy() { + this.free = false; + } + + + public void free() { + this.free = true; + } + + public boolean isFree() { + return free; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/PluginObjectStore.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,119 @@ +/* PluginObjectStore -- manage identifier-to-object mapping + Copyright (C) 2008 Red Hat + +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; either version 2, or (at your option) +any later version. + +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 org.classpath.icedtea.plugin; + +import java.util.*; +import java.lang.reflect.*; +import java.io.*; + +public class PluginObjectStore +{ + private static HashMap<Integer, Object> objects = new HashMap(); + private static HashMap<Integer, Integer> counts = new HashMap(); + private static HashMap<Object, Integer> identifiers = new HashMap(); + // FIXME: + // + // IF uniqueID == MAX_LONG, uniqueID = + // 0 && wrapped = true + // + // if (wrapped), check if + // objects.get(uniqueID) returns null + // + // if yes, use uniqueID, if no, + // uniqueID++ and keep checking + // or: + // stack of available ids: + // derefed id -> derefed id -> nextUniqueIdentifier + private static int nextUniqueIdentifier = 1; + + public Object getObject(Integer identifier) { + return objects.get(identifier); + } + + public Integer getIdentifier(Object object) { + if (object == null) + return 0; + return identifiers.get(object); + } + + public void reference(Object object) { + Integer identifier = identifiers.get(object); + if (identifier == null) { + objects.put(nextUniqueIdentifier, object); + counts.put(nextUniqueIdentifier, 1); + identifiers.put(object, nextUniqueIdentifier); + System.out.println("JAVA ADDED: " + nextUniqueIdentifier); + System.out.println("JAVA REFERENCED: " + nextUniqueIdentifier + + " to: 1"); + nextUniqueIdentifier++; + } else { + counts.put(identifier, counts.get(identifier) + 1); + System.out.println("JAVA REFERENCED: " + identifier + + " to: " + counts.get(identifier)); + } + } + + public void unreference(int identifier) { + Integer currentCount = counts.get(identifier); + if (currentCount == null) + System.out.println("ERROR UNREFERENCING: " + identifier); + if (currentCount == 1) { + System.out.println("JAVA DEREFERENCED: " + identifier + + " to: 0"); + Object object = objects.get(identifier); + objects.remove(identifier); + counts.remove(identifier); + identifiers.remove(object); + System.out.println("JAVA REMOVED: " + identifier); + } else { + counts.put(identifier, currentCount - 1); + System.out.println("JAVA DEREFERENCED: " + + identifier + " to: " + + counts.get(identifier)); + } + } + + public void dump() { + Iterator i = objects.keySet().iterator(); + while (i.hasNext()) { + Object key = i.next(); + System.err.println(key + "::" + objects.get(key)); + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/PluginStreamHandlerImpl.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,362 @@ +package org.classpath.icedtea.plugin; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.StreamTokenizer; +import java.net.MalformedURLException; +import java.nio.charset.Charset; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.LinkedList; +import java.util.StringTokenizer; + +import sun.applet.AppletSecurityContextManager; +import sun.applet.PluginAppletViewer; +import sun.applet.PluginCallRequest; +import sun.applet.PluginDebug; +import sun.applet.PluginException; +import sun.applet.PluginStreamHandler; + +public class PluginStreamHandlerImpl implements PluginStreamHandler { + + private BufferedReader pluginInputReader; + private StreamTokenizer pluginInputTokenizer; + private BufferedWriter pluginOutputWriter; + + private RequestQueue queue = new RequestQueue(); + + LinkedList<String> writeQueue = new LinkedList<String>(); + + PluginMessageConsumer consumer; + Boolean shuttingDown = false; + + PluginAppletViewer pav; + + public PluginStreamHandlerImpl(InputStream inputstream, OutputStream outputstream) + throws MalformedURLException, IOException + { + + System.err.println("Current context CL=" + Thread.currentThread().getContextClassLoader()); + try { + pav = (PluginAppletViewer) ClassLoader.getSystemClassLoader().loadClass("sun.applet.PluginAppletViewer").newInstance(); + System.err.println("Loaded: " + pav + " CL=" + pav.getClass().getClassLoader()); + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + System.err.println("Creating consumer..."); + consumer = new PluginMessageConsumer(this); + + // Set up input and output pipes. Use UTF-8 encoding. + pluginInputReader = + new BufferedReader(new InputStreamReader(inputstream, + Charset.forName("UTF-8"))); + pluginInputTokenizer = new StreamTokenizer(pluginInputReader); + pluginInputTokenizer.resetSyntax(); + pluginInputTokenizer.whitespaceChars('\u0000', '\u0000'); + pluginInputTokenizer.wordChars('\u0001', '\u00FF'); + pluginOutputWriter = + new BufferedWriter(new OutputStreamWriter + (outputstream, Charset.forName("UTF-8"))); + + /* + while(true) { + String message = read(); + PluginDebug.debug(message); + handleMessage(message); + // TODO: + // write(queue.peek()); + } + */ + } + + public void startProcessing() { + + Thread listenerThread = new Thread() { + + public void run() { + while (true) { + + System.err.println("Waiting for data..."); + + int readChar = -1; + // blocking read, discard first character + try { + readChar = pluginInputReader.read(); + } catch (IOException ioe) { + // plugin may have detached + } + + // if not disconnected + if (readChar != -1) { + String s = read(); + System.err.println("Got data, consuming " + s); + consumer.consume(s); + } else { + try { + // Close input/output channels to plugin. + pluginInputReader.close(); + pluginOutputWriter.close(); + } catch (IOException exception) { + // Deliberately ignore IOException caused by broken + // pipe since plugin may have already detached. + } + AppletSecurityContextManager.dumpStore(0); + System.err.println("APPLETVIEWER: exiting appletviewer"); + System.exit(0); + } + } + } + }; + + listenerThread.start(); + } + + public void postMessage(String s) { + + if (s == null || s.equals("shutdown")) { + try { + // Close input/output channels to plugin. + pluginInputReader.close(); + pluginOutputWriter.close(); + } catch (IOException exception) { + // Deliberately ignore IOException caused by broken + // pipe since plugin may have already detached. + } + AppletSecurityContextManager.dumpStore(0); + System.err.println("APPLETVIEWER: exiting appletviewer"); + System.exit(0); + } + + //PluginAppletSecurityContext.contexts.get(0).store.dump(); + PluginDebug.debug("Plugin posted: " + s); + + System.err.println("Consuming " + s); + consumer.consume(s); + + PluginDebug.debug("Added to queue"); + } + + public void handleMessage(String message) throws PluginException { + + StringTokenizer st = new StringTokenizer(message, " "); + + String type = st.nextToken(); + final int identifier = Integer.parseInt(st.nextToken()); + + String rest = ""; + int reference = -1; + String src = null; + + String potentialReference = st.hasMoreTokens() ? st.nextToken() : ""; + + // if the next token is reference, read it, else reset "rest" + if (potentialReference.equals("reference")) { + reference = Integer.parseInt(st.nextToken()); + } else { + rest += potentialReference + " "; + } + + String potentialSrc = st.hasMoreTokens() ? st.nextToken() : ""; + + if (potentialSrc.equals("src")) { + src = st.nextToken(); + } else { + rest += potentialSrc + " "; + } + + while (st.hasMoreElements()) { + rest += st.nextToken(); + rest += " "; + } + + rest = rest.trim(); + + try { + + System.err.println("Breakdown -- type: " + type + " identifier: " + identifier + " reference: " + reference + " src: " + src + " rest: " + rest); + + if (rest.contains("JavaScriptGetWindow") + || rest.contains("JavaScriptGetMember") + || rest.contains("JavaScriptSetMember") + || rest.contains("JavaScriptGetSlot") + || rest.contains("JavaScriptSetSlot") + || rest.contains("JavaScriptEval") + || rest.contains("JavaScriptRemoveMember") + || rest.contains("JavaScriptCall") + || rest.contains("JavaScriptFinalize") + || rest.contains("JavaScriptToString")) { + + finishCallRequest(rest); + return; + } + + final int freference = reference; + final String frest = rest; + + if (type.equals("instance")) { + PluginAppletViewer.handleMessage(identifier, freference,frest); + } else if (type.equals("context")) { + PluginDebug.debug("Sending to PASC: " + identifier + "/" + reference + " and " + rest); + AppletSecurityContextManager.handleMessage(identifier, src, reference, rest); + } + } catch (Exception e) { + throw new PluginException(this, identifier, reference, e); + } + } + + public void postCallRequest(PluginCallRequest request) { + synchronized(queue) { + queue.post(request); + } + } + + private void finishCallRequest(String message) { + PluginDebug.debug ("DISPATCHCALLREQUESTS 1"); + synchronized(queue) { + PluginDebug.debug ("DISPATCHCALLREQUESTS 2"); + PluginCallRequest request = queue.pop(); + + // make sure we give the message to the right request + // in the queue.. for the love of God, MAKE SURE! + + // first let's be efficient.. if there was only one + // request in queue, we're already set + if (queue.size() != 0) { + + int size = queue.size(); + int count = 0; + + while (!request.serviceable(message)) { + + // something is very wrong.. we have a message to + // process, but no one to service it + if (count >= size) { + throw new RuntimeException("Unable to find processor for message " + message); + } + + // post request at the end of the queue + queue.post(request); + + // Look at the next request + request = queue.pop(); + + count++; + } + + } + + PluginDebug.debug ("DISPATCHCALLREQUESTS 3"); + if (request != null) { + PluginDebug.debug ("DISPATCHCALLREQUESTS 5"); + synchronized(request) { + request.parseReturn(message); + request.notifyAll(); + } + PluginDebug.debug ("DISPATCHCALLREQUESTS 6"); + PluginDebug.debug ("DISPATCHCALLREQUESTS 7"); + } + } + PluginDebug.debug ("DISPATCHCALLREQUESTS 8"); + } + + /** + * Read string from plugin. + * + * @return the read string + * + * @exception IOException if an error occurs + */ + private String read() + { + try { + pluginInputTokenizer.nextToken(); + } catch (IOException e) { + throw new RuntimeException(e); + } + String message = pluginInputTokenizer.sval; + PluginDebug.debug(" PIPE: appletviewer read: " + message); + if (message == null || message.equals("shutdown")) { + synchronized(shuttingDown) { + shuttingDown = true; + } + try { + // Close input/output channels to plugin. + pluginInputReader.close(); + pluginOutputWriter.close(); + } catch (IOException exception) { + // Deliberately ignore IOException caused by broken + // pipe since plugin may have already detached. + } + AppletSecurityContextManager.dumpStore(0); + System.err.println("APPLETVIEWER: exiting appletviewer"); + System.exit(0); + } + return message; + } + + /** + * Write string to plugin. + * + * @param message the message to write + * + * @exception IOException if an error occurs + */ + public void write(String message) + { + + System.err.println(" PIPE: appletviewer wrote: " + message); + synchronized(pluginOutputWriter) { + try { + pluginOutputWriter.write(message, 0, message.length()); + pluginOutputWriter.write(0); + pluginOutputWriter.flush(); + } catch (IOException e) { + // if we are shutting down, ignore write failures as + // pipe may have closed + synchronized(shuttingDown) { + if (!shuttingDown) { + e.printStackTrace(); + } + } + + // either ways, if the pipe is broken, there is nothing + // we can do anymore. Don't hang around. + System.err.println("Unable to write to PIPE. APPLETVIEWER exiting"); + System.exit(1); + } + } + + return; + /* + synchronized(writeQueue) { + writeQueue.add(message); + System.err.println(" PIPE: appletviewer wrote: " + message); + } + */ + + } + + public boolean messageAvailable() { + return writeQueue.size() != 0; + } + + public String getMessage() { + synchronized(writeQueue) { + String ret = writeQueue.size() > 0 ? writeQueue.poll() : ""; + return ret; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/RequestQueue.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,40 @@ +package org.classpath.icedtea.plugin; + +import sun.applet.PluginCallRequest; + +public class RequestQueue { + PluginCallRequest head = null; + PluginCallRequest tail = null; + private int size = 0; + + public void post(PluginCallRequest request) { + System.err.println("Securitymanager=" + System.getSecurityManager()); + if (head == null) { + head = tail = request; + tail.setNext(null); + } else { + tail.setNext(request); + tail = request; + tail.setNext(null); + } + + size++; + } + + public PluginCallRequest pop() { + if (head == null) + return null; + + PluginCallRequest ret = head; + head = head.getNext(); + ret.setNext(null); + + size--; + + return ret; + } + + public int size() { + return size; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/TestEnv.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,172 @@ +/* TestEnv -- test JavaScript-to-Java calls + Copyright (C) 2008 Red Hat + +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; either version 2, or (at your option) +any later version. + +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 org.classpath.icedtea.plugin; + +public class TestEnv +{ + public static int intField = 103; + public int intInstanceField = 7822; + public String stringField = "hello"; + // z <musical G clef> <chinese water> + public String complexStringField = "z\uD834\uDD1E\u6C34"; + + public static void TestIt() { + System.out.println("TestIt"); + } + + public static void TestItBool(boolean arg) { + System.out.println("TestItBool: " + arg); + } + + public static void TestItByte(byte arg) { + System.out.println("TestItByte: " + arg); + } + + public static void TestItChar(char arg) { + System.out.println("TestItChar: " + arg); + } + + public static void TestItShort(short arg) { + System.out.println("TestItShort: " + arg); + } + + public static void TestItInt(int arg) { + System.out.println("TestItInt: " + arg); + } + + public static void TestItLong(long arg) { + System.out.println("TestItLong: " + arg); + } + + public static void TestItFloat(float arg) { + System.out.println("TestItFloat: " + arg); + } + + public static void TestItDouble(double arg) { + System.out.println("TestItDouble: " + arg); + } + + public static void TestItObject(TestEnv arg) { + System.out.println("TestItObject: " + arg); + } + + public static void TestItObjectString(String arg) { + System.out.println("TestItObjectString: " + arg); + } + + public static void TestItIntArray(int[] arg) { + System.out.println("TestItIntArray: " + arg); + for (int i = 0; i < arg.length; i++) + System.out.println ("ELEMENT: " + i + " " + arg[i]); + } + + public static void TestItObjectArray(String[] arg) { + System.out.println("TestItObjectArray: " + arg); + for (int i = 0; i < arg.length; i++) + System.out.println ("ELEMENT: " + i + " " + arg[i]); + } + + public static void TestItObjectArrayMulti(String[][] arg) { + System.out.println("TestItObjectArrayMulti: " + arg); + for (int i = 0; i < arg.length; i++) + for (int j = 0; j < arg[i].length; j++) + System.out.println ("ELEMENT: " + i + " " + j + " " + arg[i][j]); + } + + public static boolean TestItBoolReturnTrue() { + return true; + } + + public static boolean TestItBoolReturnFalse() { + return false; + } + + public static byte TestItByteReturn() { + return (byte) 0xfe; + } + + public static char TestItCharReturn() { + return 'K'; + } + + public static char TestItCharUnicodeReturn() { + return '\u6C34'; + } + + public static short TestItShortReturn() { + return 23; + } + + public static int TestItIntReturn() { + return 3445; + } + + public static long TestItLongReturn() { + return 3242883; + } + + public static float TestItFloatReturn() { + return 9.21E4f; + } + + public static double TestItDoubleReturn() { + return 8.33E88; + } + + public static Object TestItObjectReturn() { + return new String("Thomas"); + } + + public static int[] TestItIntArrayReturn() { + return new int[] { 6, 7, 8 }; + } + + public static String[] TestItObjectArrayReturn() { + return new String[] { "Thomas", "Brigitte" }; + } + + public static String[][] TestItObjectArrayMultiReturn() { + return new String[][] { {"Thomas", "Brigitte"}, + {"Lindsay", "Michael"} }; + } + + public int TestItIntInstance(int arg) { + System.out.println("TestItIntInstance: " + this + " " + arg); + return 899; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/org/classpath/icedtea/plugin/VoidPluginCallRequest.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,69 @@ +/* VoidPluginCallRequest -- represent Java-to-JavaScript requests + Copyright (C) 2008 Red Hat + +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; either version 2, or (at your option) +any later version. + +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 org.classpath.icedtea.plugin; + +import sun.applet.PluginCallRequest; + +public class VoidPluginCallRequest extends PluginCallRequest { + public VoidPluginCallRequest(String message, String returnString) { + super(message, returnString); + System.out.println ("VoidPLUGINCAlL " + message + " " + returnString); + } + + public void parseReturn(String message) { + setDone(true); + } + + + /** + * Returns whether the given message is serviceable by this object + * + * @param message The message to service + * @return boolean indicating if message is serviceable + */ + public boolean serviceable(String message) { + return message.contains("JavaScriptFinalize") || + message.contains("JavaScriptRemoveMember") || + message.contains("JavaScriptSetMember") || + message.contains("JavaScriptSetSlot"); + } + + public Object getObject() { + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/AppletSecurityContext.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,25 @@ +package sun.applet; + +import java.util.HashMap; + +public abstract class AppletSecurityContext { + + public static PluginStreamHandler streamhandler; + + public static void setStreamhandler(PluginStreamHandler sh) { + streamhandler = sh; + } + + public abstract void handleMessage(String src, int reference, String message); + + public abstract void addClassLoader(String id, ClassLoader cl); + + public abstract void dumpStore(); + + public abstract Object getObject(int identifier); + + public abstract int getIdentifier(Object o); + + public abstract void store(Object o); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/AppletSecurityContextManager.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,27 @@ +package sun.applet; + +import java.util.HashMap; + +public class AppletSecurityContextManager { + + // Context identifier -> PluginAppletSecurityContext object. + // FIXME: make private + private static HashMap<Integer, AppletSecurityContext> contexts = new HashMap(); + + public static void addContext(int identifier, AppletSecurityContext context) { + contexts.put(identifier, context); + } + + public static AppletSecurityContext getSecurityContext(int identifier) { + return contexts.get(identifier); + } + + public static void dumpStore(int identifier) { + contexts.get(identifier).dumpStore(); + } + + public static void handleMessage(int identifier, String src, int reference, String message) { + System.err.println(identifier + " -- " + src + " -- " + reference + " -- " + message + " CONTEXT= " + contexts.get(identifier)); + contexts.get(identifier).handleMessage(src, reference, message); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/PluginAppletViewer.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,1481 @@ + /* + * Copyright 1995-2004 Sun Microsystems, Inc. All Rights Reserved. + * 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. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + package sun.applet; + + import java.applet.Applet; +import java.applet.AppletContext; +import java.applet.AudioClip; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Label; +import java.awt.Toolkit; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.Reader; +import java.io.StringReader; +import java.net.SocketPermission; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; + +import net.sourceforge.jnlp.NetxPanel; + +import sun.awt.AppContext; +import sun.awt.SunToolkit; +import sun.awt.X11.XEmbeddedFrame; +import sun.misc.Ref; + + /** + * Lets us construct one using unix-style one shot behaviors + */ + + class PluginAppletViewerFactory + { + public PluginAppletViewer createAppletViewer(int identifier, + long handle, int x, int y, + URL doc, Hashtable atts) { + PluginAppletViewer pluginappletviewer = new PluginAppletViewer(identifier, handle, x, y, doc, atts, System.out, this); + return pluginappletviewer; + } + + public boolean isStandalone() + { + return false; + } + } + + class PluginParseRequest + { + long handle; + String tag; + String documentbase; + } + + /* + */ + // FIXME: declare JSProxy implementation + public class PluginAppletViewer extends XEmbeddedFrame + implements AppletContext, Printable { + /** + * Some constants... + */ + private static String defaultSaveFile = "Applet.ser"; + + /** + * The panel in which the applet is being displayed. + */ + AppletViewerPanel panel; + + /** + * The status line. + */ + Label label; + + /** + * output status messages to this stream + */ + + PrintStream statusMsgStream; + + /** + * For cloning + */ + PluginAppletViewerFactory factory; + + int identifier; + + private static HashMap<Integer, PluginParseRequest> requests = new HashMap(); + + // Instance identifier -> PluginAppletViewer object. + private static HashMap<Integer, PluginAppletViewer> applets = new HashMap(); + + private static PluginStreamHandler streamhandler; + + private static PluginCallRequestFactory requestFactory; + + /** + * Null constructor to allow instantiation via newInstance() + */ + public PluginAppletViewer() { + } + + /** + * Create the applet viewer + */ + public PluginAppletViewer(int identifier, long handle, int x, int y, final URL doc, + final Hashtable atts, PrintStream statusMsgStream, + PluginAppletViewerFactory factory) { + super(handle, true); + this.factory = factory; + this.statusMsgStream = statusMsgStream; + this.identifier = identifier; + // FIXME: when/where do we remove this? + PluginDebug.debug ("PARSING: PUTTING " + identifier + " " + this); + applets.put(identifier, this); + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + panel = new NetxPanel(doc, atts); + AppletViewerPanel.debug("Using NetX panel"); + } catch (Exception ex) { + AppletViewerPanel.debug("Unable to start NetX applet - defaulting to Sun applet", ex); + panel = new AppletViewerPanel(doc, atts); + } + return null; + } + }); + + add("Center", panel); + panel.init(); + appletPanels.addElement(panel); + + pack(); + setVisible(true); + + WindowListener windowEventListener = new WindowAdapter() { + + public void windowClosing(WindowEvent evt) { + appletClose(); + } + + public void windowIconified(WindowEvent evt) { + appletStop(); + } + + public void windowDeiconified(WindowEvent evt) { + appletStart(); + } + }; + + class AppletEventListener implements AppletListener + { + final Frame frame; + + public AppletEventListener(Frame frame) + { + this.frame = frame; + } + + public void appletStateChanged(AppletEvent evt) + { + AppletPanel src = (AppletPanel)evt.getSource(); + + switch (evt.getID()) { + case AppletPanel.APPLET_RESIZE: { + if(src != null) { + resize(preferredSize()); + validate(); + } + break; + } + case AppletPanel.APPLET_LOADING_COMPLETED: { + Applet a = src.getApplet(); // sun.applet.AppletPanel + + // Fixed #4754451: Applet can have methods running on main + // thread event queue. + // + // The cause of this bug is that the frame of the applet + // is created in main thread group. Thus, when certain + // AWT/Swing events are generated, the events will be + // dispatched through the wrong event dispatch thread. + // + // To fix this, we rearrange the AppContext with the frame, + // so the proper event queue will be looked up. + // + // Swing also maintains a Frame list for the AppContext, + // so we will have to rearrange it as well. + // + if (a != null) + AppletPanel.changeFrameAppContext(frame, SunToolkit.targetToAppContext(a)); + else + AppletPanel.changeFrameAppContext(frame, AppContext.getAppContext()); + + break; + } + } + } + }; + + addWindowListener(windowEventListener); + panel.addAppletListener(new AppletEventListener(this)); + + // Start the applet + showStatus(amh.getMessage("status.start")); + initEventQueue(); + + try { + write("initialized"); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + + // Wait for a maximum of 10 seconds for the panel to initialize + // (happens in a separate thread) + Applet a; + int maxSleepTime = 10000; + int sleepTime = 0; + while ((a = panel.getApplet()) == null && sleepTime < maxSleepTime) { + try { + Thread.sleep(100); + sleepTime += 100; + PluginDebug.debug("Waiting for applet to initialize... "); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + + PluginDebug.debug("Applet initialized"); + + // Applet initialized. Find out it's classloader and add it to the list + AppletSecurityContextManager.getSecurityContext(0).addClassLoader(Integer.toString(identifier), a.getClass().getClassLoader()); + + } + + public static void setStreamhandler(PluginStreamHandler sh) { + streamhandler = sh; + } + + public static void setPluginCallRequestFactory(PluginCallRequestFactory rf) { + requestFactory = rf; + } + + /** + * Handle an incoming message from the plugin. + */ + public static void handleMessage(int identifier, int reference, String message) + { + + PluginDebug.debug("PAV handling: " + message); + + try { + if (message.startsWith("tag")) { + + // tag and handle must both be set before parsing, so we need + // synchronization here, as the setting of these variables + // may happen in independent threads + + synchronized(requests) { + PluginParseRequest request = requests.get(identifier); + if (request == null) { + request = new PluginParseRequest(); + requests.put(identifier, request); + } + int index = message.indexOf(' ', "tag".length() + 1); + request.documentbase = + message.substring("tag".length() + 1, index); + request.tag = message.substring(index + 1); + PluginDebug.debug ("REQUEST TAG: " + request.tag + " " + + Thread.currentThread()); + + if (request.handle != 0) { + PluginDebug.debug ("REQUEST TAG, PARSING " + + Thread.currentThread()); + PluginAppletViewer.parse + (identifier, request.handle, + new StringReader(request.tag), + new URL(request.documentbase)); + requests.remove(identifier); + } else { + PluginDebug.debug ("REQUEST HANDLE NOT SET: " + request.handle + ". BYPASSING"); + } + } + } else if (message.startsWith("handle")) { + synchronized(requests) { + PluginParseRequest request = requests.get(identifier); + if (request == null) { + request = new PluginParseRequest(); + requests.put(identifier, request); + } + request.handle = Long.parseLong + (message.substring("handle".length() + 1)); + PluginDebug.debug ("REQUEST HANDLE: " + request.handle); + if (request.tag != null) { + PluginDebug.debug ("REQUEST HANDLE, PARSING " + + Thread.currentThread()); + PluginAppletViewer.parse + (identifier, request.handle, + new StringReader(request.tag), + new URL(request.documentbase)); + requests.remove(identifier); + PluginDebug.debug ("REQUEST HANDLE, DONE PARSING " + + Thread.currentThread()); + } else { + PluginDebug.debug ("REQUEST TAG NOT SET: " + request.tag + ". BYPASSING"); + } + } + } else { + PluginDebug.debug ("HANDLING MESSAGE " + message + " instance " + identifier + " " + Thread.currentThread()); + applets.get(identifier).handleMessage(reference, message); + } + } catch (Exception e) { + throw new RuntimeException("Failed to handle message: " + message + " " + + Thread.currentThread(), e); + } + } + + public void handleMessage(int reference, String message) + { + if (message.startsWith("width")) { + int width = + Integer.parseInt(message.substring("width".length() + 1)); + //panel.setAppletSizeIfNeeded(width, -1); + setSize(width, getHeight()); + } else if (message.startsWith("height")) { + int height = + Integer.parseInt(message.substring("height".length() + 1)); + //panel.setAppletSizeIfNeeded(-1, height); + setSize(getWidth(), height); + } else if (message.startsWith("destroy")) { + dispose(); + } else if (message.startsWith("GetJavaObject")) { + // FIXME: how do we determine what security context this + // object should belong to? + Object o; + + // Wait for a maximum of 10 seconds for the panel to initialize + // (happens in a separate thread) + int maxSleepTime = 10000; + int sleepTime = 0; + while ((o = panel.getApplet()) == null && sleepTime < maxSleepTime) { + try { + Thread.sleep(100); + sleepTime += 100; + PluginDebug.debug("Waiting for applet to initialize..."); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + + System.err.println ("Looking for object " + o + " panel is " + panel.getClass()); + AppletSecurityContextManager.getSecurityContext(0).store(o); + System.err.println ("WRITING 1: " + "context 0 reference " + reference + " GetJavaObject " + + AppletSecurityContextManager.getSecurityContext(0).getIdentifier(o)); + streamhandler.write("context 0 reference " + reference + " GetJavaObject " + + AppletSecurityContextManager.getSecurityContext(0).getIdentifier(o)); + System.err.println ("WRITING 1 DONE"); + } + } + + /** + * Send the initial set of events to the appletviewer event queue. + * On start-up the current behaviour is to load the applet and call + * Applet.init() and Applet.start(). + */ + private void initEventQueue() { + // appletviewer.send.event is an undocumented and unsupported system + // property which is used exclusively for testing purposes. + PrivilegedAction pa = new PrivilegedAction() { + public Object run() { + return System.getProperty("appletviewer.send.event"); + } + }; + String eventList = (String) AccessController.doPrivileged(pa); + + if (eventList == null) { + // Add the standard events onto the event queue. + panel.sendEvent(AppletPanel.APPLET_LOAD); + panel.sendEvent(AppletPanel.APPLET_INIT); + panel.sendEvent(AppletPanel.APPLET_START); + } else { + // We're testing AppletViewer. Force the specified set of events + // onto the event queue, wait for the events to be processed, and + // exit. + + // The list of events that will be executed is provided as a + // ","-separated list. No error-checking will be done on the list. + String [] events = splitSeparator(",", eventList); + + for (int i = 0; i < events.length; i++) { + System.out.println("Adding event to queue: " + events[i]); + if (events[i].equals("dispose")) + panel.sendEvent(AppletPanel.APPLET_DISPOSE); + else if (events[i].equals("load")) + panel.sendEvent(AppletPanel.APPLET_LOAD); + else if (events[i].equals("init")) + panel.sendEvent(AppletPanel.APPLET_INIT); + else if (events[i].equals("start")) + panel.sendEvent(AppletPanel.APPLET_START); + else if (events[i].equals("stop")) + panel.sendEvent(AppletPanel.APPLET_STOP); + else if (events[i].equals("destroy")) + panel.sendEvent(AppletPanel.APPLET_DESTROY); + else if (events[i].equals("quit")) + panel.sendEvent(AppletPanel.APPLET_QUIT); + else if (events[i].equals("error")) + panel.sendEvent(AppletPanel.APPLET_ERROR); + else + // non-fatal error if we get an unrecognized event + System.out.println("Unrecognized event name: " + events[i]); + } + + while (!panel.emptyEventQueue()) ; + appletSystemExit(); + } + } + + /** + * Split a string based on the presence of a specified separator. Returns + * an array of arbitrary length. The end of each element in the array is + * indicated by the separator of the end of the string. If there is a + * separator immediately before the end of the string, the final element + * will be empty. None of the strings will contain the separator. Useful + * when separating strings such as "foo/bar/bas" using separator "/". + * + * @param sep The separator. + * @param s The string to split. + * @return An array of strings. Each string in the array is determined + * by the location of the provided sep in the original string, + * s. Whitespace not stripped. + */ + private String [] splitSeparator(String sep, String s) { + Vector v = new Vector(); + int tokenStart = 0; + int tokenEnd = 0; + + while ((tokenEnd = s.indexOf(sep, tokenStart)) != -1) { + v.addElement(s.substring(tokenStart, tokenEnd)); + tokenStart = tokenEnd+1; + } + // Add the final element. + v.addElement(s.substring(tokenStart)); + + String [] retVal = new String[v.size()]; + v.copyInto(retVal); + return retVal; + } + + /* + * Methods for java.applet.AppletContext + */ + + private static Map audioClips = new HashMap(); + + /** + * Get an audio clip. + */ + public AudioClip getAudioClip(URL url) { + checkConnect(url); + synchronized (audioClips) { + AudioClip clip = (AudioClip)audioClips.get(url); + if (clip == null) { + audioClips.put(url, clip = new AppletAudioClip(url)); + } + return clip; + } + } + + private static Map imageRefs = new HashMap(); + + /** + * Get an image. + */ + public Image getImage(URL url) { + return getCachedImage(url); + } + + static Image getCachedImage(URL url) { + // System.getSecurityManager().checkConnection(url.getHost(), url.getPort()); + return (Image)getCachedImageRef(url).get(); + } + + /** + * Get an image ref. + */ + static Ref getCachedImageRef(URL url) { + synchronized (imageRefs) { + AppletImageRef ref = (AppletImageRef)imageRefs.get(url); + if (ref == null) { + ref = new AppletImageRef(url); + imageRefs.put(url, ref); + } + return ref; + } + } + + /** + * Flush the image cache. + */ + static void flushImageCache() { + imageRefs.clear(); + } + + static Vector appletPanels = new Vector(); + + /** + * Get an applet by name. + */ + public Applet getApplet(String name) { + AppletSecurity security = (AppletSecurity)System.getSecurityManager(); + name = name.toLowerCase(); + SocketPermission panelSp = + new SocketPermission(panel.getCodeBase().getHost(), "connect"); + for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) { + AppletPanel p = (AppletPanel)e.nextElement(); + String param = p.getParameter("name"); + if (param != null) { + param = param.toLowerCase(); + } + if (name.equals(param) && + p.getDocumentBase().equals(panel.getDocumentBase())) { + + SocketPermission sp = + new SocketPermission(p.getCodeBase().getHost(), "connect"); + + if (panelSp.implies(sp)) { + return p.applet; + } + } + } + return null; + } + + /** + * Return an enumeration of all the accessible + * applets on this page. + */ + public Enumeration getApplets() { + AppletSecurity security = (AppletSecurity)System.getSecurityManager(); + Vector v = new Vector(); + SocketPermission panelSp = + new SocketPermission(panel.getCodeBase().getHost(), "connect"); + + for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) { + AppletPanel p = (AppletPanel)e.nextElement(); + if (p.getDocumentBase().equals(panel.getDocumentBase())) { + + SocketPermission sp = + new SocketPermission(p.getCodeBase().getHost(), "connect"); + if (panelSp.implies(sp)) { + v.addElement(p.applet); + } + } + } + return v.elements(); + } + + /** + * Ignore. + */ + public void showDocument(URL url) { + PluginDebug.debug("Showing document..."); + showDocument(url, "_self"); + } + + /** + * Ignore. + */ + public void showDocument(URL url, String target) { + try { + // FIXME: change to postCallRequest + write("url " + url + " " + target); + } catch (IOException exception) { + // Deliberately ignore IOException. showDocument may be + // called from threads other than the main thread after + // streamhandler.pluginOutputStream has been closed. + } + } + + /** + * Show status. + */ + public void showStatus(String status) { + try { + // FIXME: change to postCallRequest + write("status " + status); + } catch (IOException exception) { + // Deliberately ignore IOException. showStatus may be + // called from threads other than the main thread after + // streamhandler.pluginOutputStream has been closed. + } + } + + public int getWindow() { + System.out.println ("STARTING getWindow"); + PluginCallRequest request = requestFactory.getPluginCallRequest("window", + "instance " + identifier + " " + "GetWindow", + "JavaScriptGetWindow"); + System.out.println ("STARTING postCallRequest"); + streamhandler.postCallRequest(request); + System.out.println ("STARTING postCallRequest done"); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait request 1"); + synchronized(request) { + System.out.println ("wait request 2"); + while ((Integer) request.getObject() == 0) + request.wait(); + System.out.println ("wait request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + + System.out.println ("STARTING getWindow DONE"); + return (Integer) request.getObject(); + } + + // FIXME: make private, access via reflection. + public static Object getMember(int internal, String name) + { + AppletSecurityContextManager.getSecurityContext(0).store(name); + int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name); + + // Prefix with dummy instance for convenience. + PluginCallRequest request = requestFactory.getPluginCallRequest("member", + "instance " + 0 + " GetMember " + internal + " " + nameID, + "JavaScriptGetMember"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.err.println ("wait getMEM request 1"); + synchronized(request) { + System.err.println ("wait getMEM request 2"); + while (request.isDone() == false) + request.wait(); + System.err.println ("wait getMEM request 3 GOT: " + request.getObject().getClass()); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.err.println (" getMember DONE"); + return request.getObject(); + } + + public static void setMember(int internal, String name, Object value) { + AppletSecurityContextManager.getSecurityContext(0).store(name); + int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name); + AppletSecurityContextManager.getSecurityContext(0).store(value); + int valueID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(value); + + // Prefix with dummy instance for convenience. + PluginCallRequest request = requestFactory.getPluginCallRequest("void", + "instance " + 0 + " SetMember " + internal + " " + nameID + " " + valueID, + "JavaScriptSetMember"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait setMem request: " + request.getMessage()); + System.out.println ("wait setMem request 1"); + synchronized(request) { + System.out.println ("wait setMem request 2"); + while (request.isDone() == false) + request.wait(); + System.out.println ("wait setMem request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.out.println (" setMember DONE"); + } + + // FIXME: handle long index as well. + public static void setSlot(int internal, int index, Object value) { + AppletSecurityContextManager.getSecurityContext(0).store(value); + int valueID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(value); + + // Prefix with dummy instance for convenience. + PluginCallRequest request = requestFactory.getPluginCallRequest("void", + "instance " + 0 + " SetSlot " + internal + " " + index + " " + valueID, + "JavaScriptSetSlot"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait setSlot request 1"); + synchronized(request) { + System.out.println ("wait setSlot request 2"); + while (request.isDone() == false) + request.wait(); + System.out.println ("wait setSlot request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.out.println (" setSlot DONE"); + } + + public static Object getSlot(int internal, int index) + { + // Prefix with dummy instance for convenience. + PluginCallRequest request = requestFactory.getPluginCallRequest("member", + "instance " + 0 + " GetSlot " + internal + " " + index, + "JavaScriptGetSlot"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait getSlot request 1"); + synchronized(request) { + System.out.println ("wait getSlot request 2"); + while (request.isDone() == false) + request.wait(); + System.out.println ("wait getSlot request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.out.println (" getSlot DONE"); + return request.getObject(); + } + + public static Object eval(int internal, String s) + { + AppletSecurityContextManager.getSecurityContext(0).store(s); + int stringID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(s); + // Prefix with dummy instance for convenience. + // FIXME: rename GetMemberPluginCallRequest ObjectPluginCallRequest. + PluginCallRequest request = requestFactory.getPluginCallRequest("member", + "instance " + 0 + " Eval " + internal + " " + stringID, + "JavaScriptEval"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait eval request 1"); + synchronized(request) { + System.out.println ("wait eval request 2"); + while (request.isDone() == false) + request.wait(); + System.out.println ("wait eval request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.out.println (" getSlot DONE"); + return request.getObject(); + } + + public static void removeMember (int internal, String name) { + AppletSecurityContextManager.getSecurityContext(0).store(name); + int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name); + + // Prefix with dummy instance for convenience. + PluginCallRequest request = requestFactory.getPluginCallRequest("void", + "instance " + 0 + " RemoveMember " + internal + " " + nameID, + "JavaScriptRemoveMember"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait removeMember request 1"); + synchronized(request) { + System.out.println ("wait removeMember request 2"); + while (request.isDone() == false) + request.wait(); + System.out.println ("wait removeMember request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.out.println (" RemoveMember DONE"); + } + + public static Object call(int internal, String name, Object args[]) + { + // FIXME: when is this removed from the object store? + // FIXME: reference should return the ID. + // FIXME: convenience method for this long line. + AppletSecurityContextManager.getSecurityContext(0).store(name); + int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name); + AppletSecurityContextManager.getSecurityContext(0).store(args); + int argsID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(args); + + // Prefix with dummy instance for convenience. + PluginCallRequest request = requestFactory.getPluginCallRequest("member", + "instance " + 0 + " Call " + internal + " " + nameID + " " + argsID, + "JavaScriptCall"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait call request 1"); + synchronized(request) { + System.out.println ("wait call request 2"); + while (request.isDone() == false) + request.wait(); + System.out.println ("wait call request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.out.println (" Call DONE"); + return request.getObject(); + } + + public static void JavaScriptFinalize(int internal) + { + // Prefix with dummy instance for convenience. + PluginCallRequest request = requestFactory.getPluginCallRequest("void", + "instance " + 0 + " Finalize " + internal, + "JavaScriptFinalize"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait finalize request 1"); + synchronized(request) { + System.out.println ("wait finalize request 2"); + while (request.isDone() == false) + request.wait(); + System.out.println ("wait finalize request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.out.println (" finalize DONE"); + } + + public static String javascriptToString(int internal) + { + // Prefix with dummy instance for convenience. + PluginCallRequest request = requestFactory.getPluginCallRequest("member", + "instance " + 0 + " ToString " + internal, + "JavaScriptToString"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); + try { + System.out.println ("wait ToString request 1"); + synchronized(request) { + System.out.println ("wait ToString request 2"); + while (request.isDone() == false) + request.wait(); + System.out.println ("wait ToString request 3"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted waiting for call request.", + e); + } + System.out.println (" ToString DONE"); + return (String) request.getObject(); + } + + // FIXME: make this private and access it from JSObject using + // reflection. + private void write(String message) throws IOException { + System.err.println ("WRITING 2: " + "instance " + identifier + " " + message); + streamhandler.write("instance " + identifier + " " + message); + System.err.println ("WRITING 2 DONE"); + } + + public void setStream(String key, InputStream stream)throws IOException{ + // We do nothing. + } + + public InputStream getStream(String key){ + // We do nothing. + return null; + } + + public Iterator getStreamKeys(){ + // We do nothing. + return null; + } + + /** + * System parameters. + */ + static Hashtable systemParam = new Hashtable(); + + static { + systemParam.put("codebase", "codebase"); + systemParam.put("code", "code"); + systemParam.put("alt", "alt"); + systemParam.put("width", "width"); + systemParam.put("height", "height"); + systemParam.put("align", "align"); + systemParam.put("vspace", "vspace"); + systemParam.put("hspace", "hspace"); + } + + /** + * Print the HTML tag. + */ + public static void printTag(PrintStream out, Hashtable atts) { + out.print("<applet"); + + String v = (String)atts.get("codebase"); + if (v != null) { + out.print(" codebase=\"" + v + "\""); + } + + v = (String)atts.get("code"); + if (v == null) { + v = "applet.class"; + } + out.print(" code=\"" + v + "\""); + v = (String)atts.get("width"); + if (v == null) { + v = "150"; + } + out.print(" width=" + v); + + v = (String)atts.get("height"); + if (v == null) { + v = "100"; + } + out.print(" height=" + v); + + v = (String)atts.get("name"); + if (v != null) { + out.print(" name=\"" + v + "\""); + } + out.println(">"); + + // A very slow sorting algorithm + int len = atts.size(); + String params[] = new String[len]; + len = 0; + for (Enumeration e = atts.keys() ; e.hasMoreElements() ;) { + String param = (String)e.nextElement(); + int i = 0; + for (; i < len ; i++) { + if (params[i].compareTo(param) >= 0) { + break; + } + } + System.arraycopy(params, i, params, i + 1, len - i); + params[i] = param; + len++; + } + + for (int i = 0 ; i < len ; i++) { + String param = params[i]; + if (systemParam.get(param) == null) { + out.println("<param name=" + param + + " value=\"" + atts.get(param) + "\">"); + } + } + out.println("</applet>"); + } + + /** + * Make sure the atrributes are uptodate. + */ + public void updateAtts() { + Dimension d = panel.size(); + Insets in = panel.insets(); + panel.atts.put("width", + new Integer(d.width - (in.left + in.right)).toString()); + panel.atts.put("height", + new Integer(d.height - (in.top + in.bottom)).toString()); + } + + /** + * Restart the applet. + */ + void appletRestart() { + panel.sendEvent(AppletPanel.APPLET_STOP); + panel.sendEvent(AppletPanel.APPLET_DESTROY); + panel.sendEvent(AppletPanel.APPLET_INIT); + panel.sendEvent(AppletPanel.APPLET_START); + } + + /** + * Reload the applet. + */ + void appletReload() { + panel.sendEvent(AppletPanel.APPLET_STOP); + panel.sendEvent(AppletPanel.APPLET_DESTROY); + panel.sendEvent(AppletPanel.APPLET_DISPOSE); + + /** + * Fixed #4501142: Classlaoder sharing policy doesn't + * take "archive" into account. This will be overridden + * by Java Plug-in. [stanleyh] + */ + AppletPanel.flushClassLoader(panel.getClassLoaderCacheKey()); + + /* + * Make sure we don't have two threads running through the event queue + * at the same time. + */ + try { + panel.joinAppletThread(); + panel.release(); + } catch (InterruptedException e) { + return; // abort the reload + } + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + panel.createAppletThread(); + return null; + } + }); + + panel.sendEvent(AppletPanel.APPLET_LOAD); + panel.sendEvent(AppletPanel.APPLET_INIT); + panel.sendEvent(AppletPanel.APPLET_START); + } + + public int print(Graphics graphics, PageFormat pf, int pageIndex) { + return Printable.NO_SUCH_PAGE; + } + + /** + * Start the applet. + */ + void appletStart() { + panel.sendEvent(AppletPanel.APPLET_START); + } + + /** + * Stop the applet. + */ + void appletStop() { + panel.sendEvent(AppletPanel.APPLET_STOP); + } + + /** + * Shutdown a viewer. + * Stop, Destroy, Dispose and Quit a viewer + */ + private void appletShutdown(AppletPanel p) { + p.sendEvent(AppletPanel.APPLET_STOP); + p.sendEvent(AppletPanel.APPLET_DESTROY); + p.sendEvent(AppletPanel.APPLET_DISPOSE); + p.sendEvent(AppletPanel.APPLET_QUIT); + } + + /** + * Close this viewer. + * Stop, Destroy, Dispose and Quit an AppletView, then + * reclaim resources and exit the program if this is + * the last applet. + */ + void appletClose() { + + // The caller thread is event dispatch thread, so + // spawn a new thread to avoid blocking the event queue + // when calling appletShutdown. + // + final AppletPanel p = panel; + + new Thread(new Runnable() + { + public void run() + { + appletShutdown(p); + appletPanels.removeElement(p); + dispose(); + + if (countApplets() == 0) { + appletSystemExit(); + } + } + }).start(); + } + + /** + * Exit the program. + * Exit from the program (if not stand alone) - do no clean-up + */ + private void appletSystemExit() { + if (factory.isStandalone()) + System.exit(0); + } + + /** + * How many applets are running? + */ + + public static int countApplets() { + return appletPanels.size(); + } + + + /** + * The current character. + */ + static int c; + + /** + * Scan spaces. + */ + public static void skipSpace(Reader in) throws IOException { + while ((c >= 0) && + ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) { + c = in.read(); + } + } + + /** + * Scan identifier + */ + public static String scanIdentifier(Reader in) throws IOException { + StringBuffer buf = new StringBuffer(); + while (true) { + if (((c >= 'a') && (c <= 'z')) || + ((c >= 'A') && (c <= 'Z')) || + ((c >= '0') && (c <= '9')) || (c == '_')) { + buf.append((char)c); + c = in.read(); + } else { + return buf.toString(); + } + } + } + + /** + * Scan tag + */ + public static Hashtable scanTag(Reader in) throws IOException { + Hashtable atts = new Hashtable(); + skipSpace(in); + while (c >= 0 && c != '>') { + String att = scanIdentifier(in); + String val = ""; + skipSpace(in); + if (c == '=') { + int quote = -1; + c = in.read(); + skipSpace(in); + if ((c == '\'') || (c == '\"')) { + quote = c; + c = in.read(); + } + StringBuffer buf = new StringBuffer(); + while ((c > 0) && + (((quote < 0) && (c != ' ') && (c != '\t') && + (c != '\n') && (c != '\r') && (c != '>')) + || ((quote >= 0) && (c != quote)))) { + buf.append((char)c); + c = in.read(); + } + if (c == quote) { + c = in.read(); + } + skipSpace(in); + val = buf.toString(); + } + System.err.println("PUT " + att + " = '" + val + "'"); + if (! val.equals("")) { + atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val); + } + while (true) { + if ((c == '>') || (c < 0) || + ((c >= 'a') && (c <= 'z')) || + ((c >= 'A') && (c <= 'Z')) || + ((c >= '0') && (c <= '9')) || (c == '_')) + break; + c = in.read(); + } + //skipSpace(in); + } + return atts; + } + + /* values used for placement of AppletViewer's frames */ + private static int x = 0; + private static int y = 0; + private static final int XDELTA = 30; + private static final int YDELTA = XDELTA; + + static String encoding = null; + + static private Reader makeReader(InputStream is) { + if (encoding != null) { + try { + return new BufferedReader(new InputStreamReader(is, encoding)); + } catch (IOException x) { } + } + InputStreamReader r = new InputStreamReader(is); + encoding = r.getEncoding(); + return new BufferedReader(r); + } + + /** + * Scan an html file for <applet> tags + */ + public static void parse(int identifier, long handle, Reader in, URL url, String enc) + throws IOException { + encoding = enc; + parse(identifier, handle, in, url, System.out, new PluginAppletViewerFactory()); + } + + public static void parse(int identifier, long handle, Reader in, URL url) + throws IOException { + final int fIdentifier = identifier; + final long fHandle = handle; + final Reader fIn = in; + final URL fUrl = url; + PrivilegedAction pa = new PrivilegedAction() { + public Object run() { + try { + parse(fIdentifier, fHandle, fIn, fUrl, System.out, new PluginAppletViewerFactory()); + } catch (IOException ioe) { + return ioe; + } + + return null; + } + }; + + Object ret = AccessController.doPrivileged(pa); + if (ret instanceof IOException) { + throw (IOException) ret; + } + } + + public static void parse(int identifier, long handle, Reader in, URL url, + PrintStream statusMsgStream, + PluginAppletViewerFactory factory) + throws IOException + { + // <OBJECT> <EMBED> tag flags + boolean isAppletTag = false; + boolean isObjectTag = false; + boolean isEmbedTag = false; + + // warning messages + String requiresNameWarning = amh.getMessage("parse.warning.requiresname"); + String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside"); + String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode"); + String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight"); + String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth"); + String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode"); + String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight"); + String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth"); + String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode"); + String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight"); + String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth"); + String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported"); + + java.net.URLConnection conn = url.openConnection(); + /* The original URL may have been redirected - this + * sets it to whatever URL/codebase we ended up getting + */ + url = conn.getURL(); + + int ydisp = 1; + Hashtable atts = null; + + while(true) { + c = in.read(); + if (c == -1) + break; + + if (c == '<') { + c = in.read(); + if (c == '/') { + c = in.read(); + String nm = scanIdentifier(in); + if (nm.equalsIgnoreCase("applet") || + nm.equalsIgnoreCase("object") || + nm.equalsIgnoreCase("embed")) { + + // We can't test for a code tag until </OBJECT> + // because it is a parameter, not an attribute. + if(isObjectTag) { + if (atts.get("code") == null && atts.get("object") == null) { + statusMsgStream.println(objectRequiresCodeWarning); + atts = null; + } + } + + if (atts != null) { + // XXX 5/18 In general this code just simply + // shouldn't be part of parsing. It's presence + // causes things to be a little too much of a + // hack. + factory.createAppletViewer(identifier, handle, x, y, url, atts); + x += XDELTA; + y += YDELTA; + // make sure we don't go too far! + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + if ((x > d.width - 300) || (y > d.height - 300)) { + x = 0; + y = 2 * ydisp * YDELTA; + ydisp++; + } + } + atts = null; + isAppletTag = false; + isObjectTag = false; + isEmbedTag = false; + } + } + else { + String nm = scanIdentifier(in); + if (nm.equalsIgnoreCase("param")) { + Hashtable t = scanTag(in); + String att = (String)t.get("name"); + if (att == null) { + statusMsgStream.println(requiresNameWarning); + } else { + String val = (String)t.get("value"); + if (val == null) { + statusMsgStream.println(requiresNameWarning); + } else if (atts != null) { + atts.put(att.toLowerCase(), val); + } else { + statusMsgStream.println(paramOutsideWarning); + } + } + } + else if (nm.equalsIgnoreCase("applet")) { + isAppletTag = true; + atts = scanTag(in); + + // If there is a classid present, transform it to code tag + if (atts.get("code") == null && atts.get("classid") != null && + ((String) atts.get("classid")).startsWith("java:")) { + //skip "java:" + atts.put("code", ((String) atts.get("classid")).substring(5)); + } + + if (atts.get("code") == null && atts.get("object") == null) { + statusMsgStream.println(appletRequiresCodeWarning); + atts = null; + } + + if (atts.get("width") == null) { + atts.put("width", "100%"); + } + + if (atts.get("height") == null) { + atts.put("height", "100%"); + } + } + else if (nm.equalsIgnoreCase("object")) { + isObjectTag = true; + atts = scanTag(in); + + // If there is a classid present, transform it to code tag + if (atts.get("code") == null && atts.get("classid") != null && + ((String) atts.get("classid")).startsWith("java:")) { + //skip "java:" + atts.put("code", ((String) atts.get("classid")).substring(5)); + } + + // The <OBJECT> attribute codebase isn't what + // we want when not dealing with jars. If its + // defined, remove it in that case. + if(atts.get("archive") == null && atts.get("codebase") != null) { + atts.remove("codebase"); + } + + if (atts.get("width") == null) { + atts.put("width", "100%"); + } + + if (atts.get("height") == null) { + atts.put("height", "100%"); + } + } + else if (nm.equalsIgnoreCase("embed")) { + isEmbedTag = true; + atts = scanTag(in); + + // If there is a classid present, transform it to code tag + if (atts.get("code") == null && atts.get("classid") != null && + ((String) atts.get("classid")).startsWith("java:")) { + //skip "java:" + atts.put("code", ((String) atts.get("classid")).substring(5)); + } + + if (atts.get("code") == null && atts.get("object") == null) { + statusMsgStream.println(embedRequiresCodeWarning); + atts = null; + } + + if (atts.get("width") == null) { + atts.put("width", "100%"); + } + + if (atts.get("height") == null) { + atts.put("height", "100%"); + } + } + else if (nm.equalsIgnoreCase("app")) { + statusMsgStream.println(appNotLongerSupportedWarning); + Hashtable atts2 = scanTag(in); + nm = (String)atts2.get("class"); + if (nm != null) { + atts2.remove("class"); + atts2.put("code", nm + ".class"); + } + nm = (String)atts2.get("src"); + if (nm != null) { + atts2.remove("src"); + atts2.put("codebase", nm); + } + if (atts2.get("width") == null) { + atts2.put("width", "100%"); + } + if (atts2.get("height") == null) { + atts2.put("height", "100%"); + } + printTag(statusMsgStream, atts2); + statusMsgStream.println(); + } + } + } + } + in.close(); + } + + + private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer"); + + private static void checkConnect(URL url) + { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + try { + java.security.Permission perm = + url.openConnection().getPermission(); + if (perm != null) + security.checkPermission(perm); + else + security.checkConnect(url.getHost(), url.getPort()); + } catch (java.io.IOException ioe) { + security.checkConnect(url.getHost(), url.getPort()); + } + } + } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/PluginCallRequest.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,85 @@ +/* PluginCallRequest -- represent Java-to-JavaScript requests + Copyright (C) 2008 Red Hat + +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; either version 2, or (at your option) +any later version. + +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 sun.applet; + +import java.security.AccessControlContext; +import java.security.ProtectionDomain; + +// FIXME: for each type of request extend a new (anonymous?) +// PluginCallRequest. +public abstract class PluginCallRequest { + String message; + String returnString; + PluginCallRequest next; + boolean done = false; + + public PluginCallRequest(String message, String returnString) { + this.message = message; + this.returnString = returnString; + } + + public String getMessage() { + return this.message; + } + + public String getReturnString() { + return this.returnString; + } + + public boolean isDone() { + return this.done; + } + + public boolean setDone(boolean done) { + return this.done = done; + } + + public void setNext(PluginCallRequest next) { + this.next = next; + } + + public PluginCallRequest getNext() { + return this.next; + } + + public abstract void parseReturn(String message); + + public abstract boolean serviceable(String message); + + public abstract Object getObject(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/PluginCallRequestFactory.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,7 @@ +package sun.applet; + +public interface PluginCallRequestFactory { + + public PluginCallRequest getPluginCallRequest(String id, String message, String returnString); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/PluginClassLoader.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,13 @@ +package sun.applet; + +public class PluginClassLoader extends ClassLoader { + + public PluginClassLoader() { + super(); + } + + public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + return super.loadClass(name, resolve); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/PluginDebug.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,13 @@ +package sun.applet; + +import java.io.*; + +public class PluginDebug { + + static final boolean DEBUG = true; + + public static void debug(String message) { + if (DEBUG) + System.err.println(message); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/PluginException.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,15 @@ +package sun.applet; + + +public class PluginException extends Exception { + + public PluginException (PluginStreamHandler sh, int instance, int reference, Throwable t) { + t.printStackTrace(); + this.setStackTrace(t.getStackTrace()); + + AppletSecurityContextManager.dumpStore(0); + + String message = "instance " + instance + " reference " + reference + " Error " + t.getMessage(); + sh.write(message); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/sun/applet/PluginStreamHandler.java Wed Sep 24 11:44:16 2008 -0400 @@ -0,0 +1,20 @@ +package sun.applet; + + +public interface PluginStreamHandler { + + public void postMessage(String s); + + public void handleMessage(String message) throws PluginException; + + public void postCallRequest(PluginCallRequest request); + + public void write(String message); + + public boolean messageAvailable(); + + public String getMessage(); + + public void startProcessing(); + +} \ No newline at end of file
--- a/rt/net/sourceforge/jnlp/Launcher.java Mon Sep 22 10:39:01 2008 -0400 +++ b/rt/net/sourceforge/jnlp/Launcher.java Wed Sep 24 11:44:16 2008 -0400 @@ -592,6 +592,7 @@ } } catch (LaunchException ex) { + ex.printStackTrace(); exception = ex; // Exit if we can't launch the application. System.exit(0);
--- a/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java Mon Sep 22 10:39:01 2008 -0400 +++ b/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java Wed Sep 24 11:44:16 2008 -0400 @@ -135,6 +135,8 @@ if (baseDir == null) throw new IllegalStateException(JNLPRuntime.getMessage("BNoBase")); + ServiceManager.setServiceManagerStub(new XServiceManagerStub()); // ignored if we're running under Web Start + policy = new JNLPPolicy(); security = new JNLPSecurityManager(); // side effect: create JWindow @@ -143,8 +145,6 @@ System.setSecurityManager(security); } - ServiceManager.setServiceManagerStub(new XServiceManagerStub()); // ignored if we're running under Web Start - initialized = true; }
--- a/rt/netscape/javascript/JSException.java Mon Sep 22 10:39:01 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -package netscape.javascript; - -/** - * JSException is an exception which is thrown when JavaScript code - * returns an error. - */ - -public -class JSException extends RuntimeException { - public static final int EXCEPTION_TYPE_EMPTY = -1; - public static final int EXCEPTION_TYPE_VOID = 0; - public static final int EXCEPTION_TYPE_OBJECT = 1; - public static final int EXCEPTION_TYPE_FUNCTION = 2; - public static final int EXCEPTION_TYPE_STRING = 3; - public static final int EXCEPTION_TYPE_NUMBER = 4; - public static final int EXCEPTION_TYPE_BOOLEAN = 5; - public static final int EXCEPTION_TYPE_ERROR = 6; - - public String filename; - public int lineno; - public String source; - public int tokenIndex; - public int wrappedExceptionType; - public Object wrappedException; - - /** - * Constructs a JSException without a detail message. - * A detail message is a String that describes this particular exception. - * - * @deprecated Not for public use in future versions. - */ - public JSException() { - super(); - filename = "unknown"; - lineno = 0; - source = ""; - tokenIndex = 0; - wrappedExceptionType = EXCEPTION_TYPE_EMPTY; - } - - /** - * Constructs a JSException with a detail message. - * A detail message is a String that describes this particular exception. - * @param s the detail message - * - * @deprecated Not for public use in future versions. - */ - public JSException(String s) { - super(s); - filename = "unknown"; - lineno = 0; - source = ""; - tokenIndex = 0; - wrappedExceptionType = EXCEPTION_TYPE_EMPTY; - } - - /** - * Constructs a JSException with a wrapped JavaScript exception object. - * This constructor needs to be public so that Java users can throw - * exceptions to JS cleanly. - */ - public JSException(int wrappedExceptionType, Object wrappedException) { - super(); - this.wrappedExceptionType = wrappedExceptionType; - this.wrappedException = wrappedException; - } - - /** - * Constructs a JSException with a detail message and all the - * other info that usually comes with a JavaScript error. - * @param s the detail message - * - * @deprecated Not for public use in future versions. - */ - public JSException(String s, String filename, int lineno, - String source, int tokenIndex) { - super(s); - this.filename = filename; - this.lineno = lineno; - this.source = source; - this.tokenIndex = tokenIndex; - wrappedExceptionType = EXCEPTION_TYPE_EMPTY; - } - - /** - * Instance method getWrappedExceptionType returns the int mapping of the - * type of the wrappedException Object. - */ - public int getWrappedExceptionType() { - return wrappedExceptionType; - } - - /** - * Instance method getWrappedException. - */ - public Object getWrappedException() { - return wrappedException; - } - -} -
--- a/rt/netscape/javascript/JSObject.java Mon Sep 22 10:39:01 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,258 +0,0 @@ -/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* more doc todo: - * threads - * gc - * - * - */ - -package netscape.javascript; - -import java.applet.Applet; -import java.io.IOException; -import sun.applet.PluginAppletViewer; - -/** - * JSObject allows Java to manipulate objects that are - * defined in JavaScript. - * Values passed from Java to JavaScript are converted as - * follows:<ul> - * <li>JSObject is converted to the original JavaScript object - * <li>Any other Java object is converted to a JavaScript wrapper, - * which can be used to access methods and fields of the java object. - * Converting this wrapper to a string will call the toString method - * on the original object, converting to a number will call the - * doubleValue method if possible and fail otherwise. Converting - * to a boolean will try to call the booleanValue method in the - * same way. - * <li>Java arrays are wrapped with a JavaScript object that understands - * array.length and array[index] - * <li>A Java boolean is converted to a JavaScript boolean - * <li>Java byte, char, short, int, long, float, and double are converted - * to JavaScript numbers - * </ul> - * Values passed from JavaScript to Java are converted as follows:<ul> - * <li>objects which are wrappers around java objects are unwrapped - * <li>other objects are wrapped with a JSObject - * <li>strings, numbers and booleans are converted to String, Double, - * and Boolean objects respectively - * </ul> - * This means that all JavaScript values show up as some kind - * of java.lang.Object in Java. In order to make much use of them, - * you will have to cast them to the appropriate subclass of Object, - * e.g. <code>(String) window.getMember("name");</code> or - * <code>(JSObject) window.getMember("document");</code>. - */ -public final class JSObject { - /* the internal object data */ - private int internal; - private long long_internal; - - /** - * initialize - */ - private static void initClass() { - System.err.println ("JSObject.initClass"); - } - - static { - System.err.println ("JSObject INITIALIZER"); - } - - /** - * it is illegal to construct a JSObject manually - */ - // FIXME: make private! - public JSObject(int jsobj_addr) { - System.err.println ("JSObject int CONSTRUCTOR"); - internal = jsobj_addr; - } - - private JSObject(long jsobj_addr) { - System.err.println ("JSObject long CONSTRUCTOR"); - long_internal = jsobj_addr; - } - - /** - * Retrieves a named member of a JavaScript object. - * Equivalent to "this.<i>name</i>" in JavaScript. - */ - public Object getMember(String name) - { - System.err.println ("JSObject.getMember " + name); - - Object o = PluginAppletViewer.getMember(internal, name); - System.out.println ("JSObject.getMember GOT " + o); - return o; - } - - - /** - * Retrieves an indexed member of a JavaScript object. - * Equivalent to "this[<i>index</i>]" in JavaScript. - */ - // public Object getMember(int index) { return getSlot(index); } - public Object getSlot(int index) - { - System.err.println ("JSObject.getSlot " + index); - - return PluginAppletViewer.getSlot(internal, index); - } - - - /** - * Sets a named member of a JavaScript object. - * Equivalent to "this.<i>name</i> = <i>value</i>" in JavaScript. - */ - public void setMember(String name, Object value) - { - System.err.println ("JSObject.setMember " + name + " " + value); - - PluginAppletViewer.setMember(internal, name, value); - } - - /** - * Sets an indexed member of a JavaScript object. - * Equivalent to "this[<i>index</i>] = <i>value</i>" in JavaScript. - */ - // public void setMember(int index, Object value) { - // setSlot(index, value); - // } - public void setSlot(int index, Object value) - { - System.err.println ("JSObject.setSlot " + index + " " + value); - - PluginAppletViewer.setSlot(internal, index, value); - } - - - // TODO: toString, finalize. - - /** - * Removes a named member of a JavaScript object. - */ - public void removeMember(String name) - { - System.err.println ("JSObject.removeMember " + name); - - PluginAppletViewer.removeMember(internal, name); - } - - - /** - * Calls a JavaScript method. - * Equivalent to "this.<i>methodName</i>(<i>args</i>[0], <i>args</i>[1], ...)" in JavaScript. - */ - public Object call(String methodName, Object args[]) - { - System.err.print ("JSObject.call " + methodName); - for (int i = 0; i < args.length; i++) - System.err.print (" " + args[i]); - System.err.println(""); - return PluginAppletViewer.call(internal, methodName, args); - } - - - /** - * Evaluates a JavaScript expression. The expression is a string - * of JavaScript source code which will be evaluated in the context - * given by "this". - */ - public Object eval(String s) - { - System.err.println("JSObject.eval " + s); - return PluginAppletViewer.eval(internal, s); - } - - - /** - * Converts a JSObject to a String. - */ - public String toString() - { - System.err.println("JSObject.toString"); - return PluginAppletViewer.javascriptToString(internal); - } - - - // should use some sort of identifier rather than String - // is "property" the right word? - // native String[] listProperties(); - - - /** - * get a JSObject for the window containing the given applet - */ - public static JSObject getWindow(Applet applet) - { - System.err.println("JSObject.getWindow"); - // FIXME: handle long case as well. - int internal = 0; - internal = ((PluginAppletViewer) - applet.getAppletContext()).getWindow(); - System.out.println ("GOT IT: " + internal); - return new JSObject(internal); - } - - - /** - * Finalization decrements the reference count on the corresponding - * JavaScript object. - */ - protected void finalize() - { - System.err.println("JSObject.finalize "); - PluginAppletViewer.JavaScriptFinalize(internal); - } - - - /** - * Override java.lang.Object.equals() because identity is not preserved - * with instances of JSObject. - */ - public boolean equals(Object obj) - { - System.err.println("JSObject.equals " + obj); - - return false; - } - -}
--- a/rt/netscape/javascript/JSProxy.java Mon Sep 22 10:39:01 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/** - * The JSProxy interface allows applets and plugins to - * share javascript contexts. - */ - -package netscape.javascript; -import java.applet.Applet; - -public interface JSProxy { - Object getMember(JSObject jso, String name); - Object getSlot(JSObject jso, int index); - void setMember(JSObject jso, String name, Object value); - void setSlot(JSObject jso, int index, Object value); - void removeMember(JSObject jso, String name); - Object call(JSObject jso, String methodName, Object args[]); - Object eval(JSObject jso, String s); - String toString(JSObject jso); - JSObject getWindow(Applet applet); -}
--- a/rt/netscape/javascript/JSRunnable.java Mon Sep 22 10:39:01 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -package netscape.javascript; - -/** - * Runs a JavaScript object with a run() method in a separate thread. - */ -public class JSRunnable implements Runnable { - private JSObject runnable; - - public JSRunnable(JSObject runnable) { - this.runnable = runnable; - synchronized(this) { - new Thread(this).start(); - try { - this.wait(); - } catch (InterruptedException ie) { - } - } - } - - public void run() { - try { - runnable.call("run", null); - synchronized(this) { - notifyAll(); - } - } catch (Throwable t) { - System.err.println(t); - t.printStackTrace(System.err); - } - } -}
--- a/rt/netscape/javascript/JSUtil.java Mon Sep 22 10:39:01 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* -*- Mode: Java; tab-width: 8; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -/* ** */ - -package netscape.javascript; -import java.io.*; - -public class JSUtil { - - /* Return the stack trace of an exception or error as a String */ - public static String getStackTrace(Throwable t) { - ByteArrayOutputStream captureStream; - PrintWriter p; - - captureStream = new ByteArrayOutputStream(); - p = new PrintWriter(captureStream); - - t.printStackTrace(p); - p.flush(); - - return captureStream.toString(); - } -}