001    /**
002     * Copyright (c) 2000-2013 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.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    /**
036     * @author Bruno Farache
037     * @author Raymond Aug??
038     * @author Michael C. Han
039     */
040    public class SearchEngineUtil {
041    
042            /**
043             * @deprecated As of 6.2.0, replaced by {@link
044             *             com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS}
045             */
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            /**
053             * @deprecated As of 6.2.0, replaced by {@link #addDocument(String, long,
054             *             Document)}
055             */
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            /**
089             * @deprecated As of 6.2.0, replaced by {@link #addDocuments(String, long,
090             *             Collection)}
091             */
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            /**
129             * @deprecated As of 6.2.0, replaced by {@link #setSearchEngine(String,
130             *             SearchEngine)}
131             */
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            /**
141             * @deprecated As of 6.2.0, replaced by {@link #deleteDocument(String, long,
142             *             String)}
143             */
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            /**
173             * @deprecated As of 6.2.0, replaced by {@link #deleteDocuments(String,
174             *             long, Collection)}
175             */
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            /**
205             * @deprecated As of 6.2.0, replaced by {@link
206             *             #deletePortletDocuments(String, long, String)}
207             */
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            /**
264             * @deprecated As of 6.2.0, replaced by {@link #getSearchEngine(String)}
265             */
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 indexQuerySuggestionDictionaries(long companyId)
323                    throws SearchException {
324    
325                    Set<String> searchEngineIds = getSearchEngineIds();
326    
327                    for (String searchEngineId : searchEngineIds) {
328                            indexQuerySuggestionDictionaries(searchEngineId, companyId);
329                    }
330            }
331    
332            public static void indexQuerySuggestionDictionaries(
333                            String searchEngineId, long companyId)
334                    throws SearchException {
335    
336                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
337    
338                    IndexWriter indexWriter = searchEngine.getIndexWriter();
339    
340                    SearchContext searchContext = new SearchContext();
341    
342                    searchContext.setCompanyId(companyId);
343                    searchContext.setSearchEngineId(searchEngineId);
344    
345                    indexWriter.indexQuerySuggestionDictionaries(searchContext);
346            }
347    
348            public static void indexQuerySuggestionDictionary(
349                            long companyId, Locale locale)
350                    throws SearchException {
351    
352                    Set<String> searchEngineIds = getSearchEngineIds();
353    
354                    for (String searchEngineId : searchEngineIds) {
355                            indexQuerySuggestionDictionary(searchEngineId, companyId, locale);
356                    }
357            }
358    
359            public static void indexQuerySuggestionDictionary(
360                            String searchEngineId, long companyId, Locale locale)
361                    throws SearchException {
362    
363                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
364    
365                    IndexWriter indexWriter = searchEngine.getIndexWriter();
366    
367                    SearchContext searchContext = new SearchContext();
368    
369                    searchContext.setCompanyId(companyId);
370                    searchContext.setSearchEngineId(searchEngineId);
371                    searchContext.setLocale(locale);
372    
373                    indexWriter.indexQuerySuggestionDictionary(searchContext);
374            }
375    
376            public static void indexSpellCheckerDictionaries(long companyId)
377                    throws SearchException {
378    
379                    Set<String> searchEngineIds = getSearchEngineIds();
380    
381                    for (String searchEngineId : searchEngineIds) {
382                            indexSpellCheckerDictionaries(searchEngineId, companyId);
383                    }
384            }
385    
386            public static void indexSpellCheckerDictionaries(
387                            String searchEngineId, long companyId)
388                    throws SearchException {
389    
390                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
391    
392                    IndexWriter indexWriter = searchEngine.getIndexWriter();
393    
394                    SearchContext searchContext = new SearchContext();
395    
396                    searchContext.setCompanyId(companyId);
397                    searchContext.setSearchEngineId(searchEngineId);
398    
399                    indexWriter.indexSpellCheckerDictionaries(searchContext);
400            }
401    
402            public static void indexSpellCheckerDictionary(
403                            long companyId, Locale locale)
404                    throws SearchException {
405    
406                    Set<String> searchEngineIds = getSearchEngineIds();
407    
408                    for (String searchEngineId : searchEngineIds) {
409                            indexSpellCheckerDictionary(searchEngineId, companyId, locale);
410                    }
411            }
412    
413            public static void indexSpellCheckerDictionary(
414                            String searchEngineId, long companyId, Locale locale)
415                    throws SearchException {
416    
417                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
418    
419                    IndexWriter indexWriter = searchEngine.getIndexWriter();
420    
421                    SearchContext searchContext = new SearchContext();
422    
423                    searchContext.setCompanyId(companyId);
424                    searchContext.setSearchEngineId(searchEngineId);
425                    searchContext.setLocale(locale);
426    
427                    indexWriter.indexSpellCheckerDictionary(searchContext);
428            }
429    
430            public static boolean isIndexReadOnly() {
431                    PortalRuntimePermission.checkGetBeanProperty(
432                            SearchEngineUtil.class, "indexReadOnly");
433    
434                    return _indexReadOnly;
435            }
436    
437            public static SearchEngine removeSearchEngine(String searchEngineId) {
438                    PortalRuntimePermission.checkSearchEngine(searchEngineId);
439    
440                    return _searchEngines.remove(searchEngineId);
441            }
442    
443            /**
444             * @deprecated As of 6.2.0
445             */
446            public static Hits search(
447                            long companyId, long[] groupIds, long userId, String className,
448                            Query query, int start, int end)
449                    throws SearchException {
450    
451                    SearchContext searchContext = new SearchContext();
452    
453                    searchContext.setSearchEngineId(getDefaultSearchEngineId());
454    
455                    if (userId > 0) {
456                            query = _searchPermissionChecker.getPermissionQuery(
457                                    companyId, groupIds, userId, className, query, searchContext);
458                    }
459    
460                    return search(
461                            companyId, query, SortFactoryUtil.getDefaultSorts(), start, end);
462            }
463    
464            /**
465             * @deprecated As of 6.2.0
466             */
467            public static Hits search(
468                            long companyId, long[] groupIds, long userId, String className,
469                            Query query, Sort sort, int start, int end)
470                    throws SearchException {
471    
472                    SearchContext searchContext = new SearchContext();
473    
474                    searchContext.setSearchEngineId(getDefaultSearchEngineId());
475    
476                    if (userId > 0) {
477                            query = _searchPermissionChecker.getPermissionQuery(
478                                    companyId, groupIds, userId, className, query, searchContext);
479                    }
480    
481                    return search(companyId, query, sort, start, end);
482            }
483    
484            /**
485             * @deprecated As of 6.2.0
486             */
487            public static Hits search(
488                            long companyId, long[] groupIds, long userId, String className,
489                            Query query, Sort[] sorts, int start, int end)
490                    throws SearchException {
491    
492                    SearchContext searchContext = new SearchContext();
493    
494                    searchContext.setSearchEngineId(getDefaultSearchEngineId());
495    
496                    if (userId > 0) {
497                            query = _searchPermissionChecker.getPermissionQuery(
498                                    companyId, groupIds, userId, className, query, searchContext);
499                    }
500    
501                    return search(companyId, query, sorts, start, end);
502            }
503    
504            /**
505             * @deprecated As of 6.2.0, replaced by {@link #search(String, long, Query,
506             *             int, int)}
507             */
508            public static Hits search(long companyId, Query query, int start, int end)
509                    throws SearchException {
510    
511                    return search(getDefaultSearchEngineId(), companyId, query, start, end);
512            }
513    
514            /**
515             * @deprecated As of 6.2.0, replaced by {@link #search(String, long, Query,
516             *             Sort, int, int)}
517             */
518            public static Hits search(
519                            long companyId, Query query, Sort sort, int start, int end)
520                    throws SearchException {
521    
522                    return search(
523                            getDefaultSearchEngineId(), companyId, query, sort, start, end);
524            }
525    
526            /**
527             * @deprecated As of 6.2.0, replaced by {@link #search(String, long, Query,
528             *             Sort[], int, int)}
529             */
530            public static Hits search(
531                            long companyId, Query query, Sort[] sorts, int start, int end)
532                    throws SearchException {
533    
534                    return search(
535                            getDefaultSearchEngineId(), companyId, query, sorts, start, end);
536            }
537    
538            public static Hits search(SearchContext searchContext, Query query)
539                    throws SearchException {
540    
541                    if (_log.isDebugEnabled()) {
542                            _log.debug("Search query " + query.toString());
543                    }
544    
545                    SearchEngine searchEngine = getSearchEngine(
546                            searchContext.getSearchEngineId());
547    
548                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
549    
550                    return indexSearcher.search(searchContext, query);
551            }
552    
553            public static Hits search(
554                            String searchEngineId, long companyId, Query query, int start,
555                            int end)
556                    throws SearchException {
557    
558                    if (_log.isDebugEnabled()) {
559                            _log.debug("Search query " + query.toString());
560                    }
561    
562                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
563    
564                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
565    
566                    return indexSearcher.search(
567                            searchEngineId, companyId, query, SortFactoryUtil.getDefaultSorts(),
568                            start, end);
569            }
570    
571            public static Hits search(
572                            String searchEngineId, long companyId, Query query, Sort sort,
573                            int start, int end)
574                    throws SearchException {
575    
576                    if (_log.isDebugEnabled()) {
577                            _log.debug("Search query " + query.toString());
578                    }
579    
580                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
581    
582                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
583    
584                    return indexSearcher.search(
585                            searchEngineId, companyId, query, new Sort[] {sort}, start, end);
586            }
587    
588            public static Hits search(
589                            String searchEngineId, long companyId, Query query, Sort[] sorts,
590                            int start, int end)
591                    throws SearchException {
592    
593                    if (_log.isDebugEnabled()) {
594                            _log.debug("Search query " + query.toString());
595                    }
596    
597                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
598    
599                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
600    
601                    return indexSearcher.search(
602                            searchEngineId, companyId, query, sorts, start, end);
603            }
604    
605            public static void setDefaultSearchEngineId(String defaultSearchEngineId) {
606                    PortalRuntimePermission.checkSetBeanProperty(
607                            SearchEngineUtil.class, "defaultSearchEngineId");
608    
609                    _defaultSearchEngineId = defaultSearchEngineId;
610            }
611    
612            public static void setIndexReadOnly(boolean indexReadOnly) {
613                    PortalRuntimePermission.checkSetBeanProperty(
614                            SearchEngineUtil.class, "indexReadOnly");
615    
616                    _indexReadOnly = indexReadOnly;
617            }
618    
619            public static void setSearchEngine(
620                    String searchEngineId, SearchEngine searchEngine) {
621    
622                    PortalRuntimePermission.checkSearchEngine(searchEngineId);
623    
624                    _searchEngines.put(searchEngineId, searchEngine);
625            }
626    
627            public static String spellCheckKeywords(SearchContext searchContext)
628                    throws SearchException {
629    
630                    if (_log.isDebugEnabled()) {
631                            _log.debug("Spell checking " + searchContext.getKeywords());
632                    }
633    
634                    SearchEngine searchEngine = getSearchEngine(
635                            searchContext.getSearchEngineId());
636    
637                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
638    
639                    return indexSearcher.spellCheckKeywords(searchContext);
640            }
641    
642            public static Map<String, List<String>> spellCheckKeywords(
643                            SearchContext searchContext, int max)
644                    throws SearchException {
645    
646                    if (_log.isDebugEnabled()) {
647                            _log.debug("Spell checking " + searchContext.getKeywords());
648                    }
649    
650                    SearchEngine searchEngine = getSearchEngine(
651                            searchContext.getSearchEngineId());
652    
653                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
654    
655                    return indexSearcher.spellCheckKeywords(searchContext, max);
656            }
657    
658            public static String[] suggestKeywordQueries(
659                            SearchContext searchContext, int max)
660                    throws SearchException {
661    
662                    if (_log.isDebugEnabled()) {
663                            _log.debug(
664                                    "Suggesting keyword queries" + searchContext.getKeywords());
665                    }
666    
667                    SearchEngine searchEngine = getSearchEngine(
668                            searchContext.getSearchEngineId());
669    
670                    IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
671    
672                    return indexSearcher.suggestKeywordQueries(searchContext, max);
673            }
674    
675            /**
676             * @deprecated As of 6.2.0, replaced by {@link #updateDocument(String, long,
677             *             Document)}
678             */
679            public static void updateDocument(long companyId, Document document)
680                    throws SearchException {
681    
682                    updateDocument(_getSearchEngineId(document), companyId, document);
683            }
684    
685            public static void updateDocument(
686                            String searchEngineId, long companyId, Document document)
687                    throws SearchException {
688    
689                    if (isIndexReadOnly()) {
690                            return;
691                    }
692    
693                    if (_log.isDebugEnabled()) {
694                            _log.debug("Document " + document.toString());
695                    }
696    
697                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
698    
699                    IndexWriter indexWriter = searchEngine.getIndexWriter();
700    
701                    _searchPermissionChecker.addPermissionFields(companyId, document);
702    
703                    SearchContext searchContext = new SearchContext();
704    
705                    searchContext.setCompanyId(companyId);
706                    searchContext.setSearchEngineId(searchEngineId);
707    
708                    indexWriter.updateDocument(searchContext, document);
709            }
710    
711            /**
712             * @deprecated As of 6.2.0, replaced by {@link #updateDocuments(String,
713             *             long, Collection)}
714             */
715            public static void updateDocuments(
716                            long companyId, Collection<Document> documents)
717                    throws SearchException {
718    
719                    updateDocuments(_getSearchEngineId(documents), companyId, documents);
720            }
721    
722            public static void updateDocuments(
723                            String searchEngineId, long companyId,
724                            Collection<Document> documents)
725                    throws SearchException {
726    
727                    if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
728                            return;
729                    }
730    
731                    SearchEngine searchEngine = getSearchEngine(searchEngineId);
732    
733                    IndexWriter indexWriter = searchEngine.getIndexWriter();
734    
735                    for (Document document : documents) {
736                            if (_log.isDebugEnabled()) {
737                                    _log.debug("Document " + document.toString());
738                            }
739    
740                            _searchPermissionChecker.addPermissionFields(companyId, document);
741                    }
742    
743                    SearchContext searchContext = new SearchContext();
744    
745                    searchContext.setCompanyId(companyId);
746                    searchContext.setSearchEngineId(searchEngineId);
747    
748                    indexWriter.updateDocuments(searchContext, documents);
749            }
750    
751            public static void updatePermissionFields(String name, String primKey) {
752                    if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
753                            return;
754                    }
755    
756                    _searchPermissionChecker.updatePermissionFields(name, primKey);
757            }
758    
759            public void setExcludedEntryClassNames(
760                    List<String> excludedEntryClassNames) {
761    
762                    PortalRuntimePermission.checkSetBeanProperty(
763                            getClass(), "excludedEntryClassNames");
764    
765                    _excludedEntryClassNames.addAll(excludedEntryClassNames);
766            }
767    
768            /**
769             * @deprecated As of 6.2.0, replaced by {@link #setSearchEngine(String,
770             *             SearchEngine)}
771             */
772            public void setSearchEngine(SearchEngine searchEngine) {
773                    String searchEngineId = getDefaultSearchEngineId();
774    
775                    PortalRuntimePermission.checkSearchEngine(searchEngineId);
776    
777                    _searchEngines.put(searchEngineId, searchEngine);
778            }
779    
780            public void setSearchPermissionChecker(
781                    SearchPermissionChecker searchPermissionChecker) {
782    
783                    PortalRuntimePermission.checkSetBeanProperty(
784                            getClass(), "searchPermissionChecker");
785    
786                    _searchPermissionChecker = searchPermissionChecker;
787            }
788    
789            private static String _getSearchEngineId(Collection<Document> documents) {
790                    if (!documents.isEmpty()) {
791                            Document document = documents.iterator().next();
792    
793                            return _getSearchEngineId(document);
794                    }
795    
796                    return getDefaultSearchEngineId();
797            }
798    
799            private static String _getSearchEngineId(Document document) {
800                    String entryClassName = document.get("entryClassName");
801    
802                    Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
803    
804                    String searchEngineId = indexer.getSearchEngineId();
805    
806                    if (_log.isDebugEnabled()) {
807                            _log.debug(
808                                    "Search engine ID for " + indexer.getClass() + " is " +
809                                            searchEngineId);
810                    }
811    
812                    return searchEngineId;
813            }
814    
815            private static Log _log = LogFactoryUtil.getLog(SearchEngineUtil.class);
816    
817            private static String _defaultSearchEngineId;
818            private static Set<String> _excludedEntryClassNames = new HashSet<String>();
819            private static boolean _indexReadOnly = GetterUtil.getBoolean(
820                    PropsUtil.get(PropsKeys.INDEX_READ_ONLY));
821            private static Map<String, SearchEngine> _searchEngines =
822                    new ConcurrentHashMap<String, SearchEngine>();
823            private static SearchPermissionChecker _searchPermissionChecker;
824    
825    }