/*
* Copyright (c) 2005-2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.wso2.carbon.registry.indexing.internal;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.registry.common.AttributeSearchService;
import org.wso2.carbon.registry.common.ResourceData;
import org.wso2.carbon.registry.common.TermData;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.registry.indexing.IndexingManager;
import org.wso2.carbon.registry.indexing.Utils;
import org.wso2.carbon.registry.indexing.indexer.IndexerException;
import org.wso2.carbon.registry.indexing.service.*;
import org.wso2.carbon.utils.AbstractAxis2ConfigurationContextObserver;
import org.wso2.carbon.utils.Axis2ConfigurationContextObserver;
import org.wso2.carbon.utils.WaitBeforeShutdownObserver;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
* @scr.component name="org.wso2.carbon.registry.indexing" immediate="true"
* @scr.reference name="registry.service"
* interface="org.wso2.carbon.registry.core.service.RegistryService" cardinality="1..1"
* policy="dynamic" bind="setRegistryService" unbind="unsetRegistryService"
*/
public class IndexingServiceComponent {
/**
* This class is the bridge between Carbon and Indexing code
*/
private static Log log = LogFactory.getLog(IndexingServiceComponent.class);
private static Stack<ServiceRegistration> registrations = new Stack<ServiceRegistration>();
private static List<Integer> initializedTenants = new LinkedList<Integer>();
protected void activate(ComponentContext context) {
registrations.push(context.getBundleContext().registerService(
ContentSearchService.class.getName(), new ContentSearchServiceImpl(), null));
registrations.push(context.getBundleContext().registerService(
AttributeSearchService.class.getName(), new AttributeSearchServiceImpl(), null));
registrations.push(context.getBundleContext().registerService(
TermsSearchService.class.getName(), new TermsSearchServiceImpl(), null));
registrations.push(context.getBundleContext().registerService(
TermsQuerySearchService.class.getName(), new TermsQuerySearchServiceImpl(), null));
registrations.push(context.getBundleContext().registerService(
WaitBeforeShutdownObserver.class.getName(), new WaitBeforeShutdownObserver() {
boolean status = false;
public void startingShutdown() {
try {
IndexingManager.getInstance().stopIndexing();
} finally {
status = true;
}
}
public boolean isTaskComplete() {
return status;
}
}, null));
TenantDeploymentListenerImpl listener = new TenantDeploymentListenerImpl();
registrations.push(context.getBundleContext().registerService(
Axis2ConfigurationContextObserver.class.getName(), listener, null));
registrations.push(context.getBundleContext().registerService(
TenantIndexingLoader.class.getName(), listener, null));
try {
if (Utils.isIndexingConfigAvailable()) {
IndexingManager.getInstance().startIndexing();
} else {
log.debug("<indexingConfiguration/> not available in registry.xml to start the resource indexing task");
}
} catch (RegistryException e) {
log.error("Failed to start resource indexing task");
}
log.debug("Registry Indexing bundle is activated");
}
protected void deactivate(ComponentContext context) {
while (!registrations.empty()) {
registrations.pop().unregister();
}
log.debug("Registry Indexing bundle is deactivated");
}
protected void setRegistryService(RegistryService registryService) {
Utils.setRegistryService(registryService);
}
protected void unsetRegistryService(RegistryService registryService) {
stopIndexing();
Utils.setRegistryService(null);
}
private void stopIndexing() {
IndexingManager.getInstance().stopIndexing();
}
private static class ContentSearchServiceImpl implements ContentSearchService {
public ResourceData[] search(UserRegistry registry, String query)
throws RegistryException {
SearchResultsBean resultsBean;
try {
resultsBean = new ContentBasedSearchService().searchContent(query, registry);
} catch (IndexerException e) {
throw new RegistryException("Unable to obtain an instance of a Solr client", e);
}
String errorMessage = resultsBean.getErrorMessage();
if (errorMessage != null) {
throw new RegistryException(errorMessage);
}
return resultsBean.getResourceDataList();
}
public ResourceData[] search(int tenantId, String query)
throws RegistryException {
return search(Utils.getRegistryService().getRegistry(
CarbonConstants.REGISTRY_SYSTEM_USERNAME, tenantId), query);
}
public ResourceData[] search(String query) throws RegistryException {
return search(MultitenantConstants.SUPER_TENANT_ID, query);
}
}
private static class AttributeSearchServiceImpl implements AttributeSearchService {
public ResourceData[] search(UserRegistry registry, Map<String, String> query)
throws RegistryException {
SearchResultsBean resultsBean;
try {
resultsBean = new ContentBasedSearchService().searchByAttribute(query, registry);
} catch (IndexerException e) {
throw new RegistryException("Unable to obtain an instance of a Solr client", e);
}
String errorMessage = resultsBean.getErrorMessage();
if (errorMessage != null) {
throw new RegistryException(errorMessage);
}
return resultsBean.getResourceDataList();
}
public ResourceData[] search(int tenantId, Map<String, String> query)
throws RegistryException {
return search(Utils.getRegistryService().getRegistry(
CarbonConstants.REGISTRY_SYSTEM_USERNAME, tenantId), query);
}
public ResourceData[] search(Map<String, String> query) throws RegistryException {
int tenantId;
try {
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
} catch (Exception ignored) {
tenantId = MultitenantConstants.SUPER_TENANT_ID;
}
if (tenantId == MultitenantConstants.INVALID_TENANT_ID) {
tenantId = MultitenantConstants.SUPER_TENANT_ID;
}
return search(tenantId, query);
}
}
private static class TermsSearchServiceImpl implements TermsSearchService {
@Override
public TermData[] search(UserRegistry registry, Map<String, String> query) throws RegistryException {
SearchResultsBean resultsBean;
try {
resultsBean = new ContentBasedSearchService().searchTerms(query, registry);
} catch (IndexerException e) {
throw new RegistryException("Unable to obtain an instance of a Solr client", e);
}
String errorMessage = resultsBean.getErrorMessage();
if (errorMessage != null) {
throw new RegistryException(errorMessage);
}
return resultsBean.getTermDataList();
}
@Override
public TermData[] search(int tenantId, Map<String, String> query) throws RegistryException {
return search(Utils.getRegistryService().getRegistry(
CarbonConstants.REGISTRY_SYSTEM_USERNAME, tenantId), query);
}
@Override
public TermData[] search(Map<String, String> query) throws RegistryException {
int tenantId;
try {
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
} catch (Exception ignored) {
tenantId = MultitenantConstants.SUPER_TENANT_ID;
}
if (tenantId == MultitenantConstants.INVALID_TENANT_ID) {
tenantId = MultitenantConstants.SUPER_TENANT_ID;
}
return search(tenantId, query);
}
}
private static class TermsQuerySearchServiceImpl implements TermsQuerySearchService {
@Override
public TermData[] search(UserRegistry registry, String query, String facetField) throws RegistryException {
SearchResultsBean resultsBean;
try {
resultsBean = new ContentBasedSearchService().searchTermsByQuery(query, facetField, registry);
} catch (IndexerException e) {
throw new RegistryException("Unable to obtain an instance of a Solr client", e);
}
String errorMessage = resultsBean.getErrorMessage();
if (errorMessage != null) {
throw new RegistryException(errorMessage);
}
return resultsBean.getTermDataList();
}
@Override
public TermData[] search(int tenantId, String query, String facetField) throws RegistryException {
return search(Utils.getRegistryService().getRegistry(
CarbonConstants.REGISTRY_SYSTEM_USERNAME, tenantId), query, facetField);
}
@Override
public TermData[] search(String query, String facetField) throws RegistryException {
int tenantId;
try {
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
} catch (Exception ignored) {
tenantId = MultitenantConstants.SUPER_TENANT_ID;
}
if (tenantId == MultitenantConstants.INVALID_TENANT_ID) {
tenantId = MultitenantConstants.SUPER_TENANT_ID;
}
return search(tenantId, query, facetField);
}
}
// An implementation of an Axis2 Configuration Context observer,
// which is used to handle the requirement of initializing the indexer for a tenant.
@SuppressWarnings("unused")
private static class TenantDeploymentListenerImpl extends AbstractAxis2ConfigurationContextObserver
implements TenantIndexingLoader {
public void createdConfigurationContext(ConfigurationContext configurationContext) {
loadTenantIndex(MultitenantUtils.getTenantId(configurationContext));
}
public void terminatingConfigurationContext(ConfigurationContext configContext) {
// It is important to create an object when removing to avoid REGISTRY-2015.
initializedTenants.remove(new Integer(MultitenantUtils.getTenantId(configContext)));
}
public void loadTenantIndex(int tenantId) {
if(initializedTenants.contains(tenantId))
{
return;
}
initializedTenants.add(tenantId);
}
}
public static boolean canIndexTenant(int tenantId) {
return tenantId == MultitenantConstants.SUPER_TENANT_ID || initializedTenants.contains(tenantId);
}
}