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" + StringPool.SLASH);
186                    }
187    
188                    buildPath(sb, fileNameFragment);
189    
190                    File repositoryDir = getRepositoryDir(companyId, repositoryId);
191    
192                    File fileNameDir = new File(
193                            repositoryDir + StringPool.SLASH + sb.toString() +
194                                    StringPool.SLASH + fileNameFragment + ext);
195    
196                    File parentFile = fileNameDir.getParentFile();
197    
198                    if (!parentFile.exists()) {
199                            parentFile.mkdirs();
200                    }
201    
202                    return fileNameDir;
203            }
204    
205            @Override
206            protected File getFileNameVersionFile(
207                    long companyId, long repositoryId, String fileName, String version) {
208    
209                    String ext = StringPool.PERIOD + FileUtil.getExtension(fileName);
210    
211                    if (ext.equals(StringPool.PERIOD)) {
212                            ext += _HOOK_EXTENSION;
213                    }
214    
215                    int pos = fileName.lastIndexOf(CharPool.SLASH);
216    
217                    if (pos == -1) {
218                            StringBundler sb = new StringBundler();
219    
220                            String fileNameFragment = FileUtil.stripExtension(fileName);
221    
222                            if (fileNameFragment.startsWith("DLFE-")) {
223                                    fileNameFragment = fileNameFragment.substring(5);
224    
225                                    sb.append("DLFE" + StringPool.SLASH);
226                            }
227    
228                            buildPath(sb, fileNameFragment);
229    
230                            File repositoryDir = getRepositoryDir(companyId, repositoryId);
231    
232                            return new File(
233                                    repositoryDir + StringPool.SLASH + sb.toString() +
234                                            StringPool.SLASH + fileNameFragment + ext +
235                                                    StringPool.SLASH + fileNameFragment +
236                                                            StringPool.UNDERLINE + version + ext);
237                    }
238                    else {
239                            File fileNameDir = getDirNameDir(companyId, repositoryId, fileName);
240    
241                            String fileNameFragment = FileUtil.stripExtension(
242                                    fileName.substring(pos + 1));
243    
244                            return new File(
245                                    fileNameDir + StringPool.SLASH + fileNameFragment +
246                                            StringPool.UNDERLINE + version + ext);
247                    }
248            }
249    
250            @Override
251            protected String getHeadVersionLabel(
252                    long companyId, long repositoryId, String fileName) {
253    
254                    File fileNameDir = getFileNameDir(companyId, repositoryId, fileName);
255    
256                    if (!fileNameDir.exists()) {
257                            return VERSION_DEFAULT;
258                    }
259    
260                    String[] versionLabels = FileUtil.listFiles(fileNameDir);
261    
262                    String headVersionLabel = VERSION_DEFAULT;
263    
264                    for (int i = 0; i < versionLabels.length; i++) {
265                            String versionLabelFragment = versionLabels[i];
266    
267                            int x = versionLabelFragment.lastIndexOf(CharPool.UNDERLINE);
268                            int y = versionLabelFragment.lastIndexOf(CharPool.PERIOD);
269    
270                            if (x > -1) {
271                                    versionLabelFragment = versionLabelFragment.substring(x + 1, y);
272                            }
273    
274                            String versionLabel = versionLabelFragment;
275    
276                            if (DLUtil.compareVersions(versionLabel, headVersionLabel) > 0) {
277                                    headVersionLabel = versionLabel;
278                            }
279                    }
280    
281                    return headVersionLabel;
282            }
283    
284            private static final String _HOOK_EXTENSION = "afsh";
285    
286    }