/*
* @(#)FilePolicyModule.java
*
* Copyright 2003-2006 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 com.sun.xacml.support.finder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.xacml.AbstractPolicy;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.ParsingException;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderModule;
import com.sun.xacml.finder.PolicyFinderResult;
/**
* 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. It does not
* support policy references.
* <p>
* Note that this class used to be provided in the <code>com.sun.xacml.finder.impl</code> package
* with a warning that it would move out of the core packages eventually. This is partly because
* this class doesn't represent standard functionality, and partly because it isn't designed to be
* generally useful as anything more than an example. Because so many people have used this class,
* however, it stayed in place until the 2.0 release.
* <p>
* As of the 2.0 release, you may still use this class (in its new location), but you are encouraged
* to migrate to the new support modules that are much richer and designed for general-purpose use.
* Also, note that the <code>loadPolicy</code> methods that used to be available from this class
* have been removed. That functionality has been replaced by the much more useful
* <code>PolicyReader</code> class. If you need to load policies directly, you should consider that
* new class.
*
* @since 1.0
* @author Seth Proctor
*
* Adding generic type support by Christian Mueller (geotools)
*/
public class FilePolicyModule extends PolicyFinderModule {
// the schema file we're using, if any
private File schemaFile = null;
// the filenames for the files we'll load
private Set<String> fileNames;
// the actual loaded policies
private PolicyCollection 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
* <code>PolicyReader.POLICY_SCHEMA_PROPERTY</code>. If the retrieved property is null, then no
* schema validation will occur.
*/
public FilePolicyModule() {
fileNames = new HashSet<String>();
policies = new PolicyCollection();
String schemaName = System.getProperty(PolicyReader.POLICY_SCHEMA_PROPERTY);
if (schemaName != null)
schemaFile = new File(schemaName);
}
/**
* Constructor that uses the specified <code>File</code> as the schema file for XML validation.
* 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<String>();
policies = new PolicyCollection();
this.schemaFile = schemaFile;
}
/**
* Constructor that uses the specified <code>String</code> as the schema file for XML
* validation. 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(String schemaFile) {
this((schemaFile != null) ? new File(schemaFile) : null);
}
/**
* Constructor that specifies a set of initial policy files to use. This retrieves the schema
* file to validate policies against from the <code>PolicyReader.POLICY_SCHEMA_PROPERTY</code>.
* If the retrieved property is null, then no schema validation will occur.
*
* @param fileNames
* a <code>List</code> of <code>String</code>s that identify policy files
*/
public FilePolicyModule(List<String> fileNames) {
this();
if (fileNames != null)
this.fileNames.addAll(fileNames);
}
/**
* Constructor that specifies a set of initial policy files to use and the schema file used to
* validate the policies. If schema validation is not desired, a null value should be used.
*
* @param fileNames
* a <code>List</code> of <code>String</code>s that identify policy files
* @param schemaFile
* the schema file to validate policies against, or null if schema validation is not
* desired.
*/
public FilePolicyModule(List<String> fileNames, String schemaFile) {
this(schemaFile);
if (fileNames != null)
this.fileNames.addAll(fileNames);
}
/**
* Adds a file (containing a policy) to the collection of filenames associated with this module.
* Note that this doesn't actually load the policy file. Policies aren't loaded from their files
* until the module is initialized through the <code>init</code> method (which is called
* automatically by the <code>PolicyFinder</code> when the system comes up).
*
* @param filename
* the file to add to this module's collection of files
*/
public boolean addPolicy(String filename) {
return fileNames.add(filename);
}
/**
* 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) {
PolicyReader reader = new PolicyReader(finder, logger, schemaFile);
for (String fname : fileNames) {
try {
AbstractPolicy policy = reader.readPolicy(new FileInputStream(fname));
policies.addPolicy(policy);
} catch (FileNotFoundException fnfe) {
if (logger.isLoggable(Level.WARNING))
logger.log(Level.WARNING, "File couldn't be read: " + fname, fnfe);
} catch (ParsingException pe) {
if (logger.isLoggable(Level.WARNING))
logger.log(Level.WARNING, "Error reading policy from file " + fname, pe);
}
}
}
/**
* Finds a policy based on a request's context. If more than one applicable policy is found,
* this will return an error. Note that 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) {
try {
AbstractPolicy policy = policies.getPolicy(context);
if (policy == null)
return new PolicyFinderResult();
else
return new PolicyFinderResult(policy);
} catch (TopLevelPolicyException tlpe) {
return new PolicyFinderResult(tlpe.getStatus());
}
}
}