001    /**
002     * Copyright (c) 2000-2013 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.kernel.lar;
016    
017    import com.liferay.portal.NoSuchModelException;
018    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
019    import com.liferay.portal.kernel.dao.orm.Session;
020    import com.liferay.portal.kernel.dao.orm.SessionFactory;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.PropsUtil;
026    import com.liferay.portal.kernel.workflow.WorkflowConstants;
027    import com.liferay.portal.kernel.xml.Element;
028    import com.liferay.portal.model.StagedModel;
029    import com.liferay.portal.model.TrashedModel;
030    import com.liferay.portal.model.WorkflowedModel;
031    
032    import java.util.HashMap;
033    import java.util.Map;
034    
035    /**
036     * @author Mate Thurzo
037     * @author Daniel Kocsis
038     * @author Zsolt Berentey
039     */
040    public abstract class BaseStagedModelDataHandler<T extends StagedModel>
041            implements StagedModelDataHandler<T> {
042    
043            public static final int STAGING_HIBERNATE_CACHE_FLUSH_FREQUENCY =
044                    GetterUtil.getInteger(PropsUtil.get(
045                            "staging.hibernate.cache.flush.frequency"));
046    
047            @Override
048            public abstract void deleteStagedModel(
049                            String uuid, long groupId, String className, String extraData)
050                    throws PortalException, SystemException;
051    
052            @Override
053            public void exportStagedModel(
054                            PortletDataContext portletDataContext, T stagedModel)
055                    throws PortletDataException {
056    
057                    validateExport(portletDataContext, stagedModel);
058    
059                    String path = ExportImportPathUtil.getModelPath(stagedModel);
060    
061                    if (portletDataContext.isPathExportedInScope(path)) {
062                            return;
063                    }
064    
065                    try {
066                            ManifestSummary manifestSummary =
067                                    portletDataContext.getManifestSummary();
068    
069                            PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
070                                    "stagedModel", stagedModel, manifestSummary);
071    
072                            doExportStagedModel(portletDataContext, (T)stagedModel.clone());
073    
074                            if (countStagedModel(portletDataContext, stagedModel)) {
075                                    manifestSummary.incrementModelAdditionCount(
076                                            stagedModel.getStagedModelType());
077                            }
078    
079                            portletDataContext.cleanUpMissingReferences(stagedModel);
080                    }
081                    catch (PortletDataException pde) {
082                            throw pde;
083                    }
084                    catch (Exception e) {
085                            PortletDataException pde = new PortletDataException(e);
086    
087                            if (e instanceof NoSuchModelException) {
088                                    pde.setStagedModel(stagedModel);
089                                    pde.setType(PortletDataException.MISSING_DEPENDENCY);
090                            }
091    
092                            throw pde;
093                    }
094            }
095    
096            @Override
097            public abstract String[] getClassNames();
098    
099            @Override
100            public String getDisplayName(T stagedModel) {
101                    return stagedModel.getUuid();
102            }
103    
104            @Override
105            public int[] getExportableStatuses() {
106                    return new int[] {WorkflowConstants.STATUS_APPROVED};
107            }
108    
109            @Override
110            public Map<String, String> getReferenceAttributes(
111                    PortletDataContext portletDataContext, T stagedModel) {
112    
113                    return new HashMap<String, String>();
114            }
115    
116            @Override
117            public void importCompanyStagedModel(
118                            PortletDataContext portletDataContext, Element element)
119                    throws PortletDataException {
120    
121                    String uuid = element.attributeValue("uuid");
122                    long classPK = GetterUtil.getLong(element.attributeValue("class-pk"));
123    
124                    importCompanyStagedModel(portletDataContext, uuid, classPK);
125            }
126    
127            @Override
128            public void importCompanyStagedModel(
129                            PortletDataContext portletDataContext, String uuid, long classPK)
130                    throws PortletDataException {
131    
132                    try {
133                            doImportCompanyStagedModel(portletDataContext, uuid, classPK);
134                    }
135                    catch (PortletDataException pde) {
136                            throw pde;
137                    }
138                    catch (Exception e) {
139                            throw new PortletDataException(e);
140                    }
141            }
142    
143            @Override
144            public void importStagedModel(
145                            PortletDataContext portletDataContext, T stagedModel)
146                    throws PortletDataException {
147    
148                    String path = ExportImportPathUtil.getModelPath(stagedModel);
149    
150                    if (portletDataContext.isPathProcessed(path)) {
151                            return;
152                    }
153    
154                    try {
155                            ManifestSummary manifestSummary =
156                                    portletDataContext.getManifestSummary();
157    
158                            PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
159                                    "stagedModel", stagedModel, manifestSummary);
160    
161                            if (stagedModel instanceof TrashedModel) {
162                                    restoreStagedModel(portletDataContext, stagedModel);
163                            }
164    
165                            doImportStagedModel(portletDataContext, stagedModel);
166    
167                            manifestSummary.incrementModelAdditionCount(
168                                    stagedModel.getStagedModelType());
169    
170                            maintainSessionCache(portletDataContext);
171                    }
172                    catch (PortletDataException pde) {
173                            throw pde;
174                    }
175                    catch (Exception e) {
176                            throw new PortletDataException(e);
177                    }
178            }
179    
180            protected void maintainSessionCache(PortletDataContext portletDataContext) {
181                    ManifestSummary manifestSummary =
182                            portletDataContext.getManifestSummary();
183    
184                    int hibernateCacheFlushFrequency =
185                            STAGING_HIBERNATE_CACHE_FLUSH_FREQUENCY;
186    
187                    if ((manifestSummary.getModelAdditionCount() %
188                                    hibernateCacheFlushFrequency) != 0) {
189    
190                            return;
191                    }
192    
193                    Session session = sessionFactory.getCurrentSession();
194    
195                    session.flush();
196    
197                    session.clear();
198            }
199    
200            @Override
201            public void restoreStagedModel(
202                            PortletDataContext portletDataContext, T stagedModel)
203                    throws PortletDataException {
204    
205                    try {
206                            doRestoreStagedModel(portletDataContext, stagedModel);
207                    }
208                    catch (PortletDataException pde) {
209                            throw pde;
210                    }
211                    catch (Exception e) {
212                            throw new PortletDataException(e);
213                    }
214            }
215    
216            @Override
217            public boolean validateReference(
218                    PortletDataContext portletDataContext, Element referenceElement) {
219    
220                    String uuid = referenceElement.attributeValue("uuid");
221    
222                    try {
223                            boolean valid = validateMissingReference(
224                                    uuid, portletDataContext.getCompanyId(),
225                                    portletDataContext.getScopeGroupId());
226    
227                            if (!valid) {
228                                    valid = validateMissingReference(
229                                            uuid, portletDataContext.getCompanyId(),
230                                            portletDataContext.getCompanyGroupId());
231                            }
232    
233                            return valid;
234                    }
235                    catch (Exception e) {
236                            return false;
237                    }
238            }
239    
240            protected boolean countStagedModel(
241                    PortletDataContext portletDataContext, T stagedModel) {
242    
243                    return !portletDataContext.isStagedModelCounted(stagedModel);
244            }
245    
246            protected abstract void doExportStagedModel(
247                            PortletDataContext portletDataContext, T stagedModel)
248                    throws Exception;
249    
250            protected void doImportCompanyStagedModel(
251                            PortletDataContext portletDataContext, String uuid, long classPK)
252                    throws Exception {
253    
254                    throw new UnsupportedOperationException();
255            }
256    
257            protected abstract void doImportStagedModel(
258                            PortletDataContext portletDataContext, T stagedModel)
259                    throws Exception;
260    
261            protected void doRestoreStagedModel(
262                            PortletDataContext portletDataContext, T stagedModel)
263                    throws Exception {
264    
265                    throw new UnsupportedOperationException();
266            }
267    
268            protected void validateExport(
269                            PortletDataContext portletDataContext, T stagedModel)
270                    throws PortletDataException {
271    
272                    if (stagedModel instanceof WorkflowedModel) {
273                            WorkflowedModel workflowedModel = (WorkflowedModel)stagedModel;
274    
275                            if (!ArrayUtil.contains(
276                                            getExportableStatuses(), workflowedModel.getStatus())) {
277    
278                                    PortletDataException pde = new PortletDataException(
279                                            PortletDataException.STATUS_UNAVAILABLE);
280    
281                                    pde.setStagedModel(stagedModel);
282    
283                                    throw pde;
284                            }
285                    }
286    
287                    if (stagedModel instanceof TrashedModel) {
288                            TrashedModel trashedModel = (TrashedModel)stagedModel;
289    
290                            if (trashedModel.isInTrash()) {
291                                    PortletDataException pde = new PortletDataException(
292                                            PortletDataException.STATUS_IN_TRASH);
293    
294                                    pde.setStagedModel(stagedModel);
295    
296                                    throw pde;
297                            }
298                    }
299            }
300    
301            protected boolean validateMissingReference(
302                            String uuid, long companyId, long groupId)
303                    throws Exception {
304    
305                    return true;
306            }
307    
308            protected final SessionFactory sessionFactory =
309                    (SessionFactory)PortalBeanLocatorUtil.locate("liferaySessionFactory");
310    
311    }