
com.liferay.registry.BasicRegistryImpl Maven / Gradle / Ivy
/**
* 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;
import com.liferay.registry.dependency.ServiceDependencyManager;
import com.liferay.registry.util.StringPlus;
import com.liferay.registry.util.UnmodifiableCaseInsensitiveMapDictionary;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author Raymond Augé
*/
public class BasicRegistryImpl implements Registry {
@Override
public Filter getFilter(String filterString) throws RuntimeException {
return new BasicFilter(filterString);
}
@Override
public Registry getRegistry() throws SecurityException {
return this;
}
@Override
public T getService(Class clazz) {
return getService(clazz.getName());
}
@Override
public T getService(ServiceReference serviceReference) {
BasicServiceReference> basicServiceReference =
(BasicServiceReference>)serviceReference;
for (Entry, Object> entry : _services.entrySet()) {
if (basicServiceReference.matches(entry.getKey())) {
return (T)entry.getValue();
}
}
return null;
}
@Override
public T getService(String className) {
Filter filter = getFilter("(objectClass=" + className + ")");
for (Entry, Object> entry : _services.entrySet()) {
if (filter.matches(entry.getKey())) {
return (T)entry.getValue();
}
}
return null;
}
@Override
public Collection getServiceDependencyManagers() {
return Collections.unmodifiableCollection(_serviceDependencyManagers);
}
@Override
public ServiceReference getServiceReference(Class clazz) {
return getServiceReference(clazz.getName());
}
@Override
public ServiceReference getServiceReference(String className) {
Filter filter = getFilter("(objectClass=" + className + ")");
for (Entry, Object> entry : _services.entrySet()) {
if (filter.matches(entry.getKey())) {
return (ServiceReference)entry.getKey();
}
}
return null;
}
@Override
public Collection> getServiceReferences(
Class clazz, String filterString)
throws Exception {
return Arrays.asList(
this.getServiceReferences(clazz.getName(), filterString));
}
@Override
public ServiceReference[] getServiceReferences(
String className, String filterString)
throws Exception {
List> serviceReferences = new ArrayList<>();
Filter filter = new BasicFilter(filterString);
for (Entry, Object> entry : _services.entrySet()) {
if (filter.matches(entry.getKey())) {
serviceReferences.add((ServiceReference)entry.getKey());
}
}
if (serviceReferences.isEmpty()) {
return null;
}
return serviceReferences.toArray(new ServiceReference[0]);
}
@Override
public ServiceRegistrar getServiceRegistrar(Class clazz) {
return new ServiceRegistrar<>(this, clazz);
}
@Override
public Collection getServices(Class clazz, String filterString)
throws Exception {
T[] services = getServices(clazz.getName(), filterString);
if (services == null) {
return Collections.emptyList();
}
return Arrays.asList(services);
}
@Override
public T[] getServices(String className, String filterString)
throws Exception {
List services = new ArrayList<>();
if ((filterString == null) || filterString.equals("")) {
filterString = "(objectClass=" + className + ")";
}
Filter filter = new BasicFilter(filterString);
for (Entry, Object> entry : _services.entrySet()) {
if (filter.matches(entry.getKey())) {
services.add((T)entry.getValue());
}
}
if (services.isEmpty()) {
return null;
}
T service = services.get(0);
Class> clazz = service.getClass();
T[] array = (T[])Array.newInstance(clazz, services.size());
return services.toArray(array);
}
@Override
public ServiceRegistration registerService(
Class clazz, T service) {
BasicServiceReference basicServiceReference =
new BasicServiceReference(
clazz.getName(), _serviceIdCounter.incrementAndGet(), 0,
new HashMap());
_addingService(basicServiceReference, service);
return new BasicServiceRegistration<>(basicServiceReference);
}
@Override
public ServiceRegistration registerService(
Class clazz, T service, Map properties) {
Integer serviceRanking = (Integer)properties.get("service.ranking");
if (serviceRanking == null) {
serviceRanking = Integer.valueOf(0);
}
BasicServiceReference basicServiceReference =
new BasicServiceReference(
clazz.getName(), _serviceIdCounter.incrementAndGet(),
serviceRanking.intValue(), properties);
_addingService(basicServiceReference, service);
return new BasicServiceRegistration<>(basicServiceReference);
}
@Override
public ServiceRegistration registerService(
String className, T service) {
BasicServiceReference basicServiceReference =
new BasicServiceReference(
className, _serviceIdCounter.incrementAndGet(), 0,
new HashMap());
_addingService(basicServiceReference, service);
return new BasicServiceRegistration<>(basicServiceReference);
}
@Override
public ServiceRegistration registerService(
String className, T service, Map properties) {
Integer serviceRanking = (Integer)properties.get("service.ranking");
if (serviceRanking == null) {
serviceRanking = Integer.valueOf(0);
}
BasicServiceReference basicServiceReference =
new BasicServiceReference(
className, _serviceIdCounter.incrementAndGet(),
serviceRanking.intValue(), properties);
_addingService(basicServiceReference, service);
return new BasicServiceRegistration<>(basicServiceReference);
}
@Override
public ServiceRegistration registerService(
String[] classNames, T service) {
if ((classNames == null) || (classNames.length == 0)) {
throw new IllegalArgumentException();
}
Map properties = new HashMap<>();
properties.put("objectClass", classNames);
BasicServiceReference basicServiceReference =
new BasicServiceReference(
classNames[0], _serviceIdCounter.incrementAndGet(), 0,
properties);
_addingService(basicServiceReference, service);
return new BasicServiceRegistration<>(basicServiceReference);
}
@Override
public ServiceRegistration registerService(
String[] classNames, T service, Map properties) {
if ((classNames == null) || (classNames.length == 0)) {
throw new IllegalArgumentException();
}
properties.put("objectClass", classNames);
Integer serviceRanking = (Integer)properties.get("service.ranking");
if (serviceRanking == null) {
serviceRanking = Integer.valueOf(0);
}
BasicServiceReference basicServiceReference =
new BasicServiceReference(
classNames[0], _serviceIdCounter.incrementAndGet(),
serviceRanking.intValue(), properties);
_addingService(basicServiceReference, service);
return new BasicServiceRegistration<>(basicServiceReference);
}
@Override
public synchronized void registerServiceDependencyManager(
ServiceDependencyManager serviceDependencyManager) {
_serviceDependencyManagers.add(serviceDependencyManager);
}
@Override
public Registry setRegistry(Registry registry) throws SecurityException {
return registry;
}
@Override
public ServiceTracker trackServices(Class clazz) {
Filter filter = new BasicFilter(
"(objectClass=" + clazz.getName() + ")");
return new BasicServiceTracker<>(filter);
}
@Override
public ServiceTracker trackServices(
Class clazz,
ServiceTrackerCustomizer serviceTrackerCustomizer) {
Filter filter = new BasicFilter(
"(objectClass=" + clazz.getName() + ")");
return new BasicServiceTracker<>(filter, serviceTrackerCustomizer);
}
@Override
public ServiceTracker trackServices(Filter filter) {
return new BasicServiceTracker<>(filter);
}
@Override
public ServiceTracker trackServices(
Filter filter,
ServiceTrackerCustomizer serviceTrackerCustomizer) {
return new BasicServiceTracker<>(filter, serviceTrackerCustomizer);
}
@Override
public ServiceTracker trackServices(String className) {
return new BasicServiceTracker<>(
new BasicFilter("(objectClass=" + className + ")"));
}
@Override
public ServiceTracker trackServices(
String className,
ServiceTrackerCustomizer serviceTrackerCustomizer) {
Filter filter = new BasicFilter("(objectClass=" + className + ")");
return new BasicServiceTracker<>(filter, serviceTrackerCustomizer);
}
@Override
public boolean ungetService(ServiceReference serviceReference) {
return true;
}
@Override
public void unregisterServiceDependencyManager(
ServiceDependencyManager serviceDependencyManager) {
_serviceDependencyManagers.remove(serviceDependencyManager);
}
private void _addingService(
BasicServiceReference basicServiceReference, S service) {
_services.put(basicServiceReference, service);
for (Map.Entry, Filter> entry :
_serviceTrackers.entrySet()) {
Filter filter = entry.getValue();
if (!filter.matches(basicServiceReference)) {
continue;
}
ServiceTracker serviceTracker =
(ServiceTracker)entry.getKey();
try {
serviceTracker.addingService(basicServiceReference);
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
private void _modifiedService(
BasicServiceReference basicServiceReference) {
for (Map.Entry, Filter> entry :
_serviceTrackers.entrySet()) {
Filter filter = entry.getValue();
if (!filter.matches(basicServiceReference)) {
continue;
}
ServiceTracker serviceTracker =
(ServiceTracker)entry.getKey();
T service = serviceTracker.getService(basicServiceReference);
if (service == null) {
continue;
}
try {
serviceTracker.modifiedService(basicServiceReference, service);
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
private void _removedService(
BasicServiceReference basicServiceReference) {
for (Map.Entry, Filter> entry :
_serviceTrackers.entrySet()) {
Filter filter = entry.getValue();
if (!filter.matches(basicServiceReference)) {
continue;
}
ServiceTracker serviceTracker =
(ServiceTracker)entry.getKey();
try {
serviceTracker.remove(basicServiceReference);
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
private final Set _serviceDependencyManagers =
new HashSet<>();
private final AtomicLong _serviceIdCounter = new AtomicLong();
private final Map, Object> _services =
new ConcurrentSkipListMap<>();
private final Map, Filter> _serviceTrackers =
new ConcurrentHashMap<>();
private static class BasicFilter implements Filter {
public BasicFilter(String filterString) {
_filter = new aQute.lib.filter.Filter(filterString);
}
@Override
public boolean matches(Map properties) {
Dictionary dictionary =
new UnmodifiableCaseInsensitiveMapDictionary<>(properties);
return _filter.match(dictionary);
}
@Override
public boolean matches(ServiceReference> serviceReference) {
BasicServiceReference> basicServiceReference =
(BasicServiceReference>)serviceReference;
Dictionary dictionary =
new UnmodifiableCaseInsensitiveMapDictionary<>(
basicServiceReference._properties);
return _filter.match(dictionary);
}
@Override
public boolean matchesCase(Map properties) {
return matches(properties);
}
@Override
public String toString() {
return _filter.toString();
}
private aQute.lib.filter.Filter _filter;
}
private static class LowerCaseKeyTreeMap extends TreeMap {
@Override
public Object put(String key, Object value) {
return super.put(key.toLowerCase(), value);
}
}
private class BasicServiceReference implements ServiceReference {
public BasicServiceReference(
String className, long id, int ranking,
Map properties) {
_properties.put("service.id", id);
_properties.put("service.ranking", ranking);
List classNames = new ArrayList<>();
classNames.add(className);
classNames.addAll(StringPlus.asList(properties.get("objectClass")));
_properties.putAll(properties);
_properties.put("objectClass", classNames);
}
@Override
public int compareTo(Object serviceReference) {
BasicServiceReference> otherServiceReference =
(BasicServiceReference>)serviceReference;
int thisServiceRanking = (Integer)_properties.get(
"service.ranking");
Map otherProperties =
otherServiceReference._properties;
int otherServiceRanking = (Integer)otherProperties.get(
"service.ranking");
if (thisServiceRanking != otherServiceRanking) {
if (thisServiceRanking < otherServiceRanking) {
return -1;
}
return 1;
}
long thisServiceId = (Long)_properties.get("service.id");
long otherServiceId = (Long)otherProperties.get("service.id");
if (thisServiceId == otherServiceId) {
return 0;
}
if (thisServiceId < otherServiceId) {
return 1;
}
return -1;
}
@Override
public Map getProperties() {
return new HashMap<>(_properties);
}
@Override
public Object getProperty(String key) {
return _properties.get(key.toLowerCase());
}
@Override
public String[] getPropertyKeys() {
Set set = _properties.keySet();
return set.toArray(new String[set.size()]);
}
public boolean matches(ServiceReference> serviceReference) {
Filter filter = new BasicFilter(toString());
return filter.matches(serviceReference);
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
Set> entrySet = _properties.entrySet();
if (entrySet.size() > 1) {
stringBuilder.append('(');
stringBuilder.append('&');
}
for (Entry entry : entrySet) {
String key = entry.getKey();
Object value = entry.getValue();
Object[] array = null;
Class> clazz = value.getClass();
if (clazz.isArray()) {
array = (Object[])value;
}
else if (value instanceof Collection) {
Collection> collection = (Collection>)value;
array = collection.toArray();
}
else {
array = new Object[] {value};
}
if (array.length > 0) {
for (Object object : array) {
stringBuilder.append('(');
stringBuilder.append(key);
stringBuilder.append('=');
stringBuilder.append(object);
stringBuilder.append(')');
}
}
}
if (entrySet.size() > 1) {
stringBuilder.append(')');
}
return stringBuilder.toString();
}
private final Map _properties =
new LowerCaseKeyTreeMap();
}
private class BasicServiceRegistration
implements ServiceRegistration {
public BasicServiceRegistration(
BasicServiceReference basicServiceReference) {
_basicServiceReference = basicServiceReference;
}
@Override
public ServiceReference getServiceReference() {
return _basicServiceReference;
}
@Override
public void setProperties(Map properties) {
_basicServiceReference._properties.putAll(properties);
_modifiedService(_basicServiceReference);
}
@Override
public void unregister() {
_services.remove(_basicServiceReference);
_removedService(_basicServiceReference);
}
private final BasicServiceReference _basicServiceReference;
}
private class BasicServiceTracker implements ServiceTracker {
public BasicServiceTracker(Filter filter) {
this(filter, null);
}
public BasicServiceTracker(
Filter filter,
ServiceTrackerCustomizer serviceTrackerCustomizer) {
_filter = filter;
_serviceTrackerCustomizer = serviceTrackerCustomizer;
}
@Override
public T addingService(ServiceReference serviceReference) {
T service = null;
try {
if (_serviceTrackerCustomizer != null) {
service = _serviceTrackerCustomizer.addingService(
serviceReference);
}
else {
service = (T)BasicRegistryImpl.this.getService(
serviceReference);
}
if (service == null) {
return null;
}
_trackedServices.put(serviceReference, service);
return service;
}
finally {
if (service != null) {
_stateCounter.incrementAndGet();
_countDownLatch.countDown();
}
}
}
@Override
public void close() {
_serviceTrackers.remove(this);
Set, T>> set =
_trackedServices.entrySet();
Iterator, T>> iterator = set.iterator();
while (iterator.hasNext()) {
Entry, T> entry = iterator.next();
iterator.remove();
removedService(entry.getKey(), entry.getValue());
}
_trackedServices.clear();
}
@Override
public T getService() {
Entry, T> firstEntry =
_trackedServices.firstEntry();
if (firstEntry == null) {
return null;
}
return firstEntry.getValue();
}
@Override
public T getService(ServiceReference serviceReference) {
BasicServiceReference basicServiceReference =
(BasicServiceReference)serviceReference;
for (ServiceReference curServiceReference :
_trackedServices.keySet()) {
if (basicServiceReference.matches(curServiceReference)) {
return _trackedServices.get(curServiceReference);
}
}
return null;
}
@Override
public ServiceReference getServiceReference() {
return _trackedServices.firstKey();
}
@Override
public ServiceReference[] getServiceReferences() {
Set set = (Set)_trackedServices.keySet();
return set.toArray(new ServiceReference[_trackedServices.size()]);
}
@Override
public Object[] getServices() {
Collection values = _trackedServices.values();
return values.toArray();
}
@Override
public T[] getServices(T[] services) {
Collection values = _trackedServices.values();
return values.toArray(services);
}
@Override
public SortedMap, T> getTrackedServiceReferences() {
return _trackedServices;
}
@Override
public int getUpdateMarker() {
return _stateCounter.get();
}
@Override
public boolean isEmpty() {
return _trackedServices.isEmpty();
}
@Override
public void modifiedService(
ServiceReference serviceReference, T service) {
try {
if (_serviceTrackerCustomizer != null) {
_serviceTrackerCustomizer.modifiedService(
serviceReference, service);
}
}
finally {
_stateCounter.incrementAndGet();
}
}
@Override
public void open() {
_serviceTrackers.put(this, _filter);
Set, Object>> set = _services.entrySet();
Iterator, Object>> iterator =
set.iterator();
while (iterator.hasNext()) {
Entry, Object> entry = iterator.next();
BasicServiceReference> basicServiceReference =
(BasicServiceReference>)entry.getKey();
if (_filter.matches(basicServiceReference._properties)) {
ServiceReference serviceReference =
(ServiceReference)entry.getKey();
addingService(serviceReference);
}
}
}
@Override
public void open(boolean trackAllServices) {
open();
}
@Override
public void remove(ServiceReference serviceReference) {
T service = _trackedServices.remove(serviceReference);
if (_trackedServices.isEmpty()) {
_countDownLatch = new CountDownLatch(1);
}
removedService(serviceReference, service);
}
@Override
public void removedService(
ServiceReference serviceReference, T service) {
try {
if (_serviceTrackerCustomizer != null) {
_serviceTrackerCustomizer.removedService(
serviceReference, service);
}
}
finally {
_stateCounter.incrementAndGet();
}
}
@Override
public int size() {
return _trackedServices.size();
}
@Override
public T waitForService(long timeout) throws InterruptedException {
_countDownLatch.await(timeout, TimeUnit.MILLISECONDS);
return getService();
}
private volatile CountDownLatch _countDownLatch = new CountDownLatch(1);
private Filter _filter;
private final ServiceTrackerCustomizer _serviceTrackerCustomizer;
private final AtomicInteger _stateCounter = new AtomicInteger();
private final NavigableMap, T> _trackedServices =
new ConcurrentSkipListMap<>();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy