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