/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.store.file.system;
import com.liferay.document.library.kernel.exception.DuplicateFileException;
import com.liferay.document.library.kernel.exception.NoSuchFileException;
import com.liferay.document.library.kernel.store.Store;
import com.liferay.document.library.kernel.util.DLUtil;
import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.convert.documentlibrary.FileSystemStoreRootDirException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.store.file.system.configuration.AdvancedFileSystemStoreConfiguration;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
/**
* <p>
* See https://issues.liferay.com/browse/LPS-1976.
* </p>
*
* @author Jorge Ferrer
* @author Ryan Park
* @author Brian Wing Shun Chan
* @author Manuel de la Peña
*/
@Component(
configurationPid = "com.liferay.portal.store.file.system.configuration.AdvancedFileSystemStoreConfiguration",
configurationPolicy = ConfigurationPolicy.REQUIRE, immediate = true,
property = "store.type=com.liferay.portal.store.file.system.AdvancedFileSystemStore",
service = Store.class
)
public class AdvancedFileSystemStore extends FileSystemStore {
@Override
public void updateFile(
long companyId, long repositoryId, String fileName,
String newFileName)
throws DuplicateFileException, NoSuchFileException {
super.updateFile(companyId, repositoryId, fileName, newFileName);
File newFileNameDir = getFileNameDir(
companyId, repositoryId, newFileName);
String[] fileNameVersions = FileUtil.listFiles(newFileNameDir);
for (String fileNameVersion : fileNameVersions) {
String ext = FileUtil.getExtension(fileNameVersion);
String newFileNameVersion = newFileName;
if (ext.equals(_HOOK_EXTENSION)) {
int pos = fileNameVersion.lastIndexOf(CharPool.UNDERLINE);
newFileNameVersion += fileNameVersion.substring(pos);
}
File fileNameVersionFile = new File(
newFileNameDir + StringPool.SLASH + fileNameVersion);
if (!fileNameVersionFile.exists()) {
throw new NoSuchFileException(
companyId, repositoryId, fileName, fileNameVersion);
}
File newFileNameVersionFile = new File(
newFileNameDir + StringPool.SLASH + newFileNameVersion);
boolean renamed = FileUtil.move(
fileNameVersionFile, newFileNameVersionFile);
if (!renamed) {
throw new SystemException(
"File name version file was not renamed from " +
fileNameVersionFile.getPath() + " to " +
newFileNameVersionFile.getPath());
}
}
}
@Activate
@Override
protected void activate(Map<String, Object> properties) {
_advancedFileSystemStoreConfiguration =
ConfigurableUtil.createConfigurable(
AdvancedFileSystemStoreConfiguration.class, properties);
if (Validator.isBlank(
_advancedFileSystemStoreConfiguration.rootDir())) {
throw new IllegalArgumentException(
"Advanced file system root directory is not set",
new FileSystemStoreRootDirException());
}
initializeRootDir();
}
protected void buildPath(StringBundler sb, String fileNameFragment) {
int fileNameFragmentLength = fileNameFragment.length();
if (fileNameFragmentLength <= 2) {
return;
}
for (int i = 0; (i + 2) < fileNameFragmentLength; i += 2) {
sb.append(fileNameFragment.substring(i, i + 2));
sb.append(StringPool.SLASH);
if (getDepth(sb.toString()) > 3) {
return;
}
}
}
/**
* @deprecated As of 2.0.0, replaced by {@link #getFileNames(List, String,
* String)}
*/
@Deprecated
protected List<String> getAdvancedFileNames(
long companyId, long repositoryId, String fileName) {
List<String> fileNames = new ArrayList<>();
getFileNames(fileNames, StringPool.BLANK, fileName);
return fileNames;
}
protected int getDepth(String path) {
String[] fragments = StringUtil.split(path, CharPool.SLASH);
return fragments.length;
}
@Override
protected File getDirNameDir(
long companyId, long repositoryId, String dirName) {
File repositoryDir = getRepositoryDir(companyId, repositoryId);
return new File(repositoryDir + StringPool.SLASH + dirName);
}
@Override
protected File getFileNameDir(
long companyId, long repositoryId, String fileName) {
if (fileName.indexOf(CharPool.SLASH) != -1) {
return getDirNameDir(companyId, repositoryId, fileName);
}
String ext = StringPool.PERIOD + FileUtil.getExtension(fileName);
if (ext.equals(StringPool.PERIOD)) {
ext += _HOOK_EXTENSION;
}
StringBundler sb = new StringBundler();
String fileNameFragment = FileUtil.stripExtension(fileName);
if (fileNameFragment.startsWith("DLFE-")) {
fileNameFragment = fileNameFragment.substring(5);
sb.append("DLFE/");
}
buildPath(sb, fileNameFragment);
File repositoryDir = getRepositoryDir(companyId, repositoryId);
StringBundler pathSB = new StringBundler(6);
pathSB.append(repositoryDir);
pathSB.append(StringPool.SLASH);
pathSB.append(sb.toString());
FileUtil.mkdirs(pathSB.toString());
pathSB.append(StringPool.SLASH);
pathSB.append(fileNameFragment);
pathSB.append(ext);
return new File(pathSB.toString());
}
@Override
protected void getFileNames(
List<String> fileNames, String dirName, String path) {
super.getFileNames(fileNames, dirName, path);
ListIterator<String> iterator = fileNames.listIterator();
while (iterator.hasNext()) {
String shortFileName = iterator.next();
if (path.endsWith(_HOOK_EXTENSION)) {
shortFileName = FileUtil.stripExtension(shortFileName);
}
iterator.set(unbuildPath(shortFileName));
}
}
@Override
protected File getFileNameVersionFile(
long companyId, long repositoryId, String fileName, String version) {
String ext = StringPool.PERIOD + FileUtil.getExtension(fileName);
if (ext.equals(StringPool.PERIOD)) {
ext += _HOOK_EXTENSION;
}
int pos = fileName.lastIndexOf(CharPool.SLASH);
if (pos == -1) {
StringBundler sb = new StringBundler();
String fileNameFragment = FileUtil.stripExtension(fileName);
if (fileNameFragment.startsWith("DLFE-")) {
fileNameFragment = fileNameFragment.substring(5);
sb.append("DLFE/");
}
buildPath(sb, fileNameFragment);
File repositoryDir = getRepositoryDir(companyId, repositoryId);
StringBundler pathSB = new StringBundler(11);
pathSB.append(repositoryDir);
pathSB.append(StringPool.SLASH);
pathSB.append(sb.toString());
pathSB.append(StringPool.SLASH);
pathSB.append(fileNameFragment);
pathSB.append(ext);
pathSB.append(StringPool.SLASH);
pathSB.append(fileNameFragment);
pathSB.append(StringPool.UNDERLINE);
pathSB.append(version);
pathSB.append(ext);
return new File(pathSB.toString());
}
else {
File fileNameDir = getDirNameDir(companyId, repositoryId, fileName);
String fileNameFragment = FileUtil.stripExtension(
fileName.substring(pos + 1));
StringBundler pathSB = new StringBundler(6);
pathSB.append(fileNameDir);
pathSB.append(StringPool.SLASH);
pathSB.append(fileNameFragment);
pathSB.append(StringPool.UNDERLINE);
pathSB.append(version);
pathSB.append(ext);
return new File(pathSB.toString());
}
}
@Override
protected String getHeadVersionLabel(
long companyId, long repositoryId, String fileName) {
File fileNameDir = getFileNameDir(companyId, repositoryId, fileName);
if (!fileNameDir.exists()) {
return VERSION_DEFAULT;
}
String[] versionLabels = FileUtil.listFiles(fileNameDir);
String headVersionLabel = VERSION_DEFAULT;
for (int i = 0; i < versionLabels.length; i++) {
String versionLabelFragment = versionLabels[i];
int x = versionLabelFragment.lastIndexOf(CharPool.UNDERLINE);
int y = versionLabelFragment.lastIndexOf(CharPool.PERIOD);
if (x > -1) {
versionLabelFragment = versionLabelFragment.substring(x + 1, y);
}
String versionLabel = versionLabelFragment;
if (DLUtil.compareVersions(versionLabel, headVersionLabel) > 0) {
headVersionLabel = versionLabel;
}
}
return headVersionLabel;
}
@Override
protected String getRootDirName() {
return _advancedFileSystemStoreConfiguration.rootDir();
}
protected String unbuildPath(String path) {
if (path.startsWith("DLFE/")) {
path = path.substring(5);
}
if (path.length() <= 2) {
return path;
}
String[] parts = StringUtil.split(path, CharPool.SLASH);
StringBundler sb = new StringBundler(parts.length - 1);
for (int i = 0; i < parts.length - 1; i++) {
sb.append(parts[i]);
}
String simpleName = parts[parts.length - 1];
if (simpleName.startsWith(sb.toString())) {
return simpleName;
}
return path;
}
private static final String _HOOK_EXTENSION = "afsh";
private static volatile AdvancedFileSystemStoreConfiguration
_advancedFileSystemStoreConfiguration;
}