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