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