001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.documentlibrary.util;
016    
017    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
018    import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
019    import com.liferay.portal.kernel.dao.orm.Projection;
020    import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
021    import com.liferay.portal.kernel.dao.orm.ProjectionList;
022    import com.liferay.portal.kernel.dao.orm.Property;
023    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
024    import com.liferay.portal.kernel.exception.PortalException;
025    import com.liferay.portal.kernel.exception.SystemException;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
029    import com.liferay.portal.kernel.portlet.LiferayWindowState;
030    import com.liferay.portal.kernel.search.BaseIndexer;
031    import com.liferay.portal.kernel.search.BooleanClauseOccur;
032    import com.liferay.portal.kernel.search.BooleanQuery;
033    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
034    import com.liferay.portal.kernel.search.Document;
035    import com.liferay.portal.kernel.search.DocumentImpl;
036    import com.liferay.portal.kernel.search.Field;
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.GetterUtil;
043    import com.liferay.portal.kernel.util.PropsKeys;
044    import com.liferay.portal.kernel.util.StringPool;
045    import com.liferay.portal.kernel.util.Validator;
046    import com.liferay.portal.kernel.workflow.WorkflowConstants;
047    import com.liferay.portal.model.Group;
048    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
049    import com.liferay.portal.security.permission.ActionKeys;
050    import com.liferay.portal.security.permission.PermissionChecker;
051    import com.liferay.portal.service.GroupLocalServiceUtil;
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.bookmarks.service.BookmarksFolderLocalServiceUtil;
056    import com.liferay.portlet.documentlibrary.asset.DLFileEntryAssetRendererFactory;
057    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
058    import com.liferay.portlet.documentlibrary.model.DLFileEntryMetadata;
059    import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
060    import com.liferay.portlet.documentlibrary.model.DLFileVersion;
061    import com.liferay.portlet.documentlibrary.model.DLFolder;
062    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
063    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
064    import com.liferay.portlet.documentlibrary.service.DLFileEntryMetadataLocalServiceUtil;
065    import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
066    import com.liferay.portlet.documentlibrary.service.DLFolderLocalServiceUtil;
067    import com.liferay.portlet.documentlibrary.service.DLFolderServiceUtil;
068    import com.liferay.portlet.documentlibrary.service.permission.DLFileEntryPermission;
069    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
070    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
071    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
072    import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
073    import com.liferay.portlet.dynamicdatamapping.util.DDMIndexerUtil;
074    import com.liferay.portlet.expando.model.ExpandoBridge;
075    import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
076    import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
077    
078    import java.io.IOException;
079    import java.io.InputStream;
080    
081    import java.util.ArrayList;
082    import java.util.Collection;
083    import java.util.LinkedHashMap;
084    import java.util.List;
085    import java.util.Locale;
086    import java.util.Set;
087    import java.util.TreeSet;
088    
089    import javax.portlet.PortletRequest;
090    import javax.portlet.PortletURL;
091    import javax.portlet.WindowStateException;
092    
093    /**
094     * @author Brian Wing Shun Chan
095     * @author Raymond Augé
096     * @author Alexander Chow
097     */
098    public class DLIndexer extends BaseIndexer {
099    
100            public static final String[] CLASS_NAMES = {DLFileEntry.class.getName()};
101    
102            public static final String PORTLET_ID = PortletKeys.DOCUMENT_LIBRARY;
103    
104            public DLIndexer() {
105                    setFilterSearch(true);
106                    setPermissionAware(true);
107            }
108    
109            public String[] getClassNames() {
110                    return CLASS_NAMES;
111            }
112    
113            public String getPortletId() {
114                    return PORTLET_ID;
115            }
116    
117            @Override
118            public boolean hasPermission(
119                            PermissionChecker permissionChecker, String entryClassName,
120                            long entryClassPK, String actionId)
121                    throws Exception {
122    
123                    return DLFileEntryPermission.contains(
124                            permissionChecker, entryClassPK, ActionKeys.VIEW);
125            }
126    
127            @Override
128            public void postProcessContextQuery(
129                            BooleanQuery contextQuery, SearchContext searchContext)
130                    throws Exception {
131    
132                    int status = GetterUtil.getInteger(
133                            searchContext.getAttribute(Field.STATUS),
134                            WorkflowConstants.STATUS_APPROVED);
135    
136                    if (status != WorkflowConstants.STATUS_ANY) {
137                            contextQuery.addRequiredTerm(Field.STATUS, status);
138                    }
139    
140                    long[] folderIds = searchContext.getFolderIds();
141    
142                    if ((folderIds != null) && (folderIds.length > 0)) {
143                            if (folderIds[0] == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
144                                    return;
145                            }
146    
147                            BooleanQuery folderIdsQuery = BooleanQueryFactoryUtil.create(
148                                    searchContext);
149    
150                            for (long folderId : folderIds) {
151                                    try {
152                                            DLFolderServiceUtil.getFolder(folderId);
153                                    }
154                                    catch (Exception e) {
155                                            continue;
156                                    }
157    
158                                    folderIdsQuery.addTerm(Field.FOLDER_ID, folderId);
159                            }
160    
161                            contextQuery.add(folderIdsQuery, BooleanClauseOccur.MUST);
162                    }
163            }
164    
165            @Override
166            public void postProcessSearchQuery(
167                            BooleanQuery searchQuery, SearchContext searchContext)
168                    throws Exception {
169    
170                    Set<DDMStructure> ddmStructuresSet = new TreeSet<DDMStructure>();
171    
172                    long[] groupIds = searchContext.getGroupIds();
173    
174                    if ((groupIds != null) && (groupIds.length > 0)) {
175                            List<DLFileEntryType> dlFileEntryTypes =
176                                    DLFileEntryTypeLocalServiceUtil.getFileEntryTypes(groupIds);
177    
178                            for (DLFileEntryType dlFileEntryType : dlFileEntryTypes) {
179                                    ddmStructuresSet.addAll(dlFileEntryType.getDDMStructures());
180                            }
181                    }
182    
183                    Group group = GroupLocalServiceUtil.getCompanyGroup(
184                            searchContext.getCompanyId());
185    
186                    DDMStructure tikaRawMetadataStructure =
187                            DDMStructureLocalServiceUtil.fetchStructure(
188                                    group.getGroupId(), "TikaRawMetadata");
189    
190                    if (tikaRawMetadataStructure != null) {
191                            ddmStructuresSet.add(tikaRawMetadataStructure);
192                    }
193    
194                    for (DDMStructure ddmStructure : ddmStructuresSet) {
195                            addSearchDDMStruture(searchQuery, searchContext, ddmStructure);
196                    }
197    
198                    String keywords = searchContext.getKeywords();
199    
200                    if (Validator.isNull(keywords)) {
201                            addSearchTerm(searchQuery, searchContext, Field.DESCRIPTION, false);
202                            addSearchTerm(searchQuery, searchContext, Field.TITLE, false);
203                            addSearchTerm(searchQuery, searchContext, Field.USER_NAME, false);
204                    }
205    
206                    addSearchTerm(searchQuery, searchContext, "extension", false);
207                    addSearchTerm(searchQuery, searchContext, "fileEntryTypeId", false);
208                    addSearchTerm(searchQuery, searchContext, "path", false);
209    
210                    LinkedHashMap<String, Object> params =
211                            (LinkedHashMap<String, Object>)searchContext.getAttribute("params");
212    
213                    if (params != null) {
214                            String expandoAttributes = (String)params.get("expandoAttributes");
215    
216                            if (Validator.isNotNull(expandoAttributes)) {
217                                    addSearchExpando(searchQuery, searchContext, expandoAttributes);
218                            }
219                    }
220            }
221    
222            protected void addFileEntryTypeAttributes(
223                            Document document, DLFileVersion dlFileVersion)
224                    throws PortalException, SystemException {
225    
226                    List<DLFileEntryMetadata> dlFileEntryMetadatas =
227                            DLFileEntryMetadataLocalServiceUtil.
228                                    getFileVersionFileEntryMetadatas(
229                                            dlFileVersion.getFileVersionId());
230    
231                    for (DLFileEntryMetadata dlFileEntryMetadata : dlFileEntryMetadatas) {
232                            Fields fields = null;
233    
234                            try {
235                                    fields = StorageEngineUtil.getFields(
236                                            dlFileEntryMetadata.getDDMStorageId());
237                            }
238                            catch (Exception e) {
239                            }
240    
241                            if (fields != null) {
242                                    DDMStructure ddmStructure =
243                                            DDMStructureLocalServiceUtil.getStructure(
244                                                    dlFileEntryMetadata.getDDMStructureId());
245    
246                                    DDMIndexerUtil.addAttributes(document, ddmStructure, fields);
247                            }
248                    }
249            }
250    
251            protected void addReindexCriteria(
252                    DynamicQuery dynamicQuery, long companyId) {
253    
254                    Property property = PropertyFactoryUtil.forName("companyId");
255    
256                    dynamicQuery.add(property.eq(companyId));
257            }
258    
259            protected void addReindexCriteria(
260                    DynamicQuery dynamicQuery, long groupId, long folderId) {
261    
262                    Property groupIdProperty = PropertyFactoryUtil.forName("groupId");
263    
264                    dynamicQuery.add(groupIdProperty.eq(groupId));
265    
266                    Property folderIdProperty = PropertyFactoryUtil.forName("folderId");
267    
268                    dynamicQuery.add(folderIdProperty.eq(folderId));
269            }
270    
271            @Override
272            protected void doDelete(Object obj) throws Exception {
273                    DLFileEntry dlFileEntry = (DLFileEntry)obj;
274    
275                    Document document = new DocumentImpl();
276    
277                    document.addUID(PORTLET_ID, dlFileEntry.getFileEntryId());
278    
279                    SearchEngineUtil.deleteDocument(
280                            getSearchEngineId(), dlFileEntry.getCompanyId(),
281                            document.get(Field.UID));
282            }
283    
284            @Override
285            protected Document doGetDocument(Object obj) throws Exception {
286                    DLFileEntry dlFileEntry = (DLFileEntry)obj;
287    
288                    if (_log.isDebugEnabled()) {
289                            _log.debug("Indexing document " + dlFileEntry);
290                    }
291    
292                    boolean indexContent = true;
293    
294                    InputStream is = null;
295    
296                    try {
297                            if (PropsValues.DL_FILE_INDEXING_MAX_SIZE == 0) {
298                                    indexContent = false;
299                            }
300                            else if (PropsValues.DL_FILE_INDEXING_MAX_SIZE != -1) {
301                                    if (dlFileEntry.getSize() >
302                                                    PropsValues.DL_FILE_INDEXING_MAX_SIZE) {
303    
304                                            indexContent = false;
305                                    }
306                            }
307    
308                            if (indexContent) {
309                                    String[] ignoreExtensions = PrefsPropsUtil.getStringArray(
310                                            PropsKeys.DL_FILE_INDEXING_IGNORE_EXTENSIONS,
311                                            StringPool.COMMA);
312    
313                                    if (ArrayUtil.contains(
314                                                    ignoreExtensions,
315                                                    StringPool.PERIOD + dlFileEntry.getExtension())) {
316    
317                                            indexContent = false;
318                                    }
319                            }
320    
321                            if (indexContent) {
322                                    is = dlFileEntry.getFileVersion().getContentStream(false);
323                            }
324                    }
325                    catch (Exception e) {
326                    }
327    
328                    if (indexContent && (is == null)) {
329                            if (_log.isDebugEnabled()) {
330                                    _log.debug(
331                                            "Document " + dlFileEntry + " does not have any content");
332                            }
333    
334                            return null;
335                    }
336    
337                    DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
338    
339                    try {
340                            Document document = getBaseModelDocument(
341                                    PORTLET_ID, dlFileEntry, dlFileVersion);
342    
343                            if (indexContent) {
344                                    try {
345                                            document.addFile(Field.CONTENT, is, dlFileEntry.getTitle());
346                                    }
347                                    catch (IOException ioe) {
348                                            throw new SearchException(
349                                                    "Cannot extract text from file" + dlFileEntry);
350                                    }
351                            }
352    
353                            document.addText(Field.DESCRIPTION, dlFileEntry.getDescription());
354                            document.addKeyword(Field.FOLDER_ID, dlFileEntry.getFolderId());
355                            document.addText(
356                                    Field.PROPERTIES, dlFileEntry.getLuceneProperties());
357                            document.addText(Field.TITLE, dlFileEntry.getTitle());
358    
359                            document.addKeyword(
360                                    "dataRepositoryId", dlFileEntry.getDataRepositoryId());
361                            document.addKeyword("extension", dlFileEntry.getExtension());
362                            document.addKeyword(
363                                    "fileEntryTypeId", dlFileEntry.getFileEntryTypeId());
364                            document.addKeyword("path", dlFileEntry.getTitle());
365    
366                            ExpandoBridge expandoBridge =
367                                    ExpandoBridgeFactoryUtil.getExpandoBridge(
368                                            dlFileEntry.getCompanyId(), DLFileEntry.class.getName(),
369                                            dlFileVersion.getFileVersionId());
370    
371                            ExpandoBridgeIndexerUtil.addAttributes(document, expandoBridge);
372    
373                            addFileEntryTypeAttributes(document, dlFileVersion);
374    
375                            if (!dlFileVersion.isInTrash() && dlFileVersion.isInTrashFolder()) {
376                                    DLFolder trashedFolder = dlFileVersion.getTrashFolder();
377    
378                                    addTrashFields(
379                                            document, DLFolder.class.getName(),
380                                            trashedFolder.getFolderId(), null, null,
381                                            DLFileEntryAssetRendererFactory.TYPE);
382    
383                                    document.addKeyword(
384                                            Field.ROOT_ENTRY_CLASS_NAME, DLFolder.class.getName());
385                                    document.addKeyword(
386                                            Field.ROOT_ENTRY_CLASS_PK, trashedFolder.getFolderId());
387                                    document.addKeyword(
388                                            Field.STATUS, WorkflowConstants.STATUS_IN_TRASH);
389                            }
390    
391                            if (_log.isDebugEnabled()) {
392                                    _log.debug("Document " + dlFileEntry + " indexed successfully");
393                            }
394    
395                            return document;
396                    }
397                    finally {
398                            if (is != null) {
399                                    try {
400                                            is.close();
401                                    }
402                                    catch (IOException ioe) {
403                                    }
404                            }
405                    }
406            }
407    
408            @Override
409            protected Summary doGetSummary(
410                    Document document, Locale locale, String snippet,
411                    PortletURL portletURL) {
412    
413                    LiferayPortletURL liferayPortletURL = (LiferayPortletURL)portletURL;
414    
415                    liferayPortletURL.setLifecycle(PortletRequest.ACTION_PHASE);
416    
417                    try {
418                            liferayPortletURL.setWindowState(LiferayWindowState.EXCLUSIVE);
419                    }
420                    catch (WindowStateException wse) {
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                    Summary summary = createSummary(document, Field.TITLE, Field.CONTENT);
429    
430                    summary.setMaxContentLength(200);
431                    summary.setPortletURL(portletURL);
432    
433                    return summary;
434            }
435    
436            @Override
437            protected void doReindex(Object obj) throws Exception {
438                    DLFileEntry dlFileEntry = (DLFileEntry)obj;
439    
440                    DLFileVersion dlFileVersion = dlFileEntry.getFileVersion();
441    
442                    if (!dlFileVersion.isApproved() && !dlFileVersion.isInTrash()) {
443                            return;
444                    }
445    
446                    Document document = getDocument(dlFileEntry);
447    
448                    if (document != null) {
449                            SearchEngineUtil.updateDocument(
450                                    getSearchEngineId(), dlFileEntry.getCompanyId(), document);
451                    }
452            }
453    
454            @Override
455            protected void doReindex(String className, long classPK) throws Exception {
456                    DLFileEntry dlFileEntry = DLFileEntryLocalServiceUtil.getFileEntry(
457                            classPK);
458    
459                    doReindex(dlFileEntry);
460            }
461    
462            @Override
463            protected void doReindex(String[] ids) throws Exception {
464                    if (ids.length == 1) {
465                            long companyId = GetterUtil.getLong(ids[0]);
466    
467                            reindexFolders(companyId);
468                            reindexRoot(companyId);
469                    }
470                    else {
471                            long companyId = GetterUtil.getLong(ids[0]);
472                            long groupId = GetterUtil.getLong(ids[2]);
473                            long dataRepositoryId = GetterUtil.getLong(ids[3]);
474    
475                            reindexFileEntries(companyId, groupId, dataRepositoryId);
476                    }
477            }
478    
479            @Override
480            protected String getPortletId(SearchContext searchContext) {
481                    return PORTLET_ID;
482            }
483    
484            protected void reindexFileEntries(
485                            long companyId, long groupId, long dataRepositoryId)
486                    throws Exception {
487    
488                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
489                            DLFileEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
490    
491                    Projection minFileEntryIdProjection = ProjectionFactoryUtil.min(
492                            "fileEntryId");
493                    Projection maxFileEntryIdProjection = ProjectionFactoryUtil.max(
494                            "fileEntryId");
495    
496                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
497    
498                    projectionList.add(minFileEntryIdProjection);
499                    projectionList.add(maxFileEntryIdProjection);
500    
501                    dynamicQuery.setProjection(projectionList);
502    
503                    long folderId = DLFolderConstants.getFolderId(
504                            groupId, dataRepositoryId);
505    
506                    addReindexCriteria(dynamicQuery, groupId, folderId);
507    
508                    List<Object[]> results = DLFileEntryLocalServiceUtil.dynamicQuery(
509                            dynamicQuery);
510    
511                    Object[] minAndMaxFileEntryIds = results.get(0);
512    
513                    if ((minAndMaxFileEntryIds[0] == null) ||
514                            (minAndMaxFileEntryIds[1] == null)) {
515    
516                            return;
517                    }
518    
519                    long minFileEntryId = (Long)minAndMaxFileEntryIds[0];
520                    long maxFileEntryId = (Long)minAndMaxFileEntryIds[1];
521    
522                    long startFileEntryId = minFileEntryId;
523                    long endFileEntryId = startFileEntryId + DEFAULT_INTERVAL;
524    
525                    while (startFileEntryId <= maxFileEntryId) {
526                            reindexFileEntries(
527                                    companyId, groupId, folderId, startFileEntryId, endFileEntryId);
528    
529                            startFileEntryId = endFileEntryId;
530                            endFileEntryId += DEFAULT_INTERVAL;
531                    }
532            }
533    
534            protected void reindexFileEntries(
535                            long companyId, long groupId, long folderId, long startFileEntryId,
536                            long endFileEntryId)
537                    throws Exception {
538    
539                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
540                            DLFileEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
541    
542                    Property property = PropertyFactoryUtil.forName("fileEntryId");
543    
544                    dynamicQuery.add(property.ge(startFileEntryId));
545                    dynamicQuery.add(property.lt(endFileEntryId));
546    
547                    addReindexCriteria(dynamicQuery, groupId, folderId);
548    
549                    List<DLFileEntry> dlFileEntries =
550                            DLFileEntryLocalServiceUtil.dynamicQuery(dynamicQuery);
551    
552                    if (dlFileEntries.isEmpty()) {
553                            return;
554                    }
555    
556                    Collection<Document> documents = new ArrayList<Document>(
557                            dlFileEntries.size());
558    
559                    for (DLFileEntry dlFileEntry : dlFileEntries) {
560                            Document document = getDocument(dlFileEntry);
561    
562                            if (document != null) {
563                                    documents.add(document);
564                            }
565                    }
566    
567                    SearchEngineUtil.updateDocuments(
568                            getSearchEngineId(), companyId, documents);
569            }
570    
571            protected void reindexFolders(long companyId) throws Exception {
572                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
573                            DLFolder.class, PACLClassLoaderUtil.getPortalClassLoader());
574    
575                    Projection minFolderIdProjection = ProjectionFactoryUtil.min(
576                            "folderId");
577                    Projection maxFolderIdProjection = ProjectionFactoryUtil.max(
578                            "folderId");
579    
580                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
581    
582                    projectionList.add(minFolderIdProjection);
583                    projectionList.add(maxFolderIdProjection);
584    
585                    dynamicQuery.setProjection(projectionList);
586    
587                    addReindexCriteria(dynamicQuery, companyId);
588    
589                    List<Object[]> results = BookmarksFolderLocalServiceUtil.dynamicQuery(
590                            dynamicQuery);
591    
592                    Object[] minAndMaxFolderIds = results.get(0);
593    
594                    if ((minAndMaxFolderIds[0] == null) ||
595                            (minAndMaxFolderIds[1] == null)) {
596    
597                            return;
598                    }
599    
600                    long minFolderId = (Long)minAndMaxFolderIds[0];
601                    long maxFolderId = (Long)minAndMaxFolderIds[1];
602    
603                    long startFolderId = minFolderId;
604                    long endFolderId = startFolderId + DEFAULT_INTERVAL;
605    
606                    while (startFolderId <= maxFolderId) {
607                            reindexFolders(companyId, startFolderId, endFolderId);
608    
609                            startFolderId = endFolderId;
610                            endFolderId += DEFAULT_INTERVAL;
611                    }
612            }
613    
614            protected void reindexFolders(
615                            long companyId, long startFolderId, long endFolderId)
616                    throws Exception {
617    
618                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
619                            DLFolder.class, PACLClassLoaderUtil.getPortalClassLoader());
620    
621                    Property property = PropertyFactoryUtil.forName("folderId");
622    
623                    dynamicQuery.add(property.ge(startFolderId));
624                    dynamicQuery.add(property.lt(endFolderId));
625    
626                    addReindexCriteria(dynamicQuery, companyId);
627    
628                    List<DLFolder> dlFolders = DLFolderLocalServiceUtil.dynamicQuery(
629                            dynamicQuery);
630    
631                    for (DLFolder dlFolder : dlFolders) {
632                            String portletId = PortletKeys.DOCUMENT_LIBRARY;
633                            long groupId = dlFolder.getGroupId();
634                            long folderId = dlFolder.getFolderId();
635    
636                            String[] newIds = {
637                                    String.valueOf(companyId), portletId, String.valueOf(groupId),
638                                    String.valueOf(folderId)
639                            };
640    
641                            reindex(newIds);
642                    }
643            }
644    
645            protected void reindexRoot(long companyId) throws Exception {
646                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
647                            Group.class, PACLClassLoaderUtil.getPortalClassLoader());
648    
649                    Projection minGroupIdProjection = ProjectionFactoryUtil.min("groupId");
650                    Projection maxGroupIdProjection = ProjectionFactoryUtil.max("groupId");
651    
652                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
653    
654                    projectionList.add(minGroupIdProjection);
655                    projectionList.add(maxGroupIdProjection);
656    
657                    dynamicQuery.setProjection(projectionList);
658    
659                    addReindexCriteria(dynamicQuery, companyId);
660    
661                    List<Object[]> results = GroupLocalServiceUtil.dynamicQuery(
662                            dynamicQuery);
663    
664                    Object[] minAndMaxGroupIds = results.get(0);
665    
666                    if ((minAndMaxGroupIds[0] == null) || (minAndMaxGroupIds[1] == null)) {
667                            return;
668                    }
669    
670                    long minGroupId = (Long)minAndMaxGroupIds[0];
671                    long maxGroupId = (Long)minAndMaxGroupIds[1];
672    
673                    long startGroupId = minGroupId;
674                    long endGroupId = startGroupId + DEFAULT_INTERVAL;
675    
676                    while (startGroupId <= maxGroupId) {
677                            reindexRoot(companyId, startGroupId, endGroupId);
678    
679                            startGroupId = endGroupId;
680                            endGroupId += DEFAULT_INTERVAL;
681                    }
682            }
683    
684            protected void reindexRoot(
685                            long companyId, long startGroupId, long endGroupId)
686                    throws Exception {
687    
688                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
689                            Group.class, PACLClassLoaderUtil.getPortalClassLoader());
690    
691                    Property property = PropertyFactoryUtil.forName("groupId");
692    
693                    dynamicQuery.add(property.ge(startGroupId));
694                    dynamicQuery.add(property.lt(endGroupId));
695    
696                    addReindexCriteria(dynamicQuery, companyId);
697    
698                    List<Group> groups = GroupLocalServiceUtil.dynamicQuery(dynamicQuery);
699    
700                    for (Group group : groups) {
701                            String portletId = PortletKeys.DOCUMENT_LIBRARY;
702                            long groupId = group.getGroupId();
703                            long folderId = groupId;
704    
705                            String[] newIds = {
706                                    String.valueOf(companyId), portletId, String.valueOf(groupId),
707                                    String.valueOf(folderId)
708                            };
709    
710                            reindex(newIds);
711                    }
712            }
713    
714            private static Log _log = LogFactoryUtil.getLog(DLIndexer.class);
715    
716    }