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