com.knockturnmc.api.util.ConfigurationUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.knockturnmc.api.util.ConfigurationUtils.java

Source

/*
The MIT License (MIT)
    
Copyright (c) 2016 Sven Olderaan, http://knockturnmc.com/
    
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
    
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
    
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 */

package com.knockturnmc.api.util;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Constructor;
import java.util.Properties;

/**
 * Provides utilities for loading configurations and loading mapped {@link NamedProperties}
 */
public final class ConfigurationUtils {

    private static final Logger logger = LoggerFactory.getLogger(ConfigurationUtils.class);

    private ConfigurationUtils() {
    }

    /**
     * Loads a standard Java {@link Properties} file.
     * If the desired file is not found, a file with the same name will be copied from the classpath to the datafolder.
     * If no default file was found, an empty file will be created.
     *
     * @param classLoader the classloader to use for the default file
     * @param file        the filename to create/load
     * @param datafolder  the datafolder to use
     * @return the loaded/created file
     */
    public static Properties loadConfiguration(ClassLoader classLoader, String file, File datafolder) {
        try {
            File config = getConfigFile(classLoader, file, datafolder);
            Properties props = new Properties();
            try (FileInputStream stream = new FileInputStream(config)) {
                props.load(stream);
            }
            return props;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Loads a plain file.
     * If the desired file is not found, a file with the same name will be copied from the classpath to the datafolder.
     * If no default file was found in the classloader's classpath, an empty file will be created.
     *
     * @param classLoader the classloader to use for the default file
     * @param file        the filename to create/load
     * @param datafolder  the datafolder to use
     * @return the loaded/created file
     * @throws IOException if something went wrong
     */
    public static File getConfigFile(ClassLoader classLoader, String file, File datafolder) throws IOException {
        File config = new File(datafolder, file);
        datafolder.mkdirs();
        if (!config.exists()) {
            logger.info("No configuration file found. Copying default configuration...");
            try (InputStream in = classLoader.getResourceAsStream(file)) {
                if (in != null) {
                    if (!config.createNewFile()) {
                        logger.error("Failed creating default file.");
                        throw new RuntimeException("Failed to create default file");
                    }
                    try (OutputStream out = new FileOutputStream(config)) {
                        IOUtils.copy(in, out);
                        out.flush();
                    }
                } else {
                    config.createNewFile();
                }
            }
        }
        return config;
    }

    /**
     * Loads a plain file.
     * If the desired file is not found, a file with the same name will be copied from the classpath to the current working directory.
     * If no default file was found in the classloader's classpath, an empty file will be created.
     *
     * @param classLoader the classloader to use for the default file
     * @param file        the filename to create/load
     * @return the loaded/created file
     * @throws IOException if something went wrong
     */
    public static File getConfigFile(ClassLoader classLoader, String file) throws IOException {
        return getConfigFile(classLoader, file, getDataFolder());
    }

    /**
     * Loads a standard Java {@link Properties} file.
     * If the desired file is not found, a file with the same name will be copied from the classpath to the current working directory.
     * If no default file was found, an empty file will be created.
     *
     * @param classLoader the classloader to use for the default file
     * @param file        the filename to create/load
     * @return the loaded/created file
     */
    public static Properties loadConfiguration(ClassLoader classLoader, String file) {
        return loadConfiguration(classLoader, file, getDataFolder());
    }

    /**
     * Loads a mapped {@link Properties} file and applies the mapping provided by the {@link NamedProperties}.
     * If the desired file was not found in the datafolder, a default file will be copied from the classpath.
     *
     * @param classLoader the classloader to use for the default file
     * @param filename    the filename
     * @param datafolder  the datafolder
     * @param mapping     the mapped file
     * @param <T>         the type of the mapped file
     * @return the loaded configuration mapping
     */
    public static <T extends NamedProperties> T loadConfiguration(ClassLoader classLoader, String filename,
            File datafolder, Class<? extends T> mapping) {
        try {
            File file = getConfigFile(classLoader, filename, datafolder);
            Constructor<? extends T> constructor = mapping.getDeclaredConstructor();
            constructor.setAccessible(true);
            T properties = constructor.newInstance();
            FileInputStream stream = new FileInputStream(file);
            properties.load(stream);
            stream.close();

            OutputStream fos = new FileOutputStream(file);

            properties.store(fos, "Configuration for " + filename);
            fos.close();
            return properties;
        } catch (Exception e) {
            logger.warn("Failed to load configuration", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Loads a mapped {@link Properties} file and applies the mapping provided by the {@link NamedProperties}.
     * If the desired file was not found in the current working directory, a default file will be copied from the classpath.
     *
     * @param classLoader the classloader to use for the default file
     * @param filename    the filename
     * @param mapping     the mapped file
     * @param <T>         the type of the mapped file
     * @return the loaded configuration mapping
     */
    public static <T extends NamedProperties> T loadConfiguration(ClassLoader classLoader, String filename,
            Class<? extends T> mapping) {
        return loadConfiguration(classLoader, filename, getDataFolder(), mapping);
    }

    /**
     * Gets the current working directory, this is also the default datafolder for all methods in {@link ConfigurationUtils}
     *
     * @return the current working directory
     */
    public static File getDataFolder() {
        return new File(System.getProperty("user.dir"));
    }
}