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