harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ton...@apache.org
Subject svn commit: r548684 [1/3] - in /harmony/enhanced/classlib/branches/java6/modules: awt/make/ awt/src/main/native/fontlib/shared/ beans/src/main/java/java/beans/beancontext/ beans/src/main/java/org/apache/harmony/beans/internal/nls/ jndi/META-INF/ jndi/s...
Date Tue, 19 Jun 2007 10:37:07 GMT
Author: tonywu
Date: Tue Jun 19 03:37:02 2007
New Revision: 548684

URL: http://svn.apache.org/viewvc?view=rev&rev=548684
Log:
Merge updates from classlib trunk@548679 since 548383

Added:
    harmony/enhanced/classlib/branches/java6/modules/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
      - copied unchanged from r548679, harmony/enhanced/classlib/trunk/modules/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
    harmony/enhanced/classlib/branches/java6/modules/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.golden.ser
      - copied unchanged from r548679, harmony/enhanced/classlib/trunk/modules/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.golden.ser
Modified:
    harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.linux.x86_64.drl
    harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.windows.x86_64.drl
    harmony/enhanced/classlib/branches/java6/modules/awt/src/main/native/fontlib/shared/TypeDefinition.cpp
    harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextChildSupport.java
    harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextMembershipEvent.java
    harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServiceRevokedEvent.java
    harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServicesSupport.java
    harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextSupport.java
    harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/org/apache/harmony/beans/internal/nls/messages.properties
    harmony/enhanced/classlib/branches/java6/modules/jndi/META-INF/MANIFEST.MF
    harmony/enhanced/classlib/branches/java6/modules/jndi/src/main/java/javax/naming/ldap/Rdn.java
    harmony/enhanced/classlib/branches/java6/modules/jndi/src/test/java/org/apache/harmony/jndi/tests/javax/naming/ldap/RdnTest.java
    harmony/enhanced/classlib/branches/java6/modules/luni/.classpath
    harmony/enhanced/classlib/branches/java6/modules/luni/src/main/java/java/util/BitSet.java
    harmony/enhanced/classlib/branches/java6/modules/luni/src/main/native/launcher/shared/main.c
    harmony/enhanced/classlib/branches/java6/modules/luni/src/main/native/launcher/windows/java.rc
    harmony/enhanced/classlib/branches/java6/modules/luni/src/main/native/launcher/windows/javaw.rc
    harmony/enhanced/classlib/branches/java6/modules/luni/src/main/native/luni/windows/hyluni.rc
    harmony/enhanced/classlib/branches/java6/modules/luni/src/main/native/vmi/windows/vmi.rc
    harmony/enhanced/classlib/branches/java6/modules/luni/src/test/api/common/tests/api/java/util/BitSetTest.java
    harmony/enhanced/classlib/branches/java6/modules/misc/src/main/native/accessors/windows/accessors.rc
    harmony/enhanced/classlib/branches/java6/modules/portlib/src/main/native/port/windows/hyprt.rc
    harmony/enhanced/classlib/branches/java6/modules/portlib/src/main/native/sig/windows/hysig.rc
    harmony/enhanced/classlib/branches/java6/modules/portlib/src/main/native/sig/windows/makefile
    harmony/enhanced/classlib/branches/java6/modules/portlib/src/main/native/thread/windows/hythr.rc
    harmony/enhanced/classlib/branches/java6/modules/portlib/src/main/native/thrstub/windows/hythr.rc
    harmony/enhanced/classlib/branches/java6/modules/prefs/src/main/native/prefs/windows/hyprefs.rc
    harmony/enhanced/classlib/branches/java6/modules/security/src/main/java/common/java/security/KeyStore.java
    harmony/enhanced/classlib/branches/java6/modules/security/src/main/java/common/java/security/UnresolvedPermission.java
    harmony/enhanced/classlib/branches/java6/modules/security/src/main/java/common/org/apache/harmony/security/fortress/DefaultPolicyParser.java
    harmony/enhanced/classlib/branches/java6/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/KeyStore3Test.java
    harmony/enhanced/classlib/branches/java6/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
    harmony/enhanced/classlib/branches/java6/modules/security/src/test/impl/java/org/apache/harmony/security/tests/java/security/KeyStore_Impl3Test.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/main/java/java/sql/DriverManager.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/main/java/javax/sql/ConnectionEvent.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/main/java/javax/sql/rowset/BaseRowSet.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/main/java/javax/sql/rowset/serial/DefaultUDTMap.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/main/java/javax/sql/rowset/serial/SerialArray.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/main/java/javax/sql/rowset/serial/SerialClob.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/main/java/javax/sql/rowset/spi/ProviderImpl.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/main/java/javax/sql/rowset/spi/SyncFactory.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/rowset/BaseRowSetTest.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/rowset/serial/SerialArrayTest.java
    harmony/enhanced/classlib/branches/java6/modules/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/rowset/serial/SerialClobTest.java
    harmony/enhanced/classlib/branches/java6/modules/swing/src/test/api/java.injected/org/apache/harmony/swing/tests/javax/swing/text/parser/ContentModelSemanticTest.java

Modified: harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.linux.x86_64.drl
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.linux.x86_64.drl?view=diff&rev=548684&r1=548683&r2=548684
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.linux.x86_64.drl (original)
+++ harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.linux.x86_64.drl Tue Jun 19 03:37:02 2007
@@ -13,3 +13,6 @@
 java/awt/font/LineBreakMeasurerTest.java
 java/awt/ButtonRTest.java
 java/awt/KeyboardFocusManagerRTest.java
+
+#HARMONY-4181
+java/awt/geom/AreaTest.java

Modified: harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.windows.x86_64.drl
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.windows.x86_64.drl?view=diff&rev=548684&r1=548683&r2=548684
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.windows.x86_64.drl (original)
+++ harmony/enhanced/classlib/branches/java6/modules/awt/make/exclude.windows.x86_64.drl Tue Jun 19 03:37:02 2007
@@ -1,3 +1,4 @@
+# see HARMONY-3483
 java/awt/BasicStrokeTest.java
 java/awt/ButtonRTest.java
 java/awt/font/TextLayoutTest.java
@@ -11,3 +12,6 @@
 java/awt/image/SinglePixelPackedSampleModelTest.java
 org/apache/harmony/awt/gl/MultiRectAreaLineCashTest.java
 org/apache/harmony/awt/tests/nativebridge/PointerPointerTest.java
+
+#HARMONY-4181
+java/awt/geom/AreaTest.java

Modified: harmony/enhanced/classlib/branches/java6/modules/awt/src/main/native/fontlib/shared/TypeDefinition.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/awt/src/main/native/fontlib/shared/TypeDefinition.cpp?view=diff&rev=548684&r1=548683&r2=548684
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/awt/src/main/native/fontlib/shared/TypeDefinition.cpp (original)
+++ harmony/enhanced/classlib/branches/java6/modules/awt/src/main/native/fontlib/shared/TypeDefinition.cpp Tue Jun 19 03:37:02 2007
@@ -2,6 +2,9 @@
 
 fint fwcslen(fwchar_t* str)
 {
+    if (!str)
+        return 0;
+        
 	fint counter=0;
 	fwchar_t* tmpstr = str;
 	while(*tmpstr != 0)
@@ -14,6 +17,9 @@
 
 fint fwcscmp(fwchar_t* str1, fwchar_t* str2)
 {
+    if (str1 == 0 || str2 == 0)
+        return str1 - str2;
+        
 	fwchar_t* tmpstr1 = str1; 
 	fwchar_t* tmpstr2 = str2;
 	while(*tmpstr1 != 0 || *tmpstr2 !=0)

Modified: harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextChildSupport.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextChildSupport.java?view=diff&rev=548684&r1=548683&r2=548684
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextChildSupport.java (original)
+++ harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextChildSupport.java Tue Jun 19 03:37:02 2007
@@ -46,6 +46,8 @@
     protected transient boolean rejectedSetBCOnce;
 
     protected VetoableChangeSupport vcSupport;
+    
+    private transient BeanContext lastVetoedContext;
 
     public BeanContextChildSupport() {
         // This class implements the JavaBean component itself
@@ -81,6 +83,7 @@
         }
 
         this.vcSupport.addVetoableChangeListener(name, vcl);
+        this.lastVetoedContext = null;
     }
 
     public void firePropertyChange(String name, Object oldValue, Object newValue) {
@@ -127,6 +130,7 @@
             VetoableChangeListener vcl) {
 
         this.vcSupport.removeVetoableChangeListener(name, vcl);
+        this.lastVetoedContext = null;
     }
 
     public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) {
@@ -158,22 +162,23 @@
        
         
 
+        
         // Children are not allowed to repeatedly veto this operation.
         // So, we set rejectedSetBCOnce flag to true if veto occurs
         // and never veto the change again
-        if (!this.rejectedSetBCOnce) {
-
+        if (!(this.rejectedSetBCOnce && this.lastVetoedContext == bc)) {
+            this.lastVetoedContext = bc;
             this.rejectedSetBCOnce = true;
             // Validate the new BeanContext value and throw
             // PropertyVetoException if it was not successful
-            if (!validatePendingSetBeanContext(bc)) {
-                
-
+            if (!validatePendingSetBeanContext(bc)) {                
                 throw new PropertyVetoException(Messages.getString("beans.0F"), //$NON-NLS-1$
                         new PropertyChangeEvent(this.beanContextChildPeer,
                                 BEAN_CONTEXT, this.beanContext, bc));
             }
             fireVetoableChange(BEAN_CONTEXT, this.beanContext, bc);
+        }
+            
             this.rejectedSetBCOnce = false;
             
             releaseBeanContextResources();
@@ -183,7 +188,7 @@
             firePropertyChange(BEAN_CONTEXT, this.beanContext, bc);
             this.beanContext = bc;
             initializeBeanContextResources();
-        }
+        //}
     }
 
     public boolean validatePendingSetBeanContext(BeanContext newValue) {

Modified: harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextMembershipEvent.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextMembershipEvent.java?view=diff&rev=548684&r1=548683&r2=548684
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextMembershipEvent.java (original)
+++ harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextMembershipEvent.java Tue Jun 19 03:37:02 2007
@@ -17,9 +17,9 @@
 
 package java.beans.beancontext;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
-import java.util.Vector;
 
 import org.apache.harmony.beans.internal.nls.Messages;
 @SuppressWarnings("unchecked")
@@ -47,11 +47,7 @@
         }
 
         // Initialize collection
-        this.children = new Vector<Object>();
-
-        for (Object element : changes) {
-            this.children.add(element);
-        }
+        this.children = Arrays.asList(changes);
     }
 
     public boolean contains(Object child) {

Modified: harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServiceRevokedEvent.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServiceRevokedEvent.java?view=diff&rev=548684&r1=548683&r2=548684
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServiceRevokedEvent.java (original)
+++ harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServiceRevokedEvent.java Tue Jun 19 03:37:02 2007
@@ -52,10 +52,7 @@
         return this.invalidateRefs;
     }
 
-    public boolean isServiceClass(Class service) {
-        if (service == null) {
-            return false;
-        }
-        return service.equals(this.serviceClass);
+    public boolean isServiceClass(Class service) {        
+        return serviceClass.equals(service);
     }
 }

Modified: harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServicesSupport.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServicesSupport.java?view=diff&rev=548684&r1=548683&r2=548684
==============================================================================
--- harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServicesSupport.java (original)
+++ harmony/enhanced/classlib/branches/java6/modules/beans/src/main/java/java/beans/beancontext/BeanContextServicesSupport.java Tue Jun 19 03:37:02 2007
@@ -26,559 +26,971 @@
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.TooManyListenersException;
+import java.util.Map.Entry;
 
 import org.apache.harmony.beans.internal.nls.Messages;
-@SuppressWarnings("unchecked")
+
+/**
+ * This support class implements <code>BeanContextServices</code> interface. 
+ * This class can be used directly, or be a super class of your class,
+ * or be a delegate of your implementation that needs to support 
+ * <code>BeanContextServices</code> interface.
+ * 
+ */
 public class BeanContextServicesSupport extends BeanContextSupport implements
-        BeanContextServices {
+        BeanContextServices, Serializable {
+
+    private static class ServiceRecord {
+
+        BeanContextServiceProvider provider;
+
+        BeanContextChild child;
+
+        Object requestor;
+
+        Class serviceClass;
+
+        BeanContextServiceRevokedListener revokedListener;
+
+        Object service;
 
-    private static final long serialVersionUID = -8494482757288719206L;
+        boolean isDelegate;
+
+        ServiceRecord(BeanContextServiceProvider provider,
+                BeanContextChild child, Object requestor, Class serviceClass,
+                BeanContextServiceRevokedListener revokedListener,
+                Object service, boolean isDelegate) {
+            this.provider = provider;
+            this.child = child;
+            this.requestor = requestor;
+            this.serviceClass = serviceClass;
+            this.revokedListener = revokedListener;
+            this.service = service;
+            this.isDelegate = isDelegate;
+        }
+    }
 
     /**
-     * Nested class
+     * Every child of context is companied with a <code>BCSSChild</code>
+     * instance. It can hold implementation specific information about
+     * each child.
+     * <p>
+     * This class keeps records of all services requests submitted by
+     * this child.</p>
+     * 
      */
     protected class BCSSChild extends BeanContextSupport.BCSChild {
 
-        private static final long serialVersionUID = -3263851306889194873L;
+    	private static final long serialVersionUID = -3263851306889194873L;
 
-        BCSSChild(Object child, Object peer) {
-            super(child, peer);
+        transient ArrayList serviceRecords;
+
+        BCSSChild(Object child, Object proxyPeer) {
+            super(child, proxyPeer);
         }
+
     }
 
     /**
-     * Nested class
+     * This class implements the <code>BeanContextServiceProvider</code> 
+     * interface by wrapping a <code>BeanContextServices</code>. All services
+     * registered in the <code>BeanContextServices</code> are accessible 
+     * via this wrapper service provider.
+     * <p>
+     * This class is used by <code>BeanContextServicesSupport</code> to access
+     * services provided by its parent context (if there is one).</p>
+     * 
      */
     protected class BCSSProxyServiceProvider implements
             BeanContextServiceProvider, BeanContextServiceRevokedListener {
 
-        /**
-         * The peer of this object
-         */
-        private BeanContextChild child;
+        private BeanContextServices backBCS;
 
-        /**
-         * Initialize the peer
-         * 
-         * @param child -
-         *            The peer to initialize with
-         */
-        BCSSProxyServiceProvider(BeanContextChild child) {
-            this.child = child;
+        BCSSProxyServiceProvider(BeanContextServices backBCS) {
+            this.backBCS = backBCS;
         }
 
+        /**
+         * Throws <code>UnsupportedOperationException</code>.
+         */
         public Iterator getCurrentServiceSelectors(BeanContextServices bcs,
                 Class serviceClass) {
-
-            return bcs.getCurrentServiceSelectors(serviceClass);
+            throw new UnsupportedOperationException();
         }
 
+        /**
+         * Throws <code>UnsupportedOperationException</code>.
+         */
         public Object getService(BeanContextServices bcs, Object requestor,
                 Class serviceClass, Object serviceSelector) {
+            throw new UnsupportedOperationException();
+        }
 
-            try {
-                BeanContextServiceRevokedListener l = this;
-                return bcs.getService(this.child, requestor, serviceClass,
-                        serviceSelector, l);
-            } catch (TooManyListenersException e) {
-                return null;
-            }
+        /**
+         * Delegate to the wrapped <code>BeanContextServices</code>.
+         */
+        public Object getService(BeanContextServices bcs, Object requestor,
+                Class serviceClass, Object serviceSelector,
+                BeanContextServiceRevokedListener listener)
+                throws TooManyListenersException {
+            return backBCS.getService(BeanContextServicesSupport.this
+                    .getBeanContextServicesPeer(), requestor, serviceClass,
+                    serviceSelector, new ServiceRevokedListenerDelegator(
+                            listener));
         }
 
+        /**
+         * Delegate to the wrapped <code>BeanContextServices</code>.
+         */
         public void releaseService(BeanContextServices bcs, Object requestor,
                 Object service) {
-
-            bcs.releaseService(this.child, requestor, service);
+            backBCS.releaseService(BeanContextServicesSupport.this
+                    .getBeanContextServicesPeer(), requestor, service);
         }
 
+        /**
+         * Throws <code>UnsupportedOperationException</code>.
+         */
         public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
+            throw new UnsupportedOperationException();
+        }
 
-            if (this.child instanceof BeanContextServices) {
-                BeanContextServices ser = (BeanContextServices) this.child;
-                ser.serviceRevoked(bcsre);
-            }
+    }
+
+    private class ServiceRevokedListenerDelegator implements
+            BeanContextServiceRevokedListener {
+
+        private BeanContextServiceRevokedListener backListener;
+
+        public ServiceRevokedListenerDelegator(
+                BeanContextServiceRevokedListener backListener) {
+            this.backListener = backListener;
+        }
+
+        public void serviceRevoked(BeanContextServiceRevokedEvent event) {
+            backListener.serviceRevoked(new BeanContextServiceRevokedEvent(
+                    BeanContextServicesSupport.this
+                            .getBeanContextServicesPeer(), event
+                            .getServiceClass(), event
+                            .isCurrentServiceInvalidNow()));
         }
+
     }
 
     /**
-     * Nested class
+     * Every servie registered in this context is companied with a 
+     * <code>BCSSServiceProvider</code> instance. It can hold implementation 
+     * specific information about each registered service.
+     * <p>
+     * This class holds a reference to the service provider of the service.</p>
+     * 
      */
     protected static class BCSSServiceProvider implements Serializable {
 
-        private static final long serialVersionUID = 861278251667444782L;
+        static final long serialVersionUID = 861278251667444782L;
 
         /**
-         * @serial
+         * The service provider of the related service.
          */
         protected BeanContextServiceProvider serviceProvider;
 
-        /**
-         * Service class
-         */
-        private transient Class sc;
+        BCSSServiceProvider(BeanContextServiceProvider provider) {
+            this.serviceProvider = provider;
+        }
 
         /**
-         * Constructor for setting BeanContextServiceProvider in this class
+         * Returns the service provider of the related service.
          * 
-         * @param sc -
-         *            service class
-         * @param serviceProvider -
-         *            service provider
+         * @return the service provider of the related service
          */
-        BCSSServiceProvider(Class sc, BeanContextServiceProvider serviceProvider) {
-            this.sc = sc;
-            this.serviceProvider = serviceProvider;
-        }
-
         protected BeanContextServiceProvider getServiceProvider() {
-            return this.serviceProvider;
+            return serviceProvider;
         }
 
-        Class getServiceClass() {
-            return this.sc;
-        }
     }
 
-    protected transient ArrayList bcsListeners;
+    static final long serialVersionUID = -8494482757288719206L;
 
-    protected transient BCSSProxyServiceProvider proxy;
+    /**
+     * A map of all registered services - key is service class, value is 
+     * <code>BCSSServiceProvider</code> object.
+     * All access to this object should be synchronized on itself.
+     */
+    protected transient HashMap services;
 
+    /**
+     * The number of serializable service providers currently registered.
+     */
     protected transient int serializable;
 
-    protected transient HashMap services;
+    /**
+     * A proxy service provider that delegates service requests to the 
+     * parent context.
+     */
+    protected transient BCSSProxyServiceProvider proxy;
+
+    /**
+     * A list of registered <code>BeanContextServicesListener</code>s.
+     * All access to this object should be synchronized on itself.
+     */
+    protected transient ArrayList bcsListeners;
 
+    /**
+     * Constructs a standload <code>BeanContextServicesSupport</code>.
+     */
     public BeanContextServicesSupport() {
         super();
     }
 
+    /**
+     * Constructs a <code>BeanContextServicesSupport</code> which is a delegate
+     * of the given peer.
+     * 
+     * @param peer  the peer of this context
+     */
     public BeanContextServicesSupport(BeanContextServices peer) {
         super(peer);
     }
 
-    public BeanContextServicesSupport(BeanContextServices peer, Locale lcle) {
-        super(peer, lcle);
+    /**
+     * Constructs a <code>BeanContextServicesSupport</code> which is a delegate
+     * of the given peer.
+     * 
+     * @param peer      the peer of this context
+     * @param locale    the locale of this context
+     */
+    public BeanContextServicesSupport(BeanContextServices peer, Locale locale) {
+        super(peer, locale);
     }
 
-    public BeanContextServicesSupport(BeanContextServices peer, Locale lcle,
-            boolean dtime) {
-
-        super(peer, lcle, dtime);
+    /**
+     * Constructs a <code>BeanContextServicesSupport</code> which is a delegate
+     * of the given peer.
+     * 
+     * @param peer          the peer of this context
+     * @param locale        the locale of this context
+     * @param designTime    whether in design mode or not
+     */
+    public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
+            boolean designTime) {
+        super(peer, locale, designTime);
     }
 
-    public BeanContextServicesSupport(BeanContextServices peer, Locale lcle,
-            boolean dtime, boolean visible) {
-
-        super(peer, lcle, dtime, visible);
+    /**
+     * Constructs a <code>BeanContextServicesSupport</code> which is a delegate
+     * of the given peer.
+     * 
+     * @param peer          the peer of this context
+     * @param locale        the locale of this context
+     * @param designTime    whether in design mode or not
+     * @param okToUseGui    whether GUI is usable or not
+     */
+    public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
+            boolean designTime, boolean okToUseGui) {
+        super(peer, locale, designTime, okToUseGui);
     }
 
-    public void addBeanContextServicesListener(BeanContextServicesListener bcsl) {
-
-        if (bcsl == null) {
-            throw new NullPointerException(Messages.getString("beans.15")); //$NON-NLS-1$
+    /* (non-Javadoc)
+     * @see java.beans.beancontext.BeanContextServices#addBeanContextServicesListener(java.beans.beancontext.BeanContextServicesListener)
+     */
+    public void addBeanContextServicesListener(
+            BeanContextServicesListener listener) {
+        if (listener == null) {
+            throw new NullPointerException();
         }
-
-        synchronized (this.bcsListeners) {
-            this.bcsListeners.add(bcsl);
+        synchronized (bcsListeners) {
+            bcsListeners.add(listener);
         }
     }
 
+    /**
+     * Add a service to this context.
+     * <p>
+     * Delegate to <code>addService(serviceClass, provider, true)</code>.</p>
+     * 
+     * @see java.beans.beancontext.BeanContextServices#addService(java.lang.Class, java.beans.beancontext.BeanContextServiceProvider)
+     */
     public boolean addService(Class serviceClass,
-            BeanContextServiceProvider bcsp) {
-
-        return addService(serviceClass, bcsp, true);
+            BeanContextServiceProvider provider) {
+        return addService(serviceClass, provider, true);
     }
 
+    /**
+     * Add a service to this context.
+     * <p>
+     * If the service already exists in the context, simply return false.
+     * Otherwise, the service is added and event is fired if required.</p>
+     * 
+     * @param serviceClass  the service class
+     * @param provider      the provider of the service
+     * @param fireEvent     the flag indicating to fire event or not
+     * @return true if the service is added; or false if the context already has this service
+     */
     protected boolean addService(Class serviceClass,
-            BeanContextServiceProvider bcsp, boolean fireEvent) {
-
-        if (bcsp == null) {
-            throw new NullPointerException(Messages.getString("beans.16")); //$NON-NLS-1$
+            BeanContextServiceProvider provider, boolean fireEvent) {
+        if (serviceClass == null || provider == null) {
+            throw new NullPointerException();
         }
-        
-        boolean added = false;
 
-        synchronized (BeanContext.globalHierarchyLock) {
-            synchronized (this.services) {
-                if (!this.services.containsKey(serviceClass)) {
-                    this.services.put(serviceClass, createBCSSServiceProvider(
-                            serviceClass, bcsp));
-
-                    if (getChildSerializable(bcsp) != null) {
-                        this.serializable++;
-                    }
-                    added = true;
-                } 
+        synchronized (globalHierarchyLock) {
+            synchronized (services) {
+                if (services.containsKey(serviceClass)) {
+                    return false;
+                }
+                // add to services
+                services.put(serviceClass, createBCSSServiceProvider(
+                        serviceClass, provider));
+                // count Serializable
+                if (provider instanceof Serializable) {
+                    serializable++;
+                }
             }
+        }
 
-            BeanContextServiceAvailableEvent ev = getEvent(serviceClass);
+        if (fireEvent) {
+            // notify all listeners and BeanContextServices children
+            notifyServiceAvailable(new BeanContextServiceAvailableEvent(this,
+                    serviceClass));
+        }
+        return true;
+    }
 
-            if (added && fireEvent) {
-                fireServiceAdded(ev);
-                for (Iterator it = iterator(); it.hasNext();) {
-                    Object child = it.next();
-                    if (child instanceof BeanContextServices) {
-                        ((BeanContextServices) child).serviceAvailable(ev);
-                    }
-                }
+    private void notifyServiceAvailable(BeanContextServiceAvailableEvent event) {
+        fireServiceAdded(event);
+        Object childs[] = copyChildren();
+        for (int i = 0; i < childs.length; i++) {
+            if (childs[i] instanceof BeanContextServices) {
+                ((BeanContextServices) childs[i]).serviceAvailable(event);
             }
-            return added;
         }
     }
 
-    @Override
-    protected synchronized void bcsPreDeserializationHook(ObjectInputStream ois)
+    /**
+     * Deserializes all serializable services and their providers
+     * before the children of this context is deserialized.
+     * <p>
+     * First a <code>int</code> is read, indicating the number of services to
+     * read. Then pairs of service class and service provider are read one
+     * by one.</p>
+     * 
+     * @see java.beans.beancontext.BeanContextSupport#bcsPreDeserializationHook(java.io.ObjectInputStream)
+     */
+    protected void bcsPreDeserializationHook(ObjectInputStream ois)
             throws IOException, ClassNotFoundException {
+        super.bcsPreDeserializationHook(ois);
 
-        synchronized (this.services) {
-            for (int i = 0; i < this.serializable; i++) {
-                BCSSServiceProvider provider = (BCSSServiceProvider) ois
-                        .readObject();
-                this.services.put(provider.getClass(), provider);
+        // deserialize services
+        synchronized (services) {
+            serializable = ois.readInt();
+            for (int i = 0; i < serializable; i++) {
+                Object serviceClass = ois.readObject();
+                Object bcssProvider = ois.readObject();
+                services.put(serviceClass, bcssProvider);
             }
         }
     }
 
-    @Override
-    protected synchronized void bcsPreSerializationHook(ObjectOutputStream oos)
+    /**
+     * Serializes all serializable services and their providers
+     * before the children of this context is serialized.
+     * <p>
+     * First a <code>int</code> is writtern, indicating the number of 
+     * serializable services. Then pairs of service class and service 
+     * provider are writtern one by one.</p>
+     * 
+     * @see java.beans.beancontext.BeanContextSupport#bcsPreSerializationHook(java.io.ObjectOutputStream)
+     */
+    protected void bcsPreSerializationHook(ObjectOutputStream oos)
             throws IOException {
+        super.bcsPreSerializationHook(oos);
 
-        synchronized (this.services) {
-            for (Object key : this.services.keySet()) {
-                if (BeanContextSupport.getChildSerializable(key) != null) {
-                    oos.writeObject(this.services.get(key));
+        // serialize services
+        synchronized (services) {
+            oos.writeInt(serializable);
+            for (Iterator iter = services.entrySet().iterator(); iter.hasNext();) {
+                Entry entry = (Entry) iter.next();
+                if (((BCSSServiceProvider) entry.getValue())
+                        .getServiceProvider() instanceof Serializable) {
+                    oos.writeObject(entry.getKey());
+                    oos.writeObject(entry.getValue());
                 }
             }
         }
     }
 
-    @Override
-    protected void childJustRemovedHook(Object child,
-            BeanContextSupport.BCSChild bcsc) {
-
-        return;
+    /**
+     * This method is called everytime a child is removed from this context.
+     * <p>
+     * The implementation releases all services requested by the child.</p>
+     * 
+     * @see java.beans.beancontext.BeanContextSupport#childJustRemovedHook(java.lang.Object, java.beans.beancontext.BeanContextSupport.BCSChild)
+     */
+    protected void childJustRemovedHook(Object child, BCSChild bcsChild) {
+        if (bcsChild instanceof BCSSChild) {
+            releaseServicesForChild((BCSSChild) bcsChild, false);
+        }
     }
 
-    @Override
-    protected BeanContextSupport.BCSChild createBCSChild(Object targetChild,
-            Object peer) {
-
-        return new BCSSChild(targetChild, peer);
+    /**
+     * Release all services requested by the given child.
+     * 
+     * @param bcssChild         a child
+     * @param delegatedServices only release services that are delegated to parent context
+     */
+    private void releaseServicesForChild(BCSSChild bcssChild,
+            boolean delegatedServices) {
+        if (bcssChild.serviceRecords == null
+                || bcssChild.serviceRecords.isEmpty()) {
+            return;
+        }
+        synchronized (bcssChild.child) {
+            Object records[] = bcssChild.serviceRecords.toArray();
+            for (int i = 0; i < records.length; i++) {
+                ServiceRecord rec = (ServiceRecord) records[i];
+                if (delegatedServices) {
+                    if (rec.isDelegate) {
+                        releaseServiceWithoutCheck(rec.child, bcssChild,
+                                rec.requestor, rec.service, true);
+                    }
+                } else {
+                    releaseServiceWithoutCheck(rec.child, bcssChild,
+                            rec.requestor, rec.service, false);
+                }
+            }
+        }
     }
 
-    protected BCSSServiceProvider createBCSSServiceProvider(Class sc,
-            BeanContextServiceProvider bcsp) {
-
-        return new BCSSServiceProvider(sc, bcsp);
+    /**
+     * Creates a <code>BCSSChild</code> object to company the given child.
+     * 
+     * @see java.beans.beancontext.BeanContextSupport#createBCSChild(java.lang.Object, java.lang.Object)
+     */
+    protected BCSChild createBCSChild(Object child, Object proxyPeer) {
+        return new BCSSChild(child, proxyPeer);
     }
 
-    protected final void fireServiceAdded(
-            BeanContextServiceAvailableEvent bcssae) {
-
-        for (BeanContextServicesListener l : (ArrayList<BeanContextServicesListener>)this.bcsListeners) {
-            l.serviceAvailable(bcssae);
-        }
+    /**
+     * Creates a <code>BCSSServiceProvider</code> to company the given service.
+     * 
+     * @param serviceClass  the service class
+     * @param provider      the service provider
+     * @return a <code>BCSSServiceProvider</code> to company the given service
+     */
+    protected BCSSServiceProvider createBCSSServiceProvider(Class serviceClass,
+            BeanContextServiceProvider provider) {
+        return new BCSSServiceProvider(provider);
     }
 
+    /**
+     * Fires a <code>BeanContextServiceAvailableEvent</code> to registered 
+     * <code>BeanContextServicesListener</code>s.
+     * 
+     * @param serviceClass  the service that has been added
+     */
     protected final void fireServiceAdded(Class serviceClass) {
-        fireServiceAdded(getEvent(serviceClass));
+        fireServiceAdded(new BeanContextServiceAvailableEvent(this,
+                serviceClass));
     }
 
-    protected final void fireServiceRevoked(BeanContextServiceRevokedEvent bcsre) {
-
-        for (BeanContextServicesListener l : (ArrayList<BeanContextServicesListener>)this.bcsListeners) {
-            l.serviceRevoked(bcsre);
+    /**
+     * Fires a <code>BeanContextServiceAvailableEvent</code> to registered 
+     * <code>BeanContextServicesListener</code>s.
+     * 
+     * @param event     the event
+     */
+    protected final void fireServiceAdded(BeanContextServiceAvailableEvent event) {
+        Object listeners[];
+        synchronized (bcsListeners) {
+            listeners = bcsListeners.toArray();
+        }
+        for (int i = 0; i < listeners.length; i++) {
+            BeanContextServicesListener l = (BeanContextServicesListener) listeners[i];
+            l.serviceAvailable(event);
         }
     }
 
+    /**
+     * Fires a <code>BeanContextServiceRevokedEvent</code> to registered 
+     * <code>BeanContextServicesListener</code>s.
+     * 
+     * @param serviceClass  the service that has been revoked
+     * @param revokeNow     whether to terminate service immediately
+     */
     protected final void fireServiceRevoked(Class serviceClass,
             boolean revokeNow) {
+        fireServiceRevoked(new BeanContextServiceRevokedEvent(this,
+                serviceClass, revokeNow));
+    }
 
-        fireServiceRevoked(new BeanContextServiceRevokedEvent(
-                getBeanContextServicesPeer(), serviceClass, revokeNow));
+    /**
+     * Fires a <code>BeanContextServiceRevokedEvent</code> to registered 
+     * <code>BeanContextServicesListener</code>s.
+     * 
+     * @param event     the event
+     */
+    protected final void fireServiceRevoked(BeanContextServiceRevokedEvent event) {
+        Object listeners[];
+        synchronized (bcsListeners) {
+            listeners = bcsListeners.toArray();
+        }
+        for (int i = 0; i < listeners.length; i++) {
+            BeanContextServicesListener l = (BeanContextServicesListener) listeners[i];
+            l.serviceRevoked(event);
+        }
     }
 
+    /**
+     * Returns the peer of this context casted as <code>BeanContextServices</code>.
+     * 
+     * @return the peer of this context casted as <code>BeanContextServices</code>
+     */
     public BeanContextServices getBeanContextServicesPeer() {
-        return (BeanContextServices) getBeanContextPeer();
+        return (BeanContextServices) beanContextChildPeer;
     }
 
+    /**
+     * Returns the given child casted to <code>BeanContextServicesListener</code>,
+     * or null if it does not implements the interface.
+     * 
+     * @param child     a child
+     * @return the given child casted to <code>BeanContextServicesListener</code>,
+     * or null if it does not implements the interface
+     */
     protected static final BeanContextServicesListener getChildBeanContextServicesListener(
             Object child) {
-
         if (child instanceof BeanContextServicesListener) {
             return (BeanContextServicesListener) child;
         }
-        return null;
+		return null;
     }
 
+    /**
+     * Returns an iterator of all registered service classes,
+     * with <code>removed()</code> disabled.
+     * 
+     * @return an iterator of all registered service classes
+     * @see java.beans.beancontext.BeanContextServices#getCurrentServiceClasses()
+     */
     public Iterator getCurrentServiceClasses() {
-        synchronized (BeanContext.globalHierarchyLock) {
-            synchronized (this.services) {
-                return this.services.keySet().iterator();
-            }
-        }
-    }
-
-    private class BCSIterator implements Iterator {
-        private Iterator it;
-
-        public BCSIterator(Iterator it) {
-            this.it = it;
-        }
-
-        public boolean hasNext() {
-            return it.hasNext();
-        }
-
-        public Object next() {
-            return it.next();
-        }
-
-        public void remove() {
-            // do nothing
+        synchronized (services) {
+            return new BCSIterator(services.keySet().iterator());
         }
     }
 
+    /**
+     * Returns the service selectors of the specified service. The iterator's
+     * <code>remove()</code> operation is disabled.
+     * 
+     * @see java.beans.beancontext.BeanContextServices#getCurrentServiceSelectors(java.lang.Class)
+     */
     public Iterator getCurrentServiceSelectors(Class serviceClass) {
+        BeanContextServiceProvider provider = getLocalServiceProvider(serviceClass);
+        return provider == null ? null : new BCSIterator(provider
+                .getCurrentServiceSelectors(getBeanContextServicesPeer(),
+                        serviceClass));
+    }
 
-        if (serviceClass == null) {
-            return null;
-        }
-
-        synchronized (BeanContext.globalHierarchyLock) {
-            synchronized (this.services) {
-                BCSSServiceProvider bcsp = (BCSSServiceProvider)this.services.get(serviceClass);
-                if (bcsp == null) {
-                    return null;
-                }
-
-                return new BCSIterator(bcsp.getServiceProvider()
-                        .getCurrentServiceSelectors(
-                                getBeanContextServicesPeer(), serviceClass));
+    private BeanContextServiceProvider getLocalServiceProvider(
+            Class serviceClass) {
+        synchronized (services) {
+            BCSSServiceProvider bcssProvider = (BCSSServiceProvider) services
+                    .get(serviceClass);
+            if (bcssProvider != null) {
+                return bcssProvider.getServiceProvider();
             }
+			return null;
         }
     }
 
-    private BeanContextServiceAvailableEvent getEvent(Class serviceClass) {
-        return new BeanContextServiceAvailableEvent(
-                getBeanContextServicesPeer(), serviceClass);
-    }
-
+    /**
+     * Get a service instance on behalf of the specified child of this 
+     * context, by calling the registered service provider, or by delegating
+     * to the parent context.
+     * 
+     * @param child             the child that request service
+     * @param requestor         the requestor object
+     * @param serviceClass      the service class
+     * @param serviceSelector   the service selectors
+     * @param bcsrl             the <code>BeanContextServiceRevokedListener</code>
+     * @return a service instance on behalf of the specified child of this context
+     * @throws IllegalArgumentException if <code>child</code> is not a child of this context
+     * @throws TooManyListenersException
+     * @see java.beans.beancontext.BeanContextServices#getService(java.beans.beancontext.BeanContextChild, java.lang.Object, java.lang.Class, java.lang.Object, java.beans.beancontext.BeanContextServiceRevokedListener)
+     */
     public Object getService(BeanContextChild child, Object requestor,
             Class serviceClass, Object serviceSelector,
             BeanContextServiceRevokedListener bcsrl)
             throws TooManyListenersException {
-
-        if (child == null) {
-            throw new NullPointerException(Messages.getString("beans.17")); //$NON-NLS-1$
+        if (child == null || requestor == null || serviceClass == null
+                || bcsrl == null) {
+            throw new NullPointerException();
         }
 
-        if (requestor == null) {
-            throw new NullPointerException(Messages.getString("beans.18")); //$NON-NLS-1$
-        }
+        BCSSChild bcssChild = null;
+        BeanContextServiceProvider provider = null;
+        Object service = null;
+        boolean isDelegate = false;
 
-        if (serviceClass == null) {
-            throw new NullPointerException(Messages.getString("beans.19")); //$NON-NLS-1$
-        }
+        synchronized (globalHierarchyLock) {
+            // check child
+            synchronized (children) {
+                bcssChild = (BCSSChild) children.get(child);
+            }
+            if (bcssChild == null) {
+                throw new IllegalArgumentException(
+                        "not a child of this context");
+            }
 
-        if (serviceSelector == null) {
-            throw new NullPointerException(Messages.getString("beans.1A")); //$NON-NLS-1$
-        }
+            // try local service
+            provider = getLocalServiceProvider(serviceClass);
+            if (provider != null) {
+                service = provider.getService(getBeanContextServicesPeer(),
+                        requestor, serviceClass, serviceSelector);
+            }
 
-        if (bcsrl == null) {
-            throw new NullPointerException(Messages.getString("beans.15")); //$NON-NLS-1$
+            // no local service, try delegate
+            if (service == null && proxy != null) {
+                provider = proxy;
+                service = proxy.getService(getBeanContextServicesPeer(),
+                        requestor, serviceClass, serviceSelector, bcsrl);
+                isDelegate = true;
+            }
         }
 
-        synchronized (BeanContext.globalHierarchyLock) {
-            Object service = null;
-
-            synchronized (this.services) {
-                BCSSServiceProvider bcsp = (BCSSServiceProvider)this.services.get(serviceClass);
-
-                if (bcsp != null) {
-                    service = bcsp.getServiceProvider().getService(
-                            getBeanContextServicesPeer(), requestor,
-                            serviceClass, serviceSelector);
-                }
-
-                if ((service == null) && this.proxy != null) {
-                    service = this.proxy.getService(
-                            getBeanContextServicesPeer(), requestor,
-                            serviceClass, serviceSelector);
+        if (service != null) {
+            // save record
+            synchronized (child) {
+                if (bcssChild.serviceRecords == null) {
+                    bcssChild.serviceRecords = new ArrayList();
                 }
+                bcssChild.serviceRecords.add(new ServiceRecord(provider, child,
+                        requestor, serviceClass, bcsrl, service, isDelegate));
             }
-
-            return service;
         }
+
+        return service;
     }
 
-    public synchronized boolean hasService(Class serviceClass) {
+    /**
+     * Checks whether a service is registed in this context or the
+     * parent context.
+     * 
+     * @param serviceClass  the service class
+     * @return true if the service is registered
+     * @see java.beans.beancontext.BeanContextServices#hasService(java.lang.Class)
+     */
+    public boolean hasService(Class serviceClass) {
         if (serviceClass == null) {
-            throw new NullPointerException(Messages.getString("beans.19")); //$NON-NLS-1$
+            throw new NullPointerException();
         }
 
-        synchronized (BeanContext.globalHierarchyLock) {
-            synchronized (this.services) {
-                return this.services.containsKey(serviceClass);
-            }
+        boolean has;
+        synchronized (services) {
+            has = services.containsKey(serviceClass);
         }
+        if (!has && getBeanContext() instanceof BeanContextServices) {
+            has = ((BeanContextServices) getBeanContext())
+                    .hasService(serviceClass);
+        }
+        return has;
     }
 
-    @Override
+    /* (non-Javadoc)
+     * @see java.beans.beancontext.BeanContextSupport#initialize()
+     */
     public void initialize() {
         super.initialize();
-
-        this.services = new HashMap<Class, BCSSServiceProvider>();
-        this.bcsListeners = new ArrayList<BeanContextServicesListener>();
+        services = new HashMap();
+        serializable = 0;
+        proxy = null;
+        bcsListeners = new ArrayList();
     }
 
-    @Override
-    protected synchronized void initializeBeanContextResources() {
+    /**
+     * Called after the parent context is updated. The implementation 
+     * checks if the parent context is a <code>BeanContextServices</code>.
+     * If it is, then a <code>BCSSProxyServiceProvider</code> is created
+     * to delegate service requests to the parent context.
+     * 
+     * @see java.beans.beancontext.BeanContextChildSupport#initializeBeanContextResources()
+     */
+    protected void initializeBeanContextResources() {
         super.initializeBeanContextResources();
-        this.proxy = new BCSSProxyServiceProvider(getBeanContextServicesPeer());
+        
+        BeanContext context = getBeanContext();
+        if (context instanceof BeanContextServices) {
+            proxy = new BCSSProxyServiceProvider((BeanContextServices) context);
+        } else {
+            proxy = null;
+        }
     }
 
-    private void readObject(ObjectInputStream ois) throws IOException,
-            ClassNotFoundException {
-
-        synchronized (BeanContext.globalHierarchyLock) {
-            ois.defaultReadObject();
-            initialize();
-            bcsPreDeserializationHook(ois);
-            this.serializable = ois.readInt();
-
-            synchronized (this.services) {
-                for (int i = 0; i < this.serializable; i++) {
-                    BCSSServiceProvider prov = (BCSSServiceProvider) ois
-                            .readObject();
+    /**
+     * Called before the parent context is updated. The implementation
+     * releases any service that is currently provided by the parent context.
+     * 
+     * @see java.beans.beancontext.BeanContextChildSupport#releaseBeanContextResources()
+     */
+    protected void releaseBeanContextResources() {
+        super.releaseBeanContextResources();
+        
+        releaseAllDelegatedServices();
+        proxy = null;
+    }
 
-                    this.services.put(prov.getServiceClass(), prov);
-                }
+    private void releaseAllDelegatedServices() {
+        synchronized (children) {
+            for (Iterator iter = bcsChildren(); iter.hasNext();) {
+                releaseServicesForChild((BCSSChild) iter.next(), true);
             }
-
-            deserialize(ois, this.bcsListeners);
         }
     }
 
-    @Override
-    protected synchronized void releaseBeanContextResources() {
-        super.releaseBeanContextResources();
-        this.proxy = null;
-    }
-
+    /**
+     * Release a service which has been requested previously.
+     * 
+     * @param child     the child that request the service
+     * @param requestor the requestor object
+     * @param service   the service instance
+     * @throws IllegalArgumentException if <code>child</code> is not a child of this context
+     */
     public void releaseService(BeanContextChild child, Object requestor,
             Object service) {
-
-        if (child == null) {
-            throw new NullPointerException(Messages.getString("beans.17")); //$NON-NLS-1$
+        if (child == null || requestor == null || service == null) {
+            throw new NullPointerException();
         }
 
-        if (requestor == null) {
-            throw new NullPointerException(Messages.getString("beans.18")); //$NON-NLS-1$
-        }
+        synchronized (globalHierarchyLock) {
+            BCSSChild bcssChild;
+            synchronized (children) {
+                bcssChild = (BCSSChild) children.get(child);
+            }
+            if (bcssChild == null) {
+                throw new IllegalArgumentException(
+                        "not a child of this context");
+            }
 
-        if (service == null) {
-            throw new NullPointerException(Messages.getString("beans.1B")); //$NON-NLS-1$
+            releaseServiceWithoutCheck(child, bcssChild, requestor, service,
+                    false);
         }
+    }
 
-        synchronized (BeanContext.globalHierarchyLock) {
-            if (this.proxy != null) {
-                this.proxy.releaseService(getBeanContextServicesPeer(),
-                        requestor, service);
+    /**
+     * Releases a service without checking the memebership of the child.
+     */
+    private void releaseServiceWithoutCheck(BeanContextChild child,
+            BCSSChild bcssChild, Object requestor, Object service,
+            boolean callRevokedListener) {
+        synchronized (child) {
+            // scan record
+            for (Iterator iter = bcssChild.serviceRecords.iterator(); iter
+                    .hasNext();) {
+                ServiceRecord rec = (ServiceRecord) iter.next();
+                if (rec.requestor == requestor && rec.service == service) {
+                    // release service
+                    rec.provider.releaseService(getBeanContextServicesPeer(),
+                            requestor, service);
+                    // call service revoked listener
+                    if (callRevokedListener && rec.revokedListener != null) {
+                        rec.revokedListener
+                                .serviceRevoked(new BeanContextServiceRevokedEvent(
+                                        getBeanContextServicesPeer(),
+                                        rec.serviceClass, true));
+                    }
+                    // remove record
+                    iter.remove();
+                    break;
+                }
             }
         }
     }
 
+    /* (non-Javadoc)
+     * @see java.beans.beancontext.BeanContextServices#removeBeanContextServicesListener(java.beans.beancontext.BeanContextServicesListener)
+     */
     public void removeBeanContextServicesListener(
-            BeanContextServicesListener bcsl) {
-
-        if (bcsl == null) {
-            throw new NullPointerException(Messages.getString("beans.15")); //$NON-NLS-1$
+            BeanContextServicesListener listener) {
+        if (listener == null) {
+            throw new NullPointerException();
         }
-
-        synchronized (this.bcsListeners) {
-            this.bcsListeners.remove(bcsl);
+        synchronized (bcsListeners) {
+            bcsListeners.remove(listener);
         }
     }
 
+    /**
+     * Revokes a service in this bean context.
+     * <p>
+     * The given service provider is unregistered and a 
+     * <code>BeanContextServiceRevokedEvent</code> is fired.
+     * All registered service listeners and current service users get
+     * notified.</p>
+     * 
+     * @param serviceClass      the service class
+     * @param serviceProvider   the service provider
+     * @param revokeCurrentServicesNow  true if service should be terminated immediantly
+     * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class, java.beans.beancontext.BeanContextServiceProvider, boolean)
+     */
     public void revokeService(Class serviceClass,
-            BeanContextServiceProvider bcsp, boolean revokeCurrentServicesNow) {
-
-        if (serviceClass == null) {
-            throw new NullPointerException(Messages.getString("beans.19")); //$NON-NLS-1$
+            BeanContextServiceProvider serviceProvider,
+            boolean revokeCurrentServicesNow) {
+        if (serviceClass == null || serviceProvider == null) {
+            throw new NullPointerException();
         }
 
-        if (bcsp == null) {
-            throw new NullPointerException(Messages.getString("beans.16")); //$NON-NLS-1$
-        }
+        synchronized (globalHierarchyLock) {
+            synchronized (services) {
+                BCSSServiceProvider bcssProvider = (BCSSServiceProvider) services
+                        .get(serviceClass);
+                if (bcssProvider == null) { // non-exist service
+                    return;
+                }
+                if (bcssProvider.getServiceProvider() != serviceProvider) {
+                    throw new IllegalArgumentException(
+                            "not the service provider registered with this context");
+                }
 
-        synchronized (BeanContext.globalHierarchyLock) {
-            synchronized (this.services) {
-                Object removed = this.services.remove(serviceClass);
+                services.remove(serviceClass);
 
-                if (removed != null) {
-                    if (getChildSerializable(bcsp) != null) {
-                        this.serializable--;
-                    }
+                if (serviceProvider instanceof Serializable) {
+                    serializable--;
                 }
             }
+        }
 
-            BeanContextServiceRevokedEvent ev = new BeanContextServiceRevokedEvent(
-                    getBeanContextServicesPeer(), serviceClass,
-                    revokeCurrentServicesNow);
+        // notify listeners
+        fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
 
-            fireServiceRevoked(ev);
+        // notify service users
+        notifyServiceRevokedToServiceUsers(serviceClass, serviceProvider,
+                revokeCurrentServicesNow);
+    }
 
-            for (Iterator it = iterator(); it.hasNext();) {
-                Object child = it.next();
+    /**
+     * Notify all children that a service has been revoked.
+     */
+    private void notifyServiceRevokedToServiceUsers(Class serviceClass,
+            BeanContextServiceProvider serviceProvider,
+            boolean revokeCurrentServicesNow) {
+        synchronized (children) {
+            for (Iterator iter = bcsChildren(); iter.hasNext();) {
+                BCSSChild bcssChild = (BCSSChild) iter.next();
+                notifyServiceRevokedToServiceUsers(serviceClass,
+                        serviceProvider, revokeCurrentServicesNow, bcssChild);
+            }
+        }
+    }
 
-                if (child instanceof BeanContextServices) {
-                    ((BeanContextServices) child).serviceRevoked(ev);
+    /**
+     * Notify the given child that a service has been revoked.
+     */
+    private void notifyServiceRevokedToServiceUsers(Class serviceClass,
+            BeanContextServiceProvider serviceProvider,
+            boolean revokeCurrentServicesNow, BCSSChild bcssChild) {
+        if (bcssChild.serviceRecords == null
+                || bcssChild.serviceRecords.isEmpty()) {
+            return;
+        }
+        synchronized (bcssChild.child) {
+            for (Iterator it = bcssChild.serviceRecords.iterator(); it
+                    .hasNext();) {
+                ServiceRecord rec = (ServiceRecord) it.next();
+                if (rec.serviceClass == serviceClass
+                        && rec.provider == serviceProvider
+                        && rec.revokedListener != null && !rec.isDelegate) {
+                    rec.revokedListener
+                            .serviceRevoked(new BeanContextServiceRevokedEvent(
+                                    getBeanContextServicesPeer(), serviceClass,
+                                    revokeCurrentServicesNow));
+                    // prevent duplicate notification
+                    rec.revokedListener = null;
                 }
             }
         }
     }
 
-    @Override
-    public void serviceAvailable(BeanContextServiceAvailableEvent bcssae) {
-        if (bcssae == null) {
+    /**
+     * Notify all listeners and children that implements 
+     * <code>BeanContextServices</code> of the event.
+     * 
+     * @see java.beans.beancontext.BeanContextServicesListener#serviceAvailable(java.beans.beancontext.BeanContextServiceAvailableEvent)
+     */
+    public void serviceAvailable(BeanContextServiceAvailableEvent event) {
+        if (null == event) {
             throw new NullPointerException(Messages.getString("beans.1C")); //$NON-NLS-1$
         }
-
-        for (BeanContextServicesListener l : (ArrayList<BeanContextServicesListener>)this.bcsListeners) {
-            l.serviceAvailable(bcssae);
+        fireServiceAdded(event);
+        Object childs[] = copyChildren();
+        for (int i = 0; i < childs.length; i++) {
+            if (childs[i] instanceof BeanContextServices) {
+                ((BeanContextServices) childs[i]).serviceAvailable(event);
+            }
         }
     }
 
-    @Override
-    public void serviceRevoked(BeanContextServiceRevokedEvent bcssre) {
-        if (bcssre == null) {
+    /**
+     * Notify all listeners and children that implements 
+     * <code>BeanContextServices</code> of the event.
+     * 
+     * @see java.beans.beancontext.BeanContextServiceRevokedListener#serviceRevoked(java.beans.beancontext.BeanContextServiceRevokedEvent)
+     */
+    public void serviceRevoked(BeanContextServiceRevokedEvent event) {
+        if (null == event) {
             throw new NullPointerException(Messages.getString("beans.1C")); //$NON-NLS-1$
         }
-
-        for (BeanContextServicesListener l : (ArrayList<BeanContextServicesListener>)this.bcsListeners) {
-            l.serviceRevoked(bcssre);
+        fireServiceRevoked(event);
+        Object childs[] = copyChildren();
+        for (int i = 0; i < childs.length; i++) {
+            if (childs[i] instanceof BeanContextServices) {
+                ((BeanContextServices) childs[i]).serviceRevoked(event);
+            }
         }
     }
 
+    /**
+     * The implementation goes through following steps:
+     * <p>
+     * <ol>
+     * <li>Calls <code>defaultWriteObject()</code>.</li>
+     * <li>Writes out serializable service listeners.</li>
+     * </ol>
+     * </p>
+     * 
+     * @param oos   the object output stream
+     * @throws IOException if I/O exception occurs
+     */
     private void writeObject(ObjectOutputStream oos) throws IOException {
 
-        synchronized (BeanContext.globalHierarchyLock) {
-            oos.defaultWriteObject();
-            bcsPreSerializationHook(oos);
-            oos.writeInt(this.serializable);
-
-            synchronized (this.services) {
-                for (Iterator it = this.getCurrentServiceClasses(); it
-                        .hasNext();) {
-                    BCSSServiceProvider prov = (BCSSServiceProvider) it.next();
+        oos.defaultWriteObject();
 
-                    if (prov.getServiceProvider() instanceof Serializable) {
-                        oos.writeObject(prov);
-                    }
-                }
-            }
+        synchronized (bcsListeners) {
+            serialize(oos, bcsListeners);
+        }
+    }
 
-            serialize(oos, this.bcsListeners);
+    /**
+     * The implementation goes through following steps:
+     * <p>
+     * <ol>
+     * <li>Calls <code>defaultReadObject()</code>.</li>
+     * <li>Reads serializable service listeners.</li>
+     * </ol>
+     * </p>
+     * 
+     * @param ois   the object input stream
+     * @throws IOException if I/O error occurs
+     * @throws ClassNotFoundException if class of read object is not found
+     */
+    private void readObject(ObjectInputStream ois) throws IOException,
+            ClassNotFoundException {
+
+        ois.defaultReadObject();
+
+        synchronized (bcsListeners) {
+            deserialize(ois, bcsListeners);
         }
     }
+
 }
+
+



Mime
View raw message