Package org.jboss.security.xacml.sunxacml

Source Code of org.jboss.security.xacml.sunxacml.PolicyReference

/*
* @(#)PolicyReference.java
*
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*   1. Redistribution of source code must retain the above copyright notice,
*      this list of conditions and the following disclaimer.
*
*   2. Redistribution in binary form must reproduce the above copyright
*      notice, this list of conditions and the following disclaimer in the
*      documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use in
* the design, construction, operation or maintenance of any nuclear facility.
*/

package org.jboss.security.xacml.sunxacml;




import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.security.xacml.sunxacml.combine.CombiningAlgorithm;
import org.jboss.security.xacml.sunxacml.ctx.Result;
import org.jboss.security.xacml.sunxacml.ctx.Status;
import org.jboss.security.xacml.sunxacml.finder.PolicyFinder;
import org.jboss.security.xacml.sunxacml.finder.PolicyFinderResult;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;


/**
* This class is used as a placeholder for the PolicyIdReference and
* PolicySetIdReference fields in a PolicySetType. When a reference is used
* in a policy set, it is telling the PDP to use an external policy in
* the current policy. Each time the PDP needs to evaluate that policy
* reference, it asks the policy finder for the policy. Typically the policy
* finder will have cached the referenced policy, so this isn't too slow.
* <p>
* NOTE: all of the accessor methods, the match method, and the evaluate method
* require this class to ask its <code>PolicyFinder</code> for the referenced
* policy, which can be a slow operation. Care should be taken, therefore in
* calling these methods too often. Also note that it's not safe to cache the
* results of these calls, since the referenced policy may change.
*
* @since 1.0
* @author Seth Proctor
*/
public class PolicyReference extends AbstractPolicy
{
   
    /**
     * Identifies this as a reference to a <code>Policy</code>
     */
    public static final int POLICY_REFERENCE = 0;

    /**
     * Identifies this as a reference to a <code>PolicySet</code>
     */
    public static final int POLICYSET_REFERENCE = 1;

    // the reference
    private URI reference;

    // the reference type
    private int policyType;

    // and version constraints on this reference
    private VersionConstraints constraints;

    // the finder to use in finding the referenced policy
    private PolicyFinder finder;

    // the meta-data for the parent policy
    private PolicyMetaData parentMetaData;

    // the logger we'll use for all messages
    private static final Logger logger =
        Logger.getLogger(PolicyReference.class.getName());

    /**
     * Creates a new <code>PolicyReference</code> instance. This has no
     * constraints on version matching. Note that an XACML 1.x reference may
     * not have any constraints.
     *
     * @param reference the reference to the policy
     * @param policyType one of the two fields in this class
     * @param finder the <code>PolicyFinder</code> used to handle the reference
     * @param parentMetaData the meta-data associated with the containing
     *                       (parent) policy
     *
     * @throws IllegalArgumentException if the input policyType isn't valid
     */
    public PolicyReference(URI reference, int policyType, PolicyFinder finder,
                           PolicyMetaData parentMetaData)
        throws IllegalArgumentException
    {
        this(reference, policyType, new VersionConstraints(null, null, null),
             finder, parentMetaData);
    }

    /**
     * Creates a new <code>PolicyReference</code> instance with version
     * constraints. Note that an XACML 1.x reference may not have any
     * constraints.
     *
     * @param reference the reference to the policy
     * @param policyType one of the two fields in this class
     * @param constraints any optional constraints on the version of the
     *                    referenced policy (this is never null, but
     *                    it may impose no constraints, and in fact will
     *                    never impose constraints when used from a pre-2.0
     *                    XACML policy)
     * @param finder the <code>PolicyFinder</code> used to handle the reference
     * @param parentMetaData the meta-data associated with the containing
     *                       (parent) policy
     *
     * @throws IllegalArgumentException if the input policyType isn't valid
     */
    public PolicyReference(URI reference, int policyType,
                           VersionConstraints constraints, PolicyFinder finder,
                           PolicyMetaData parentMetaData)
        throws IllegalArgumentException {

        // check if input policyType is a valid value
        if ((policyType != POLICY_REFERENCE) &&
            (policyType != POLICYSET_REFERENCE))
            throw new IllegalArgumentException("Input policyType is not a" +
                                               "valid value");

        this.reference = reference;
        this.policyType = policyType;
        this.constraints = constraints;
        this.finder = finder;
        this.parentMetaData = parentMetaData;
    }

    /**
     * Creates an instance of a <code>PolicyReference</code> object based on
     * a DOM node.
     *
     * @deprecated As of 2.0 you should avoid using this method and should
     *             instead use the version that takes a
     *             <code>PolicyMetaData</code> instance. This method will
     *             only work for XACML 1.x policies.
     *
     * @param root the DOM root of a PolicyIdReference or a
     *             PolicySetIdReference XML type
     * @param finder the <code>PolicyFinder</code> used to handle the reference
     *
     * @exception ParsingException if the node is invalid
     */
    public static PolicyReference getInstance(Node root, PolicyFinder finder)
        throws ParsingException
    {
        return getInstance(root, finder, new PolicyMetaData());
    }

    /**
     * Creates an instance of a <code>PolicyReference</code> object based on
     * a DOM node.
     *
     * @param root the DOM root of a PolicyIdReference or a
     *             PolicySetIdReference XML type
     * @param finder the <code>PolicyFinder</code> used to handle the reference
     * @param metaData the meta-data associated with the containing policy
     *
     * @exception ParsingException if the node is invalid
     */
    public static PolicyReference getInstance(Node root, PolicyFinder finder,
                                              PolicyMetaData metaData)
        throws ParsingException
    {
        URI reference = null;
        int policyType;
       
        // see what type of reference we are
        String name = SunxacmlUtil.getNodeName(root);
        if (name.equals("PolicyIdReference")) {
            policyType = POLICY_REFERENCE;
        } else if (name.equals("PolicySetIdReference")) {
            policyType = POLICYSET_REFERENCE;
        } else {
            throw new ParsingException("Unknown reference type: " + name);
        }

        // next get the reference
        try {
            reference = new URI(root.getFirstChild().getNodeValue());
        } catch (Exception e) {
            throw new ParsingException("Invalid URI in Reference", e);
        }

        // now get any constraints
        NamedNodeMap map = root.getAttributes();

        String versionConstraint = null;
        Node versionNode = map.getNamedItem("Version");
        if (versionNode != null)
            versionConstraint = versionNode.getNodeValue();

        String earlyConstraint = null;
        Node earlyNode = map.getNamedItem("EarliestVersion");
        if (earlyNode != null)
            earlyConstraint = earlyNode.getNodeValue();

        String lateConstraint = null;
        Node lateNode = map.getNamedItem("LatestVersion");
        if (lateNode != null)
            lateConstraint = lateNode.getNodeValue();

        VersionConstraints constraints =
            new VersionConstraints(versionConstraint, earlyConstraint,
                                   lateConstraint);

        // finally, create the reference
        return new PolicyReference(reference, policyType, constraints, finder,
                                   metaData);
    }

    /**
     * Returns the refernce identitfier used to resolve the policy.
     *
     * @return the reference <code>URI</code>
     */
    public URI getReference() {
        return reference;
    }

    /**
     * Returns the version constraints associated with this reference. This
     * will never be null, though the constraints may be empty.
     *
     * @return the version constraints
     */
    public VersionConstraints getConstraints() {
        return constraints;
    }

    /**
     * Returns whether this is a reference to a policy or to a policy set.
     *
     * @return the reference type, either <code>POLICY_REFERENCE</code>
     *         or <code>POLICYSET_REFERENCE</code>
     */
    public int getReferenceType() {
        return policyType;
    }

    /**
     * Returns the id of this policy. If the policy is invalid or can't be
     * retrieved, then a runtime exception is thrown.
     *
     * @return the policy id
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public URI getId() {
        return resolvePolicy().getId();
    }

    /**
     * Returns the version of this policy. If the policy is invalid or can't
     * be retrieved, then a runtime exception is thrown.
     *
     * @return the policy version
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public String getVersion() {
        return resolvePolicy().getVersion();
    }

    /**
     * Returns the combining algorithm used by this policy. If the policy is
     * invalid or can't be retrieved, then a runtime exception is thrown.
     *
     * @return the combining algorithm
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public CombiningAlgorithm getCombiningAlg() {
        return resolvePolicy().getCombiningAlg();
    }

    /**
     * Returns the given description of this policy or null if there is no
     * description. If the policy is invalid or can't be retrieved, then a
     * runtime exception is thrown.
     *
     * @return the description or null
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public String getDescription() {
        return resolvePolicy().getDescription();
    }

    /**
     * Returns the target for this policy. If the policy is invalid or can't be
     * retrieved, then a runtime exception is thrown.
     *
     * @return the policy's target
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public Target getTarget() {
        return resolvePolicy().getTarget();
    }

    /**
     * Returns the default version for this policy. If the policy is
     * invalid or can't be retrieved, then a runtime exception is thrown.
     *
     * @return the policy's default version
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public String getDefaultVersion() {
        return resolvePolicy().getDefaultVersion();
    }

    /**
     * Returns the child policy nodes under this node in the policy tree. If
     * the policy is invalid or can't be retrieved, then a runtime exception
     * is thrown.
     *
     * @return the <code>List</code> of child policy nodes
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public List getChildren() {
        return resolvePolicy().getChildren();
    }

    /**
     * Returns the child policy nodes and their associated parameters. If
     * the policy is invalid or can't be retrieved, then a runtime exception
     * is thrown.
     *
     * @return a <code>List</code> of <code>CombinerElement</code>s
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public List getChildElements() {
        return resolvePolicy().getChildElements();
    }

    /**
     * Returns the Set of obligations for this policy, which may be empty if
     * there are no obligations. If the policy is invalid or can't be
     * retrieved, then a runtime exception is thrown.
     *
     * @return the policy's obligations
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public Set getObligations() {
        return resolvePolicy().getObligations();
    }

    /**
     * Returns the meta-data associated with this policy. If the policy is
     * invalid or can't be retrieved, then a runtime exception is thrown.
     * Note that this is the meta-data for the referenced policy, not the
     * meta-data for the parent policy (which is what gets provided to the
     * constructors of this class).
     *
     * @return the policy's meta-data
     *
     * @throws ProcessingException if the referenced policy can't be retrieved
     */
    public PolicyMetaData getMetaData() {
        return resolvePolicy().getMetaData();
    }

    /**
     * Given the input context sees whether or not the request matches this
     * policy. This must be called by combining algorithms before they
     * evaluate a policy. This is also used in the initial policy finding
     * operation to determine which top-level policies might apply to the
     * request. If the policy is invalid or can't be retrieved, then a
     * runtime exception is thrown.
     *
     * @param context the representation of the request
     *
     * @return the result of trying to match the policy and the request
     */
    public MatchResult match(EvaluationCtx context) {
        try {
            return getTarget().match(context);
        } catch (ProcessingException pe) {
            // this means that we couldn't resolve the policy
            ArrayList code = new ArrayList();
            code.add(Status.STATUS_PROCESSING_ERROR);
            Status status = new Status(code, "couldn't resolve policy ref");
            return new MatchResult(MatchResult.INDETERMINATE, status);
        }
    }

    /**
     * Private helper method that tried to resolve the policy
     */
    private AbstractPolicy resolvePolicy() {
        // see if this reference was setup with a finder
        if (finder == null) {
            if (logger.isLoggable(Level.WARNING))
                logger.warning("PolicyReference with id " +
                               reference.toString() + " was queried but was " +
                               "not configured with a PolicyFinder");

            throw new ProcessingException("couldn't find the policy with " +
                                          "a null finder");
        }

        PolicyFinderResult pfr =
            finder.findPolicy(reference, policyType, constraints,
                              parentMetaData);
       
        if (pfr.notApplicable())
            throw new ProcessingException("couldn't resolve the policy");
       
        if (pfr.indeterminate())
            throw new ProcessingException("error resolving the policy");

        return pfr.getPolicy();
    }

    /**
     * Tries to evaluate the policy by calling the combining algorithm on
     * the given policies or rules. The <code>match</code> method must always
     * be called first, and must always return MATCH, before this method
     * is called.
     *
     * @param context the representation of the request
     *
     * @return the result of evaluation
     */
    public Result evaluate(EvaluationCtx context) {
        // if there is no finder, then we return NotApplicable
        if (finder == null)
            return new Result(Result.DECISION_NOT_APPLICABLE,
                              context.getResourceId().encode());

        PolicyFinderResult pfr = finder.findPolicy(reference, policyType,
                                                   constraints,
                                                   parentMetaData);

        // if we found nothing, then we return NotApplicable
        if (pfr.notApplicable())
            return new Result(Result.DECISION_NOT_APPLICABLE,
                              context.getResourceId().encode());

        // if there was an error, we return that status data
        if (pfr.indeterminate())
            return new Result(Result.DECISION_INDETERMINATE, pfr.getStatus(),
                              context.getResourceId().encode());

        // we must have found a policy
        return pfr.getPolicy().evaluate(context);
    }

    /**
     * Encodes this <code>PolicyReference</code> into its XML representation
     * and writes this encoding to the given <code>OutputStream</code> with
     * no indentation.
     *
     * @param output a stream into which the XML-encoded data is written
     */
    public void encode(OutputStream output) {
        encode(output, new Indenter(0));
    }

    /**
     * Encodes this <code>PolicyReference</code> into its XML representation
     * and writes this encoding to the given <code>OutputStream</code> with
     * indentation.
     *
     * @param output a stream into which the XML-encoded data is written
     * @param indenter an object that creates indentation strings
     */
    public void encode(OutputStream output, Indenter indenter) {
        PrintStream out = new PrintStream(output);
        String encoded = indenter.makeString();

        if (policyType == POLICY_REFERENCE) {
            out.println(encoded + "<PolicyIdReference" + encodeConstraints() +
                        ">" + reference.toString() + "</PolicyIdReference>");
        } else {
            out.println(encoded + "<PolicySetIdReference" +
                        encodeConstraints() + ">" + reference.toString() +
                        "</PolicySetIdReference>");
        }
    }

    /**
     * Private helper method that encodes the variable constraints info. Note
     * that if this is a pre-2.0 policy the constraints are always null, so
     * nothing will be added here.
     */
    private String encodeConstraints() {
        String str = "";
        VersionConstraints version = getConstraints();

        String v = version.getVersionConstraint();
        if (v != null)
            str += " Version=\"" + v + "\"";

        String e = version.getEarliestConstraint();
        if (e != null)
            str += " EarliestVersion=\"" + e + "\"";

        String l = version.getLatestConstraint();
        if (l != null)
            str += " LatestVersion=\"" + l + "\"";

        return str;
    }

}
TOP

Related Classes of org.jboss.security.xacml.sunxacml.PolicyReference

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.