/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library 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 library 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. */ package com.liferay.registry.internal; import com.liferay.registry.Filter; import com.liferay.registry.Registry; import com.liferay.registry.ServiceReference; import com.liferay.registry.ServiceRegistrar; import com.liferay.registry.ServiceRegistration; import com.liferay.registry.ServiceTracker; import com.liferay.registry.ServiceTrackerCustomizer; import com.liferay.registry.dependency.ServiceDependencyManager; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; /** * @author Raymond Augé */ public class RegistryImpl implements Registry { public RegistryImpl(BundleContext bundleContext) { _bundleContext = bundleContext; } public void closeServiceTrackers() { Iterator<Reference<org.osgi.util.tracker.ServiceTracker<?, ?>>> iterator = _serviceTrackerReferences.iterator(); while (iterator.hasNext()) { Reference<org.osgi.util.tracker.ServiceTracker<?, ?>> serviceTrackerReference = iterator.next(); iterator.remove(); org.osgi.util.tracker.ServiceTracker<?, ?> serviceTracker = serviceTrackerReference.get(); if (serviceTracker != null) { try { serviceTracker.close(); } catch (Throwable t) { } } } // Drain the reference queue since there are no more service tracker // references while (_referenceQueue.poll() != null); } @Override public Filter getFilter(String filterString) throws RuntimeException { try { return new FilterWrapper(_bundleContext.createFilter(filterString)); } catch (InvalidSyntaxException ise) { throw new RuntimeException(ise); } } @Override public Registry getRegistry() throws SecurityException { return this; } @Override public <T> T getService(Class<T> clazz) { org.osgi.framework.ServiceReference<T> serviceReference = _bundleContext.getServiceReference(clazz); if (serviceReference == null) { return null; } return _bundleContext.getService(serviceReference); } @Override public <T> T getService(ServiceReference<T> serviceReference) { if (!(serviceReference instanceof ServiceReferenceWrapper)) { throw new IllegalArgumentException(); } ServiceReferenceWrapper<T> serviceReferenceWrapper = (ServiceReferenceWrapper<T>)serviceReference; return _bundleContext.getService( serviceReferenceWrapper.getServiceReference()); } @Override public <T> T getService(String className) { org.osgi.framework.ServiceReference<?> serviceReference = _bundleContext.getServiceReference(className); if (serviceReference == null) { return null; } return (T)_bundleContext.getService(serviceReference); } @Override public Collection<ServiceDependencyManager> getServiceDependencyManagers() { return Collections.unmodifiableCollection(_serviceDependencyManagers); } @Override public <T> ServiceReference<T> getServiceReference(Class<T> clazz) { org.osgi.framework.ServiceReference<T> serviceReference = _bundleContext.getServiceReference(clazz); if (serviceReference == null) { return null; } return new ServiceReferenceWrapper<>(serviceReference); } @Override public <T> ServiceReference<T> getServiceReference(String className) { org.osgi.framework.ServiceReference<T> serviceReference = (org.osgi.framework.ServiceReference<T>) _bundleContext.getServiceReference(className); if (serviceReference == null) { return null; } return new ServiceReferenceWrapper<>(serviceReference); } @Override public <T> Collection<ServiceReference<T>> getServiceReferences( Class<T> clazz, String filterString) throws Exception { Collection<org.osgi.framework.ServiceReference<T>> osgiServiceReferences = _bundleContext.getServiceReferences( clazz, filterString); if (osgiServiceReferences.isEmpty()) { return Collections.emptyList(); } Collection<ServiceReference<T>> serviceReferences = new ArrayList<>( osgiServiceReferences.size()); Iterator<org.osgi.framework.ServiceReference<T>> iterator = osgiServiceReferences.iterator(); while (iterator.hasNext()) { org.osgi.framework.ServiceReference<T> osgiServiceReference = iterator.next(); ServiceReference<T> serviceReference = new ServiceReferenceWrapper<>(osgiServiceReference); serviceReferences.add(serviceReference); } return serviceReferences; } @Override public <T> ServiceReference<T>[] getServiceReferences( String className, String filterString) throws Exception { org.osgi.framework.ServiceReference<T>[] osgiServiceReferences = (org.osgi.framework.ServiceReference<T>[]) _bundleContext.getServiceReferences(className, filterString); if (osgiServiceReferences == null) { return null; } ServiceReference<T>[] serviceReferences = new ServiceReference[osgiServiceReferences.length]; for (int i = 0; i < osgiServiceReferences.length; i++) { org.osgi.framework.ServiceReference<T> osgiServiceReference = osgiServiceReferences[i]; serviceReferences[i] = new ServiceReferenceWrapper<>( osgiServiceReference); } return serviceReferences; } @Override public <T> ServiceRegistrar<T> getServiceRegistrar(Class<T> clazz) { return new ServiceRegistrar<>(this, clazz); } @Override public <T> Collection<T> getServices(Class<T> clazz, String filterString) throws Exception { Collection<org.osgi.framework.ServiceReference<T>> serviceReferences = _bundleContext.getServiceReferences(clazz, filterString); if (serviceReferences.isEmpty()) { return Collections.emptyList(); } List<T> services = new ArrayList<>(); Iterator<org.osgi.framework.ServiceReference<T>> iterator = serviceReferences.iterator(); while (iterator.hasNext()) { org.osgi.framework.ServiceReference<T> serviceReference = iterator.next(); T service = _bundleContext.getService(serviceReference); if (service != null) { services.add(service); } } return services; } @Override public <T> T[] getServices(String className, String filterString) throws Exception { org.osgi.framework.ServiceReference<?>[] serviceReferences = _bundleContext.getServiceReferences(className, filterString); if (serviceReferences == null) { return null; } Object service = _bundleContext.getService(serviceReferences[0]); T[] services = (T[])Array.newInstance( service.getClass(), serviceReferences.length); services[0] = (T)service; for (int i = 1; i < serviceReferences.length; i++) { org.osgi.framework.ServiceReference<?> serviceReference = serviceReferences[i]; service = _bundleContext.getService(serviceReference); if (service != null) { services[i] = (T)service; } } return services; } @Override public <T> ServiceRegistration<T> registerService( Class<T> clazz, T service) { return registerService(clazz, service, null); } @Override public <T> ServiceRegistration<T> registerService( Class<T> clazz, T service, Map<String, Object> properties) { properties = _addBundleContextProperties(properties); org.osgi.framework.ServiceRegistration<T> serviceRegistration = _bundleContext.registerService( clazz, service, new MapWrapper(properties)); return new ServiceRegistrationWrapper<>(serviceRegistration); } @Override public <T> ServiceRegistration<T> registerService( String className, T service) { return registerService(className, service, null); } @Override @SuppressWarnings("rawtypes") public <T> ServiceRegistration<T> registerService( String className, T service, Map<String, Object> properties) { properties = _addBundleContextProperties(properties); org.osgi.framework.ServiceRegistration<?> serviceRegistration = _bundleContext.registerService( className, service, new MapWrapper(properties)); return new ServiceRegistrationWrapper(serviceRegistration); } @Override public <T> ServiceRegistration<T> registerService( String[] classNames, T service) { return registerService(classNames, service, null); } @Override @SuppressWarnings("rawtypes") public <T> ServiceRegistration<T> registerService( String[] classNames, T service, Map<String, Object> properties) { properties = _addBundleContextProperties(properties); org.osgi.framework.ServiceRegistration<?> serviceRegistration = _bundleContext.registerService( classNames, service, new MapWrapper(properties)); return new ServiceRegistrationWrapper(serviceRegistration); } @Override public synchronized void registerServiceDependencyManager( ServiceDependencyManager serviceDependencyManager) { _serviceDependencyManagers.add(serviceDependencyManager); } @Override public Registry setRegistry(Registry registry) throws SecurityException { return registry; } @Override public <S, T> ServiceTracker<S, T> trackServices(Class<S> clazz) { org.osgi.util.tracker.ServiceTracker<S, T> serviceTracker = new org.osgi.util.tracker.ServiceTracker<S, T>( _bundleContext, clazz, null); addServiceTracker(serviceTracker); return new ServiceTrackerWrapper<>(serviceTracker); } @Override public <S, T> ServiceTracker<S, T> trackServices( Class<S> clazz, ServiceTrackerCustomizer<S, T> serviceTrackerCustomizer) { org.osgi.util.tracker.ServiceTracker<S, T> serviceTracker = new org.osgi.util.tracker.ServiceTracker<S, T>( _bundleContext, clazz, new ServiceTrackerCustomizerAdapter<S, T>( serviceTrackerCustomizer)); addServiceTracker(serviceTracker); return new ServiceTrackerWrapper<>(serviceTracker); } @Override public <S, T> ServiceTracker<S, T> trackServices(Filter filter) { if (!(filter instanceof FilterWrapper)) { throw new IllegalArgumentException(); } FilterWrapper filterWrapper = (FilterWrapper)filter; org.osgi.util.tracker.ServiceTracker<S, T> serviceTracker = new org.osgi.util.tracker.ServiceTracker<S, T>( _bundleContext, filterWrapper.getFilter(), null); addServiceTracker(serviceTracker); return new ServiceTrackerWrapper<>(serviceTracker); } @Override public <S, T> ServiceTracker<S, T> trackServices( Filter filter, ServiceTrackerCustomizer<S, T> serviceTrackerCustomizer) { if (!(filter instanceof FilterWrapper)) { throw new IllegalArgumentException(); } FilterWrapper filterWrapper = (FilterWrapper)filter; org.osgi.util.tracker.ServiceTracker<S, T> serviceTracker = new org.osgi.util.tracker.ServiceTracker<S, T>( _bundleContext, filterWrapper.getFilter(), new ServiceTrackerCustomizerAdapter<S, T>( serviceTrackerCustomizer)); addServiceTracker(serviceTracker); return new ServiceTrackerWrapper<>(serviceTracker); } @Override public <S, T> ServiceTracker<S, T> trackServices(String className) { org.osgi.util.tracker.ServiceTracker<S, T> serviceTracker = new org.osgi.util.tracker.ServiceTracker<S, T>( _bundleContext, className, null); addServiceTracker(serviceTracker); return new ServiceTrackerWrapper<>(serviceTracker); } @Override public <S, T> ServiceTracker<S, T> trackServices( String className, ServiceTrackerCustomizer<S, T> serviceTrackerCustomizer) { org.osgi.util.tracker.ServiceTracker<S, T> serviceTracker = new org.osgi.util.tracker.ServiceTracker<S, T>( _bundleContext, className, new ServiceTrackerCustomizerAdapter<S, T>( serviceTrackerCustomizer)); addServiceTracker(serviceTracker); return new ServiceTrackerWrapper<>(serviceTracker); } @Override public <T> boolean ungetService(ServiceReference<T> serviceReference) { if (!(serviceReference instanceof ServiceReferenceWrapper)) { throw new IllegalArgumentException(); } ServiceReferenceWrapper<T> serviceReferenceWrapper = (ServiceReferenceWrapper<T>)serviceReference; return _bundleContext.ungetService( serviceReferenceWrapper.getServiceReference()); } @Override public void unregisterServiceDependencyManager( ServiceDependencyManager serviceDependencyManager) { _serviceDependencyManagers.remove(serviceDependencyManager); } protected void addServiceTracker( org.osgi.util.tracker.ServiceTracker<?, ?> serviceTracker) { Reference<org.osgi.util.tracker.ServiceTracker<?, ?>> reference = new WeakReference<org.osgi.util.tracker.ServiceTracker<?, ?>>( serviceTracker, _referenceQueue); _serviceTrackerReferences.add(reference); while ((reference = (Reference<org.osgi.util.tracker.ServiceTracker<?, ?>>) _referenceQueue.poll()) != null) { _serviceTrackerReferences.remove(reference); } } private Map<String, Object> _addBundleContextProperties( Map<String, Object> properties) { Bundle bundle = _bundleContext.getBundle(); if (properties == null) { properties = new HashMap<>(); } properties.put("bundle.id", bundle.getBundleId()); properties.put("bundle.symbolic.name", bundle.getSymbolicName()); properties.put("bundle.version", bundle.getVersion()); return properties; } private final BundleContext _bundleContext; private final ReferenceQueue<org.osgi.util.tracker.ServiceTracker<?, ?>> _referenceQueue = new ReferenceQueue<>(); private final Set<ServiceDependencyManager> _serviceDependencyManagers = new HashSet<>(); private final Set<Reference<org.osgi.util.tracker.ServiceTracker<?, ?>>> _serviceTrackerReferences = Collections.newSetFromMap( new ConcurrentHashMap <Reference<org.osgi.util.tracker.ServiceTracker<?, ?>>, Boolean>()); }