001
014
015 package com.liferay.portlet.documentlibrary.util;
016
017 import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
018 import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019 import com.liferay.portal.kernel.dao.orm.Property;
020 import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
021 import com.liferay.portal.kernel.exception.PortalException;
022 import com.liferay.portal.kernel.exception.SystemException;
023 import com.liferay.portal.kernel.log.Log;
024 import com.liferay.portal.kernel.log.LogFactoryUtil;
025 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
026 import com.liferay.portal.kernel.portlet.LiferayWindowState;
027 import com.liferay.portal.kernel.search.BaseIndexer;
028 import com.liferay.portal.kernel.search.BooleanClauseOccur;
029 import com.liferay.portal.kernel.search.BooleanQuery;
030 import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
031 import com.liferay.portal.kernel.search.Document;
032 import com.liferay.portal.kernel.search.DocumentImpl;
033 import com.liferay.portal.kernel.search.Field;
034 import com.liferay.portal.kernel.search.Indexer;
035 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
036 import com.liferay.portal.kernel.search.SearchContext;
037 import com.liferay.portal.kernel.search.SearchEngineUtil;
038 import com.liferay.portal.kernel.search.SearchException;
039 import com.liferay.portal.kernel.search.Summary;
040 import com.liferay.portal.kernel.util.ArrayUtil;
041 import com.liferay.portal.kernel.util.CharPool;
042 import com.liferay.portal.kernel.util.GetterUtil;
043 import com.liferay.portal.kernel.util.LocaleUtil;
044 import com.liferay.portal.kernel.util.PropsKeys;
045 import com.liferay.portal.kernel.util.StringBundler;
046 import com.liferay.portal.kernel.util.StringPool;
047 import com.liferay.portal.kernel.util.StringUtil;
048 import com.liferay.portal.kernel.util.Validator;
049 import com.liferay.portal.model.Group;
050 import com.liferay.portal.model.Repository;
051 import com.liferay.portal.security.permission.ActionKeys;
052 import com.liferay.portal.security.permission.PermissionChecker;
053 import com.liferay.portal.service.GroupLocalServiceUtil;
054 import com.liferay.portal.service.RepositoryLocalServiceUtil;
055 import com.liferay.portal.service.persistence.GroupActionableDynamicQuery;
056 import com.liferay.portal.util.PortalUtil;
057 import com.liferay.portal.util.PortletKeys;
058 import com.liferay.portal.util.PrefsPropsUtil;
059 import com.liferay.portal.util.PropsValues;
060 import com.liferay.portlet.documentlibrary.model.DLFileEntry;
061 import com.liferay.portlet.documentlibrary.model.DLFileEntryMetadata;
062 import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
063 import com.liferay.portlet.documentlibrary.model.DLFileEntryTypeConstants;
064 import com.liferay.portlet.documentlibrary.model.DLFileVersion;
065 import com.liferay.portlet.documentlibrary.model.DLFolder;
066 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
067 import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
068 import com.liferay.portlet.documentlibrary.service.DLFileEntryMetadataLocalServiceUtil;
069 import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
070 import com.liferay.portlet.documentlibrary.service.permission.DLFileEntryPermission;
071 import com.liferay.portlet.documentlibrary.service.persistence.DLFileEntryActionableDynamicQuery;
072 import com.liferay.portlet.documentlibrary.service.persistence.DLFolderActionableDynamicQuery;
073 import com.liferay.portlet.dynamicdatamapping.StructureFieldException;
074 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
075 import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
076 import com.liferay.portlet.dynamicdatamapping.storage.Fields;
077 import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
078 import com.liferay.portlet.dynamicdatamapping.util.DDMIndexerUtil;
079 import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
080 import com.liferay.portlet.expando.model.ExpandoBridge;
081 import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
082 import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
083 import com.liferay.portlet.messageboards.model.MBMessage;
084
085 import java.io.IOException;
086 import java.io.InputStream;
087 import java.io.Serializable;
088
089 import java.util.LinkedHashMap;
090 import java.util.List;
091 import java.util.Locale;
092
093 import javax.portlet.PortletRequest;
094 import javax.portlet.PortletURL;
095 import javax.portlet.WindowStateException;
096
097
102 public class DLFileEntryIndexer extends BaseIndexer {
103
104 public static final String[] CLASS_NAMES = {DLFileEntry.class.getName()};
105
106 public static final String PORTLET_ID = PortletKeys.DOCUMENT_LIBRARY;
107
108 public DLFileEntryIndexer() {
109 setFilterSearch(true);
110 setPermissionAware(true);
111 }
112
113 @Override
114 public void addRelatedEntryFields(Document document, Object obj)
115 throws Exception {
116
117 MBMessage message = (MBMessage)obj;
118
119 DLFileEntry dlFileEntry = DLFileEntryLocalServiceUtil.getDLFileEntry(
120 message.getClassPK());
121
122 document.addKeyword(Field.FOLDER_ID, dlFileEntry.getFolderId());
123 document.addKeyword(Field.HIDDEN, dlFileEntry.isInHiddenFolder());
124 document.addKeyword(Field.RELATED_ENTRY, true);
125 }
126
127 @Override
128 public String[] getClassNames() {
129 return CLASS_NAMES;
130 }
131
132 @Override
133 public String getPortletId() {
134 return PORTLET_ID;
135 }
136
137 @Override
138 public boolean hasPermission(
139 PermissionChecker permissionChecker, String entryClassName,
140 long entryClassPK, String actionId)
141 throws Exception {
142
143 return DLFileEntryPermission.contains(
144 permissionChecker, entryClassPK, ActionKeys.VIEW);
145 }
146
147 @Override
148 public void postProcessContextQuery(
149 BooleanQuery contextQuery, SearchContext searchContext)
150 throws Exception {
151
152 addStatus(contextQuery, searchContext);
153
154 if (searchContext.isIncludeAttachments()) {
155 addRelatedClassNames(contextQuery, searchContext);
156 }
157
158 contextQuery.addRequiredTerm(
159 Field.HIDDEN, searchContext.isIncludeAttachments());
160
161 addSearchClassTypeIds(contextQuery, searchContext);
162
163 String ddmStructureFieldName = (String)searchContext.getAttribute(
164 "ddmStructureFieldName");
165 Serializable ddmStructureFieldValue = searchContext.getAttribute(
166 "ddmStructureFieldValue");
167
168 if (Validator.isNotNull(ddmStructureFieldName) &&
169 Validator.isNotNull(ddmStructureFieldValue)) {
170
171 String[] ddmStructureFieldNameParts = StringUtil.split(
172 ddmStructureFieldName, StringPool.SLASH);
173
174 DDMStructure structure = DDMStructureLocalServiceUtil.getStructure(
175 GetterUtil.getLong(ddmStructureFieldNameParts[1]));
176
177 String fieldName = StringUtil.replaceLast(
178 ddmStructureFieldNameParts[2],
179 StringPool.UNDERLINE.concat(
180 LocaleUtil.toLanguageId(searchContext.getLocale())),
181 StringPool.BLANK);
182
183 try {
184 ddmStructureFieldValue = DDMUtil.getIndexedFieldValue(
185 ddmStructureFieldValue, structure.getFieldType(fieldName));
186 }
187 catch (StructureFieldException sfe) {
188 }
189
190 contextQuery.addRequiredTerm(
191 ddmStructureFieldName,
192 StringPool.QUOTE + ddmStructureFieldValue + StringPool.QUOTE);
193 }
194
195 String[] mimeTypes = (String[])searchContext.getAttribute("mimeTypes");
196
197 if (ArrayUtil.isNotEmpty(mimeTypes)) {
198 BooleanQuery mimeTypesQuery = BooleanQueryFactoryUtil.create(
199 searchContext);
200
201 for (String mimeType : mimeTypes) {
202 mimeTypesQuery.addTerm(
203 "mimeType",
204 StringUtil.replace(
205 mimeType, CharPool.FORWARD_SLASH, CharPool.UNDERLINE));
206 }
207
208 contextQuery.add(mimeTypesQuery, BooleanClauseOccur.MUST);
209 }
210 }
211
212 @Override
213 public void postProcessSearchQuery(
214 BooleanQuery searchQuery, SearchContext searchContext)
215 throws Exception {
216
217 Group group = GroupLocalServiceUtil.getCompanyGroup(
218 searchContext.getCompanyId());
219
220 DDMStructure tikaRawMetadataStructure =
221 DDMStructureLocalServiceUtil.fetchStructure(
222 group.getGroupId(),
223 PortalUtil.getClassNameId(RawMetadataProcessor.class),
224 "TikaRawMetadata");
225
226 if (tikaRawMetadataStructure != null) {
227 addSearchDDMStruture(
228 searchQuery, searchContext, tikaRawMetadataStructure);
229 }
230
231 String keywords = searchContext.getKeywords();
232
233 if (Validator.isNull(keywords)) {
234 addSearchTerm(searchQuery, searchContext, Field.DESCRIPTION, false);
235 addSearchTerm(searchQuery, searchContext, Field.TITLE, false);
236 addSearchTerm(searchQuery, searchContext, Field.USER_NAME, false);
237 }
238
239 addSearchTerm(searchQuery, searchContext, "ddmContent", false);
240 addSearchTerm(searchQuery, searchContext, "extension", false);
241 addSearchTerm(searchQuery, searchContext, "fileEntryTypeId", false);
242 addSearchTerm(searchQuery, searchContext, "path", false);
243
244 LinkedHashMap<String, Object> params =
245 (LinkedHashMap<String, Object>)searchContext.getAttribute("params");
246
247 if (params != null) {
248 String expandoAttributes = (String)params.get("expandoAttributes");
249
250 if (Validator.isNotNull(expandoAttributes)) {
251 addSearchExpando(searchQuery, searchContext, expandoAttributes);
252 }
253 }
254 }
255
256 protected void addFileEntryTypeAttributes(
257 Document document, DLFileVersion dlFileVersion)
258 throws PortalException, SystemException {
259
260 DLFileEntryType dlFileEntryType =
261 DLFileEntryTypeLocalServiceUtil.getDLFileEntryType(
262 dlFileVersion.getFileEntryTypeId());
263
264 List<DDMStructure> ddmStructures = dlFileEntryType.getDDMStructures();
265
266 for (DDMStructure ddmStructure : ddmStructures) {
267 Fields fields = null;
268
269 try {
270 DLFileEntryMetadata fileEntryMetadata =
271 DLFileEntryMetadataLocalServiceUtil.getFileEntryMetadata(
272 ddmStructure.getStructureId(),
273 dlFileVersion.getFileVersionId());
274
275 fields = StorageEngineUtil.getFields(
276 fileEntryMetadata.getDDMStorageId());
277 }
278 catch (Exception e) {
279 }
280
281 if (fields != null) {
282 DDMIndexerUtil.addAttributes(document, ddmStructure, fields);
283 }
284 }
285 }
286
287 @Override
288 protected void doDelete(Object obj) throws Exception {
289 DLFileEntry dlFileEntry = (DLFileEntry)obj;
290
291 Document document = new DocumentImpl();
292
293 document.addUID(PORTLET_ID, dlFileEntry.getFileEntryId());
294
295 SearchEngineUtil.deleteDocument(
296 getSearchEngineId(), dlFileEntry.getCompanyId(),
297 document.get(Field.UID));
298 }
299
300 @Override
301 protected Document doGetDocument(Object obj) throws Exception {
302 DLFileEntry dlFileEntry = (DLFileEntry)obj;
303
304 if (_log.isDebugEnabled()) {
305 _log.debug("Indexing document " + dlFileEntry);
306 }
307
308 boolean indexContent = true;
309
310 InputStream is = null;
311
312 try {
313 if (PropsValues.DL_FILE_INDEXING_MAX_SIZE == 0) {
314 indexContent = false;
315 }
316 else if (PropsValues.DL_FILE_INDEXING_MAX_SIZE != -1) {
317 if (dlFileEntry.getSize() >
318 PropsValues.DL_FILE_INDEXING_MAX_SIZE) {
319
320 indexContent = false;
321 }
322 }
323
324 if (indexContent) {
325 String[] ignoreExtensions = PrefsPropsUtil.getStringArray(
326 PropsKeys.DL_FILE_INDEXING_IGNORE_EXTENSIONS,
327 StringPool.COMMA);
328
329 if (ArrayUtil.contains(
330 ignoreExtensions,
331 StringPool.PERIOD + dlFileEntry.getExtension())) {
332
333 indexContent = false;
334 }
335 }
336
337 if (indexContent) {
338 is = dlFileEntry.getFileVersion().getContentStream(false);
339 }
340 }
341 catch (Exception e) {
342 }
343
344 DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
345
346 try {
347 Document document = getBaseModelDocument(
348 PORTLET_ID, dlFileEntry, dlFileVersion);
349
350 if (indexContent) {
351 if (is != null) {
352 try {
353 document.addFile(
354 Field.CONTENT, is, dlFileEntry.getTitle());
355 }
356 catch (IOException ioe) {
357 throw new SearchException(
358 "Cannot extract text from file" + dlFileEntry);
359 }
360 }
361 else if (_log.isDebugEnabled()) {
362 _log.debug(
363 "Document " + dlFileEntry +
364 " does not have any content");
365 }
366 }
367
368 document.addKeyword(
369 Field.CLASS_TYPE_ID, dlFileEntry.getFileEntryTypeId());
370 document.addText(Field.DESCRIPTION, dlFileEntry.getDescription());
371 document.addKeyword(Field.FOLDER_ID, dlFileEntry.getFolderId());
372 document.addKeyword(Field.HIDDEN, dlFileEntry.isInHiddenFolder());
373 document.addText(
374 Field.PROPERTIES, dlFileEntry.getLuceneProperties());
375 document.addText(Field.TITLE, dlFileEntry.getTitle());
376 document.addKeyword(
377 Field.TREE_PATH,
378 StringUtil.split(dlFileEntry.getTreePath(), CharPool.SLASH));
379
380 document.addKeyword(
381 "dataRepositoryId", dlFileEntry.getDataRepositoryId());
382 document.addText(
383 "ddmContent",
384 extractContent(dlFileVersion, LocaleUtil.getSiteDefault()));
385 document.addKeyword("extension", dlFileEntry.getExtension());
386 document.addKeyword(
387 "fileEntryTypeId", dlFileEntry.getFileEntryTypeId());
388 document.addKeyword(
389 "mimeType",
390 StringUtil.replace(
391 dlFileEntry.getMimeType(), CharPool.FORWARD_SLASH,
392 CharPool.UNDERLINE));
393 document.addKeyword("path", dlFileEntry.getTitle());
394 document.addKeyword("readCount", dlFileEntry.getReadCount());
395 document.addKeyword("size", dlFileEntry.getSize());
396
397 ExpandoBridge expandoBridge =
398 ExpandoBridgeFactoryUtil.getExpandoBridge(
399 dlFileEntry.getCompanyId(), DLFileEntry.class.getName(),
400 dlFileVersion.getFileVersionId());
401
402 ExpandoBridgeIndexerUtil.addAttributes(document, expandoBridge);
403
404 addFileEntryTypeAttributes(document, dlFileVersion);
405
406 if (dlFileEntry.isInHiddenFolder()) {
407 try {
408 Repository repository =
409 RepositoryLocalServiceUtil.getRepository(
410 dlFileEntry.getRepositoryId());
411
412 String portletId = repository.getPortletId();
413
414 for (Indexer indexer : IndexerRegistryUtil.getIndexers()) {
415 if (portletId.equals(indexer.getPortletId())) {
416 indexer.addRelatedEntryFields(document, obj);
417 }
418 }
419 }
420 catch (Exception e) {
421 }
422 }
423
424 if (_log.isDebugEnabled()) {
425 _log.debug("Document " + dlFileEntry + " indexed successfully");
426 }
427
428 return document;
429 }
430 finally {
431 if (is != null) {
432 try {
433 is.close();
434 }
435 catch (IOException ioe) {
436 }
437 }
438 }
439 }
440
441 @Override
442 protected Summary doGetSummary(
443 Document document, Locale locale, String snippet,
444 PortletURL portletURL) {
445
446 LiferayPortletURL liferayPortletURL = (LiferayPortletURL)portletURL;
447
448 liferayPortletURL.setLifecycle(PortletRequest.ACTION_PHASE);
449
450 try {
451 liferayPortletURL.setWindowState(LiferayWindowState.EXCLUSIVE);
452 }
453 catch (WindowStateException wse) {
454 }
455
456 String fileEntryId = document.get(Field.ENTRY_CLASS_PK);
457
458 portletURL.setParameter("struts_action", "/document_library/get_file");
459 portletURL.setParameter("fileEntryId", fileEntryId);
460
461 Summary summary = createSummary(document, Field.TITLE, Field.CONTENT);
462
463 summary.setMaxContentLength(200);
464 summary.setPortletURL(portletURL);
465
466 return summary;
467 }
468
469 @Override
470 protected void doReindex(Object obj) throws Exception {
471 DLFileEntry dlFileEntry = (DLFileEntry)obj;
472
473 DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
474
475 if (!dlFileVersion.isApproved() && !dlFileEntry.isInTrash()) {
476 return;
477 }
478
479 Document document = getDocument(dlFileEntry);
480
481 if (document != null) {
482 SearchEngineUtil.updateDocument(
483 getSearchEngineId(), dlFileEntry.getCompanyId(), document);
484 }
485 }
486
487 @Override
488 protected void doReindex(String className, long classPK) throws Exception {
489 DLFileEntry dlFileEntry = DLFileEntryLocalServiceUtil.getFileEntry(
490 classPK);
491
492 doReindex(dlFileEntry);
493 }
494
495 @Override
496 protected void doReindex(String[] ids) throws Exception {
497 if (ids.length == 1) {
498 long companyId = GetterUtil.getLong(ids[0]);
499
500 reindexFolders(companyId);
501 reindexRoot(companyId);
502 }
503 else {
504 long companyId = GetterUtil.getLong(ids[0]);
505 long groupId = GetterUtil.getLong(ids[2]);
506 long dataRepositoryId = GetterUtil.getLong(ids[3]);
507
508 reindexFileEntries(companyId, groupId, dataRepositoryId);
509 }
510 }
511
512 @Override
513 protected void doReindexDDMStructures(List<Long> ddmStructureIds)
514 throws Exception {
515
516 List<DLFileEntry> dlFileEntries =
517 DLFileEntryLocalServiceUtil.getDDMStructureFileEntries(
518 ArrayUtil.toLongArray(ddmStructureIds));
519
520 for (DLFileEntry dlFileEntry : dlFileEntries) {
521 doReindex(dlFileEntry);
522 }
523 }
524
525 protected String extractContent(DLFileVersion dlFileVersion, Locale locale)
526 throws Exception {
527
528 if (dlFileVersion.getFileEntryTypeId() ==
529 DLFileEntryTypeConstants.FILE_ENTRY_TYPE_ID_BASIC_DOCUMENT) {
530
531 return StringPool.BLANK;
532 }
533
534 return extractDDMContent(dlFileVersion, locale);
535 }
536
537 protected String extractDDMContent(
538 DLFileVersion dlFileVersion, Locale locale)
539 throws Exception {
540
541 DLFileEntryType dlFileEntryType =
542 DLFileEntryTypeLocalServiceUtil.getDLFileEntryType(
543 dlFileVersion.getFileEntryTypeId());
544
545 List<DDMStructure> ddmStructures = dlFileEntryType.getDDMStructures();
546
547 StringBundler sb = new StringBundler(ddmStructures.size());
548
549 for (DDMStructure ddmStructure : ddmStructures) {
550 DLFileEntryMetadata fileEntryMetadata =
551 DLFileEntryMetadataLocalServiceUtil.fetchFileEntryMetadata(
552 ddmStructure.getStructureId(),
553 dlFileVersion.getFileVersionId());
554
555 if (fileEntryMetadata == null) {
556 continue;
557 }
558
559 Fields fields = null;
560
561 try {
562 fields = StorageEngineUtil.getFields(
563 fileEntryMetadata.getDDMStorageId());
564 }
565 catch (Exception e) {
566 continue;
567 }
568
569 if (fields != null) {
570 sb.append(
571 DDMIndexerUtil.extractAttributes(
572 ddmStructure, fields, locale));
573 }
574 }
575
576 return sb.toString();
577 }
578
579 @Override
580 protected String getPortletId(SearchContext searchContext) {
581 return PORTLET_ID;
582 }
583
584 protected void reindexFileEntries(
585 long companyId, final long groupId, final long dataRepositoryId)
586 throws PortalException, SystemException {
587
588 ActionableDynamicQuery actionableDynamicQuery =
589 new DLFileEntryActionableDynamicQuery() {
590
591 @Override
592 protected void addCriteria(DynamicQuery dynamicQuery) {
593 Property property = PropertyFactoryUtil.forName("folderId");
594
595 long folderId = DLFolderConstants.getFolderId(
596 groupId, dataRepositoryId);
597
598 dynamicQuery.add(property.eq(folderId));
599 }
600
601 @Override
602 protected void performAction(Object object) throws PortalException {
603 DLFileEntry dlFileEntry = (DLFileEntry)object;
604
605 Document document = getDocument(dlFileEntry);
606
607 if (document != null) {
608 addDocument(document);
609 }
610 }
611
612 };
613
614 actionableDynamicQuery.setCompanyId(companyId);
615 actionableDynamicQuery.setGroupId(groupId);
616 actionableDynamicQuery.setSearchEngineId(getSearchEngineId());
617
618 actionableDynamicQuery.performActions();
619 }
620
621 protected void reindexFolders(final long companyId)
622 throws PortalException, SystemException {
623
624 ActionableDynamicQuery actionableDynamicQuery =
625 new DLFolderActionableDynamicQuery() {
626
627 @Override
628 protected void performAction(Object object) throws PortalException {
629 DLFolder dlFolder = (DLFolder)object;
630
631 String portletId = PortletKeys.DOCUMENT_LIBRARY;
632 long groupId = dlFolder.getGroupId();
633 long folderId = dlFolder.getFolderId();
634
635 String[] newIds = {
636 String.valueOf(companyId), portletId,
637 String.valueOf(groupId), String.valueOf(folderId)
638 };
639
640 reindex(newIds);
641 }
642
643 };
644
645 actionableDynamicQuery.setCompanyId(companyId);
646
647 actionableDynamicQuery.performActions();
648 }
649
650 protected void reindexRoot(final long companyId)
651 throws PortalException, SystemException {
652
653 ActionableDynamicQuery actionableDynamicQuery =
654 new GroupActionableDynamicQuery() {
655
656 @Override
657 protected void performAction(Object object) throws PortalException {
658 Group group = (Group)object;
659
660 String portletId = PortletKeys.DOCUMENT_LIBRARY;
661 long groupId = group.getGroupId();
662 long folderId = groupId;
663
664 String[] newIds = {
665 String.valueOf(companyId), portletId,
666 String.valueOf(groupId), String.valueOf(folderId)
667 };
668
669 reindex(newIds);
670 }
671
672 };
673
674 actionableDynamicQuery.setCompanyId(companyId);
675
676 actionableDynamicQuery.performActions();
677 }
678
679 private static Log _log = LogFactoryUtil.getLog(DLFileEntryIndexer.class);
680
681 }