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