/**
* 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.portal.kernel.model;
import com.liferay.portal.kernel.bean.ClassLoaderBeanHandler;
import com.liferay.portal.kernel.util.ProxyUtil;
import com.liferay.portal.kernel.util.ReflectionUtil;
import com.liferay.registry.Filter;
import com.liferay.registry.Registry;
import com.liferay.registry.RegistryUtil;
import com.liferay.registry.ServiceReference;
import com.liferay.registry.ServiceRegistration;
import com.liferay.registry.ServiceTracker;
import com.liferay.registry.ServiceTrackerCustomizer;
import java.lang.reflect.InvocationHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author Peter Fellwock
*/
public class ModelListenerRegistrationUtil {
public static <T> ModelListener<T>[] getModelListeners(Class<T> clazz) {
return _instance._getModelListeners(clazz);
}
public static void register(ModelListener<?> modelListener) {
Class<?> clazz = modelListener.getClass();
_instance._register(clazz.getName(), modelListener);
}
public static void unregister(ModelListener<?> modelListener) {
Class<?> clazz = modelListener.getClass();
_instance._unregister(clazz.getName());
}
private ModelListenerRegistrationUtil() {
Registry registry = RegistryUtil.getRegistry();
Filter filter = registry.getFilter(
"(objectClass=" + ModelListener.class.getName() + ")");
_serviceTracker = registry.trackServices(
filter, new ModelListenerTrackerCustomizer());
_serviceTracker.open();
}
private <T> ModelListener<T>[] _getModelListeners(Class<T> clazz) {
List<ModelListener<?>> modelListeners = _modelListeners.get(clazz);
if (modelListeners == null) {
modelListeners = new ArrayList<>();
List<ModelListener<?>> previousModelListeners =
_modelListeners.putIfAbsent(clazz, modelListeners);
if (previousModelListeners != null) {
modelListeners = previousModelListeners;
}
}
return modelListeners.toArray(new ModelListener[modelListeners.size()]);
}
private <T> void _register(
String className, ModelListener<T> modelListener) {
Registry registry = RegistryUtil.getRegistry();
ServiceRegistration<?> serviceRegistration = registry.registerService(
ModelListener.class.getName(), modelListener);
_serviceRegistrations.put(className, serviceRegistration);
}
private void _unregister(String className) {
ServiceRegistration<?> serviceRegistration =
_serviceRegistrations.remove(className);
if (serviceRegistration != null) {
serviceRegistration.unregister();
}
}
private static final ModelListenerRegistrationUtil _instance =
new ModelListenerRegistrationUtil();
private final ConcurrentMap<Class<?>, List<ModelListener<?>>>
_modelListeners = new ConcurrentHashMap<>();
private final Map<String, ServiceRegistration<?>> _serviceRegistrations =
new ConcurrentHashMap<>();
private final ServiceTracker<ModelListener<?>, ModelListener<?>>
_serviceTracker;
private class ModelListenerTrackerCustomizer
implements
ServiceTrackerCustomizer<ModelListener<?>, ModelListener<?>> {
@Override
public ModelListener<?> addingService(
ServiceReference<ModelListener<?>> serviceReference) {
Registry registry = RegistryUtil.getRegistry();
ModelListener<?> modelListener = registry.getService(
serviceReference);
Class<?> modelClass = _getModelClass(modelListener);
if (modelClass == null) {
return null;
}
List<ModelListener<?>> modelListeners = _modelListeners.get(
modelClass);
if (modelListeners == null) {
modelListeners = new ArrayList<>();
List<ModelListener<?>> previousModelListeners =
_modelListeners.putIfAbsent(modelClass, modelListeners);
if (previousModelListeners != null) {
modelListeners = previousModelListeners;
}
}
modelListeners.add(modelListener);
return modelListener;
}
@Override
public void modifiedService(
ServiceReference<ModelListener<?>> serviceReference,
ModelListener<?> modelListener) {
}
@Override
public void removedService(
ServiceReference<ModelListener<?>> serviceReference,
ModelListener<?> modelListener) {
Registry registry = RegistryUtil.getRegistry();
registry.ungetService(serviceReference);
Class<?> modelClass = _getModelClass(modelListener);
List<ModelListener<?>> modelListeners = _modelListeners.get(
modelClass);
if (modelListeners != null) {
modelListeners.remove(modelListener);
}
}
private Class<?> _getModelClass(ModelListener<?> modelListener) {
Class<?> clazz = modelListener.getClass();
if (ProxyUtil.isProxyClass(clazz)) {
InvocationHandler invocationHandler =
ProxyUtil.getInvocationHandler(modelListener);
if (invocationHandler instanceof ClassLoaderBeanHandler) {
ClassLoaderBeanHandler classLoaderBeanHandler =
(ClassLoaderBeanHandler)invocationHandler;
Object bean = classLoaderBeanHandler.getBean();
clazz = bean.getClass();
}
}
return ReflectionUtil.getGenericSuperType(clazz);
}
}
}