001    /**
002     * Copyright (c) 2000-present 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.portal.lar.backgroundtask;
016    
017    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskResult;
018    import com.liferay.portal.kernel.backgroundtask.BaseBackgroundTaskExecutor;
019    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
020    import com.liferay.portal.kernel.dao.orm.Property;
021    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
022    import com.liferay.portal.kernel.lar.PortletDataContext;
023    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.search.Indexer;
027    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
028    import com.liferay.portal.kernel.util.ArrayUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.MapUtil;
031    import com.liferay.portal.kernel.util.ReflectionUtil;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.model.BackgroundTask;
035    import com.liferay.portal.model.User;
036    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
037    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
038    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
039    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
040    import com.liferay.portlet.journal.model.JournalArticle;
041    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
042    
043    import java.io.Serializable;
044    
045    import java.lang.reflect.Method;
046    
047    import java.util.ArrayList;
048    import java.util.List;
049    import java.util.Map;
050    
051    /**
052     * @author Mate Thurzo
053     */
054    public class StagingIndexingBackgroundTaskExecutor
055            extends BaseBackgroundTaskExecutor {
056    
057            public StagingIndexingBackgroundTaskExecutor() {
058                    setSerial(true);
059            }
060    
061            @Override
062            public BackgroundTaskResult execute(BackgroundTask backgroundTask)
063                    throws Exception {
064    
065                    Map<String, Serializable> taskContextMap =
066                            backgroundTask.getTaskContextMap();
067    
068                    PortletDataContext portletDataContext =
069                            (PortletDataContext)taskContextMap.get("portletDataContext");
070    
071                    boolean importPermissions = MapUtil.getBoolean(
072                            portletDataContext.getParameterMap(),
073                            PortletDataHandlerKeys.PERMISSIONS);
074    
075                    if (importPermissions) {
076                            long userId = MapUtil.getLong(taskContextMap, "userId");
077    
078                            if (userId > 0) {
079                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
080                                            User.class);
081    
082                                    indexer.reindex(userId);
083                            }
084                    }
085    
086                    Map<String, Map<?, ?>> newPrimaryKeysMaps =
087                            portletDataContext.getNewPrimaryKeysMaps();
088    
089                    for (Map.Entry<String, Map<?, ?>> newPrimaryKeysMapsEntry :
090                                    newPrimaryKeysMaps.entrySet()) {
091    
092                            String className = newPrimaryKeysMapsEntry.getKey();
093    
094                            Indexer indexer = IndexerRegistryUtil.getIndexer(className);
095    
096                            if ((indexer == null) &&
097                                    !className.equals(DDMStructure.class.getName())) {
098    
099                                    continue;
100                            }
101    
102                            Map<?, ?> newPrimaryKeysMap = newPrimaryKeysMapsEntry.getValue();
103    
104                            List<Long> newPrimaryKeys = new ArrayList<Long>();
105    
106                            for (Object object : newPrimaryKeysMap.values()) {
107                                    long classPK = GetterUtil.getLong(object);
108    
109                                    if (classPK > 0) {
110                                            newPrimaryKeys.add(classPK);
111                                    }
112                            }
113    
114                            if (className.equals(DDMStructure.class.getName())) {
115                                    reindexDDMStructures(
116                                            newPrimaryKeys, newPrimaryKeysMaps,
117                                            portletDataContext.getGroupId());
118                            }
119                            else {
120                                    for (Long classPK : newPrimaryKeys) {
121                                            indexer.reindex(className, classPK);
122                                    }
123                            }
124                    }
125    
126                    return BackgroundTaskResult.SUCCESS;
127            }
128    
129            protected void reindexDDMStructures(
130                            List<Long> ddmStructureIds,
131                            Map<String, Map<?, ?>> newPrimaryKeysMaps, long groupId)
132                    throws Exception {
133    
134                    if ((ddmStructureIds == null) || ddmStructureIds.isEmpty()) {
135                            return;
136                    }
137    
138                    String[] ddmStructureKeys = new String[ddmStructureIds.size()];
139    
140                    for (int i = 0; i < ddmStructureIds.size(); i++) {
141                            long structureId = ddmStructureIds.get(i);
142    
143                            DDMStructure ddmStructure =
144                                    DDMStructureLocalServiceUtil.getDDMStructure(structureId);
145    
146                            ddmStructureKeys[i] = ddmStructure.getStructureKey();
147                    }
148    
149                    DynamicQuery journalArticleDynamicQuery =
150                            JournalArticleLocalServiceUtil.dynamicQuery();
151    
152                    Property groupIdProperty = PropertyFactoryUtil.forName("groupId");
153    
154                    journalArticleDynamicQuery.add(groupIdProperty.eq(groupId));
155    
156                    Property structureIdProperty = PropertyFactoryUtil.forName(
157                            "structureId");
158    
159                    journalArticleDynamicQuery.add(
160                            structureIdProperty.in(ddmStructureKeys));
161    
162                    List<JournalArticle> journalArticles =
163                            JournalArticleLocalServiceUtil.dynamicQuery(
164                                    journalArticleDynamicQuery);
165    
166                    Map<?, ?> journalArticlePrimaryKeysMap = newPrimaryKeysMaps.get(
167                            JournalArticle.class.getName());
168    
169                    Indexer journalArticleIndexer = IndexerRegistryUtil.getIndexer(
170                            JournalArticle.class);
171    
172                    for (JournalArticle article : journalArticles) {
173                            if (containsValue(
174                                            journalArticlePrimaryKeysMap,
175                                            article.getResourcePrimKey())) {
176    
177                                    continue;
178                            }
179    
180                            journalArticleIndexer.reindex(article);
181                    }
182    
183                    List<DLFileEntry> dlFileEntries = new ArrayList<DLFileEntry>();
184    
185                    try {
186                            Method method = ReflectionUtil.getDeclaredMethod(
187                                    DLFileEntryLocalServiceUtil.class, "getDDMStructureFileEntries",
188                                    long.class, long[].class);
189    
190                            Object object = method.invoke(
191                                    DLFileEntryLocalServiceUtil.class, groupId,
192                                    ArrayUtil.toLongArray(ddmStructureIds));
193    
194                            if (object != null) {
195                                    dlFileEntries = (List<DLFileEntry>)object;
196                            }
197                    }
198                    catch (Exception e) {
199                            List<DLFileEntry> allDlFileEntries =
200                                    DLFileEntryLocalServiceUtil.getDDMStructureFileEntries(
201                                            ArrayUtil.toLongArray(ddmStructureIds));
202    
203                            for (DLFileEntry dlFileEntry : allDlFileEntries) {
204                                    if (groupId == dlFileEntry.getGroupId()) {
205                                            dlFileEntries.add(dlFileEntry);
206                                    }
207                            }
208                    }
209    
210                    Map<?, ?> dlFileEntryPrimaryKeysMap = newPrimaryKeysMaps.get(
211                            DLFileEntry.class.getName());
212    
213                    Indexer dlFileEntryIndexer = IndexerRegistryUtil.getIndexer(
214                            DLFileEntry.class);
215    
216                    for (DLFileEntry dlFileEntry : dlFileEntries) {
217                            if (containsValue(
218                                            dlFileEntryPrimaryKeysMap, dlFileEntry.getFileEntryId())) {
219    
220                                    continue;
221                            }
222    
223                            dlFileEntryIndexer.reindex(dlFileEntry);
224                    }
225            }
226    
227            protected boolean containsValue(Map<?, ?> map, long value) {
228                    if ((map == null) || map.isEmpty() || (value <= 0)) {
229                            return false;
230                    }
231    
232                    for (Object object : map.values()) {
233                            if (GetterUtil.getLong(object) == value) {
234                                    return true;
235                            }
236                    }
237    
238                    return false;
239            }
240    
241            @Override
242            public String handleException(BackgroundTask backgroundTask, Exception e) {
243                    StringBundler sb = new StringBundler(4);
244    
245                    sb.append("Indexing failed after importing with the following error: ");
246                    sb.append(e.getMessage());
247                    sb.append(StringPool.PERIOD);
248                    sb.append(StringPool.SPACE);
249                    sb.append("Please reindex site manually.");
250    
251                    String message = sb.toString();
252    
253                    if (_log.isInfoEnabled()) {
254                            _log.info(message);
255                    }
256    
257                    return message;
258            }
259    
260            private static Log _log = LogFactoryUtil.getLog(
261                    StagingIndexingBackgroundTaskExecutor.class);
262    
263    }