001    /**
002     * Copyright (c) 2000-present 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.repository.capabilities;
016    
017    import com.liferay.portal.exception.NoSuchModelException;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
022    import com.liferay.portal.kernel.repository.DocumentRepository;
023    import com.liferay.portal.kernel.repository.capabilities.BulkOperationCapability;
024    import com.liferay.portal.kernel.repository.capabilities.ConfigurationCapability;
025    import com.liferay.portal.kernel.repository.capabilities.TemporaryFileEntriesCapability;
026    import com.liferay.portal.kernel.repository.capabilities.TemporaryFileEntriesScope;
027    import com.liferay.portal.kernel.repository.model.BaseRepositoryModelOperation;
028    import com.liferay.portal.kernel.repository.model.FileEntry;
029    import com.liferay.portal.kernel.repository.model.Folder;
030    import com.liferay.portal.kernel.util.FileUtil;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.StringUtil;
035    import com.liferay.portal.kernel.workflow.WorkflowConstants;
036    import com.liferay.portal.service.ServiceContext;
037    import com.liferay.portlet.documentlibrary.exception.NoSuchFolderException;
038    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
039    
040    import java.io.File;
041    import java.io.IOException;
042    import java.io.InputStream;
043    
044    import java.util.Collections;
045    import java.util.Date;
046    import java.util.List;
047    
048    /**
049     * @author Iv??n Zaera
050     */
051    public class TemporaryFileEntriesCapabilityImpl
052            implements TemporaryFileEntriesCapability {
053    
054            public TemporaryFileEntriesCapabilityImpl(
055                    DocumentRepository documentRepository) {
056    
057                    _documentRepository = documentRepository;
058            }
059    
060            @Override
061            public FileEntry addTemporaryFileEntry(
062                            TemporaryFileEntriesScope temporaryFileEntriesScope,
063                            String fileName, String mimeType, InputStream inputStream)
064                    throws PortalException {
065    
066                    Folder folder = addTempFolder(temporaryFileEntriesScope);
067    
068                    File file = null;
069    
070                    try {
071                            if (inputStream == null) {
072                                    inputStream = new UnsyncByteArrayInputStream(new byte[0]);
073                            }
074    
075                            file = FileUtil.createTempFile(inputStream);
076    
077                            ServiceContext serviceContext = new ServiceContext();
078    
079                            serviceContext.setAddGroupPermissions(true);
080                            serviceContext.setAddGuestPermissions(true);
081    
082                            return _documentRepository.addFileEntry(
083                                    temporaryFileEntriesScope.getUserId(), folder.getFolderId(),
084                                    fileName, mimeType, fileName, StringPool.BLANK,
085                                    StringPool.BLANK, file, serviceContext);
086                    }
087                    catch (IOException ioe) {
088                            throw new SystemException("Unable to write temporary file", ioe);
089                    }
090                    finally {
091                            FileUtil.delete(file);
092                    }
093            }
094    
095            @Override
096            public void deleteExpiredTemporaryFileEntries() throws PortalException {
097                    BulkOperationCapability bulkOperationCapability =
098                            _documentRepository.getCapability(BulkOperationCapability.class);
099    
100                    BulkOperationCapability.Filter<Date> bulkFilter =
101                            new BulkOperationCapability.Filter<>(
102                                    BulkOperationCapability.Field.CreateDate.class,
103                                    BulkOperationCapability.Operator.LT,
104                                    new Date(
105                                            System.currentTimeMillis() -
106                                                    getTemporaryFileEntriesTimeout()));
107    
108                    bulkOperationCapability.execute(
109                            bulkFilter,
110                            new DeleteExpiredTemporaryFilesRepositoryModelOperation());
111            }
112    
113            @Override
114            public void deleteTemporaryFileEntry(
115                            TemporaryFileEntriesScope temporaryFileEntriesScope,
116                            String fileName)
117                    throws PortalException {
118    
119                    try {
120                            FileEntry fileEntry = getTemporaryFileEntry(
121                                    temporaryFileEntriesScope, fileName);
122    
123                            _documentRepository.deleteFileEntry(fileEntry.getFileEntryId());
124                    }
125                    catch (NoSuchModelException nsme) {
126                    }
127            }
128    
129            @Override
130            public List<FileEntry> getTemporaryFileEntries(
131                            TemporaryFileEntriesScope temporaryFileEntriesScope)
132                    throws PortalException {
133    
134                    try {
135                            Folder folder = addTempFolder(temporaryFileEntriesScope);
136    
137                            return _documentRepository.getRepositoryFileEntries(
138                                    temporaryFileEntriesScope.getUserId(), folder.getFolderId(),
139                                    QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
140                    }
141                    catch (NoSuchModelException nsme) {
142                            return Collections.emptyList();
143                    }
144            }
145    
146            @Override
147            public long getTemporaryFileEntriesTimeout() {
148                    ConfigurationCapability configurationCapability =
149                            _documentRepository.getCapability(ConfigurationCapability.class);
150    
151                    String temporaryFileEntriesTimeout =
152                            configurationCapability.getProperty(
153                                    getClass(), _PROPERTY_TEMPORARY_FILE_ENTRIES_TIMEOUT);
154    
155                    if (temporaryFileEntriesTimeout == null) {
156                            return _TEMPORARY_FILE_ENTRIES_TIMEOUT_DEFAULT;
157                    }
158    
159                    return GetterUtil.getLong(temporaryFileEntriesTimeout);
160            }
161    
162            @Override
163            public FileEntry getTemporaryFileEntry(
164                            TemporaryFileEntriesScope temporaryFileEntriesScope,
165                            String fileName)
166                    throws PortalException {
167    
168                    Folder folder = getTempFolder(temporaryFileEntriesScope);
169    
170                    return _documentRepository.getFileEntry(folder.getFolderId(), fileName);
171            }
172    
173            @Override
174            public void setTemporaryFileEntriesTimeout(
175                    long temporaryFileEntriesTimeout) {
176    
177                    ConfigurationCapability configurationCapability =
178                            _documentRepository.getCapability(ConfigurationCapability.class);
179    
180                    configurationCapability.setProperty(
181                            getClass(), _PROPERTY_TEMPORARY_FILE_ENTRIES_TIMEOUT,
182                            String.valueOf(temporaryFileEntriesTimeout));
183            }
184    
185            protected Folder addFolder(
186                            long userId, long parentFolderId, String folderName,
187                            ServiceContext serviceContext)
188                    throws PortalException {
189    
190                    try {
191                            return _documentRepository.getFolder(parentFolderId, folderName);
192                    }
193                    catch (NoSuchFolderException nsfe) {
194                            return _documentRepository.addFolder(
195                                    userId, parentFolderId, folderName, StringPool.BLANK,
196                                    serviceContext);
197                    }
198            }
199    
200            protected Folder addFolders(
201                            long userId, long folderId, String folderPath,
202                            ServiceContext serviceContext)
203                    throws PortalException {
204    
205                    Folder folder = null;
206    
207                    String[] folderNames = StringUtil.split(folderPath, StringPool.SLASH);
208    
209                    for (String folderName : folderNames) {
210                            folder = addFolder(userId, folderId, folderName, serviceContext);
211    
212                            folderId = folder.getFolderId();
213                    }
214    
215                    return folder;
216            }
217    
218            protected Folder addTempFolder(
219                            TemporaryFileEntriesScope temporaryFileEntriesScope)
220                    throws PortalException {
221    
222                    ServiceContext serviceContext = new ServiceContext();
223    
224                    serviceContext.setAddGroupPermissions(true);
225                    serviceContext.setAddGuestPermissions(true);
226    
227                    return addFolders(
228                            temporaryFileEntriesScope.getUserId(),
229                            DLFolderConstants.DEFAULT_PARENT_FOLDER_ID,
230                            _getFolderPath(temporaryFileEntriesScope), serviceContext);
231            }
232    
233            protected Folder getDeepestFolder(long parentFolderId, String folderPath)
234                    throws PortalException {
235    
236                    Folder folder = null;
237    
238                    String[] folderNames = StringUtil.split(folderPath, StringPool.SLASH);
239    
240                    for (String folderName : folderNames) {
241                            folder = _documentRepository.getFolder(parentFolderId, folderName);
242    
243                            parentFolderId = folder.getFolderId();
244                    }
245    
246                    return folder;
247            }
248    
249            protected Folder getTempFolder(
250                            TemporaryFileEntriesScope temporaryFileEntriesScope)
251                    throws PortalException {
252    
253                    ServiceContext serviceContext = new ServiceContext();
254    
255                    serviceContext.setAddGroupPermissions(true);
256                    serviceContext.setAddGuestPermissions(true);
257    
258                    return getDeepestFolder(
259                            DLFolderConstants.DEFAULT_PARENT_FOLDER_ID,
260                            _getFolderPath(temporaryFileEntriesScope));
261            }
262    
263            private String _getFolderPath(
264                    TemporaryFileEntriesScope temporaryFileEntriesScope) {
265    
266                    StringBundler sb = new StringBundler(7);
267    
268                    sb.append(_FOLDER_NAME_TEMP);
269                    sb.append(StringPool.SLASH);
270                    sb.append(temporaryFileEntriesScope.getCallerUuid());
271                    sb.append(StringPool.SLASH);
272                    sb.append(temporaryFileEntriesScope.getUserId());
273                    sb.append(StringPool.SLASH);
274                    sb.append(temporaryFileEntriesScope.getFolderPath());
275    
276                    return sb.toString();
277            }
278    
279            private static final String _FOLDER_NAME_TEMP = "temp";
280    
281            private static final String _PROPERTY_TEMPORARY_FILE_ENTRIES_TIMEOUT =
282                    "temporaryFilesTimeout";
283    
284            private static final long _TEMPORARY_FILE_ENTRIES_TIMEOUT_DEFAULT =
285                    12 * 60 * 60 * 1000;
286    
287            private final DocumentRepository _documentRepository;
288    
289            private class DeleteExpiredTemporaryFilesRepositoryModelOperation
290                    extends BaseRepositoryModelOperation {
291    
292                    @Override
293                    public void execute(FileEntry fileEntry) throws PortalException {
294                            Folder folder = fileEntry.getFolder();
295    
296                            _documentRepository.deleteFileEntry(fileEntry.getFileEntryId());
297    
298                            Folder mountFolder = _documentRepository.getFolder(
299                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
300    
301                            while ((folder.getFolderId() != mountFolder.getFolderId()) &&
302                                       (_documentRepository.getFileEntriesCount(
303                                               folder.getFolderId(),
304                                               WorkflowConstants.STATUS_ANY) == 0)) {
305    
306                                    long folderId = folder.getFolderId();
307    
308                                    folder = folder.getParentFolder();
309    
310                                    _documentRepository.deleteFolder(folderId);
311                            }
312                    }
313    
314            }
315    
316    }