001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.search;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.messaging.DestinationNames;
020    import com.liferay.portal.kernel.util.GetterUtil;
021    import com.liferay.portal.kernel.util.PropsKeys;
022    import com.liferay.portal.kernel.util.PropsUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.security.permission.PermissionThreadLocal;
025    
026    import java.util.Collection;
027    import java.util.HashSet;
028    import java.util.List;
029    import java.util.Map;
030    import java.util.Set;
031    import java.util.concurrent.ConcurrentHashMap;
032    
033    /**
034     * @author Bruno Farache
035     * @author Raymond Augé
036     * @author Michael C. Han
037     */
038    public class SearchEngineUtil {
039    
040            /**
041             * @deprecated Use {@link
042             *             com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS}.
043             */
044            public static final int ALL_POS = -1;
045    
046            public static final String GENERIC_ENGINE_ID = "GENERIC_ENGINE";
047    
048            public static final String SYSTEM_ENGINE_ID = "SYSTEM_ENGINE";
049    
050            public static void addDocument(long companyId, Document document)
051                    throws SearchException {
052    
053                    addDocument(SYSTEM_ENGINE_ID, companyId, document);
054            }
055    
056            public static void addDocument(
057                            String searchEngineId, long companyId, Document document)
058                    throws SearchException {
059    
060                    if (isIndexReadOnly()) {
061                            return;
062                    }
063    
064                    if (_log.isDebugEnabled()) {
065                            _log.debug("Add document " + document.toString());
066                    }
067    
068                    _searchPermissionChecker.addPermissionFields(companyId, document);
069    
070                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
071    
072                    IndexWriter indexWriter = searchEngine.getIndexWriter();
073    
074                    SearchContext searchContext = new SearchContext();
075    
076                    searchContext.setCompanyId(companyId);
077                    searchContext.setSearchEngineId(searchEngineId);
078    
079                    indexWriter.addDocument(searchContext, document);
080            }
081    
082            public static void addDocuments(
083                            long companyId, Collection<Document> documents)
084                    throws SearchException {
085    
086                    addDocuments(SYSTEM_ENGINE_ID, companyId, documents);
087            }
088    
089            public static void addDocuments(
090                            String searchEngineId, long companyId,
091                            Collection<Document> documents)
092                    throws SearchException {
093    
094                    if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
095                            return;
096                    }
097    
098                    for (Document document : documents) {
099                            if (_log.isDebugEnabled()) {
100                                    _log.debug("Add document " + document.toString());
101                            }
102    
103                            _searchPermissionChecker.addPermissionFields(companyId, document);
104                    }
105    
106                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
107    
108                    IndexWriter indexWriter = searchEngine.getIndexWriter();
109    
110                    SearchContext searchContext = new SearchContext();
111    
112                    searchContext.setCompanyId(companyId);
113                    searchContext.setSearchEngineId(searchEngineId);
114    
115                    indexWriter.addDocuments(searchContext, documents);
116            }
117    
118            public static void addSearchEngine(SearchEngine searchEngine) {
119                    _searchEngines.put(searchEngine.getName(), searchEngine);
120            }
121    
122            public static void deleteDocument(long companyId, String uid)
123                    throws SearchException {
124    
125                    deleteDocument(SYSTEM_ENGINE_ID, companyId, uid);
126            }
127    
128            public static void deleteDocument(
129                            String searchEngineId, long companyId, String uid)
130                    throws SearchException {
131    
132                    if (isIndexReadOnly()) {
133                            return;
134                    }
135    
136                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
137    
138                    IndexWriter indexWriter = searchEngine.getIndexWriter();
139    
140                    SearchContext searchContext = new SearchContext();
141    
142                    searchContext.setCompanyId(companyId);
143                    searchContext.setSearchEngineId(searchEngineId);
144    
145                    indexWriter.deleteDocument(searchContext, uid);
146            }
147    
148            public static void deleteDocuments(long companyId, Collection<String> uids)
149                    throws SearchException {
150    
151                    deleteDocuments(SYSTEM_ENGINE_ID, companyId, uids);
152            }
153    
154            public static void deleteDocuments(
155                            String searchEngineId, long companyId, Collection<String> uids)
156                    throws SearchException {
157    
158                    if (isIndexReadOnly() || (uids == null) || uids.isEmpty()) {
159                            return;
160                    }
161    
162                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
163    
164                    IndexWriter indexWriter = searchEngine.getIndexWriter();
165    
166                    SearchContext searchContext = new SearchContext();
167    
168                    searchContext.setCompanyId(companyId);
169                    searchContext.setSearchEngineId(searchEngineId);
170    
171                    indexWriter.deleteDocuments(searchContext, uids);
172            }
173    
174            public static void deletePortletDocuments(long companyId, String portletId)
175                    throws SearchException {
176    
177                    deletePortletDocuments(SYSTEM_ENGINE_ID, companyId, portletId);
178            }
179    
180            public static void deletePortletDocuments(
181                            String searchEngineId, long companyId, String portletId)
182                    throws SearchException {
183    
184                    if (isIndexReadOnly()) {
185                            return;
186                    }
187    
188                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
189    
190                    if (searchEngine == null) {
191                            return;
192                    }
193    
194                    IndexWriter indexWriter = searchEngine.getIndexWriter();
195    
196                    SearchContext searchContext = new SearchContext();
197    
198                    searchContext.setCompanyId(companyId);
199                    searchContext.setSearchEngineId(searchEngineId);
200    
201                    indexWriter.deletePortletDocuments(searchContext, portletId);
202            }
203    
204            public static String[] getEntryClassNames() {
205                    Set<String> assetEntryClassNames = new HashSet<String>();
206    
207                    for (Indexer indexer : IndexerRegistryUtil.getIndexers()) {
208                            for (String className : indexer.getClassNames()) {
209                                    if (!_excludedEntryClassNames.contains(className)) {
210                                            assetEntryClassNames.add(className);
211                                    }
212                            }
213                    }
214    
215                    return assetEntryClassNames.toArray(
216                            new String[assetEntryClassNames.size()]);
217            }
218    
219            public static SearchEngine getSearchEngine() {
220                    return getSearchEngine(SYSTEM_ENGINE_ID);
221            }
222    
223            public static SearchEngine getSearchEngine(String searchEngineId) {
224                    return _searchEngines.get(searchEngineId);
225            }
226    
227            public static SearchPermissionChecker getSearchPermissionChecker() {
228                    return _searchPermissionChecker;
229            }
230    
231            public static String getSearchReaderDestinationName(String searchEngineId) {
232                    return DestinationNames.SEARCH_READER.concat(StringPool.SLASH).concat(
233                            searchEngineId);
234            }
235    
236            public static String getSearchWriterDestinationName(String searchEngineId) {
237                    return DestinationNames.SEARCH_WRITER.concat(StringPool.SLASH).concat(
238                            searchEngineId);
239            }
240    
241            public static boolean isIndexReadOnly() {
242                    return _indexReadOnly;
243            }
244    
245            public static SearchEngine removeSearchEngine(String searchEngineName) {
246                    return _searchEngines.remove(searchEngineName);
247            }
248    
249            public static Hits search(
250                            long companyId, long[] groupIds, long userId, String className,
251                            Query query, int start, int end)
252                    throws SearchException {
253    
254                    SearchContext searchContext = new SearchContext();
255    
256                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
257    
258                    if (userId > 0) {
259                            query = _searchPermissionChecker.getPermissionQuery(
260                                    companyId, groupIds, userId, className, query, searchContext);
261                    }
262    
263                    return search(
264                            companyId, query, SortFactoryUtil.getDefaultSorts(), start, end);
265            }
266    
267            public static Hits search(
268                            long companyId, long[] groupIds, long userId, String className,
269                            Query query, Sort sort, int start, int end)
270                    throws SearchException {
271    
272                    SearchContext searchContext = new SearchContext();
273    
274                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
275    
276                    if (userId > 0) {
277                            query = _searchPermissionChecker.getPermissionQuery(
278                                    companyId, groupIds, userId, className, query, searchContext);
279                    }
280    
281                    return search(companyId, query, sort, start, end);
282            }
283    
284            public static Hits search(
285                            long companyId, long[] groupIds, long userId, String className,
286                            Query query, Sort[] sorts, int start, int end)
287                    throws SearchException {
288    
289                    SearchContext searchContext = new SearchContext();
290    
291                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
292    
293                    if (userId > 0) {
294                            query = _searchPermissionChecker.getPermissionQuery(
295                                    companyId, groupIds, userId, className, query, searchContext);
296                    }
297    
298                    return search(companyId, query, sorts, start, end);
299            }
300    
301            public static Hits search(long companyId, Query query, int start, int end)
302                    throws SearchException {
303    
304                    return search(SYSTEM_ENGINE_ID, companyId, query, start, end);
305            }
306    
307            public static Hits search(
308                            long companyId, Query query, Sort sort, int start, int end)
309                    throws SearchException {
310    
311                    return search(SYSTEM_ENGINE_ID, companyId, query, sort, start, end);
312            }
313    
314            public static Hits search(
315                            long companyId, Query query, Sort[] sorts, int start, int end)
316                    throws SearchException {
317    
318                    return search(SYSTEM_ENGINE_ID, companyId, query, sorts, start, end);
319            }
320    
321            public static Hits search(SearchContext searchContext, Query query)
322                    throws SearchException {
323    
324                    if (_log.isDebugEnabled()) {
325                            _log.debug("Search query " + query.toString());
326                    }
327    
328                    SearchEngine searchEngine = _searchEngines.get(
329                            searchContext.getSearchEngineId());
330    
331                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
332    
333                    return indexSearcher.search(searchContext, query);
334            }
335    
336            public static Hits search(
337                            String searchEngineId, long companyId, Query query, int start,
338                            int end)
339                    throws SearchException {
340    
341                    if (_log.isDebugEnabled()) {
342                            _log.debug("Search query " + query.toString());
343                    }
344    
345                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
346    
347                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
348    
349                    return indexSearcher.search(
350                            searchEngineId, companyId, query, SortFactoryUtil.getDefaultSorts(),
351                            start, end);
352            }
353    
354            public static Hits search(
355                            String searchEngineId, long companyId, Query query, Sort sort,
356                            int start, int end)
357                    throws SearchException {
358    
359                    if (_log.isDebugEnabled()) {
360                            _log.debug("Search query " + query.toString());
361                    }
362    
363                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
364    
365                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
366    
367                    return indexSearcher.search(
368                            searchEngineId, companyId, query, new Sort[] {sort}, start, end);
369            }
370    
371            public static Hits search(
372                            String searchEngineId, long companyId, Query query, Sort[] sorts,
373                            int start, int end)
374                    throws SearchException {
375    
376                    if (_log.isDebugEnabled()) {
377                            _log.debug("Search query " + query.toString());
378                    }
379    
380                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
381    
382                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
383    
384                    return indexSearcher.search(
385                            searchEngineId, companyId, query, sorts, start, end);
386            }
387    
388            public static void setIndexReadOnly(boolean indexReadOnly) {
389                    _indexReadOnly = indexReadOnly;
390            }
391    
392            public static void updateDocument(long companyId, Document document)
393                    throws SearchException {
394    
395                    updateDocument(SYSTEM_ENGINE_ID, companyId, document);
396            }
397    
398            public static void updateDocument(
399                            String searchEngineId, long companyId, Document document)
400                    throws SearchException {
401    
402                    if (isIndexReadOnly()) {
403                            return;
404                    }
405    
406                    if (_log.isDebugEnabled()) {
407                            _log.debug("Document " + document.toString());
408                    }
409    
410                    _searchPermissionChecker.addPermissionFields(companyId, document);
411    
412                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
413    
414                    IndexWriter indexWriter = searchEngine.getIndexWriter();
415    
416                    SearchContext searchContext = new SearchContext();
417    
418                    searchContext.setCompanyId(companyId);
419                    searchContext.setSearchEngineId(searchEngineId);
420    
421                    indexWriter.updateDocument(searchContext, document);
422            }
423    
424            public static void updateDocuments(
425                            long companyId, Collection<Document> documents)
426                    throws SearchException {
427    
428                    updateDocuments(SYSTEM_ENGINE_ID, companyId, documents);
429            }
430    
431            public static void updateDocuments(
432                            String searchEngineId, long companyId,
433                            Collection<Document> documents)
434                    throws SearchException {
435    
436                    if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
437                            return;
438                    }
439    
440                    for (Document document : documents) {
441                            if (_log.isDebugEnabled()) {
442                                    _log.debug("Document " + document.toString());
443                            }
444    
445                            _searchPermissionChecker.addPermissionFields(companyId, document);
446                    }
447    
448                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
449    
450                    IndexWriter indexWriter = searchEngine.getIndexWriter();
451    
452                    SearchContext searchContext = new SearchContext();
453    
454                    searchContext.setCompanyId(companyId);
455                    searchContext.setSearchEngineId(searchEngineId);
456    
457                    indexWriter.updateDocuments(searchContext, documents);
458            }
459    
460            public static void updatePermissionFields(long resourceId) {
461                    if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
462                            return;
463                    }
464    
465                    _searchPermissionChecker.updatePermissionFields(resourceId);
466            }
467    
468            public static void updatePermissionFields(String name, String primKey) {
469                    if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
470                            return;
471                    }
472    
473                    _searchPermissionChecker.updatePermissionFields(name, primKey);
474            }
475    
476            public void setExcludedEntryClassNames(
477                    List<String> excludedEntryClassNames) {
478    
479                    _excludedEntryClassNames.addAll(excludedEntryClassNames);
480            }
481    
482            public void setSearchEngine(SearchEngine searchEngine) {
483                    _searchEngines.put(SYSTEM_ENGINE_ID, searchEngine);
484            }
485    
486            public void setSearchEngines(Map<String, SearchEngine> searchEngines) {
487                    _searchEngines.putAll(searchEngines);
488            }
489    
490            public void setSearchPermissionChecker(
491                    SearchPermissionChecker searchPermissionChecker) {
492    
493                    _searchPermissionChecker = searchPermissionChecker;
494            }
495    
496            private static Log _log = LogFactoryUtil.getLog(SearchEngineUtil.class);
497    
498            private static Set<String> _excludedEntryClassNames = new HashSet<String>();
499            private static boolean _indexReadOnly = GetterUtil.getBoolean(
500                    PropsUtil.get(PropsKeys.INDEX_READ_ONLY));
501            private static Map<String, SearchEngine> _searchEngines =
502                    new ConcurrentHashMap<String, SearchEngine>();
503            private static SearchPermissionChecker _searchPermissionChecker;
504    
505    }