Author: thomas.diesler(a)jboss.com
Date: 2010-03-21 15:48:04 -0400 (Sun, 21 Mar 2010)
New Revision: 102691
Added:
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/util/RemoveOnlyCollection.java
Modified:
projects/jboss-osgi/projects/runtime/framework/trunk/bundle/src/test/java/org/jboss/test/osgi/service/ServiceEventHookTestCase.java
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/bundle/AbstractBundleState.java
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/bundle/ServiceManagerPluginImpl.java
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/plugins/ServiceManagerPlugin.java
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/plugins/internal/FrameworkEventsPluginImpl.java
Log:
Add FindHook support - first cut
[TCK] EventHook pass
Modified:
projects/jboss-osgi/projects/runtime/framework/trunk/bundle/src/test/java/org/jboss/test/osgi/service/ServiceEventHookTestCase.java
===================================================================
---
projects/jboss-osgi/projects/runtime/framework/trunk/bundle/src/test/java/org/jboss/test/osgi/service/ServiceEventHookTestCase.java 2010-03-21
18:41:27 UTC (rev 102690)
+++
projects/jboss-osgi/projects/runtime/framework/trunk/bundle/src/test/java/org/jboss/test/osgi/service/ServiceEventHookTestCase.java 2010-03-21
19:48:04 UTC (rev 102691)
@@ -74,7 +74,7 @@
contexts.add(context);
fail("Cannot add a context");
}
- catch (RuntimeException ex)
+ catch (UnsupportedOperationException ex)
{
// expected
}
Modified:
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/bundle/AbstractBundleState.java
===================================================================
---
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/bundle/AbstractBundleState.java 2010-03-21
18:41:27 UTC (rev 102690)
+++
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/bundle/AbstractBundleState.java 2010-03-21
19:48:04 UTC (rev 102691)
@@ -484,7 +484,7 @@
{
checkValidBundleContext();
ServiceManagerPlugin plugin =
getBundleManager().getPlugin(ServiceManagerPlugin.class);
- return plugin.getAllServiceReferences(this, clazz, filter);
+ return plugin.getServiceReferences(this, clazz, filter, false);
}
public Object getService(ServiceReference reference)
@@ -505,7 +505,7 @@
{
checkValidBundleContext();
ServiceManagerPlugin plugin =
getBundleManager().getPlugin(ServiceManagerPlugin.class);
- return plugin.getServiceReferences(this, clazz, filter);
+ return plugin.getServiceReferences(this, clazz, filter, true);
}
@SuppressWarnings({ "rawtypes" })
Modified:
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/bundle/ServiceManagerPluginImpl.java
===================================================================
---
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/bundle/ServiceManagerPluginImpl.java 2010-03-21
18:41:27 UTC (rev 102690)
+++
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/bundle/ServiceManagerPluginImpl.java 2010-03-21
19:48:04 UTC (rev 102691)
@@ -55,13 +55,16 @@
import org.jboss.osgi.framework.plugins.internal.AbstractPlugin;
import org.jboss.osgi.framework.util.KernelUtils;
import org.jboss.osgi.framework.util.NoFilter;
+import org.jboss.osgi.framework.util.RemoveOnlyCollection;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.hooks.service.FindHook;
import org.osgi.framework.hooks.service.ListenerHook;
import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo;
@@ -90,11 +93,11 @@
/** Enable MDR usage */
private boolean enableMDRUsage = true;
-
+
public ServiceManagerPluginImpl(OSGiBundleManager bundleManager, DeploymentRegistry
registry)
{
super(bundleManager);
-
+
if (registry == null)
throw new IllegalArgumentException("Null deployment registry");
@@ -135,7 +138,7 @@
}
if (result.isEmpty())
return null;
-
+
return result.toArray(new ServiceReference[result.size()]);
}
@@ -156,25 +159,11 @@
if (references.isEmpty())
return null;
-
+
return references.toArray(new ServiceReference[references.size()]);
}
@Override
- public ServiceReference[] getAllServiceReferences(AbstractBundleState bundle, String
clazz, String filterStr) throws InvalidSyntaxException
- {
- Filter filter = NoFilter.INSTANCE;
- if (filterStr != null)
- filter = FrameworkUtil.createFilter(filterStr);
-
- Collection<ServiceReference> services = getServices(bundle, clazz, filter,
false);
- if (services == null || services.isEmpty())
- return null;
-
- return services.toArray(new ServiceReference[services.size()]);
- }
-
- @Override
public Set<Bundle> getUsingBundles(OSGiServiceState serviceState)
{
AbstractBundleState bundleState = serviceState.getBundleState();
@@ -191,13 +180,13 @@
}
return bundles;
}
-
+
@Override
public Object getService(AbstractBundleState bundleState, ServiceReference reference)
{
if (reference == null)
throw new IllegalArgumentException("Null reference");
-
+
ControllerContextHandle handle = (ControllerContextHandle)reference;
ControllerContext context = handle.getContext();
if (KernelUtils.isUnregistered(context)) // we're probably not installed
anymore
@@ -213,28 +202,72 @@
{
if (clazz == null)
throw new IllegalArgumentException("Null clazz");
-
- Collection<ServiceReference> services = getServices(bundle, clazz, null,
true);
- if (services == null || services.isEmpty())
+
+ Collection<ServiceReference> srefs = getServiceReferencesInternal(bundle,
clazz, null, true);
+ srefs = processFindHooks(bundle, clazz, null, true, srefs);
+ if (srefs.isEmpty())
return null;
- return services.iterator().next();
+ return srefs.iterator().next();
}
@Override
- public ServiceReference[] getServiceReferences(AbstractBundleState bundle, String
clazz, String filterStr) throws InvalidSyntaxException
+ public ServiceReference[] getServiceReferences(AbstractBundleState bundle, String
clazz, String filterStr, boolean checkAssignable)
+ throws InvalidSyntaxException
{
- Filter filter = NoFilter.INSTANCE;
+ Filter filter = null;
if (filterStr != null)
filter = FrameworkUtil.createFilter(filterStr);
- Collection<ServiceReference> services = getServices(bundle, clazz, filter,
true);
- if (services == null || services.isEmpty())
+ Collection<ServiceReference> srefs = getServiceReferencesInternal(bundle,
clazz, filter, checkAssignable);
+ srefs = processFindHooks(bundle, clazz, filterStr, checkAssignable, srefs);
+ if (srefs.isEmpty())
return null;
- return services.toArray(new ServiceReference[services.size()]);
+ return srefs.toArray(new ServiceReference[srefs.size()]);
}
+ /*
+ * The FindHook is called when a target bundle searches the service registry
+ * with the getServiceReference or getServiceReferences methods. A registered
+ * FindHook service gets a chance to inspect the returned set of service
+ * references and can optionally shrink the set of returned services. The order
+ * in which the find hooks are called is the reverse compareTo ordering of
+ * their Service References.
+ */
+ @SuppressWarnings("unchecked")
+ private Collection<ServiceReference> processFindHooks(AbstractBundleState
bundle, String clazz, String filterStr, boolean checkAssignable,
Collection<ServiceReference> srefs)
+ {
+ BundleContext context = bundle.getBundleContext();
+ if (context == null)
+ return srefs;
+
+ // Get and sort the FindHook refs
+ Collection<ServiceReference> hookRefs = getServiceReferencesInternal(bundle,
FindHook.class.getName(), null, true);
+ List<ServiceReference> sortedHookRefs = new
ArrayList<ServiceReference>(hookRefs);
+ Collections.sort(sortedHookRefs);
+ Collections.reverse(sortedHookRefs);
+
+ srefs = new RemoveOnlyCollection<ServiceReference>(srefs);
+
+ List<FindHook> hooks = new ArrayList<FindHook>();
+ for(ServiceReference hookRef : sortedHookRefs)
+ hooks.add((FindHook)context.getService(hookRef));
+
+ for (FindHook hook : hooks)
+ {
+ try
+ {
+ hook.find(context, clazz, filterStr, !checkAssignable, srefs);
+ }
+ catch (Exception ex)
+ {
+ log.warn("Error while calling FindHook: " + hook, ex);
+ }
+ }
+ return srefs;
+ }
+
@Override
@SuppressWarnings("rawtypes")
public OSGiServiceState registerService(AbstractBundleState bundleState, String[]
clazzes, Object service, Dictionary properties)
@@ -247,7 +280,7 @@
FrameworkEventsPlugin eventsPlugin = getPlugin(FrameworkEventsPlugin.class);
listenerInfos = eventsPlugin.getServiceListenerInfos(null);
}
-
+
OSGiServiceState result = new OSGiServiceState(bundleState, clazzes, service,
properties);
result.internalRegister();
try
@@ -272,11 +305,11 @@
ListenerHook listenerHook = (ListenerHook)service;
listenerHook.added(listenerInfos);
}
-
+
// This event is synchronously delivered after the service has been registered with
the Framework.
FrameworkEventsPlugin eventsPlugin = getPlugin(FrameworkEventsPlugin.class);
eventsPlugin.fireServiceEvent(bundleState, ServiceEvent.REGISTERED, result);
-
+
return result;
}
@@ -284,15 +317,15 @@
public void unregisterService(OSGiServiceState serviceState)
{
AbstractBundleState bundleState = serviceState.getBundleState();
-
+
// This event is synchronously delivered before the service has completed
unregistering.
FrameworkEventsPlugin plugin = getPlugin(FrameworkEventsPlugin.class);
plugin.fireServiceEvent(bundleState, ServiceEvent.UNREGISTERING, serviceState);
-
+
internalUnregister(serviceState);
if (bundleState instanceof OSGiBundleState)
removeContext(serviceState,
((OSGiBundleState)bundleState).getDeploymentUnit());
-
+
Controller controller = kernel.getController();
controller.uninstall(serviceState.getName());
}
@@ -309,17 +342,17 @@
Set<AbstractBundleState> used = new
HashSet<AbstractBundleState>();
OSGiBundleManager manager = bundleState.getBundleManager();
ControllerContextPlugin plugin =
manager.getPlugin(ControllerContextPlugin.class);
-
+
for (Object user : users)
{
AbstractBundleState using = plugin.getBundleForUser(user);
- if (used.add(using) == true)
+ if (used.add(using) == true)
{
// ungetService will cleanup service cache
int count = ct.getUsedByCount(serviceState, using);
while (count > 0)
{
- using.ungetContext(serviceState);
+ using.ungetContext(serviceState);
count--;
}
}
@@ -328,7 +361,7 @@
}
serviceState.clearTarget();
}
-
+
@Override
public boolean ungetService(AbstractBundleState bundleState, ServiceReference
reference)
{
@@ -339,7 +372,7 @@
ControllerContext context = serviceReference.getContext();
if (KernelUtils.isUnregistered(context))
return false;
-
+
return bundleState.removeContextInUse(context);
}
@@ -420,7 +453,7 @@
return mdrFactory;
}
- private Collection<ServiceReference> getServices(AbstractBundleState bundle,
String clazz, Filter filter, boolean checkAssignable)
+ private Collection<ServiceReference>
getServiceReferencesInternal(AbstractBundleState bundle, String clazz, Filter filter,
boolean checkAssignable)
{
Set<ControllerContext> contexts;
KernelController controller = kernel.getController();
@@ -435,7 +468,7 @@
{
Class<?> type = getBundleManager().loadClassFailsafe(bundle, clazz);
if (type == null)
- return null; // or check all?
+ return Collections.emptyList();
contexts = controller.getContexts(type, ControllerState.INSTALLED);
}
@@ -445,7 +478,7 @@
}
if (contexts == null || contexts.isEmpty())
- return null;
+ return Collections.emptyList();
if (filter == null)
filter = NoFilter.INSTANCE;
Modified:
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/plugins/ServiceManagerPlugin.java
===================================================================
---
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/plugins/ServiceManagerPlugin.java 2010-03-21
18:41:27 UTC (rev 102690)
+++
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/plugins/ServiceManagerPlugin.java 2010-03-21
19:48:04 UTC (rev 102691)
@@ -63,21 +63,10 @@
/**
* Returns an array of <code>ServiceReference</code> objects. The
returned
* array of <code>ServiceReference</code> objects contains services that
- * were registered under the specified class and match the specified filter
+ * were registered under the specified class, match the specified filter
* expression.
*
- * @param clazz The class name with which the service was registered or
<code>null</code> for all services.
- * @param filter The filter expression or <code>null</code> for all
services.
- * @return An array of <code>ServiceReference</code> objects or
<code>null</code>
- * if no services are registered which satisfy the search.
- */
- ServiceReference[] getAllServiceReferences(AbstractBundleState bundleState, String
clazz, String filter) throws InvalidSyntaxException;
-
- /**
- * Returns an array of <code>ServiceReference</code> objects. The
returned
- * array of <code>ServiceReference</code> objects contains services that
- * were registered under the specified class, match the specified filter
- * expression, and the packages for the class names under which the services
+ * If checkAssignable is true, the packages for the class names under which the
services
* were registered match the context bundle's packages as defined in
* {@link ServiceReference#isAssignableTo(Bundle, String)}.
*
@@ -85,7 +74,7 @@
* @param clazz The class name with which the service was registered or
<code>null</code> for all services.
* @param filter The filter expression or <code>null</code> for all
services.
*/
- ServiceReference[] getServiceReferences(AbstractBundleState bundleState, String clazz,
String filter) throws InvalidSyntaxException;
+ ServiceReference[] getServiceReferences(AbstractBundleState bundleState, String clazz,
String filter, boolean checkAssignable) throws InvalidSyntaxException;
/**
* Returns a <code>ServiceReference</code> object for a service that
Modified:
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/plugins/internal/FrameworkEventsPluginImpl.java
===================================================================
---
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/plugins/internal/FrameworkEventsPluginImpl.java 2010-03-21
18:41:27 UTC (rev 102690)
+++
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/plugins/internal/FrameworkEventsPluginImpl.java 2010-03-21
19:48:04 UTC (rev 102691)
@@ -46,6 +46,7 @@
import org.jboss.osgi.framework.bundle.OSGiServiceState;
import org.jboss.osgi.framework.plugins.FrameworkEventsPlugin;
import org.jboss.osgi.framework.util.NoFilter;
+import org.jboss.osgi.framework.util.RemoveOnlyCollection;
import org.jboss.osgi.spi.util.ConstantsHelper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -57,7 +58,6 @@
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceException;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
@@ -66,7 +66,8 @@
import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo;
/**
- * A plugin that installs/starts bundles on framework startup.
+ * A plugin that manages {@link FrameworkListener}, {@link BundleListener}, {@link
ServiceListener} and their
+ * associated {@link FrameworkEvent}, {@link BundleEvent}, {@link ServiceEvent}.
*
* @author thomas.diesler(a)jboss.com
* @since 18-Aug-2009
@@ -526,7 +527,6 @@
{
// Get a snapshot of the current listeners
List<ServiceListenerRegistration> listeners = new
ArrayList<ServiceListenerRegistration>();
- Collection<BundleContext> contexts = new HashSet<BundleContext>();
synchronized (serviceListeners)
{
for (Entry<Bundle, List<ServiceListenerRegistration>> entry :
serviceListeners.entrySet())
@@ -535,13 +535,9 @@
{
BundleContext context = listener.getBundleContext();
if (context != null)
- {
listeners.add(listener);
- contexts.add(context);
- }
}
}
- contexts = new RemoveOnlyCollection<BundleContext>(contexts);
}
// Expose the wrapper not the state itself
@@ -555,31 +551,8 @@
return;
// Call the registered event hooks
- List<EventHook> eventHooks = getEventHooks();
- for (EventHook hook : eventHooks)
- {
- try
- {
- hook.event(event, contexts);
- }
- catch (Exception ex)
- {
- log.warn("Error while calling EventHook: " + hook, ex);
- }
- }
+ listeners = processEventHooks(listeners, event);
- // Remove the listeners that have been filtered by the EventHooks
- if (contexts.size() != listeners.size())
- {
- Iterator<ServiceListenerRegistration> it = listeners.iterator();
- while (it.hasNext())
- {
- ServiceListenerRegistration slreg = it.next();
- if (contexts.contains(slreg.getBundleContext()) == false)
- it.remove();
- }
- }
-
// Nobody is interested
if (listeners.isEmpty())
return;
@@ -609,6 +582,46 @@
}
}
+ private List<ServiceListenerRegistration>
processEventHooks(List<ServiceListenerRegistration> listeners, final ServiceEvent
event)
+ {
+ // Collect the BundleContexts
+ Collection<BundleContext> contexts = new HashSet<BundleContext>();
+ for (ServiceListenerRegistration listener : listeners)
+ {
+ BundleContext context = listener.getBundleContext();
+ if (context != null)
+ contexts.add(context);
+ }
+ contexts = new RemoveOnlyCollection<BundleContext>(contexts);
+
+ // Call the registered event hooks
+ List<EventHook> eventHooks = getEventHooks();
+ for (EventHook hook : eventHooks)
+ {
+ try
+ {
+ hook.event(event, contexts);
+ }
+ catch (Exception ex)
+ {
+ log.warn("Error while calling EventHook: " + hook, ex);
+ }
+ }
+
+ // Remove the listeners that have been filtered by the EventHooks
+ if (contexts.size() != listeners.size())
+ {
+ Iterator<ServiceListenerRegistration> it = listeners.iterator();
+ while (it.hasNext())
+ {
+ ServiceListenerRegistration slreg = it.next();
+ if (contexts.contains(slreg.getBundleContext()) == false)
+ it.remove();
+ }
+ }
+ return listeners;
+ }
+
@SuppressWarnings("unchecked")
private List<EventHook> getEventHooks()
{
@@ -833,97 +846,4 @@
return "ServiceEvent[type=" + ConstantsHelper.serviceEvent(getType())
+ ",source=" + getSource() + "]";
}
}
-
- /**
- * A Collection that does not allow add operations.
- */
- @SuppressWarnings("rawtypes")
- static class RemoveOnlyCollection<T> implements Collection<T>
- {
- Collection<T> delegate;
-
- RemoveOnlyCollection(Collection<T> delegate)
- {
- this.delegate = delegate;
- }
-
- @Override
- public int size()
- {
- return delegate.size();
- }
-
- @Override
- public boolean isEmpty()
- {
- return delegate.isEmpty();
- }
-
- @Override
- public boolean contains(Object o)
- {
- return delegate.contains(o);
- }
-
- @Override
- public Iterator<T> iterator()
- {
- return delegate.iterator();
- }
-
- @Override
- public Object[] toArray()
- {
- return delegate.toArray();
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public Object[] toArray(Object[] a)
- {
- return delegate.toArray(a);
- }
-
- @Override
- public boolean add(Object e)
- {
- throw new ServiceException("Add not supported");
- }
-
- @Override
- public boolean remove(Object o)
- {
- return delegate.remove(o);
- }
-
- @Override
- public boolean containsAll(Collection c)
- {
- return delegate.containsAll(c);
- }
-
- @Override
- public boolean addAll(Collection c)
- {
- throw new ServiceException("Add not supported");
- }
-
- @Override
- public boolean removeAll(Collection c)
- {
- return delegate.removeAll(c);
- }
-
- @Override
- public boolean retainAll(Collection c)
- {
- return delegate.removeAll(c);
- }
-
- @Override
- public void clear()
- {
- delegate.clear();
- }
- }
}
\ No newline at end of file
Added:
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/util/RemoveOnlyCollection.java
===================================================================
---
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/util/RemoveOnlyCollection.java
(rev 0)
+++
projects/jboss-osgi/projects/runtime/framework/trunk/core/src/main/java/org/jboss/osgi/framework/util/RemoveOnlyCollection.java 2010-03-21
19:48:04 UTC (rev 102691)
@@ -0,0 +1,123 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.osgi.framework.util;
+
+//$Id: SystemPackagesPluginImpl.java 92858 2009-08-27 10:58:32Z thomas.diesler(a)jboss.com
$
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A Collection that does not allow add operations.
+ *
+ * @author thomas.diesler(a)jboss.com
+ * @since 21-MAr-2010
+ */
+@SuppressWarnings("rawtypes")
+public class RemoveOnlyCollection<T> implements Collection<T>
+{
+ Collection<T> delegate;
+
+ public RemoveOnlyCollection(Collection<T> delegate)
+ {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public int size()
+ {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o)
+ {
+ return delegate.contains(o);
+ }
+
+ @Override
+ public Iterator<T> iterator()
+ {
+ return delegate.iterator();
+ }
+
+ @Override
+ public Object[] toArray()
+ {
+ return delegate.toArray();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object[] toArray(Object[] a)
+ {
+ return delegate.toArray(a);
+ }
+
+ @Override
+ public boolean add(Object e)
+ {
+ throw new UnsupportedOperationException("Add not supported");
+ }
+
+ @Override
+ public boolean remove(Object o)
+ {
+ return delegate.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection c)
+ {
+ return delegate.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection c)
+ {
+ throw new UnsupportedOperationException("Add not supported");
+ }
+
+ @Override
+ public boolean removeAll(Collection c)
+ {
+ return delegate.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection c)
+ {
+ return delegate.removeAll(c);
+ }
+
+ @Override
+ public void clear()
+ {
+ delegate.clear();
+ }
+}
\ No newline at end of file