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.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
020    import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
021    import com.liferay.portal.kernel.lar.MissingReferences;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.repository.model.FileEntry;
025    import com.liferay.portal.kernel.repository.model.Folder;
026    import com.liferay.portal.kernel.util.ContentTypes;
027    import com.liferay.portal.kernel.util.FileUtil;
028    import com.liferay.portal.kernel.util.StreamUtil;
029    import com.liferay.portal.model.Group;
030    import com.liferay.portal.model.Repository;
031    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
032    import com.liferay.portal.service.ServiceContext;
033    import com.liferay.portal.service.base.StagingLocalServiceBaseImpl;
034    import com.liferay.portal.util.PortletKeys;
035    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
036    import com.liferay.portlet.documentlibrary.NoSuchFolderException;
037    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
038    
039    import java.io.File;
040    import java.io.FileOutputStream;
041    import java.io.IOException;
042    import java.io.InputStream;
043    
044    import java.util.List;
045    import java.util.Map;
046    
047    /**
048     * @author Michael C. Han
049     * @author Mate Thurzo
050     */
051    public class StagingLocalServiceImpl extends StagingLocalServiceBaseImpl {
052    
053            @Override
054            public void cleanUpStagingRequest(long stagingRequestId)
055                    throws PortalException, SystemException {
056    
057                    try {
058                            PortletFileRepositoryUtil.deleteFolder(stagingRequestId);
059                    }
060                    catch (NoSuchFolderException nsfe) {
061                            if (_log.isDebugEnabled()) {
062                                    _log.debug(
063                                            "Unable to clean up staging request " + stagingRequestId,
064                                            nsfe);
065                            }
066                    }
067            }
068    
069            @Override
070            public long createStagingRequest(long userId, long groupId, String checksum)
071                    throws PortalException, SystemException {
072    
073                    ServiceContext serviceContext = new ServiceContext();
074    
075                    Repository repository = PortletFileRepositoryUtil.addPortletRepository(
076                            groupId, PortletKeys.SITES_ADMIN, serviceContext);
077    
078                    Folder folder = PortletFileRepositoryUtil.addPortletFolder(
079                            userId, repository.getRepositoryId(),
080                            DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, checksum,
081                            serviceContext);
082    
083                    return folder.getFolderId();
084            }
085    
086            @Override
087            public void publishStagingRequest(
088                            long userId, long stagingRequestId, boolean privateLayout,
089                            Map<String, String[]> parameterMap)
090                    throws PortalException, SystemException {
091    
092                    try {
093                            ExportImportThreadLocal.setLayoutImportInProcess(true);
094    
095                            Folder folder = PortletFileRepositoryUtil.getPortletFolder(
096                                    stagingRequestId);
097    
098                            FileEntry stagingRequestFileEntry = getStagingRequestFileEntry(
099                                    userId, stagingRequestId, folder);
100    
101                            layoutLocalService.importLayouts(
102                                    userId, folder.getGroupId(), privateLayout, parameterMap,
103                                    stagingRequestFileEntry.getContentStream());
104                    }
105                    finally {
106                            ExportImportThreadLocal.setLayoutImportInProcess(false);
107                    }
108            }
109    
110            @Override
111            public void updateStagingRequest(
112                            long userId, long stagingRequestId, String fileName, byte[] bytes)
113                    throws PortalException, SystemException {
114    
115                    Folder folder = PortletFileRepositoryUtil.getPortletFolder(
116                            stagingRequestId);
117    
118                    fileName += PortletFileRepositoryUtil.getPortletFileEntriesCount(
119                            folder.getGroupId(), folder.getFolderId());
120    
121                    PortletFileRepositoryUtil.addPortletFileEntry(
122                            folder.getGroupId(), userId, Group.class.getName(),
123                            folder.getGroupId(), PortletKeys.SITES_ADMIN, folder.getFolderId(),
124                            new UnsyncByteArrayInputStream(bytes), fileName,
125                            ContentTypes.APPLICATION_ZIP, false);
126            }
127    
128            @Override
129            public MissingReferences validateStagingRequest(
130                            long userId, long stagingRequestId, boolean privateLayout,
131                            Map<String, String[]> parameterMap)
132                    throws PortalException, SystemException {
133    
134                    try {
135                            ExportImportThreadLocal.setLayoutValidationInProcess(true);
136    
137                            Folder folder = PortletFileRepositoryUtil.getPortletFolder(
138                                    stagingRequestId);
139    
140                            FileEntry fileEntry = getStagingRequestFileEntry(
141                                    userId, stagingRequestId, folder);
142    
143                            return layoutLocalService.validateImportLayoutsFile(
144                                    userId, folder.getGroupId(), privateLayout, parameterMap,
145                                    fileEntry.getContentStream());
146                    }
147                    finally {
148                            ExportImportThreadLocal.setLayoutValidationInProcess(false);
149                    }
150            }
151    
152            protected FileEntry fetchStagingRequestFileEntry(
153                            long stagingRequestId, Folder folder)
154                    throws PortalException, SystemException {
155    
156                    try {
157                            return PortletFileRepositoryUtil.getPortletFileEntry(
158                                    folder.getGroupId(), folder.getFolderId(),
159                                    getAssembledFileName(stagingRequestId));
160                    }
161                    catch (NoSuchFileEntryException nsfe) {
162                            return null;
163                    }
164            }
165    
166            protected String getAssembledFileName(long stagingRequestId) {
167                    return _ASSEMBLED_LAR_PREFIX + String.valueOf(stagingRequestId) +
168                            ".lar";
169            }
170    
171            protected FileEntry getStagingRequestFileEntry(
172                            long userId, long stagingRequestId, Folder folder)
173                    throws PortalException, SystemException {
174    
175                    FileEntry stagingRequestFileEntry = fetchStagingRequestFileEntry(
176                            stagingRequestId, folder);
177    
178                    if (stagingRequestFileEntry != null) {
179                            return stagingRequestFileEntry;
180                    }
181    
182                    FileOutputStream fileOutputStream = null;
183    
184                    File tempFile = null;
185    
186                    try {
187                            tempFile = FileUtil.createTempFile("lar");
188    
189                            fileOutputStream = new FileOutputStream(tempFile);
190    
191                            List<FileEntry> fileEntries =
192                                    PortletFileRepositoryUtil.getPortletFileEntries(
193                                            folder.getGroupId(), folder.getFolderId());
194    
195                            for (FileEntry fileEntry : fileEntries) {
196                                    InputStream inputStream = fileEntry.getContentStream();
197    
198                                    try {
199                                            StreamUtil.transfer(inputStream, fileOutputStream, false);
200                                    }
201                                    finally {
202                                            StreamUtil.cleanUp(inputStream);
203    
204                                            PortletFileRepositoryUtil.deletePortletFileEntry(
205                                                    fileEntry.getFileEntryId());
206                                    }
207                            }
208    
209                            String checksum = FileUtil.getMD5Checksum(tempFile);
210    
211                            if (!checksum.equals(folder.getName())) {
212                                    throw new SystemException("Invalid checksum for LAR file");
213                            }
214    
215                            PortletFileRepositoryUtil.addPortletFileEntry(
216                                    folder.getGroupId(), userId, Group.class.getName(),
217                                    folder.getGroupId(), PortletKeys.SITES_ADMIN,
218                                    folder.getFolderId(), tempFile,
219                                    getAssembledFileName(stagingRequestId),
220                                    ContentTypes.APPLICATION_ZIP, false);
221    
222                            stagingRequestFileEntry = fetchStagingRequestFileEntry(
223                                    stagingRequestId, folder);
224    
225                            if (stagingRequestFileEntry == null) {
226                                    throw new SystemException("Unable to assemble LAR file");
227                            }
228    
229                            return stagingRequestFileEntry;
230                    }
231                    catch (IOException ioe) {
232                            throw new SystemException("Unable to reassemble LAR file", ioe);
233                    }
234                    finally {
235                            StreamUtil.cleanUp(fileOutputStream);
236    
237                            FileUtil.delete(tempFile);
238                    }
239            }
240    
241            private static final String _ASSEMBLED_LAR_PREFIX = "assembled_";
242    
243            private static Log _log = LogFactoryUtil.getLog(
244                    StagingLocalServiceImpl.class);
245    
246    }