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

org.ow2.petals.cli.pref.AbstractPreferencesImpl Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2010-2012 EBM WebSourcing, 2012-2023 Linagora
 *
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * This program/library 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 Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see http://www.gnu.org/licenses/
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.cli.pref;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.ow2.petals.cli.api.connection.ConnectionParameters;
import org.ow2.petals.cli.api.pref.PreferenceFileException;
import org.ow2.petals.cli.api.pref.Preferences;
import org.ow2.petals.cli.api.pref.exception.DirectoryAsPreferenceFileException;
import org.ow2.petals.cli.api.pref.exception.IncorrectPropertyNameException;
import org.ow2.petals.cli.api.pref.exception.IncorrectPropertyValueException;
import org.ow2.petals.cli.api.pref.exception.MissingDefaultPreferenceFileException;
import org.ow2.petals.cli.api.pref.exception.MissingPropertyException;
import org.ow2.petals.cli.api.pref.exception.PreferenceFileNotFoundException;
import org.ow2.petals.cli.api.pref.exception.PreferenceFileNotReadableException;

public abstract class AbstractPreferencesImpl implements Preferences {

    private static final String PREFERENCE_FILE_ERRORS_PATTERN = "The preference file contains %d error(s)";

    /**
     * Property name identifying the default alias
     */
    public static final String DEFAULT_ALIAS_PROPERTY = "alias.default";

    public static final String HOST_PROPERTY_SUFFIX = ".host";

    public static final String PORT_PROPERTY_SUFFIX = ".port";

    /**
     * The default connection parameters read from the default alias in the preferences file.
     */
    private ConnectionParameters defaultConnectionParameters = null;

    /**
     * Connection parameters per alias
     */
    private Map preferenceConnectionParameters = new HashMap<>();

    /**
     * Name of the environment variable containing the name of the preference file
     */
    private final String filePrefEnvVarName;

    /**
     * Name of the default resource used as preference file
     */
    private final String filePrefAsDefaultResource;

    protected AbstractPreferencesImpl(final String filePrefEnvVarName, final String filePrefAsDefaultResource) {
        this.filePrefEnvVarName = filePrefEnvVarName;
        this.filePrefAsDefaultResource = filePrefAsDefaultResource;
    }

    /**
     * {@inheritDoc}
     * 
     * Connection parameters are read from the default alias if exists.
     * 
     * @return The default connection parameters, or null if the default alias is not defined or has no
     *         connection parameters.
     */
    @Override
    public final ConnectionParameters getDefaultConnectionParameters() {
        return this.defaultConnectionParameters;
    }

    /**
     * 
     * @return The connection parameters per alias
     */
    @Override
    public final Map getPreferenceConnectionParameters() {
        return this.preferenceConnectionParameters;
    }

    /**
     * Entry point of the preference parameter initialization.
     * 
     * @throws MissingDefaultPreferenceFileException
     *             The default preference file is missing
     * @throws PreferenceFileNotFoundException
     *             The preference file was not found
     * @throws PreferenceFileException
     *             An error occurs reading the preference file
     */
    @Override
    public final void intializePreferenceParameters() throws MissingDefaultPreferenceFileException,
            PreferenceFileNotFoundException, PreferenceFileException {

        final File preferenceFilePath = this.getPreferenceFile();

        if (preferenceFilePath == null) {
            throw new MissingDefaultPreferenceFileException();
        } else if (preferenceFilePath.exists()) {
            final Properties preferenceProperties = AbstractPreferencesImpl
                    .loadPreferenceProperties(preferenceFilePath);

            final List errors = new ArrayList<>();
            final String defaultConnectionAlias = AbstractPreferencesImpl.initializeDefaultAlias(preferenceProperties,
                    errors);
            this.initializeAliases(preferenceProperties, errors);

            this.otherPreferenceInitialization(preferenceProperties, errors);

            final int errorNumber = errors.size();
            if (errorNumber > 0) {
                final StringBuilder errorMessage = new StringBuilder(String.format(PREFERENCE_FILE_ERRORS_PATTERN,
                        errorNumber));
                for (final Exception error : errors) {
                    errorMessage.append("\n\t - " + error.getMessage());
                }
                throw new PreferenceFileException(errorMessage.toString());
            }

            this.defaultConnectionParameters = this.preferenceConnectionParameters.get(defaultConnectionAlias);

        } else {
            // The preference file does not exist
            throw new PreferenceFileNotFoundException(preferenceFilePath);
        }
    }

    /**
     * Entry point to read extra preferences. The default implementation does nothing.
     * 
     * @param preferenceProperties
     *            The properties read from the preference file. Not null.
     * @param errors
     *            List in which errors must be added to have a report error. Not null.
     */
    protected void otherPreferenceInitialization(final Properties preferenceProperties, final List errors) {
        assert preferenceProperties != null;
        assert errors != null;
    }

    /**
     * Retrieve the default alias in the preferences
     * 
     * @param preferenceProperties
     *            The properties read from the preference file
     * @param errors
     *            List in which errors must be added to have a report error
     * @return The name of the default alias
     * @throws PreferenceFileException
     */
    private static final String initializeDefaultAlias(final Properties preferenceProperties,
            final List errors) throws PreferenceFileException {
        assert preferenceProperties != null;
        assert errors != null;

        final String defaultConnectionAlias = preferenceProperties
                .getProperty(AbstractPreferencesImpl.DEFAULT_ALIAS_PROPERTY);
        if (defaultConnectionAlias == null) {
            errors.add(new MissingPropertyException(AbstractPreferencesImpl.DEFAULT_ALIAS_PROPERTY));
        } else {
            preferenceProperties.remove(AbstractPreferencesImpl.DEFAULT_ALIAS_PROPERTY);
        }

        return defaultConnectionAlias;
    }
    
    /**
     * Get all suffixes accepted by an alias
     * 
     * @return All suffixes accepted by aliases
     */
    protected Collection getRecognizedSuffixes() {
        return Collections.unmodifiableCollection(Arrays
                .asList(new String[] { HOST_PROPERTY_SUFFIX, PORT_PROPERTY_SUFFIX }));
    }

    /**
     * Get all bases of properties that has not to be considered as alias
     * 
     * @return All bases of properties that has not to be considered as alias
     */
    protected Collection recognizedBasesAsNotAliases() {
        return Collections.EMPTY_LIST;
    }

    /**
     * Initialize the connection parameters of aliases
     * 
     * @param preferenceProperties
     *            The properties read from the preference file
     * @param errors
     *            List in which errors must be added to have a report error
     * @throws PreferenceFileException
     *             An error occurs managing
     */
    private final void initializeAliases(final Properties preferenceProperties,
            final List errors) throws PreferenceFileException {
        assert preferenceProperties != null;
        assert errors != null;

        final Collection recognizedSuffixes = this.getRecognizedSuffixes();
        final Collection recognizedBasesAsNotAliases = this.recognizedBasesAsNotAliases();

        final List treatedAlias = new ArrayList<>();
        final Set propertyNames = preferenceProperties.stringPropertyNames();
        for (final String propertyName : propertyNames) {
            final int endOfEntryAlias = propertyName.lastIndexOf('.');
            if (endOfEntryAlias == -1) {
                errors.add(new IncorrectPropertyNameException(propertyName));
                continue;
            }

            final String propertySuffix = propertyName.substring(endOfEntryAlias);
            if (!recognizedSuffixes.contains(propertySuffix)) {
                errors.add(new IncorrectPropertyNameException(propertyName));
                continue;
            }

            final String alias = propertyName.substring(0, endOfEntryAlias);
            if (!recognizedBasesAsNotAliases.contains(alias) && !treatedAlias.contains(alias)) {
                treatedAlias.add(alias);

                final String hostPropertyKey = alias + HOST_PROPERTY_SUFFIX;
                final String host = preferenceProperties.getProperty(hostPropertyKey);
                if (host == null) {
                    errors.add(new MissingPropertyException(hostPropertyKey));
                }

                final String portPropertyKey = alias + PORT_PROPERTY_SUFFIX;
                final String portString = preferenceProperties.getProperty(portPropertyKey);
                int port = -1;
                try {
                    if (portString == null) {
                        errors.add(new MissingPropertyException(portPropertyKey));
                    } else {
                        port = Integer.parseInt(portString);
                    }
                } catch (final NumberFormatException nfe) {
                    errors.add(new IncorrectPropertyValueException(portPropertyKey, portString, nfe));
                }

                this.preferenceConnectionParameters.put(alias,
                        this.createConnectionParameters(preferenceProperties, alias, host, port, errors));

            }
        }
    }

    /**
     * 

* Create the connection parameters of an alias according the need of the real CLI. *

*

* Extra connection parameters can be managed through this method. *

* * @param preferenceProperties * The properties read from the preference file * @param alias * The current alias * @param host * The host part of the connection parameters * @param port * The port part of the connection parameters * @param errors * List in which errors must be added to have a report error * @return The connection parameters as {@link ConnectionParameters} */ protected abstract ConnectionParameters createConnectionParameters(final Properties preferenceProperties, final String alias, final String host, final int port, final List errors); /** *

* Get the preferences file name. *

*

* The preference file name is defined: *

    *
  1. through an environment variable,
  2. *
  3. through a resource available on the classpath.
  4. *
*

* * @return The preferences file name, or null if the preference resource can not be found on the * classpath */ private File getPreferenceFile() { final String preferenceEnvVarPath = System.getenv(this.filePrefEnvVarName); File preferenceFilePath = null; if (preferenceEnvVarPath == null || preferenceEnvVarPath.trim().isEmpty()) { final URL defaultPrefFileUrl = Thread.currentThread().getContextClassLoader() .getResource(this.filePrefAsDefaultResource); try { if (defaultPrefFileUrl != null) { preferenceFilePath = new File(defaultPrefFileUrl.toURI()); } } catch (final URISyntaxException e) { throw new IllegalStateException("this should never happen", e); } } else { preferenceFilePath = new File(preferenceEnvVarPath); } return preferenceFilePath; } /** * Load the preference file as a properties file * * @param preferenceFilePath * The preference file. Must exist. * @return The content of the preference file as {@link Properties} * @throws PreferenceFileNotReadableException * The preference file can not be read */ private static final Properties loadPreferenceProperties(final File preferenceFilePath) throws PreferenceFileException { if (preferenceFilePath.isFile()) { if (preferenceFilePath.canRead()) { final Properties preferenceProperties = new Properties(); try { final InputStream is = new FileInputStream(preferenceFilePath); try { preferenceProperties.load(is); } finally { is.close(); } } catch (final IOException ioe) { throw new PreferenceFileException("An error occurs reading the preference file", ioe); } return preferenceProperties; } else { throw new PreferenceFileNotReadableException(preferenceFilePath); } } else { throw new DirectoryAsPreferenceFileException(preferenceFilePath); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy