001    /**
002     * Copyright (c) 2000-2011 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.Map;
028    import java.util.concurrent.ConcurrentHashMap;
029    
030    /**
031     * @author Bruno Farache
032     * @author Raymond Augé
033     * @author Michael C. Han
034     */
035    public class SearchEngineUtil {
036    
037            /**
038             * @deprecated Use {@link
039             *             com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS}.
040             */
041            public static final int ALL_POS = -1;
042    
043            public static final String GENERIC_ENGINE_ID = "GENERIC_ENGINE";
044    
045            public static final String SYSTEM_ENGINE_ID = "SYSTEM_ENGINE";
046    
047            public static void addDocument(long companyId, Document document)
048                    throws SearchException {
049    
050                    addDocument(SYSTEM_ENGINE_ID, companyId, document);
051            }
052    
053            public static void addDocument(
054                            String searchEngineId, long companyId, Document document)
055                    throws SearchException {
056    
057                    if (isIndexReadOnly()) {
058                            return;
059                    }
060    
061                    if (_log.isDebugEnabled()) {
062                            _log.debug("Add document " + document.toString());
063                    }
064    
065                    _searchPermissionChecker.addPermissionFields(companyId, document);
066    
067                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
068    
069                    IndexWriter indexWriter = searchEngine.getIndexWriter();
070    
071                    SearchContext searchContext = new SearchContext();
072    
073                    searchContext.setCompanyId(companyId);
074                    searchContext.setSearchEngineId(searchEngineId);
075    
076                    indexWriter.addDocument(searchContext, document);
077            }
078    
079            public static void addDocuments(
080                            long companyId, Collection<Document> documents)
081                    throws SearchException {
082    
083                    addDocuments(SYSTEM_ENGINE_ID, companyId, documents);
084            }
085    
086            public static void addDocuments(
087                            String searchEngineId, long companyId,
088                            Collection<Document> documents)
089                    throws SearchException {
090    
091                    if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
092                            return;
093                    }
094    
095                    for (Document document : documents) {
096                            if (_log.isDebugEnabled()) {
097                                    _log.debug("Add document " + document.toString());
098                            }
099    
100                            _searchPermissionChecker.addPermissionFields(companyId, document);
101                    }
102    
103                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
104    
105                    IndexWriter indexWriter = searchEngine.getIndexWriter();
106    
107                    SearchContext searchContext = new SearchContext();
108    
109                    searchContext.setCompanyId(companyId);
110                    searchContext.setSearchEngineId(searchEngineId);
111    
112                    indexWriter.addDocuments(searchContext, documents);
113            }
114    
115            public static void addSearchEngine(SearchEngine searchEngine) {
116                    _searchEngines.put(searchEngine.getName(), searchEngine);
117            }
118    
119            public static void deleteDocument(long companyId, String uid)
120                    throws SearchException {
121    
122                    deleteDocument(SYSTEM_ENGINE_ID, companyId, uid);
123            }
124    
125            public static void deleteDocument(
126                            String searchEngineId, long companyId, String uid)
127                    throws SearchException {
128    
129                    if (isIndexReadOnly()) {
130                            return;
131                    }
132    
133                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
134    
135                    IndexWriter indexWriter = searchEngine.getIndexWriter();
136    
137                    SearchContext searchContext = new SearchContext();
138    
139                    searchContext.setCompanyId(companyId);
140                    searchContext.setSearchEngineId(searchEngineId);
141    
142                    indexWriter.deleteDocument(searchContext, uid);
143            }
144    
145            public static void deleteDocuments(long companyId, Collection<String> uids)
146                    throws SearchException {
147    
148                    deleteDocuments(SYSTEM_ENGINE_ID, companyId, uids);
149            }
150    
151            public static void deleteDocuments(
152                            String searchEngineId, long companyId, Collection<String> uids)
153                    throws SearchException {
154    
155                    if (isIndexReadOnly() || (uids == null) || uids.isEmpty()) {
156                            return;
157                    }
158    
159                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
160    
161                    IndexWriter indexWriter = searchEngine.getIndexWriter();
162    
163                    SearchContext searchContext = new SearchContext();
164    
165                    searchContext.setCompanyId(companyId);
166                    searchContext.setSearchEngineId(searchEngineId);
167    
168                    indexWriter.deleteDocuments(searchContext, uids);
169            }
170    
171            public static void deletePortletDocuments(long companyId, String portletId)
172                    throws SearchException {
173    
174                    deletePortletDocuments(SYSTEM_ENGINE_ID, companyId, portletId);
175            }
176    
177            public static void deletePortletDocuments(
178                            String searchEngineId, long companyId, String portletId)
179                    throws SearchException {
180    
181                    if (isIndexReadOnly()) {
182                            return;
183                    }
184    
185                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
186    
187                    if (searchEngine == null) {
188                            return;
189                    }
190    
191                    IndexWriter indexWriter = searchEngine.getIndexWriter();
192    
193                    SearchContext searchContext = new SearchContext();
194    
195                    searchContext.setCompanyId(companyId);
196                    searchContext.setSearchEngineId(searchEngineId);
197    
198                    indexWriter.deletePortletDocuments(searchContext, portletId);
199            }
200    
201            public static SearchEngine getSearchEngine() {
202                    return getSearchEngine(SYSTEM_ENGINE_ID);
203            }
204    
205            public static SearchEngine getSearchEngine(String searchEngineId) {
206                    return _searchEngines.get(searchEngineId);
207            }
208    
209            public static SearchPermissionChecker getSearchPermissionChecker() {
210                    return _searchPermissionChecker;
211            }
212    
213            public static String getSearchReaderDestinationName(String searchEngineId) {
214                    return DestinationNames.SEARCH_READER.concat(StringPool.SLASH).concat(
215                            searchEngineId);
216            }
217    
218            public static String getSearchWriterDestinationName(String searchEngineId) {
219                    return DestinationNames.SEARCH_WRITER.concat(StringPool.SLASH).concat(
220                            searchEngineId);
221            }
222    
223            public static boolean isIndexReadOnly() {
224                    return _indexReadOnly;
225            }
226    
227            public static SearchEngine removeSearchEngine(String searchEngineName) {
228                    return _searchEngines.remove(searchEngineName);
229            }
230    
231            public static Hits search(
232                            long companyId, long[] groupIds, long userId, String className,
233                            Query query, int start, int end)
234                    throws SearchException {
235    
236                    SearchContext searchContext = new SearchContext();
237    
238                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
239    
240                    if (userId > 0) {
241                            query = _searchPermissionChecker.getPermissionQuery(
242                                    companyId, groupIds, userId, className, query, searchContext);
243                    }
244    
245                    return search(
246                            companyId, query, SortFactoryUtil.getDefaultSorts(), start, end);
247            }
248    
249            public static Hits search(
250                            long companyId, long[] groupIds, long userId, String className,
251                            Query query, Sort sort, 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(companyId, query, sort, start, end);
264            }
265    
266            public static Hits search(
267                            long companyId, long[] groupIds, long userId, String className,
268                            Query query, Sort[] sorts, int start, int end)
269                    throws SearchException {
270    
271                    SearchContext searchContext = new SearchContext();
272    
273                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
274    
275                    if (userId > 0) {
276                            query = _searchPermissionChecker.getPermissionQuery(
277                                    companyId, groupIds, userId, className, query, searchContext);
278                    }
279    
280                    return search(companyId, query, sorts, start, end);
281            }
282    
283            public static Hits search(long companyId, Query query, int start, int end)
284                    throws SearchException {
285    
286                    return search(SYSTEM_ENGINE_ID, companyId, query, start, end);
287            }
288    
289            public static Hits search(
290                            long companyId, Query query, Sort sort, int start, int end)
291                    throws SearchException {
292    
293                    return search(SYSTEM_ENGINE_ID, companyId, query, sort, start, end);
294            }
295    
296            public static Hits search(
297                            long companyId, Query query, Sort[] sorts, int start, int end)
298                    throws SearchException {
299    
300                    return search(SYSTEM_ENGINE_ID, companyId, query, sorts, start, end);
301            }
302    
303            public static Hits search(SearchContext searchContext, Query query)
304                    throws SearchException {
305    
306                    if (_log.isDebugEnabled()) {
307                            _log.debug("Search query " + query.toString());
308                    }
309    
310                    SearchEngine searchEngine = _searchEngines.get(
311                            searchContext.getSearchEngineId());
312    
313                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
314    
315                    return indexSearcher.search(searchContext, query);
316            }
317    
318            public static Hits search(
319                            String searchEngineId, long companyId, Query query, int start,
320                            int end)
321                    throws SearchException {
322    
323                    if (_log.isDebugEnabled()) {
324                            _log.debug("Search query " + query.toString());
325                    }
326    
327                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
328    
329                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
330    
331                    return indexSearcher.search(
332                            searchEngineId, companyId, query, SortFactoryUtil.getDefaultSorts(),
333                            start, end);
334            }
335    
336            public static Hits search(
337                            String searchEngineId, long companyId, Query query, Sort sort,
338                            int start, 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, new Sort[] {sort}, start, end);
351            }
352    
353            public static Hits search(
354                            String searchEngineId, long companyId, Query query, Sort[] sorts,
355                            int start, int end)
356                    throws SearchException {
357    
358                    if (_log.isDebugEnabled()) {
359                            _log.debug("Search query " + query.toString());
360                    }
361    
362                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
363    
364                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
365    
366                    return indexSearcher.search(
367                            searchEngineId, companyId, query, sorts, start, end);
368            }
369    
370            public static void setIndexReadOnly(boolean indexReadOnly) {
371                    _indexReadOnly = indexReadOnly;
372            }
373    
374            public static void updateDocument(long companyId, Document document)
375                    throws SearchException {
376    
377                    updateDocument(SYSTEM_ENGINE_ID, companyId, document);
378            }
379    
380            public static void updateDocument(
381                            String searchEngineId, long companyId, Document document)
382                    throws SearchException {
383    
384                    if (isIndexReadOnly()) {
385                            return;
386                    }
387    
388                    if (_log.isDebugEnabled()) {
389                            _log.debug("Document " + document.toString());
390                    }
391    
392                    _searchPermissionChecker.addPermissionFields(companyId, document);
393    
394                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
395    
396                    IndexWriter indexWriter = searchEngine.getIndexWriter();
397    
398                    SearchContext searchContext = new SearchContext();
399    
400                    searchContext.setCompanyId(companyId);
401                    searchContext.setSearchEngineId(searchEngineId);
402    
403                    indexWriter.updateDocument(searchContext, document);
404            }
405    
406            public static void updateDocuments(
407                            long companyId, Collection<Document> documents)
408                    throws SearchException {
409    
410                    updateDocuments(SYSTEM_ENGINE_ID, companyId, documents);
411            }
412    
413            public static void updateDocuments(
414                            String searchEngineId, long companyId,
415                            Collection<Document> documents)
416                    throws SearchException {
417    
418                    if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
419                            return;
420                    }
421    
422                    for (Document document : documents) {
423                            if (_log.isDebugEnabled()) {
424                                    _log.debug("Document " + document.toString());
425                            }
426    
427                            _searchPermissionChecker.addPermissionFields(companyId, document);
428                    }
429    
430                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
431    
432                    IndexWriter indexWriter = searchEngine.getIndexWriter();
433    
434                    SearchContext searchContext = new SearchContext();
435    
436                    searchContext.setCompanyId(companyId);
437                    searchContext.setSearchEngineId(searchEngineId);
438    
439                    indexWriter.updateDocuments(searchContext, documents);
440            }
441    
442            public static void updatePermissionFields(long resourceId) {
443                    if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
444                            return;
445                    }
446    
447                    _searchPermissionChecker.updatePermissionFields(resourceId);
448            }
449    
450            public static void updatePermissionFields(String name, String primKey) {
451                    if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
452                            return;
453                    }
454    
455                    _searchPermissionChecker.updatePermissionFields(name, primKey);
456            }
457    
458            public void setSearchEngine(SearchEngine searchEngine) {
459                    _searchEngines.put(SYSTEM_ENGINE_ID, searchEngine);
460            }
461    
462            public void setSearchEngines(Map<String, SearchEngine> searchEngines) {
463                    _searchEngines.putAll(searchEngines);
464            }
465    
466            public void setSearchPermissionChecker(
467                    SearchPermissionChecker searchPermissionChecker) {
468    
469                    _searchPermissionChecker = searchPermissionChecker;
470            }
471    
472            private static Log _log = LogFactoryUtil.getLog(SearchEngineUtil.class);
473    
474            private static boolean _indexReadOnly = GetterUtil.getBoolean(
475                    PropsUtil.get(PropsKeys.INDEX_READ_ONLY));
476            private static Map<String, SearchEngine> _searchEngines =
477                    new ConcurrentHashMap<String, SearchEngine>();
478            private static SearchPermissionChecker _searchPermissionChecker;
479    
480    }