/** * Copyright (c) Members of the EGEE Collaboration. 2006-2009. * See http://www.eu-egee.org/partners/ for details on the copyright holders. * * 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. */ package org.glite.authz.pap.distribution; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.glite.authz.pap.common.PAPConfiguration; import org.glite.authz.pap.common.Pap; import org.glite.authz.pap.common.utils.Utils; import org.glite.authz.pap.papmanagement.PapManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class has methods to read distribution information from configuration and to write back * these information to the configuration file. The reason for having both read and write facilities * is that these information can be modified through the command line. * * @see PapManager * @see Pap */ public class DistributionConfiguration { private static final Logger log = LoggerFactory.getLogger(DistributionConfiguration.class); private static final String PAPS_STANZA = "paps"; private static final String PAPS_PROPERTIES_STANZA = "paps:properties"; private static DistributionConfiguration instance = null; private PAPConfiguration papConfiguration; private DistributionConfiguration() { papConfiguration = PAPConfiguration.instance(); } public static DistributionConfiguration getInstance() { if (instance == null) instance = new DistributionConfiguration(); return instance; } /** * Returns the <code>alias</code> key part (INI configuration) of a pap. This is the first part * common to all the keys associated to a pap. * * @param papAlias alias of the pap. * @return the key build as {@link DistributionConfiguration#PAPS_STANZA} + "." + * <i>papAlias</i> */ private static String aliasKey(String papAlias) { return PAPS_STANZA + "." + papAlias; } /** * Returns the <i>dn</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>dn</i> key. */ private static String dnKey(String papAlias) { return aliasKey(papAlias) + "." + "dn"; } /** * Returns the <i>enabled</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>enabled</i> key. */ private static String enabledKey(String papAlias) { return aliasKey(papAlias) + "." + "enabled"; } /** * Returns the <i>hostname</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>hostname</i> key. */ private static String hostnameKey(String papAlias) { return aliasKey(papAlias) + "." + "hostname"; } /** * Returns the <i>minKeyLength</i> key for all the paps. * * @return the <i>minKeyLength</i> key. */ @SuppressWarnings("unused") private static String minKeyLengthKey() { return PAPS_STANZA + "." + "min_key_length"; } /** * Returns the <i>minKeyLength</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>minKeyLength</i> key. */ @SuppressWarnings("unused") private static String minKeyLengthKey(String papAlias) { return aliasKey(papAlias) + "." + "min_key_length"; } /** * Returns the <i>papOrdering</i> key. * * @return the <i>papOrdering</i> key. */ private static String papOrderingKey() { return PAPS_PROPERTIES_STANZA + "." + "ordering"; } /** * Returns the <i>pathKey</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>pathKey</i> key. */ private static String pathKey(String papAlias) { return aliasKey(papAlias) + "." + "path"; } /** * Returns the <i>pollInterval</i> key. * * @return the <i>pollIntervall</i> key. */ private static String pollIntervallKey() { return PAPS_PROPERTIES_STANZA + "." + "poll_interval"; } /** * Returns the <i>port</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>port</i> key. */ private static String portKey(String papAlias) { return aliasKey(papAlias) + "." + "port"; } /** * Returns the <i>protocol</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>protocol</i> key. */ private static String protocolKey(String papAlias) { return aliasKey(papAlias) + "." + "protocol"; } /** * Returns the <i>type</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>type</i> key. */ private static String typeKey(String papAlias) { return aliasKey(papAlias) + "." + "type"; } /** * Returns the <i>visibilityPublic</i> key of a pap. * * @param papAlias alias if the pap. * @return the <i>visibilityPublic</i> key. */ private static String visibilityPublicKey(String papAlias) { return aliasKey(papAlias) + "." + "public"; } /** * Reads the list of defined paps from configuration. Paps are read following without a specific * order, there the returned list does <b>not</b> follow the paps ordering. * * @return list of paps defined in the configuration (not ordered). * * @throws DistributionConfigurationException if a configuration error was found (the reason in * the exception message). */ @SuppressWarnings("unchecked") public List<Pap> getPapList() { Set<String> aliasSet = Utils.getAliasSet((Iterator<String>) papConfiguration.getKeys(PAPS_STANZA)); List<Pap> papList = new ArrayList<Pap>(aliasSet.size()); for (String papAlias : aliasSet) { if (Pap.DEFAULT_PAP_ALIAS.equals(papAlias)) { continue; } papList.add(getPapFromProperties(papAlias)); } return papList; } /** * Reads the pap ordering (list of aliases) from the configuration. * * @return an array of aliases (can be empty, i.e. no ordering defined). * * @throws DistributionConfigurationException if the ordering contains an undefined alias and/or * duplicated aliases (the reason is in the exception message). */ public String[] getPapOrdering() { String[] papOrderingArray = papConfiguration.getStringArray(papOrderingKey()); if (papOrderingArray == null) { papOrderingArray = new String[0]; } validatePapOrdering(papOrderingArray); return papOrderingArray; } /** * Reads the <i>polling interval</i> from the configuration. * * @return the <i>polling interval</i> in seconds. */ public long getPollIntervall() { long pollIntervalInSecs = papConfiguration.getLong(pollIntervallKey()); log.info("Polling interval for remote paps is set to: " + pollIntervalInSecs + " seconds"); return pollIntervalInSecs; } /** * Set the polling interval into configuration. * * @param seconds new polling interval in seconds */ public void savePollInterval(long seconds) { papConfiguration.clearDistributionProperty(pollIntervallKey()); papConfiguration.setDistributionProperty(pollIntervallKey(), seconds); papConfiguration.saveStartupConfiguration(); } /** * Removes a pap from the configuration. * * @param papAlias alias of the pap to remove. */ public void removePap(String papAlias) { String[] oldPapOrdering = getPapOrdering(); clearPapProperties(papAlias); int newArraySize = oldPapOrdering.length - 1; if (newArraySize >= 0) { String[] newPapOrdering = new String[newArraySize]; for (int i = 0, j = 0; i < oldPapOrdering.length; i++) { String aliasItem = oldPapOrdering[i]; if (!(aliasItem.equals(papAlias))) { if (j < newArraySize) { newPapOrdering[j] = aliasItem; j++; } } } savePapOrdering(newPapOrdering); } papConfiguration.saveStartupConfiguration(); } /** * Saves a pap into configuration. * <p> * If the pap already exists its information are updated with the new one. * * @param pap the pap to be saved. */ public void savePap(Pap pap) { setPapProperties(pap); papConfiguration.saveStartupConfiguration(); } /** * Save the given paps ordering into configuration. * <p> * If the given array is <code>null</code> or <code>empty</code> the previous ordering (if any) * is cleared (i.e. no ordering defined). * * @param aliasArray the array of aliases identifying the new ordering (can be <code>null</code> * or <code>empty</code>). * * @throws DistributionConfigurationException if the new ordering contains duplicated or unknown * aliases. */ public void savePapOrdering(String[] aliasArray) { if (aliasArray == null) { papConfiguration.clearDistributionProperty(papOrderingKey()); papConfiguration.saveStartupConfiguration(); return; } validatePapOrdering(aliasArray); if (aliasArray.length == 0) { papConfiguration.clearDistributionProperty(papOrderingKey()); papConfiguration.saveStartupConfiguration(); return; } StringBuilder sb = new StringBuilder(aliasArray[0]); for (int i = 1; i < aliasArray.length; i++) { sb.append(", " + aliasArray[i]); } log.info("Setting new paps ordering to: " + sb.toString()); papConfiguration.clearDistributionProperty(papOrderingKey()); papConfiguration.setDistributionProperty(papOrderingKey(), aliasArray); papConfiguration.saveStartupConfiguration(); } /** * Checks for the existence of an alias in the configuration. * * @param alias the alias to check. * @return <code>true</code> if the alias exists in the configuration, <code>false</code> * otherwise. */ private boolean aliasExists(String alias) { if (!Utils.isDefined(alias)) { return false; } if (Pap.DEFAULT_PAP_ALIAS.equals(alias)) { return true; } String value = papConfiguration.getString(typeKey(alias)); if (!Utils.isDefined(value)) { return false; } return true; } /** * Clears the properites associated to a pap. * * @param papAlias alias of the pap to clear. */ private void clearPapProperties(String papAlias) { papConfiguration.clearDistributionProperty(dnKey(papAlias)); papConfiguration.clearDistributionProperty(hostnameKey(papAlias)); papConfiguration.clearDistributionProperty(enabledKey(papAlias)); papConfiguration.clearDistributionProperty(portKey(papAlias)); papConfiguration.clearDistributionProperty(pathKey(papAlias)); papConfiguration.clearDistributionProperty(protocolKey(papAlias)); papConfiguration.clearDistributionProperty(visibilityPublicKey(papAlias)); papConfiguration.clearDistributionProperty(typeKey(papAlias)); } /** * Returns a <code>Pap</code> reading it from configuration. * * @param papAlias alias of the pap to get. * @return the retrieved <code>Pap</code>. * * @throws DistributionConfigurationException if there is some configuration error like missing * required information (specific reason is put in the exception message). */ private Pap getPapFromProperties(String papAlias) { String type = papConfiguration.getString(typeKey(papAlias)); if (type == null) { throw new DistributionConfigurationException("\"type\" is not set for remote pap \"" + papAlias + "\""); } boolean isLocal = Pap.isLocal(type); String dn = papConfiguration.getString(dnKey(papAlias)); String hostname = papConfiguration.getString(hostnameKey(papAlias)); if ((hostname == null) && (!isLocal)) { throw new DistributionConfigurationException("\"hostname\" is not set for remote pap \"" + papAlias + "\""); } String port = papConfiguration.getString(portKey(papAlias)); String path = papConfiguration.getString(pathKey(papAlias)); String protocol = papConfiguration.getString(protocolKey(papAlias)); boolean visibilityPublic = papConfiguration.getBoolean(visibilityPublicKey(papAlias)); boolean enabled = papConfiguration.getBoolean(enabledKey(papAlias), false); Pap pap = new Pap(papAlias, isLocal, dn, hostname, port, path, protocol, visibilityPublic); pap.setEnabled(enabled); return pap; } /** * Set the properties of a pap into configuration. * * @param pap the pap to set the properties for. */ private void setPapProperties(Pap pap) { String papAlias = pap.getAlias(); papConfiguration.setDistributionProperty(typeKey(papAlias), pap.getTypeAsString()); papConfiguration.setDistributionProperty(enabledKey(papAlias), pap.isEnabled()); papConfiguration.setDistributionProperty(dnKey(papAlias), pap.getDn()); papConfiguration.setDistributionProperty(hostnameKey(papAlias), pap.getHostname()); papConfiguration.setDistributionProperty(portKey(papAlias), pap.getPort()); papConfiguration.setDistributionProperty(pathKey(papAlias), pap.getPath()); papConfiguration.setDistributionProperty(protocolKey(papAlias), pap.getProtocol()); papConfiguration.setDistributionProperty(visibilityPublicKey(papAlias), pap.isVisibilityPublic()); } /** * checks if the given alias array is a valid pap ordering. * @param aliasArray array of aliases to be validated. * * @throws DistributionConfigurationException if there are unknown or duplicated aliases. */ private void validatePapOrdering(String[] aliasArray) { if (aliasArray == null) { throw new DistributionConfigurationException("aliasArray is null"); } Set<String> aliasSet = new HashSet<String>(aliasArray.length); for (String alias : aliasArray) { if (aliasSet.contains(alias)) { throw new DistributionConfigurationException(String.format("Error in remote paps order: alias \"%s\" appears more than one time", alias)); } aliasSet.add(alias); if (!aliasExists(alias)) { throw new DistributionConfigurationException(String.format("Error in remote paps order: unknown alias \"%s\"", alias)); } } } }