Return-Path: X-Original-To: apmail-felix-commits-archive@www.apache.org Delivered-To: apmail-felix-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 31332118E0 for ; Fri, 1 Aug 2014 13:19:19 +0000 (UTC) Received: (qmail 27150 invoked by uid 500); 1 Aug 2014 13:19:18 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 27108 invoked by uid 500); 1 Aug 2014 13:19:18 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 27099 invoked by uid 99); 1 Aug 2014 13:19:18 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 01 Aug 2014 13:19:18 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 01 Aug 2014 13:19:13 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 6263523892C0; Fri, 1 Aug 2014 13:18:46 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1615093 - in /felix/trunk/framework/src: main/java/org/apache/felix/framework/ main/java/org/apache/felix/framework/util/ test/java/org/apache/felix/framework/ Date: Fri, 01 Aug 2014 13:18:45 -0000 To: commits@felix.apache.org From: cziegeler@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140801131846.6263523892C0@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: cziegeler Date: Fri Aug 1 13:18:45 2014 New Revision: 1615093 URL: http://svn.apache.org/r1615093 Log: FELIX-4505 : [Core R6] Support Prototype Service Factory Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java felix/trunk/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java Fri Aug 1 13:18:45 2014 @@ -20,10 +20,12 @@ package org.apache.felix.framework; 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 @@ class BundleContextImpl implements Felix ((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 @@ class BundleContextImpl implements Felix */ public ServiceObjects getServiceObjects(final ServiceReference 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 @@ class BundleContextImpl implements Felix { private final ServiceReference m_ref; + private final List srvObjects = new ArrayList(); + public ServiceObjectsImpl(final ServiceReference 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(); + } + } + else + { + // ungetService handles singleton and bundle scope + BundleContextImpl.this.ungetService(m_ref); } - // ungetService handles singleton and bundle scope - BundleContextImpl.this.ungetService(m_ref); } public ServiceReference getServiceReference() Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java Fri Aug 1 13:18:45 2014 @@ -1278,7 +1278,7 @@ class BundleImpl implements Bundle, Bund Collection shrinkableCollisionCandidates = new ShrinkableCollection(collisionCanditates); for (ServiceReference hook : hooks) { - CollisionHook ch = getFramework().getService(getFramework(), hook); + CollisionHook ch = getFramework().getService(getFramework(), hook, false); if (ch != null) { int operationType; Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java Fri Aug 1 13:18:45 2014 @@ -591,7 +591,7 @@ public class BundleWiringImpl implements private static List asWireList(List wires) { - return (List) wires; + return wires; } public List getProvidedResourceWires(String namespace) @@ -706,7 +706,7 @@ public class BundleWiringImpl implements // 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 @@ public class BundleWiringImpl implements + 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 @@ public class BundleWiringImpl implements m_isParallel = registered; } + @Override protected boolean isParallel() { return m_isParallel; @@ -2087,7 +2088,7 @@ public class BundleWiringImpl implements // 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 @@ public class BundleWiringImpl implements } finally { - felix.ungetService(felix, sr); + felix.ungetService(felix, sr, null); } } } Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Fri Aug 1 13:18:45 2014 @@ -3070,7 +3070,7 @@ public class Felix extends BundleImpl im bundles = new ShrinkableCollection(bundles); for (ServiceReference 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 @@ public class Felix extends BundleImpl im bundles = new ShrinkableCollection(bundles); for (ServiceReference 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 @@ public class Felix extends BundleImpl im bundles = new ShrinkableCollection(new ArrayList(bundles)); for (ServiceReference 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 @@ public class Felix extends BundleImpl im ServiceListener.class, l, oldFilter, null, true)); for (ServiceReference 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 @@ public class Felix extends BundleImpl im } finally { - m_registry.ungetService(this, sr); + m_registry.ungetService(this, sr, null); } } } @@ -3324,7 +3324,7 @@ public class Felix extends BundleImpl im ServiceListener.class, l, newFilter, null, false)); for (ServiceReference 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 @@ public class Felix extends BundleImpl im } finally { - m_registry.ungetService(this, sr); + m_registry.ungetService(this, sr, null); } } } @@ -3365,7 +3365,7 @@ public class Felix extends BundleImpl im Collection removed = Collections.singleton(listener); for (ServiceReference 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 @@ public class Felix extends BundleImpl im } finally { - m_registry.ungetService(this, sr); + m_registry.ungetService(this, sr, null); } } } @@ -3454,7 +3454,7 @@ public class Felix extends BundleImpl im { 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 @@ public class Felix extends BundleImpl im } finally { - m_registry.ungetService(this, reg.getReference()); + m_registry.ungetService(this, reg.getReference(), null); } } } @@ -3534,7 +3534,7 @@ public class Felix extends BundleImpl im m_registry.getHooks(org.osgi.framework.hooks.service.FindHook.class); for (ServiceReference 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 @@ public class Felix extends BundleImpl im } finally { - m_registry.ungetService(this, sr); + m_registry.ungetService(this, sr, null); } } } @@ -3616,11 +3616,11 @@ public class Felix extends BundleImpl im } - S getService(Bundle bundle, ServiceReference ref) + S getService(Bundle bundle, ServiceReference ref, boolean isPrototype) { try { - return m_registry.getService(bundle, ref); + return m_registry.getService(bundle, ref, isPrototype); } catch (ServiceException ex) { @@ -3630,9 +3630,9 @@ public class Felix extends BundleImpl im 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) Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java Fri Aug 1 13:18:45 2014 @@ -20,6 +20,7 @@ package org.apache.felix.framework; 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 @@ class FrameworkStartLevelImpl implements m_registry = registry; } + @SuppressWarnings("unchecked") void start() { - m_slReg = m_registry.registerService(m_felix._getBundleContext(), + m_slReg = (ServiceRegistration) m_registry.registerService(m_felix._getBundleContext(), new String[] { StartLevel.class.getName() }, new StartLevelImpl(m_felix), null); @@ -235,7 +237,7 @@ class FrameworkStartLevelImpl implements // 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) }); Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java Fri Aug 1 13:18:45 2014 @@ -49,9 +49,10 @@ class FrameworkWiringImpl implements Fra m_registry = registry; } + @SuppressWarnings("unchecked") void start() { - m_paReg = m_registry.registerService(m_felix._getBundleContext(), + m_paReg = (ServiceRegistration) m_registry.registerService(m_felix._getBundleContext(), new String[] { PackageAdmin.class.getName() }, new PackageAdminImpl(m_felix), null); Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java Fri Aug 1 13:18:45 2014 @@ -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 @@ public class ServiceRegistry 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[]> m_regsMap = Collections.synchronizedMap(new HashMap[]>()); // 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, Object> m_lockedRegsMap = new HashMap, Object>(); // Maps bundle to an array of usage counts. - private final Map m_inUseMap = new HashMap(); + private final Map m_inUseMap = new HashMap(); private final ServiceRegistryCallbacks m_callbacks; - private final WeakHashMap m_blackList = - new WeakHashMap(); + private final WeakHashMap, ServiceReference> m_blackList = + new WeakHashMap, ServiceReference>(); private final static Class[] m_hookClasses = { org.osgi.framework.hooks.bundle.CollisionHook.class, @@ -80,12 +90,12 @@ public class ServiceRegistry 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 refs = new ArrayList(regs.length); for (int i = 0; i < regs.length; i++) { try @@ -97,13 +107,13 @@ public class ServiceRegistry // 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 @@ public class ServiceRegistry 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 @@ public class ServiceRegistry 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 @@ public class ServiceRegistry // 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 @@ public class ServiceRegistry } // 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 class ServiceRegistry 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 @@ public class ServiceRegistry else if ((className != null) && (filter != null)) { // Return services matching the class name and filter. - List filters = new ArrayList(2); + List filters = new ArrayList(2); filters.add(new SimpleFilter(Constants.OBJECTCLASS, className, SimpleFilter.EQ)); filters.add(filter); filter = new SimpleFilter(null, filters, SimpleFilter.AND); @@ -240,15 +262,15 @@ public class ServiceRegistry Set matches = m_regCapSet.match(filter, false); - return new ArrayList(matches); + return new ArrayList(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 @@ public class ServiceRegistry return null; } - public S getService(Bundle bundle, ServiceReference ref) + @SuppressWarnings("unchecked") + public S getService(Bundle bundle, ServiceReference ref, boolean isPrototype) { UsageCount usage = null; Object svcObj = null; @@ -299,14 +322,15 @@ public class ServiceRegistry 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 @@ public class ServiceRegistry // 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 @@ public class ServiceRegistry 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 @@ public class ServiceRegistry } // 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 @@ public class ServiceRegistry 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 @@ public class ServiceRegistry UsageCount[] usages; synchronized (this) { - usages = (UsageCount[]) m_inUseMap.get(bundle); + usages = m_inUseMap.get(bundle); } if (usages == null) @@ -466,21 +490,21 @@ public class ServiceRegistry 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> 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 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 @@ public class ServiceRegistry 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 @@ public class ServiceRegistry 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 @@ public class ServiceRegistry } 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 @@ public class ServiceRegistry 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 @@ public class ServiceRegistry // 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 @@ public class ServiceRegistry * @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 @@ public class ServiceRegistry * @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 @@ public class ServiceRegistry * @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 @@ public class ServiceRegistry usages, i + 1, newUsages, i, newUsages.length - i); } usages = newUsages; + i--; } } } @@ -671,12 +699,12 @@ public class ServiceRegistry // 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 @@ public class ServiceRegistry } } - 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 @@ public class ServiceRegistry } } - private void removeHook(ServiceReference ref) + private void removeHook(ServiceReference ref) { Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref) .getRegistration().getService(); @@ -790,25 +818,26 @@ public class ServiceRegistry Set> hooks = m_allHooks.get(hookClass); if (hooks != null) { - SortedSet sorted = new TreeSet>(Collections.reverseOrder()); + SortedSet> sorted = new TreeSet>(Collections.reverseOrder()); sorted.addAll(hooks); return asTypedSortedSet(sorted); } - return Collections.EMPTY_SET; + return Collections.emptySet(); } } private static SortedSet> asTypedSortedSet( SortedSet> ss) { - return (SortedSet>) (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 Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/StatefulResolver.java Fri Aug 1 13:18:45 2014 @@ -31,6 +31,7 @@ import java.util.Map.Entry; 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.resolv 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 @@ class StatefulResolver 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 @@ class StatefulResolver triggers = Collections.unmodifiableSet(triggers); BundleException rethrow = null; - + // Create resolver hook objects by calling begin() on factory. for (ServiceReference 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 @@ class StatefulResolver 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 @@ class StatefulResolver 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 @@ class StatefulResolver { invalid = true; } - m_felix.ungetService(m_felix, ref); + m_felix.ungetService(m_felix, ref, null); } if (invalid) { @@ -824,7 +824,7 @@ class StatefulResolver { BundleCapability cap = itCand.next(); if (CapabilitySet.matches( - (BundleCapabilityImpl) cap, + cap, ((BundleRequirementImpl) dynamics.get(dynIdx)).getFilter())) { dynReq = (BundleRequirementImpl) dynamics.get(dynIdx); @@ -841,7 +841,7 @@ class StatefulResolver { BundleCapability cap = itCand.next(); if (!CapabilitySet.matches( - (BundleCapabilityImpl) cap, dynReq.getFilter())) + cap, dynReq.getFilter())) { itCand.remove(); } @@ -1570,7 +1570,7 @@ class StatefulResolver { final Map, ResolverHook> m_resolveHookMap; final Collection 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 @@ class StatefulResolver m_resolveHookMap = resolveHookMap; m_brWhitelist = brWhiteList; } - - Collection getBundleRevisionWhitelist() + + Collection getBundleRevisionWhitelist() { return m_brWhitelist; } Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java Fri Aug 1 13:18:45 2014 @@ -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.BundleActivato import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.url.URLStreamHandlerService; -import org.osgi.util.tracker.ServiceTracker; /** *

@@ -107,13 +104,13 @@ class URLHandlersActivator implements Bu { 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); } } } Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/EventDispatcher.java Fri Aug 1 13:18:45 2014 @@ -585,7 +585,7 @@ public class EventDispatcher new ShrinkableCollection(new ArrayList(entry.getValue())); shrinkableMap.put( entry.getKey(), - (Collection) shrinkableCollection); + shrinkableCollection); } shrinkableMap = new ShrinkableMap> @@ -598,7 +598,7 @@ public class EventDispatcher 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 @@ public class EventDispatcher } finally { - m_registry.ungetService(felix, sr); + m_registry.ungetService(felix, sr, null); } } } @@ -675,7 +675,7 @@ public class EventDispatcher T eh = null; try { - eh = m_registry.getService(felix, sr); + eh = m_registry.getService(felix, sr, false); } catch (Exception ex) { @@ -705,7 +705,7 @@ public class EventDispatcher } finally { - m_registry.ungetService(felix, sr); + m_registry.ungetService(felix, sr, null); } } } Modified: felix/trunk/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java?rev=1615093&r1=1615092&r2=1615093&view=diff ============================================================================== --- felix/trunk/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java (original) +++ felix/trunk/framework/src/test/java/org/apache/felix/framework/CollisionHookTest.java Fri Aug 1 13:18:45 2014 @@ -66,7 +66,7 @@ public class CollisionHookTest extends T { 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 headerMap = new HashMap(); @@ -129,7 +129,7 @@ public class CollisionHookTest extends T { 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 headerMap = new HashMap(); @@ -185,7 +185,7 @@ public class CollisionHookTest extends T { 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 headerMap = new HashMap();