FELIX-4505 : [Core R6] Support Prototype Service Factory
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1615093 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
index 436dcc5..ed0f52b 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -20,10 +20,12 @@
import java.io.File;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
+import java.util.List;
import org.apache.felix.framework.ext.FelixBundleContext;
import org.osgi.framework.AdminPermission;
@@ -467,25 +469,20 @@
((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
}
- return m_felix.getService(m_bundle, ref);
+ return m_felix.getService(m_bundle, ref, false);
}
public boolean ungetService(ServiceReference<?> ref)
{
checkValidity();
- // CONCURRENCY NOTE: This is a check-then-act situation,
- // but we ignore it since the time window is small and
- // the result is the same as if the calling thread had
- // won the race condition.
-
if (ref == null)
{
throw new NullPointerException("Specified service reference cannot be null.");
}
// Unget the specified service.
- return m_felix.ungetService(m_bundle, ref);
+ return m_felix.ungetService(m_bundle, ref, null);
}
public File getDataFile(String s)
@@ -531,7 +528,14 @@
*/
public <S> ServiceObjects<S> getServiceObjects(final ServiceReference<S> ref)
{
- return new ServiceObjectsImpl(ref);
+ checkValidity();
+ ServiceRegistrationImpl reg =
+ ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration();
+ if ( reg.isValid() )
+ {
+ return new ServiceObjectsImpl(ref);
+ }
+ return null;
}
//
@@ -541,30 +545,89 @@
{
private final ServiceReference<S> m_ref;
+ private final List<S> srvObjects = new ArrayList<S>();
+
public ServiceObjectsImpl(final ServiceReference<S> ref)
{
this.m_ref = ref;
}
public S getService() {
+ S srvObj = null;
// special handling for prototype scope
if ( m_ref.getProperty(Constants.SERVICE_SCOPE) == Constants.SCOPE_PROTOTYPE )
{
- throw new UnsupportedOperationException();
+ checkValidity();
+
+ // CONCURRENCY NOTE: This is a check-then-act situation,
+ // but we ignore it since the time window is small and
+ // the result is the same as if the calling thread had
+ // won the race condition.
+
+ Object sm = System.getSecurityManager();
+
+ if (sm != null)
+ {
+ ((SecurityManager) sm).checkPermission(new ServicePermission(m_ref, ServicePermission.GET));
+ }
+
+ srvObj = m_felix.getService(m_bundle, m_ref, true);
+ }
+ else
+ {
+ // getService handles singleton and bundle scope
+ srvObj = BundleContextImpl.this.getService(m_ref);
}
- // getService handles singleton and bundle scope
- return BundleContextImpl.this.getService(m_ref);
+
+ if ( srvObj != null )
+ {
+ synchronized ( srvObjects )
+ {
+ srvObjects.add(srvObj);
+ }
+ }
+
+ return srvObj;
}
- public void ungetService(final S service)
+ public void ungetService(final S srvObj)
{
+ if ( srvObj != null )
+ {
+ // check if this object was returned by this service objects
+ synchronized ( srvObjects )
+ {
+ boolean found = false;
+ int i = 0;
+ while ( !found && i < srvObjects.size() )
+ {
+ found = srvObjects.get(i) == srvObj;
+ i++;
+ }
+ if ( !found )
+ {
+ throw new IllegalArgumentException();
+ }
+ srvObjects.remove(i-1);
+ }
+
+ }
// special handling for prototype scope
if ( m_ref.getProperty(Constants.SERVICE_SCOPE) == Constants.SCOPE_PROTOTYPE )
{
- throw new UnsupportedOperationException();
+ checkValidity();
+
+ // Unget the specified service.
+ if ( !m_felix.ungetService(m_bundle, m_ref, srvObj) )
+ {
+ throw new IllegalArgumentException();
+ }
}
- // ungetService handles singleton and bundle scope
- BundleContextImpl.this.ungetService(m_ref);
+ else
+ {
+ // ungetService handles singleton and bundle scope
+ BundleContextImpl.this.ungetService(m_ref);
+ }
}
public ServiceReference<S> getServiceReference()
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index f04bac7..280bc85 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -1278,7 +1278,7 @@
Collection<Bundle> shrinkableCollisionCandidates = new ShrinkableCollection<Bundle>(collisionCanditates);
for (ServiceReference<CollisionHook> hook : hooks)
{
- CollisionHook ch = getFramework().getService(getFramework(), hook);
+ CollisionHook ch = getFramework().getService(getFramework(), hook, false);
if (ch != null)
{
int operationType;
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
index 8d2a967..2c4336d 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -591,7 +591,7 @@
private static List<Wire> asWireList(List wires)
{
- return (List<Wire>) wires;
+ return wires;
}
public List<Wire> getProvidedResourceWires(String namespace)
@@ -706,7 +706,7 @@
// enabled; otherwise, create it directly.
try
{
- Constructor ctor = (Constructor) BundleRevisionImpl.getSecureAction()
+ Constructor ctor = BundleRevisionImpl.getSecureAction()
.getConstructor(clazz, new Class[] { BundleWiringImpl.class, ClassLoader.class });
m_classLoader = (BundleClassLoader)
BundleRevisionImpl.getSecureAction().invoke(ctor,
@@ -1521,11 +1521,11 @@
+ m_revision.getSymbolicName()
+ " is no longer valid.");
}
- result = (Object) ((BundleClassLoader) cl).findClass(name);
+ result = ((BundleClassLoader) cl).findClass(name);
}
else
{
- result = (Object) m_revision.getResourceLocal(name);
+ result = m_revision.getResourceLocal(name);
}
// If still not found, then try the revision's dynamic imports.
@@ -1883,6 +1883,7 @@
m_isParallel = registered;
}
+ @Override
protected boolean isParallel()
{
return m_isParallel;
@@ -2087,7 +2088,7 @@
// Note that we don't use the bundle context
// to get the service object since that would
// perform sercurity checks.
- WeavingHook wh = felix.getService(felix, sr);
+ WeavingHook wh = felix.getService(felix, sr, false);
if (wh != null)
{
try
@@ -2115,7 +2116,7 @@
}
finally
{
- felix.ungetService(felix, sr);
+ felix.ungetService(felix, sr, null);
}
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index cf3d073..fa2c129 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -3070,7 +3070,7 @@
bundles = new ShrinkableCollection<Bundle>(bundles);
for (ServiceReference<org.osgi.framework.hooks.bundle.FindHook> hook : hooks)
{
- org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook);
+ org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook, false);
if (fh != null)
{
try
@@ -3156,7 +3156,7 @@
bundles = new ShrinkableCollection<Bundle>(bundles);
for (ServiceReference<org.osgi.framework.hooks.bundle.FindHook> hook : hooks)
{
- org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook);
+ org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook, false);
if (fh != null)
{
try
@@ -3224,7 +3224,7 @@
bundles = new ShrinkableCollection<Bundle>(new ArrayList(bundles));
for (ServiceReference<org.osgi.framework.hooks.bundle.FindHook> hook : hooks)
{
- org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook);
+ org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook, false);
if (fh != null)
{
try
@@ -3298,7 +3298,7 @@
ServiceListener.class, l, oldFilter, null, true));
for (ServiceReference<org.osgi.framework.hooks.service.ListenerHook> sr : listenerHooks)
{
- org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr);
+ org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr, false);
if (lh != null)
{
try
@@ -3312,7 +3312,7 @@
}
finally
{
- m_registry.ungetService(this, sr);
+ m_registry.ungetService(this, sr, null);
}
}
}
@@ -3324,7 +3324,7 @@
ServiceListener.class, l, newFilter, null, false));
for (ServiceReference<org.osgi.framework.hooks.service.ListenerHook> sr : listenerHooks)
{
- org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr);
+ org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr, false);
if (lh != null)
{
try
@@ -3338,7 +3338,7 @@
}
finally
{
- m_registry.ungetService(this, sr);
+ m_registry.ungetService(this, sr, null);
}
}
}
@@ -3365,7 +3365,7 @@
Collection removed = Collections.singleton(listener);
for (ServiceReference<org.osgi.framework.hooks.service.ListenerHook> sr : listenerHooks)
{
- org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr);
+ org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr, false);
if (lh != null)
{
try
@@ -3379,7 +3379,7 @@
}
finally
{
- m_registry.ungetService(this, sr);
+ m_registry.ungetService(this, sr, null);
}
}
}
@@ -3454,7 +3454,7 @@
{
org.osgi.framework.hooks.service.ListenerHook lh =
(org.osgi.framework.hooks.service.ListenerHook)
- getService(this, reg.getReference());
+ getService(this, reg.getReference(), false);
if (lh != null)
{
try
@@ -3469,7 +3469,7 @@
}
finally
{
- m_registry.ungetService(this, reg.getReference());
+ m_registry.ungetService(this, reg.getReference(), null);
}
}
}
@@ -3534,7 +3534,7 @@
m_registry.getHooks(org.osgi.framework.hooks.service.FindHook.class);
for (ServiceReference<org.osgi.framework.hooks.service.FindHook> sr : findHooks)
{
- org.osgi.framework.hooks.service.FindHook fh = getService(this, sr);
+ org.osgi.framework.hooks.service.FindHook fh = getService(this, sr, false);
if (fh != null)
{
try
@@ -3554,7 +3554,7 @@
}
finally
{
- m_registry.ungetService(this, sr);
+ m_registry.ungetService(this, sr, null);
}
}
}
@@ -3616,11 +3616,11 @@
}
- <S> S getService(Bundle bundle, ServiceReference<S> ref)
+ <S> S getService(Bundle bundle, ServiceReference<S> ref, boolean isPrototype)
{
try
{
- return m_registry.getService(bundle, ref);
+ return m_registry.getService(bundle, ref, isPrototype);
}
catch (ServiceException ex)
{
@@ -3630,9 +3630,9 @@
return null;
}
- boolean ungetService(Bundle bundle, ServiceReference ref)
+ boolean ungetService(Bundle bundle, ServiceReference ref, Object srvObj)
{
- return m_registry.ungetService(bundle, ref);
+ return m_registry.ungetService(bundle, ref, srvObj);
}
File getDataFile(BundleImpl bundle, String s)
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
index e6509ce..715158f 100644
--- a/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
@@ -20,6 +20,7 @@
import java.util.ArrayList;
import java.util.List;
+
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -50,9 +51,10 @@
m_registry = registry;
}
+ @SuppressWarnings("unchecked")
void start()
{
- m_slReg = m_registry.registerService(m_felix._getBundleContext(),
+ m_slReg = (ServiceRegistration<StartLevel>) m_registry.registerService(m_felix._getBundleContext(),
new String[] { StartLevel.class.getName() },
new StartLevelImpl(m_felix),
null);
@@ -235,7 +237,7 @@
// Start thread if necessary.
startThread();
// Synchronously persists the start level.
- ((BundleImpl) m_bundle).setStartLevel(startlevel);
+ m_bundle.setStartLevel(startlevel);
// Queue request.
m_requestListeners.add(null);
m_requests.add(new Object[] { m_bundle, new Integer(startlevel) });
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
index ba51e43..5789947 100644
--- a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
@@ -49,9 +49,10 @@
m_registry = registry;
}
+ @SuppressWarnings("unchecked")
void start()
{
- m_paReg = m_registry.registerService(m_felix._getBundleContext(),
+ m_paReg = (ServiceRegistration<PackageAdmin>) m_registry.registerService(m_felix._getBundleContext(),
new String[] { PackageAdmin.class.getName() },
new PackageAdminImpl(m_felix),
null);
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
index 46c880b..f820a56 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
@@ -18,7 +18,17 @@
*/
package org.apache.felix.framework;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.capabilityset.SimpleFilter;
@@ -38,21 +48,21 @@
private final Logger m_logger;
private long m_currentServiceId = 1L;
// Maps bundle to an array of service registrations.
- private final Map m_regsMap = Collections.synchronizedMap(new HashMap());
+ private final Map<Bundle, ServiceRegistration<?>[]> m_regsMap = Collections.synchronizedMap(new HashMap<Bundle, ServiceRegistration<?>[]>());
// Capability set for all service registrations.
private final CapabilitySet m_regCapSet;
// Maps registration to thread to keep track when a
// registration is in use, which will cause other
// threads to wait.
- private final Map m_lockedRegsMap = new HashMap();
+ private final Map<ServiceRegistration<?>, Object> m_lockedRegsMap = new HashMap<ServiceRegistration<?>, Object>();
// Maps bundle to an array of usage counts.
- private final Map m_inUseMap = new HashMap();
+ private final Map<Bundle, UsageCount[]> m_inUseMap = new HashMap<Bundle, UsageCount[]>();
private final ServiceRegistryCallbacks m_callbacks;
- private final WeakHashMap<ServiceReference, ServiceReference> m_blackList =
- new WeakHashMap<ServiceReference, ServiceReference>();
+ private final WeakHashMap<ServiceReference<?>, ServiceReference<?>> m_blackList =
+ new WeakHashMap<ServiceReference<?>, ServiceReference<?>>();
private final static Class<?>[] m_hookClasses = {
org.osgi.framework.hooks.bundle.CollisionHook.class,
@@ -80,12 +90,12 @@
m_regCapSet = new CapabilitySet(indices, false);
}
- public ServiceReference[] getRegisteredServices(Bundle bundle)
+ public ServiceReference<?>[] getRegisteredServices(Bundle bundle)
{
- ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+ ServiceRegistration<?>[] regs = m_regsMap.get(bundle);
if (regs != null)
{
- List refs = new ArrayList(regs.length);
+ List<Object> refs = new ArrayList<Object>(regs.length);
for (int i = 0; i < regs.length; i++)
{
try
@@ -97,13 +107,13 @@
// Don't include the reference as it is not valid anymore
}
}
- return (ServiceReference[]) refs.toArray(new ServiceReference[refs.size()]);
+ return refs.toArray(new ServiceReference[refs.size()]);
}
return null;
}
// Caller is expected to fire REGISTERED event.
- public ServiceRegistration registerService(
+ public ServiceRegistration<?> registerService(
BundleContext context, String[] classNames, Object svcObj, Dictionary dict)
{
ServiceRegistrationImpl reg = null;
@@ -120,7 +130,7 @@
addHooks(classNames, svcObj, reg.getReference());
// Get the bundles current registered services.
- ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+ ServiceRegistration<?>[] regs = m_regsMap.get(bundle);
m_regsMap.put(bundle, addServiceRegistration(regs, reg));
m_regCapSet.addCapability((BundleCapabilityImpl) reg.getReference());
}
@@ -128,7 +138,7 @@
return reg;
}
- public void unregisterService(Bundle bundle, ServiceRegistration reg)
+ public void unregisterService(Bundle bundle, ServiceRegistration<?> reg)
{
// If this is a hook, it should be removed.
removeHook(reg.getReference());
@@ -142,7 +152,7 @@
// new bundles will be able to look up the service.
// Now remove the registered service.
- ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+ ServiceRegistration<?>[] regs = m_regsMap.get(bundle);
m_regsMap.put(bundle, removeServiceRegistration(regs, reg));
m_regCapSet.removeCapability((BundleCapabilityImpl) reg.getReference());
}
@@ -155,20 +165,32 @@
}
// Now forcibly unget the service object for all stubborn clients.
- ServiceReference ref = reg.getReference();
+ ServiceReference<?> ref = reg.getReference();
Bundle[] clients = getUsingBundles(ref);
for (int i = 0; (clients != null) && (i < clients.length); i++)
{
- while (ungetService(clients[i], reg.getReference()))
- ; // Keep removing until it is no longer possible
+ UsageCount[] usages = m_inUseMap.get(clients[i]);
+ for (int x = 0; (usages != null) && (x < usages.length); x++)
+ {
+ if (usages[x].m_ref.equals(ref))
+ {
+ ungetService(clients[i], ref, (usages[x].m_prototype ? usages[x].m_svcObj : null));
+ }
+ }
}
// Invalidate registration
((ServiceRegistrationImpl) reg).invalidate();
// Bundles are allowed to get a reference while unregistering
for (int i = 0; (clients != null) && (i < clients.length); i++)
{
- while (ungetService(clients[i], ref))
- ; // Keep removing until it is no longer possible
+ UsageCount[] usages = m_inUseMap.get(clients[i]);
+ for (int x = 0; (usages != null) && (x < usages.length); x++)
+ {
+ if (usages[x].m_ref.equals(ref))
+ {
+ ungetService(clients[i], ref, (usages[x].m_prototype ? usages[x].m_svcObj : null));
+ }
+ }
}
}
@@ -182,10 +204,10 @@
public void unregisterServices(Bundle bundle)
{
// Simply remove all service registrations for the bundle.
- ServiceRegistration[] regs = null;
+ ServiceRegistration<?>[] regs = null;
synchronized (this)
{
- regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+ regs = m_regsMap.get(bundle);
}
// Note, there is no race condition here with respect to the
@@ -231,7 +253,7 @@
else if ((className != null) && (filter != null))
{
// Return services matching the class name and filter.
- List filters = new ArrayList(2);
+ List<SimpleFilter> filters = new ArrayList<SimpleFilter>(2);
filters.add(new SimpleFilter(Constants.OBJECTCLASS, className, SimpleFilter.EQ));
filters.add(filter);
filter = new SimpleFilter(null, filters, SimpleFilter.AND);
@@ -240,15 +262,15 @@
Set<BundleCapability> matches = m_regCapSet.match(filter, false);
- return new ArrayList(matches);
+ return new ArrayList<BundleCapability>(matches);
}
- public synchronized ServiceReference[] getServicesInUse(Bundle bundle)
+ public synchronized ServiceReference<?>[] getServicesInUse(Bundle bundle)
{
- UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount[] usages = m_inUseMap.get(bundle);
if (usages != null)
{
- ServiceReference[] refs = new ServiceReference[usages.length];
+ ServiceReference<?>[] refs = new ServiceReference[usages.length];
for (int i = 0; i < refs.length; i++)
{
refs[i] = usages[i].m_ref;
@@ -258,7 +280,8 @@
return null;
}
- public <S> S getService(Bundle bundle, ServiceReference<S> ref)
+ @SuppressWarnings("unchecked")
+ public <S> S getService(Bundle bundle, ServiceReference<S> ref, boolean isPrototype)
{
UsageCount usage = null;
Object svcObj = null;
@@ -299,14 +322,15 @@
if (reg.isValid())
{
// Get the usage count, if any.
- usage = getUsageCount(bundle, ref);
+ // if prototype, we always create a new usage
+ usage = isPrototype ? null : getUsageCount(bundle, ref, null);
// If we don't have a usage count, then create one and
// since the spec says we increment usage count before
// actually getting the service object.
if (usage == null)
{
- usage = addUsageCount(bundle, ref);
+ usage = addUsageCount(bundle, ref, isPrototype);
}
// Increment the usage count and grab the already retrieved
@@ -340,7 +364,7 @@
// unregistered while we didn't hold the lock.
if (!reg.isValid() || (svcObj == null))
{
- flushUsageCount(bundle, ref);
+ flushUsageCount(bundle, ref, usage);
}
else
{
@@ -354,7 +378,7 @@
return (S) svcObj;
}
- public boolean ungetService(Bundle bundle, ServiceReference ref)
+ public boolean ungetService(Bundle bundle, ServiceReference<?> ref, Object svcObj)
{
UsageCount usage = null;
ServiceRegistrationImpl reg =
@@ -384,7 +408,7 @@
}
// Get the usage count.
- usage = getUsageCount(bundle, ref);
+ usage = getUsageCount(bundle, ref, svcObj);
// If there is no cached services, then just return immediately.
if (usage == null)
{
@@ -424,7 +448,7 @@
if (!reg.isValid() || (usage.m_count <= 0))
{
usage.m_svcObj = null;
- flushUsageCount(bundle, ref);
+ flushUsageCount(bundle, ref, usage);
}
// Release the registration lock so any waiting threads can
@@ -448,7 +472,7 @@
UsageCount[] usages;
synchronized (this)
{
- usages = (UsageCount[]) m_inUseMap.get(bundle);
+ usages = m_inUseMap.get(bundle);
}
if (usages == null)
@@ -466,21 +490,21 @@
for (int i = 0; i < usages.length; i++)
{
// Keep ungetting until all usage count is zero.
- while (ungetService(bundle, usages[i].m_ref))
+ while (ungetService(bundle, usages[i].m_ref, usages[i].m_prototype ? usages[i].m_svcObj : null))
{
// Empty loop body.
}
}
}
- public synchronized Bundle[] getUsingBundles(ServiceReference ref)
+ public synchronized Bundle[] getUsingBundles(ServiceReference<?> ref)
{
Bundle[] bundles = null;
- for (Iterator iter = m_inUseMap.entrySet().iterator(); iter.hasNext(); )
+ for (Iterator<Map.Entry<Bundle, UsageCount[]>> iter = m_inUseMap.entrySet().iterator(); iter.hasNext(); )
{
- Map.Entry entry = (Map.Entry) iter.next();
- Bundle bundle = (Bundle) entry.getKey();
- UsageCount[] usages = (UsageCount[]) entry.getValue();
+ Map.Entry<Bundle, UsageCount[]> entry = iter.next();
+ Bundle bundle = entry.getKey();
+ UsageCount[] usages = entry.getValue();
for (int useIdx = 0; useIdx < usages.length; useIdx++)
{
if (usages[useIdx].m_ref.equals(ref))
@@ -503,7 +527,7 @@
return bundles;
}
- void servicePropertiesModified(ServiceRegistration reg, Dictionary oldProps)
+ void servicePropertiesModified(ServiceRegistration<?> reg, Dictionary oldProps)
{
updateHook(reg.getReference());
if (m_callbacks != null)
@@ -518,8 +542,8 @@
return m_logger;
}
- private static ServiceRegistration[] addServiceRegistration(
- ServiceRegistration[] regs, ServiceRegistration reg)
+ private static ServiceRegistration<?>[] addServiceRegistration(
+ ServiceRegistration<?>[] regs, ServiceRegistration<?> reg)
{
if (regs == null)
{
@@ -527,7 +551,7 @@
}
else
{
- ServiceRegistration[] newRegs = new ServiceRegistration[regs.length + 1];
+ ServiceRegistration<?>[] newRegs = new ServiceRegistration[regs.length + 1];
System.arraycopy(regs, 0, newRegs, 0, regs.length);
newRegs[regs.length] = reg;
regs = newRegs;
@@ -535,8 +559,8 @@
return regs;
}
- private static ServiceRegistration[] removeServiceRegistration(
- ServiceRegistration[] regs, ServiceRegistration reg)
+ private static ServiceRegistration<?>[] removeServiceRegistration(
+ ServiceRegistration<?>[] regs, ServiceRegistration<?> reg)
{
for (int i = 0; (regs != null) && (i < regs.length); i++)
{
@@ -550,7 +574,7 @@
// Otherwise, we need to do some array copying.
else
{
- ServiceRegistration[] newRegs = new ServiceRegistration[regs.length - 1];
+ ServiceRegistration<?>[] newRegs = new ServiceRegistration[regs.length - 1];
System.arraycopy(regs, 0, newRegs, 0, i);
if (i < newRegs.length)
{
@@ -571,12 +595,14 @@
* @param ref The service reference to find in the bundle's usage counts.
* @return The associated usage count or null if not found.
**/
- private UsageCount getUsageCount(Bundle bundle, ServiceReference ref)
+ private UsageCount getUsageCount(Bundle bundle, ServiceReference<?> ref, final Object svcObj)
{
- UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount[] usages = m_inUseMap.get(bundle);
for (int i = 0; (usages != null) && (i < usages.length); i++)
{
- if (usages[i].m_ref.equals(ref))
+ if (usages[i].m_ref.equals(ref)
+ && ((svcObj == null && !usages[i].m_prototype)
+ || (usages[i].m_svcObj == svcObj && usages[i].m_prototype)))
{
return usages[i];
}
@@ -594,12 +620,13 @@
* @param ref The service reference of the acquired service.
* @param svcObj The service object of the acquired service.
**/
- private UsageCount addUsageCount(Bundle bundle, ServiceReference ref)
+ private UsageCount addUsageCount(Bundle bundle, ServiceReference<?> ref, boolean isPrototype)
{
- UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount[] usages = m_inUseMap.get(bundle);
UsageCount usage = new UsageCount();
usage.m_ref = ref;
+ usage.m_prototype = isPrototype;
if (usages == null)
{
@@ -630,12 +657,12 @@
* @param bundle The bundle whose usage count should be removed.
* @param ref The service reference whose usage count should be removed.
**/
- private void flushUsageCount(Bundle bundle, ServiceReference ref)
+ private void flushUsageCount(Bundle bundle, ServiceReference<?> ref, UsageCount uc)
{
- UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount[] usages = m_inUseMap.get(bundle);
for (int i = 0; (usages != null) && (i < usages.length); i++)
{
- if (usages[i].m_ref.equals(ref))
+ if ((uc == null && usages[i].m_ref.equals(ref)) || (uc == usages[i]))
{
// If this is the only usage, then point to empty list.
if ((usages.length - 1) == 0)
@@ -653,6 +680,7 @@
usages, i + 1, newUsages, i, newUsages.length - i);
}
usages = newUsages;
+ i--;
}
}
}
@@ -671,12 +699,12 @@
// Hook-related methods.
//
- boolean isHookBlackListed(ServiceReference sr)
+ boolean isHookBlackListed(ServiceReference<?> sr)
{
return m_blackList.containsKey(sr);
}
- void blackListHook(ServiceReference sr)
+ void blackListHook(ServiceReference<?> sr)
{
m_blackList.put(sr, sr);
}
@@ -731,7 +759,7 @@
}
}
- private void updateHook(ServiceReference ref)
+ private void updateHook(ServiceReference<?> ref)
{
// We maintain the hooks sorted, so if ranking has changed for example,
// we need to ensure the order remains correct by resorting the hooks.
@@ -757,7 +785,7 @@
}
}
- private void removeHook(ServiceReference ref)
+ private void removeHook(ServiceReference<?> ref)
{
Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref)
.getRegistration().getService();
@@ -790,25 +818,26 @@
Set<ServiceReference<?>> hooks = m_allHooks.get(hookClass);
if (hooks != null)
{
- SortedSet sorted = new TreeSet<ServiceReference<?>>(Collections.reverseOrder());
+ SortedSet<ServiceReference<?>> sorted = new TreeSet<ServiceReference<?>>(Collections.reverseOrder());
sorted.addAll(hooks);
return asTypedSortedSet(sorted);
}
- return Collections.EMPTY_SET;
+ return Collections.emptySet();
}
}
private static <S> SortedSet<ServiceReference<S>> asTypedSortedSet(
SortedSet<ServiceReference<?>> ss)
{
- return (SortedSet<ServiceReference<S>>) (SortedSet) ss;
+ return (SortedSet) ss;
}
private static class UsageCount
{
- public int m_count = 0;
- public ServiceReference m_ref = null;
- public Object m_svcObj = null;
+ public int m_count;
+ public ServiceReference<?> m_ref;
+ public Object m_svcObj;
+ public boolean m_prototype;
}
public interface ServiceRegistryCallbacks
diff --git a/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java b/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
index 6c6e75f..0270af8 100644
--- a/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java
@@ -31,6 +31,7 @@
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
+
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.capabilityset.SimpleFilter;
import org.apache.felix.framework.resolver.CandidateComparator;
@@ -41,7 +42,6 @@
import org.apache.felix.framework.util.ShrinkableCollection;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.R4Library;
-import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
import org.apache.felix.framework.wiring.BundleWireImpl;
import org.osgi.framework.Bundle;
@@ -566,7 +566,7 @@
throws BundleException
{
// This map maps the hook factory service to the actual hook objects. It
- // needs to be a map that preserves insertion order to ensure that we call
+ // needs to be a map that preserves insertion order to ensure that we call
// hooks in the correct order.
// The hooks are added in the order that m_felix.getHooks() returns them which
// is also the order in which they should be called.
@@ -595,13 +595,13 @@
triggers = Collections.unmodifiableSet(triggers);
BundleException rethrow = null;
-
+
// Create resolver hook objects by calling begin() on factory.
for (ServiceReference<ResolverHookFactory> ref : hookRefs)
{
try
{
- ResolverHookFactory rhf = m_felix.getService(m_felix, ref);
+ ResolverHookFactory rhf = m_felix.getService(m_felix, ref, false);
if (rhf != null)
{
ResolverHook hook =
@@ -621,7 +621,7 @@
ex);
// Resolver hook spec: if there is an exception during the resolve operation; abort.
// So we break here to make sure that no further resolver hooks are created.
- break;
+ break;
}
}
@@ -663,7 +663,7 @@
ex);
// Resolver hook spec: if there is an exception during the resolve operation; abort.
// So we break here to make sure that no further resolver operations are executed.
- break;
+ break;
}
}
@@ -751,7 +751,7 @@
{
invalid = true;
}
- m_felix.ungetService(m_felix, ref);
+ m_felix.ungetService(m_felix, ref, null);
}
if (invalid)
{
@@ -824,7 +824,7 @@
{
BundleCapability cap = itCand.next();
if (CapabilitySet.matches(
- (BundleCapabilityImpl) cap,
+ cap,
((BundleRequirementImpl) dynamics.get(dynIdx)).getFilter()))
{
dynReq = (BundleRequirementImpl) dynamics.get(dynIdx);
@@ -841,7 +841,7 @@
{
BundleCapability cap = itCand.next();
if (!CapabilitySet.matches(
- (BundleCapabilityImpl) cap, dynReq.getFilter()))
+ cap, dynReq.getFilter()))
{
itCand.remove();
}
@@ -1570,7 +1570,7 @@
{
final Map<ServiceReference<ResolverHookFactory>, ResolverHook> m_resolveHookMap;
final Collection<BundleRevision> m_brWhitelist;
-
+
/** The map passed in must be of an ordered type, so that the iteration order over the values
* is predictable.
*/
@@ -1580,8 +1580,8 @@
m_resolveHookMap = resolveHookMap;
m_brWhitelist = brWhiteList;
}
-
- Collection<BundleRevision> getBundleRevisionWhitelist()
+
+ Collection<BundleRevision> getBundleRevisionWhitelist()
{
return m_brWhitelist;
}
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
index 4eca450..d8dea4a 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
@@ -19,8 +19,6 @@
package org.apache.felix.framework;
import java.net.ContentHandler;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -29,7 +27,6 @@
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.url.URLStreamHandlerService;
-import org.osgi.util.tracker.ServiceTracker;
/**
* <p>
@@ -107,13 +104,13 @@
{
if (value.equals(((String[]) values)[valueIdx]))
{
- return m_framework.getService(m_framework, ref);
+ return m_framework.getService(m_framework, ref, false);
}
}
}
else if (value.equals(values))
{
- return m_framework.getService(m_framework, ref);
+ return m_framework.getService(m_framework, ref, false);
}
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
index c5c264c..fe6d0ad 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
@@ -585,7 +585,7 @@
new ShrinkableCollection(new ArrayList(entry.getValue()));
shrinkableMap.put(
entry.getKey(),
- (Collection<ListenerHook.ListenerInfo>) shrinkableCollection);
+ shrinkableCollection);
}
shrinkableMap =
new ShrinkableMap<BundleContext, Collection<ListenerHook.ListenerInfo>>
@@ -598,7 +598,7 @@
org.osgi.framework.hooks.service.EventListenerHook elh = null;
try
{
- elh = m_registry.getService(felix, sr);
+ elh = m_registry.getService(felix, sr, false);
}
catch (Exception ex)
{
@@ -618,7 +618,7 @@
}
finally
{
- m_registry.ungetService(felix, sr);
+ m_registry.ungetService(felix, sr, null);
}
}
}
@@ -675,7 +675,7 @@
T eh = null;
try
{
- eh = m_registry.getService(felix, sr);
+ eh = m_registry.getService(felix, sr, false);
}
catch (Exception ex)
{
@@ -705,7 +705,7 @@
}
finally
{
- m_registry.ungetService(felix, sr);
+ m_registry.ungetService(felix, sr, null);
}
}
}
diff --git a/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java b/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java
index 31eafd0..63496a5 100644
--- a/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java
@@ -66,7 +66,7 @@
{
differentBundle, identicalBundle
});
- Mockito.when(felixMock.getService(felixMock, chRef)).thenReturn(testCollisionHook);
+ Mockito.when(felixMock.getService(felixMock, chRef, false)).thenReturn(testCollisionHook);
// Mock the archive of the bundle being installed
Map<String, String> headerMap = new HashMap<String, String>();
@@ -129,7 +129,7 @@
{
differentBundle, identicalBundle
});
- Mockito.when(felixMock.getService(felixMock, chRef)).thenReturn(testCollisionHook);
+ Mockito.when(felixMock.getService(felixMock, chRef, false)).thenReturn(testCollisionHook);
// Mock the archive of the bundle being installed
Map<String, String> headerMap = new HashMap<String, String>();
@@ -185,7 +185,7 @@
{
differentBundle, identicalBundle
});
- Mockito.when(felixMock.getService(felixMock, chRef)).thenReturn(testCollisionHook);
+ Mockito.when(felixMock.getService(felixMock, chRef, false)).thenReturn(testCollisionHook);
// Mock the archive of the bundle being installed
Map<String, String> headerMap = new HashMap<String, String>();