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