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.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.CharPool;
020    import com.liferay.portal.kernel.util.FileUtil;
021    import com.liferay.portal.kernel.util.StringBundler;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portlet.documentlibrary.util.DLUtil;
026    
027    import java.io.File;
028    
029    import java.util.ArrayList;
030    import java.util.List;
031    
032    /**
033     * <p>
034     * See http://issues.liferay.com/browse/LPS-1976.
035     * </p>
036     *
037     * @author Jorge Ferrer
038     * @author Ryan Park
039     * @author Brian Wing Shun Chan
040     */
041    public class AdvancedFileSystemStore extends FileSystemStore {
042    
043            @Override
044            public String[] getFileNames(long companyId, long repositoryId) {
045                    File repositoryDir = getRepositoryDir(companyId, repositoryId);
046    
047                    String[] directories = FileUtil.listDirs(repositoryDir);
048    
049                    List<String> fileNames = new ArrayList<String>();
050    
051                    for (String directory : directories) {
052                            fileNames.addAll(
053                                    getAdvancedFileNames(
054                                            companyId, repositoryId,
055                                            repositoryDir.getPath() + StringPool.SLASH + directory));
056                    }
057    
058                    return fileNames.toArray(new String[fileNames.size()]);
059            }
060    
061            @Override
062            public void updateFile(
063                            long companyId, long repositoryId, String fileName,
064                            String newFileName)
065                    throws PortalException, SystemException {
066    
067                    super.updateFile(companyId, repositoryId, fileName, newFileName);
068    
069                    File newFileNameDir = getFileNameDir(
070                            companyId, repositoryId, newFileName);
071    
072                    String[] fileNameVersions = FileUtil.listFiles(newFileNameDir);
073    
074                    for (String fileNameVersion : fileNameVersions) {
075                            String ext = FileUtil.getExtension(fileNameVersion);
076    
077                            if (ext.equals(_HOOK_EXTENSION)) {
078                                    continue;
079                            }
080    
081                            File fileNameVersionFile = new File(
082                                    newFileNameDir + StringPool.SLASH + fileNameVersion);
083                            File newFileNameVersionFile = new File(
084                                    newFileNameDir + StringPool.SLASH +
085                                            FileUtil.stripExtension(fileNameVersion) +
086                                                    StringPool.PERIOD + _HOOK_EXTENSION);
087    
088                            boolean renamed = FileUtil.move(
089                                    fileNameVersionFile, newFileNameVersionFile);
090    
091                            if (!renamed) {
092                                    throw new SystemException(
093                                            "File name version file was not renamed from " +
094                                                    fileNameVersionFile.getPath() + " to " +
095                                                            newFileNameVersionFile.getPath());
096                            }
097                    }
098            }
099    
100            protected void buildPath(StringBundler sb, String fileNameFragment) {
101                    int fileNameFragmentLength = fileNameFragment.length();
102    
103                    if ((fileNameFragmentLength <= 2) || (getDepth(sb.toString()) > 3)) {
104                            return;
105                    }
106    
107                    for (int i = 0; i < fileNameFragmentLength; i += 2) {
108                            if ((i + 2) < fileNameFragmentLength) {
109                                    sb.append(fileNameFragment.substring(i, i + 2));
110                                    sb.append(StringPool.SLASH);
111    
112                                    if (getDepth(sb.toString()) > 3) {
113                                            return;
114                                    }
115                            }
116                    }
117    
118                    return;
119            }
120    
121            protected List<String> getAdvancedFileNames(
122                    long companyId, long repositoryId, String fileName) {
123    
124                    List<String> fileNames = new ArrayList<String>();
125    
126                    String shortFileName = FileUtil.getShortFileName(fileName);
127    
128                    if (shortFileName.equals("DLFE") || Validator.isNumber(shortFileName)) {
129                            String[] curFileNames = FileUtil.listDirs(fileName);
130    
131                            for (String curFileName : curFileNames) {
132                                    fileNames.addAll(
133                                            getAdvancedFileNames(
134                                                    companyId, repositoryId,
135                                                    fileName + StringPool.SLASH + curFileName));
136                            }
137                    }
138                    else {
139                            if (shortFileName.endsWith(_HOOK_EXTENSION)) {
140                                    shortFileName = FileUtil.stripExtension(shortFileName);
141                            }
142    
143                            fileNames.add(shortFileName);
144                    }
145    
146                    return fileNames;
147            }
148    
149            protected int getDepth(String path) {
150                    String[] fragments = StringUtil.split(path, CharPool.SLASH);
151    
152                    return fragments.length;
153            }
154    
155            @Override
156            protected File getDirNameDir(
157                    long companyId, long repositoryId, String dirName) {
158    
159                    File repositoryDir = getRepositoryDir(companyId, repositoryId);
160    
161                    return new File(repositoryDir + StringPool.SLASH + dirName);
162            }
163    
164            @Override
165            protected File getFileNameDir(
166                    long companyId, long repositoryId, String fileName) {
167    
168                    if (fileName.indexOf(CharPool.SLASH) != -1) {
169                            return getDirNameDir(companyId, repositoryId, fileName);
170                    }
171    
172                    String ext = StringPool.PERIOD + FileUtil.getExtension(fileName);
173    
174                    if (ext.equals(StringPool.PERIOD)) {
175                            ext += _HOOK_EXTENSION;
176                    }
177    
178                    StringBundler sb = new StringBundler();
179    
180                    String fileNameFragment = FileUtil.stripExtension(fileName);
181    
182                    if (fileNameFragment.startsWith("DLFE-")) {
183                            fileNameFragment = fileNameFragment.substring(5);
184    
185                            sb.append("DLFE/");
186                    }
187    
188                    buildPath(sb, fileNameFragment);
189    
190                    File repositoryDir = getRepositoryDir(companyId, repositoryId);
191    
192                    String parentDirName = repositoryDir + StringPool.SLASH + sb.toString();
193    
194                    FileUtil.mkdirs(parentDirName);
195    
196                    return new File(
197                            parentDirName + StringPool.SLASH + fileNameFragment + ext);
198            }
199    
200            @Override
201            protected File getFileNameVersionFile(
202                    long companyId, long repositoryId, String fileName, String version) {
203    
204                    String ext = StringPool.PERIOD + FileUtil.getExtension(fileName);
205    
206                    if (ext.equals(StringPool.PERIOD)) {
207                            ext += _HOOK_EXTENSION;
208                    }
209    
210                    int pos = fileName.lastIndexOf(CharPool.SLASH);
211    
212                    if (pos == -1) {
213                            StringBundler sb = new StringBundler();
214    
215                            String fileNameFragment = FileUtil.stripExtension(fileName);
216    
217                            if (fileNameFragment.startsWith("DLFE-")) {
218                                    fileNameFragment = fileNameFragment.substring(5);
219    
220                                    sb.append("DLFE/");
221                            }
222    
223                            buildPath(sb, fileNameFragment);
224    
225                            File repositoryDir = getRepositoryDir(companyId, repositoryId);
226    
227                            return new File(
228                                    repositoryDir + StringPool.SLASH + sb.toString() +
229                                            StringPool.SLASH + fileNameFragment + ext +
230                                                    StringPool.SLASH + fileNameFragment +
231                                                            StringPool.UNDERLINE + version + ext);
232                    }
233                    else {
234                            File fileNameDir = getDirNameDir(companyId, repositoryId, fileName);
235    
236                            String fileNameFragment = FileUtil.stripExtension(
237                                    fileName.substring(pos + 1));
238    
239                            return new File(
240                                    fileNameDir + StringPool.SLASH + fileNameFragment +
241                                            StringPool.UNDERLINE + version + ext);
242                    }
243            }
244    
245            @Override
246            protected String getHeadVersionLabel(
247                    long companyId, long repositoryId, String fileName) {
248    
249                    File fileNameDir = getFileNameDir(companyId, repositoryId, fileName);
250    
251                    if (!fileNameDir.exists()) {
252                            return VERSION_DEFAULT;
253                    }
254    
255                    String[] versionLabels = FileUtil.listFiles(fileNameDir);
256    
257                    String headVersionLabel = VERSION_DEFAULT;
258    
259                    for (int i = 0; i < versionLabels.length; i++) {
260                            String versionLabelFragment = versionLabels[i];
261    
262                            int x = versionLabelFragment.lastIndexOf(CharPool.UNDERLINE);
263                            int y = versionLabelFragment.lastIndexOf(CharPool.PERIOD);
264    
265                            if (x > -1) {
266                                    versionLabelFragment = versionLabelFragment.substring(x + 1, y);
267                            }
268    
269                            String versionLabel = versionLabelFragment;
270    
271                            if (DLUtil.compareVersions(versionLabel, headVersionLabel) > 0) {
272                                    headVersionLabel = versionLabel;
273                            }
274                    }
275    
276                    return headVersionLabel;
277            }
278    
279            private static final String _HOOK_EXTENSION = "afsh";
280    
281    }