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