/**
* 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.background.task.constants.BackgroundTaskContextMapConstants;
import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.kernel.backgroundtask.BackgroundTask;
import com.liferay.portal.kernel.backgroundtask.BackgroundTaskManager;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.proxy.ProxyModeThreadLocal;
import com.liferay.portal.kernel.model.CompanyConstants;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.IndexWriter;
import com.liferay.portal.kernel.search.IndexWriterHelper;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.SearchEngine;
import com.liferay.portal.kernel.search.SearchEngineHelper;
import com.liferay.portal.kernel.search.SearchException;
import com.liferay.portal.kernel.search.SearchPermissionChecker;
import com.liferay.portal.kernel.search.background.task.ReindexBackgroundTaskConstants;
import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.search.configuration.IndexWriterHelperConfiguration;
import com.liferay.portal.search.index.IndexStatusManager;
import com.liferay.portal.search.internal.background.task.ReindexPortalBackgroundTaskExecutor;
import com.liferay.portal.search.internal.background.task.ReindexSingleIndexerBackgroundTaskExecutor;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
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;
/**
* @author Michael C. Han
*/
@Component(
configurationPid = "com.liferay.portal.search.configuration.IndexWriterHelperConfiguration",
immediate = true, service = IndexWriterHelper.class
)
public class IndexWriterHelperImpl implements IndexWriterHelper {
@Override
public void addDocument(
String searchEngineId, long companyId, Document document,
boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly() || (document == null)) {
return;
}
if (_log.isDebugEnabled()) {
_log.debug("Add document " + document.toString());
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
_searchPermissionChecker.addPermissionFields(companyId, document);
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(searchContext, commitImmediately);
indexWriter.addDocument(searchContext, document);
}
@Override
public void addDocuments(
String searchEngineId, long companyId,
Collection<Document> documents, boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
return;
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
for (Document document : documents) {
if (_log.isDebugEnabled()) {
_log.debug("Add document " + document.toString());
}
_searchPermissionChecker.addPermissionFields(companyId, document);
}
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(searchContext, commitImmediately);
indexWriter.addDocuments(searchContext, documents);
}
@Override
public void commit(String searchEngineId) throws SearchException {
for (long companyId : _searchEngineHelper.getCompanyIds()) {
commit(searchEngineId, companyId);
}
}
@Override
public void commit(String searchEngineId, long companyId)
throws SearchException {
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
indexWriter.commit(searchContext);
}
@Override
public void deleteDocument(
String searchEngineId, long companyId, String uid,
boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly()) {
return;
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(searchContext, commitImmediately);
indexWriter.deleteDocument(searchContext, uid);
}
@Override
public void deleteDocuments(
String searchEngineId, long companyId, Collection<String> uids,
boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly() || (uids == null) || uids.isEmpty()) {
return;
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(searchContext, commitImmediately);
indexWriter.deleteDocuments(searchContext, uids);
}
@Override
public void deleteEntityDocuments(
String searchEngineId, long companyId, String className,
boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly()) {
return;
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
if (searchEngine == null) {
return;
}
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(searchContext, commitImmediately);
indexWriter.deleteEntityDocuments(searchContext, className);
}
@Override
public int getReindexTaskCount(long groupId, boolean completed)
throws SearchException {
return _backgroundTaskManager.getBackgroundTasksCount(
groupId,
new String[] {
ReindexPortalBackgroundTaskExecutor.class.getName(),
ReindexSingleIndexerBackgroundTaskExecutor.class.getName()
},
completed);
}
@Override
public void indexKeyword(
long companyId, String querySuggestion, float weight,
String keywordType, Locale locale)
throws SearchException {
String searchEngineId = _searchEngineHelper.getDefaultSearchEngineId();
indexKeyword(
searchEngineId, companyId, querySuggestion, weight, keywordType,
locale);
}
@Override
public void indexKeyword(
String searchEngineId, long companyId, String querySuggestion,
float weight, String keywordType, Locale locale)
throws SearchException {
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
searchContext.setKeywords(querySuggestion);
searchContext.setLocale(locale);
indexWriter.indexKeyword(searchContext, weight, keywordType);
}
@Override
public void indexQuerySuggestionDictionaries(long companyId)
throws SearchException {
Set<String> searchEngineIds = _searchEngineHelper.getSearchEngineIds();
for (String searchEngineId : searchEngineIds) {
indexQuerySuggestionDictionaries(searchEngineId, companyId);
}
}
@Override
public void indexQuerySuggestionDictionaries(
String searchEngineId, long companyId)
throws SearchException {
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
indexWriter.indexQuerySuggestionDictionaries(searchContext);
}
@Override
public void indexQuerySuggestionDictionary(long companyId, Locale locale)
throws SearchException {
String searchEngineId = _searchEngineHelper.getDefaultSearchEngineId();
indexQuerySuggestionDictionary(searchEngineId, companyId, locale);
}
@Override
public void indexQuerySuggestionDictionary(
String searchEngineId, long companyId, Locale locale)
throws SearchException {
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
searchContext.setLocale(locale);
indexWriter.indexQuerySuggestionDictionary(searchContext);
}
@Override
public void indexSpellCheckerDictionaries(long companyId)
throws SearchException {
String searchEngineId = _searchEngineHelper.getDefaultSearchEngineId();
indexSpellCheckerDictionaries(searchEngineId, companyId);
}
@Override
public void indexSpellCheckerDictionaries(
String searchEngineId, long companyId)
throws SearchException {
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
indexWriter.indexSpellCheckerDictionaries(searchContext);
}
@Override
public void indexSpellCheckerDictionary(long companyId, Locale locale)
throws SearchException {
String searchEngineId = _searchEngineHelper.getDefaultSearchEngineId();
indexSpellCheckerDictionary(searchEngineId, companyId, locale);
}
@Override
public void indexSpellCheckerDictionary(
String searchEngineId, long companyId, Locale locale)
throws SearchException {
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
searchContext.setLocale(locale);
indexWriter.indexSpellCheckerDictionary(searchContext);
}
/**
* @deprecated As of 3.3.0, replaced by {@link IndexStatusManager#
* isIndexReadOnly}
*/
@Deprecated
@Override
public boolean isIndexReadOnly() {
return _indexStatusManager.isIndexReadOnly();
}
/**
* @deprecated As of 3.3.0, replaced by {@link IndexStatusManager#
* isIndexReadOnly(String)}
*/
@Deprecated
@Override
public boolean isIndexReadOnly(String className) {
return _indexStatusManager.isIndexReadOnly(className);
}
@Override
public void partiallyUpdateDocument(
String searchEngineId, long companyId, Document document,
boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly() || (document == null)) {
return;
}
if (_log.isDebugEnabled()) {
_log.debug("Document " + document.toString());
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
_searchPermissionChecker.addPermissionFields(companyId, document);
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(searchContext, commitImmediately);
indexWriter.partiallyUpdateDocument(searchContext, document);
}
@Override
public void partiallyUpdateDocuments(
String searchEngineId, long companyId,
Collection<Document> documents, boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
return;
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
for (Document document : documents) {
if (_log.isDebugEnabled()) {
_log.debug("Document " + document.toString());
}
_searchPermissionChecker.addPermissionFields(companyId, document);
}
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(searchContext, commitImmediately);
indexWriter.partiallyUpdateDocuments(searchContext, documents);
}
@Override
public BackgroundTask reindex(
long userId, String jobName, long[] companyIds,
Map<String, Serializable> taskContextMap)
throws SearchException {
if (taskContextMap == null) {
taskContextMap = new HashMap<>();
}
taskContextMap.put(
ReindexBackgroundTaskConstants.COMPANY_IDS, companyIds);
taskContextMap.put(
BackgroundTaskContextMapConstants.DELETE_ON_SUCCESS, true);
try {
return _backgroundTaskManager.addBackgroundTask(
userId, CompanyConstants.SYSTEM, jobName,
ReindexPortalBackgroundTaskExecutor.class.getName(),
taskContextMap, new ServiceContext());
}
catch (PortalException pe) {
throw new SearchException("Unable to schedule portal reindex", pe);
}
}
@Override
public BackgroundTask reindex(
long userId, String jobName, long[] companyIds, String className,
Map<String, Serializable> taskContextMap)
throws SearchException {
if (Validator.isNull(className)) {
return reindex(userId, jobName, companyIds, taskContextMap);
}
if (taskContextMap == null) {
taskContextMap = new HashMap<>();
}
taskContextMap.put(
ReindexBackgroundTaskConstants.CLASS_NAME, className);
taskContextMap.put(
ReindexBackgroundTaskConstants.COMPANY_IDS, companyIds);
taskContextMap.put(
BackgroundTaskContextMapConstants.DELETE_ON_SUCCESS, true);
try {
return _backgroundTaskManager.addBackgroundTask(
userId, CompanyConstants.SYSTEM, jobName,
ReindexSingleIndexerBackgroundTaskExecutor.class.getName(),
taskContextMap, new ServiceContext());
}
catch (PortalException pe) {
throw new SearchException("Unable to schedule portal reindex", pe);
}
}
/**
* @deprecated As of 3.3.0, replaced by {@link IndexStatusManager.
* setIndexReadOnly(boolean)}
*/
@Deprecated
@Override
public void setIndexReadOnly(boolean indexReadOnly) {
_indexStatusManager.setIndexReadOnly(indexReadOnly);
}
/**
* @deprecated As of 3.3.0, replaced by {@link IndexStatusManager.
* setIndexReadOnly(String, boolean)}
*/
@Deprecated
@Override
public void setIndexReadOnly(String className, boolean indexReadOnly) {
_indexStatusManager.setIndexReadOnly(className, indexReadOnly);
}
@Override
public void updateDocument(
String searchEngineId, long companyId, Document document,
boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly() || (document == null)) {
return;
}
if (_log.isDebugEnabled()) {
_log.debug("Document " + document.toString());
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
_searchPermissionChecker.addPermissionFields(companyId, document);
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(
searchContext,
commitImmediately || ProxyModeThreadLocal.isForceSync());
indexWriter.updateDocument(searchContext, document);
}
@Override
public void updateDocuments(
String searchEngineId, long companyId,
Collection<Document> documents, boolean commitImmediately)
throws SearchException {
if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
return;
}
SearchEngine searchEngine = _searchEngineHelper.getSearchEngine(
searchEngineId);
IndexWriter indexWriter = searchEngine.getIndexWriter();
for (Document document : documents) {
if (_log.isDebugEnabled()) {
_log.debug("Document " + document.toString());
}
_searchPermissionChecker.addPermissionFields(companyId, document);
}
SearchContext searchContext = new SearchContext();
searchContext.setCompanyId(companyId);
searchContext.setSearchEngineId(searchEngineId);
setCommitImmediately(searchContext, commitImmediately);
indexWriter.updateDocuments(searchContext, documents);
}
@Override
public void updatePermissionFields(String name, String primKey) {
if (isIndexReadOnly()) {
return;
}
if (PermissionThreadLocal.isFlushResourcePermissionEnabled(
name, primKey)) {
_searchPermissionChecker.updatePermissionFields(name, primKey);
}
}
@Activate
@Modified
protected void activate(Map<String, Object> properties) {
IndexWriterHelperConfiguration indexWriterHelperConfiguration =
ConfigurableUtil.createConfigurable(
IndexWriterHelperConfiguration.class, properties);
_commitImmediately =
indexWriterHelperConfiguration.indexCommitImmediately();
}
protected void setCommitImmediately(
SearchContext searchContext, boolean commitImmediately) {
if (!commitImmediately) {
searchContext.setCommitImmediately(_commitImmediately);
}
else {
searchContext.setCommitImmediately(true);
}
}
private static final Log _log = LogFactoryUtil.getLog(
IndexWriterHelperImpl.class);
@Reference
private BackgroundTaskManager _backgroundTaskManager;
private volatile boolean _commitImmediately;
@Reference
private IndexStatusManager _indexStatusManager;
@Reference
private SearchEngineHelper _searchEngineHelper;
@Reference
private SearchPermissionChecker _searchPermissionChecker;
}