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