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