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