Package org.glite.authz.pap.papmanagement

Source Code of org.glite.authz.pap.papmanagement.PapManager

/**
* 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.papmanagement;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.glite.authz.pap.common.Pap;
import org.glite.authz.pap.common.utils.Utils;
import org.glite.authz.pap.distribution.DistributionConfiguration;
import org.glite.authz.pap.distribution.DistributionConfigurationException;
import org.glite.authz.pap.distribution.DistributionModule;
import org.glite.authz.pap.repository.dao.DAOFactory;
import org.glite.authz.pap.repository.dao.PapDAO;
import org.glite.authz.pap.repository.exceptions.AlreadyExistsException;
import org.glite.authz.pap.repository.exceptions.NotFoundException;
import org.glite.authz.pap.repository.exceptions.RepositoryException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This class provides methods to manage {@link Pap} objects (i.e. add, update, delete, etc). It
* also provides methods to manage the <code>Pap</code> ordering. All of these methods affects both
* the repository and the configuration.
* <p>
* Use the {@link PapManager#initialize()} method before doing anything with this class.
* <p>
* The PAP service has always one (special) pap defined. This pap is commonly identified in the code
* with the word <i>default</i>. The alias of this special pap is defined by the constant
* {@link Pap#DEFAULT_PAP_ALIAS} (its value is {@value Pap#DEFAULT_PAP_ALIAS}). The <i>default</i>
* pap is local and public.
* <p>
* <b>Paps ordering</b><br>
* For the policy evaluation process (performed by the <i>PDP</i>) the oder of the policies matters.
* Therefore it is possible to specify an ordering for the <code>Pap</code> objects (which are
* containers of policies). The policies of <code>Pap</code> <i>A</i> are evaluated before the
* policies of <code>Pap</code> <i>B</i> if <i>A</i> comes before <i>B</i> in the order. There are
* two points concerning the pap ordering that must be kept in mind:<br>
* 1. if the <i>defdault</i> pap is <b>not</b> listed in the pap ordering then it is automatically
* placed as the first pap in the order;<br>
* 2. if the pap ordering does not contains all the defined paps then the paps not listed in the
* order comes after (except the <i>default</i> pap, see point 1).
* <p>
* <b>Repository and configuration</b><br>
* The information associated to a <code>Pap</code> object are stored both in the repository and in
* the configuration. Since the configuration can be changed off-line (when the PAP service is not
* running), synchronization between the configuration and the repository is needed at startup time.
* See the method {@link PapManager#synchronizeRepositoryWithConfiguration()}.<br>
* Information like the polling interval and the pap ordering are only in the configuration.
*
* @see Pap
* @see PapContainer
* @see DistributionConfiguration
* @see PapDAO
* @see DistributionModule
*/
public class PapManager {

    private static PapManager instance = null;
    private static final Logger log = LoggerFactory.getLogger(PapManager.class);

    private String[] configurationPapOrdering;
    private DistributionConfiguration distributionConfiguration;
    private PapDAO papDAO;

    /**
     * Constructor.
     * <p>
     * The <i>default</i> pap is created if it doesn't exists.
     */
    private PapManager() {

        papDAO = DAOFactory.getDAOFactory().getPapDAO();

        createDefaultPapIfNotExists();

        distributionConfiguration = DistributionConfiguration.getInstance();

        configurationPapOrdering = distributionConfiguration.getPapOrdering();

        synchronizeRepositoryWithConfiguration();
    }

    public static PapManager getInstance() {

        if (instance == null) {
            throw new PapManagerException("Please initialize configuration before calling the instance method!");
        }
        return instance;
    }

    /**
     * Initialization method. The main purpose of this method is to create (through the constructor)
     * the <i>default</i> pap it doesn't exits.
     */
    public static void initialize() {
        if (instance == null) {
            instance = new PapManager();
        }
    }

    /**
     * Add a pap to the repository and to the configuration.
     *
     * @param pap the pap to be added.
     *
     * @throws PapManagerException if the alias of the pap is equal to {@link Pap#DEFAULT_PAP_ALIAS}
     *             .
     * @throws AlreadyExistsException if the alias of the pap already exists.
     */
    public void addPap(Pap pap) {

        String papAlias = pap.getAlias();

        if (Pap.DEFAULT_PAP_ALIAS.equals(papAlias)) {
            throw new PapManagerException("Forbidden alias: " + papAlias);
        }

        if (exists(papAlias)) {
            throw new AlreadyExistsException("pap \"" + papAlias + "\" already exists");
        }

        distributionConfiguration.savePap(pap);
        papDAO.store(pap);

        PapContainer papContainer = new PapContainer(pap);
        papContainer.createRootPolicySet();
    }

    /**
     * Delete a pap from the configuration and from the repository.
     *
     * @param papAlias the alias of the pap to remove.
     *
     * @throws NotFoundException if a pap with the given alias does not exists.
     * @throws PapManagerException if the alias is equal to {@link Pap#DEFAULT_PAP_ALIAS}.
     */
    public void deletePap(String papAlias) {

        if (Pap.DEFAULT_PAP_ALIAS.equals(papAlias)) {
            throw new PapManagerException("Deleting the default pap is not allowed");
        }

        distributionConfiguration.removePap(papAlias);
        papDAO.delete(papAlias);

        // pap ordering could be modified.
        configurationPapOrdering = distributionConfiguration.getPapOrdering();
    }

    /**
     * Checks for the existence of a pap.
     *
     * @param papAlias alias of the pap.
     * @return <code>true</code> if a pap with the given alias exists, <code>false</code> otherwise.
     */
    public boolean exists(String papAlias) {
        return papDAO.exists(papAlias);
    }

    /**
     * Returns a <code>List</code> of all the defined paps.<br>
     * The paps in the list are ordered following the pap ordering as specified in the
     * configuration.
     *
     * @return an <i>ordered</i> <code>List</code> of all the defined paps.
     */
    public List<Pap> getAllPaps() {
        return getPapList();
    }

    /**
     * Returns a <code>List</code> of all the defined local paps.<br>
     * The paps in the list are ordered following the pap ordering as specified in the
     * configuration.
     *
     * @return an <i>ordered</i> <code>List</code> of all the defined local paps.
     */
    public List<Pap> getLocalPaps() {

        List<Pap> resultList = new LinkedList<Pap>();

        for (Pap pap : getPapList()) {
            if (pap.isLocal()) {
                resultList.add(pap);
            }
        }
        return resultList;
    }

    /**
     * Returns a <code>List</code> of all the defined remote paps.<br>
     * The paps in the list are ordered following the pap ordering as specified in the
     * configuration.
     *
     * @return an <i>ordered</i> <code>List</code> of all the defined remote paps.
     */
    public List<Pap> getRemotePaps() {

        List<Pap> remotePapList = new LinkedList<Pap>();

        for (Pap pap : getPapList()) {
            if (pap.isRemote()) {
                remotePapList.add(pap);
            }
        }
        return remotePapList;
    }

    /**
     * Returns the pap identified by the given alias.
     *
     * @param papAlias the alias of the pap to retrieve.
     * @return the <code>Pap</code> associated to the given alias.
     *
     * @throws NotFoundException if a pap with the given alias was not found.
     */
    public Pap getPap(String papAlias) {
        return papDAO.get(papAlias);
    }

    /**
     * Convenience method to get a <code>PapContainer</code> from a pap alias.
     *
     * @param papAlias alias of the pap.
     * @return the <code>PapContainer</code> of the pap with the given alias.
     *
     * @throws NotFoundException if a pap with the given alias was not found.
     */
    public PapContainer getPapContainer(String papAlias) {
        return new PapContainer(getPap(papAlias));
    }

    /**
     * Returns the pap ordering as defined in the configuration.
     *
     * @return the pap ordering as defined in the configuration.
     */
    public String[] getPapOrdering() {
        return configurationPapOrdering;
    }

    /**
     * Returns a <code>List</code> of all the defined public paps.<br>
     * The paps in the list are ordered following the pap ordering as specified in the
     * configuration.
     *
     * @return an <i>ordered</i> <code>List</code> of all the defined public paps.
     */
    public List<Pap> getPublicPaps() {

        List<Pap> resultList = new LinkedList<Pap>();

        for (Pap pap : getPapList()) {
            if (pap.isVisibilityPublic()) {
                resultList.add(pap);
            }
        }
        return resultList;
    }

    /**
     * Set the pap ordering in the configuration.<br>
     * If the given array is <code>null</code> or <code>empty</code> then the previous order (if
     * any) is cleared.
     *
     * @param aliasArray array of pap aliases defining the new pap ordering (can be
     *            <code>null</code> or <code>empty</code>).
     *
     * @throws DistributionConfigurationException if the new ordering contains duplicated or unknown
     *             aliases.
     */
    public void setPapOrdering(String[] aliasArray) {
        distributionConfiguration.savePapOrdering(aliasArray);

        // update to the new order
        configurationPapOrdering = distributionConfiguration.getPapOrdering();
    }

    /**
     * Update the information associated to a pap.
     *
     * @param newPap update the information of the pap with the same alias of the given one.
     *
     * @throws NotFoundException if a pap with the same alias of the given one was not found.
     * @throws PapManagerException if the given pap is <code>null</code>.
     */
    public void updatePap(Pap newPap) {

        if (newPap == null) {
            throw new PapManagerException("pap cannot be null");
        }

        String alias = newPap.getAlias();

        if (Pap.DEFAULT_PAP_ALIAS.equals(alias)) {
            updateDefaultPap(newPap);
            return;
        }

        Pap oldPap = papDAO.get(alias);

        // id (and alias) cannot change
        newPap.setId(oldPap.getId());

        distributionConfiguration.savePap(newPap);
        papDAO.update(newPap);
    }

    /**
     * Builds a list of alias of all the defined paps that follows the pap ordering defined in the
     * configuration.
     *
     * @return a list of alias of all the defined paps that follows the pap ordering defined in the
     *         configuration.
     */
    private List<String> buildOrderedAliasList() {

        List<String> repositoryAliasList = papDAO.getAliasList();

        int configurationArraySize = configurationPapOrdering.length;

        if (configurationArraySize > repositoryAliasList.size()) {
            throw new PapManagerException("BUG: configuration contains more paps than the repository");
        }

        int defaultPapAliasIdx = repositoryAliasList.indexOf(Pap.DEFAULT_PAP_ALIAS);

        if (defaultPapAliasIdx == -1) {
            throw new PapManagerException("BUG: default pap does not exist in the repository");
        }

        /* enforce the order specified in the configuration file */

        List<String> configurationAliasOrderedList = new LinkedList<String>();

        // if the default pap is not specified in the order in configuration then it goes for first
        if (Utils.indexOf(Pap.DEFAULT_PAP_ALIAS, configurationPapOrdering) == -1) {
            configurationAliasOrderedList.add(Pap.DEFAULT_PAP_ALIAS);
        }

        for (int i = 0; i < configurationArraySize; i++) {
            configurationAliasOrderedList.add(configurationPapOrdering[i]);
        }

        // follow the order specified in the configuration file
        for (int i = 0; i < configurationAliasOrderedList.size(); i++) {
            String alias = configurationAliasOrderedList.get(i);

            int aliasIndex = repositoryAliasList.indexOf(alias);

            if (aliasIndex == -1) {
                throw new PapManagerException("BUG: initialization error. pap defined in the configuration is not in the repository");
            }

            Collections.swap(repositoryAliasList, aliasIndex, i);
        }

        return repositoryAliasList;
    }

    /** Create the <i>default</i> pap if it doesn't exist. */
    private void createDefaultPapIfNotExists() {

        Pap defaultPap;

        if (!papDAO.exists(Pap.DEFAULT_PAP_ALIAS)) {

            defaultPap = Pap.makeDefaultPAP();
            papDAO.store(defaultPap);

        } else {
            defaultPap = papDAO.get(Pap.DEFAULT_PAP_ALIAS);
        }

        PapContainer defaultPapContainer = getPapContainer(Pap.DEFAULT_PAP_ALIAS);

        // check if the root policy set exists
        if (defaultPapContainer.hasPolicySet(defaultPapContainer.getRootPolicySetId())) {
            return;
        }

        // create the root policy set
        defaultPapContainer.createRootPolicySet();
    }

    /**
     * Returns a <code>List</code> of all the defined paps.<br>
     * The paps in the list are ordered following the pap ordering as specified in the
     * configuration.
     *
     * @return an <i>ordered</i> <code>List</code> of all the defined paps.
     */
    private List<Pap> getPapList() {
        List<String> aliasOrderedList = buildOrderedAliasList();
        List<Pap> papList = new ArrayList<Pap>(aliasOrderedList.size());

        for (String alias : aliasOrderedList) {
            papList.add(papDAO.get(alias));
        }
        return papList;
    }

    /**
     * The information associated to a <code>Pap</code> object are stored both in the repository and
     * in the configuration. Since the configuration can be changed off-line (when the PAP service
     * is not running), synchronization between the configuration and the repository is needed. This
     * method synchronize these information doing the following steps:<br>
     * 1. add to the repository all the paps defined in the configuration that are not present in
     * the repository;<br>
     * 2. if a pap is defined both in the repository and in the configuration then update the
     * information in the repository with the one found in the configuration (if they differs);<br>
     * 3. delete from the repository the paps that are not in the configuration.
     *
     */
    private void synchronizeRepositoryWithConfiguration() {

        List<Pap> papListFromConfiguration = DistributionConfiguration.getInstance().getPapList();

        if (papListFromConfiguration.isEmpty()) {
            log.info("No remote paps has been defined");
        }

        // make sure that all paps defined in the configuration are also in the repository
        for (Pap papFromConfiguration : papListFromConfiguration) {
            try {

                String papAlias = papFromConfiguration.getAlias();

                Pap papFromRepository = papDAO.get(papAlias);

                if (papFromConfiguration.equals(papFromRepository)) {
                    continue;
                }

                // paps in the repository but must be updated with the information of the paps found
                // in the configuration. Since the cache of a pap must be removed we can delete the
                // pap and store it again
                log.info("Settings for pap \"" + papAlias + "\" has been updated. Invalidating cache");
                papDAO.delete(papAlias);

            } catch (NotFoundException e) {
                // the pap is not in the repository therefore go on and store it
            }

            papDAO.store(papFromConfiguration);
            PapContainer papContainer = new PapContainer(papFromConfiguration);
            papContainer.createRootPolicySet();
        }

        // remove from the repository paps that are not in the configuration
        for (String alias : papDAO.getAliasList()) {

            // do not remove the default pap
            if (alias.equals(Pap.DEFAULT_PAP_ALIAS)) {
                continue;
            }

            boolean notFoundInConfiguration = true;
            for (Pap papFromConfiguration : papListFromConfiguration) {
                if (alias.equals(papFromConfiguration.getAlias())) {
                    notFoundInConfiguration = false;
                    break;
                }
            }

            if (notFoundInConfiguration) {
                papDAO.delete(alias);
                log.info("Removed pap \"" + alias
                        + "\" from the repository because it hasn't been found in the configuration file.");
            }
        }
    }

    /**
     * Updates the <i>default</i> pap.
     *
     * @param newDefaultPap
     */
    private void updateDefaultPap(Pap newDefaultPap) {

        if (!Pap.DEFAULT_PAP_ALIAS.equals(newDefaultPap.getAlias())) {
            throw new RepositoryException("Invalid alias for default pap. Cannot perform updateDefaultPap request.");
        }

        Pap oldDefaultPap = getPap(Pap.DEFAULT_PAP_ALIAS);

        newDefaultPap.setId(oldDefaultPap.getId());

        papDAO.update(newDefaultPap);
    }
}
TOP

Related Classes of org.glite.authz.pap.papmanagement.PapManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.