/**
* 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.search.internal;
import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.search.IndexerRegistry;
import com.liferay.portal.kernel.search.dummy.DummyIndexer;
import com.liferay.portal.kernel.service.PersistedModelLocalServiceRegistry;
import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import com.liferay.portal.kernel.util.ProxyUtil;
import com.liferay.portal.search.buffer.IndexerRequestBuffer;
import com.liferay.portal.search.buffer.IndexerRequestBufferOverflowHandler;
import com.liferay.portal.search.configuration.IndexerRegistryConfiguration;
import com.liferay.portal.search.index.IndexStatusManager;
import com.liferay.portal.search.internal.buffer.BufferedIndexerInvocationHandler;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.ClassUtils;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* @author Michael C. Han
*/
@Component(
configurationPid = "com.liferay.portal.search.configuration.IndexerRegistryConfiguration",
immediate = true, service = IndexerRegistry.class
)
public class IndexerRegistryImpl implements IndexerRegistry {
@Override
public <T> Indexer<T> getIndexer(Class<T> clazz) {
return getIndexer(clazz.getName());
}
@Override
public <T> Indexer<T> getIndexer(String className) {
Indexer<T> indexer = (Indexer<T>)_indexers.get(className);
return proxyIndexer(indexer);
}
@Override
public Set<Indexer<?>> getIndexers() {
return new HashSet<>(_indexers.values());
}
@Override
public <T> Indexer<T> nullSafeGetIndexer(Class<T> clazz) {
return nullSafeGetIndexer(clazz.getName());
}
@Override
public <T> Indexer<T> nullSafeGetIndexer(String className) {
Indexer<T> indexer = getIndexer(className);
if (indexer != null) {
return indexer;
}
if (_log.isInfoEnabled()) {
_log.info("No indexer found for " + className);
}
return (Indexer<T>)_dummyIndexer;
}
@Override
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY, unbind = "unregister"
)
public void register(Indexer<?> indexer) {
Class<?> clazz = indexer.getClass();
_indexers.put(clazz.getName(), indexer);
_indexers.put(indexer.getClassName(), indexer);
}
@Override
public void unregister(Indexer<?> indexer) {
Class<?> clazz = indexer.getClass();
unregister(clazz.getName());
unregister(indexer.getClassName());
}
@Override
public void unregister(String className) {
_bufferedInvocationHandlers.remove(className);
_indexers.remove(className);
_proxiedIndexers.remove(className);
}
@Activate
@Modified
protected void activate(Map<String, Object> properties) {
_indexerRegistryConfiguration = ConfigurableUtil.createConfigurable(
IndexerRegistryConfiguration.class, properties);
for (BufferedIndexerInvocationHandler bufferedIndexerInvocationHandler :
_bufferedInvocationHandlers.values()) {
bufferedIndexerInvocationHandler.setIndexerRegistryConfiguration(
_indexerRegistryConfiguration);
}
}
protected <T> Indexer<T> proxyIndexer(Indexer<T> indexer) {
if (indexer == null) {
return null;
}
IndexerRequestBuffer indexerRequestBuffer = IndexerRequestBuffer.get();
if ((indexerRequestBuffer == null) ||
!_indexerRegistryConfiguration.buffered()) {
return indexer;
}
Indexer<?> proxiedIndexer = _proxiedIndexers.get(
indexer.getClassName());
if (proxiedIndexer == null) {
List<?> interfaces = ClassUtils.getAllInterfaces(
indexer.getClass());
BufferedIndexerInvocationHandler bufferedIndexerInvocationHandler =
new BufferedIndexerInvocationHandler(
indexer, _indexStatusManager, _indexerRegistryConfiguration,
_persistedModelLocalServiceRegistry);
if (_indexerRequestBufferOverflowHandler == null) {
bufferedIndexerInvocationHandler.
setIndexerRequestBufferOverflowHandler(
_defaultIndexerRequestBufferOverflowHandler);
}
else {
bufferedIndexerInvocationHandler.
setIndexerRequestBufferOverflowHandler(
_indexerRequestBufferOverflowHandler);
}
_bufferedInvocationHandlers.put(
indexer.getClassName(), bufferedIndexerInvocationHandler);
proxiedIndexer = (Indexer<?>)ProxyUtil.newProxyInstance(
PortalClassLoaderUtil.getClassLoader(),
interfaces.toArray(new Class<?>[interfaces.size()]),
bufferedIndexerInvocationHandler);
_proxiedIndexers.put(indexer.getClassName(), proxiedIndexer);
}
return (Indexer<T>)proxiedIndexer;
}
@Reference(
cardinality = ReferenceCardinality.OPTIONAL,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY
)
protected void setIndexerRequestBufferOverflowHandler(
IndexerRequestBufferOverflowHandler
indexerRequestBufferOverflowHandler) {
_indexerRequestBufferOverflowHandler =
indexerRequestBufferOverflowHandler;
for (BufferedIndexerInvocationHandler bufferedIndexerInvocationHandler :
_bufferedInvocationHandlers.values()) {
bufferedIndexerInvocationHandler.
setIndexerRequestBufferOverflowHandler(
_indexerRequestBufferOverflowHandler);
}
}
protected void unsetIndexerRequestBufferOverflowHandler(
IndexerRequestBufferOverflowHandler
indexerRequestBufferOverflowHandler) {
_indexerRequestBufferOverflowHandler = null;
for (BufferedIndexerInvocationHandler bufferedIndexerInvocationHandler :
_bufferedInvocationHandlers.values()) {
bufferedIndexerInvocationHandler.
setIndexerRequestBufferOverflowHandler(
_defaultIndexerRequestBufferOverflowHandler);
}
}
private static final Log _log = LogFactoryUtil.getLog(
IndexerRegistryImpl.class);
private final Map<String, BufferedIndexerInvocationHandler>
_bufferedInvocationHandlers = new ConcurrentHashMap<>();
@Reference(target = "(mode=DEFAULT)")
private IndexerRequestBufferOverflowHandler
_defaultIndexerRequestBufferOverflowHandler;
private final Indexer<?> _dummyIndexer = new DummyIndexer();
private volatile IndexerRegistryConfiguration _indexerRegistryConfiguration;
private volatile IndexerRequestBufferOverflowHandler
_indexerRequestBufferOverflowHandler;
private final Map<String, Indexer<? extends Object>> _indexers =
new ConcurrentHashMap<>();
@Reference
private IndexStatusManager _indexStatusManager;
@Reference
private PersistedModelLocalServiceRegistry
_persistedModelLocalServiceRegistry;
private final Map<String, Indexer<? extends Object>> _proxiedIndexers =
new ConcurrentHashMap<>();
}