at.ac.univie.isc.asio.tool.PropertyHierarchy.java Source code

Java tutorial

Introduction

Here is the source code for at.ac.univie.isc.asio.tool.PropertyHierarchy.java

Source

/*
 * #%L
 * asio cli
 * %%
 * Copyright (C) 2013 - 2015 Research Group Scientific Computing, University of Vienna
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package at.ac.univie.isc.asio.tool;

import com.google.common.io.Resources;
import org.slf4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Create layered {@link java.util.Properties} with values defined in one or more sources.
 * - .properties file on the classpath
 * - system properties
 * - external .properties file
 * - command line
 */
public final class PropertyHierarchy {
    private static final Logger log = getLogger(PropertyHierarchy.class);

    /**
     * key of the property pointing to an external .properties file
     */
    public static final String EXTERNAL_LOCATION_PROPERTY = "config_location";

    private Properties merged;

    public PropertyHierarchy() {
        merged = new Properties();
    }

    private static RuntimeException wrapped(final Exception e) {
        throw new IllegalStateException("failed to load property hierarchy - " + e.getMessage(), e);
    }

    /**
     * The merged property hierarchy.
     */
    public Properties get() {
        return merged;
    }

    /**
     * Add all properties from a file in the classpath, e.g. embedded in the .jar.
     */
    public PropertyHierarchy loadEmbedded(final String location) {
        log.debug("loading embedded properties from {}", location);
        final URL resource = Resources.getResource(location);
        try (final InputStream stream = resource.openStream()) {
            merged.load(stream);
        } catch (IOException e) {
            throw wrapped(e);
        }
        return this;
    }

    /**
     * Add all properties from the system environment.
     */
    public PropertyHierarchy loadSystem() {
        log.debug("loading system properties");
        merged.putAll(System.getenv());
        merged.putAll(System.getProperties());
        return this;
    }

    /**
     * Load properties from an external file. If present the {@link #EXTERNAL_LOCATION_PROPERTY} is
     * searched instead of the current directory
     */
    public PropertyHierarchy loadExternal(final String filename) {
        final String externalLocation = merged.getProperty(EXTERNAL_LOCATION_PROPERTY, "");
        final Path path = Paths.get(externalLocation, filename);
        if (Files.isReadable(path)) {
            log.debug("loading external properties from {}", path);
            try (final InputStream stream = Files.newInputStream(path)) {
                merged.load(stream);
            } catch (final IOException e) {
                throw wrapped(e);
            }
        } else {
            log.warn("cannot read properties from {} - check permissions if the file exists", path);
        }
        return this;
    }

    /**
     * Add all non-positional arguments as property, expects --key=value or --toggle format.
     */
    public PropertyHierarchy parseCommandLine(final String[] arguments) {
        log.debug("parsing cli arguments {}", (Object) arguments);
        for (final String arg : arguments) {
            if (arg.startsWith("--")) {
                final String option = arg.substring(2);
                if (!option.isEmpty()) {
                    include(option);
                }
            }
        }
        return this;
    }

    private void include(final String arg) {
        final String[] parts = arg.split("=", 2);
        if (parts.length == 1) { // toggle
            log.debug("found cli toggle {}", parts[0]);
            merged.setProperty(parts[0], "true");
        } else { // key-value argument
            log.debug("found cli option {} with value {}", parts[0], parts[1]);
            merged.setProperty(parts[0], parts[1]);
        }
    }

    PropertyHierarchy single(final String key, final String value) {
        merged.setProperty(key, value);
        return this;
    }
}