001
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.security.pacl.permission.PortalRuntimePermission;
021 import com.liferay.portal.kernel.util.GetterUtil;
022 import com.liferay.portal.kernel.util.PropsKeys;
023 import com.liferay.portal.kernel.util.PropsUtil;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.security.permission.PermissionThreadLocal;
026
027 import java.util.Collection;
028 import java.util.HashSet;
029 import java.util.List;
030 import java.util.Locale;
031 import java.util.Map;
032 import java.util.Set;
033 import java.util.concurrent.ConcurrentHashMap;
034
035
040 public class SearchEngineUtil {
041
042
046 public static final int ALL_POS = -1;
047
048 public static final String GENERIC_ENGINE_ID = "GENERIC_ENGINE";
049
050 public static final String SYSTEM_ENGINE_ID = "SYSTEM_ENGINE";
051
052
056 public static void addDocument(long companyId, Document document)
057 throws SearchException {
058
059 addDocument(_getSearchEngineId(document), companyId, document);
060 }
061
062 public static void addDocument(
063 String searchEngineId, long companyId, Document document)
064 throws SearchException {
065
066 if (isIndexReadOnly()) {
067 return;
068 }
069
070 if (_log.isDebugEnabled()) {
071 _log.debug("Add document " + document.toString());
072 }
073
074 SearchEngine searchEngine = getSearchEngine(searchEngineId);
075
076 IndexWriter indexWriter = searchEngine.getIndexWriter();
077
078 _searchPermissionChecker.addPermissionFields(companyId, document);
079
080 SearchContext searchContext = new SearchContext();
081
082 searchContext.setCompanyId(companyId);
083 searchContext.setSearchEngineId(searchEngineId);
084
085 indexWriter.addDocument(searchContext, document);
086 }
087
088
092 public static void addDocuments(
093 long companyId, Collection<Document> documents)
094 throws SearchException {
095
096 addDocuments(_getSearchEngineId(documents), companyId, documents);
097 }
098
099 public static void addDocuments(
100 String searchEngineId, long companyId,
101 Collection<Document> documents)
102 throws SearchException {
103
104 if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
105 return;
106 }
107
108 SearchEngine searchEngine = getSearchEngine(searchEngineId);
109
110 IndexWriter indexWriter = searchEngine.getIndexWriter();
111
112 for (Document document : documents) {
113 if (_log.isDebugEnabled()) {
114 _log.debug("Add document " + document.toString());
115 }
116
117 _searchPermissionChecker.addPermissionFields(companyId, document);
118 }
119
120 SearchContext searchContext = new SearchContext();
121
122 searchContext.setCompanyId(companyId);
123 searchContext.setSearchEngineId(searchEngineId);
124
125 indexWriter.addDocuments(searchContext, documents);
126 }
127
128
132 public static void addSearchEngine(SearchEngine searchEngine) {
133 String searchEngineId = getDefaultSearchEngineId();
134
135 PortalRuntimePermission.checkSearchEngine(searchEngineId);
136
137 _searchEngines.put(searchEngineId, searchEngine);
138 }
139
140
144 public static void deleteDocument(long companyId, String uid)
145 throws SearchException {
146
147 for (String searchEngineId : _searchEngines.keySet()) {
148 deleteDocument(searchEngineId, companyId, uid);
149 }
150 }
151
152 public static void deleteDocument(
153 String searchEngineId, long companyId, String uid)
154 throws SearchException {
155
156 if (isIndexReadOnly()) {
157 return;
158 }
159
160 SearchEngine searchEngine = getSearchEngine(searchEngineId);
161
162 IndexWriter indexWriter = searchEngine.getIndexWriter();
163
164 SearchContext searchContext = new SearchContext();
165
166 searchContext.setCompanyId(companyId);
167 searchContext.setSearchEngineId(searchEngineId);
168
169 indexWriter.deleteDocument(searchContext, uid);
170 }
171
172
176 public static void deleteDocuments(long companyId, Collection<String> uids)
177 throws SearchException {
178
179 for (String searchEngineId : _searchEngines.keySet()) {
180 deleteDocuments(searchEngineId, companyId, uids);
181 }
182 }
183
184 public static void deleteDocuments(
185 String searchEngineId, long companyId, Collection<String> uids)
186 throws SearchException {
187
188 if (isIndexReadOnly() || (uids == null) || uids.isEmpty()) {
189 return;
190 }
191
192 SearchEngine searchEngine = getSearchEngine(searchEngineId);
193
194 IndexWriter indexWriter = searchEngine.getIndexWriter();
195
196 SearchContext searchContext = new SearchContext();
197
198 searchContext.setCompanyId(companyId);
199 searchContext.setSearchEngineId(searchEngineId);
200
201 indexWriter.deleteDocuments(searchContext, uids);
202 }
203
204
208 public static void deletePortletDocuments(long companyId, String portletId)
209 throws SearchException {
210
211 for (String searchEngineId : _searchEngines.keySet()) {
212 deletePortletDocuments(searchEngineId, companyId, portletId);
213 }
214 }
215
216 public static void deletePortletDocuments(
217 String searchEngineId, long companyId, String portletId)
218 throws SearchException {
219
220 if (isIndexReadOnly()) {
221 return;
222 }
223
224 SearchEngine searchEngine = getSearchEngine(searchEngineId);
225
226 if (searchEngine == null) {
227 return;
228 }
229
230 IndexWriter indexWriter = searchEngine.getIndexWriter();
231
232 SearchContext searchContext = new SearchContext();
233
234 searchContext.setCompanyId(companyId);
235 searchContext.setSearchEngineId(searchEngineId);
236
237 indexWriter.deletePortletDocuments(searchContext, portletId);
238 }
239
240 public static String getDefaultSearchEngineId() {
241 if (_defaultSearchEngineId == null) {
242 return SYSTEM_ENGINE_ID;
243 }
244
245 return _defaultSearchEngineId;
246 }
247
248 public static String[] getEntryClassNames() {
249 Set<String> assetEntryClassNames = new HashSet<String>();
250
251 for (Indexer indexer : IndexerRegistryUtil.getIndexers()) {
252 for (String className : indexer.getClassNames()) {
253 if (!_excludedEntryClassNames.contains(className)) {
254 assetEntryClassNames.add(className);
255 }
256 }
257 }
258
259 return assetEntryClassNames.toArray(
260 new String[assetEntryClassNames.size()]);
261 }
262
263
266 public static SearchEngine getSearchEngine() {
267 return getSearchEngine(getDefaultSearchEngineId());
268 }
269
270 public static SearchEngine getSearchEngine(String searchEngineId) {
271 PortalRuntimePermission.checkSearchEngine(searchEngineId);
272
273 SearchEngine searchEngine = _searchEngines.get(searchEngineId);
274
275 if (searchEngine == null) {
276 if (getDefaultSearchEngineId().equals(searchEngineId)) {
277 throw new IllegalStateException(
278 "There is no default search engine configured with ID " +
279 getDefaultSearchEngineId());
280 }
281
282 if (_log.isWarnEnabled()) {
283 _log.warn(
284 "There is no search engine configured with ID " +
285 searchEngineId);
286 }
287 }
288
289 return searchEngine;
290 }
291
292 public static Set<String> getSearchEngineIds() {
293 PortalRuntimePermission.checkGetBeanProperty(
294 SearchEngineUtil.class, "searchEngineIds");
295
296 return _searchEngines.keySet();
297 }
298
299 public static SearchEngine getSearchEngineSilent(String searchEngineId) {
300 PortalRuntimePermission.checkSearchEngine(searchEngineId);
301
302 return _searchEngines.get(searchEngineId);
303 }
304
305 public static SearchPermissionChecker getSearchPermissionChecker() {
306 PortalRuntimePermission.checkGetBeanProperty(
307 SearchEngineUtil.class, "searchPermissionChecker");
308
309 return _searchPermissionChecker;
310 }
311
312 public static String getSearchReaderDestinationName(String searchEngineId) {
313 return DestinationNames.SEARCH_READER.concat(StringPool.SLASH).concat(
314 searchEngineId);
315 }
316
317 public static String getSearchWriterDestinationName(String searchEngineId) {
318 return DestinationNames.SEARCH_WRITER.concat(StringPool.SLASH).concat(
319 searchEngineId);
320 }
321
322 public static void indexDictionaries(long companyId)
323 throws SearchException {
324
325 Set<String> searchEngineIds = getSearchEngineIds();
326
327 for (String searchEngineId : searchEngineIds) {
328 indexDictionaries(searchEngineId, companyId);
329 }
330 }
331
332 public static void indexDictionaries(String searchEngineId, long companyId)
333 throws SearchException {
334
335 SearchEngine searchEngine = getSearchEngine(searchEngineId);
336
337 IndexWriter indexWriter = searchEngine.getIndexWriter();
338
339 SearchContext searchContext = new SearchContext();
340
341 searchContext.setCompanyId(companyId);
342 searchContext.setSearchEngineId(searchEngineId);
343
344 indexWriter.indexDictionaries(searchContext);
345 }
346
347 public static void indexDictionary(long companyId, Locale locale)
348 throws SearchException {
349
350 Set<String> searchEngineIds = getSearchEngineIds();
351
352 for (String searchEngineId : searchEngineIds) {
353 indexDictionary(searchEngineId, companyId, locale);
354 }
355 }
356
357 public static void indexDictionary(
358 String searchEngineId, long companyId, Locale locale)
359 throws SearchException {
360
361 SearchEngine searchEngine = getSearchEngine(searchEngineId);
362
363 IndexWriter indexWriter = searchEngine.getIndexWriter();
364
365 SearchContext searchContext = new SearchContext();
366
367 searchContext.setCompanyId(companyId);
368 searchContext.setSearchEngineId(searchEngineId);
369 searchContext.setLocale(locale);
370
371 indexWriter.indexDictionary(searchContext);
372 }
373
374 public static boolean isIndexReadOnly() {
375 PortalRuntimePermission.checkGetBeanProperty(
376 SearchEngineUtil.class, "indexReadOnly");
377
378 return _indexReadOnly;
379 }
380
381 public static SearchEngine removeSearchEngine(String searchEngineId) {
382 PortalRuntimePermission.checkSearchEngine(searchEngineId);
383
384 return _searchEngines.remove(searchEngineId);
385 }
386
387
390 public static Hits search(
391 long companyId, long[] groupIds, long userId, String className,
392 Query query, int start, int end)
393 throws SearchException {
394
395 SearchContext searchContext = new SearchContext();
396
397 searchContext.setSearchEngineId(getDefaultSearchEngineId());
398
399 if (userId > 0) {
400 query = _searchPermissionChecker.getPermissionQuery(
401 companyId, groupIds, userId, className, query, searchContext);
402 }
403
404 return search(
405 companyId, query, SortFactoryUtil.getDefaultSorts(), start, end);
406 }
407
408
411 public static Hits search(
412 long companyId, long[] groupIds, long userId, String className,
413 Query query, Sort sort, int start, int end)
414 throws SearchException {
415
416 SearchContext searchContext = new SearchContext();
417
418 searchContext.setSearchEngineId(getDefaultSearchEngineId());
419
420 if (userId > 0) {
421 query = _searchPermissionChecker.getPermissionQuery(
422 companyId, groupIds, userId, className, query, searchContext);
423 }
424
425 return search(companyId, query, sort, start, end);
426 }
427
428
431 public static Hits search(
432 long companyId, long[] groupIds, long userId, String className,
433 Query query, Sort[] sorts, int start, int end)
434 throws SearchException {
435
436 SearchContext searchContext = new SearchContext();
437
438 searchContext.setSearchEngineId(getDefaultSearchEngineId());
439
440 if (userId > 0) {
441 query = _searchPermissionChecker.getPermissionQuery(
442 companyId, groupIds, userId, className, query, searchContext);
443 }
444
445 return search(companyId, query, sorts, start, end);
446 }
447
448
452 public static Hits search(long companyId, Query query, int start, int end)
453 throws SearchException {
454
455 return search(getDefaultSearchEngineId(), companyId, query, start, end);
456 }
457
458
462 public static Hits search(
463 long companyId, Query query, Sort sort, int start, int end)
464 throws SearchException {
465
466 return search(
467 getDefaultSearchEngineId(), companyId, query, sort, start, end);
468 }
469
470
474 public static Hits search(
475 long companyId, Query query, Sort[] sorts, int start, int end)
476 throws SearchException {
477
478 return search(
479 getDefaultSearchEngineId(), companyId, query, sorts, start, end);
480 }
481
482 public static Hits search(SearchContext searchContext, Query query)
483 throws SearchException {
484
485 if (_log.isDebugEnabled()) {
486 _log.debug("Search query " + query.toString());
487 }
488
489 SearchEngine searchEngine = getSearchEngine(
490 searchContext.getSearchEngineId());
491
492 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
493
494 return indexSearcher.search(searchContext, query);
495 }
496
497 public static Hits search(
498 String searchEngineId, long companyId, Query query, int start,
499 int end)
500 throws SearchException {
501
502 if (_log.isDebugEnabled()) {
503 _log.debug("Search query " + query.toString());
504 }
505
506 SearchEngine searchEngine = getSearchEngine(searchEngineId);
507
508 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
509
510 return indexSearcher.search(
511 searchEngineId, companyId, query, SortFactoryUtil.getDefaultSorts(),
512 start, end);
513 }
514
515 public static Hits search(
516 String searchEngineId, long companyId, Query query, Sort sort,
517 int start, int end)
518 throws SearchException {
519
520 if (_log.isDebugEnabled()) {
521 _log.debug("Search query " + query.toString());
522 }
523
524 SearchEngine searchEngine = getSearchEngine(searchEngineId);
525
526 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
527
528 return indexSearcher.search(
529 searchEngineId, companyId, query, new Sort[] {sort}, start, end);
530 }
531
532 public static Hits search(
533 String searchEngineId, long companyId, Query query, Sort[] sorts,
534 int start, int end)
535 throws SearchException {
536
537 if (_log.isDebugEnabled()) {
538 _log.debug("Search query " + query.toString());
539 }
540
541 SearchEngine searchEngine = getSearchEngine(searchEngineId);
542
543 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
544
545 return indexSearcher.search(
546 searchEngineId, companyId, query, sorts, start, end);
547 }
548
549 public static void setDefaultSearchEngineId(String defaultSearchEngineId) {
550 PortalRuntimePermission.checkSetBeanProperty(
551 SearchEngineUtil.class, "defaultSearchEngineId");
552
553 _defaultSearchEngineId = defaultSearchEngineId;
554 }
555
556 public static void setIndexReadOnly(boolean indexReadOnly) {
557 PortalRuntimePermission.checkSetBeanProperty(
558 SearchEngineUtil.class, "indexReadOnly");
559
560 _indexReadOnly = indexReadOnly;
561 }
562
563 public static void setSearchEngine(
564 String searchEngineId, SearchEngine searchEngine) {
565
566 PortalRuntimePermission.checkSearchEngine(searchEngineId);
567
568 _searchEngines.put(searchEngineId, searchEngine);
569 }
570
571 public static String spellCheckKeywords(SearchContext searchContext)
572 throws SearchException {
573
574 if (_log.isDebugEnabled()) {
575 _log.debug("Spell checking " + searchContext.getKeywords());
576 }
577
578 SearchEngine searchEngine = getSearchEngine(
579 searchContext.getSearchEngineId());
580
581 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
582
583 return indexSearcher.spellCheckKeywords(searchContext);
584 }
585
586 public static Map<String, List<String>> spellCheckKeywords(
587 SearchContext searchContext, int max)
588 throws SearchException {
589
590 if (_log.isDebugEnabled()) {
591 _log.debug("Spell checking " + searchContext.getKeywords());
592 }
593
594 SearchEngine searchEngine = getSearchEngine(
595 searchContext.getSearchEngineId());
596
597 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
598
599 return indexSearcher.spellCheckKeywords(searchContext, max);
600 }
601
602 public static String[] suggestKeywordQueries(
603 SearchContext searchContext, int max)
604 throws SearchException {
605
606 if (_log.isDebugEnabled()) {
607 _log.debug(
608 "Suggesting keyword queries" + searchContext.getKeywords());
609 }
610
611 SearchEngine searchEngine = getSearchEngine(
612 searchContext.getSearchEngineId());
613
614 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
615
616 return indexSearcher.suggestKeywordQueries(searchContext, max);
617 }
618
619
623 public static void updateDocument(long companyId, Document document)
624 throws SearchException {
625
626 updateDocument(_getSearchEngineId(document), companyId, document);
627 }
628
629 public static void updateDocument(
630 String searchEngineId, long companyId, Document document)
631 throws SearchException {
632
633 if (isIndexReadOnly()) {
634 return;
635 }
636
637 if (_log.isDebugEnabled()) {
638 _log.debug("Document " + document.toString());
639 }
640
641 SearchEngine searchEngine = getSearchEngine(searchEngineId);
642
643 IndexWriter indexWriter = searchEngine.getIndexWriter();
644
645 _searchPermissionChecker.addPermissionFields(companyId, document);
646
647 SearchContext searchContext = new SearchContext();
648
649 searchContext.setCompanyId(companyId);
650 searchContext.setSearchEngineId(searchEngineId);
651
652 indexWriter.updateDocument(searchContext, document);
653 }
654
655
659 public static void updateDocuments(
660 long companyId, Collection<Document> documents)
661 throws SearchException {
662
663 updateDocuments(_getSearchEngineId(documents), companyId, documents);
664 }
665
666 public static void updateDocuments(
667 String searchEngineId, long companyId,
668 Collection<Document> documents)
669 throws SearchException {
670
671 if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
672 return;
673 }
674
675 SearchEngine searchEngine = getSearchEngine(searchEngineId);
676
677 IndexWriter indexWriter = searchEngine.getIndexWriter();
678
679 for (Document document : documents) {
680 if (_log.isDebugEnabled()) {
681 _log.debug("Document " + document.toString());
682 }
683
684 _searchPermissionChecker.addPermissionFields(companyId, document);
685 }
686
687 SearchContext searchContext = new SearchContext();
688
689 searchContext.setCompanyId(companyId);
690 searchContext.setSearchEngineId(searchEngineId);
691
692 indexWriter.updateDocuments(searchContext, documents);
693 }
694
695 public static void updatePermissionFields(String name, String primKey) {
696 if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
697 return;
698 }
699
700 _searchPermissionChecker.updatePermissionFields(name, primKey);
701 }
702
703 public void setExcludedEntryClassNames(
704 List<String> excludedEntryClassNames) {
705
706 PortalRuntimePermission.checkSetBeanProperty(
707 getClass(), "excludedEntryClassNames");
708
709 _excludedEntryClassNames.addAll(excludedEntryClassNames);
710 }
711
712
716 public void setSearchEngine(SearchEngine searchEngine) {
717 String searchEngineId = getDefaultSearchEngineId();
718
719 PortalRuntimePermission.checkSearchEngine(searchEngineId);
720
721 _searchEngines.put(searchEngineId, searchEngine);
722 }
723
724 public void setSearchPermissionChecker(
725 SearchPermissionChecker searchPermissionChecker) {
726
727 PortalRuntimePermission.checkSetBeanProperty(
728 getClass(), "searchPermissionChecker");
729
730 _searchPermissionChecker = searchPermissionChecker;
731 }
732
733 private static String _getSearchEngineId(Collection<Document> documents) {
734 if (!documents.isEmpty()) {
735 Document document = documents.iterator().next();
736
737 return _getSearchEngineId(document);
738 }
739
740 return getDefaultSearchEngineId();
741 }
742
743 private static String _getSearchEngineId(Document document) {
744 String entryClassName = document.get("entryClassName");
745
746 Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
747
748 String searchEngineId = indexer.getSearchEngineId();
749
750 if (_log.isDebugEnabled()) {
751 _log.debug(
752 "Search engine ID for " + indexer.getClass() + " is " +
753 searchEngineId);
754 }
755
756 return searchEngineId;
757 }
758
759 private static Log _log = LogFactoryUtil.getLog(SearchEngineUtil.class);
760
761 private static String _defaultSearchEngineId;
762 private static Set<String> _excludedEntryClassNames = new HashSet<String>();
763 private static boolean _indexReadOnly = GetterUtil.getBoolean(
764 PropsUtil.get(PropsKeys.INDEX_READ_ONLY));
765 private static Map<String, SearchEngine> _searchEngines =
766 new ConcurrentHashMap<String, SearchEngine>();
767 private static SearchPermissionChecker _searchPermissionChecker;
768
769 }