001
014
015 package com.liferay.portal.kernel.search;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.messaging.DestinationNames;
020 import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
021 import com.liferay.portal.kernel.util.GetterUtil;
022 import com.liferay.portal.kernel.util.PropsKeys;
023 import com.liferay.portal.kernel.util.PropsUtil;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.security.permission.PermissionThreadLocal;
026
027 import java.util.Collection;
028 import java.util.HashSet;
029 import java.util.List;
030 import java.util.Map;
031 import java.util.Set;
032 import java.util.concurrent.ConcurrentHashMap;
033
034
039 public class SearchEngineUtil {
040
041
044 public static final int ALL_POS = -1;
045
046 public static final String GENERIC_ENGINE_ID = "GENERIC_ENGINE";
047
048 public static final String SYSTEM_ENGINE_ID = "SYSTEM_ENGINE";
049
050
053 public static void addDocument(long companyId, Document document)
054 throws SearchException {
055
056 addDocument(_getSearchEngineId(document), companyId, document);
057 }
058
059 public static void addDocument(
060 String searchEngineId, long companyId, Document document)
061 throws SearchException {
062
063 if (isIndexReadOnly()) {
064 return;
065 }
066
067 if (_log.isDebugEnabled()) {
068 _log.debug("Add document " + document.toString());
069 }
070
071 SearchEngine searchEngine = getSearchEngine(searchEngineId);
072
073 IndexWriter indexWriter = searchEngine.getIndexWriter();
074
075 _searchPermissionChecker.addPermissionFields(companyId, document);
076
077 SearchContext searchContext = new SearchContext();
078
079 searchContext.setCompanyId(companyId);
080 searchContext.setSearchEngineId(searchEngineId);
081
082 indexWriter.addDocument(searchContext, document);
083 }
084
085
088 public static void addDocuments(
089 long companyId, Collection<Document> documents)
090 throws SearchException {
091
092 addDocuments(_getSearchEngineId(documents), companyId, documents);
093 }
094
095 public static void addDocuments(
096 String searchEngineId, long companyId,
097 Collection<Document> documents)
098 throws SearchException {
099
100 if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
101 return;
102 }
103
104 SearchEngine searchEngine = getSearchEngine(searchEngineId);
105
106 IndexWriter indexWriter = searchEngine.getIndexWriter();
107
108 for (Document document : documents) {
109 if (_log.isDebugEnabled()) {
110 _log.debug("Add document " + document.toString());
111 }
112
113 _searchPermissionChecker.addPermissionFields(companyId, document);
114 }
115
116 SearchContext searchContext = new SearchContext();
117
118 searchContext.setCompanyId(companyId);
119 searchContext.setSearchEngineId(searchEngineId);
120
121 indexWriter.addDocuments(searchContext, documents);
122 }
123
124
127 public static void addSearchEngine(SearchEngine searchEngine) {
128 String searchEngineId = getDefaultSearchEngineId();
129
130 PortalRuntimePermission.checkSearchEngine(searchEngineId);
131
132 _searchEngines.put(searchEngineId, searchEngine);
133 }
134
135
138 public static void deleteDocument(long companyId, String uid)
139 throws SearchException {
140
141 for (String searchEngineId : _searchEngines.keySet()) {
142 deleteDocument(searchEngineId, companyId, uid);
143 }
144 }
145
146 public static void deleteDocument(
147 String searchEngineId, long companyId, String uid)
148 throws SearchException {
149
150 if (isIndexReadOnly()) {
151 return;
152 }
153
154 SearchEngine searchEngine = getSearchEngine(searchEngineId);
155
156 IndexWriter indexWriter = searchEngine.getIndexWriter();
157
158 SearchContext searchContext = new SearchContext();
159
160 searchContext.setCompanyId(companyId);
161 searchContext.setSearchEngineId(searchEngineId);
162
163 indexWriter.deleteDocument(searchContext, uid);
164 }
165
166
169 public static void deleteDocuments(long companyId, Collection<String> uids)
170 throws SearchException {
171
172 for (String searchEngineId : _searchEngines.keySet()) {
173 deleteDocuments(searchEngineId, companyId, uids);
174 }
175 }
176
177 public static void deleteDocuments(
178 String searchEngineId, long companyId, Collection<String> uids)
179 throws SearchException {
180
181 if (isIndexReadOnly() || (uids == null) || uids.isEmpty()) {
182 return;
183 }
184
185 SearchEngine searchEngine = getSearchEngine(searchEngineId);
186
187 IndexWriter indexWriter = searchEngine.getIndexWriter();
188
189 SearchContext searchContext = new SearchContext();
190
191 searchContext.setCompanyId(companyId);
192 searchContext.setSearchEngineId(searchEngineId);
193
194 indexWriter.deleteDocuments(searchContext, uids);
195 }
196
197
200 public static void deletePortletDocuments(long companyId, String portletId)
201 throws SearchException {
202
203 for (String searchEngineId : _searchEngines.keySet()) {
204 deletePortletDocuments(searchEngineId, companyId, portletId);
205 }
206 }
207
208 public static void deletePortletDocuments(
209 String searchEngineId, long companyId, String portletId)
210 throws SearchException {
211
212 if (isIndexReadOnly()) {
213 return;
214 }
215
216 SearchEngine searchEngine = getSearchEngine(searchEngineId);
217
218 if (searchEngine == null) {
219 return;
220 }
221
222 IndexWriter indexWriter = searchEngine.getIndexWriter();
223
224 SearchContext searchContext = new SearchContext();
225
226 searchContext.setCompanyId(companyId);
227 searchContext.setSearchEngineId(searchEngineId);
228
229 indexWriter.deletePortletDocuments(searchContext, portletId);
230 }
231
232 public static String getDefaultSearchEngineId() {
233 if (_defaultSearchEngineId == null) {
234 return SYSTEM_ENGINE_ID;
235 }
236
237 return _defaultSearchEngineId;
238 }
239
240 public static String[] getEntryClassNames() {
241 Set<String> assetEntryClassNames = new HashSet<String>();
242
243 for (Indexer indexer : IndexerRegistryUtil.getIndexers()) {
244 for (String className : indexer.getClassNames()) {
245 if (!_excludedEntryClassNames.contains(className)) {
246 assetEntryClassNames.add(className);
247 }
248 }
249 }
250
251 return assetEntryClassNames.toArray(
252 new String[assetEntryClassNames.size()]);
253 }
254
255
258 public static SearchEngine getSearchEngine() {
259 return getSearchEngine(getDefaultSearchEngineId());
260 }
261
262 public static SearchEngine getSearchEngine(String searchEngineId) {
263 PortalRuntimePermission.checkSearchEngine(searchEngineId);
264
265 SearchEngine searchEngine = _searchEngines.get(searchEngineId);
266
267 if (searchEngine == null) {
268 if (getDefaultSearchEngineId().equals(searchEngineId)) {
269 throw new IllegalStateException(
270 "There is no default search engine configured with ID " +
271 getDefaultSearchEngineId());
272 }
273
274 if (_log.isWarnEnabled()) {
275 _log.warn(
276 "There is no search engine configured with ID " +
277 searchEngineId);
278 }
279 }
280
281 return searchEngine;
282 }
283
284 public static Set<String> getSearchEngineIds() {
285 PortalRuntimePermission.checkGetBeanProperty(
286 SearchEngineUtil.class, "searchEngineIds");
287
288 return _searchEngines.keySet();
289 }
290
291 public static SearchEngine getSearchEngineSilent(String searchEngineId) {
292 PortalRuntimePermission.checkSearchEngine(searchEngineId);
293
294 return _searchEngines.get(searchEngineId);
295 }
296
297 public static SearchPermissionChecker getSearchPermissionChecker() {
298 PortalRuntimePermission.checkGetBeanProperty(
299 SearchEngineUtil.class, "searchPermissionChecker");
300
301 return _searchPermissionChecker;
302 }
303
304 public static String getSearchReaderDestinationName(String searchEngineId) {
305 return DestinationNames.SEARCH_READER.concat(StringPool.SLASH).concat(
306 searchEngineId);
307 }
308
309 public static String getSearchWriterDestinationName(String searchEngineId) {
310 return DestinationNames.SEARCH_WRITER.concat(StringPool.SLASH).concat(
311 searchEngineId);
312 }
313
314 public static boolean isIndexReadOnly() {
315 PortalRuntimePermission.checkGetBeanProperty(
316 SearchEngineUtil.class, "indexReadOnly");
317
318 return _indexReadOnly;
319 }
320
321 public static SearchEngine removeSearchEngine(String searchEngineId) {
322 PortalRuntimePermission.checkSearchEngine(searchEngineId);
323
324 return _searchEngines.remove(searchEngineId);
325 }
326
327
330 public static Hits search(
331 long companyId, long[] groupIds, long userId, String className,
332 Query query, int start, int end)
333 throws SearchException {
334
335 SearchContext searchContext = new SearchContext();
336
337 searchContext.setSearchEngineId(getDefaultSearchEngineId());
338
339 if (userId > 0) {
340 query = _searchPermissionChecker.getPermissionQuery(
341 companyId, groupIds, userId, className, query, searchContext);
342 }
343
344 return search(
345 companyId, query, SortFactoryUtil.getDefaultSorts(), start, end);
346 }
347
348
351 public static Hits search(
352 long companyId, long[] groupIds, long userId, String className,
353 Query query, Sort sort, int start, int end)
354 throws SearchException {
355
356 SearchContext searchContext = new SearchContext();
357
358 searchContext.setSearchEngineId(getDefaultSearchEngineId());
359
360 if (userId > 0) {
361 query = _searchPermissionChecker.getPermissionQuery(
362 companyId, groupIds, userId, className, query, searchContext);
363 }
364
365 return search(companyId, query, sort, start, end);
366 }
367
368
371 public static Hits search(
372 long companyId, long[] groupIds, long userId, String className,
373 Query query, Sort[] sorts, int start, int end)
374 throws SearchException {
375
376 SearchContext searchContext = new SearchContext();
377
378 searchContext.setSearchEngineId(getDefaultSearchEngineId());
379
380 if (userId > 0) {
381 query = _searchPermissionChecker.getPermissionQuery(
382 companyId, groupIds, userId, className, query, searchContext);
383 }
384
385 return search(companyId, query, sorts, start, end);
386 }
387
388
391 public static Hits search(long companyId, Query query, int start, int end)
392 throws SearchException {
393
394 return search(getDefaultSearchEngineId(), companyId, query, start, end);
395 }
396
397
400 public static Hits search(
401 long companyId, Query query, Sort sort, int start, int end)
402 throws SearchException {
403
404 return search(
405 getDefaultSearchEngineId(), companyId, query, sort, start, end);
406 }
407
408
411 public static Hits search(
412 long companyId, Query query, Sort[] sorts, int start, int end)
413 throws SearchException {
414
415 return search(
416 getDefaultSearchEngineId(), companyId, query, sorts, start, end);
417 }
418
419 public static Hits search(SearchContext searchContext, Query query)
420 throws SearchException {
421
422 if (_log.isDebugEnabled()) {
423 _log.debug("Search query " + query.toString());
424 }
425
426 SearchEngine searchEngine = getSearchEngine(
427 searchContext.getSearchEngineId());
428
429 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
430
431 return indexSearcher.search(searchContext, query);
432 }
433
434 public static Hits search(
435 String searchEngineId, long companyId, Query query, int start,
436 int end)
437 throws SearchException {
438
439 if (_log.isDebugEnabled()) {
440 _log.debug("Search query " + query.toString());
441 }
442
443 SearchEngine searchEngine = getSearchEngine(searchEngineId);
444
445 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
446
447 return indexSearcher.search(
448 searchEngineId, companyId, query, SortFactoryUtil.getDefaultSorts(),
449 start, end);
450 }
451
452 public static Hits search(
453 String searchEngineId, long companyId, Query query, Sort sort,
454 int start, int end)
455 throws SearchException {
456
457 if (_log.isDebugEnabled()) {
458 _log.debug("Search query " + query.toString());
459 }
460
461 SearchEngine searchEngine = getSearchEngine(searchEngineId);
462
463 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
464
465 return indexSearcher.search(
466 searchEngineId, companyId, query, new Sort[] {sort}, start, end);
467 }
468
469 public static Hits search(
470 String searchEngineId, long companyId, Query query, Sort[] sorts,
471 int start, int end)
472 throws SearchException {
473
474 if (_log.isDebugEnabled()) {
475 _log.debug("Search query " + query.toString());
476 }
477
478 SearchEngine searchEngine = getSearchEngine(searchEngineId);
479
480 IndexSearcher indexSearcher = searchEngine.getIndexSearcher();
481
482 return indexSearcher.search(
483 searchEngineId, companyId, query, sorts, start, end);
484 }
485
486 public static void setDefaultSearchEngineId(String defaultSearchEngineId) {
487 PortalRuntimePermission.checkSetBeanProperty(
488 SearchEngineUtil.class, "defaultSearchEngineId");
489
490 _defaultSearchEngineId = defaultSearchEngineId;
491 }
492
493 public static void setIndexReadOnly(boolean indexReadOnly) {
494 PortalRuntimePermission.checkSetBeanProperty(
495 SearchEngineUtil.class, "indexReadOnly");
496
497 _indexReadOnly = indexReadOnly;
498 }
499
500 public static void setSearchEngine(
501 String searchEngineId, SearchEngine searchEngine) {
502
503 PortalRuntimePermission.checkSearchEngine(searchEngineId);
504
505 _searchEngines.put(searchEngineId, searchEngine);
506 }
507
508
511 public static void updateDocument(long companyId, Document document)
512 throws SearchException {
513
514 updateDocument(_getSearchEngineId(document), companyId, document);
515 }
516
517 public static void updateDocument(
518 String searchEngineId, long companyId, Document document)
519 throws SearchException {
520
521 if (isIndexReadOnly()) {
522 return;
523 }
524
525 if (_log.isDebugEnabled()) {
526 _log.debug("Document " + document.toString());
527 }
528
529 SearchEngine searchEngine = getSearchEngine(searchEngineId);
530
531 IndexWriter indexWriter = searchEngine.getIndexWriter();
532
533 _searchPermissionChecker.addPermissionFields(companyId, document);
534
535 SearchContext searchContext = new SearchContext();
536
537 searchContext.setCompanyId(companyId);
538 searchContext.setSearchEngineId(searchEngineId);
539
540 indexWriter.updateDocument(searchContext, document);
541 }
542
543
546 public static void updateDocuments(
547 long companyId, Collection<Document> documents)
548 throws SearchException {
549
550 updateDocuments(_getSearchEngineId(documents), companyId, documents);
551 }
552
553 public static void updateDocuments(
554 String searchEngineId, long companyId,
555 Collection<Document> documents)
556 throws SearchException {
557
558 if (isIndexReadOnly() || (documents == null) || documents.isEmpty()) {
559 return;
560 }
561
562 SearchEngine searchEngine = getSearchEngine(searchEngineId);
563
564 IndexWriter indexWriter = searchEngine.getIndexWriter();
565
566 for (Document document : documents) {
567 if (_log.isDebugEnabled()) {
568 _log.debug("Document " + document.toString());
569 }
570
571 _searchPermissionChecker.addPermissionFields(companyId, document);
572 }
573
574 SearchContext searchContext = new SearchContext();
575
576 searchContext.setCompanyId(companyId);
577 searchContext.setSearchEngineId(searchEngineId);
578
579 indexWriter.updateDocuments(searchContext, documents);
580 }
581
582 public static void updatePermissionFields(long resourceId) {
583 if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
584 return;
585 }
586
587 _searchPermissionChecker.updatePermissionFields(resourceId);
588 }
589
590 public static void updatePermissionFields(String name, String primKey) {
591 if (isIndexReadOnly() || !PermissionThreadLocal.isFlushEnabled()) {
592 return;
593 }
594
595 _searchPermissionChecker.updatePermissionFields(name, primKey);
596 }
597
598 public void setExcludedEntryClassNames(
599 List<String> excludedEntryClassNames) {
600
601 PortalRuntimePermission.checkSetBeanProperty(
602 getClass(), "excludedEntryClassNames");
603
604 _excludedEntryClassNames.addAll(excludedEntryClassNames);
605 }
606
607
610 public void setSearchEngine(SearchEngine searchEngine) {
611 String searchEngineId = getDefaultSearchEngineId();
612
613 PortalRuntimePermission.checkSearchEngine(searchEngineId);
614
615 _searchEngines.put(searchEngineId, searchEngine);
616 }
617
618 public void setSearchPermissionChecker(
619 SearchPermissionChecker searchPermissionChecker) {
620
621 PortalRuntimePermission.checkSetBeanProperty(
622 getClass(), "searchPermissionChecker");
623
624 _searchPermissionChecker = searchPermissionChecker;
625 }
626
627 private static String _getSearchEngineId(Collection<Document> documents) {
628 if (!documents.isEmpty()) {
629 Document document = documents.iterator().next();
630
631 return _getSearchEngineId(document);
632 }
633
634 return getDefaultSearchEngineId();
635 }
636
637 private static String _getSearchEngineId(Document document) {
638 String entryClassName = document.get("entryClassName");
639
640 Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
641
642 String searchEngineId = indexer.getSearchEngineId();
643
644 if (_log.isDebugEnabled()) {
645 _log.debug(
646 "Search engine ID for " + indexer.getClass() + " is " +
647 searchEngineId);
648 }
649
650 return searchEngineId;
651 }
652
653 private static Log _log = LogFactoryUtil.getLog(SearchEngineUtil.class);
654
655 private static String _defaultSearchEngineId;
656 private static Set<String> _excludedEntryClassNames = new HashSet<String>();
657 private static boolean _indexReadOnly = GetterUtil.getBoolean(
658 PropsUtil.get(PropsKeys.INDEX_READ_ONLY));
659 private static Map<String, SearchEngine> _searchEngines =
660 new ConcurrentHashMap<String, SearchEngine>();
661 private static SearchPermissionChecker _searchPermissionChecker;
662
663 }