|
|
Line 86: |
Line 86: |
| Well, there is a problem. The ''java.beans.AppletInitializer'' interface. It resides in beans, yet its signature contains ''java.applet.Applet''. This means that the ''java.beans'' package has compile time dependency on ''java.applet''. Does that mean whoever uses [[JavaBean]]s module in future, needs to install applet module as well? | | Well, there is a problem. The ''java.beans.AppletInitializer'' interface. It resides in beans, yet its signature contains ''java.applet.Applet''. This means that the ''java.beans'' package has compile time dependency on ''java.applet''. Does that mean whoever uses [[JavaBean]]s module in future, needs to install applet module as well? |
| | | |
- | No. I have a solution: Let's use [[CodeInjection]]! Let's change Beans code to not talk directly to Applet, but rather create a '''code slot''' that can be injected by the applet module. Here is the diff against [http://hg.openjdk.java.net/jdk7/jdk7/jdk openjdk repository]: | + | No. I have a solution: Let's use [[CodeInjection]]! Let's change Beans code to not talk directly to Applet, but rather create a '''code slot''' that can be injected by the applet module. Here is the diff against out [http://source.apidesign.org/hg/jdk/ openjdk repository]: |
| | | |
- | <source lang="diff">
| + | The diff is [http://source.apidesign.org/hg/jdk/rev/57914fd9382f here]. |
- | diff -r f72c0dc047b9 -r 57914fd9382f src/share/classes/META-INF/services/sun.beans.AppletProxy
| + | |
- | --- /dev/null Thu Jan 01 00:00:00 1970 +0000
| + | |
- | +++ b/src/share/classes/META-INF/services/sun.beans.AppletProxy Tue Jun 16 17:53:32 2009 +0200
| + | |
- | @@ -0,0 +1,1 @@
| + | |
- | +sun.applet.BeansBridge
| + | |
- | diff -r f72c0dc047b9 -r 57914fd9382f src/share/classes/java/beans/Beans.java
| + | |
- | --- a/src/share/classes/java/beans/Beans.java Thu Jun 11 10:54:22 2009 -0700
| + | |
- | +++ b/src/share/classes/java/beans/Beans.java Tue Jun 16 17:53:32 2009 +0200
| + | |
- | @@ -27,13 +27,7 @@
| + | |
- |
| + | |
- | import com.sun.beans.finder.ClassFinder;
| + | |
- |
| + | |
- | -import java.applet.Applet;
| + | |
- | -import java.applet.AppletContext;
| + | |
- | -import java.applet.AppletStub;
| + | |
- | -import java.applet.AudioClip;
| + | |
- | -
| + | |
- | import java.awt.GraphicsEnvironment;
| + | |
- | -import java.awt.Image;
| + | |
- |
| + | |
- | import java.beans.beancontext.BeanContext;
| + | |
- |
| + | |
- | @@ -43,17 +37,15 @@
| + | |
- | import java.io.ObjectStreamClass;
| + | |
- | import java.io.StreamCorruptedException;
| + | |
- |
| + | |
- | -import java.net.URL;
| + | |
- |
| + | |
- | import java.security.AccessController;
| + | |
- | import java.security.PrivilegedAction;
| + | |
- |
| + | |
- | -import java.util.Enumeration;
| + | |
- | -import java.util.Hashtable;
| + | |
- | import java.util.Iterator;
| + | |
- | -import java.util.Vector;
| + | |
- | +import java.util.ServiceLoader;
| + | |
- |
| + | |
- | import sun.awt.AppContext;
| + | |
- | +import sun.beans.AppletProxy;
| + | |
- |
| + | |
- | /**
| + | |
- | * This class provides some general purpose beans control methods.
| + | |
- | @@ -155,8 +147,14 @@
| + | |
- | * @exception IOException if an I/O error occurs.
| + | |
- | */
| + | |
- |
| + | |
- | - public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext, AppletInitializer initializer)
| + | |
- | - throws IOException, ClassNotFoundException {
| + | |
- | + public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext,
| + | |
- | + /** TBD: Oops , this is bad. The AppletInitializer is used from
| + | |
- | + * public API. I have not noticed that sooner. Opps.
| + | |
- | + AppletInitializer initializer
| + | |
- | + * meanwhile turning into object, but this cannot be final solution:
| + | |
- | + */
| + | |
- | + Object initializer
| + | |
- | + ) throws IOException, ClassNotFoundException {
| + | |
- |
| + | |
- | InputStream ins;
| + | |
- | ObjectInputStream oins = null;
| + | |
- | @@ -231,7 +229,7 @@
| + | |
- | * Try to instantiate the class.
| + | |
- | */
| + | |
- |
| + | |
- | - try {
| + | |
- | + try {
| + | |
- | result = cl.newInstance();
| + | |
- | } catch (Exception ex) {
| + | |
- | // We have to remap the exception to one in our signature.
| + | |
- | @@ -243,108 +241,13 @@
| + | |
- | if (result != null) {
| + | |
- |
| + | |
- | // Ok, if the result is an applet initialize it.
| + | |
- | -
| + | |
- | - AppletStub stub = null;
| + | |
- | -
| + | |
- | - if (result instanceof Applet) {
| + | |
- | - Applet applet = (Applet) result;
| + | |
- | - boolean needDummies = initializer == null;
| + | |
- | -
| + | |
- | - if (needDummies) {
| + | |
- | -
| + | |
- | - // Figure our the codebase and docbase URLs. We do this
| + | |
- | - // by locating the URL for a known resource, and then
| + | |
- | - // massaging the URL.
| + | |
- | -
| + | |
- | - // First find the "resource name" corresponding to the bean
| + | |
- | - // itself. So a serialzied bean "a.b.c" would imply a
| + | |
- | - // resource name of "a/b/c.ser" and a classname of "x.y"
| + | |
- | - // would imply a resource name of "x/y.class".
| + | |
- | -
| + | |
- | - final String resourceName;
| + | |
- | -
| + | |
- | - if (serialized) {
| + | |
- | - // Serialized bean
| + | |
- | - resourceName = beanName.replace('.','/').concat(".ser");
| + | |
- | - } else {
| + | |
- | - // Regular class
| + | |
- | - resourceName = beanName.replace('.','/').concat(".class");
| + | |
- | - }
| + | |
- | -
| + | |
- | - URL objectUrl = null;
| + | |
- | - URL codeBase = null;
| + | |
- | - URL docBase = null;
| + | |
- | -
| + | |
- | - // Now get the URL correponding to the resource name.
| + | |
- | -
| + | |
- | - final ClassLoader cloader = cls;
| + | |
- | - objectUrl = (URL)
| + | |
- | - AccessController.doPrivileged
| + | |
- | - (new PrivilegedAction() {
| + | |
- | - public Object run() {
| + | |
- | - if (cloader == null)
| + | |
- | - return ClassLoader.getSystemResource
| + | |
- | - (resourceName);
| + | |
- | - else
| + | |
- | - return cloader.getResource(resourceName);
| + | |
- | - }
| + | |
- | - });
| + | |
- | -
| + | |
- | - // If we found a URL, we try to locate the docbase by taking
| + | |
- | - // of the final path name component, and the code base by taking
| + | |
- | - // of the complete resourceName.
| + | |
- | - // So if we had a resourceName of "a/b/c.class" and we got an
| + | |
- | - // objectURL of "file://bert/classes/a/b/c.class" then we would
| + | |
- | - // want to set the codebase to "file://bert/classes/" and the
| + | |
- | - // docbase to "file://bert/classes/a/b/"
| + | |
- | -
| + | |
- | - if (objectUrl != null) {
| + | |
- | - String s = objectUrl.toExternalForm();
| + | |
- | -
| + | |
- | - if (s.endsWith(resourceName)) {
| + | |
- | - int ix = s.length() - resourceName.length();
| + | |
- | - codeBase = new URL(s.substring(0,ix));
| + | |
- | - docBase = codeBase;
| + | |
- | -
| + | |
- | - ix = s.lastIndexOf('/');
| + | |
- | -
| + | |
- | - if (ix >= 0) {
| + | |
- | - docBase = new URL(s.substring(0,ix+1));
| + | |
- | - }
| + | |
- | - }
| + | |
- | - }
| + | |
- | -
| + | |
- | - // Setup a default context and stub.
| + | |
- | - BeansAppletContext context = new BeansAppletContext(applet);
| + | |
- | -
| + | |
- | - stub = (AppletStub)new BeansAppletStub(applet, context, codeBase, docBase);
| + | |
- | - applet.setStub(stub);
| + | |
- | - } else {
| + | |
- | - initializer.initialize(applet, beanContext);
| + | |
- | - }
| + | |
- | -
| + | |
- | - // now, if there is a BeanContext, add the bean, if applicable.
| + | |
- | -
| + | |
- | - if (beanContext != null) {
| + | |
- | - beanContext.add(result);
| + | |
- | - }
| + | |
- | -
| + | |
- | - // If it was deserialized then it was already init-ed.
| + | |
- | - // Otherwise we need to initialize it.
| + | |
- | -
| + | |
- | - if (!serialized) {
| + | |
- | - // We need to set a reasonable initial size, as many
| + | |
- | - // applets are unhappy if they are started without
| + | |
- | - // having been explicitly sized.
| + | |
- | - applet.setSize(100,100);
| + | |
- | - applet.init();
| + | |
- | - }
| + | |
- | -
| + | |
- | - if (needDummies) {
| + | |
- | - ((BeansAppletStub)stub).active = true;
| + | |
- | - } else initializer.activate(applet);
| + | |
- | -
| + | |
- | - } else if (beanContext != null) beanContext.add(result);
| + | |
- | + Iterator<AppletProxy> it = ServiceLoader.load(AppletProxy.class).iterator();
| + | |
- | + AppletProxy ap = it.hasNext() ? it.next() : null;
| + | |
- | + if (ap != null || !ap.initialize(
| + | |
- | + result, initializer, serialized, beanName, beanContext, cls
| + | |
- | + )) {
| + | |
- | + if (beanContext != null) beanContext.add(result);
| + | |
- | + }
| + | |
- | }
| + | |
- |
| + | |
- | return result;
| + | |
- | @@ -504,134 +407,3 @@
| + | |
- | }
| + | |
- | }
| + | |
- |
| + | |
- | -/**
| + | |
- | - * Package private support class. This provides a default AppletContext
| + | |
- | - * for beans which are applets.
| + | |
- | - */
| + | |
- | -
| + | |
- | -class BeansAppletContext implements AppletContext {
| + | |
- | - Applet target;
| + | |
- | - Hashtable imageCache = new Hashtable();
| + | |
- | -
| + | |
- | - BeansAppletContext(Applet target) {
| + | |
- | - this.target = target;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public AudioClip getAudioClip(URL url) {
| + | |
- | - // We don't currently support audio clips in the Beans.instantiate
| + | |
- | - // applet context, unless by some luck there exists a URL content
| + | |
- | - // class that can generate an AudioClip from the audio URL.
| + | |
- | - try {
| + | |
- | - return (AudioClip) url.getContent();
| + | |
- | - } catch (Exception ex) {
| + | |
- | - return null;
| + | |
- | - }
| + | |
- | - }
| + | |
- | -
| + | |
- | - public synchronized Image getImage(URL url) {
| + | |
- | - Object o = imageCache.get(url);
| + | |
- | - if (o != null) {
| + | |
- | - return (Image)o;
| + | |
- | - }
| + | |
- | - try {
| + | |
- | - o = url.getContent();
| + | |
- | - if (o == null) {
| + | |
- | - return null;
| + | |
- | - }
| + | |
- | - if (o instanceof Image) {
| + | |
- | - imageCache.put(url, o);
| + | |
- | - return (Image) o;
| + | |
- | - }
| + | |
- | - // Otherwise it must be an ImageProducer.
| + | |
- | - Image img = target.createImage((java.awt.image.ImageProducer)o);
| + | |
- | - imageCache.put(url, img);
| + | |
- | - return img;
| + | |
- | -
| + | |
- | - } catch (Exception ex) {
| + | |
- | - return null;
| + | |
- | - }
| + | |
- | - }
| + | |
- | -
| + | |
- | - public Applet getApplet(String name) {
| + | |
- | - return null;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public Enumeration getApplets() {
| + | |
- | - Vector applets = new Vector();
| + | |
- | - applets.addElement(target);
| + | |
- | - return applets.elements();
| + | |
- | - }
| + | |
- | -
| + | |
- | - public void showDocument(URL url) {
| + | |
- | - // We do nothing.
| + | |
- | - }
| + | |
- | -
| + | |
- | - public void showDocument(URL url, String target) {
| + | |
- | - // We do nothing.
| + | |
- | - }
| + | |
- | -
| + | |
- | - public void showStatus(String status) {
| + | |
- | - // We do nothing.
| + | |
- | - }
| + | |
- | -
| + | |
- | - public void setStream(String key, InputStream stream)throws IOException{
| + | |
- | - // We do nothing.
| + | |
- | - }
| + | |
- | -
| + | |
- | - public InputStream getStream(String key){
| + | |
- | - // We do nothing.
| + | |
- | - return null;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public Iterator getStreamKeys(){
| + | |
- | - // We do nothing.
| + | |
- | - return null;
| + | |
- | - }
| + | |
- | -}
| + | |
- | -
| + | |
- | -/**
| + | |
- | - * Package private support class. This provides an AppletStub
| + | |
- | - * for beans which are applets.
| + | |
- | - */
| + | |
- | -class BeansAppletStub implements AppletStub {
| + | |
- | - transient boolean active;
| + | |
- | - transient Applet target;
| + | |
- | - transient AppletContext context;
| + | |
- | - transient URL codeBase;
| + | |
- | - transient URL docBase;
| + | |
- | -
| + | |
- | - BeansAppletStub(Applet target,
| + | |
- | - AppletContext context, URL codeBase,
| + | |
- | - URL docBase) {
| + | |
- | - this.target = target;
| + | |
- | - this.context = context;
| + | |
- | - this.codeBase = codeBase;
| + | |
- | - this.docBase = docBase;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public boolean isActive() {
| + | |
- | - return active;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public URL getDocumentBase() {
| + | |
- | - // use the root directory of the applet's class-loader
| + | |
- | - return docBase;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public URL getCodeBase() {
| + | |
- | - // use the directory where we found the class or serialized object.
| + | |
- | - return codeBase;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public String getParameter(String name) {
| + | |
- | - return null;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public AppletContext getAppletContext() {
| + | |
- | - return context;
| + | |
- | - }
| + | |
- | -
| + | |
- | - public void appletResize(int width, int height) {
| + | |
- | - // we do nothing.
| + | |
- | - }
| + | |
- | -}
| + | |
- | diff -r f72c0dc047b9 -r 57914fd9382f src/share/classes/java/beans/beancontext/BeanContextSupport.java | + | |
- | --- a/src/share/classes/java/beans/beancontext/BeanContextSupport.java Thu Jun 11 10:54:22 2009 -0700
| + | |
- | +++ b/src/share/classes/java/beans/beancontext/BeanContextSupport.java Tue Jun 16 17:53:32 2009 +0200
| + | |
- | @@ -29,16 +29,12 @@
| + | |
- | import java.awt.Container;
| + | |
- |
| + | |
- | import java.beans.Beans;
| + | |
- | -import java.beans.AppletInitializer;
| + | |
- |
| + | |
- | -import java.beans.DesignMode;
| + | |
- |
| + | |
- | import java.beans.PropertyChangeEvent;
| + | |
- | import java.beans.PropertyChangeListener;
| + | |
- | -import java.beans.PropertyChangeSupport;
| + | |
- |
| + | |
- | import java.beans.VetoableChangeListener;
| + | |
- | -import java.beans.VetoableChangeSupport;
| + | |
- | import java.beans.PropertyVetoException;
| + | |
- |
| + | |
- | import java.beans.Visibility;
| + | |
- | diff -r f72c0dc047b9 -r 57914fd9382f src/share/classes/sun/applet/BeansBridge.java
| + | |
- | --- /dev/null Thu Jan 01 00:00:00 1970 +0000
| + | |
- | +++ b/src/share/classes/sun/applet/BeansBridge.java Tue Jun 16 17:53:32 2009 +0200
| + | |
- | @@ -0,0 +1,298 @@
| + | |
- | +/*
| + | |
- | + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
| + | |
- | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
| + | |
- | + *
| + | |
- | + * This code is free software; you can redistribute it and/or modify it
| + | |
- | + * under the terms of the GNU General Public License version 2 only, as
| + | |
- | + * published by the Free Software Foundation. Sun designates this
| + | |
- | + * particular file as subject to the "Classpath" exception as provided
| + | |
- | + * by Sun in the LICENSE file that accompanied this code.
| + | |
- | + *
| + | |
- | + * This code is distributed in the hope that it will be useful, but WITHOUT
| + | |
- | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
| + | |
- | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
| + | |
- | + * version 2 for more details (a copy is included in the LICENSE file that
| + | |
- | + * accompanied this code).
| + | |
- | + *
| + | |
- | + * You should have received a copy of the GNU General Public License version
| + | |
- | + * 2 along with this work; if not, write to the Free Software Foundation,
| + | |
- | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
| + | |
- | + *
| + | |
- | + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
| + | |
- | + * CA 95054 USA or visit www.sun.com if you need additional information or
| + | |
- | + * have any questions.
| + | |
- | + */
| + | |
- | +
| + | |
- | +package sun.applet;
| + | |
- | +
| + | |
- | +import java.applet.Applet;
| + | |
- | +import java.applet.AppletContext;
| + | |
- | +import java.applet.AppletStub;
| + | |
- | +import java.applet.AudioClip;
| + | |
- | +import java.awt.Image;
| + | |
- | +import java.beans.AppletInitializer;
| + | |
- | +import java.beans.beancontext.BeanContext;
| + | |
- | +import java.io.IOException;
| + | |
- | +import java.io.InputStream;
| + | |
- | +import java.net.MalformedURLException;
| + | |
- | +import java.net.URL;
| + | |
- | +import java.security.AccessController;
| + | |
- | +import java.security.PrivilegedAction;
| + | |
- | +import java.util.Enumeration;
| + | |
- | +import java.util.Hashtable;
| + | |
- | +import java.util.Iterator;
| + | |
- | +import java.util.Vector;
| + | |
- | +import sun.beans.AppletProxy;
| + | |
- | +
| + | |
- | +/**
| + | |
- | + * Implementaiton of the bridge between
| + | |
- | + * java.beans module and java.applet module.
| + | |
- | + *
| + | |
- | + * @author Jaroslav Tulach
| + | |
- | + */
| + | |
- | +
| + | |
- | +public class BeansBridge extends AppletProxy {
| + | |
- | + public boolean initialize(
| + | |
- | + Object result, Object init, boolean serialized,
| + | |
- | + String beanName, BeanContext beanContext, ClassLoader cls
| + | |
- | + ) throws MalformedURLException {
| + | |
- | + if (!(result instanceof Applet)) {
| + | |
- | + return false;
| + | |
- | + }
| + | |
- | + AppletInitializer initializer = (AppletInitializer)init;
| + | |
- | +
| + | |
- | + AppletStub stub = null;
| + | |
- | + Applet applet = (Applet) result;
| + | |
- | + boolean needDummies = initializer == null;
| + | |
- | +
| + | |
- | + if (needDummies) {
| + | |
- | +
| + | |
- | + // Figure our the codebase and docbase URLs. We do this
| + | |
- | + // by locating the URL for a known resource, and then
| + | |
- | + // massaging the URL.
| + | |
- | +
| + | |
- | + // First find the "resource name" corresponding to the bean
| + | |
- | + // itself. So a serialzied bean "a.b.c" would imply a
| + | |
- | + // resource name of "a/b/c.ser" and a classname of "x.y"
| + | |
- | + // would imply a resource name of "x/y.class".
| + | |
- | +
| + | |
- | + final String resourceName;
| + | |
- | +
| + | |
- | + if (serialized) {
| + | |
- | + // Serialized bean
| + | |
- | + resourceName = beanName.replace('.', '/').concat(".ser");
| + | |
- | + } else {
| + | |
- | + // Regular class
| + | |
- | + resourceName = beanName.replace('.', '/').concat(".class");
| + | |
- | + }
| + | |
- | +
| + | |
- | + URL objectUrl = null;
| + | |
- | + URL codeBase = null;
| + | |
- | + URL docBase = null;
| + | |
- | +
| + | |
- | + // Now get the URL correponding to the resource name.
| + | |
- | +
| + | |
- | + final ClassLoader cloader = cls;
| + | |
- | + objectUrl = (URL) AccessController.doPrivileged(new PrivilegedAction() {
| + | |
- | +
| + | |
- | + public Object run() {
| + | |
- | + if (cloader == null) {
| + | |
- | + return ClassLoader.getSystemResource(resourceName);
| + | |
- | + } else {
| + | |
- | + return cloader.getResource(resourceName);
| + | |
- | + }
| + | |
- | + }
| + | |
- | + });
| + | |
- | +
| + | |
- | + // If we found a URL, we try to locate the docbase by taking
| + | |
- | + // of the final path name component, and the code base by taking
| + | |
- | + // of the complete resourceName.
| + | |
- | + // So if we had a resourceName of "a/b/c.class" and we got an
| + | |
- | + // objectURL of "file://bert/classes/a/b/c.class" then we would
| + | |
- | + // want to set the codebase to "file://bert/classes/" and the
| + | |
- | + // docbase to "file://bert/classes/a/b/"
| + | |
- | +
| + | |
- | + if (objectUrl != null) {
| + | |
- | + String s = objectUrl.toExternalForm();
| + | |
- | +
| + | |
- | + if (s.endsWith(resourceName)) {
| + | |
- | + int ix = s.length() - resourceName.length();
| + | |
- | + codeBase = new URL(s.substring(0, ix));
| + | |
- | + docBase = codeBase;
| + | |
- | +
| + | |
- | + ix = s.lastIndexOf('/');
| + | |
- | +
| + | |
- | + if (ix >= 0) {
| + | |
- | + docBase = new URL(s.substring(0, ix + 1));
| + | |
- | + }
| + | |
- | + }
| + | |
- | + }
| + | |
- | +
| + | |
- | + // Setup a default context and stub.
| + | |
- | + BeansAppletContext context = new BeansAppletContext(applet);
| + | |
- | +
| + | |
- | + stub = (AppletStub) new BeansAppletStub(applet, context, codeBase, docBase);
| + | |
- | + applet.setStub(stub);
| + | |
- | + } else {
| + | |
- | + initializer.initialize(applet, beanContext);
| + | |
- | + }
| + | |
- | +
| + | |
- | + // now, if there is a BeanContext, add the bean, if applicable.
| + | |
- | +
| + | |
- | + if (beanContext != null) {
| + | |
- | + beanContext.add(result);
| + | |
- | + }
| + | |
- | +
| + | |
- | + // If it was deserialized then it was already init-ed.
| + | |
- | + // Otherwise we need to initialize it.
| + | |
- | +
| + | |
- | + if (!serialized) {
| + | |
- | + // We need to set a reasonable initial size, as many
| + | |
- | + // applets are unhappy if they are started without
| + | |
- | + // having been explicitly sized.
| + | |
- | + applet.setSize(100, 100);
| + | |
- | + applet.init();
| + | |
- | + }
| + | |
- | +
| + | |
- | + if (needDummies) {
| + | |
- | + ((BeansAppletStub) stub).active = true;
| + | |
- | + } else {
| + | |
- | + initializer.activate(applet);
| + | |
- | + }
| + | |
- | +
| + | |
- | + return true;
| + | |
- | + }
| + | |
- | +}
| + | |
- | +
| + | |
- | +
| + | |
- | +/**
| + | |
- | + * Package private support class. This provides a default AppletContext
| + | |
- | + * for beans which are applets.
| + | |
- | + */
| + | |
- | +
| + | |
- | +class BeansAppletContext implements AppletContext {
| + | |
- | + Applet target;
| + | |
- | + Hashtable imageCache = new Hashtable();
| + | |
- | +
| + | |
- | + BeansAppletContext(Applet target) {
| + | |
- | + this.target = target;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public AudioClip getAudioClip(URL url) {
| + | |
- | + // We don't currently support audio clips in the Beans.instantiate
| + | |
- | + // applet context, unless by some luck there exists a URL content
| + | |
- | + // class that can generate an AudioClip from the audio URL.
| + | |
- | + try {
| + | |
- | + return (AudioClip) url.getContent();
| + | |
- | + } catch (Exception ex) {
| + | |
- | + return null;
| + | |
- | + }
| + | |
- | + }
| + | |
- | +
| + | |
- | + public synchronized Image getImage(URL url) {
| + | |
- | + Object o = imageCache.get(url);
| + | |
- | + if (o != null) {
| + | |
- | + return (Image)o;
| + | |
- | + }
| + | |
- | + try {
| + | |
- | + o = url.getContent();
| + | |
- | + if (o == null) {
| + | |
- | + return null;
| + | |
- | + }
| + | |
- | + if (o instanceof Image) {
| + | |
- | + imageCache.put(url, o);
| + | |
- | + return (Image) o;
| + | |
- | + }
| + | |
- | + // Otherwise it must be an ImageProducer.
| + | |
- | + Image img = target.createImage((java.awt.image.ImageProducer)o);
| + | |
- | + imageCache.put(url, img);
| + | |
- | + return img;
| + | |
- | +
| + | |
- | + } catch (Exception ex) {
| + | |
- | + return null;
| + | |
- | + }
| + | |
- | + }
| + | |
- | +
| + | |
- | + public Applet getApplet(String name) {
| + | |
- | + return null;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public Enumeration getApplets() {
| + | |
- | + Vector applets = new Vector();
| + | |
- | + applets.addElement(target);
| + | |
- | + return applets.elements();
| + | |
- | + }
| + | |
- | +
| + | |
- | + public void showDocument(URL url) {
| + | |
- | + // We do nothing.
| + | |
- | + }
| + | |
- | +
| + | |
- | + public void showDocument(URL url, String target) {
| + | |
- | + // We do nothing.
| + | |
- | + }
| + | |
- | +
| + | |
- | + public void showStatus(String status) {
| + | |
- | + // We do nothing.
| + | |
- | + }
| + | |
- | +
| + | |
- | + public void setStream(String key, InputStream stream)throws IOException{
| + | |
- | + // We do nothing.
| + | |
- | + }
| + | |
- | +
| + | |
- | + public InputStream getStream(String key){
| + | |
- | + // We do nothing.
| + | |
- | + return null;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public Iterator getStreamKeys(){
| + | |
- | + // We do nothing.
| + | |
- | + return null;
| + | |
- | + }
| + | |
- | +}
| + | |
- | +
| + | |
- | +/**
| + | |
- | + * Package private support class. This provides an AppletStub
| + | |
- | + * for beans which are applets.
| + | |
- | + */
| + | |
- | +class BeansAppletStub implements AppletStub {
| + | |
- | + transient boolean active;
| + | |
- | + transient Applet target;
| + | |
- | + transient AppletContext context;
| + | |
- | + transient URL codeBase;
| + | |
- | + transient URL docBase;
| + | |
- | +
| + | |
- | + BeansAppletStub(Applet target,
| + | |
- | + AppletContext context, URL codeBase,
| + | |
- | + URL docBase) {
| + | |
- | + this.target = target;
| + | |
- | + this.context = context;
| + | |
- | + this.codeBase = codeBase;
| + | |
- | + this.docBase = docBase;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public boolean isActive() {
| + | |
- | + return active;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public URL getDocumentBase() {
| + | |
- | + // use the root directory of the applet's class-loader
| + | |
- | + return docBase;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public URL getCodeBase() {
| + | |
- | + // use the directory where we found the class or serialized object.
| + | |
- | + return codeBase;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public String getParameter(String name) {
| + | |
- | + return null;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public AppletContext getAppletContext() {
| + | |
- | + return context;
| + | |
- | + }
| + | |
- | +
| + | |
- | + public void appletResize(int width, int height) {
| + | |
- | + // we do nothing.
| + | |
- | + }
| + | |
- | +}
| + | |
- | diff -r f72c0dc047b9 -r 57914fd9382f src/share/classes/sun/beans/AppletProxy.java
| + | |
- | --- /dev/null Thu Jan 01 00:00:00 1970 +0000
| + | |
- | +++ b/src/share/classes/sun/beans/AppletProxy.java Tue Jun 16 17:53:32 2009 +0200
| + | |
- | @@ -0,0 +1,42 @@
| + | |
- | +/*
| + | |
- | + * Copyright 1996-2009 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.beans;
| + | |
- | +
| + | |
- | +import java.beans.beancontext.BeanContext;
| + | |
- | +import java.net.MalformedURLException;
| + | |
- | +
| + | |
- | +
| + | |
- | +/**
| + | |
- | + * Bridge between java.beans module and java.applet module.
| + | |
- | + * @author Jaroslav Tulach
| + | |
- | + */
| + | |
- | +
| + | |
- | +public abstract class AppletProxy {
| + | |
- | + public abstract boolean initialize(
| + | |
- | + Object result, Object init, boolean serialized,
| + | |
- | + String beanName, BeanContext beanContext, ClassLoader cls
| + | |
- | + ) throws MalformedURLException;
| + | |
- | +}
| + | |
- | diff -r f72c0dc047b9 -r 57914fd9382f build.xml
| + | |
- | --- /dev/null Thu Jan 01 00:00:00 1970 +0000
| + | |
- | +++ b/build.xml Tue Jun 16 17:53:32 2009 +0200
| + | |
- | @@ -0,0 +1,131 @@
| + | |
- | +<?xml version="1.0" encoding="UTF-8"?>
| + | |
- | +<project name="modularize" default="all" basedir=".">
| + | |
- | + <description>Scripts to build JDK Java sources in modularized way</description>
| + | |
- | +
| + | |
- | + <target name="all">
| + | |
- | + <antcall target="base"/>
| + | |
- | + <antcall target="beans"/>
| + | |
- | + <antcall target="applet"/>
| + | |
- | + </target>
| + | |
- | + <!-- basic parameters -->
| + | |
- | + <path id="src.path">
| + | |
- | + <pathelement location="src/share/classes"/>
| + | |
- | + <pathelement location="src/windows/classes"/>
| + | |
- | + <pathelement location="src/solaris/classes"/>
| + | |
- | + </path>
| + | |
- | + <property name="build.dir" location="build/modularize"/>
| + | |
- | +
| + | |
- | + <!-- this is the core of the separation - definition
| + | |
- | + of what classes belong into what compilation group.
| + | |
- | + -->
| + | |
- | + <selector id="applet">
| + | |
- | + <or>
| + | |
- | + <filename name="java/beans/AppletInitializer*"/>
| + | |
- | + <filename name="java/applet/**"/>
| + | |
- | + <filename name="sun/applet/**"/>
| + | |
- | + <filename name="META-INF/services/sun.beans.AppletProxy"/>
| + | |
- | + </or>
| + | |
- | + </selector>
| + | |
- | + <selector id="beans">
| + | |
- | + <and>
| + | |
- | + <or>
| + | |
- | + <filename name="java/beans/**"/>
| + | |
- | + <filename name="sun/beans/**"/>
| + | |
- | + <filename name="com/sun/beans/**"/>
| + | |
- | + </or>
| + | |
- | + <none>
| + | |
- | + <selector refid="applet"/>
| + | |
- | + </none>
| + | |
- | + </and>
| + | |
- | + </selector>
| + | |
- | +
| + | |
- | + <selector id="corba">
| + | |
- | + <or>
| + | |
- | + <filename name="org/omg/**"/>
| + | |
- | + <filename name="com/sun/corba/**"/>
| + | |
- | + </or>
| + | |
- | + </selector>
| + | |
- | +
| + | |
- | + <selector id="base">
| + | |
- | + <none>
| + | |
- | + <selector refid="applet"/>
| + | |
- | + <selector refid="beans"/>
| + | |
- | + <selector refid="corba"/>
| + | |
- | + </none>
| + | |
- | + </selector>
| + | |
- | +
| + | |
- | + <!-- individual compilation tasks -->
| + | |
- | +
| + | |
- | + <target name="applet">
| + | |
- | + <antcall target="-compile-one-module">
| + | |
- | + <param name="module" value="applet"/>
| + | |
- | + <param name="depends" value="beans"/>
| + | |
- | + </antcall>
| + | |
- | + </target>
| + | |
- | + <target name="beans">
| + | |
- | + <antcall target="-compile-one-module">
| + | |
- | + <param name="module" value="beans"/>
| + | |
- | + </antcall>
| + | |
- | + </target>
| + | |
- | +
| + | |
- | +
| + | |
- | + <!-- as I am currently unable to build JDK myself, I'll start
| + | |
- | + the modularization by extracting the base module from an existing
| + | |
- | + classes
| + | |
- | + -->
| + | |
- | + <target name="base">
| + | |
- | + <property name="rt.jar" location="${java.home}/lib/rt.jar"/>
| + | |
- | + <fail message="Cannot find rt.jar, specify with -Drt.jar=...">
| + | |
- | + <condition><not><available file="${rt.jar}"/></not></condition>
| + | |
- | + </fail>
| + | |
- | +
| + | |
- | + <mkdir dir="${build.dir}/rt"/>
| + | |
- | + <unzip src="${rt.jar}" dest="${build.dir}/rt"/>
| + | |
- | + <jar file="${build.dir}/base.jar" compress="false">
| + | |
- | + <fileset dir="${build.dir}/rt">
| + | |
- | + <selector refid="base"/>
| + | |
- | + </fileset>
| + | |
- | + </jar>
| + | |
- | + </target>
| + | |
- | +
| + | |
- | + <!-- shared routine to compile one of the modules -->
| + | |
- | + <target name="-compile-one-module">
| + | |
- | + <mkdir dir="${build.dir}/classes/${module}"/>
| + | |
- | + <pathconvert pathsep="," property="module.cp">
| + | |
- | + <path path="${depends}"/>
| + | |
- | + <mapper type="regexp" from=".*[/\\]([^/\\]*)" to="${build.dir}/\1.jar"/>
| + | |
- | + </pathconvert>
| + | |
- | + <javac
| + | |
- | + bootclasspath="${build.dir}/base.jar"
| + | |
- | + sourcepath=""
| + | |
- | + destdir="${build.dir}/classes/${module}"
| + | |
- | + classpath="${module.cp}"
| + | |
- | + includejavaruntime="false"
| + | |
- | + includeantruntime="false"
| + | |
- | + >
| + | |
- | + <src refid="src.path"/>
| + | |
- | + <selector refid="${module}"/>
| + | |
- | + </javac>
| + | |
- | + <copy todir="${build.dir}/classes/${module}">
| + | |
- | + <fileset dir="src/share/classes">
| + | |
- | + <and>
| + | |
- | + <selector refid="${module}"/>
| + | |
- | + <not>
| + | |
- | + <filename name="**/*.java"/>
| + | |
- | + </not>
| + | |
- | + </and>
| + | |
- | + </fileset>
| + | |
- | + </copy>
| + | |
- | +
| + | |
- | + <jar
| + | |
- | + basedir="${build.dir}/classes/${module}"
| + | |
- | + destfile="${build.dir}/${module}.jar"
| + | |
- | + compress="false"
| + | |
- | + />
| + | |
- | + </target>
| + | |
- | +
| + | |
- | + <!-- clean everything -->
| + | |
- | + <target name="clean">
| + | |
- | + <delete dir="${build.dir}"/>
| + | |
- | + </target>
| + | |
- | +</project>
| + | |
- | </source>
| + | |
| | | |
| The | | The |
I like puzzles that tease my mind (a bit). Last week I've been introduced to one. Modularize JDK (a described at Mark Reinhold's blog). This page will capture my thoughts on this topic.
Sometimes people expect to get better performance just by modularizing their application. This is probably a false expectation, at least in the initial step.
Modularization really pays off (we can easily deprecate obsoleted modules and make the system smaller), but it may take a little while. If you are seeking immediate improvements in terms of ms spend while loading a Hello World! application, you'd better refactor your code and classes. Modularization is not going to help you. Modularization is for those who seek long term improvements in deployment, ability to deprecate and more rapidly evolve the framework.
What is the foremost check to ensure your code is split into pieces? Well, each piece needs to compile separately. Thus, before modularization, I tweak the build infrastructure to make sure it really compiles the pieces and not everything at once.
To do this, you very likely don't want to mangle with location of your sources in your version control system. This would be premature, as the final division of the units is not yet know and your version history would be full of useless moves and renames. Luckily Ant offers powerful enough way to define sets of files and feed them into the compiler.
Please note that the selectors are referring to each other. The beans group explicitly says it wants nothing from the applet group and the base group is solitelly defined as everything not included in the previous groups.
With infrastructure like this one, you can start splitting your project apart.
The
idea is that when the applet module is not installed, there is no
AppletProxy provider meaning that the application would not reference
any types in the applet module. When the applet module is installed, it
will install the provider and update
META-INF/services/sun.beans.AppletProxy and thereafter the service
loader will find it.