Package org.jboss.security.xacml.sunxacml.finder.impl

Source Code of org.jboss.security.xacml.sunxacml.finder.impl.FilePolicyModule

/*
* @(#)FilePolicyModule.java
*
* Copyright 2003-2004 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.finder.impl;




import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.jboss.security.xacml.sunxacml.AbstractPolicy;
import org.jboss.security.xacml.sunxacml.EvaluationCtx;
import org.jboss.security.xacml.sunxacml.MatchResult;
import org.jboss.security.xacml.sunxacml.Policy;
import org.jboss.security.xacml.sunxacml.PolicySet;
import org.jboss.security.xacml.sunxacml.ctx.Status;
import org.jboss.security.xacml.sunxacml.finder.PolicyFinder;
import org.jboss.security.xacml.sunxacml.finder.PolicyFinderModule;
import org.jboss.security.xacml.sunxacml.finder.PolicyFinderResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;


/**
* This module represents a collection of files containing polices,
* each of which will be searched through when trying to find a
* policy that is applicable to a specific request.
* <p>
* Note: this module is provided only as an example and for testing
* purposes. It is not part of the standard, and it should not be
* relied upon for production systems. In the future, this will likely
* be moved into a package with other similar example and testing
* code.
*
* @since 1.0
* @author Seth Proctor
*/
@SuppressWarnings({"unused", "unchecked", "rawtypes"})
public class FilePolicyModule extends PolicyFinderModule
    implements ErrorHandler
{

    /**
     * The property which is used to specify the schema
     * file to validate against (if any)
     */
    public static final String POLICY_SCHEMA_PROPERTY =
        "com.sun.xacml.PolicySchema";


    public static final String JAXP_SCHEMA_LANGUAGE =
        "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
   
    public static final String W3C_XML_SCHEMA =
        "http://www.w3.org/2001/XMLSchema";

    public static final String JAXP_SCHEMA_SOURCE =
        "http://java.sun.com/xml/jaxp/properties/schemaSource";
   

    // the finder that is using this module
    private PolicyFinder finder;

    //
    private File schemaFile;

    //
    private Set fileNames;

    //
    private Set policies;

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

    /**
     * Constructor which retrieves the schema file to validate policies against
     * from the POLICY_SCHEMA_PROPERTY. If the retrieved property
     * is null, then no schema validation will occur.
     */
    public FilePolicyModule() {
        fileNames = new HashSet();
        policies = new HashSet();

        String schemaName = System.getProperty(POLICY_SCHEMA_PROPERTY);

        if (schemaName == null)
            schemaFile = null;
        else
            schemaFile = new File(schemaName);
    }

    /**
     * Constructor that uses the specified input as the schema file to
     * validate policies against. If schema validation is not desired,
     * a null value should be used.
     *
     * @param schemaFile the schema file to validate policies against,
     *                   or null if schema validation is not desired.
     */
    public FilePolicyModule(File schemaFile) {
        fileNames = new HashSet();
        policies = new HashSet();

        this.schemaFile = schemaFile;
    }

    /**
     * Constructor that specifies a set of initial policy files to use.
     * No schema validation is performed.
     *
     * @param fileNames a <code>List</code> of <code>String</code>s that
     *                  identify policy files
     */
    public FilePolicyModule(List fileNames) {
        this();

        if (fileNames != null)
            this.fileNames.addAll(fileNames);
    }

    /**
     * Indicates whether this module supports finding policies based on
     * a request (target matching). Since this module does support
     * finding policies based on requests, it returns true.
     *
     * @return true, since finding policies based on requests is supported
     */
    public boolean isRequestSupported() {
        return true;
    }

    /**
     * Initializes the <code>FilePolicyModule</code> by loading
     * the policies contained in the collection of files associated
     * with this module. This method also uses the specified
     * <code>PolicyFinder</code> to help in instantiating PolicySets.
     *
     * @param finder a PolicyFinder used to help in instantiating PolicySets
     */
    public void init(PolicyFinder finder) {
        this.finder = finder;

        Iterator it = fileNames.iterator();
        while (it.hasNext()) {
            String fname = (String)(it.next());
            AbstractPolicy policy = loadPolicy(fname, finder,
                                               schemaFile, this);
            if (policy != null)
                policies.add(policy);
        }
    }

    /**
     * Adds a file (containing a policy) to the collection of filenames
     * associated with this module.
     *
     * @param filename the file to add to this module's collection of files
     */
    public boolean addPolicy(String filename) {
        return fileNames.add(filename);
    }

    /**
     * Loads a policy from the specified filename and uses the specified
     * <code>PolicyFinder</code> to help with instantiating PolicySets.
     *
     * @param filename the file to load the policy from
     * @param finder a PolicyFinder used to help in instantiating PolicySets
     *
     * @return a (potentially schema-validated) policy associated with the
     *         specified filename, or null if there was an error
     */
    public static AbstractPolicy loadPolicy(String filename,
                                            PolicyFinder finder) {
        return loadPolicy(filename, finder, null, null);
    }

    /**
     * Loads a policy from the specified filename, using the specified
     * <code>PolicyFinder</code> to help with instantiating PolicySets,
     * and using the specified input as the schema file to validate
     * policies against. If schema validation is not desired, a null
     * value should be used for schemaFile
     *
     * @param filename the file to load the policy from
     * @param finder a PolicyFinder used to help in instantiating PolicySets
     * @param schemaFile the schema file to validate policies against, or
     *                   null if schema validation is not desired
     * @param handler an error handler used to print warnings and errors
     *                during parsing
     *
     * @return a (potentially schema-validated) policy associated with the
     *         specified filename, or null if there was an error
     */
    public static AbstractPolicy loadPolicy(String filename,
                                            PolicyFinder finder,
                                            File schemaFile,
                                            ErrorHandler handler) {
        try {
            // create the factory
            DocumentBuilderFactory factory =
                DocumentBuilderFactory.newInstance();
            factory.setIgnoringComments(true);

            DocumentBuilder db = null;

            // as of 1.2, we always are namespace aware
            factory.setNamespaceAware(true);

            // set the factory to work the way the system requires
            if (schemaFile == null) {
                // we're not doing any validation
                factory.setValidating(false);

                db = factory.newDocumentBuilder();
            } else {
                // we're using a validating parser
                factory.setValidating(true);

                factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
                factory.setAttribute(JAXP_SCHEMA_SOURCE, schemaFile);
               
                db = factory.newDocumentBuilder();
                db.setErrorHandler(handler);
            }

            // try to load the policy file
            Document doc = db.parse(new FileInputStream(filename));
           
            // handle the policy, if it's a known type
            Element root = doc.getDocumentElement();
            String name = root.getTagName();

            if (name.equals("Policy")) {
                return Policy.getInstance(root);
            } else if (name.equals("PolicySet")) {
                return PolicySet.getInstance(root, finder);
            } else {
                // this isn't a root type that we know how to handle
                throw new Exception("Unknown root document type: " + name);
            }
        } catch (Exception e) {
            if (logger.isLoggable(Level.WARNING))
                logger.log(Level.WARNING, "Error reading policy from file " +
                           filename, e);
        }

        // a default fall-through in the case of an error
        return null;
    }

    /**
     * Finds a policy based on a request's context. This may involve using
     * the request data as indexing data to lookup a policy. This will always
     * do a Target match to make sure that the given policy applies. If more
     * than one applicable policy is found, this will return an error.
     * NOTE: this is basically just a subset of the OnlyOneApplicable Policy
     * Combining Alg that skips the evaluation step. See comments in there
     * for details on this algorithm.
     *
     * @param context the representation of the request data
     *
     * @return the result of trying to find an applicable policy
     */
    public PolicyFinderResult findPolicy(EvaluationCtx context) {
        AbstractPolicy selectedPolicy = null;
        Iterator it = policies.iterator();

        while (it.hasNext()) {
            AbstractPolicy policy = (AbstractPolicy)(it.next());

            // see if we match
            MatchResult match = policy.match(context);
            int result = match.getResult();
           
            // if there was an error, we stop right away
            if (result == MatchResult.INDETERMINATE)
                return new PolicyFinderResult(match.getStatus());

            if (result == MatchResult.MATCH) {
                // if we matched before, this is an error...
                if (selectedPolicy != null) {
                    ArrayList code = new ArrayList();
                    code.add(Status.STATUS_PROCESSING_ERROR);
                    Status status = new Status(code, "too many applicable top-"
                                               + "level policies");
                    return new PolicyFinderResult(status);
                }

                // ...otherwise remember this policy
                selectedPolicy = policy;
            }
        }

        // if we found a policy, return it, otherwise we're N/A
        if (selectedPolicy != null)
            return new PolicyFinderResult(selectedPolicy);
        else
            return new PolicyFinderResult();
    }

    /**
     * Standard handler routine for the XML parsing.
     *
     * @param exception information on what caused the problem
     */
    public void warning(SAXParseException exception) throws SAXException {
        if (logger.isLoggable(Level.WARNING))
            logger.warning("Warning on line " + exception.getLineNumber() +
                           ": " + exception.getMessage());
    }

    /**
     * Standard handler routine for the XML parsing.
     *
     * @param exception information on what caused the problem
     *
     * @throws SAXException always to halt parsing on errors
     */
    public void error(SAXParseException exception) throws SAXException {
        if (logger.isLoggable(Level.WARNING))
            logger.warning("Error on line " + exception.getLineNumber() +
                           ": " + exception.getMessage() + " ... " +
                           "Policy will not be available");

        throw new SAXException("error parsing policy");
    }

    /**
     * Standard handler routine for the XML parsing.
     *
     * @param exception information on what caused the problem
     *
     * @throws SAXException always to halt parsing on errors
     */
    public void fatalError(SAXParseException exception) throws SAXException {
        if (logger.isLoggable(Level.WARNING))
            logger.warning("Fatal error on line " + exception.getLineNumber() +
                           ": " + exception.getMessage() + " ... " +
                           "Policy will not be available");

        throw new SAXException("fatal error parsing policy");
    }

}
TOP

Related Classes of org.jboss.security.xacml.sunxacml.finder.impl.FilePolicyModule

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.