/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@ow2.org
 *
 * This 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 any later version.
 *
 * This 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Initial developer: Florent BENOIT
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.lib.security;

import java.security.Policy;

import javax.security.jacc.PolicyConfiguration;
import javax.security.jacc.PolicyConfigurationFactory;
import javax.security.jacc.PolicyContextException;

import org.ow2.jonas.lib.security.mapping.JPolicyUserRoleMapping;


/**
 * Defines an abstract PermissionManager class which will manage JACC
 * permissions for an ejbjar, webapp, etc.
 * @author Florent Benoit
 */
public abstract class AbsPermissionManager {

    /**
     * JACC Policy configuration.
     */
    private PolicyConfiguration policyConfiguration = null;

    /**
     * Context ID.
     */
    private String contextId = null;

    /**
     * Policy to use.
     */
    private static Policy policy = null;

    /**
     * Default Constructor.
     * @param contextId context ID used for PolicyContext
     * @throws PermissionManagerException if permissions can't be set
     */
    public AbsPermissionManager(final String contextId) throws PermissionManagerException {
        this(contextId, true);
    }


    /**
     * Default Constructor.
     * @param contextId context ID used for PolicyContext
     * @param remove - if true, the policy configuration will be removed.
     * @throws PermissionManagerException if permissions can't be set
     */
    public AbsPermissionManager(final String contextId,
                                final boolean remove) throws PermissionManagerException {
        this.contextId = contextId;

        PolicyConfigurationFactory policyConfigurationFactory = null;
        try {
            policyConfigurationFactory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (PolicyContextException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            this.policyConfiguration = policyConfigurationFactory.getPolicyConfiguration(contextId, remove);
        } catch (PolicyContextException pce) {
            throw new PermissionManagerException(
                    "Error when trying to get the PolicyConfiguration object with contextId '" + contextId + "' : "
                            + pce.getMessage(), pce);
        }

        // Policy to use
        policy = Policy.getPolicy();
    }

    /**
     * Delete this object.
     * @throws PermissionManagerException if the configuration can't be deleted
     */
    public void delete() throws PermissionManagerException {
        resetDeploymentDesc();

        try {
            policyConfiguration.delete();
        } catch (PolicyContextException pce) {
            throw new PermissionManagerException("Can't delete policyConfiguration object", pce);
        }
        policyConfiguration = null;

        // Also delete user-to-role mapping
        JPolicyUserRoleMapping.removeUserToRoleMapping(contextId);

        // Policy need to be refresh
        policy.refresh();
    }

    /**
     * Commit the Policy Configuration.
     * @throws PermissionManagerException if commit can't be done
     */
    public void commit() throws PermissionManagerException {
        try {
            policyConfiguration.commit();
            policy.refresh();
        } catch (PolicyContextException pce) {
            throw new PermissionManagerException("Can't commit configuration", pce);
        }
    }

    /**
     * Reset Deployment Descriptor.
     */
    protected abstract void resetDeploymentDesc();

    /**
     * @return Returns the policy.
     */
    protected static Policy getPolicy() {
        return policy;
    }

    /**
     * @param policy The policy to set.
     */
    protected static void setPolicy(final Policy policy) {
        AbsPermissionManager.policy = policy;
    }

    /**
     * @return Returns the contextId.
     */
    protected String getContextId() {
        return contextId;
    }

    /**
     * @param contextId The contextId to set.
     */
    protected void setContextId(final String contextId) {
        this.contextId = contextId;
    }

    /**
     * @return Returns the policyConfiguration.
     */
    protected PolicyConfiguration getPolicyConfiguration() {
        return policyConfiguration;
    }

    /**
     * @param policyConfiguration The policyConfiguration to set.
     */
    protected void setPolicyConfiguration(final PolicyConfiguration policyConfiguration) {
        this.policyConfiguration = policyConfiguration;
    }

}
