Mercurial > hg > release > icedtea6-1.4.1
changeset 1048:5cf4df1bc010
- Refactor java-side of icedtea code for proper security management
- Remove most new files from iced tea plugin patch, and move it to a directory
line wrap: on
line diff
--- a/Makefile.am Sun Sep 21 15:58:46 2008 -0400 +++ b/Makefile.am Tue Sep 23 16:33:17 2008 -0400 @@ -16,11 +16,13 @@ ICEDTEAPLUGIN_TARGET = IcedTeaPlugin.so ICEDTEAPLUGIN_JAR = IcedTeaPlugin.jar PLUGIN_PATCH = patches/icedtea-liveconnect.patch +LIVECONNECT = $(abs_top_srcdir)/plugin/icedtea/java/src/main else ICEDTEAPLUGIN_CLEAN = ICEDTEAPLUGIN_TARGET = ICEDTEAPLUGIN_JAR = PLUGIN_PATCH = patches/icedtea-plugin.patch +LIVECONNECT = if ENABLE_PLUGIN GCJWEBPLUGIN_CLEAN = clean-gcjwebplugin GCJWEBPLUGIN_TARGET = gcjwebplugin.so @@ -578,7 +580,7 @@ else \ test x$${all_patches_ok} = "xyes" && all_patches_ok=$$p ; \ fi ; \ - done ; + done ; \ mv stamps/patch.stamp.tmp stamps/patch.stamp ; \ if ! test x$${all_patches_ok} = "xyes"; then \ echo ERROR patch $${all_patches_ok} FAILED! ; \ @@ -909,12 +911,6 @@ $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/ cp -pPRf IcedTeaPlugin.jar \ $(BUILD_OUTPUT_DIR)/j2re-image/lib/ - - $(JAR) uf $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/rt.jar \ - -C $(BUILD_OUTPUT_DIR)/plugin/icedtea/classes sun - - $(JAR) uf $(BUILD_OUTPUT_DIR)/j2re-image/lib/rt.jar \ - -C $(BUILD_OUTPUT_DIR)/plugin/icedtea/classes sun else if ENABLE_PLUGIN cp -pPRf gcjwebplugin.so \ @@ -970,12 +966,6 @@ $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib/ cp -pPRf IcedTeaPlugin.jar \ $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/ - - $(JAR) uf $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib/rt.jar \ - -C $(BUILD_OUTPUT_DIR)/plugin/icedtea/classes sun - - $(JAR) uf $(BUILD_OUTPUT_DIR)/j2re-image/lib/rt.jar \ - -C $(BUILD_OUTPUT_DIR)/plugin/icedtea/classes sun else if ENABLE_PLUGIN cp -pPRf gcjwebplugin.so \ @@ -1207,8 +1197,8 @@ # 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' \ + $(EXCLUDE_LIVECONNECT) \ | sort -u > $@ stamps/rt-class-files.stamp: rt-source-files.txt @@ -1337,7 +1327,7 @@ $(ICEDTEA_BOOT_DIR)/bin/javac -g \ -d ../../../../../$(BUILD_OUTPUT_DIR)/plugin/icedtea/classes \ -bootclasspath $(ICEDTEA_BOOT_DIR)/jre/lib/rt.jar \ - sun/applet/*.java netscape/javascript/*.java org/classpath/icedtea/plugin/*.java \ + netscape/javascript/*.java org/classpath/icedtea/plugin/*.java \ ) $(JAR) cf $@ \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/netscape/javascript/JSException.java Tue Sep 23 16:33:17 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/java/src/main/netscape/javascript/JSObject.java Tue Sep 23 16:33:17 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/java/src/main/netscape/javascript/JSProxy.java Tue Sep 23 16:33:17 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/java/src/main/netscape/javascript/JSRunnable.java Tue Sep 23 16:33:17 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/java/src/main/netscape/javascript/JSUtil.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/GetMemberPluginCallRequest.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/GetWindowPluginCallRequest.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/PluginAppletSecurityContext.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/PluginCallRequestFactoryImpl.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/PluginMain.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/PluginMessageConsumer.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/PluginMessageHandlerWorker.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/PluginObjectStore.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/PluginStreamHandlerImpl.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/RequestQueue.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/TestEnv.java Tue Sep 23 16:33:17 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/java/src/main/org/classpath/icedtea/plugin/VoidPluginCallRequest.java Tue Sep 23 16:33:17 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/java/src/main/sun/applet/AppletAudioClip.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,151 @@ +/* + * Copyright 1995-2003 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.IOException; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.net.URL; +import java.net.URLConnection; +import java.applet.AudioClip; + +import com.sun.media.sound.JavaSoundAudioClip; + + +/** + * Applet audio clip; + * + * @author Arthur van Hoff, Kara Kytle + */ + +public class AppletAudioClip implements AudioClip { + + // url that this AudioClip is based on + private URL url = null; + + // the audio clip implementation + private AudioClip audioClip = null; + + boolean DEBUG = false /*true*/; + + /** + * Constructs an AppletAudioClip from an URL. + */ + public AppletAudioClip(URL url) { + + // store the url + this.url = url; + + try { + // create a stream from the url, and use it + // in the clip. + InputStream in = url.openStream(); + createAppletAudioClip(in); + + } catch (IOException e) { + /* just quell it */ + if (DEBUG) { + System.err.println("IOException creating AppletAudioClip" + e); + } + } + } + + /** + * Constructs an AppletAudioClip from a URLConnection. + */ + public AppletAudioClip(URLConnection uc) { + + try { + // create a stream from the url, and use it + // in the clip. + createAppletAudioClip(uc.getInputStream()); + + } catch (IOException e) { + /* just quell it */ + if (DEBUG) { + System.err.println("IOException creating AppletAudioClip" + e); + } + } + } + + + /** + * For constructing directly from Jar entries, or any other + * raw Audio data. Note that the data provided must include the format + * header. + */ + public AppletAudioClip(byte [] data) { + + try { + + // construct a stream from the byte array + InputStream in = new ByteArrayInputStream(data); + + createAppletAudioClip(in); + + } catch (IOException e) { + /* just quell it */ + if (DEBUG) { + System.err.println("IOException creating AppletAudioClip " + e); + } + } + } + + + /* + * Does the real work of creating an AppletAudioClip from an InputStream. + * This function is used by both constructors. + */ + void createAppletAudioClip(InputStream in) throws IOException { + + try { + audioClip = new JavaSoundAudioClip(in); + } catch (Exception e3) { + // no matter what happened, we throw an IOException to avoid changing the interfaces.... + throw new IOException("Failed to construct the AudioClip: " + e3); + } + } + + + public synchronized void play() { + + if (audioClip != null) + audioClip.play(); + } + + + public synchronized void loop() { + + if (audioClip != null) + audioClip.loop(); + } + + public synchronized void stop() { + + if (audioClip != null) + audioClip.stop(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletClassLoader.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,861 @@ +/* + * Copyright 1995-2005 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.lang.NullPointerException; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.SocketPermission; +import java.net.URLConnection; +import java.net.MalformedURLException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.io.File; +import java.io.FilePermission; +import java.io.IOException; +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.NoSuchElementException; +import java.security.AccessController; +import java.security.AccessControlContext; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import sun.awt.AppContext; +import sun.awt.SunToolkit; +import sun.net.www.ParseUtil; +import sun.security.util.SecurityConstants; + +/** + * This class defines the class loader for loading applet classes and + * resources. It extends URLClassLoader to search the applet code base + * for the class or resource after checking any loaded JAR files. + */ +public class AppletClassLoader extends URLClassLoader { + private URL base; /* applet code base URL */ + private CodeSource codesource; /* codesource for the base URL */ + private AccessControlContext acc; + private boolean exceptionStatus = false; + + private final Object threadGroupSynchronizer = new Object(); + private final Object grabReleaseSynchronizer = new Object(); + + private boolean codebaseLookup = true; + + /* + * Creates a new AppletClassLoader for the specified base URL. + */ + protected AppletClassLoader(URL base) { + super(new URL[0]); + this.base = base; + this.codesource = + new CodeSource(base, (java.security.cert.Certificate[]) null); + acc = AccessController.getContext(); + } + + /** + * Set the codebase lookup flag. + */ + void setCodebaseLookup(boolean codebaseLookup) { + this.codebaseLookup = codebaseLookup; + } + + /* + * Returns the applet code base URL. + */ + URL getBaseURL() { + return base; + } + + /* + * Returns the URLs used for loading classes and resources. + */ + public URL[] getURLs() { + URL[] jars = super.getURLs(); + URL[] urls = new URL[jars.length + 1]; + System.arraycopy(jars, 0, urls, 0, jars.length); + urls[urls.length - 1] = base; + return urls; + } + + /* + * Adds the specified JAR file to the search path of loaded JAR files. + * Changed modifier to protected in order to be able to overwrite addJar() + * in PluginClassLoader.java + */ + protected void addJar(String name) throws IOException { + URL url; + try { + url = new URL(base, name); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("name"); + } + addURL(url); + // DEBUG + //URL[] urls = getURLs(); + //for (int i = 0; i < urls.length; i++) { + // System.out.println("url[" + i + "] = " + urls[i]); + //} + } + + /* + * Override loadClass so that class loading errors can be caught in + * order to print better error messages. + */ + public synchronized Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + // First check if we have permission to access the package. This + // should go away once we've added support for exported packages. + int i = name.lastIndexOf('.'); + if (i != -1) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPackageAccess(name.substring(0, i)); + } + try { + return super.loadClass(name, resolve); + } catch (ClassNotFoundException e) { + //printError(name, e.getException()); + throw e; + } catch (RuntimeException e) { + //printError(name, e); + throw e; + } catch (Error e) { + //printError(name, e); + throw e; + } + } + + /* + * Finds the applet class with the specified name. First searches + * loaded JAR files then the applet code base for the class. + */ + protected Class findClass(String name) throws ClassNotFoundException { + + int index = name.indexOf(";"); + String cookie = ""; + if(index != -1) { + cookie = name.substring(index, name.length()); + name = name.substring(0, index); + } + + // check loaded JAR files + try { + return super.findClass(name); + } catch (ClassNotFoundException e) { + } + + // Otherwise, try loading the class from the code base URL + + // 4668479: Option to turn off codebase lookup in AppletClassLoader + // during resource requests. [stanley.ho] + if (codebaseLookup == false) + throw new ClassNotFoundException(name); + +// final String path = name.replace('.', '/').concat(".class").concat(cookie); + String encodedName = ParseUtil.encodePath(name.replace('.', '/'), false); + final String path = (new StringBuffer(encodedName)).append(".class").append(cookie).toString(); + try { + byte[] b = (byte[]) AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Object run() throws IOException { + return getBytes(new URL(base, path)); + } + }, acc); + + if (b != null) { + return defineClass(name, b, 0, b.length, codesource); + } else { + throw new ClassNotFoundException(name); + } + } catch (PrivilegedActionException e) { + throw new ClassNotFoundException(name, e.getException()); + } + } + + /** + * Returns the permissions for the given codesource object. + * The implementation of this method first calls super.getPermissions, + * to get the permissions + * granted by the super class, and then adds additional permissions + * based on the URL of the codesource. + * <p> + * If the protocol is "file" + * and the path specifies a file, permission is granted to read all files + * and (recursively) all files and subdirectories contained in + * that directory. This is so applets with a codebase of + * file:/blah/some.jar can read in file:/blah/, which is needed to + * be backward compatible. We also add permission to connect back to + * the "localhost". + * + * @param codesource the codesource + * @return the permissions granted to the codesource + */ + protected PermissionCollection getPermissions(CodeSource codesource) + { + final PermissionCollection perms = super.getPermissions(codesource); + + URL url = codesource.getLocation(); + + String path = null; + Permission p; + + try { + p = url.openConnection().getPermission(); + } catch (java.io.IOException ioe) { + p = null; + } + + if (p instanceof FilePermission) { + path = p.getName(); + } else if ((p == null) && (url.getProtocol().equals("file"))) { + path = url.getFile().replace('/', File.separatorChar); + path = ParseUtil.decode(path); + } + + if (path != null) { + if (!path.endsWith(File.separator)) { + int endIndex = path.lastIndexOf(File.separatorChar); + if (endIndex != -1) { + path = path.substring(0, endIndex+1) + "-"; + perms.add(new FilePermission(path, + SecurityConstants.FILE_READ_ACTION)); + } + } + perms.add(new SocketPermission("localhost", + SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + String host = InetAddress.getLocalHost().getHostName(); + perms.add(new SocketPermission(host, + SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); + } catch (UnknownHostException uhe) { + + } + return null; + } + }); + + Permission bperm; + try { + bperm = base.openConnection().getPermission(); + } catch (java.io.IOException ioe) { + bperm = null; + } + if (bperm instanceof FilePermission) { + String bpath = bperm.getName(); + if (bpath.endsWith(File.separator)) { + bpath += "-"; + } + perms.add(new FilePermission(bpath, + SecurityConstants.FILE_READ_ACTION)); + } else if ((bperm == null) && (base.getProtocol().equals("file"))) { + String bpath = base.getFile().replace('/', File.separatorChar); + bpath = ParseUtil.decode(bpath); + if (bpath.endsWith(File.separator)) { + bpath += "-"; + } + perms.add(new FilePermission(bpath, SecurityConstants.FILE_READ_ACTION)); + } + + } + return perms; + } + + /* + * Returns the contents of the specified URL as an array of bytes. + */ + private static byte[] getBytes(URL url) throws IOException { + URLConnection uc = url.openConnection(); + if (uc instanceof java.net.HttpURLConnection) { + java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc; + int code = huc.getResponseCode(); + if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) { + throw new IOException("open HTTP connection failed."); + } + } + int len = uc.getContentLength(); + + // Fixed #4507227: Slow performance to load + // class and resources. [stanleyh] + // + // Use buffered input stream [stanleyh] + InputStream in = new BufferedInputStream(uc.getInputStream()); + + byte[] b; + try { + if (len != -1) { + // Read exactly len bytes from the input stream + b = new byte[len]; + while (len > 0) { + int n = in.read(b, b.length - len, len); + if (n == -1) { + throw new IOException("unexpected EOF"); + } + len -= n; + } + } else { + // Read until end of stream is reached - use 8K buffer + // to speed up performance [stanleyh] + b = new byte[8192]; + int total = 0; + while ((len = in.read(b, total, b.length - total)) != -1) { + total += len; + if (total >= b.length) { + byte[] tmp = new byte[total * 2]; + System.arraycopy(b, 0, tmp, 0, total); + b = tmp; + } + } + // Trim array to correct size, if necessary + if (total != b.length) { + byte[] tmp = new byte[total]; + System.arraycopy(b, 0, tmp, 0, total); + b = tmp; + } + } + } finally { + in.close(); + } + return b; + } + + // Object for synchronization around getResourceAsStream() + private Object syncResourceAsStream = new Object(); + private Object syncResourceAsStreamFromJar = new Object(); + + // Flag to indicate getResourceAsStream() is in call + private boolean resourceAsStreamInCall = false; + private boolean resourceAsStreamFromJarInCall = false; + + /** + * Returns an input stream for reading the specified resource. + * + * The search order is described in the documentation for {@link + * #getResource(String)}.<p> + * + * @param name the resource name + * @return an input stream for reading the resource, or <code>null</code> + * if the resource could not be found + * @since JDK1.1 + */ + public InputStream getResourceAsStream(String name) + { + + if (name == null) { + throw new NullPointerException("name"); + } + + try + { + InputStream is = null; + + // Fixed #4507227: Slow performance to load + // class and resources. [stanleyh] + // + // The following is used to avoid calling + // AppletClassLoader.findResource() in + // super.getResourceAsStream(). Otherwise, + // unnecessary connection will be made. + // + synchronized(syncResourceAsStream) + { + resourceAsStreamInCall = true; + + // Call super class + is = super.getResourceAsStream(name); + + resourceAsStreamInCall = false; + } + + // 4668479: Option to turn off codebase lookup in AppletClassLoader + // during resource requests. [stanley.ho] + if (codebaseLookup == true && is == null) + { + // If resource cannot be obtained, + // try to download it from codebase + URL url = new URL(base, ParseUtil.encodePath(name, false)); + is = url.openStream(); + } + + return is; + } + catch (Exception e) + { + return null; + } + } + + + /** + * Returns an input stream for reading the specified resource from the + * the loaded jar files. + * + * The search order is described in the documentation for {@link + * #getResource(String)}.<p> + * + * @param name the resource name + * @return an input stream for reading the resource, or <code>null</code> + * if the resource could not be found + * @since JDK1.1 + */ + public InputStream getResourceAsStreamFromJar(String name) { + + if (name == null) { + throw new NullPointerException("name"); + } + + try { + InputStream is = null; + synchronized(syncResourceAsStreamFromJar) { + resourceAsStreamFromJarInCall = true; + // Call super class + is = super.getResourceAsStream(name); + resourceAsStreamFromJarInCall = false; + } + + return is; + } catch (Exception e) { + return null; + } + } + + + /* + * Finds the applet resource with the specified name. First checks + * loaded JAR files then the applet code base for the resource. + */ + public URL findResource(String name) { + // check loaded JAR files + URL url = super.findResource(name); + + // 6215746: Disable META-INF/* lookup from codebase in + // applet/plugin classloader. [stanley.ho] + if (name.startsWith("META-INF/")) + return url; + + // 4668479: Option to turn off codebase lookup in AppletClassLoader + // during resource requests. [stanley.ho] + if (codebaseLookup == false) + return url; + + if (url == null) + { + //#4805170, if it is a call from Applet.getImage() + //we should check for the image only in the archives + boolean insideGetResourceAsStreamFromJar = false; + synchronized(syncResourceAsStreamFromJar) { + insideGetResourceAsStreamFromJar = resourceAsStreamFromJarInCall; + } + + if (insideGetResourceAsStreamFromJar) { + return null; + } + + // Fixed #4507227: Slow performance to load + // class and resources. [stanleyh] + // + // Check if getResourceAsStream is called. + // + boolean insideGetResourceAsStream = false; + + synchronized(syncResourceAsStream) + { + insideGetResourceAsStream = resourceAsStreamInCall; + } + + // If getResourceAsStream is called, don't + // trigger the following code. Otherwise, + // unnecessary connection will be made. + // + if (insideGetResourceAsStream == false) + { + // otherwise, try the code base + try { + url = new URL(base, ParseUtil.encodePath(name, false)); + // check if resource exists + if(!resourceExists(url)) + url = null; + } catch (Exception e) { + // all exceptions, including security exceptions, are caught + url = null; + } + } + } + return url; + } + + + private boolean resourceExists(URL url) { + // Check if the resource exists. + // It almost works to just try to do an openConnection() but + // HttpURLConnection will return true on HTTP_BAD_REQUEST + // when the requested name ends in ".html", ".htm", and ".txt" + // and we want to be able to handle these + // + // Also, cannot just open a connection for things like FileURLConnection, + // because they succeed when connecting to a nonexistent file. + // So, in those cases we open and close an input stream. + boolean ok = true; + try { + URLConnection conn = url.openConnection(); + if (conn instanceof java.net.HttpURLConnection) { + java.net.HttpURLConnection hconn = + (java.net.HttpURLConnection) conn; + + // To reduce overhead, using http HEAD method instead of GET method + hconn.setRequestMethod("HEAD"); + + int code = hconn.getResponseCode(); + if (code == java.net.HttpURLConnection.HTTP_OK) { + return true; + } + if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) { + return false; + } + } else { + /** + * Fix for #4182052 - stanleyh + * + * The same connection should be reused to avoid multiple + * HTTP connections + */ + + // our best guess for the other cases + InputStream is = conn.getInputStream(); + is.close(); + } + } catch (Exception ex) { + ok = false; + } + return ok; + } + + /* + * Returns an enumeration of all the applet resources with the specified + * name. First checks loaded JAR files then the applet code base for all + * available resources. + */ + public Enumeration findResources(String name) throws IOException { + + final Enumeration e = super.findResources(name); + + // 6215746: Disable META-INF/* lookup from codebase in + // applet/plugin classloader. [stanley.ho] + if (name.startsWith("META-INF/")) + return e; + + // 4668479: Option to turn off codebase lookup in AppletClassLoader + // during resource requests. [stanley.ho] + if (codebaseLookup == false) + return e; + + URL u = new URL(base, ParseUtil.encodePath(name, false)); + if (!resourceExists(u)) { + u = null; + } + + final URL url = u; + return new Enumeration() { + private boolean done; + public Object nextElement() { + if (!done) { + if (e.hasMoreElements()) { + return e.nextElement(); + } + done = true; + if (url != null) { + return url; + } + } + throw new NoSuchElementException(); + } + public boolean hasMoreElements() { + return !done && (e.hasMoreElements() || url != null); + } + }; + } + + /* + * Load and resolve the file specified by the applet tag CODE + * attribute. The argument can either be the relative path + * of the class file itself or just the name of the class. + */ + Class loadCode(String name) throws ClassNotFoundException { + // first convert any '/' or native file separator to . + name = name.replace('/', '.'); + name = name.replace(File.separatorChar, '.'); + + // deal with URL rewriting + String cookie = null; + int index = name.indexOf(";"); + if(index != -1) { + cookie = name.substring(index, name.length()); + name = name.substring(0, index); + } + + // save that name for later + String fullName = name; + // then strip off any suffixes + if (name.endsWith(".class") || name.endsWith(".java")) { + name = name.substring(0, name.lastIndexOf('.')); + } + try { + if(cookie != null) + name = (new StringBuffer(name)).append(cookie).toString(); + return loadClass(name); + } catch (ClassNotFoundException e) { + } + // then if it didn't end with .java or .class, or in the + // really pathological case of a class named class or java + if(cookie != null) + fullName = (new StringBuffer(fullName)).append(cookie).toString(); + + return loadClass(fullName); + } + + /* + * The threadgroup that the applets loaded by this classloader live + * in. In the sun.* implementation of applets, the security manager's + * (AppletSecurity) getThreadGroup returns the thread group of the + * first applet on the stack, which is the applet's thread group. + */ + private AppletThreadGroup threadGroup; + private AppContext appContext; + + public ThreadGroup getThreadGroup() { + synchronized (threadGroupSynchronizer) { + if (threadGroup == null || threadGroup.isDestroyed()) { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + threadGroup = new AppletThreadGroup(base + "-threadGroup"); + // threadGroup.setDaemon(true); + // threadGroup is now destroyed by AppContext.dispose() + + // Create the new AppContext from within a Thread belonging + // to the newly created ThreadGroup, and wait for the + // creation to complete before returning from this method. + AppContextCreator creatorThread = new AppContextCreator(threadGroup); + + // Since this thread will later be used to launch the + // applet's AWT-event dispatch thread and we want the applet + // code executing the AWT callbacks to use their own class + // loader rather than the system class loader, explicitly + // set the context class loader to the AppletClassLoader. + creatorThread.setContextClassLoader(AppletClassLoader.this); + + synchronized(creatorThread.syncObject) { + creatorThread.start(); + try { + creatorThread.syncObject.wait(); + } catch (InterruptedException e) { } + appContext = creatorThread.appContext; + } + return null; + } + }); + } + return threadGroup; + } + } + + /* + * Get the AppContext, if any, corresponding to this AppletClassLoader. + */ + public AppContext getAppContext() { + return appContext; + } + + int usageCount = 0; + + /** + * Grab this AppletClassLoader and its ThreadGroup/AppContext, so they + * won't be destroyed. + */ + void grab() { + synchronized(grabReleaseSynchronizer) { + usageCount++; + } + getThreadGroup(); // Make sure ThreadGroup/AppContext exist + } + + protected void setExceptionStatus() + { + exceptionStatus = true; + } + + public boolean getExceptionStatus() + { + return exceptionStatus; + } + + /** + * Release this AppletClassLoader and its ThreadGroup/AppContext. + * If nothing else has grabbed this AppletClassLoader, its ThreadGroup + * and AppContext will be destroyed. + * + * Because this method may destroy the AppletClassLoader's ThreadGroup, + * this method should NOT be called from within the AppletClassLoader's + * ThreadGroup. + * + * Changed modifier to protected in order to be able to overwrite this + * function in PluginClassLoader.java + */ + protected void release() { + + AppContext tempAppContext = null; + + synchronized(grabReleaseSynchronizer) { + if (usageCount > 1) { + --usageCount; + } else { + synchronized(threadGroupSynchronizer) { + // Store app context in temp variable + tempAppContext = appContext; + usageCount = 0; + appContext = null; + threadGroup = null; + } + } + } + + // Dispose appContext outside any sync block to + // prevent potential deadlock. + if (tempAppContext != null) { + try { + tempAppContext.dispose(); // nuke the world! + } catch (IllegalThreadStateException e) { } + } + } + + // Hash map to store applet compatibility info + private HashMap jdk11AppletInfo = new HashMap(); + private HashMap jdk12AppletInfo = new HashMap(); + + /** + * Set applet target level as JDK 1.1. + * + * @param clazz Applet class. + * @param bool true if JDK is targeted for JDK 1.1; + * false otherwise. + */ + void setJDK11Target(Class clazz, boolean bool) + { + jdk11AppletInfo.put(clazz.toString(), Boolean.valueOf(bool)); + } + + /** + * Set applet target level as JDK 1.2. + * + * @param clazz Applet class. + * @param bool true if JDK is targeted for JDK 1.2; + * false otherwise. + */ + void setJDK12Target(Class clazz, boolean bool) + { + jdk12AppletInfo.put(clazz.toString(), Boolean.valueOf(bool)); + } + + /** + * Determine if applet is targeted for JDK 1.1. + * + * @param applet Applet class. + * @return TRUE if applet is targeted for JDK 1.1; + * FALSE if applet is not; + * null if applet is unknown. + */ + Boolean isJDK11Target(Class clazz) + { + return (Boolean) jdk11AppletInfo.get(clazz.toString()); + } + + /** + * Determine if applet is targeted for JDK 1.2. + * + * @param applet Applet class. + * @return TRUE if applet is targeted for JDK 1.2; + * FALSE if applet is not; + * null if applet is unknown. + */ + Boolean isJDK12Target(Class clazz) + { + return (Boolean) jdk12AppletInfo.get(clazz.toString()); + } + + private static AppletMessageHandler mh = + new AppletMessageHandler("appletclassloader"); + + /* + * Prints a class loading error message. + */ + private static void printError(String name, Throwable e) { + String s = null; + if (e == null) { + s = mh.getMessage("filenotfound", name); + } else if (e instanceof IOException) { + s = mh.getMessage("fileioexception", name); + } else if (e instanceof ClassFormatError) { + s = mh.getMessage("fileformat", name); + } else if (e instanceof ThreadDeath) { + s = mh.getMessage("filedeath", name); + } else if (e instanceof Error) { + s = mh.getMessage("fileerror", e.toString(), name); + } + if (s != null) { + System.err.println(s); + } + } +} + +/* + * The AppContextCreator class is used to create an AppContext from within + * a Thread belonging to the new AppContext's ThreadGroup. To wait for + * this operation to complete before continuing, wait for the notifyAll() + * operation on the syncObject to occur. + */ +class AppContextCreator extends Thread { + Object syncObject = new Object(); + AppContext appContext = null; + + AppContextCreator(ThreadGroup group) { + super(group, "AppContextCreator"); + } + + public void run() { + synchronized(syncObject) { + appContext = SunToolkit.createNewAppContext(); + syncObject.notifyAll(); + } + } // run() + +} // class AppContextCreator
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletEvent.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,65 @@ +/* + * Copyright 1997 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.EventObject; + + +/** + * AppletEvent class. + * + * @author Sunita Mani + */ + +public class AppletEvent extends EventObject { + + private Object arg; + private int id; + + + public AppletEvent(Object source, int id, Object argument) { + super(source); + this.arg = argument; + this.id = id; + } + + public int getID() { + return id; + } + + public Object getArgument() { + return arg; + } + + public String toString() { + String str = getClass().getName() + "[source=" + source + " + id="+ id; + if (arg != null) { + str += " + arg=" + arg; + } + str += " ]"; + return str; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletEventMulticaster.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,127 @@ +/* + * Copyright 1997 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.EventListener; +import java.io.Serializable; +import java.io.ObjectOutputStream; +import java.io.IOException; + +/** + * AppletEventMulticaster class. This class manages an immutable + * structure consisting of a chain of AppletListeners and is + * responsible for dispatching events to them. + * + * @author Sunita Mani + */ +public class AppletEventMulticaster implements AppletListener { + + private final AppletListener a, b; + + public AppletEventMulticaster(AppletListener a, AppletListener b) { + this.a = a; this.b = b; + } + + public void appletStateChanged(AppletEvent e) { + a.appletStateChanged(e); + b.appletStateChanged(e); + } + + /** + * Adds Applet-listener-a with Applet-listener-b and + * returns the resulting multicast listener. + * @param a Applet-listener-a + * @param b Applet-listener-b + */ + public static AppletListener add(AppletListener a, AppletListener b) { + return addInternal(a, b); + } + + /** + * Removes the old Applet-listener from Applet-listener-l and + * returns the resulting multicast listener. + * @param l Applet-listener-l + * @param oldl the Applet-listener being removed + */ + public static AppletListener remove(AppletListener l, AppletListener oldl) { + return removeInternal(l, oldl); + } + + /** + * Returns the resulting multicast listener from adding listener-a + * and listener-b together. + * If listener-a is null, it returns listener-b; + * If listener-b is null, it returns listener-a + * If neither are null, then it creates and returns + * a new AppletEventMulticaster instance which chains a with b. + * @param a event listener-a + * @param b event listener-b + */ + private static AppletListener addInternal(AppletListener a, AppletListener b) { + if (a == null) return b; + if (b == null) return a; + return new AppletEventMulticaster(a, b); + } + + + /** + * Removes a listener from this multicaster and returns the + * resulting multicast listener. + * @param oldl the listener to be removed + */ + protected AppletListener remove(AppletListener oldl) { + if (oldl == a) return b; + if (oldl == b) return a; + AppletListener a2 = removeInternal(a, oldl); + AppletListener b2 = removeInternal(b, oldl); + if (a2 == a && b2 == b) { + return this; // it's not here + } + return addInternal(a2, b2); + } + + + /** + * Returns the resulting multicast listener after removing the + * old listener from listener-l. + * If listener-l equals the old listener OR listener-l is null, + * returns null. + * Else if listener-l is an instance of AppletEventMulticaster + * then it removes the old listener from it. + * Else, returns listener l. + * @param l the listener being removed from + * @param oldl the listener being removed + */ + private static AppletListener removeInternal(AppletListener l, AppletListener oldl) { + if (l == oldl || l == null) { + return null; + } else if (l instanceof AppletEventMulticaster) { + return ((AppletEventMulticaster)l).remove(oldl); + } else { + return l; // it's not here + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletIOException.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,59 @@ +/* + * Copyright 1996 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.IOException; + +/** + * An applet IO exception. + * + * @author Koji Uno + */ +public +class AppletIOException extends IOException { + private String key = null; + private Object msgobj = null; + + public AppletIOException(String key) { + super(key); + this.key = key; + + } + public AppletIOException(String key, Object arg) { + this(key); + msgobj = arg; + } + + public String getLocalizedMessage() { + if( msgobj != null) + return amh.getMessage(key, msgobj); + else + return amh.getMessage(key); + } + + private static AppletMessageHandler amh = new AppletMessageHandler("appletioexception"); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletIllegalArgumentException.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,48 @@ +/* + * Copyright 1996 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; + +/** + * An applet security exception. + * + * @author Arthur van Hoff + */ +public +class AppletIllegalArgumentException extends IllegalArgumentException { + private String key = null; + + public AppletIllegalArgumentException(String key) { + super(key); + this.key = key; + + } + + public String getLocalizedMessage() { + return amh.getMessage(key); + } + + private static AppletMessageHandler amh = new AppletMessageHandler("appletillegalargumentexception"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletImageRef.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,54 @@ +/* + * Copyright 1996 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.awt.Toolkit; +import java.awt.Image; +import sun.awt.image.URLImageSource; +import java.net.URL; + +class AppletImageRef extends sun.misc.Ref { + URL url; + + /** + * Create the Ref + */ + AppletImageRef(URL url) { + this.url = url; + } + + public void flush() { + super.flush(); + } + + /** + * Reconsitute the image. Only called when the ref has been flushed. + */ + public Object reconstitute() { + Image img = Toolkit.getDefaultToolkit().createImage(new URLImageSource(url)); + return img; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletListener.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,39 @@ +/* + * Copyright 1997 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.EventListener; + +/** + * Applet Listener interface. This interface is to be implemented + * by objects interested in AppletEvents. + * + * @author Sunita Mani + */ + +public interface AppletListener extends EventListener { + public void appletStateChanged(AppletEvent e); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletMessageHandler.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,113 @@ +/* + * Copyright 1996-1997 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.ResourceBundle; +import java.util.MissingResourceException; +import java.text.MessageFormat; + +/** + * An hanlder of localized messages. + * + * @author Koji Uno + */ +class AppletMessageHandler { + private static ResourceBundle rb; + private String baseKey = null; + + static { + try { + rb = ResourceBundle.getBundle + ("sun.applet.resources.MsgAppletViewer"); + } catch (MissingResourceException e) { + System.out.println(e.getMessage()); + System.exit(1); + } + } + + AppletMessageHandler(String baseKey) { + this.baseKey = baseKey; + } + + String getMessage(String key) { + return (String)rb.getString(getQualifiedKey(key)); + } + + String getMessage(String key, Object arg){ + String basemsgfmt = (String)rb.getString(getQualifiedKey(key)); + MessageFormat msgfmt = new MessageFormat(basemsgfmt); + Object msgobj[] = new Object[1]; + if (arg == null) { + arg = "null"; // mimic java.io.PrintStream.print(String) + } + msgobj[0] = arg; + return msgfmt.format(msgobj); + } + + String getMessage(String key, Object arg1, Object arg2) { + String basemsgfmt = (String)rb.getString(getQualifiedKey(key)); + MessageFormat msgfmt = new MessageFormat(basemsgfmt); + Object msgobj[] = new Object[2]; + if (arg1 == null) { + arg1 = "null"; + } + if (arg2 == null) { + arg2 = "null"; + } + msgobj[0] = arg1; + msgobj[1] = arg2; + return msgfmt.format(msgobj); + } + + String getMessage(String key, Object arg1, Object arg2, Object arg3) { + String basemsgfmt = (String)rb.getString(getQualifiedKey(key)); + MessageFormat msgfmt = new MessageFormat(basemsgfmt); + Object msgobj[] = new Object[3]; + if (arg1 == null) { + arg1 = "null"; + } + if (arg2 == null) { + arg2 = "null"; + } + if (arg3 == null) { + arg3 = "null"; + } + msgobj[0] = arg1; + msgobj[1] = arg2; + msgobj[2] = arg3; + return msgfmt.format(msgobj); + } + + String getMessage(String key, Object arg[]) { + String basemsgfmt = (String)rb.getString(getQualifiedKey(key)); + MessageFormat msgfmt = new MessageFormat(basemsgfmt); + return msgfmt.format(arg); + } + + String getQualifiedKey(String subKey) { + return baseKey + "." + subKey; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletObjectInputStream.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,106 @@ +/* + * Copyright 1996-1997 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. + */ +/* + * COPYRIGHT goes here + */ + +package sun.applet; + +import java.io.*; +import java.lang.reflect.Array; + +/** + * This subclass of ObjectInputStream delegates loading of classes to + * an existing ClassLoader. + */ + +class AppletObjectInputStream extends ObjectInputStream +{ + private AppletClassLoader loader; + + /** + * Loader must be non-null; + */ + + public AppletObjectInputStream(InputStream in, AppletClassLoader loader) + throws IOException, StreamCorruptedException { + + super(in); + if (loader == null) { + throw new AppletIllegalArgumentException("appletillegalargumentexception.objectinputstream"); + + } + this.loader = loader; + } + + /** + * Make a primitive array class + */ + + private Class primitiveType(char type) { + switch (type) { + case 'B': return byte.class; + case 'C': return char.class; + case 'D': return double.class; + case 'F': return float.class; + case 'I': return int.class; + case 'J': return long.class; + case 'S': return short.class; + case 'Z': return boolean.class; + default: return null; + } + } + + /** + * Use the given ClassLoader rather than using the system class + */ + protected Class resolveClass(ObjectStreamClass classDesc) + throws IOException, ClassNotFoundException { + + String cname = classDesc.getName(); + if (cname.startsWith("[")) { + // An array + Class component; // component class + int dcount; // dimension + for (dcount=1; cname.charAt(dcount)=='['; dcount++) ; + if (cname.charAt(dcount) == 'L') { + component = loader.loadClass(cname.substring(dcount+1, + cname.length()-1)); + } else { + if (cname.length() != dcount+1) { + throw new ClassNotFoundException(cname);// malformed + } + component = primitiveType(cname.charAt(dcount)); + } + int dim[] = new int[dcount]; + for (int i=0; i<dcount; i++) { + dim[i]=0; + } + return Array.newInstance(component, dim).getClass(); + } else { + return loader.loadClass(cname); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletPanel.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,1334 @@ +/* + * Copyright 1995-2007 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.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.ColorModel; +import java.awt.image.MemoryImageSource; +import java.io.*; +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.JarURLConnection; +import java.net.MalformedURLException; +import java.net.SocketPermission; +import java.net.URL; +import java.net.UnknownHostException; +import java.security.*; +import java.util.*; +import javax.swing.SwingUtilities; +import sun.awt.AppContext; +import sun.awt.EmbeddedFrame; +import sun.awt.SunToolkit; +import sun.misc.MessageUtils; +import sun.misc.PerformanceLogger; +import sun.misc.Queue; +import sun.security.util.SecurityConstants; + +/** + * Applet panel class. The panel manages and manipulates the + * applet as it is being loaded. It forks a separate thread in a new + * thread group to call the applet's init(), start(), stop(), and + * destroy() methods. + * + * @author Arthur van Hoff + */ +public +abstract class AppletPanel extends Panel implements AppletStub, Runnable { + + /** + * The applet (if loaded). + */ + protected Applet applet; + + /** + * Applet will allow initialization. Should be + * set to false if loading a serialized applet + * that was pickled in the init=true state. + */ + protected boolean doInit = true; + + + /** + * The classloader for the applet. + */ + AppletClassLoader loader; + + /* applet event ids */ + public final static int APPLET_DISPOSE = 0; + public final static int APPLET_LOAD = 1; + public final static int APPLET_INIT = 2; + public final static int APPLET_START = 3; + public final static int APPLET_STOP = 4; + public final static int APPLET_DESTROY = 5; + public final static int APPLET_QUIT = 6; + public final static int APPLET_ERROR = 7; + + /* send to the parent to force relayout */ + public final static int APPLET_RESIZE = 51234; + + /* sent to a (distant) parent to indicate that the applet is being + * loaded or as completed loading + */ + public final static int APPLET_LOADING = 51235; + public final static int APPLET_LOADING_COMPLETED = 51236; + + /** + * The current status. One of: + * APPLET_DISPOSE, + * APPLET_LOAD, + * APPLET_INIT, + * APPLET_START, + * APPLET_STOP, + * APPLET_DESTROY, + * APPLET_ERROR. + */ + protected int status; + + /** + * The thread for the applet. + */ + protected Thread handler; + + + /** + * The initial applet size. + */ + Dimension defaultAppletSize = new Dimension(10, 10); + + /** + * The current applet size. + */ + Dimension currentAppletSize = new Dimension(10, 10); + + MessageUtils mu = new MessageUtils(); + + /** + * The thread to use during applet loading + */ + + Thread loaderThread = null; + + /** + * Flag to indicate that a loading has been cancelled + */ + boolean loadAbortRequest = false; + + /* abstract classes */ + abstract protected String getCode(); + abstract protected String getJarFiles(); + abstract protected String getSerializedObject(); + + abstract public int getWidth(); + abstract public int getHeight(); + abstract public boolean hasInitialFocus(); + + private static int threadGroupNumber = 0; + + protected void setupAppletAppContext() { + // do nothing + } + + /* + * Creates a thread to run the applet. This method is called + * each time an applet is loaded and reloaded. + */ + //Overridden by NetxPanel. + protected synchronized void createAppletThread() { + // Create a thread group for the applet, and start a new + // thread to load the applet. + String nm = "applet-" + getCode(); + loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); + loader.grab(); // Keep this puppy around! + + // 4668479: Option to turn off codebase lookup in AppletClassLoader + // during resource requests. [stanley.ho] + String param = getParameter("codebase_lookup"); + + if (param != null && param.equals("false")) + loader.setCodebaseLookup(false); + else + loader.setCodebaseLookup(true); + + + ThreadGroup appletGroup = loader.getThreadGroup(); + + handler = new Thread(appletGroup, this, "thread " + nm); + // set the context class loader for this thread + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + handler.setContextClassLoader(loader); + return null; + } + }); + handler.start(); + } + + void joinAppletThread() throws InterruptedException { + if (handler != null) { + handler.join(); + handler = null; + } + } + + void release() { + if (loader != null) { + loader.release(); + loader = null; + } + } + + /** + * Construct an applet viewer and start the applet. + */ + public void init() { + try { + // Get the width (if any) + defaultAppletSize.width = getWidth(); + currentAppletSize.width = defaultAppletSize.width; + + // Get the height (if any) + defaultAppletSize.height = getHeight(); + currentAppletSize.height = defaultAppletSize.height; + + } catch (NumberFormatException e) { + // Turn on the error flag and let TagAppletPanel + // do the right thing. + status = APPLET_ERROR; + showAppletStatus("badattribute.exception"); + showAppletLog("badattribute.exception"); + showAppletException(e); + } + + setLayout(new BorderLayout()); + + createAppletThread(); + } + + /** + * Minimum size + */ + public Dimension minimumSize() { + return new Dimension(defaultAppletSize.width, + defaultAppletSize.height); + } + + /** + * Preferred size + */ + public Dimension preferredSize() { + return new Dimension(currentAppletSize.width, + currentAppletSize.height); + } + + private AppletListener listeners; + + /** + * AppletEvent Queue + */ + private Queue queue = null; + + + synchronized public void addAppletListener(AppletListener l) { + listeners = AppletEventMulticaster.add(listeners, l); + } + + synchronized public void removeAppletListener(AppletListener l) { + listeners = AppletEventMulticaster.remove(listeners, l); + } + + /** + * Dispatch event to the listeners.. + */ + public void dispatchAppletEvent(int id, Object argument) { + //System.out.println("SEND= " + id); + if (listeners != null) { + AppletEvent evt = new AppletEvent(this, id, argument); + listeners.appletStateChanged(evt); + } + } + + /** + * Send an event. Queue it for execution by the handler thread. + */ + public void sendEvent(int id) { + synchronized(this) { + if (queue == null) { + //System.out.println("SEND0= " + id); + queue = new Queue(); + } + Integer eventId = new Integer(id); + queue.enqueue(eventId); + notifyAll(); + } + if (id == APPLET_QUIT) { + try { + joinAppletThread(); // Let the applet event handler exit + } catch (InterruptedException e) { + } + + // AppletClassLoader.release() must be called by a Thread + // not within the applet's ThreadGroup + if (loader == null) + loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); + release(); + } + } + + /** + * Get an event from the queue. + */ + protected synchronized AppletEvent getNextEvent() throws InterruptedException { + while (queue == null || queue.isEmpty()) { + wait(); + } + Integer eventId = (Integer)queue.dequeue(); + return new AppletEvent(this, eventId.intValue(), null); + } + + boolean emptyEventQueue() { + if ((queue == null) || (queue.isEmpty())) + return true; + else + return false; + } + + /** + * This kludge is specific to get over AccessControlException thrown during + * Applet.stop() or destroy() when static thread is suspended. Set a flag + * in AppletClassLoader to indicate that an + * AccessControlException for RuntimePermission "modifyThread" or + * "modifyThreadGroup" had occurred. + */ + private void setExceptionStatus(AccessControlException e) { + Permission p = e.getPermission(); + if (p instanceof RuntimePermission) { + if (p.getName().startsWith("modifyThread")) { + if (loader == null) + loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); + loader.setExceptionStatus(); + } + } + } + + /** + * Execute applet events. + * Here is the state transition diagram + * + * Note: (XXX) is the action + * APPLET_XXX is the state + * (applet code loaded) --> APPLET_LOAD -- (applet init called)--> APPLET_INIT -- ( + * applet start called) --> APPLET_START -- (applet stop called) -->APPLET_STOP --(applet + * destroyed called) --> APPLET_DESTROY -->(applet gets disposed) --> + * APPLET_DISPOSE -->.... + * + * In the legacy lifecycle model. The applet gets loaded, inited and started. So it stays + * in the APPLET_START state unless the applet goes away(refresh page or leave the page). + * So the applet stop method called and the applet enters APPLET_STOP state. Then if the applet + * is revisited, it will call applet start method and enter the APPLET_START state and stay there. + * + * In the modern lifecycle model. When the applet first time visited, it is same as legacy lifecycle + * model. However, when the applet page goes away. It calls applet stop method and enters APPLET_STOP + * state and then applet destroyed method gets called and enters APPLET_DESTROY state. + * + * This code is also called by AppletViewer. In AppletViewer "Restart" menu, the applet is jump from + * APPLET_STOP to APPLET_DESTROY and to APPLET_INIT . + * + * Also, the applet can jump from APPLET_INIT state to APPLET_DESTROY (in Netscape/Mozilla case). + * Same as APPLET_LOAD to + * APPLET_DISPOSE since all of this are triggered by browser. + * + * + */ + public void run() { + + Thread curThread = Thread.currentThread(); + if (curThread == loaderThread) { + // if we are in the loader thread, cause + // loading to occur. We may exit this with + // status being APPLET_DISPOSE, APPLET_ERROR, + // or APPLET_LOAD + runLoader(); + return; + } + + boolean disposed = false; + while (!disposed && !curThread.isInterrupted()) { + AppletEvent evt; + try { + evt = getNextEvent(); + } catch (InterruptedException e) { + showAppletStatus("bail"); + return; + } + + //showAppletStatus("EVENT = " + evt.getID()); + try { + switch (evt.getID()) { + case APPLET_LOAD: + if (!okToLoad()) { + break; + } + // This complexity allows loading of applets to be + // interruptable. The actual thread loading runs + // in a separate thread, so it can be interrupted + // without harming the applet thread. + // So that we don't have to worry about + // concurrency issues, the main applet thread waits + // until the loader thread terminates. + // (one way or another). + if (loaderThread == null) { + // REMIND: do we want a name? + //System.out.println("------------------- loading applet"); + setLoaderThread(new Thread(this)); + loaderThread.start(); + // we get to go to sleep while this runs + loaderThread.join(); + setLoaderThread(null); + } else { + // REMIND: issue an error -- this case should never + // occur. + } + break; + + case APPLET_INIT: + // AppletViewer "Restart" will jump from destroy method to + // init, that is why we need to check status w/ APPLET_DESTROY + if (status != APPLET_LOAD && status != APPLET_DESTROY) { + showAppletStatus("notloaded"); + break; + } + applet.resize(defaultAppletSize); + if (doInit) { + if (PerformanceLogger.loggingEnabled()) { + PerformanceLogger.setTime("Applet Init"); + PerformanceLogger.outputLog(); + } + applet.init(); + } + + //Need the default(fallback) font to be created in this AppContext + Font f = getFont(); + if (f == null || + "dialog".equals(f.getFamily().toLowerCase(Locale.ENGLISH)) && + f.getSize() == 12 && f.getStyle() == Font.PLAIN) { + setFont(new Font(Font.DIALOG, Font.PLAIN, 12)); + } + + doInit = true; // allow restarts + + // Validate the applet in event dispatch thread + // to avoid deadlock. + try { + final AppletPanel p = this; + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + p.validate(); + } + }); + } + catch(InterruptedException ie) { + } + catch(InvocationTargetException ite) { + } + + status = APPLET_INIT; + showAppletStatus("inited"); + break; + + case APPLET_START: + { + if (status != APPLET_INIT && status != APPLET_STOP) { + showAppletStatus("notinited"); + break; + } + applet.resize(currentAppletSize); + applet.start(); + + // Validate and show the applet in event dispatch thread + // to avoid deadlock. + try { + final AppletPanel p = this; + final Applet a = applet; + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + p.validate(); + a.setVisible(true); + + // Fix for BugTraq ID 4041703. + // Set the default focus for an applet. + if (hasInitialFocus()) + setDefaultFocus(); + } + }); + } + catch(InterruptedException ie) { + } + catch(InvocationTargetException ite) { + } + + status = APPLET_START; + showAppletStatus("started"); + + // reset size to make up for applets that specify height in % + try { + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + int width = getWidth(); + int height = getHeight(); + + appletResize(width, height); + validate(); + } + }); + } catch (Exception e) { + System.err.println("Applet resize failed."); + e.printStackTrace(); + } + + break; + } + case APPLET_STOP: + if (status != APPLET_START) { + showAppletStatus("notstarted"); + break; + } + status = APPLET_STOP; + + // Hide the applet in event dispatch thread + // to avoid deadlock. + try { + final Applet a = applet; + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() + { + a.setVisible(false); + } + }); + } + catch(InterruptedException ie) { + } + catch(InvocationTargetException ite) { + } + + + // During Applet.stop(), any AccessControlException on an involved Class remains in + // the "memory" of the AppletClassLoader. If the same instance of the ClassLoader is + // reused, the same exception will occur during class loading. Set the AppletClassLoader's + // exceptionStatusSet flag to allow recognition of what had happened + // when reusing AppletClassLoader object. + try { + applet.stop(); + } catch (java.security.AccessControlException e) { + setExceptionStatus(e); + // rethrow exception to be handled as it normally would be. + throw e; + } + showAppletStatus("stopped"); + break; + + case APPLET_DESTROY: + if (status != APPLET_STOP && status != APPLET_INIT) { + showAppletStatus("notstopped"); + break; + } + status = APPLET_DESTROY; + + // During Applet.destroy(), any AccessControlException on an involved Class remains in + // the "memory" of the AppletClassLoader. If the same instance of the ClassLoader is + // reused, the same exception will occur during class loading. Set the AppletClassLoader's + // exceptionStatusSet flag to allow recognition of what had happened + // when reusing AppletClassLoader object. + try { + applet.destroy(); + } catch (java.security.AccessControlException e) { + setExceptionStatus(e); + // rethrow exception to be handled as it normally would be. + throw e; + } + showAppletStatus("destroyed"); + break; + + case APPLET_DISPOSE: + if (status != APPLET_DESTROY && status != APPLET_LOAD) { + showAppletStatus("notdestroyed"); + break; + } + status = APPLET_DISPOSE; + + try + { + final Applet a = applet; + + EventQueue.invokeAndWait(new Runnable() + { + public void run() + { + remove(a); + } + }); + } + catch(InterruptedException ie) + { + } + catch(InvocationTargetException ite) + { + } + applet = null; + showAppletStatus("disposed"); + disposed = true; + break; + + case APPLET_QUIT: + return; + } + } catch (Exception e) { + status = APPLET_ERROR; + if (e.getMessage() != null) { + showAppletStatus("exception2", e.getClass().getName(), + e.getMessage()); + } else { + showAppletStatus("exception", e.getClass().getName()); + } + showAppletException(e); + } catch (ThreadDeath e) { + showAppletStatus("death"); + return; + } catch (Error e) { + status = APPLET_ERROR; + if (e.getMessage() != null) { + showAppletStatus("error2", e.getClass().getName(), + e.getMessage()); + } else { + showAppletStatus("error", e.getClass().getName()); + } + showAppletException(e); + } + clearLoadAbortRequest(); + } + } + + /** + * Gets most recent focus owner component associated with the given window. + * It does that without calling Window.getMostRecentFocusOwner since it + * provides its own logic contradicting with setDefautlFocus. Instead, it + * calls KeyboardFocusManager directly. + */ + private Component getMostRecentFocusOwnerForWindow(Window w) { + Method meth = (Method)AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + Method meth = null; + try { + meth = KeyboardFocusManager.class.getDeclaredMethod("getMostRecentFocusOwner", new Class[] {Window.class}); + meth.setAccessible(true); + } catch (Exception e) { + // Must never happen + e.printStackTrace(); + } + return meth; + } + }); + if (meth != null) { + // Meth refers static method + try { + return (Component)meth.invoke(null, new Object[] {w}); + } catch (Exception e) { + // Must never happen + e.printStackTrace(); + } + } + // Will get here if exception was thrown or meth is null + return w.getMostRecentFocusOwner(); + } + + /* + * Fix for BugTraq ID 4041703. + * Set the focus to a reasonable default for an Applet. + */ + private void setDefaultFocus() { + Component toFocus = null; + Container parent = getParent(); + + if(parent != null) { + if (parent instanceof Window) { + toFocus = getMostRecentFocusOwnerForWindow((Window)parent); + if (toFocus == parent || toFocus == null) { + toFocus = parent.getFocusTraversalPolicy(). + getInitialComponent((Window)parent); + } + } else if (parent.isFocusCycleRoot()) { + toFocus = parent.getFocusTraversalPolicy(). + getDefaultComponent(parent); + } + } + + if (toFocus != null) { + if (parent instanceof EmbeddedFrame) { + ((EmbeddedFrame)parent).synthesizeWindowActivation(true); + } + // EmbeddedFrame might have focus before the applet was added. + // Thus after its activation the most recent focus owner will be + // restored. We need the applet's initial focusabled component to + // be focused here. + toFocus.requestFocusInWindow(); + } + } + + /** + * Load the applet into memory. + * Runs in a seperate (and interruptible) thread from the rest of the + * applet event processing so that it can be gracefully interrupted from + * things like HotJava. + */ + //Overridden by NetxPanel. + protected void runLoader() { + if (status != APPLET_DISPOSE) { + showAppletStatus("notdisposed"); + return; + } + + dispatchAppletEvent(APPLET_LOADING, null); + + // REMIND -- might be cool to visually indicate loading here -- + // maybe do animation? + status = APPLET_LOAD; + + // Create a class loader + loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); + + // Load the archives if present. + // REMIND - this probably should be done in a separate thread, + // or at least the additional archives (epll). + + String code = getCode(); + + // setup applet AppContext + // this must be called before loadJarFiles + setupAppletAppContext(); + + try { + loadJarFiles(loader); + applet = createApplet(loader); + } catch (ClassNotFoundException e) { + status = APPLET_ERROR; + showAppletStatus("notfound", code); + showAppletLog("notfound", code); + showAppletException(e); + return; + } catch (InstantiationException e) { + status = APPLET_ERROR; + showAppletStatus("nocreate", code); + showAppletLog("nocreate", code); + showAppletException(e); + return; + } catch (IllegalAccessException e) { + status = APPLET_ERROR; + showAppletStatus("noconstruct", code); + showAppletLog("noconstruct", code); + showAppletException(e); + // sbb -- I added a return here + return; + } catch (Exception e) { + status = APPLET_ERROR; + showAppletStatus("exception", e.getMessage()); + showAppletException(e); + return; + } catch (ThreadDeath e) { + status = APPLET_ERROR; + showAppletStatus("death"); + return; + } catch (Error e) { + status = APPLET_ERROR; + showAppletStatus("error", e.getMessage()); + showAppletException(e); + return; + } finally { + // notify that loading is no longer going on + dispatchAppletEvent(APPLET_LOADING_COMPLETED, null); + } + + // Fixed #4508194: NullPointerException thrown during + // quick page switch + // + if (applet != null) + { + // Stick it in the frame + applet.setStub(this); + applet.hide(); + add("Center", applet); + showAppletStatus("loaded"); + validate(); + } + } + + protected Applet createApplet(final AppletClassLoader loader) throws ClassNotFoundException, + IllegalAccessException, IOException, InstantiationException, InterruptedException { + final String serName = getSerializedObject(); + String code = getCode(); + + if (code != null && serName != null) { + System.err.println(amh.getMessage("runloader.err")); +// return null; + throw new InstantiationException("Either \"code\" or \"object\" should be specified, but not both."); + } + if (code == null && serName == null) { + String msg = "nocode"; + status = APPLET_ERROR; + showAppletStatus(msg); + showAppletLog(msg); + repaint(); + } + if (code != null) { + applet = (Applet)loader.loadCode(code).newInstance(); + doInit = true; + } else { + // serName is not null; + InputStream is = (InputStream) + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + return loader.getResourceAsStream(serName); + } + }); + ObjectInputStream ois = + new AppletObjectInputStream(is, loader); + Object serObject = ois.readObject(); + applet = (Applet) serObject; + doInit = false; // skip over the first init + } + + // Determine the JDK level that the applet targets. + // This is critical for enabling certain backward + // compatibility switch if an applet is a JDK 1.1 + // applet. [stanley.ho] + findAppletJDKLevel(applet); + + if (Thread.interrupted()) { + try { + status = APPLET_DISPOSE; // APPLET_ERROR? + applet = null; + // REMIND: This may not be exactly the right thing: the + // status is set by the stop button and not necessarily + // here. + showAppletStatus("death"); + } finally { + Thread.currentThread().interrupt(); // resignal interrupt + } + return null; + } + return applet; + } + + protected void loadJarFiles(AppletClassLoader loader) throws IOException, + InterruptedException { + // Load the archives if present. + // REMIND - this probably should be done in a separate thread, + // or at least the additional archives (epll). + String jarFiles = getJarFiles(); + + if (jarFiles != null) { + StringTokenizer st = new StringTokenizer(jarFiles, ",", false); + while(st.hasMoreTokens()) { + String tok = st.nextToken().trim(); + try { + loader.addJar(tok); + } catch (IllegalArgumentException e) { + // bad archive name + continue; + } + } + } + } + + /** + * Request that the loading of the applet be stopped. + */ + protected synchronized void stopLoading() { + // REMIND: fill in the body + if (loaderThread != null) { + //System.out.println("Interrupting applet loader thread: " + loaderThread); + loaderThread.interrupt(); + } else { + setLoadAbortRequest(); + } + } + + + protected synchronized boolean okToLoad() { + return !loadAbortRequest; + } + + protected synchronized void clearLoadAbortRequest() { + loadAbortRequest = false; + } + + protected synchronized void setLoadAbortRequest() { + loadAbortRequest = true; + } + + + private synchronized void setLoaderThread(Thread loaderThread) { + this.loaderThread = loaderThread; + } + + /** + * Return true when the applet has been started. + */ + public boolean isActive() { + return status == APPLET_START; + } + + private EventQueue appEvtQ = null; + + /** + * Is called when the applet wants to be resized. + */ + public void appletResize(int width, int height) { + currentAppletSize.width = width; + currentAppletSize.height = height; + final Dimension currentSize = new Dimension(currentAppletSize.width, + currentAppletSize.height); + + if(loader != null) { + AppContext appCtxt = loader.getAppContext(); + if(appCtxt != null) + appEvtQ = (java.awt.EventQueue)appCtxt.get(AppContext.EVENT_QUEUE_KEY); + } + + final AppletPanel ap = this; + if (appEvtQ != null){ + appEvtQ.postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), + new Runnable(){ + public void run(){ + if(ap != null) + { + ap.dispatchAppletEvent(APPLET_RESIZE, currentSize); + } + } + })); + } + } + + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + currentAppletSize.width = width; + currentAppletSize.height = height; + } + + public Applet getApplet() { + return applet; + } + + /** + * Status line. Called by the AppletPanel to provide + * feedback on the Applet's state. + */ + protected void showAppletStatus(String status) { + getAppletContext().showStatus(amh.getMessage(status)); + } + + protected void showAppletStatus(String status, Object arg) { + getAppletContext().showStatus(amh.getMessage(status, arg)); + } + protected void showAppletStatus(String status, Object arg1, Object arg2) { + getAppletContext().showStatus(amh.getMessage(status, arg1, arg2)); + } + + /** + * Called by the AppletPanel to print to the log. + */ + protected void showAppletLog(String msg) { + System.out.println(amh.getMessage(msg)); + } + + protected void showAppletLog(String msg, Object arg) { + System.out.println(amh.getMessage(msg, arg)); + } + + /** + * Called by the AppletPanel to provide + * feedback when an exception has happened. + */ + protected void showAppletException(Throwable t) { + t.printStackTrace(); + repaint(); + } + + /** + * Get caching key for classloader cache + */ + public String getClassLoaderCacheKey() + { + /** + * Fixed #4501142: Classlaoder sharing policy doesn't + * take "archive" into account. This will be overridden + * by Java Plug-in. [stanleyh] + */ + return getCodeBase().toString(); + } + + /** + * The class loaders + */ + private static HashMap classloaders = new HashMap(); + + /** + * Flush a class loader. + */ + public static synchronized void flushClassLoader(String key) { + classloaders.remove(key); + } + + /** + * Flush all class loaders. + */ + public static synchronized void flushClassLoaders() { + classloaders = new HashMap(); + } + + /** + * This method actually creates an AppletClassLoader. + * + * It can be override by subclasses (such as the Plug-in) + * to provide different classloaders. + */ + protected AppletClassLoader createClassLoader(final URL codebase) { + return new AppletClassLoader(codebase); + } + + /** + * Get a class loader. Create in a restricted context + */ + synchronized AppletClassLoader getClassLoader(final URL codebase, final String key) { + AppletClassLoader c = (AppletClassLoader)classloaders.get(key); + if (c == null) { + AccessControlContext acc = + getAccessControlContext(codebase); + c = (AppletClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + AppletClassLoader ac = createClassLoader(codebase); + /* Should the creation of the classloader be + * within the class synchronized block? Since + * this class is used by the plugin, take care + * to avoid deadlocks, or specialize + * AppletPanel within the plugin. It may take + * an arbitrary amount of time to create a + * class loader (involving getting Jar files + * etc.) and may block unrelated applets from + * finishing createAppletThread (due to the + * class synchronization). If + * createAppletThread does not finish quickly, + * the applet cannot process other messages, + * particularly messages such as destroy + * (which timeout when called from the browser). + */ + synchronized (getClass()) { + AppletClassLoader res = + (AppletClassLoader)classloaders.get(key); + if (res == null) { + classloaders.put(key, ac); + return ac; + } else { + return res; + } + } + } + },acc); + } + return c; + } + + /** + * get the context for the AppletClassLoader we are creating. + * the context is granted permission to create the class loader, + * connnect to the codebase, and whatever else the policy grants + * to all codebases. + */ + private AccessControlContext getAccessControlContext(final URL codebase) { + + PermissionCollection perms = (PermissionCollection) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + Policy p = java.security.Policy.getPolicy(); + if (p != null) { + return p.getPermissions(new CodeSource(null, + (java.security.cert.Certificate[]) null)); + } else { + return null; + } + } + }); + + if (perms == null) + perms = new Permissions(); + + //XXX: this is needed to be able to create the classloader itself! + + perms.add(SecurityConstants.CREATE_CLASSLOADER_PERMISSION); + + Permission p; + java.net.URLConnection urlConnection = null; + try { + urlConnection = codebase.openConnection(); + p = urlConnection.getPermission(); + } catch (java.io.IOException ioe) { + p = null; + } + + if (p != null) + perms.add(p); + + if (p instanceof FilePermission) { + + String path = p.getName(); + + int endIndex = path.lastIndexOf(File.separatorChar); + + if (endIndex != -1) { + path = path.substring(0, endIndex+1); + + if (path.endsWith(File.separator)) { + path += "-"; + } + perms.add(new FilePermission(path, + SecurityConstants.FILE_READ_ACTION)); + } + } else { + URL locUrl = codebase; + if (urlConnection instanceof JarURLConnection) { + locUrl = ((JarURLConnection)urlConnection).getJarFileURL(); + } + String host = locUrl.getHost(); + if (host != null && (host.length() > 0)) + perms.add(new SocketPermission(host, + SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); + } + + ProtectionDomain domain = + new ProtectionDomain(new CodeSource(codebase, + (java.security.cert.Certificate[]) null), perms); + AccessControlContext acc = + new AccessControlContext(new ProtectionDomain[] { domain }); + + return acc; + } + + public Thread getAppletHandlerThread() { + return handler; + } + + public int getAppletWidth() { + return currentAppletSize.width; + } + + public int getAppletHeight() { + return currentAppletSize.height; + } + + public static void changeFrameAppContext(Frame frame, AppContext newAppContext) + { + // 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. + + // Check if frame's AppContext has already been set properly + AppContext oldAppContext = SunToolkit.targetToAppContext(frame); + + if (oldAppContext == newAppContext) + return; + + // Synchronization on Window.class is needed for locking the + // critical section of the window list in AppContext. + synchronized (Window.class) + { + WeakReference weakRef = null; + // Remove frame from the Window list in wrong AppContext + { + // Lookup current frame's AppContext + Vector<WeakReference<Window>> windowList = (Vector<WeakReference<Window>>)oldAppContext.get(Window.class); + if (windowList != null) { + for (WeakReference ref : windowList) { + if (ref.get() == frame) { + weakRef = ref; + break; + } + } + // Remove frame from wrong AppContext + if (weakRef != null) + windowList.remove(weakRef); + } + } + + // Put the frame into the applet's AppContext map + SunToolkit.insertTargetMapping(frame, newAppContext); + + // Insert frame into the Window list in the applet's AppContext map + { + Vector<WeakReference<Window>> windowList = (Vector)newAppContext.get(Window.class); + if (windowList == null) { + windowList = new Vector<WeakReference<Window>>(); + newAppContext.put(Window.class, windowList); + } + // use the same weakRef here as it is used elsewhere + windowList.add(weakRef); + } + } + } + + // Flag to indicate if applet is targeted for JDK 1.1. + private boolean jdk11Applet = false; + + // Flag to indicate if applet is targeted for JDK 1.2. + private boolean jdk12Applet = false; + + /** + * Determine JDK level of an applet. + */ + private void findAppletJDKLevel(Applet applet) + { + // To determine the JDK level of an applet, the + // most reliable way is to check the major version + // of the applet class file. + + // synchronized on applet class object, so calling from + // different instances of the same applet will be + // serialized. + Class appletClass = applet.getClass(); + + synchronized(appletClass) { + // Determine if the JDK level of an applet has been + // checked before. + Boolean jdk11Target = (Boolean) loader.isJDK11Target(appletClass); + Boolean jdk12Target = (Boolean) loader.isJDK12Target(appletClass); + + // if applet JDK level has been checked before, retrieve + // value and return. + if (jdk11Target != null || jdk12Target != null) { + jdk11Applet = (jdk11Target == null) ? false : jdk11Target.booleanValue(); + jdk12Applet = (jdk12Target == null) ? false : jdk12Target.booleanValue(); + return; + } + + String name = appletClass.getName(); + + // first convert any '.' to '/' + name = name.replace('.', '/'); + + // append .class + final String resourceName = name + ".class"; + + InputStream is = null; + byte[] classHeader = new byte[8]; + + try { + is = (InputStream) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + return loader.getResourceAsStream(resourceName); + } + }); + + // Read the first 8 bytes of the class file + int byteRead = is.read(classHeader, 0, 8); + is.close(); + + // return if the header is not read in entirely + // for some reasons. + if (byteRead != 8) + return; + } + catch (IOException e) { + return; + } + + // Check major version in class file header + int major_version = readShort(classHeader, 6); + + // Major version in class file is as follows: + // 45 - JDK 1.1 + // 46 - JDK 1.2 + // 47 - JDK 1.3 + // 48 - JDK 1.4 + // 49 - JDK 1.5 + if (major_version < 46) + jdk11Applet = true; + else if (major_version == 46) + jdk12Applet = true; + + // Store applet JDK level in AppContext for later lookup, + // e.g. page switch. + loader.setJDK11Target(appletClass, jdk11Applet); + loader.setJDK12Target(appletClass, jdk12Applet); + } + } + + /** + * Return true if applet is targeted to JDK 1.1. + */ + protected boolean isJDK11Applet() { + return jdk11Applet; + } + + /** + * Return true if applet is targeted to JDK1.2. + */ + protected boolean isJDK12Applet() { + return jdk12Applet; + } + + /** + * Read short from byte array. + */ + private int readShort(byte[] b, int off) { + int hi = readByte(b[off]); + int lo = readByte(b[off + 1]); + return (hi << 8) | lo; + } + + private int readByte(byte b) { + return ((int)b) & 0xFF; + } + + + private static AppletMessageHandler amh = new AppletMessageHandler("appletpanel"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletProps.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,221 @@ +/* + * Copyright 1995-2003 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.awt.*; +import java.io.*; +import java.util.Properties; +import sun.net.www.http.HttpClient; +import sun.net.ftp.FtpClient; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; + +import sun.security.action.*; + +class AppletProps extends Frame { + + TextField proxyHost; + TextField proxyPort; + Choice accessMode; + + AppletProps() { + setTitle(amh.getMessage("title")); + Panel p = new Panel(); + p.setLayout(new GridLayout(0, 2)); + + p.add(new Label(amh.getMessage("label.http.server", "Http proxy server:"))); + p.add(proxyHost = new TextField()); + + p.add(new Label(amh.getMessage("label.http.proxy"))); + p.add(proxyPort = new TextField()); + + p.add(new Label(amh.getMessage("label.class"))); + p.add(accessMode = new Choice()); + accessMode.addItem(amh.getMessage("choice.class.item.restricted")); + accessMode.addItem(amh.getMessage("choice.class.item.unrestricted")); + + add("Center", p); + p = new Panel(); + p.add(new Button(amh.getMessage("button.apply"))); + p.add(new Button(amh.getMessage("button.reset"))); + p.add(new Button(amh.getMessage("button.cancel"))); + add("South", p); + move(200, 150); + pack(); + reset(); + } + + void reset() { + AppletSecurity security = (AppletSecurity) System.getSecurityManager(); + if (security != null) + security.reset(); + + String proxyhost = (String) AccessController.doPrivileged( + new GetPropertyAction("http.proxyHost")); + String proxyport = (String) AccessController.doPrivileged( + new GetPropertyAction("http.proxyPort")); + + Boolean tmp = (Boolean) AccessController.doPrivileged( + new GetBooleanAction("package.restrict.access.sun")); + + boolean packageRestrict = tmp.booleanValue(); + if (packageRestrict) { + accessMode.select(amh.getMessage("choice.class.item.restricted")); + } else { + accessMode.select(amh.getMessage("choice.class.item.unrestricted")); + } + + if (proxyhost != null) { + proxyHost.setText(proxyhost); + proxyPort.setText(proxyport); + } else { + proxyHost.setText(""); + proxyPort.setText(""); + } + } + + void apply() { + String proxyHostValue = proxyHost.getText().trim(); + String proxyPortValue = proxyPort.getText().trim(); + + // Get properties + final Properties props = (Properties) AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return System.getProperties(); + } + }); + + if (proxyHostValue.length() != 0) { + /* 4066402 */ + /* Check for parsable value in proxy port number field before */ + /* applying. Display warning to user until parsable value is */ + /* entered. */ + int proxyPortNumber = 0; + try { + proxyPortNumber = Integer.parseInt(proxyPortValue); + } catch (NumberFormatException e) {} + + if (proxyPortNumber <= 0) { + proxyPort.selectAll(); + proxyPort.requestFocus(); + (new AppletPropsErrorDialog(this, + amh.getMessage("title.invalidproxy"), + amh.getMessage("label.invalidproxy"), + amh.getMessage("button.ok"))).show(); + return; + } + /* end 4066402 */ + + props.put("http.proxyHost", proxyHostValue); + props.put("http.proxyPort", proxyPortValue); + } else { + props.put("http.proxyHost", ""); + } + + if (amh.getMessage("choice.class.item.restricted").equals(accessMode.getSelectedItem())) { + props.put("package.restrict.access.sun", "true"); + } else { + props.put("package.restrict.access.sun", "false"); + } + + // Save properties + try { + reset(); + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws IOException { + File dotAV = Main.theUserPropertiesFile; + FileOutputStream out = new FileOutputStream(dotAV); + Properties avProps = new Properties(); + for (int i = 0; i < Main.avDefaultUserProps.length; i++) { + String avKey = Main.avDefaultUserProps[i][0]; + avProps.setProperty(avKey, props.getProperty(avKey)); + } + avProps.store(out, amh.getMessage("prop.store")); + out.close(); + return null; + } + }); + hide(); + } catch (java.security.PrivilegedActionException e) { + System.out.println(amh.getMessage("apply.exception", + e.getException())); + // XXX what's the general feeling on stack traces to System.out? + e.printStackTrace(); + reset(); + } + } + + public boolean action(Event evt, Object obj) { + if (amh.getMessage("button.apply").equals(obj)) { + apply(); + return true; + } + if (amh.getMessage("button.reset").equals(obj)) { + reset(); + return true; + } + if (amh.getMessage("button.cancel").equals(obj)) { + reset(); + hide(); + return true; + } + return false; + } + + private static AppletMessageHandler amh = new AppletMessageHandler("appletprops"); + +} + +/* 4066432 */ +/* Dialog class to display property-related errors to user */ + +class AppletPropsErrorDialog extends Dialog { + public AppletPropsErrorDialog(Frame parent, String title, String message, + String buttonText) { + super(parent, title, true); + Panel p = new Panel(); + add("Center", new Label(message)); + p.add(new Button(buttonText)); + add("South", p); + pack(); + + Dimension dDim = size(); + Rectangle fRect = parent.bounds(); + move(fRect.x + ((fRect.width - dDim.width) / 2), + fRect.y + ((fRect.height - dDim.height) / 2)); + } + + public boolean action(Event event, Object object) { + hide(); + dispose(); + return true; + } +} + +/* end 4066432 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletResourceLoader.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,48 @@ +/* + * Copyright 1996-1998 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.net.URL; +import java.awt.Image; +import sun.misc.Ref; + +/** + * Part of this class still remains only to support legacy, 100%-impure + * applications such as HotJava 1.0.1. + */ +public class AppletResourceLoader { + public static Image getImage(URL url) { + return AppletViewer.getCachedImage(url); + } + + public static Ref getImageRef(URL url) { + return AppletViewer.getCachedImageRef(url); + } + + public static void flushImages() { + AppletViewer.flushImageCache(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletSecurity.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,371 @@ +/* + * Copyright 1995-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.File; +import java.io.FilePermission; +import java.io.IOException; +import java.io.FileDescriptor; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.net.SocketPermission; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.HashSet; +import java.util.StringTokenizer; +import java.security.*; +import java.lang.reflect.*; +import sun.awt.AWTSecurityManager; +import sun.awt.AppContext; +import sun.security.provider.*; +import sun.security.util.SecurityConstants; + + +/** + * This class defines an applet security policy + * + */ +public +class AppletSecurity extends AWTSecurityManager { + private AppContext mainAppContext; + + //URLClassLoader.acc + private static Field facc = null; + + //AccessControlContext.context; + private static Field fcontext = null; + + static { + try { + facc = URLClassLoader.class.getDeclaredField("acc"); + facc.setAccessible(true); + fcontext = AccessControlContext.class.getDeclaredField("context"); + fcontext.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new UnsupportedOperationException(e); + } + } + + + /** + * Construct and initialize. + */ + public AppletSecurity() { + reset(); + mainAppContext = AppContext.getAppContext(); + } + + // Cache to store known restricted packages + private HashSet restrictedPackages = new HashSet(); + + /** + * Reset from Properties + */ + public void reset() + { + // Clear cache + restrictedPackages.clear(); + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() + { + // Enumerate system properties + Enumeration e = System.getProperties().propertyNames(); + + while (e.hasMoreElements()) + { + String name = (String) e.nextElement(); + + if (name != null && name.startsWith("package.restrict.access.")) + { + String value = System.getProperty(name); + + if (value != null && value.equalsIgnoreCase("true")) + { + String pkg = name.substring(24); + + // Cache restricted packages + restrictedPackages.add(pkg); + } + } + } + return null; + } + }); + } + + /** + * get the current (first) instance of an AppletClassLoader on the stack. + */ + private AppletClassLoader currentAppletClassLoader() + { + // try currentClassLoader first + ClassLoader loader = currentClassLoader(); + + if ((loader == null) || (loader instanceof AppletClassLoader)) + return (AppletClassLoader)loader; + + // if that fails, get all the classes on the stack and check them. + Class[] context = getClassContext(); + for (int i = 0; i < context.length; i++) { + loader = context[i].getClassLoader(); + if (loader instanceof AppletClassLoader) + return (AppletClassLoader)loader; + } + + /* + * fix bug # 6433620 the logic here is : try to find URLClassLoader from + * class context, check its AccessControlContext to see if + * AppletClassLoader is in stack when it's created. for this kind of + * URLClassLoader, return the AppContext assocated with the + * AppletClassLoader. + */ + for (int i = 0; i < context.length; i++) { + final ClassLoader currentLoader = context[i].getClassLoader(); + + if (currentLoader instanceof URLClassLoader) { + loader = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + + AccessControlContext acc = null; + ProtectionDomain[] pds = null; + + try { + acc = (AccessControlContext) facc.get(currentLoader); + if (acc == null) { + return null; + } + + pds = (ProtectionDomain[]) fcontext.get(acc); + if (pds == null) { + return null; + } + } catch (Exception e) { + throw new UnsupportedOperationException(e); + } + + for (int i=0; i<pds.length; i++) { + ClassLoader cl = pds[i].getClassLoader(); + + if (cl instanceof AppletClassLoader) { + return cl; + } + } + + return null; + } + }); + + if (loader != null) { + return (AppletClassLoader) loader; + } + } + } + + // if that fails, try the context class loader + loader = Thread.currentThread().getContextClassLoader(); + if (loader instanceof AppletClassLoader) + return (AppletClassLoader)loader; + + // no AppletClassLoaders on the stack + return (AppletClassLoader)null; + } + + /** + * Returns true if this threadgroup is in the applet's own thread + * group. This will return false if there is no current class + * loader. + */ + protected boolean inThreadGroup(ThreadGroup g) { + if (currentAppletClassLoader() == null) + return false; + else + return getThreadGroup().parentOf(g); + } + + /** + * Returns true of the threadgroup of thread is in the applet's + * own threadgroup. + */ + protected boolean inThreadGroup(Thread thread) { + return inThreadGroup(thread.getThreadGroup()); + } + + /** + * Applets are not allowed to manipulate threads outside + * applet thread groups. However a terminated thread no longer belongs + * to any group. + */ + public void checkAccess(Thread t) { + /* When multiple applets is reloaded simultaneously, there will be + * multiple invocations to this method from plugin's SecurityManager. + * This method should not be synchronized to avoid deadlock when + * a page with multiple applets is reloaded + */ + if ((t.getState() != Thread.State.TERMINATED) && !inThreadGroup(t)) { + checkPermission(SecurityConstants.MODIFY_THREAD_PERMISSION); + } + } + + private boolean inThreadGroupCheck = false; + + /** + * Applets are not allowed to manipulate thread groups outside + * applet thread groups. + */ + public synchronized void checkAccess(ThreadGroup g) { + if (inThreadGroupCheck) { + // if we are in a recursive check, it is because + // inThreadGroup is calling appletLoader.getThreadGroup + // in that case, only do the super check, as appletLoader + // has a begin/endPrivileged + checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION); + } else { + try { + inThreadGroupCheck = true; + if (!inThreadGroup(g)) { + checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION); + } + } finally { + inThreadGroupCheck = false; + } + } + } + + + /** + * Throws a <code>SecurityException</code> if the + * calling thread is not allowed to access the package specified by + * the argument. + * <p> + * This method is used by the <code>loadClass</code> method of class + * loaders. + * <p> + * The <code>checkPackageAccess</code> method for class + * <code>SecurityManager</code> calls + * <code>checkPermission</code> with the + * <code>RuntimePermission("accessClassInPackage."+pkg)</code> + * permission. + * + * @param pkg the package name. + * @exception SecurityException if the caller does not have + * permission to access the specified package. + * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) + */ + public void checkPackageAccess(final String pkgname) { + + // first see if the VM-wide policy allows access to this package + super.checkPackageAccess(pkgname); + + // now check the list of restricted packages + for (Iterator iter = restrictedPackages.iterator(); iter.hasNext();) + { + String pkg = (String) iter.next(); + + // Prevent matching "sun" and "sunir" even if they + // starts with similar beginning characters + // + if (pkgname.equals(pkg) || pkgname.startsWith(pkg + ".")) + { + checkPermission(new java.lang.RuntimePermission + ("accessClassInPackage." + pkgname)); + } + } + } + + /** + * Tests if a client can get access to the AWT event queue. + * <p> + * This method calls <code>checkPermission</code> with the + * <code>AWTPermission("accessEventQueue")</code> permission. + * + * @since JDK1.1 + * @exception SecurityException if the caller does not have + * permission to accesss the AWT event queue. + */ + public void checkAwtEventQueueAccess() { + AppContext appContext = AppContext.getAppContext(); + AppletClassLoader appletClassLoader = currentAppletClassLoader(); + + if ((appContext == mainAppContext) && (appletClassLoader != null)) { + // If we're about to allow access to the main EventQueue, + // and anything untrusted is on the class context stack, + // disallow access. + super.checkAwtEventQueueAccess(); + } + } // checkAwtEventQueueAccess() + + /** + * Returns the thread group of the applet. We consult the classloader + * if there is one. + */ + public ThreadGroup getThreadGroup() { + /* If any applet code is on the execution stack, we return + that applet's ThreadGroup. Otherwise, we use the default + behavior. */ + AppletClassLoader appletLoader = currentAppletClassLoader(); + ThreadGroup loaderGroup = (appletLoader == null) ? null + : appletLoader.getThreadGroup(); + if (loaderGroup != null) { + return loaderGroup; + } else { + return super.getThreadGroup(); + } + } // getThreadGroup() + + /** + * Get the AppContext corresponding to the current context. + * The default implementation returns null, but this method + * may be overridden by various SecurityManagers + * (e.g. AppletSecurity) to index AppContext objects by the + * calling context. + * + * @return the AppContext corresponding to the current context. + * @see sun.awt.AppContext + * @see java.lang.SecurityManager + * @since JDK1.2.1 + */ + public AppContext getAppContext() { + AppletClassLoader appletLoader = currentAppletClassLoader(); + + if (appletLoader == null) { + return null; + } else { + AppContext context = appletLoader.getAppContext(); + + // context == null when some thread in applet thread group + // has not been destroyed in AppContext.dispose() + if (context == null) { + throw new SecurityException("Applet classloader has invalid AppContext"); + } + + return context; + } + } + +} // class AppletSecurity
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletSecurityContext.java Tue Sep 23 16:33:17 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/java/src/main/sun/applet/AppletSecurityContextManager.java Tue Sep 23 16:33:17 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/java/src/main/sun/applet/AppletSecurityException.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,65 @@ +/* + * Copyright 1995-1998 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; + +/** + * An applet security exception. + * + * @author Arthur van Hoff + */ +public +class AppletSecurityException extends SecurityException { + private String key = null; + private Object msgobj[] = null; + + public AppletSecurityException(String name) { + super(name); + this.key = name; + } + + public AppletSecurityException(String name, String arg) { + this(name); + msgobj = new Object[1]; + msgobj[0] = (Object)arg; + } + + public AppletSecurityException(String name, String arg1, String arg2) { + this(name); + msgobj = new Object[2]; + msgobj[0] = (Object)arg1; + msgobj[1] = (Object)arg2; + } + + public String getLocalizedMessage() { + if( msgobj != null) + return amh.getMessage(key, msgobj); + else + return amh.getMessage(key); + } + + private static AppletMessageHandler amh = new AppletMessageHandler("appletsecurityexception"); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletThreadGroup.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,64 @@ +/* + * Copyright 1995-1997 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; + +/** + * This class defines an applet thread group. + * + * @author Arthur van Hoff + */ +public class AppletThreadGroup extends ThreadGroup { + + /** + * Constructs a new thread group for an applet. + * The parent of this new group is the thread + * group of the currently running thread. + * + * @param name the name of the new thread group. + */ + public AppletThreadGroup(String name) { + this(Thread.currentThread().getThreadGroup(), name); + } + + /** + * Creates a new thread group for an applet. + * The parent of this new group is the specified + * thread group. + * + * @param parent the parent thread group. + * @param name the name of the new thread group. + * @exception NullPointerException if the thread group argument is + * <code>null</code>. + * @exception SecurityException if the current thread cannot create a + * thread in the specified thread group. + * @see java.lang.SecurityException + * @since JDK1.1.1 + */ + public AppletThreadGroup(ThreadGroup parent, String name) { + super(parent, name); + setMaxPriority(Thread.NORM_PRIORITY - 1); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletViewerFactory.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,41 @@ +/* + * Copyright 1996 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. + */ + +/* + * AppletViewerFactory.java + */ + +package sun.applet; + +import java.util.Hashtable; +import java.net.URL; +import java.awt.MenuBar; + +public +interface AppletViewerFactory { + public AppletViewer createAppletViewer(int x, int y, URL doc, Hashtable atts); + public MenuBar getBaseMenuBar(); + public boolean isStandalone(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/AppletViewerPanel.java Tue Sep 23 16:33:17 2008 -0400 @@ -0,0 +1,254 @@ +/* + * Copyright 1995-2005 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.AppletContext; +import java.awt.Dimension; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Hashtable; + + +/** + * Sample applet panel class. The panel manages and manipulates the + * applet as it is being loaded. It forks a seperate thread in a new + * thread group to call the applet's init(), start(), stop(), and + * destroy() methods. + * + * @author Arthur van Hoff + */ +public class AppletViewerPanel extends AppletPanel { + + /* Are we debugging? */ + protected static boolean debug = true; + + /** + * The document url. + */ + protected URL documentURL; + + /** + * The base url. + */ + protected URL baseURL; + + /** + * The attributes of the applet. + */ + protected Hashtable atts; + + /* + * JDK 1.1 serialVersionUID + */ + private static final long serialVersionUID = 8890989370785545619L; + + private Dimension windowSizeFactor = new Dimension(750, 350); + + /** + * Construct an applet viewer and start the applet. + */ + protected AppletViewerPanel(URL documentURL, Hashtable atts) { + this.documentURL = documentURL; + this.atts = atts; + + String att = getParameter("codebase"); + if (att != null) { + if (!att.endsWith("/")) { + att += "/"; + } + try { + baseURL = new URL(documentURL, att); + } catch (MalformedURLException e) { + } + } + if (baseURL == null) { + String file = documentURL.getFile(); + int i = file.lastIndexOf('/'); + if (i >= 0 && i < file.length() - 1) { + try { + baseURL = new URL(documentURL, file.substring(0, i + 1)); + } catch (MalformedURLException e) { + } + } + } + + // when all is said & done, baseURL shouldn't be null + if (baseURL == null) + baseURL = documentURL; + + + } + + + /** + * Get an applet parameter. + */ + public String getParameter(String name) { + return (String)atts.get(name.toLowerCase()); + } + + /** + * Get the document url. + */ + public URL getDocumentBase() { + return documentURL; + + } + + /** + * Get the base url. + */ + public URL getCodeBase() { + return baseURL; + } + + /** + * Set applet size (as proportion of window size) if needed + */ + public synchronized void setAppletSizeIfNeeded(int width, int height) { + + Dimension newD = new Dimension(getWidth(), getHeight()); + + String h = getParameter("height"); + String w = getParameter("width"); + + if (width != -1 && w != null && w.endsWith("%")) { + newD.width = (Integer.valueOf(w.substring(0, w.length() - 1)).intValue()/100)*width; + } + + if (height != -1 && h != null && h.endsWith("%")) { + newD.height = (Integer.valueOf(h.substring(0, h.length() - 1)).intValue()/100)*height; + } + + synchronized(windowSizeFactor) { + windowSizeFactor = newD; + } + } + + /** + * Get the width. + */ + public int getWidth() { + String w = getParameter("width"); + if (w != null) { + try { + return Integer.valueOf(w).intValue(); + } catch (NumberFormatException nfe) { + synchronized(windowSizeFactor) { + System.err.println("getWidth() returning " + windowSizeFactor.width); + return windowSizeFactor.width; + } + } + } + return 0; + } + + + /** + * Get the height. + */ + public int getHeight() { + String h = getParameter("height"); + if (h != null) { + try { + return Integer.valueOf(h).intValue(); + } catch (NumberFormatException nfe) { + synchronized(windowSizeFactor) { + System.err.println("getHeight() returning " + windowSizeFactor.height); + return windowSizeFactor.height; + } + } + } + return 0; + } + + /** + * Get initial_focus + */ + public boolean hasInitialFocus() + { + + // 6234219: Do not set initial focus on an applet + // during startup if applet is targeted for + // JDK 1.1/1.2. [stanley.ho] + if (isJDK11Applet() || isJDK12Applet()) + return false; + + String initialFocus = getParameter("initial_focus"); + + if (initialFocus != null) + { + if (initialFocus.toLowerCase().equals("false")) + return false; + } + + return true; + } + + /** + * Get the code parameter + */ + public String getCode() { + return getParameter("code"); + } + + + /** + * Return the list of jar files if specified. + * Otherwise return null. + */ + public String getJarFiles() { + return getParameter("archive"); + } + + /** + * Return the value of the object param + */ + public String getSerializedObject() { + return getParameter("object");// another name? + } + + + /** + * Get the applet context. For now this is + * also implemented by the AppletPanel class. + */ + public AppletContext getAppletContext() { + return (AppletContext)getParent(); + } + + protected static void debug(String s) { + if(debug) + System.err.println("AppletViewerPanel:::" + s); + } + + protected static void debug(String s, Throwable t) { + if(debug) { + t.printStackTrace(); + debug(s); + } + } +}
--- a/plugin/icedtea/java/src/main/sun/applet/GetMemberPluginCallRequest.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* 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"); - } -} -
--- a/plugin/icedtea/java/src/main/sun/applet/GetWindowPluginCallRequest.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* 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"); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/Main.java Tue Sep 23 16:33:17 2008 -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.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.MalformedURLException; +import java.util.Enumeration; +import java.util.Properties; +import java.util.Vector; +import sun.net.www.ParseUtil; + +/** + * The main entry point into AppletViewer. + */ +public class Main { + /** + * The file which contains all of the AppletViewer specific properties. + */ + static File theUserPropertiesFile; + + /** + * The default key/value pairs for the required user-specific properties. + */ + static final String [][] avDefaultUserProps = { + // There's a bootstrapping problem here. If we don't have a proxyHost, + // then we will not be able to connect to a URL outside the firewall; + // however, there's no way for us to set the proxyHost without starting + // AppletViewer. This problem existed before the re-write. + {"http.proxyHost", ""}, + {"http.proxyPort", "80"}, + {"package.restrict.access.sun", "true"} + }; + + static { + File userHome = new File(System.getProperty("user.home")); + // make sure we can write to this location + userHome.canWrite(); + + theUserPropertiesFile = new File(userHome, ".appletviewer"); + } + + // i18n + private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer"); + + /** + * Member variables set according to options passed in to AppletViewer. + */ + private boolean debugFlag = false; + private boolean helpFlag = false; + private String encoding = null; + private boolean noSecurityFlag = false; + private static boolean cmdLineTestFlag = false; + + /** + * The list of valid URLs passed in to AppletViewer. + */ + private static Vector urlList = new Vector(1); + + // 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"); + + /** + * The main entry point into AppletViewer. + */ + public static void main(String [] args) { + Main m = new Main(); + int ret = m.run(args); + + // Exit immediately if we got some sort of error along the way. + // For debugging purposes, if we have passed in "-XcmdLineTest" we + // force a premature exit. + if ((ret != 0) || (cmdLineTestFlag)) + System.exit(ret); + } + + private int run(String [] args) { + // DECODE ARGS + try { + if (args.length == 0) { + usage(); + return 0; + } + for (int i = 0; i < args.length; ) { + int j = decodeArg(args, i); + if (j == 0) { + throw new ParseException(lookup("main.err.unrecognizedarg", + args[i])); + } + i += j; + } + } catch (ParseException e) { + System.err.println(e.getMessage()); + return 1; + } + + // CHECK ARGUMENTS + if (helpFlag) { + usage(); + return 0; + } + + if (urlList.size() == 0) { + System.err.println(lookup("main.err.inputfile")); + return 1; + } + + if (debugFlag) { + // START A DEBUG SESSION + // Given the current architecture, we will end up decoding the + // arguments again, but at least we are guaranteed to have + // arguments which are valid. + return invokeDebugger(args); + } + + // INSTALL THE SECURITY MANAGER (if necessary) + if (!noSecurityFlag && (System.getSecurityManager() == null)) + init(); + + // LAUNCH APPLETVIEWER FOR EACH URL + for (int i = 0; i < urlList.size(); i++) { + try { + // XXX 5/17 this parsing method should be changed/fixed so that + // it doesn't do both parsing of the html file and launching of + // the AppletPanel + AppletViewer.parse((URL) urlList.elementAt(i), encoding); + } catch (IOException e) { + System.err.println(lookup("main.err.io", e.getMessage())); + return 1; + } + } + return 0; + } + + private static void usage() { + System.out.println(lookup("usage")); + } + + /** + * Decode a single argument in an array and return the number of elements + * used. + * + * @param args The array of arguments. + * @param i The argument to decode. + * @return The number of array elements used when the argument was + * decoded. + * @exception ParseException + * Thrown when there is a problem with something in the + * argument array. + */ + private int decodeArg(String [] args, int i) throws ParseException { + String arg = args[i]; + int argc = args.length; + + if ("-help".equalsIgnoreCase(arg) || "-?".equals(arg)) { + helpFlag = true; + return 1; + } else if ("-encoding".equals(arg) && (i < argc - 1)) { + if (encoding != null) + throw new ParseException(lookup("main.err.dupoption", arg)); + encoding = args[++i]; + return 2; + } else if ("-debug".equals(arg)) { + debugFlag = true; + return 1; + } else if ("-Xnosecurity".equals(arg)) { + // This is an undocumented (and, in the future, unsupported) + // flag which prevents AppletViewer from installing its own + // SecurityManager. + + System.err.println(); + System.err.println(lookup("main.warn.nosecmgr")); + System.err.println(); + + noSecurityFlag = true; + return 1; + } else if ("-XcmdLineTest".equals(arg)) { + // This is an internal flag which should be used for command-line + // testing. It instructs AppletViewer to force a premature exit + // immediately after the applet has been launched. + cmdLineTestFlag = true; + return 1; + } else if (arg.startsWith("-")) { + throw new ParseException(lookup("main.err.unsupportedopt", arg)); + } else { + // we found what we hope is a url + URL url = parseURL(arg); + if (url != null) { + urlList.addElement(url); + return 1; + } + } + return 0; + } + + /** + * Following the relevant RFC, construct a valid URL based on the passed in + * string. + * + * @param url a string which represents either a relative or absolute URL. + * @return a URL when the passed in string can be interpreted according + * to the RFC, <code>null</code> otherwise. + * @exception ParseException + * Thrown when we are unable to construct a proper URL from the + * passed in string. + */ + private URL parseURL(String url) throws ParseException { + URL u = null; + // prefix of the urls with 'file' scheme + String prefix = "file:"; + + try { + if (url.indexOf(':') <= 1) + { + // appletviewer accepts only unencoded filesystem paths + u = ParseUtil.fileToEncodedURL(new File(url)); + } else if (url.startsWith(prefix) && + url.length() != prefix.length() && + !(new File(url.substring(prefix.length())).isAbsolute())) + { + // relative file URL, like this "file:index.html" + // ensure that this file URL is absolute + // ParseUtil.fileToEncodedURL should be done last (see 6329251) + String path = ParseUtil.fileToEncodedURL(new File(System.getProperty("user.dir"))).getPath() + + url.substring(prefix.length()); + u = new URL("file", "", path); + } else { + // appletviewer accepts only encoded urls + u = new URL(url); + } + } catch (MalformedURLException e) { + throw new ParseException(lookup("main.err.badurl", + url, e.getMessage())); + } + + return u; + } + + /** + * Invoke the debugger with the arguments passed in to appletviewer. + * + * @param args The arguments passed into the debugger. + * @return <code>0</code> if the debugger is invoked successfully, + * <code>1</code> otherwise. + */ + private int invokeDebugger(String [] args) { + // CONSTRUCT THE COMMAND LINE + String [] newArgs = new String[args.length + 1]; + int current = 0; + + // Add a -classpath argument that prevents + // the debugger from launching appletviewer with the default of + // ".". appletviewer's classpath should never contain valid + // classes since they will result in security exceptions. + // Ideally, the classpath should be set to "", but the VM won't + // allow an empty classpath, so a phony directory name is used. + String phonyDir = System.getProperty("java.home") + + File.separator + "phony"; + newArgs[current++] = "-Djava.class.path=" + phonyDir; + + // Appletviewer's main class is the debuggee + newArgs[current++] = "sun.applet.Main"; + + // Append all the of the original appletviewer arguments, + // leaving out the "-debug" option. + for (int i = 0; i < args.length; i++) { + if (!("-debug".equals(args[i]))) { + newArgs[current++] = args[i]; + } + } + + // LAUNCH THE DEBUGGER + // Reflection is used for two reasons: + // 1) The debugger classes are on classpath and thus must be loaded + // by the application class loader. (Currently, appletviewer are + // loaded through the boot class path out of rt.jar.) + // 2) Reflection removes any build dependency between appletviewer + // and jdb. + try { + Class c = Class.forName("com.sun.tools.example.debug.tty.TTY", true, + ClassLoader.getSystemClassLoader()); + Method m = c.getDeclaredMethod("main", + new Class[] { String[].class }); + m.invoke(null, new Object[] { newArgs }); + } catch (ClassNotFoundException cnfe) { + System.err.println(lookup("main.debug.cantfinddebug")); + return 1; + } catch (NoSuchMethodException nsme) { + System.err.println(lookup("main.debug.cantfindmain")); + return 1; + } catch (InvocationTargetException ite) { + System.err.println(lookup("main.debug.exceptionindebug")); + return 1; + } catch (IllegalAccessException iae) { + System.err.println(lookup("main.debug.cantaccess")); + return 1; + } + return 0; + } + + private void init() { + // GET APPLETVIEWER USER-SPECIFIC PROPERTIES + Properties avProps = getAVProps(); + + // 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); + String oldVal; + if ((oldVal = (String) avProps.setProperty(key, val)) != null) + System.err.println(lookup("main.warn.prop.overwrite", key, + oldVal, val)); + } + + // INSTALL THE PROPERTY LIST + System.setProperties(avProps); + + // Create and install the security manager + if (!noSecurityFlag) { + System.setSecurityManager(new AppletSecurity()); + } else { + System.err.println(lookup("main.nosecmgr")); + } + + // REMIND: Create and install a socket factory! + } + + /** + * Read the AppletViewer user-specific properties. Typically, these + * properties should reside in the file $USER/.appletviewer. If this file + * does not exist, one will be created. Information for this file will + * be gleaned from $USER/.hotjava/properties. If that file does not exist, + * then default values will be used. + * + * @return A Properties object containing all of the AppletViewer + * user-specific properties. + */ + private Properties getAVProps() { + Properties avProps = new Properties(); + + File dotAV = theUserPropertiesFile; + if (dotAV.exists()) { + // we must have already done the conversion + if (dotAV.canRead()) { + // just read the file + avProps = getAVProps(dotAV); + } else { + // send out warning and use defaults + System.err.println(lookup("main.warn.cantreadprops", + dotAV.toString())); + avProps = setDefaultAVProps(); + } + } else { + // create the $USER/.appletviewer file + + // see if $USER/.hotjava/properties exists + File userHome = new File(System.getProperty("user.home")); + File dotHJ = new File(userHome, ".hotjava"); + dotHJ = new File(dotHJ, "properties"); + if (dotHJ.exists()) { + // just read the file + avProps = getAVProps(dotHJ); + } else { + // send out warning and use defaults + System.err.println(lookup("main.warn.cantreadprops", + dotHJ.toString())); + avProps = setDefaultAVProps(); + } + + // SAVE THE FILE + try { + FileOutputStream out = new FileOutputStream(dotAV); + avProps.store(out, lookup("main.prop.store")); + out.close(); + } catch (IOException e) { + System.err.println(lookup("main.err.prop.cantsave", + dotAV.toString())); + } + } + return avProps; + } + + /** + * Set the AppletViewer user-specific properties to be the default values. + * + * @return A Properties object containing all of the AppletViewer + * user-specific properties, set to the default values. + */ + private Properties setDefaultAVProps() { + Properties avProps = new Properties(); + for (int i = 0; i < avDefaultUserProps.length; i++) { + avProps.setProperty(avDefaultUserProps[i][0], + avDefaultUserProps[i][1]); + } + return avProps; + } + + /** + * Given a file, find only the properties that are setable by AppletViewer. + * + * @param inFile A Properties file from which we select the properties of + * interest. + * @return A Properties object containing all of the AppletViewer + * user-specific properties. + */ + private Properties getAVProps(File inFile) { + Properties avProps = new Properties(); + + // read the file + Properties tmpProps = new Properties(); + try { + FileInputStream in = new FileInputStream(inFile); + tmpProps.load(new BufferedInputStream(in)); + in.close(); + } catch (IOException e) { + System.err.println(lookup("main.err.prop.cantread", + inFile.toString())); + } + + // pick off the properties we care about + for (int i = 0; i < avDefaultUserProps.length; i++) { + String value = tmpProps.getProperty(avDefaultUserProps[i][0]); + if (value != null) { + // the property exists in the file, so replace the default + avProps.setProperty(avDefaultUserProps[i][0], value); + } else { + // just use the default + avProps.setProperty(avDefaultUserProps[i][0], + avDefaultUserProps[i][1]); + } + } + return avProps; + } + + /** + * Methods for easier i18n handling. + */ + + private static String lookup(String key) { + return amh.getMessage(key); + } + + private static String lookup(String key, String arg0) { + return amh.getMessage(key, arg0); + } + + private static String lookup(String key, String arg0, String arg1) { + return amh.getMessage(key, arg0, arg1); + } + + private static String lookup(String key, String arg0, String arg1, + String arg2) { + return amh.getMessage(key, arg0, arg1, arg2); + } + + class ParseException extends RuntimeException + { + public ParseException(String msg) { + super(msg); + } + + public ParseException(Throwable t) { + super(t.getMessage()); + this.t = t; + } + + Throwable t = null; + } +}
--- a/plugin/icedtea/java/src/main/sun/applet/PluginAppletSecurityContext.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,847 +0,0 @@ -/* 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); - } -}
--- a/plugin/icedtea/java/src/main/sun/applet/PluginAppletViewer.java Sun Sep 21 15:58:46 2008 -0400 +++ b/plugin/icedtea/java/src/main/sun/applet/PluginAppletViewer.java Tue Sep 23 16:33:17 2008 -0400 @@ -25,26 +25,45 @@ 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; + 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 @@ -109,7 +128,17 @@ // 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 */ @@ -117,20 +146,25 @@ final Hashtable atts, PrintStream statusMsgStream, PluginAppletViewerFactory factory) { super(handle, true); - this.factory = factory; + 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); - } + 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(); @@ -227,21 +261,32 @@ sleepTime += 100; PluginDebug.debug("Waiting for applet to initialize... "); } catch (InterruptedException ie) { - // ignore + ie.printStackTrace(); } } + PluginDebug.debug("Applet initialized"); + // Applet initialized. Find out it's classloader and add it to the list - PluginAppletSecurityContext.classLoaders.put(Integer.toString(identifier), a.getClass().getClassLoader()); - + 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); + + PluginDebug.debug("PAV handling: " + message); try { if (message.startsWith("tag")) { @@ -296,7 +341,7 @@ PluginDebug.debug ("REQUEST HANDLE, DONE PARSING " + Thread.currentThread()); } else { - PluginDebug.debug ("REQUEST HANDLE NOT SET: " + request.tag + ". BYPASSING"); + PluginDebug.debug ("REQUEST TAG NOT SET: " + request.tag + ". BYPASSING"); } } } else { @@ -314,12 +359,12 @@ if (message.startsWith("width")) { int width = Integer.parseInt(message.substring("width".length() + 1)); - panel.setAppletSizeIfNeeded(width, -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); + //panel.setAppletSizeIfNeeded(-1, height); setSize(getWidth(), height); } else if (message.startsWith("destroy")) { dispose(); @@ -338,16 +383,16 @@ sleepTime += 100; PluginDebug.debug("Waiting for applet to initialize..."); } catch (InterruptedException ie) { - // ignore + ie.printStackTrace(); } } System.err.println ("Looking for object " + o + " panel is " + panel.getClass()); - PluginAppletSecurityContext.contexts.get(0).store.reference(o); + AppletSecurityContextManager.getSecurityContext(0).store(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)); + + AppletSecurityContextManager.getSecurityContext(0).getIdentifier(o)); + streamhandler.write("context 0 reference " + reference + " GetJavaObject " + + AppletSecurityContextManager.getSecurityContext(0).getIdentifier(o)); System.err.println ("WRITING 1 DONE"); } } @@ -360,7 +405,12 @@ 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"); + 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. @@ -562,7 +612,7 @@ } catch (IOException exception) { // Deliberately ignore IOException. showDocument may be // called from threads other than the main thread after - // PluginMain.pluginOutputStream has been closed. + // streamhandler.pluginOutputStream has been closed. } } @@ -576,24 +626,24 @@ } catch (IOException exception) { // Deliberately ignore IOException. showStatus may be // called from threads other than the main thread after - // PluginMain.pluginOutputStream has been closed. + // streamhandler.pluginOutputStream has been closed. } } public int getWindow() { System.out.println ("STARTING getWindow"); - GetWindowPluginCallRequest request = - new GetWindowPluginCallRequest("instance " + identifier + " " + - "GetWindow", "JavaScriptGetWindow"); + PluginCallRequest request = requestFactory.getPluginCallRequest("window", + "instance " + identifier + " " + "GetWindow", + "JavaScriptGetWindow"); System.out.println ("STARTING postCallRequest"); - PluginMain.postCallRequest(request); + streamhandler.postCallRequest(request); System.out.println ("STARTING postCallRequest done"); - PluginMain.write(request.message); + streamhandler.write(request.getMessage()); try { System.out.println ("wait request 1"); synchronized(request) { System.out.println ("wait request 2"); - while (request.internal == 0) + while ((Integer) request.getObject() == 0) request.wait(); System.out.println ("wait request 3"); } @@ -603,60 +653,55 @@ } System.out.println ("STARTING getWindow DONE"); - return request.internal; + return (Integer) request.getObject(); } // 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); + AppletSecurityContextManager.getSecurityContext(0).store(name); + int nameID = AppletSecurityContextManager.getSecurityContext(0).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); + PluginCallRequest request = requestFactory.getPluginCallRequest("member", + "instance " + 0 + " GetMember " + internal + " " + nameID, + "JavaScriptGetMember"); + streamhandler.postCallRequest(request); + streamhandler.write(request.getMessage()); try { - System.out.println ("wait getMEM request 1"); + System.err.println ("wait getMEM request 1"); synchronized(request) { - System.out.println ("wait getMEM request 2"); - while (request.done == false) + System.err.println ("wait getMEM request 2"); + while (request.isDone() == false) request.wait(); - System.out.println ("wait getMEM request 3"); + System.err.println ("wait getMEM request 3 GOT: " + request.getObject().getClass()); } } catch (InterruptedException e) { throw new RuntimeException("Interrupted waiting for call request.", e); } - System.out.println (" getMember DONE"); - return request.object; + System.err.println (" getMember DONE"); + return request.getObject(); } 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); + 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. - VoidPluginCallRequest request = - new VoidPluginCallRequest("instance " + 0 + - " SetMember " + internal + - " " + nameID + " " + valueID, "JavaScriptSetMember"); - PluginMain.postCallRequest(request); - PluginMain.write(request.message); + 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.message); + 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.done == false) + while (request.isDone() == false) request.wait(); System.out.println ("wait setMem request 3"); } @@ -669,22 +714,20 @@ // 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); + AppletSecurityContextManager.getSecurityContext(0).store(value); + int valueID = AppletSecurityContextManager.getSecurityContext(0).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); + 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.done == false) + while (request.isDone() == false) request.wait(); System.out.println ("wait setSlot request 3"); } @@ -698,17 +741,16 @@ 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); + 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.done == false) + while (request.isDone() == false) request.wait(); System.out.println ("wait getSlot request 3"); } @@ -717,27 +759,25 @@ e); } System.out.println (" getSlot DONE"); - return request.object; + return request.getObject(); } public static Object eval(int internal, String s) { - PluginAppletSecurityContext.contexts.get(0).store.reference(s); - int stringID = PluginAppletSecurityContext.contexts.get( - 0).store.getIdentifier(s); + AppletSecurityContextManager.getSecurityContext(0).store(s); + int stringID = AppletSecurityContextManager.getSecurityContext(0).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); + 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.done == false) + while (request.isDone() == false) request.wait(); System.out.println ("wait eval request 3"); } @@ -746,26 +786,24 @@ e); } System.out.println (" getSlot DONE"); - return request.object; + return request.getObject(); } public static void removeMember (int internal, String name) { - PluginAppletSecurityContext.contexts.get(0).store.reference(name); - int nameID = PluginAppletSecurityContext.contexts.get( - 0).store.getIdentifier(name); + AppletSecurityContextManager.getSecurityContext(0).store(name); + int nameID = AppletSecurityContextManager.getSecurityContext(0).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); + 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.done == false) + while (request.isDone() == false) request.wait(); System.out.println ("wait removeMember request 3"); } @@ -781,25 +819,22 @@ // 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); + 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. - GetMemberPluginCallRequest request = - new GetMemberPluginCallRequest("instance " + 0 + - " Call " + internal + - " " + nameID + " " + argsID, "JavaScriptCall"); - PluginMain.postCallRequest(request); - PluginMain.write(request.message); + 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.done == false) + while (request.isDone() == false) request.wait(); System.out.println ("wait call request 3"); } @@ -808,22 +843,22 @@ e); } System.out.println (" Call DONE"); - return request.object; + return request.getObject(); } 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); + 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.done == false) + while (request.isDone() == false) request.wait(); System.out.println ("wait finalize request 3"); } @@ -837,16 +872,16 @@ 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); + 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.done == false) + while (request.isDone() == false) request.wait(); System.out.println ("wait ToString request 3"); } @@ -855,26 +890,17 @@ e); } System.out.println (" ToString DONE"); - return (String) request.object; + 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); - PluginMain.write("instance " + identifier + " " + message); + streamhandler.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. } @@ -1014,7 +1040,13 @@ return; // abort the reload } - panel.createAppletThread(); + 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); @@ -1207,7 +1239,26 @@ public static void parse(int identifier, long handle, Reader in, URL url) throws IOException { - parse(identifier, handle, in, url, System.out, new PluginAppletViewerFactory()); + 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, @@ -1408,16 +1459,7 @@ 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)
--- a/plugin/icedtea/java/src/main/sun/applet/PluginCallRequest.java Sun Sep 21 15:58:46 2008 -0400 +++ b/plugin/icedtea/java/src/main/sun/applet/PluginCallRequest.java Tue Sep 23 16:33:17 2008 -0400 @@ -37,9 +37,12 @@ package sun.applet; +import java.security.AccessControlContext; +import java.security.ProtectionDomain; + // FIXME: for each type of request extend a new (anonymous?) // PluginCallRequest. -abstract class PluginCallRequest { +public abstract class PluginCallRequest { String message; String returnString; PluginCallRequest next; @@ -50,7 +53,33 @@ 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/java/src/main/sun/applet/PluginCallRequestFactory.java Tue Sep 23 16:33:17 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/java/src/main/sun/applet/PluginClassLoader.java Tue Sep 23 16:33:17 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); + } + +}
--- a/plugin/icedtea/java/src/main/sun/applet/PluginDebug.java Sun Sep 21 15:58:46 2008 -0400 +++ b/plugin/icedtea/java/src/main/sun/applet/PluginDebug.java Tue Sep 23 16:33:17 2008 -0400 @@ -3,7 +3,7 @@ import java.io.*; public class PluginDebug { - + static final boolean DEBUG = true; public static void debug(String message) {
--- a/plugin/icedtea/java/src/main/sun/applet/PluginException.java Sun Sep 21 15:58:46 2008 -0400 +++ b/plugin/icedtea/java/src/main/sun/applet/PluginException.java Tue Sep 23 16:33:17 2008 -0400 @@ -1,14 +1,15 @@ package sun.applet; + public class PluginException extends Exception { - public PluginException (int instance, int reference, Throwable t) { + public PluginException (PluginStreamHandler sh, int instance, int reference, Throwable t) { t.printStackTrace(); this.setStackTrace(t.getStackTrace()); - PluginAppletSecurityContext.contexts.get(0).store.dump(); + AppletSecurityContextManager.dumpStore(0); String message = "instance " + instance + " reference " + reference + " Error " + t.getMessage(); - PluginMain.write(message); + sh.write(message); } }
--- a/plugin/icedtea/java/src/main/sun/applet/PluginMain.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,533 +0,0 @@ -/* - * 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; - } -}
--- a/plugin/icedtea/java/src/main/sun/applet/PluginMessageConsumer.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -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"); - } - -}
--- a/plugin/icedtea/java/src/main/sun/applet/PluginMessageHandlerWorker.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -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; - } -}
--- a/plugin/icedtea/java/src/main/sun/applet/PluginObjectStore.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* 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)); - } - } -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedtea/java/src/main/sun/applet/PluginStreamHandler.java Tue Sep 23 16:33:17 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/plugin/icedtea/java/src/main/sun/applet/TestEnv.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,172 +0,0 @@ -/* 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; - } -}
--- a/plugin/icedtea/java/src/main/sun/applet/VoidPluginCallRequest.java Sun Sep 21 15:58:46 2008 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* 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"); - } -}
--- a/rt/net/sourceforge/jnlp/Launcher.java Sun Sep 21 15:58:46 2008 -0400 +++ b/rt/net/sourceforge/jnlp/Launcher.java Tue Sep 23 16:33:17 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 Sun Sep 21 15:58:46 2008 -0400 +++ b/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java Tue Sep 23 16:33:17 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 Sun Sep 21 15:58:46 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 Sun Sep 21 15:58:46 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 Sun Sep 21 15:58:46 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 Sun Sep 21 15:58:46 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 Sun Sep 21 15:58:46 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(); - } -}