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