001    /**
002     * Copyright (c) 2000-2011 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.portlet.documentlibrary.store;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.util.FileUtil;
020    import com.liferay.portal.kernel.util.StringPool;
021    import com.liferay.portal.kernel.util.Validator;
022    import com.liferay.portal.util.PropsValues;
023    import com.liferay.portlet.documentlibrary.DuplicateDirectoryException;
024    import com.liferay.portlet.documentlibrary.DuplicateFileException;
025    import com.liferay.portlet.documentlibrary.NoSuchDirectoryException;
026    import com.liferay.portlet.documentlibrary.NoSuchFileException;
027    import com.liferay.portlet.documentlibrary.util.DLUtil;
028    
029    import java.io.File;
030    import java.io.FileInputStream;
031    import java.io.FileNotFoundException;
032    import java.io.IOException;
033    import java.io.InputStream;
034    
035    import java.util.Arrays;
036    import java.util.Map;
037    import java.util.concurrent.ConcurrentHashMap;
038    
039    /**
040     * @author Brian Wing Shun Chan
041     * @author Sten Martinez
042     * @author Alexander Chow
043     * @author Edward Han
044     */
045    public class FileSystemStore extends BaseStore {
046    
047            public FileSystemStore() {
048                    if (!_rootDir.exists()) {
049                            _rootDir.mkdirs();
050                    }
051            }
052    
053            @Override
054            public void addDirectory(long companyId, long repositoryId, String dirName)
055                    throws PortalException {
056    
057                    File dirNameDir = getDirNameDir(companyId, repositoryId, dirName);
058    
059                    if (dirNameDir.exists()) {
060                            throw new DuplicateDirectoryException(dirNameDir.getPath());
061                    }
062    
063                    dirNameDir.mkdirs();
064            }
065    
066            @Override
067            public void addFile(
068                            long companyId, long repositoryId, String fileName, InputStream is)
069                    throws PortalException, SystemException {
070    
071                    try {
072                            File fileNameVersionFile = getFileNameVersionFile(
073                                    companyId, repositoryId, fileName, VERSION_DEFAULT);
074    
075                            if (fileNameVersionFile.exists()) {
076                                    throw new DuplicateFileException(fileNameVersionFile.getPath());
077                            }
078    
079                            FileUtil.write(fileNameVersionFile, is);
080                    }
081                    catch (IOException ioe) {
082                            throw new SystemException(ioe);
083                    }
084            }
085    
086            @Override
087            public void checkRoot(long companyId) {
088            }
089    
090            @Override
091            public void copyFileVersion(
092                            long companyId, long repositoryId, String fileName,
093                            String fromVersionLabel, String toVersionLabel)
094                    throws PortalException, SystemException {
095    
096                    File fromFileNameVersionFile = getFileNameVersionFile(
097                            companyId, repositoryId, fileName, fromVersionLabel);
098    
099                    File toFileNameVersionFile = getFileNameVersionFile(
100                            companyId, repositoryId, fileName, toVersionLabel);
101    
102                    if (toFileNameVersionFile.exists()) {
103                            throw new DuplicateFileException(toFileNameVersionFile.getPath());
104                    }
105    
106                    try {
107                            toFileNameVersionFile.createNewFile();
108    
109                            FileUtil.copyFile(fromFileNameVersionFile, toFileNameVersionFile);
110                    }
111                    catch (IOException ioe) {
112                            throw new SystemException(ioe);
113                    }
114            }
115    
116            @Override
117            public void deleteDirectory(
118                            long companyId, long repositoryId, String dirName)
119                    throws PortalException {
120    
121                    File dirNameDir = getDirNameDir(companyId, repositoryId, dirName);
122    
123                    if (!dirNameDir.exists()) {
124                            throw new NoSuchDirectoryException(dirNameDir.getPath());
125                    }
126    
127                    File parentFile = dirNameDir.getParentFile();
128    
129                    FileUtil.deltree(dirNameDir);
130    
131                    deleteEmptyAncestors(parentFile);
132            }
133    
134            @Override
135            public void deleteFile(long companyId, long repositoryId, String fileName)
136                    throws PortalException {
137    
138                    File fileNameDir = getFileNameDir(companyId, repositoryId, fileName);
139    
140                    if (!fileNameDir.exists()) {
141                            throw new NoSuchFileException(fileNameDir.getPath());
142                    }
143    
144                    File parentFile = fileNameDir.getParentFile();
145    
146                    FileUtil.deltree(fileNameDir);
147    
148                    deleteEmptyAncestors(parentFile);
149            }
150    
151            @Override
152            public void deleteFile(
153                            long companyId, long repositoryId, String fileName,
154                            String versionLabel)
155                    throws PortalException {
156    
157                    File fileNameVersionFile = getFileNameVersionFile(
158                            companyId, repositoryId, fileName, versionLabel);
159    
160                    if (!fileNameVersionFile.exists()) {
161                            throw new NoSuchFileException(fileNameVersionFile.getPath());
162                    }
163    
164                    File parentFile = fileNameVersionFile.getParentFile();
165    
166                    fileNameVersionFile.delete();
167    
168                    deleteEmptyAncestors(parentFile);
169            }
170    
171            @Override
172            public File getFile(
173                            long companyId, long repositoryId, String fileName,
174                            String versionLabel)
175                    throws PortalException {
176    
177                    if (Validator.isNull(versionLabel)) {
178                            versionLabel = getHeadVersionLabel(
179                                    companyId, repositoryId, fileName);
180                    }
181    
182                    File fileNameVersionFile = getFileNameVersionFile(
183                            companyId, repositoryId, fileName, versionLabel);
184    
185                    if (!fileNameVersionFile.exists()) {
186                            throw new NoSuchFileException(fileNameVersionFile.getPath());
187                    }
188    
189                    return fileNameVersionFile;
190            }
191    
192            @Override
193            public InputStream getFileAsStream(
194                            long companyId, long repositoryId, String fileName,
195                            String versionLabel)
196                    throws PortalException {
197    
198                    if (Validator.isNull(versionLabel)) {
199                            versionLabel = getHeadVersionLabel(
200                                    companyId, repositoryId, fileName);
201                    }
202    
203                    File fileNameVersionFile = getFileNameVersionFile(
204                            companyId, repositoryId, fileName, versionLabel);
205    
206                    try {
207                            return new FileInputStream(fileNameVersionFile);
208                    }
209                    catch (FileNotFoundException fnfe) {
210                            throw new NoSuchFileException(fileNameVersionFile.getPath(), fnfe);
211                    }
212            }
213    
214            public String[] getFileNames(long companyId, long repositoryId) {
215                    File repositoryDir = getRepositoryDir(companyId, repositoryId);
216    
217                    return FileUtil.listDirs(repositoryDir);
218            }
219    
220            @Override
221            public String[] getFileNames(
222                            long companyId, long repositoryId, String dirName)
223                    throws PortalException {
224    
225                    File dirNameDir = getDirNameDir(companyId, repositoryId, dirName);
226    
227                    if (!dirNameDir.exists()) {
228                            throw new NoSuchDirectoryException(dirNameDir.getPath());
229                    }
230    
231                    String[] fileNames = FileUtil.listDirs(dirNameDir);
232    
233                    Arrays.sort(fileNames);
234    
235                    // Convert /${fileName} to /${dirName}/${fileName}
236    
237                    for (int i = 0; i < fileNames.length; i++) {
238                            fileNames[i] =
239                                    StringPool.SLASH + dirName + StringPool.SLASH + fileNames[i];
240                    }
241    
242                    return fileNames;
243            }
244    
245            @Override
246            public long getFileSize(long companyId, long repositoryId, String fileName)
247                    throws PortalException {
248    
249                    String versionLabel = getHeadVersionLabel(
250                            companyId, repositoryId, fileName);
251    
252                    File fileNameVersionFile = getFileNameVersionFile(
253                            companyId, repositoryId, fileName, versionLabel);
254    
255                    if (!fileNameVersionFile.exists()) {
256                            throw new NoSuchFileException(fileNameVersionFile.getPath());
257                    }
258    
259                    return fileNameVersionFile.length();
260            }
261    
262            @Override
263            public boolean hasDirectory(
264                    long companyId, long repositoryId, String dirName) {
265    
266                    File dirNameDir = getDirNameDir(companyId, repositoryId, dirName);
267    
268                    return dirNameDir.exists();
269            }
270    
271            @Override
272            public boolean hasFile(
273                    long companyId, long repositoryId, String fileName,
274                    String versionLabel) {
275    
276                    File fileNameVersionFile = getFileNameVersionFile(
277                            companyId, repositoryId, fileName, versionLabel);
278    
279                    if (fileNameVersionFile.exists()) {
280                            return true;
281                    }
282                    else {
283                            return false;
284                    }
285            }
286    
287            @Override
288            public void move(String srcDir, String destDir) {
289            }
290    
291            @Override
292            public void updateFile(
293                            long companyId, long repositoryId, long newRepositoryId,
294                            String fileName)
295                    throws SystemException {
296    
297                    try {
298                            File fileNameDir = getFileNameDir(
299                                    companyId, repositoryId, fileName);
300                            File newFileNameDir = getFileNameDir(
301                                    companyId, newRepositoryId, fileName);
302    
303                            FileUtil.copyDirectory(fileNameDir, newFileNameDir);
304    
305                            File parentFile = fileNameDir.getParentFile();
306    
307                            FileUtil.deltree(fileNameDir);
308    
309                            deleteEmptyAncestors(parentFile);
310                    }
311                    catch (IOException ioe) {
312                            throw new SystemException(ioe);
313                    }
314            }
315    
316            public void updateFile(
317                            long companyId, long repositoryId, String fileName,
318                            String newFileName)
319                    throws SystemException {
320    
321                    try {
322                            File fileNameDir = getFileNameDir(
323                                    companyId, repositoryId, fileName);
324                            File newFileNameDir = getFileNameDir(
325                                    companyId, repositoryId, newFileName);
326    
327                            FileUtil.copyDirectory(fileNameDir, newFileNameDir);
328    
329                            File parentFile = fileNameDir.getParentFile();
330    
331                            FileUtil.deltree(fileNameDir);
332    
333                            deleteEmptyAncestors(parentFile);
334                    }
335                    catch (IOException ioe) {
336                            throw new SystemException(ioe);
337                    }
338            }
339    
340            @Override
341            public void updateFile(
342                            long companyId, long repositoryId, String fileName,
343                            String versionLabel, InputStream is)
344                    throws PortalException, SystemException {
345    
346                    try {
347                            File fileNameVersionFile = getFileNameVersionFile(
348                                    companyId, repositoryId, fileName, versionLabel);
349    
350                            if (fileNameVersionFile.exists()) {
351                                    throw new DuplicateFileException(fileNameVersionFile.getPath());
352                            }
353    
354                            FileUtil.write(fileNameVersionFile, is);
355                    }
356                    catch (IOException ioe) {
357                            throw new SystemException(ioe);
358                    }
359            }
360    
361            @Override
362            public void updateFileVersion(
363                            long companyId, long repositoryId, String fileName,
364                            String fromVersionLabel, String toVersionLabel)
365                    throws PortalException {
366    
367                    File fromFileNameVersionFile = getFileNameVersionFile(
368                            companyId, repositoryId, fileName, fromVersionLabel);
369    
370                    File toFileNameVersionFile = getFileNameVersionFile(
371                            companyId, repositoryId, fileName, toVersionLabel);
372    
373                    if (toFileNameVersionFile.exists()) {
374                            throw new DuplicateFileException(toFileNameVersionFile.getPath());
375                    }
376    
377                    fromFileNameVersionFile.renameTo(toFileNameVersionFile);
378            }
379    
380            protected void deleteEmptyAncestors(File file) {
381                    String[] fileNames = file.list();
382    
383                    if (fileNames.length == 0) {
384                            File parentFile = file.getParentFile();
385    
386                            file.delete();
387    
388                            deleteEmptyAncestors(parentFile);
389                    }
390            }
391    
392            protected File getCompanyDir(long companyId) {
393                    File companyDir = new File(_rootDir + StringPool.SLASH + companyId);
394    
395                    if (!companyDir.exists()) {
396                            companyDir.mkdirs();
397                    }
398    
399                    return companyDir;
400            }
401    
402            protected File getDirNameDir(
403                    long companyId, long repositoryId, String dirName) {
404    
405                    return getFileNameDir(companyId, repositoryId, dirName);
406            }
407    
408            protected File getFileNameDir(
409                    long companyId, long repositoryId, String fileName) {
410    
411                    File repositoryDir = getRepositoryDir(companyId, repositoryId);
412    
413                    File fileNameDir = new File(
414                            repositoryDir + StringPool.SLASH + fileName);
415    
416                    return fileNameDir;
417            }
418    
419            protected File getFileNameVersionFile(
420                    long companyId, long repositoryId, String fileName, String version) {
421    
422                    File fileNameDir = getFileNameDir(companyId, repositoryId, fileName);
423    
424                    File fileNameVersionFile = new File(
425                            fileNameDir + StringPool.SLASH + version);
426    
427                    return fileNameVersionFile;
428            }
429    
430            protected String getHeadVersionLabel(
431                    long companyId, long repositoryId, String fileName) {
432    
433                    File fileNameDir = getFileNameDir(companyId, repositoryId, fileName);
434    
435                    if (!fileNameDir.exists()) {
436                            return VERSION_DEFAULT;
437                    }
438    
439                    String[] versionLabels = FileUtil.listFiles(fileNameDir);
440    
441                    String headVersionLabel = VERSION_DEFAULT;
442    
443                    for (String versionLabel : versionLabels) {
444                            if (DLUtil.compareVersions(versionLabel, headVersionLabel) > 0) {
445                                    headVersionLabel = versionLabel;
446                            }
447                    }
448    
449                    return headVersionLabel;
450            }
451    
452            protected File getRepositoryDir(long companyId, long repositoryId) {
453                    RepositoryDirKey repositoryDirKey =
454                            new RepositoryDirKey(companyId, repositoryId);
455    
456                    File repositoryDir = _repositoryDirs.get(repositoryDirKey);
457    
458                    if (repositoryDir == null) {
459                            File companyDir = getCompanyDir(companyId);
460    
461                            repositoryDir = new File(
462                                    companyDir + StringPool.SLASH + repositoryId);
463    
464                            if (!repositoryDir.exists()) {
465                                    repositoryDir.mkdirs();
466                            }
467    
468                            _repositoryDirs.put(repositoryDirKey, repositoryDir);
469                    }
470    
471                    return repositoryDir;
472            }
473    
474            private Map<RepositoryDirKey, File> _repositoryDirs =
475                    new ConcurrentHashMap<RepositoryDirKey, File>();
476            private File _rootDir = new File(PropsValues.DL_STORE_FILE_SYSTEM_ROOT_DIR);
477    
478            private class RepositoryDirKey {
479    
480                    public RepositoryDirKey(long companyId, long repositoryId) {
481                            _companyId = companyId;
482                            _repositoryId = repositoryId;
483                    }
484    
485                    @Override
486                    public boolean equals(Object obj) {
487                            RepositoryDirKey repositoryDirKey = (RepositoryDirKey)obj;
488    
489                            if ((_companyId == repositoryDirKey._companyId) &&
490                                    (_repositoryId == repositoryDirKey._repositoryId)) {
491    
492                                    return true;
493                            }
494                            else {
495                                    return false;
496                            }
497                    }
498    
499                    @Override
500                    public int hashCode() {
501                            return (int)(_companyId * 11 + _repositoryId);
502                    }
503    
504                    private long _companyId;
505                    private long _repositoryId;
506    
507            }
508    
509    }