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.messaging.proxy.ProxyModeThreadLocal;
021 import com.liferay.portal.kernel.search.queue.QueuingSearchEngine;
022 import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
023 import com.liferay.portal.kernel.util.ClassUtil;
024 import com.liferay.portal.kernel.util.GetterUtil;
025 import com.liferay.portal.kernel.util.PropsKeys;
026 import com.liferay.portal.kernel.util.PropsUtil;
027 import com.liferay.portal.kernel.util.ProxyFactory;
028 import com.liferay.portal.kernel.util.StringPool;
029 import com.liferay.portal.security.permission.PermissionThreadLocal;
030 import com.liferay.registry.Registry;
031 import com.liferay.registry.RegistryUtil;
032 import com.liferay.registry.ServiceReference;
033 import com.liferay.registry.ServiceTracker;
034 import com.liferay.registry.ServiceTrackerCustomizer;
035
036 import java.util.Collection;
037 import java.util.HashMap;
038 import java.util.HashSet;
039 import java.util.Iterator;
040 import java.util.List;
041 import java.util.Locale;
042 import java.util.Map;
043 import java.util.Set;
044 import java.util.concurrent.ConcurrentHashMap;
045
046
051 public class SearchEngineUtil {
052
053 public static final String GENERIC_ENGINE_ID = "GENERIC_ENGINE";
054
055 public static final String SYSTEM_ENGINE_ID = "SYSTEM_ENGINE";
056
057
061 @Deprecated
062 public static void addDocument(
063 String searchEngineId, long companyId, Document document)
064 throws SearchException {
065
066 addDocument(searchEngineId, companyId, document, false);
067 }
068
069 public static void addDocument(
070 String searchEngineId, long companyId, Document document,
071 boolean commitImmediately)
072 throws SearchException {
073
074 if (isIndexReadOnly() || (document == null)) {
075 return;
076 }
077
078 if (_log.isDebugEnabled()) {
079 _log.debug("Add document " + document.toString());
080 }
081
082 SearchEngine searchEngine = getSearchEngine(searchEngineId);
083
084 IndexWriter indexWriter = searchEngine.getIndexWriter();
085
086 _searchPermissionChecker.addPermissionFields(companyId, document);
087
088 SearchContext searchContext = new SearchContext();
089
090 searchContext.setCompanyId(companyId);
091 searchContext.setSearchEngineId(searchEngineId);
092
093 setCommitImmediately(searchContext, commitImmediately);
094
095 indexWriter.addDocument(searchContext, document);
096 }
097
098
102 @Deprecated
103 public static void addDocuments(
104 String searchEngineId, long companyId,
105 Collection<Document> documents)
106 throws SearchException {
107
108 addDocuments(searchEngineId, companyId, documents, false);
109 }
110
111 public static void addDocuments(
112 String searchEngineId, long companyId,
113 Collection<Document> documents, boolean commitImmediately)
114 throws SearchException {
115
116 if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
117 return;
118 }
119
120 SearchEngine searchEngine = getSearchEngine(searchEngineId);
121
122 IndexWriter indexWriter = searchEngine.getIndexWriter();
123
124 for (Document document : documents) {
125 if (_log.isDebugEnabled()) {
126 _log.debug("Add document " + document.toString());
127 }
128
129 _searchPermissionChecker.addPermissionFields(companyId, document);
130 }
131
132 SearchContext searchContext = new SearchContext();
133
134 searchContext.setCompanyId(companyId);
135 searchContext.setSearchEngineId(searchEngineId);
136
137 setCommitImmediately(searchContext, commitImmediately);
138
139 indexWriter.addDocuments(searchContext, documents);
140 }
141
142 public synchronized static void backup(long companyId, String backupName)
143 throws SearchException {
144
145 for (SearchEngine searchEngine : _searchEngines.values()) {
146 searchEngine.backup(companyId, backupName);
147 }
148 }
149
150 public synchronized static String backup(
151 long companyId, String searchEngineId, String backupName)
152 throws SearchException {
153
154 SearchEngine searchEngine = getSearchEngine(searchEngineId);
155
156 return searchEngine.backup(companyId, backupName);
157 }
158
159 public synchronized static void backup(String backupName)
160 throws SearchException {
161
162 for (SearchEngine searchEngine : _searchEngines.values()) {
163 for (long companyId : _companyIds.keySet()) {
164 searchEngine.backup(companyId, backupName);
165 }
166 }
167 }
168
169 public static void commit(String searchEngineId) throws SearchException {
170 for (long companyId : _companyIds.keySet()) {
171 commit(searchEngineId, companyId);
172 }
173 }
174
175 public static void commit(String searchEngineId, long companyId)
176 throws SearchException {
177
178 SearchEngine searchEngine = getSearchEngine(searchEngineId);
179
180 IndexWriter indexWriter = searchEngine.getIndexWriter();
181
182 SearchContext searchContext = new SearchContext();
183
184 searchContext.setCompanyId(companyId);
185 searchContext.setSearchEngineId(searchEngineId);
186
187 indexWriter.commit(searchContext);
188 }
189
190
194 @Deprecated
195 public static void deleteDocument(
196 String searchEngineId, long companyId, String uid)
197 throws SearchException {
198
199 deleteDocument(searchEngineId, companyId, uid, false);
200 }
201
202 public static void deleteDocument(
203 String searchEngineId, long companyId, String uid,
204 boolean commitImmediately)
205 throws SearchException {
206
207 if (isIndexReadOnly()) {
208 return;
209 }
210
211 SearchEngine searchEngine = getSearchEngine(searchEngineId);
212
213 IndexWriter indexWriter = searchEngine.getIndexWriter();
214
215 SearchContext searchContext = new SearchContext();
216
217 searchContext.setCompanyId(companyId);
218 searchContext.setSearchEngineId(searchEngineId);
219
220 setCommitImmediately(searchContext, commitImmediately);
221
222 indexWriter.deleteDocument(searchContext, uid);
223 }
224
225
229 @Deprecated
230 public static void deleteDocuments(
231 String searchEngineId, long companyId, Collection<String> uids)
232 throws SearchException {
233
234 deleteDocuments(searchEngineId, companyId, uids, false);
235 }
236
237 public static void deleteDocuments(
238 String searchEngineId, long companyId, Collection<String> uids,
239 boolean commitImmediately)
240 throws SearchException {
241
242 if (isIndexReadOnly() || (uids == null) || uids.isEmpty()) {
243 return;
244 }
245
246 SearchEngine searchEngine = getSearchEngine(searchEngineId);
247
248 IndexWriter indexWriter = searchEngine.getIndexWriter();
249
250 SearchContext searchContext = new SearchContext();
251
252 searchContext.setCompanyId(companyId);
253 searchContext.setSearchEngineId(searchEngineId);
254
255 setCommitImmediately(searchContext, commitImmediately);
256
257 indexWriter.deleteDocuments(searchContext, uids);
258 }
259
260 public static void deleteEntityDocuments(
261 String searchEngineId, long companyId, String className,
262 boolean commitImmediately)
263 throws SearchException {
264
265 if (isIndexReadOnly()) {
266 return;
267 }
268
269 SearchEngine searchEngine = getSearchEngine(searchEngineId);
270
271 if (searchEngine == null) {
272 return;
273 }
274
275 IndexWriter indexWriter = searchEngine.getIndexWriter();
276
277 SearchContext searchContext = new SearchContext();
278
279 searchContext.setCompanyId(companyId);
280 searchContext.setSearchEngineId(searchEngineId);
281
282 setCommitImmediately(searchContext, commitImmediately);
283
284 indexWriter.deleteEntityDocuments(searchContext, className);
285 }
286
287
291 @Deprecated
292 public static void deletePortletDocuments(
293 String searchEngineId, long companyId, String portletId)
294 throws SearchException {
295
296 deleteEntityDocuments(searchEngineId, companyId, portletId, false);
297 }
298
299 public static void flushQueuedSearchEngine() {
300 synchronized (_queuingSearchEngines) {
301 for (QueuingSearchEngine queuingSearchEngine :
302 _queuingSearchEngines.values()) {
303
304 queuingSearchEngine.flush();
305 }
306
307 _queuingSearchEngines.clear();
308 }
309 }
310
311 public static void flushQueuedSearchEngine(String searchEngineId) {
312 QueuingSearchEngine queuingSearchEngine = null;
313
314 synchronized (_queuingSearchEngines) {
315 queuingSearchEngine = _queuingSearchEngines.remove(searchEngineId);
316 }
317
318 if (queuingSearchEngine != null) {
319 queuingSearchEngine.flush();
320 }
321 }
322
323 public static String getDefaultSearchEngineId() {
324 if (_defaultSearchEngineId == null) {
325 return SYSTEM_ENGINE_ID;
326 }
327
328 return _defaultSearchEngineId;
329 }
330
331 public static String[] getEntryClassNames() {
332 Set<String> assetEntryClassNames = new HashSet<>();
333
334 for (Indexer<?> indexer : IndexerRegistryUtil.getIndexers()) {
335 for (String className : indexer.getSearchClassNames()) {
336 if (!_excludedEntryClassNames.contains(className)) {
337 assetEntryClassNames.add(className);
338 }
339 }
340 }
341
342 return assetEntryClassNames.toArray(
343 new String[assetEntryClassNames.size()]);
344 }
345
346 public static String getQueryString(
347 SearchContext searchContext, Query query) {
348
349 SearchEngine searchEngine = getSearchEngine(
350 searchContext.getSearchEngineId());
351
352 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
353
354 try {
355 return indexSearcher.getQueryString(searchContext, query);
356 }
357 catch (ParseException pe) {
358 if (_log.isDebugEnabled()) {
359 _log.debug("Unable to parse query " + query, pe);
360 }
361 }
362
363 return StringPool.BLANK;
364 }
365
366 public static SearchEngine getSearchEngine(String searchEngineId) {
367 PortalRuntimePermission.checkSearchEngine(searchEngineId);
368
369 SearchEngine searchEngine = _searchEngines.get(searchEngineId);
370
371 if (searchEngine != null) {
372 return searchEngine;
373 }
374
375 synchronized (_queuingSearchEngines) {
376 searchEngine = _queuingSearchEngines.get(searchEngineId);
377
378 if (searchEngine == null) {
379 QueuingSearchEngine queuingSearchEngine =
380 new QueuingSearchEngine(_queueCapacity);
381
382 _queuingSearchEngines.put(searchEngineId, queuingSearchEngine);
383
384 searchEngine = queuingSearchEngine;
385 }
386
387 return searchEngine;
388 }
389 }
390
391 public static String getSearchEngineId(Collection<Document> documents) {
392 if (!documents.isEmpty()) {
393 Iterator<Document> iterator = documents.iterator();
394
395 Document document = iterator.next();
396
397 return getSearchEngineId(document);
398 }
399
400 return getDefaultSearchEngineId();
401 }
402
403 public static String getSearchEngineId(Document document) {
404 String entryClassName = document.get("entryClassName");
405
406 Indexer<?> indexer = IndexerRegistryUtil.getIndexer(entryClassName);
407
408 String searchEngineId = indexer.getSearchEngineId();
409
410 if (_log.isDebugEnabled()) {
411 _log.debug(
412 "Search engine ID " + searchEngineId + " is associated with " +
413 ClassUtil.getClassName(indexer));
414 }
415
416 return searchEngineId;
417 }
418
419 public static Set<String> getSearchEngineIds() {
420 PortalRuntimePermission.checkGetBeanProperty(
421 SearchEngineUtil.class, "searchEngineIds");
422
423 return _searchEngines.keySet();
424 }
425
426 public static SearchEngine getSearchEngineSilent(String searchEngineId) {
427 PortalRuntimePermission.checkSearchEngine(searchEngineId);
428
429 return _searchEngines.get(searchEngineId);
430 }
431
432 public static SearchPermissionChecker getSearchPermissionChecker() {
433 PortalRuntimePermission.checkGetBeanProperty(
434 SearchEngineUtil.class, "searchPermissionChecker");
435
436 return _searchPermissionChecker;
437 }
438
439 public static String getSearchReaderDestinationName(String searchEngineId) {
440 return DestinationNames.SEARCH_READER.concat(StringPool.SLASH).concat(
441 searchEngineId);
442 }
443
444 public static String getSearchWriterDestinationName(String searchEngineId) {
445 return DestinationNames.SEARCH_WRITER.concat(StringPool.SLASH).concat(
446 searchEngineId);
447 }
448
449 public static void indexKeyword(
450 long companyId, String querySuggestion, float weight,
451 String keywordType, Locale locale)
452 throws SearchException {
453
454 String searchEngineId = getDefaultSearchEngineId();
455
456 indexKeyword(
457 searchEngineId, companyId, querySuggestion, weight, keywordType,
458 locale);
459 }
460
461 public static void indexKeyword(
462 String searchEngineId, long companyId, String querySuggestion,
463 float weight, String keywordType, Locale locale)
464 throws SearchException {
465
466 SearchEngine searchEngine = getSearchEngine(searchEngineId);
467
468 IndexWriter indexWriter = searchEngine.getIndexWriter();
469
470 SearchContext searchContext = new SearchContext();
471
472 searchContext.setCompanyId(companyId);
473 searchContext.setSearchEngineId(searchEngineId);
474 searchContext.setKeywords(querySuggestion);
475 searchContext.setLocale(locale);
476
477 indexWriter.indexKeyword(searchContext, weight, keywordType);
478 }
479
480 public static void indexQuerySuggestionDictionaries(long companyId)
481 throws SearchException {
482
483 Set<String> searchEngineIds = getSearchEngineIds();
484
485 for (String searchEngineId : searchEngineIds) {
486 indexQuerySuggestionDictionaries(searchEngineId, companyId);
487 }
488 }
489
490 public static void indexQuerySuggestionDictionaries(
491 String searchEngineId, long companyId)
492 throws SearchException {
493
494 SearchEngine searchEngine = getSearchEngine(searchEngineId);
495
496 IndexWriter indexWriter = searchEngine.getIndexWriter();
497
498 SearchContext searchContext = new SearchContext();
499
500 searchContext.setCompanyId(companyId);
501 searchContext.setSearchEngineId(searchEngineId);
502
503 indexWriter.indexQuerySuggestionDictionaries(searchContext);
504 }
505
506 public static void indexQuerySuggestionDictionary(
507 long companyId, Locale locale)
508 throws SearchException {
509
510 String searchEngineId = getDefaultSearchEngineId();
511
512 indexQuerySuggestionDictionary(searchEngineId, companyId, locale);
513 }
514
515 public static void indexQuerySuggestionDictionary(
516 String searchEngineId, long companyId, Locale locale)
517 throws SearchException {
518
519 SearchEngine searchEngine = getSearchEngine(searchEngineId);
520
521 IndexWriter indexWriter = searchEngine.getIndexWriter();
522
523 SearchContext searchContext = new SearchContext();
524
525 searchContext.setCompanyId(companyId);
526 searchContext.setSearchEngineId(searchEngineId);
527 searchContext.setLocale(locale);
528
529 indexWriter.indexQuerySuggestionDictionary(searchContext);
530 }
531
532 public static void indexSpellCheckerDictionaries(long companyId)
533 throws SearchException {
534
535 String searchEngineId = getDefaultSearchEngineId();
536
537 indexSpellCheckerDictionaries(searchEngineId, companyId);
538 }
539
540 public static void indexSpellCheckerDictionaries(
541 String searchEngineId, long companyId)
542 throws SearchException {
543
544 SearchEngine searchEngine = getSearchEngine(searchEngineId);
545
546 IndexWriter indexWriter = searchEngine.getIndexWriter();
547
548 SearchContext searchContext = new SearchContext();
549
550 searchContext.setCompanyId(companyId);
551 searchContext.setSearchEngineId(searchEngineId);
552
553 indexWriter.indexSpellCheckerDictionaries(searchContext);
554 }
555
556 public static void indexSpellCheckerDictionary(
557 long companyId, Locale locale)
558 throws SearchException {
559
560 String searchEngineId = getDefaultSearchEngineId();
561
562 indexSpellCheckerDictionary(searchEngineId, companyId, locale);
563 }
564
565 public static void indexSpellCheckerDictionary(
566 String searchEngineId, long companyId, Locale locale)
567 throws SearchException {
568
569 SearchEngine searchEngine = getSearchEngine(searchEngineId);
570
571 IndexWriter indexWriter = searchEngine.getIndexWriter();
572
573 SearchContext searchContext = new SearchContext();
574
575 searchContext.setCompanyId(companyId);
576 searchContext.setSearchEngineId(searchEngineId);
577 searchContext.setLocale(locale);
578
579 indexWriter.indexSpellCheckerDictionary(searchContext);
580 }
581
582 public synchronized static void initialize(long companyId) {
583 if (_companyIds.containsKey(companyId)) {
584 return;
585 }
586
587 _companyIds.put(companyId, companyId);
588
589 for (SearchEngine searchEngine : _searchEngines.values()) {
590 searchEngine.initialize(companyId);
591 }
592 }
593
594 public static boolean isIndexReadOnly() {
595 PortalRuntimePermission.checkGetBeanProperty(
596 SearchEngineUtil.class, "indexReadOnly");
597
598 return _indexReadOnly;
599 }
600
601 public static void partiallyUpdateDocument(
602 String searchEngineId, long companyId, Document document,
603 boolean commitImmediately)
604 throws SearchException {
605
606 if (isIndexReadOnly() || (document == null)) {
607 return;
608 }
609
610 if (_log.isDebugEnabled()) {
611 _log.debug("Document " + document.toString());
612 }
613
614 SearchEngine searchEngine = getSearchEngine(searchEngineId);
615
616 IndexWriter indexWriter = searchEngine.getIndexWriter();
617
618 _searchPermissionChecker.addPermissionFields(companyId, document);
619
620 SearchContext searchContext = new SearchContext();
621
622 searchContext.setCompanyId(companyId);
623 searchContext.setSearchEngineId(searchEngineId);
624
625 setCommitImmediately(searchContext, commitImmediately);
626
627 indexWriter.partiallyUpdateDocument(searchContext, document);
628 }
629
630 public static void partiallyUpdateDocuments(
631 String searchEngineId, long companyId,
632 Collection<Document> documents, boolean commitImmediately)
633 throws SearchException {
634
635 if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
636 return;
637 }
638
639 SearchEngine searchEngine = getSearchEngine(searchEngineId);
640
641 IndexWriter indexWriter = searchEngine.getIndexWriter();
642
643 for (Document document : documents) {
644 if (_log.isDebugEnabled()) {
645 _log.debug("Document " + document.toString());
646 }
647
648 _searchPermissionChecker.addPermissionFields(companyId, document);
649 }
650
651 SearchContext searchContext = new SearchContext();
652
653 searchContext.setCompanyId(companyId);
654 searchContext.setSearchEngineId(searchEngineId);
655
656 setCommitImmediately(searchContext, commitImmediately);
657
658 indexWriter.partiallyUpdateDocuments(searchContext, documents);
659 }
660
661 public synchronized static void removeBackup(
662 long companyId, String backupName)
663 throws SearchException {
664
665 for (SearchEngine searchEngine : _searchEngines.values()) {
666 searchEngine.removeBackup(companyId, backupName);
667 }
668 }
669
670 public synchronized static void removeBackup(String backupName)
671 throws SearchException {
672
673 for (SearchEngine searchEngine : _searchEngines.values()) {
674 for (long companyId : _companyIds.keySet()) {
675 searchEngine.removeBackup(companyId, backupName);
676 }
677 }
678 }
679
680 public synchronized static void removeCompany(long companyId) {
681 if (!_companyIds.containsKey(companyId)) {
682 return;
683 }
684
685 for (SearchEngine searchEngine : _searchEngines.values()) {
686 searchEngine.removeCompany(companyId);
687 }
688
689 _companyIds.remove(companyId);
690 }
691
692 public static SearchEngine removeSearchEngine(String searchEngineId) {
693 PortalRuntimePermission.checkSearchEngine(searchEngineId);
694
695 return _searchEngines.remove(searchEngineId);
696 }
697
698 public synchronized static void restore(long companyId, String backupName)
699 throws SearchException {
700
701 for (SearchEngine searchEngine : _searchEngines.values()) {
702 searchEngine.restore(companyId, backupName);
703 }
704 }
705
706 public synchronized static void restore(String backupName)
707 throws SearchException {
708
709 for (SearchEngine searchEngine : _searchEngines.values()) {
710 for (long companyId : _companyIds.keySet()) {
711 searchEngine.restore(companyId, backupName);
712 }
713 }
714 }
715
716 public static Hits search(SearchContext searchContext, Query query)
717 throws SearchException {
718
719 if (_log.isDebugEnabled()) {
720 _log.debug("Search query " + getQueryString(searchContext, query));
721 }
722
723 SearchEngine searchEngine = getSearchEngine(
724 searchContext.getSearchEngineId());
725
726 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
727
728 return indexSearcher.search(searchContext, query);
729 }
730
731
735 @Deprecated
736 public static Hits search(
737 String searchEngineId, long companyId, Query query, int start,
738 int end)
739 throws SearchException {
740
741 return search(
742 searchEngineId, companyId, query, SortFactoryUtil.getDefaultSorts(),
743 start, end);
744 }
745
746
750 @Deprecated
751 public static Hits search(
752 String searchEngineId, long companyId, Query query, Sort sort,
753 int start, int end)
754 throws SearchException {
755
756 return search(
757 searchEngineId, companyId, query, new Sort[] {sort}, start, end);
758 }
759
760
764 @Deprecated
765 public static Hits search(
766 String searchEngineId, long companyId, Query query, Sort[] sorts,
767 int start, int end)
768 throws SearchException {
769
770 SearchContext searchContext = new SearchContext();
771
772 searchContext.setCompanyId(companyId);
773 searchContext.setEnd(end);
774 searchContext.setSearchEngineId(searchEngineId);
775 searchContext.setSorts(sorts);
776 searchContext.setStart(start);
777
778 return search(searchContext, query);
779 }
780
781 public static long searchCount(SearchContext searchContext, Query query)
782 throws SearchException {
783
784 if (_log.isDebugEnabled()) {
785 _log.debug("Search query " + getQueryString(searchContext, query));
786 }
787
788 SearchEngine searchEngine = getSearchEngine(
789 searchContext.getSearchEngineId());
790
791 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
792
793 return indexSearcher.searchCount(searchContext, query);
794 }
795
796 public static void setDefaultSearchEngineId(String defaultSearchEngineId) {
797 PortalRuntimePermission.checkSetBeanProperty(
798 SearchEngineUtil.class, "defaultSearchEngineId");
799
800 _defaultSearchEngineId = defaultSearchEngineId;
801 }
802
803 public static void setIndexReadOnly(boolean indexReadOnly) {
804 PortalRuntimePermission.checkSetBeanProperty(
805 SearchEngineUtil.class, "indexReadOnly");
806
807 _indexReadOnly = indexReadOnly;
808 }
809
810 public static void setSearchEngine(
811 String searchEngineId, SearchEngine searchEngine) {
812
813 PortalRuntimePermission.checkSearchEngine(searchEngineId);
814
815 _searchEngines.put(searchEngineId, searchEngine);
816
817 for (Long companyId : _companyIds.keySet()) {
818 searchEngine.initialize(companyId);
819 }
820
821 synchronized (_queuingSearchEngines) {
822 QueuingSearchEngine queuingSearchEngine = _queuingSearchEngines.get(
823 searchEngineId);
824
825 if (queuingSearchEngine != null) {
826 try {
827 queuingSearchEngine.invokeQueued(
828 searchEngine.getIndexWriter());
829 }
830 catch (Exception e) {
831 if (_log.isWarnEnabled()) {
832 _log.warn(
833 "Unable to execute pending write events for " +
834 "engine: " + searchEngineId,
835 e);
836 }
837 }
838 }
839 }
840 }
841
842 public static String spellCheckKeywords(SearchContext searchContext)
843 throws SearchException {
844
845 if (_log.isDebugEnabled()) {
846 _log.debug("Spell checking " + searchContext.getKeywords());
847 }
848
849 SearchEngine searchEngine = getSearchEngine(
850 searchContext.getSearchEngineId());
851
852 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
853
854 return indexSearcher.spellCheckKeywords(searchContext);
855 }
856
857 public static Map<String, List<String>> spellCheckKeywords(
858 SearchContext searchContext, int max)
859 throws SearchException {
860
861 if (_log.isDebugEnabled()) {
862 _log.debug("Spell checking " + searchContext.getKeywords());
863 }
864
865 SearchEngine searchEngine = getSearchEngine(
866 searchContext.getSearchEngineId());
867
868 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
869
870 return indexSearcher.spellCheckKeywords(searchContext, max);
871 }
872
873 public static String[] suggestKeywordQueries(
874 SearchContext searchContext, int max)
875 throws SearchException {
876
877 if (_log.isDebugEnabled()) {
878 _log.debug(
879 "Suggesting keyword queries" + searchContext.getKeywords());
880 }
881
882 SearchEngine searchEngine = getSearchEngine(
883 searchContext.getSearchEngineId());
884
885 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
886
887 return indexSearcher.suggestKeywordQueries(searchContext, max);
888 }
889
890
894 @Deprecated
895 public static void updateDocument(
896 String searchEngineId, long companyId, Document document)
897 throws SearchException {
898
899 updateDocument(searchEngineId, companyId, document, false);
900 }
901
902 public static void updateDocument(
903 String searchEngineId, long companyId, Document document,
904 boolean commitImmediately)
905 throws SearchException {
906
907 if (isIndexReadOnly() || (document == null)) {
908 return;
909 }
910
911 if (_log.isDebugEnabled()) {
912 _log.debug("Document " + document.toString());
913 }
914
915 SearchEngine searchEngine = getSearchEngine(searchEngineId);
916
917 IndexWriter indexWriter = searchEngine.getIndexWriter();
918
919 _searchPermissionChecker.addPermissionFields(companyId, document);
920
921 SearchContext searchContext = new SearchContext();
922
923 searchContext.setCompanyId(companyId);
924 searchContext.setSearchEngineId(searchEngineId);
925
926 setCommitImmediately(
927 searchContext,
928 commitImmediately || ProxyModeThreadLocal.isForceSync());
929
930 indexWriter.updateDocument(searchContext, document);
931 }
932
933
937 @Deprecated
938 public static void updateDocuments(
939 String searchEngineId, long companyId,
940 Collection<Document> documents)
941 throws SearchException {
942
943 updateDocuments(searchEngineId, companyId, documents, false);
944 }
945
946 public static void updateDocuments(
947 String searchEngineId, long companyId,
948 Collection<Document> documents, boolean commitImmediately)
949 throws SearchException {
950
951 if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
952 return;
953 }
954
955 SearchEngine searchEngine = getSearchEngine(searchEngineId);
956
957 IndexWriter indexWriter = searchEngine.getIndexWriter();
958
959 for (Document document : documents) {
960 if (_log.isDebugEnabled()) {
961 _log.debug("Document " + document.toString());
962 }
963
964 _searchPermissionChecker.addPermissionFields(companyId, document);
965 }
966
967 SearchContext searchContext = new SearchContext();
968
969 searchContext.setCompanyId(companyId);
970 searchContext.setSearchEngineId(searchEngineId);
971
972 setCommitImmediately(searchContext, commitImmediately);
973
974 indexWriter.updateDocuments(searchContext, documents);
975 }
976
977 public static void updatePermissionFields(String name, String primKey) {
978 if (isIndexReadOnly()) {
979 return;
980 }
981
982 if (PermissionThreadLocal.isFlushResourcePermissionEnabled(
983 name, primKey)) {
984
985 _searchPermissionChecker.updatePermissionFields(name, primKey);
986 }
987 }
988
989 public void setExcludedEntryClassNames(
990 List<String> excludedEntryClassNames) {
991
992 PortalRuntimePermission.checkSetBeanProperty(
993 getClass(), "excludedEntryClassNames");
994
995 _excludedEntryClassNames.addAll(excludedEntryClassNames);
996 }
997
998 public void setQueueCapacity(int queueCapacity) {
999 _queueCapacity = queueCapacity;
1000 }
1001
1002 protected static void setCommitImmediately(
1003 SearchContext searchContext, boolean commitImmediately) {
1004
1005 if (!commitImmediately) {
1006 searchContext.setCommitImmediately(_INDEX_COMMIT_IMMEDIATELY);
1007 }
1008 else {
1009 searchContext.setCommitImmediately(true);
1010 }
1011 }
1012
1013 private SearchEngineUtil() {
1014 Registry registry = RegistryUtil.getRegistry();
1015
1016 _serviceTracker = registry.trackServices(
1017 SearchEngineConfigurator.class,
1018 new SearchEngineConfiguratorServiceTrackerCustomizer());
1019
1020 _serviceTracker.open();
1021 }
1022
1023 private static final boolean _INDEX_COMMIT_IMMEDIATELY =
1024 GetterUtil.getBoolean(
1025 PropsUtil.get(PropsKeys.INDEX_COMMIT_IMMEDIATELY));
1026
1027 private static final Log _log = LogFactoryUtil.getLog(
1028 SearchEngineUtil.class);
1029
1030 private static final Map<Long, Long> _companyIds =
1031 new ConcurrentHashMap<>();
1032 private static String _defaultSearchEngineId;
1033 private static final Set<String> _excludedEntryClassNames = new HashSet<>();
1034 private static boolean _indexReadOnly = GetterUtil.getBoolean(
1035 PropsUtil.get(PropsKeys.INDEX_READ_ONLY));
1036 private static int _queueCapacity = 200;
1037 private static final Map<String, QueuingSearchEngine>
1038 _queuingSearchEngines = new HashMap<>();
1039 private static final Map<String, SearchEngine> _searchEngines =
1040 new ConcurrentHashMap<>();
1041 private static final SearchPermissionChecker _searchPermissionChecker =
1042 ProxyFactory.newServiceTrackedInstance(SearchPermissionChecker.class);
1043
1044 private final ServiceTracker
1045 <SearchEngineConfigurator, SearchEngineConfigurator> _serviceTracker;
1046
1047 private class SearchEngineConfiguratorServiceTrackerCustomizer
1048 implements ServiceTrackerCustomizer
1049 <SearchEngineConfigurator, SearchEngineConfigurator> {
1050
1051 @Override
1052 public SearchEngineConfigurator addingService(
1053 ServiceReference<SearchEngineConfigurator> serviceReference) {
1054
1055 Registry registry = RegistryUtil.getRegistry();
1056
1057 SearchEngineConfigurator searchEngineConfigurator =
1058 registry.getService(serviceReference);
1059
1060 searchEngineConfigurator.afterPropertiesSet();
1061
1062 return searchEngineConfigurator;
1063 }
1064
1065 @Override
1066 public void modifiedService(
1067 ServiceReference<SearchEngineConfigurator> serviceReference,
1068 SearchEngineConfigurator searchEngineConfigurator) {
1069 }
1070
1071 @Override
1072 public void removedService(
1073 ServiceReference<SearchEngineConfigurator> serviceReference,
1074 SearchEngineConfigurator searchEngineConfigurator) {
1075
1076 Registry registry = RegistryUtil.getRegistry();
1077
1078 registry.ungetService(serviceReference);
1079
1080 searchEngineConfigurator.destroy();
1081 }
1082
1083 }
1084
1085 }