blob: 4d25c0744febe0647d8ca5d6f8fd9171958ae9f8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.beans.beancontext;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
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;
/**
* 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, Serializable {
private static class ServiceRecord {
BeanContextServiceProvider provider;
BeanContextChild child;
Object requestor;
Class serviceClass;
BeanContextServiceRevokedListener revokedListener;
Object service;
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;
}
}
/**
* 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;
transient ArrayList<ServiceRecord> serviceRecords;
BCSSChild(Object child, Object proxyPeer) {
super(child, proxyPeer);
}
}
/**
* 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 {
private BeanContextServices backBCS;
BCSSProxyServiceProvider(BeanContextServices backBCS) {
this.backBCS = backBCS;
}
/**
* Throws <code>UnsupportedOperationException</code>.
*/
public Iterator getCurrentServiceSelectors(BeanContextServices bcs,
Class serviceClass) {
throw new UnsupportedOperationException();
}
/**
* Throws <code>UnsupportedOperationException</code>.
*/
public Object getService(BeanContextServices bcs, Object requestor,
Class serviceClass, Object serviceSelector) {
throw new UnsupportedOperationException();
}
/**
* Delegate to the wrapped <code>BeanContextServices</code>.
*/
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) {
backBCS.releaseService(BeanContextServicesSupport.this
.getBeanContextServicesPeer(), requestor, service);
}
/**
* Throws <code>UnsupportedOperationException</code>.
*/
public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
throw new UnsupportedOperationException();
}
}
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()));
}
}
/**
* 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;
/**
* The service provider of the related service.
*/
protected BeanContextServiceProvider serviceProvider;
BCSSServiceProvider(BeanContextServiceProvider provider) {
this.serviceProvider = provider;
}
/**
* Returns the service provider of the related service.
*
* @return the service provider of the related service
*/
protected BeanContextServiceProvider getServiceProvider() {
return serviceProvider;
}
}
private static final long serialVersionUID = -8494482757288719206L;
/**
* 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.
*/
@SuppressWarnings("unchecked")
protected transient HashMap services;
/**
* The number of serializable service providers currently registered.
*/
protected transient int serializable;
/**
* 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.
*/
@SuppressWarnings("unchecked")
protected transient ArrayList bcsListeners;
/**
* Constructs a standard <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);
}
/**
* 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);
}
/**
* 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);
}
/**
* 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);
}
/*
* (non-Javadoc)
*
* @see java.beans.beancontext.BeanContextServices#addBeanContextServicesListener(java.beans.beancontext.BeanContextServicesListener)
*/
public void addBeanContextServicesListener(
BeanContextServicesListener listener) {
if (listener == null) {
throw new NullPointerException();
}
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 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 provider, boolean fireEvent) {
if (serviceClass == null || provider == null) {
throw new NullPointerException();
}
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++;
}
}
}
if (fireEvent) {
// notify all listeners and BeanContextServices children
notifyServiceAvailable(new BeanContextServiceAvailableEvent(this,
serviceClass));
}
return true;
}
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);
}
}
}
/**
* 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);
// deserialize services
synchronized (services) {
serializable = ois.readInt();
for (int i = 0; i < serializable; i++) {
Object serviceClass = ois.readObject();
Object bcssProvider = ois.readObject();
services.put((Class) serviceClass,
(BCSSServiceProvider) bcssProvider);
}
}
}
/**
* 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);
// 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());
}
}
}
}
/**
* 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);
}
}
/**
* 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);
}
}
}
}
/**
* 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);
}
/**
* 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(new BeanContextServiceAvailableEvent(this,
serviceClass));
}
/**
* 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));
}
/**
* 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) 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;
}
/**
* 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 (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));
}
private BeanContextServiceProvider getLocalServiceProvider(
Class serviceClass) {
synchronized (services) {
BCSSServiceProvider bcssProvider = (BCSSServiceProvider) services
.get(serviceClass);
if (bcssProvider != null) {
return bcssProvider.getServiceProvider();
}
return null;
}
}
/**
* 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 || requestor == null || serviceClass == null
|| bcsrl == null) {
throw new NullPointerException();
}
BCSSChild bcssChild = null;
BeanContextServiceProvider provider = null;
Object service = null;
boolean isDelegate = false;
synchronized (globalHierarchyLock) {
// check child
synchronized (children) {
bcssChild = (BCSSChild) children.get(child);
}
if (bcssChild == null) {
throw new IllegalArgumentException(
Messages.getString("beans.65"));
}
// try local service
provider = getLocalServiceProvider(serviceClass);
if (provider != null) {
service = provider.getService(getBeanContextServicesPeer(),
requestor, serviceClass, serviceSelector);
}
// no local service, try delegate
if (service == null && proxy != null) {
provider = proxy;
service = proxy.getService(getBeanContextServicesPeer(),
requestor, serviceClass, serviceSelector, bcsrl);
isDelegate = true;
}
}
if (service != null) {
// save record
synchronized (child) {
if (bcssChild.serviceRecords == null) {
bcssChild.serviceRecords = new ArrayList<ServiceRecord>();
}
bcssChild.serviceRecords.add(new ServiceRecord(provider, child,
requestor, serviceClass, bcsrl, service, isDelegate));
}
}
return service;
}
/**
* 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();
}
boolean has;
synchronized (services) {
has = services.containsKey(serviceClass);
}
if (!has && getBeanContext() instanceof BeanContextServices) {
has = ((BeanContextServices) getBeanContext())
.hasService(serviceClass);
}
return has;
}
/*
* (non-Javadoc)
*
* @see java.beans.beancontext.BeanContextSupport#initialize()
*/
public void initialize() {
super.initialize();
services = new HashMap<Class, BCSSServiceProvider>();
serializable = 0;
proxy = null;
bcsListeners = new ArrayList<BeanContextServicesListener>();
}
/**
* 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();
BeanContext context = getBeanContext();
if (context instanceof BeanContextServices) {
proxy = new BCSSProxyServiceProvider((BeanContextServices) context);
} else {
proxy = null;
}
}
/**
* 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;
}
private void releaseAllDelegatedServices() {
synchronized (children) {
for (Iterator iter = bcsChildren(); iter.hasNext();) {
releaseServicesForChild((BCSSChild) iter.next(), true);
}
}
}
/**
* 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 || requestor == null || service == null) {
throw new NullPointerException();
}
synchronized (globalHierarchyLock) {
BCSSChild bcssChild;
synchronized (children) {
bcssChild = (BCSSChild) children.get(child);
}
if (bcssChild == null) {
throw new IllegalArgumentException(
Messages.getString("beans.65"));
}
releaseServiceWithoutCheck(child, bcssChild, requestor, service,
false);
}
}
/**
* Releases a service without checking the membership of the child.
*/
private void releaseServiceWithoutCheck(BeanContextChild child,
BCSSChild bcssChild, Object requestor, Object service,
boolean callRevokedListener) {
if (bcssChild.serviceRecords == null
|| bcssChild.serviceRecords.isEmpty()) {
return;
}
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 listener) {
if (listener == null) {
throw new NullPointerException();
}
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 serviceProvider,
boolean revokeCurrentServicesNow) {
if (serviceClass == null || serviceProvider == null) {
throw new NullPointerException();
}
synchronized (globalHierarchyLock) {
synchronized (services) {
BCSSServiceProvider bcssProvider = (BCSSServiceProvider) services
.get(serviceClass);
if (bcssProvider == null) { // non-exist service
return;
}
if (bcssProvider.getServiceProvider() != serviceProvider) {
throw new IllegalArgumentException(
Messages.getString("beans.66"));
}
services.remove(serviceClass);
if (serviceProvider instanceof Serializable) {
serializable--;
}
}
}
// notify listeners
fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
// notify service users
notifyServiceRevokedToServiceUsers(serviceClass, serviceProvider,
revokeCurrentServicesNow);
}
/**
* 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);
}
}
}
/**
* 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;
}
}
}
}
/**
* 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$
}
if (services.containsKey(event.serviceClass)) {
return;
}
fireServiceAdded(event);
Object childs[] = copyChildren();
for (int i = 0; i < childs.length; i++) {
if (childs[i] instanceof BeanContextServices) {
((BeanContextServices) childs[i]).serviceAvailable(event);
}
}
}
/**
* 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$
}
if (services.containsKey(event.serviceClass)) {
return;
}
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 {
oos.defaultWriteObject();
synchronized (bcsListeners) {
serialize(oos, 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();
deserialize(ois, bcsListeners);
}
}