001/*
002 * (C) Copyright 2006-2019 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.core.blob;
020
021import java.io.IOException;
022import java.nio.file.Files;
023import java.nio.file.Path;
024import java.nio.file.Paths;
025import java.util.Map;
026import java.util.regex.Pattern;
027
028import org.apache.commons.lang3.StringUtils;
029import org.nuxeo.common.Environment;
030import org.nuxeo.common.xmap.XMap;
031import org.nuxeo.ecm.core.blob.binary.BinaryManagerRootDescriptor;
032import org.nuxeo.runtime.api.Framework;
033
034/**
035 * Configuration for the local storage of files.
036 *
037 * @since 11.1
038 */
039public class LocalBlobStoreConfiguration extends PropertyBasedConfiguration {
040
041    /** In the initialization properties, the property for the store path. */
042    public static final String PROP_PATH = "path";
043
044    public static final Pattern WINDOWS_ABSOLUTE_PATH = Pattern.compile("[a-zA-Z]:[/\\\\].*");
045
046    public static final String DEFAULT_PATH = "binaries";
047
048    public static final String DATA = "data";
049
050    public static final String TMP = "tmp";
051
052    public static final String CONFIG_FILE = "config.xml";
053
054    public final Path storageDir;
055
056    public final Path tmpDir;
057
058    public final BinaryManagerRootDescriptor descriptor;
059
060    public final DigestConfiguration digestConfiguration;
061
062    public LocalBlobStoreConfiguration(Map<String, String> properties) throws IOException {
063        super(null, properties);
064        Path base = getStorageBase();
065        storageDir = base.resolve(DATA);
066        tmpDir = base.resolve(TMP);
067        Files.createDirectories(storageDir);
068        Files.createDirectories(tmpDir);
069        descriptor = getDescriptor(base.resolve(CONFIG_FILE), true);
070        digestConfiguration = new DigestConfiguration(null, properties);
071    }
072
073    /**
074     * Gets the storage base to use, based on the properties.
075     */
076    public Path getStorageBase() {
077        String path = getProperty(PROP_PATH, DEFAULT_PATH);
078        path = Framework.expandVars(path);
079        path = path.trim();
080        Path base;
081        if (path.startsWith("/") || path.startsWith("\\") || path.contains("://") || path.contains(":\\")
082                || WINDOWS_ABSOLUTE_PATH.matcher(path).matches()) {
083            // absolute
084            base = Paths.get(path);
085        } else {
086            // relative
087            Path home = Environment.getDefault().getData().toPath();
088            base = home.resolve(path).normalize();
089        }
090        // take namespace into account
091        String namespace = getProperty(BlobProviderDescriptor.NAMESPACE);
092        if (StringUtils.isNotBlank(namespace)) {
093            base = base.resolveSibling(base.getFileName() + "_" + namespace.trim());
094        }
095        return base;
096    }
097
098    public static final int DEFAULT_DEPTH = 2;
099
100    /**
101     * Gets existing descriptor or creates a default one.
102     */
103    public BinaryManagerRootDescriptor getDescriptor(Path configFile, boolean create) throws IOException {
104        BinaryManagerRootDescriptor desc;
105        if (Files.exists(configFile)) { // NOSONAR (squid:S3725)
106            XMap xmap = new XMap();
107            xmap.register(BinaryManagerRootDescriptor.class);
108            desc = (BinaryManagerRootDescriptor) xmap.load(Files.newInputStream(configFile));
109        } else {
110            desc = new BinaryManagerRootDescriptor();
111            desc.digest = DigestConfiguration.DEFAULT_DIGEST_ALGORITHM;
112            desc.depth = DEFAULT_DEPTH;
113            if (create) {
114                desc.write(configFile.toFile()); // may throw IOException
115            }
116        }
117        return desc;
118    }
119
120}