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