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