All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.server.spring.SettingsLocationEnvironmentPostProcessor Maven / Gradle / Ivy

There is a newer version: 2.0.29
Show newest version
package org.bidib.wizard.server.spring;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Properties;

import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.logging.Log;
import org.bidib.wizard.api.locale.Resources;
import org.bidib.wizard.api.utils.WizardUtils;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigDataEnvironmentUpdateListener;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.ResourceLoader;

public class SettingsLocationEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {

    public static final int ORDER = Ordered.HIGHEST_PRECEDENCE + 7;

    private final Log logger;

    private final ConfigurableBootstrapContext bootstrapContext;

    private final ConfigDataEnvironmentUpdateListener environmentUpdateListener;

    public SettingsLocationEnvironmentPostProcessor(DeferredLogFactory logFactory,
        ConfigurableBootstrapContext bootstrapContext) {
        this(logFactory, bootstrapContext, null);
    }

    public SettingsLocationEnvironmentPostProcessor(DeferredLogFactory logFactory,
        ConfigurableBootstrapContext bootstrapContext, ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
        this.logger = logFactory.getLog(getClass());
        this.bootstrapContext = bootstrapContext;
        this.environmentUpdateListener = environmentUpdateListener;
    }

    @Override
    public int getOrder() {
        return ORDER;
    }

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        postProcessEnvironment(environment, application.getResourceLoader(), application.getAdditionalProfiles());
    }

    private static final String WIZARD_SETTINGSFILE_LOCATION_REFERENCE = "wizard2.properties";

    private static final String WIZARD_SETTINGSFILE_LOCATION_PROPERTY = "wizard.settings.file-location";

    private String wizardConfigurationFileLocationReference;

    void postProcessEnvironment(
        ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection additionalProfiles) {

        try {

            wizardConfigurationFileLocationReference =
                environment.getProperty(WIZARD_SETTINGSFILE_LOCATION_PROPERTY, "${user.home}/.bidib");
            wizardConfigurationFileLocationReference =
                environment.resolvePlaceholders(wizardConfigurationFileLocationReference);

            this.logger
                .info("Location of settings file location reference: " + wizardConfigurationFileLocationReference);

            // check if the reference file to the settings location exists
            final File file =
                new File(wizardConfigurationFileLocationReference, WIZARD_SETTINGSFILE_LOCATION_REFERENCE);
            if (!file.exists()) {
                this.logger.info("The settings file location reference was not found.");

                selectLocation(environment, file);
            }
            else {
                // get the location of the wizard configuration files
                this.logger.info("The settings file location reference was found.");

                try (InputStream is = new FileInputStream(file)) {
                    //
                    Properties props = new Properties();

                    props.load(is);

                    wizardConfigurationFileLocationReference = props.getProperty(WIZARD_SETTINGSFILE_LOCATION_PROPERTY);

                    SettingsLocationEnvironmentPostProcessor.this.logger
                        .info("Read wizardSettingsFileLocationReference from location: " + file.getPath()
                            + ", wizardConfigurationFileLocationReference: "
                            + wizardConfigurationFileLocationReference);

                    final File location = new File(wizardConfigurationFileLocationReference);
                    if (!location.exists()) {
                        try {
                            FileUtils.forceMkdir(location);
                        }
                        catch (Exception ex) {
                            SettingsLocationEnvironmentPostProcessor.this.logger
                                .warn("Create directory for wizardSettingsFiles failed.", ex);
                        }
                    }
                }
                catch (Exception ex) {
                    SettingsLocationEnvironmentPostProcessor.this.logger
                        .warn("Failed to read the wizardSettingsFileLocationReference from location: " + file.getPath(),
                            ex);

                    throw new RuntimeException(
                        "Failed to read the wizardSettingsFileLocationReference from location: " + file.getPath());
                }
            }

            environment
                .getSystemProperties()
                .put("wizard.configuration.file-location", wizardConfigurationFileLocationReference);

        }
        catch (Exception ex) {
            this.logger.warn("Fetch the location of settings file location reference failed.", ex);
        }
    }

    private void selectLocation(final ConfigurableEnvironment environment, final File file) {
        String userHome = environment.resolvePlaceholders("${user.home}");

        logger.info("Select the location for wizard settings files.");

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (ClassNotFoundException | InstantiationException | IllegalAccessException
            | UnsupportedLookAndFeelException ex) {
            logger.warn("Set look and feel failed", ex);
        }

        boolean foundAndUseOldLocation = false;
        boolean copyWizardConfigFromOldLocation = false;
        // check if the wizard.yml exists in the 'old default directory'
        try {
            final File oldWizardConfigurationFile = new File(userHome, ".bidib/wizard.yml");
            if (oldWizardConfigurationFile.exists()) {
                this.logger
                    .info("Found the wizard.yml in the old default directory: " + oldWizardConfigurationFile.getPath());

                // ask the user if he wants to keep this location
                int result =
                    JOptionPane
                        .showConfirmDialog(JOptionPane.getFrameForComponent(null),
                            Resources
                                .getString(SettingsLocationEnvironmentPostProcessor.class, "keep-old-location.message",
                                    oldWizardConfigurationFile.getParentFile().getPath()),
                            Resources
                                .getString(SettingsLocationEnvironmentPostProcessor.class, "keep-old-location.title"),
                            JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (result == JOptionPane.YES_OPTION) {
                    this.logger.info("User accepted to use old configuration location.");

                    wizardConfigurationFileLocationReference = oldWizardConfigurationFile.getParentFile().getPath();
                    this.logger
                        .info("Found and use the configuration from the old location: "
                            + wizardConfigurationFileLocationReference);

                    foundAndUseOldLocation = true;
                }
                else {
                    this.logger.info("User declined to use old configuration location.");
                    copyWizardConfigFromOldLocation = true;
                }
            }
        }
        catch (Exception ex) {
            this.logger.warn("Check if the wizard.yml exists in the 'old default directory' failed.", ex);
        }

        if (!foundAndUseOldLocation) {
            File defaultDirectory = new File(userHome, WizardUtils.getDefaultConfigSubDir());

            SettingsLocationEnvironmentPostProcessor.this.logger
                .info("Prepared the default location directory: " + defaultDirectory.getPath());

            wizardConfigurationFileLocationReference = defaultDirectory.getPath();

            if (!defaultDirectory.exists()) {
                SettingsLocationEnvironmentPostProcessor.this.logger
                    .info("The selected location does not exist and will be created: "
                        + wizardConfigurationFileLocationReference);
                try {
                    FileUtils.forceMkdir(defaultDirectory);
                }
                catch (Exception ex) {
                    SettingsLocationEnvironmentPostProcessor.this.logger
                        .warn("Create directory for wizardSettingsFiles failed.", ex);
                }
            }
            else {
                SettingsLocationEnvironmentPostProcessor.this.logger
                    .info("The selected location does exist: " + wizardConfigurationFileLocationReference);
            }

            SettingsLocationEnvironmentPostProcessor.this.logger
                .info("Use the wizardSettingsFileLocationReference: " + wizardConfigurationFileLocationReference);
        }

        if (!file.getParentFile().exists()) {
            try {
                FileUtils.forceMkdir(file.getParentFile());
            }
            catch (Exception ex) {
                SettingsLocationEnvironmentPostProcessor.this.logger
                    .warn("Create directory for wizardSettingsFileLocationReference failed.", ex);
            }
        }

        try (OutputStream os = new FileOutputStream(file)) {
            //
            Properties props = new Properties();
            props.put(WIZARD_SETTINGSFILE_LOCATION_PROPERTY, wizardConfigurationFileLocationReference);

            props.store(os, "Added by Wizard 2");

            SettingsLocationEnvironmentPostProcessor.this.logger
                .info("Wrote wizardSettingsFileLocationReference to location: " + file.getPath());
        }
        catch (Exception ex) {
            SettingsLocationEnvironmentPostProcessor.this.logger
                .warn("Write the wizardSettingsFileLocationReference failed: " + file, ex);

            throw new RuntimeException("Write the wizardSettingsFileLocationReference failed: " + file);
        }

        // check if we must copy the existing configuration files to the new location
        if (copyWizardConfigFromOldLocation) {
            // check if the configuration files exist in the new location already
            try {
                final File oldDirectory = new File(userHome, ".bidib");
                final File newLocationConfigurationFile =
                    new File(wizardConfigurationFileLocationReference, "wizard.yml");
                if (!newLocationConfigurationFile.exists()) {
                    SettingsLocationEnvironmentPostProcessor.this.logger
                        .info("copy the existing wizard configuration files to the new location.");

                    // ask the user if he wants to keep this location
                    int result =
                        JOptionPane
                            .showConfirmDialog(JOptionPane.getFrameForComponent(null),
                                Resources
                                    .getString(SettingsLocationEnvironmentPostProcessor.class,
                                        "copy-config-from-old-location.message", oldDirectory.getPath()),
                                Resources
                                    .getString(SettingsLocationEnvironmentPostProcessor.class,
                                        "copy-config-from-old-location.title"),
                                JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                    if (result == JOptionPane.YES_OPTION) {
                        SettingsLocationEnvironmentPostProcessor.this.logger
                            .info("User accepted to copy existing configuration files.");

                        final File oldWizardConfigurationFile = new File(oldDirectory, "wizard.yml");
                        copyFile(oldWizardConfigurationFile, newLocationConfigurationFile);

                        FileFilter fileFilter = new WildcardFileFilter("wizardmodule_*.yml");
                        File[] files = oldDirectory.listFiles(fileFilter);
                        if (files != null && files.length > 0) {
                            for (File sourceFile : files) {
                                File targetFile =
                                    new File(wizardConfigurationFileLocationReference, sourceFile.getName());
                                copyFile(sourceFile, targetFile);
                            }
                        }
                        else {
                            SettingsLocationEnvironmentPostProcessor.this.logger
                                .info("No wizard module configuration files found.");
                        }
                    }
                    else {
                        SettingsLocationEnvironmentPostProcessor.this.logger
                            .info("User declined to copy existing configuration files.");
                    }
                }
                else {
                    SettingsLocationEnvironmentPostProcessor.this.logger
                        .info(
                            "The wizard configuration file exists in the new location already. Skip copy existing files.");
                }
            }
            catch (Exception ex) {
                SettingsLocationEnvironmentPostProcessor.this.logger
                    .warn("Write the wizardSettingsFileLocationReference failed: " + file, ex);
            }
        }
    }

    private void copyFile(File source, File target) {
        try (InputStream sourceStream = new FileInputStream(source);
            OutputStream targetStream = new FileOutputStream(target)) {
            IOUtils.copy(sourceStream, targetStream);
        }
        catch (Exception ex) {
            SettingsLocationEnvironmentPostProcessor.this.logger.warn("Copy configuration file failed: " + source, ex);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy