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.portlet.layoutsadmin.action;
016    
017    import com.liferay.portal.LARFileException;
018    import com.liferay.portal.LARFileSizeException;
019    import com.liferay.portal.LARTypeException;
020    import com.liferay.portal.LayoutImportException;
021    import com.liferay.portal.LayoutPrototypeException;
022    import com.liferay.portal.LocaleException;
023    import com.liferay.portal.NoSuchGroupException;
024    import com.liferay.portal.kernel.exception.PortalException;
025    import com.liferay.portal.kernel.exception.SystemException;
026    import com.liferay.portal.kernel.json.JSONFactoryUtil;
027    import com.liferay.portal.kernel.json.JSONObject;
028    import com.liferay.portal.kernel.lar.ExportImportHelper;
029    import com.liferay.portal.kernel.lar.ExportImportHelperUtil;
030    import com.liferay.portal.kernel.lar.MissingReference;
031    import com.liferay.portal.kernel.lar.MissingReferences;
032    import com.liferay.portal.kernel.log.Log;
033    import com.liferay.portal.kernel.log.LogFactoryUtil;
034    import com.liferay.portal.kernel.repository.model.FileEntry;
035    import com.liferay.portal.kernel.servlet.ServletResponseUtil;
036    import com.liferay.portal.kernel.servlet.SessionErrors;
037    import com.liferay.portal.kernel.staging.StagingUtil;
038    import com.liferay.portal.kernel.upload.UploadException;
039    import com.liferay.portal.kernel.upload.UploadPortletRequest;
040    import com.liferay.portal.kernel.util.Constants;
041    import com.liferay.portal.kernel.util.ContentTypes;
042    import com.liferay.portal.kernel.util.FileUtil;
043    import com.liferay.portal.kernel.util.ParamUtil;
044    import com.liferay.portal.kernel.util.StreamUtil;
045    import com.liferay.portal.kernel.util.StringUtil;
046    import com.liferay.portal.security.auth.PrincipalException;
047    import com.liferay.portal.service.LayoutServiceUtil;
048    import com.liferay.portal.struts.PortletAction;
049    import com.liferay.portal.theme.ThemeDisplay;
050    import com.liferay.portal.util.PortalUtil;
051    import com.liferay.portal.util.WebKeys;
052    import com.liferay.portlet.documentlibrary.FileSizeException;
053    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
054    import com.liferay.portlet.sites.action.ActionUtil;
055    
056    import java.io.File;
057    import java.io.InputStream;
058    
059    import java.util.Map;
060    
061    import javax.portlet.ActionRequest;
062    import javax.portlet.ActionResponse;
063    import javax.portlet.PortletConfig;
064    import javax.portlet.PortletContext;
065    import javax.portlet.PortletRequestDispatcher;
066    import javax.portlet.RenderRequest;
067    import javax.portlet.RenderResponse;
068    import javax.portlet.ResourceRequest;
069    import javax.portlet.ResourceResponse;
070    
071    import javax.servlet.http.HttpServletRequest;
072    import javax.servlet.http.HttpServletResponse;
073    
074    import org.apache.commons.fileupload.FileUploadBase;
075    import org.apache.struts.action.ActionForm;
076    import org.apache.struts.action.ActionForward;
077    import org.apache.struts.action.ActionMapping;
078    
079    /**
080     * @author Alexander Chow
081     * @author Raymond Aug??
082     */
083    public class ImportLayoutsAction extends PortletAction {
084    
085            @Override
086            public void processAction(
087                            ActionMapping actionMapping, ActionForm actionForm,
088                            PortletConfig portletConfig, ActionRequest actionRequest,
089                            ActionResponse actionResponse)
090                    throws Exception {
091    
092                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
093    
094                    try {
095                            if (cmd.equals(Constants.ADD_TEMP)) {
096                                    addTempFileEntry(
097                                            actionRequest, actionResponse,
098                                            ExportImportHelper.TEMP_FOLDER_NAME);
099    
100                                    validateFile(
101                                            actionRequest, actionResponse,
102                                            ExportImportHelper.TEMP_FOLDER_NAME);
103                            }
104                            else if (cmd.equals(Constants.DELETE_TEMP)) {
105                                    deleteTempFileEntry(
106                                            actionRequest, actionResponse,
107                                            ExportImportHelper.TEMP_FOLDER_NAME);
108                            }
109                            else if (cmd.equals(Constants.IMPORT)) {
110                                    importData(
111                                            actionRequest, actionResponse,
112                                            ExportImportHelper.TEMP_FOLDER_NAME);
113    
114                                    String redirect = ParamUtil.getString(
115                                            actionRequest, "redirect");
116    
117                                    sendRedirect(actionRequest, actionResponse, redirect);
118                            }
119                    }
120                    catch (Exception e) {
121                            if (cmd.equals(Constants.ADD_TEMP) ||
122                                    cmd.equals(Constants.DELETE_TEMP)) {
123    
124                                    handleUploadException(
125                                            portletConfig, actionRequest, actionResponse,
126                                            ExportImportHelper.TEMP_FOLDER_NAME, e);
127                            }
128                            else {
129                                    if ((e instanceof LARFileException) ||
130                                            (e instanceof LARFileSizeException) ||
131                                            (e instanceof LARTypeException)) {
132    
133                                            SessionErrors.add(actionRequest, e.getClass());
134                                    }
135                                    else if ((e instanceof LayoutPrototypeException) ||
136                                                     (e instanceof LocaleException)) {
137    
138                                            SessionErrors.add(actionRequest, e.getClass(), e);
139                                    }
140                                    else {
141                                            _log.error(e, e);
142    
143                                            SessionErrors.add(
144                                                    actionRequest, LayoutImportException.class.getName());
145                                    }
146                            }
147                    }
148            }
149    
150            @Override
151            public ActionForward render(
152                            ActionMapping actionMapping, ActionForm actionForm,
153                            PortletConfig portletConfig, RenderRequest renderRequest,
154                            RenderResponse renderResponse)
155                    throws Exception {
156    
157                    try {
158                            ActionUtil.getGroup(renderRequest);
159                    }
160                    catch (Exception e) {
161                            if (e instanceof NoSuchGroupException ||
162                                    e instanceof PrincipalException) {
163    
164                                    SessionErrors.add(renderRequest, e.getClass());
165    
166                                    return actionMapping.findForward("portlet.layouts_admin.error");
167                            }
168                            else {
169                                    throw e;
170                            }
171                    }
172    
173                    return actionMapping.findForward(
174                            getForward(renderRequest, "portlet.layouts_admin.import_layouts"));
175            }
176    
177            @Override
178            public void serveResource(
179                            ActionMapping actionMapping, ActionForm actionForm,
180                            PortletConfig portletConfig, ResourceRequest resourceRequest,
181                            ResourceResponse resourceResponse)
182                    throws Exception {
183    
184                    String cmd = ParamUtil.getString(resourceRequest, Constants.CMD);
185    
186                    PortletContext portletContext = portletConfig.getPortletContext();
187    
188                    PortletRequestDispatcher portletRequestDispatcher = null;
189    
190                    if (cmd.equals(Constants.IMPORT)) {
191                            portletRequestDispatcher = portletContext.getRequestDispatcher(
192                                    "/html/portlet/layouts_admin/import_layouts_processes.jsp");
193                    }
194                    else {
195                            portletRequestDispatcher = portletContext.getRequestDispatcher(
196                                    "/html/portlet/layouts_admin/import_layouts_resources.jsp");
197                    }
198    
199                    portletRequestDispatcher.include(resourceRequest, resourceResponse);
200            }
201    
202            protected void addTempFileEntry(
203                            ActionRequest actionRequest, ActionResponse actionResponse,
204                            String folderName)
205                    throws Exception {
206    
207                    UploadPortletRequest uploadPortletRequest =
208                            PortalUtil.getUploadPortletRequest(actionRequest);
209    
210                    checkExceededSizeLimit(uploadPortletRequest);
211    
212                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
213    
214                    deleteTempFileEntry(groupId, folderName);
215    
216                    InputStream inputStream = null;
217    
218                    try {
219                            String sourceFileName = uploadPortletRequest.getFileName("file");
220    
221                            inputStream = uploadPortletRequest.getFileAsStream("file");
222    
223                            String contentType = uploadPortletRequest.getContentType("file");
224    
225                            LayoutServiceUtil.addTempFileEntry(
226                                    groupId, sourceFileName, folderName, inputStream, contentType);
227                    }
228                    catch (Exception e) {
229                            UploadException uploadException =
230                                    (UploadException)actionRequest.getAttribute(
231                                            WebKeys.UPLOAD_EXCEPTION);
232    
233                            if ((uploadException != null) &&
234                                    (uploadException.getCause()
235                                            instanceof FileUploadBase.IOFileUploadException)) {
236    
237                                    // Cancelled a temporary upload
238    
239                            }
240                            else if ((uploadException != null) &&
241                                             uploadException.isExceededSizeLimit()) {
242    
243                                    throw new FileSizeException(uploadException.getCause());
244                            }
245                            else {
246                                    throw e;
247                            }
248                    }
249                    finally {
250                            StreamUtil.cleanUp(inputStream);
251                    }
252            }
253    
254            protected void checkExceededSizeLimit(HttpServletRequest request)
255                    throws PortalException {
256    
257                    UploadException uploadException = (UploadException)request.getAttribute(
258                            WebKeys.UPLOAD_EXCEPTION);
259    
260                    if (uploadException != null) {
261                            if (uploadException.isExceededSizeLimit()) {
262                                    throw new LARFileSizeException(uploadException.getCause());
263                            }
264    
265                            throw new PortalException(uploadException.getCause());
266                    }
267            }
268    
269            protected void deleteTempFileEntry(
270                            ActionRequest actionRequest, ActionResponse actionResponse,
271                            String folderName)
272                    throws Exception {
273    
274                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
275                            WebKeys.THEME_DISPLAY);
276    
277                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
278    
279                    try {
280                            String fileName = ParamUtil.getString(actionRequest, "fileName");
281    
282                            LayoutServiceUtil.deleteTempFileEntry(
283                                    themeDisplay.getScopeGroupId(), fileName, folderName);
284    
285                            jsonObject.put("deleted", Boolean.TRUE);
286                    }
287                    catch (Exception e) {
288                            String errorMessage = themeDisplay.translate(
289                                    "an-unexpected-error-occurred-while-deleting-the-file");
290    
291                            jsonObject.put("deleted", Boolean.FALSE);
292                            jsonObject.put("errorMessage", errorMessage);
293                    }
294    
295                    writeJSON(actionRequest, actionResponse, jsonObject);
296            }
297    
298            protected void deleteTempFileEntry(long groupId, String folderName)
299                    throws PortalException, SystemException {
300    
301                    String[] tempFileEntryNames = LayoutServiceUtil.getTempFileEntryNames(
302                            groupId, folderName);
303    
304                    for (String tempFileEntryName : tempFileEntryNames) {
305                            LayoutServiceUtil.deleteTempFileEntry(
306                                    groupId, tempFileEntryName, folderName);
307                    }
308            }
309    
310            protected void handleUploadException(
311                            PortletConfig portletConfig, ActionRequest actionRequest,
312                            ActionResponse actionResponse, String folderName, Exception e)
313                    throws Exception {
314    
315                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
316                            actionResponse);
317    
318                    response.setContentType(ContentTypes.TEXT_HTML);
319                    response.setStatus(HttpServletResponse.SC_OK);
320    
321                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
322                            WebKeys.THEME_DISPLAY);
323    
324                    deleteTempFileEntry(themeDisplay.getScopeGroupId(), folderName);
325    
326                    JSONObject jsonObject = StagingUtil.getExceptionMessagesJSONObject(
327                            themeDisplay.getLocale(), e, null);
328    
329                    writeJSON(actionRequest, actionResponse, jsonObject);
330    
331                    ServletResponseUtil.write(
332                            response, String.valueOf(jsonObject.getInt("status")));
333            }
334    
335            protected void importData(
336                            ActionRequest actionRequest, ActionResponse actionResponse,
337                            String folderName)
338                    throws Exception {
339    
340                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
341                            WebKeys.THEME_DISPLAY);
342    
343                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
344    
345                    FileEntry fileEntry = ExportImportHelperUtil.getTempFileEntry(
346                            groupId, themeDisplay.getUserId(), folderName);
347    
348                    File file = DLFileEntryLocalServiceUtil.getFile(
349                            themeDisplay.getUserId(), fileEntry.getFileEntryId(),
350                            fileEntry.getVersion(), false);
351    
352                    if ((file == null) || !file.exists()) {
353                            throw new LARFileException("Import file does not exist");
354                    }
355    
356                    boolean successfulRename = false;
357    
358                    File newFile = null;
359    
360                    try {
361                            String newFileName = StringUtil.replace(
362                                    file.getPath(), file.getName(), fileEntry.getTitle());
363    
364                            newFile = new File(newFileName);
365    
366                            successfulRename = file.renameTo(newFile);
367    
368                            if (!successfulRename) {
369                                    newFile = FileUtil.createTempFile(fileEntry.getExtension());
370    
371                                    FileUtil.copyFile(file, newFile);
372                            }
373    
374                            importData(actionRequest, newFile);
375    
376                            deleteTempFileEntry(groupId, folderName);
377    
378                            addSuccessMessage(actionRequest, actionResponse);
379                    }
380                    finally {
381                            if (successfulRename) {
382                                    successfulRename = newFile.renameTo(file);
383    
384                                    if (!successfulRename) {
385                                            FileUtil.copyFile(newFile, file);
386    
387                                            FileUtil.delete(newFile);
388                                    }
389                            }
390                            else {
391                                    FileUtil.delete(newFile);
392                            }
393                    }
394            }
395    
396            protected void importData(ActionRequest actionRequest, File file)
397                    throws Exception {
398    
399                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
400                    boolean privateLayout = ParamUtil.getBoolean(
401                            actionRequest, "privateLayout");
402    
403                    LayoutServiceUtil.importLayoutsInBackground(
404                            file.getName(), groupId, privateLayout,
405                            actionRequest.getParameterMap(), file);
406            }
407    
408            protected void validateFile(
409                            ActionRequest actionRequest, ActionResponse actionResponse,
410                            String folderName)
411                    throws Exception {
412    
413                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
414                            WebKeys.THEME_DISPLAY);
415    
416                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
417    
418                    FileEntry fileEntry = ExportImportHelperUtil.getTempFileEntry(
419                            groupId, themeDisplay.getUserId(), folderName);
420    
421                    File file = DLFileEntryLocalServiceUtil.getFile(
422                            themeDisplay.getUserId(), fileEntry.getFileEntryId(),
423                            fileEntry.getVersion(), false);
424    
425                    if ((file == null) || !file.exists()) {
426                            throw new LARFileException("Import file does not exist");
427                    }
428    
429                    boolean successfulRename = false;
430    
431                    File newFile = null;
432    
433                    try {
434                            String newFileName = StringUtil.replace(
435                                    file.getPath(), file.getName(), fileEntry.getTitle());
436    
437                            newFile = new File(newFileName);
438    
439                            successfulRename = file.renameTo(newFile);
440    
441                            if (!successfulRename) {
442                                    newFile = FileUtil.createTempFile(fileEntry.getExtension());
443    
444                                    FileUtil.copyFile(file, newFile);
445                            }
446    
447                            MissingReferences missingReferences = validateFile(
448                                    actionRequest, newFile);
449    
450                            Map<String, MissingReference> weakMissingReferences =
451                                    missingReferences.getWeakMissingReferences();
452    
453                            if (weakMissingReferences.isEmpty()) {
454                                    return;
455                            }
456    
457                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
458    
459                            if ((weakMissingReferences != null) &&
460                                    (weakMissingReferences.size() > 0)) {
461    
462                                    jsonObject.put(
463                                            "warningMessages",
464                                            StagingUtil.getWarningMessagesJSONArray(
465                                                    themeDisplay.getLocale(), weakMissingReferences, null));
466                            }
467    
468                            writeJSON(actionRequest, actionResponse, jsonObject);
469                    }
470                    finally {
471                            if (successfulRename) {
472                                    successfulRename = newFile.renameTo(file);
473    
474                                    if (!successfulRename) {
475                                            FileUtil.copyFile(newFile, file);
476    
477                                            FileUtil.delete(newFile);
478                                    }
479                            }
480                            else {
481                                    FileUtil.delete(newFile);
482                            }
483                    }
484            }
485    
486            protected MissingReferences validateFile(
487                            ActionRequest actionRequest, File file)
488                    throws Exception {
489    
490                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
491                    boolean privateLayout = ParamUtil.getBoolean(
492                            actionRequest, "privateLayout");
493    
494                    return LayoutServiceUtil.validateImportLayoutsFile(
495                            groupId, privateLayout, actionRequest.getParameterMap(), file);
496            }
497    
498            private static Log _log = LogFactoryUtil.getLog(ImportLayoutsAction.class);
499    
500    }