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