org.plukh.fluffymeow.config.S3Properties.java Source code

Java tutorial

Introduction

Here is the source code for org.plukh.fluffymeow.config.S3Properties.java

Source

/*
 * Fluffy Meow - Torrent RSS generator for TV series
 * Copyright (C) 2015 Victor Denisov
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.plukh.fluffymeow.config;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.S3Object;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.*;
import java.util.Enumeration;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;

public class S3Properties extends Properties {
    private static final Logger log = LogManager.getLogger(S3Properties.class);

    public static final String DEFAULT_BUCKET = "signal-config";
    public static final String DEFAULT_PROPERTIES = "default.properties";

    protected transient final AmazonS3 amazonS3;
    protected transient final VersionInfoProvider versionInfoProvider;

    protected final String bucket;

    public S3Properties() {
        amazonS3 = new AmazonS3Client();
        versionInfoProvider = VersionInfoProviderFactory.getInstance();
        bucket = DEFAULT_BUCKET;
    }

    public S3Properties(Properties defaults) {
        super(defaults);
        amazonS3 = new AmazonS3Client();
        versionInfoProvider = VersionInfoProviderFactory.getInstance();
        bucket = DEFAULT_BUCKET;
    }

    public S3Properties(AmazonS3 amazonS3, VersionInfoProvider versionInfoProvider, String bucket) {
        this.amazonS3 = amazonS3;
        this.versionInfoProvider = versionInfoProvider;
        this.bucket = bucket;
    }

    public S3Properties(Properties defaults, AmazonS3 amazonS3, VersionInfoProvider versionInfoProvider,
            String bucket) {
        super(defaults);
        this.amazonS3 = amazonS3;
        this.versionInfoProvider = versionInfoProvider;
        this.bucket = bucket;
    }

    public synchronized void load(String deploymentId, String applicationName, String configFileName)
            throws IOException {
        BufferedInputStream in = null;
        if (StringUtils.isEmpty(configFileName))
            configFileName = applicationName + ".properties";

        try {
            in = new BufferedInputStream(new FileInputStream(configFileName));
        } catch (FileNotFoundException e) {
            log.debug("Local config file " + configFileName + " not found");
        }

        load(deploymentId, applicationName, in);
    }

    public synchronized void load(String deploymentId, String applicationName) throws IOException {
        load(deploymentId, applicationName, applicationName + ".properties");
    }

    public synchronized void load(String deploymentId, String applicationName, InputStream in) throws IOException {
        if (in != null) {
            try {
                log.debug("Trying to load properties from provided input stream");
                super.load(in);
                if (log.isDebugEnabled())
                    log.debug("Loaded " + size() + " total properties");
                return;
            } catch (IOException e) {
                log.debug("Failed to load properties from provided input stream", e);
            }
        }

        log.debug("Proceeding with S3 download");

        log.trace("Downloading default properties");
        Properties defaultProperties = downloadFromS3(bucket, DEFAULT_PROPERTIES, null);

        log.trace("Downloading deployment-default properties");
        Properties deplDefaultProperties = downloadFromS3(bucket, deploymentId + "/" + DEFAULT_PROPERTIES,
                defaultProperties);

        log.trace("Downloading application-specific properties");
        Properties appProperties = downloadFromS3(bucket,
                deploymentId + "/" + applicationName + "/" + applicationName + ".properties",
                deplDefaultProperties);

        log.trace("Downloading version-specific properties");

        Properties versionProperties = downloadFromS3(bucket, deploymentId + "/" + applicationName + "/"
                + applicationName + "-" + versionInfoProvider.getVersion() + ".properties", appProperties);

        //Validate properties (at least one specific property file should be found!)
        if (appProperties.isEmpty() && versionProperties.isEmpty())
            throw new ConfigException("No specific configuration files found!");

        clear();
        Enumeration<?> names = versionProperties.propertyNames();
        while (names.hasMoreElements()) {
            String name = (String) names.nextElement();
            this.setProperty(name, versionProperties.getProperty(name));
        }

        if (log.isDebugEnabled())
            log.debug("Loaded " + size() + " total properties");
    }

    private Properties downloadFromS3(String bucket, String key, Properties defaultProperties) throws IOException {
        Properties properties = new Properties(defaultProperties);

        try (S3Object object = amazonS3.getObject(bucket, key)) {
            try (InputStream in = object.getObjectContent()) {
                if (log.isTraceEnabled())
                    log.trace("Downloading from " + bucket + ":" + key + ", size: "
                            + object.getObjectMetadata().getInstanceLength());
                properties.load(in);
                if (log.isTraceEnabled())
                    log.trace("Downloaded " + properties.size() + " properties");
            }
        } catch (AmazonS3Exception e) {
            if (isObjectNotFound(e)) {
                //Not found is ok, just means the file is not present
                if (log.isDebugEnabled())
                    log.debug("Object " + bucket + ":" + key + " not found");
            } else {
                //Some other exception
                throw e;
            }
        }

        return properties;
    }

    private boolean isObjectNotFound(AmazonS3Exception e) {
        return e.getStatusCode() == 404;
    }

    @Override
    public synchronized void load(Reader reader) throws IOException {
        throw new NotSupportedException("This method is not supported for S3 properties");
    }

    @Override
    public synchronized void load(InputStream inStream) throws IOException {
        throw new NotSupportedException("This method is not supported for S3 properties");
    }

    @Override
    public void store(Writer writer, String comments) throws IOException {
        throw new NotSupportedException("This method is not supported for S3 properties");
    }

    @Override
    public void store(OutputStream out, String comments) throws IOException {
        throw new NotSupportedException("This method is not supported for S3 properties");
    }

    @Override
    public synchronized void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException {
        throw new NotSupportedException("This method is not supported for S3 properties");
    }

    @Override
    public void storeToXML(OutputStream os, String comment) throws IOException {
        throw new NotSupportedException("This method is not supported for S3 properties");
    }

    @Override
    public void storeToXML(OutputStream os, String comment, String encoding) throws IOException {
        throw new NotSupportedException("This method is not supported for S3 properties");
    }
}