@Override public void unregisterService(ServiceState serviceState) { List<ServiceName> serviceNames = serviceState.getServiceNames(); log.debug("Unregister service: " + serviceNames); AbstractBundle serviceOwner = serviceState.getServiceOwner(); // This event is synchronously delivered before the service has completed unregistering. eventsPlugin.fireServiceEvent(serviceOwner, ServiceEvent.UNREGISTERING, serviceState); // Remove from using bundles for (AbstractBundle bundleState : serviceState.getUsingBundlesInternal()) { while (ungetService(bundleState, serviceState)) ; } // Remove from owner bundle serviceOwner.removeRegisteredService(serviceState); // Unregister name associations for (ServiceName serviceName : serviceNames) { String[] clazzes = (String[]) serviceState.getProperty(Constants.OBJECTCLASS); for (String clazz : clazzes) unregisterNameAssociation(clazz, serviceName); } // Remove from controller ServiceName rootServiceName = serviceNames.get(0); try { ServiceController<?> controller = serviceContainer.getService(rootServiceName); controller.setMode(Mode.REMOVE); } catch (RuntimeException ex) { log.error("Cannot remove service: " + rootServiceName, ex); } }
@Override public boolean ungetService(AbstractBundle bundleState, ServiceState serviceState) { serviceState.ungetScopedValue(bundleState); int useCount = bundleState.removeServiceInUse(serviceState); if (useCount == 0) serviceState.removeUsingBundle(bundleState); return useCount >= 0; }
/* * 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. */ private List<ServiceState> processFindHooks( AbstractBundle bundle, String clazz, String filterStr, boolean checkAssignable, List<ServiceState> serviceStates) { BundleContext context = bundle.getBundleContext(); List<ServiceState> hookRefs = getServiceReferencesInternal(bundle, FindHook.class.getName(), null, true); if (hookRefs.isEmpty()) return serviceStates; // Event and Find Hooks can not be used to hide the services from the framework. if (clazz != null && clazz.startsWith(FindHook.class.getPackage().getName())) return serviceStates; // The order in which the find hooks are called is the reverse compareTo ordering of // their ServiceReferences. That is, the service with the highest ranking number must be called // first. List<ServiceReference> sortedHookRefs = new ArrayList<ServiceReference>(hookRefs); Collections.reverse(sortedHookRefs); List<FindHook> hooks = new ArrayList<FindHook>(); for (ServiceReference hookRef : sortedHookRefs) hooks.add((FindHook) context.getService(hookRef)); Collection<ServiceReference> hookParam = new ArrayList<ServiceReference>(); for (ServiceState aux : serviceStates) hookParam.add(aux.getReference()); hookParam = new RemoveOnlyCollection<ServiceReference>(hookParam); for (FindHook hook : hooks) { try { hook.find(context, clazz, filterStr, !checkAssignable, hookParam); } catch (Exception ex) { log.warn("Error while calling FindHook: " + hook, ex); } } List<ServiceState> result = new ArrayList<ServiceState>(); for (ServiceReference aux : hookParam) { ServiceState serviceState = ServiceState.assertServiceState(aux); result.add(serviceState); } return result; }
@Override public Object getService(AbstractBundle bundleState, ServiceState serviceState) { // If the service has been unregistered, null is returned. if (serviceState.isUnregistered()) return null; // Add the given service ref to the list of used services bundleState.addServiceInUse(serviceState); serviceState.addUsingBundle(bundleState); Object value = serviceState.getScopedValue(bundleState); // If the factory returned an invalid value // restore the service usage counts if (value == null) { bundleState.removeServiceInUse(serviceState); serviceState.removeUsingBundle(bundleState); } return value; }
@Override public Set<AbstractBundle> getUsingBundles(ServiceState serviceState) { return serviceState.getUsingBundlesInternal(); }
public List<ServiceState> getServiceReferencesInternal( AbstractBundle bundleState, String clazz, Filter filter, boolean checkAssignable) { if (bundleState == null) throw new IllegalArgumentException("Null bundleState"); List<ServiceName> serviceNames; if (clazz != null) { serviceNames = serviceNameMap.get(clazz); if (serviceNames == null) serviceNames = new ArrayList<ServiceName>(); // Add potentially registered xservcie ServiceName xserviceName = ServiceName.of(ModuleContext.XSERVICE_PREFIX, clazz); ServiceController<?> xservice = serviceContainer.getService(xserviceName); if (xservice != null) serviceNames.add(xserviceName); } else { // [MSC-9] Add ability to query the ServiceContainer Set<ServiceName> allServiceNames = new HashSet<ServiceName>(); for (List<ServiceName> auxList : serviceNameMap.values()) allServiceNames.addAll(auxList); serviceNames = new ArrayList<ServiceName>(allServiceNames); } if (serviceNames.isEmpty()) return Collections.emptyList(); if (filter == null) filter = NoFilter.INSTANCE; List<ServiceState> result = new ArrayList<ServiceState>(); for (ServiceName serviceName : serviceNames) { ServiceController<?> controller = serviceContainer.getService(serviceName); if (controller == null) throw new IllegalStateException("Cannot obtain service for: " + serviceName); Object value = controller.getValue(); // Create the ServiceState on demand for an XService instance // [TODO] This should be done eagerly to keep the serviceId constant // [TODO] service events for XService lifecycle changes // [MSC-17] Canonical ServiceName string representation if (value instanceof ServiceState == false && serviceName.toString().contains(ModuleContext.XSERVICE_PREFIX)) { long serviceId = getNextServiceId(); Bundle bundle = packageAdmin.getBundle(value.getClass()); AbstractBundle owner = AbstractBundle.assertBundleState(bundle); value = new ServiceState( owner, serviceId, new ServiceName[] {serviceName}, new String[] {clazz}, value, null); } ServiceState serviceState = (ServiceState) value; if (filter.match(serviceState) == false) continue; Object rawValue = serviceState.getRawValue(); checkAssignable &= (clazz != null); checkAssignable &= (bundleState.getBundleId() != 0); checkAssignable &= !(rawValue instanceof ServiceFactory); if (checkAssignable == false || serviceState.isAssignableTo(bundleState, clazz)) { result.add(serviceState); } } // Sort the result Collections.sort(result, ServiceReferenceComparator.getInstance()); Collections.reverse(result); return Collections.unmodifiableList(result); }