001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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(
172                            long companyId, String portletId)
173                    throws SearchException {
174    
175                    deletePortletDocuments(SYSTEM_ENGINE_ID, companyId, portletId);
176            }
177    
178            public static void deletePortletDocuments(
179                            String searchEngineId, long companyId, String portletId)
180                    throws SearchException {
181    
182                    if (isIndexReadOnly()) {
183                            return;
184                    }
185    
186                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
187    
188                    if (searchEngine == null) {
189                            return;
190                    }
191    
192                    IndexWriter indexWriter = searchEngine.getIndexWriter();
193    
194                    SearchContext searchContext = new SearchContext();
195    
196                    searchContext.setCompanyId(companyId);
197                    searchContext.setSearchEngineId(searchEngineId);
198    
199                    indexWriter.deletePortletDocuments(searchContext, portletId);
200            }
201    
202            public static SearchEngine getSearchEngine() {
203                    return getSearchEngine(SYSTEM_ENGINE_ID);
204            }
205    
206            public static SearchEngine getSearchEngine(String searchEngineId) {
207                    return _searchEngines.get(searchEngineId);
208            }
209    
210            public static SearchPermissionChecker getSearchPermissionChecker() {
211                    return _searchPermissionChecker;
212            }
213    
214            public static String getSearchReaderDestinationName(String searchEngineId) {
215                    return DestinationNames.SEARCH_READER.concat(StringPool.SLASH).concat(
216                            searchEngineId);
217            }
218    
219            public static String getSearchWriterDestinationName(String searchEngineId) {
220                    return DestinationNames.SEARCH_WRITER.concat(StringPool.SLASH).concat(
221                            searchEngineId);
222            }
223    
224            public static boolean isIndexReadOnly() {
225                    return _indexReadOnly;
226            }
227    
228            public static SearchEngine removeSearchEngine(String searchEngineName) {
229                    return _searchEngines.remove(searchEngineName);
230            }
231    
232            public static Hits search(
233                            long companyId, long[] groupIds, long userId, String className,
234                            Query query, int start, int end)
235                    throws SearchException {
236    
237                    SearchContext searchContext = new SearchContext();
238    
239                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
240    
241                    if (userId > 0) {
242                            query = _searchPermissionChecker.getPermissionQuery(
243                                    companyId, groupIds, userId, className, query, searchContext);
244                    }
245    
246                    return search(
247                            companyId, query, SortFactoryUtil.getDefaultSorts(), start, end);
248            }
249    
250            public static Hits search(
251                            long companyId, long[] groupIds, long userId, String className,
252                            Query query, Sort sort, int start, int end)
253                    throws SearchException {
254    
255                    SearchContext searchContext = new SearchContext();
256    
257                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
258    
259                    if (userId > 0) {
260                            query = _searchPermissionChecker.getPermissionQuery(
261                                    companyId, groupIds, userId, className, query, searchContext);
262                    }
263    
264                    return search(companyId, query, sort, start, end);
265            }
266    
267            public static Hits search(
268                            long companyId, long[] groupIds, long userId, String className,
269                            Query query, Sort[] sorts, 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, sorts, start, end);
282            }
283    
284            public static Hits search(long companyId, Query query, int start, int end)
285                    throws SearchException {
286    
287                    return search(SYSTEM_ENGINE_ID, companyId, query, start, end);
288            }
289    
290            public static Hits search(
291                            long companyId, Query query, Sort sort, int start, int end)
292                    throws SearchException {
293    
294                    return search(SYSTEM_ENGINE_ID, companyId, query, sort, start, end);
295            }
296    
297            public static Hits search(
298                            long companyId, Query query, Sort[] sorts, int start, int end)
299                    throws SearchException {
300    
301                    return search(SYSTEM_ENGINE_ID, companyId, query, sorts, start, end);
302            }
303    
304            public static Hits search(SearchContext searchContext, Query query)
305                    throws SearchException {
306    
307                    if (_log.isDebugEnabled()) {
308                            _log.debug("Search query " + query.toString());
309                    }
310    
311                    SearchEngine searchEngine = _searchEngines.get(
312                            searchContext.getSearchEngineId());
313    
314                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
315    
316                    return indexSearcher.search(searchContext, query);
317            }
318    
319            public static Hits search(
320                            String searchEngineId, long companyId, Query query, int start,
321                            int end)
322                    throws SearchException {
323    
324                    if (_log.isDebugEnabled()) {
325                            _log.debug("Search query " + query.toString());
326                    }
327    
328                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
329    
330                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
331    
332                    return indexSearcher.search(
333                            searchEngineId, companyId, query, SortFactoryUtil.getDefaultSorts(),
334                            start, end);
335            }
336    
337            public static Hits search(
338                            String searchEngineId, long companyId, Query query, Sort sort,
339                            int start, int end)
340                    throws SearchException {
341    
342                    if (_log.isDebugEnabled()) {
343                            _log.debug("Search query " + query.toString());
344                    }
345    
346                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
347    
348                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
349    
350                    return indexSearcher.search(
351                            searchEngineId, companyId, query, new Sort[] {sort}, start, end);
352            }
353    
354            public static Hits search(
355                            String searchEngineId, long companyId, Query query, Sort[] sorts,
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, sorts, start, end);
369            }
370    
371            public static void setIndexReadOnly(boolean indexReadOnly) {
372                    _indexReadOnly = indexReadOnly;
373            }
374    
375            public static void updateDocument(long companyId, Document document)
376                    throws SearchException {
377    
378                    updateDocument(SYSTEM_ENGINE_ID, companyId, document);
379            }
380    
381            public static void updateDocument(
382                            String searchEngineId, long companyId, Document document)
383                    throws SearchException {
384    
385                    if (isIndexReadOnly()) {
386                            return;
387                    }
388    
389                    if (_log.isDebugEnabled()) {
390                            _log.debug("Document " + document.toString());
391                    }
392    
393                    _searchPermissionChecker.addPermissionFields(companyId, document);
394    
395                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
396    
397                    IndexWriter indexWriter = searchEngine.getIndexWriter();
398    
399                    SearchContext searchContext = new SearchContext();
400    
401                    searchContext.setCompanyId(companyId);
402                    searchContext.setSearchEngineId(searchEngineId);
403    
404                    indexWriter.updateDocument(searchContext, document);
405            }
406    
407            public static void updateDocuments(
408                            long companyId, Collection<Document> documents)
409                    throws SearchException {
410    
411                    updateDocuments(SYSTEM_ENGINE_ID, companyId, documents);
412            }
413    
414            public static void updateDocuments(
415                            String searchEngineId, long companyId,
416                            Collection<Document> documents)
417                    throws SearchException {
418    
419                    if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
420                            return;
421                    }
422    
423                    for (Document document : documents) {
424                            if (_log.isDebugEnabled()) {
425                                    _log.debug("Document " + document.toString());
426                            }
427    
428                            _searchPermissionChecker.addPermissionFields(companyId, document);
429                    }
430    
431                    SearchEngine searchEngine = _searchEngines.get(searchEngineId);
432    
433                    IndexWriter indexWriter = searchEngine.getIndexWriter();
434    
435                    SearchContext searchContext = new SearchContext();
436    
437                    searchContext.setCompanyId(companyId);
438                    searchContext.setSearchEngineId(searchEngineId);
439    
440                    indexWriter.updateDocuments(searchContext, documents);
441            }
442    
443            public static void updatePermissionFields(long resourceId) {
444                    if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
445                            return;
446                    }
447    
448                    _searchPermissionChecker.updatePermissionFields(resourceId);
449            }
450    
451            public static void updatePermissionFields(String name, String primKey) {
452                    if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
453                            return;
454                    }
455    
456                    _searchPermissionChecker.updatePermissionFields(name, primKey);
457            }
458    
459            public void setSearchEngine(SearchEngine searchEngine) {
460                    _searchEngines.put(SYSTEM_ENGINE_ID, searchEngine);
461            }
462    
463            public void setSearchEngines(Map<String,SearchEngine> searchEngines) {
464                    _searchEngines.putAll(searchEngines);
465            }
466    
467            public void setSearchPermissionChecker(
468                    SearchPermissionChecker searchPermissionChecker) {
469    
470                    _searchPermissionChecker = searchPermissionChecker;
471            }
472    
473            private static Log _log = LogFactoryUtil.getLog(SearchEngineUtil.class);
474    
475            private static boolean _indexReadOnly = GetterUtil.getBoolean(
476                    PropsUtil.get(PropsKeys.INDEX_READ_ONLY));
477            private static Map<String, SearchEngine> _searchEngines =
478                    new ConcurrentHashMap<String,SearchEngine>();
479            private static SearchPermissionChecker _searchPermissionChecker;
480    
481    }