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:
*
* - through an environment variable,
* - through a resource available on the classpath.
*
*
*
* @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