Initial import from git@github.com:GenericBreakGlass/GenericBreakGlass-XACML.git (34c2ebc0cc).

This commit is contained in:
Achim D. Brucker 2015-06-06 20:17:20 +02:00
parent 601a4a97c4
commit 29b887939a
401 changed files with 67683 additions and 0 deletions

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.

View File

@ -0,0 +1,6 @@
# GenericBreakGlass: XACML Reference Implementation
## Team
Main developers:
* [Achim D. Brucker](http://www.brucker.ch/)
* Helmut Petritsch

View File

@ -0,0 +1,5 @@
*/target/
*/bin/
*/.classpath
*/.project
*/.settings

View File

@ -0,0 +1,41 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.aniketos.securebpmn.xacml</groupId>
<artifactId>eu.aniketos.securebpmn.xacml.parent</artifactId>
<version>1.0</version>
<relativePath>../eu.aniketos.securebpmn.xacml.parent/pom.xml</relativePath>
</parent>
<artifactId>com.sun.xacml.support</artifactId>
<packaging>jar</packaging>
<version>0.1</version>
<name>SecureBPMN XACML - com.sun.xacml support utilities</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>[4.8,)</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>eu.aniketos.securebpmn.xacml</groupId>
<artifactId>com.sun.xacml</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,134 @@
package com.sun.xacml.support;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.log4j.Logger;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.sun.org.apache.xerces.internal.parsers.DOMParser;
import com.sun.org.apache.xerces.internal.xni.Augmentations;
import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
import com.sun.org.apache.xerces.internal.xni.QName;
import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
import com.sun.org.apache.xerces.internal.xni.XMLLocator;
import com.sun.org.apache.xerces.internal.xni.XNIException;
import com.sun.xacml.Constants;
/**
*
* Class which is able to keep track of the line numbers
*
*
*/
public class DOMLinesParser extends DOMParser {
private XMLLocator locator;
private boolean curEleNodeError = false;
private static Logger logger = Logger.getLogger(DOMLinesParser.class);
private String currentFile = null;
public DOMLinesParser() {
}
public void parse (File file) throws SAXException, IOException {
parse(new InputSource(new FileInputStream(file)), file.getPath());
}
public void parse (InputStream input, String fileName) throws SAXException, IOException {
parse(new InputSource(input), fileName);
}
public void parse (InputStream input) throws SAXException, IOException {
parse(new InputSource(input), null);
}
public void parse (InputSource input) throws SAXException, IOException {
parse(input, null);
}
public static boolean checkFeatureAvailable() {
try {
DOMParser tmpParser = new DOMParser();
tmpParser.setFeature( "http://apache.org/xml/features/dom/defer-node-expansion", false );
return true;
} catch (Exception e) {
return false;
}
}
public void parse (InputSource input, String fileName) throws SAXException, IOException {
logger.debug("Start parsing policy file " + fileName + " with line numbers");
this.currentFile = fileName;
try {
this.setFeature( "http://apache.org/xml/features/dom/defer-node-expansion", false );
curEleNodeError = false;
} catch (Exception e) {
logger.error("Could not set feature required for keeping track of line numbers!");
curEleNodeError = true;
}
super.parse(input);
}
@Override
public void startElement(QName elementQName, XMLAttributes attrList, Augmentations augs)
throws XNIException {
super.startElement(elementQName, attrList, augs);
Node node = null;
try {
node = (Node) this.getProperty( "http://apache.org/xml/properties/dom/current-element-node" );
}
catch( SAXException ex )
{
if ( ! curEleNodeError ) {
curEleNodeError = true;
logger.error("Could not retreive node for setting current start line: " + ex.getMessage(), ex);
}
}
if( node != null ) {
node.setUserData( Constants.LINE_NUMBER, new Integer( locator.getLineNumber() ), null ); // Save location String into node
if ( this.currentFile != null) {
node.setUserData( Constants.SOURCE_FILE, this.currentFile, null);
}
}
} //startElement
/* We override startDocument callback from DocumentHandler */
public void startDocument(XMLLocator locator, String encoding,
NamespaceContext namespaceContext, Augmentations augs) throws XNIException {
super.startDocument(locator, encoding, namespaceContext, augs);
this.locator = locator;
Node node = null ;
try {
node = (Node) this.getProperty( "http://apache.org/xml/properties/dom/current-element-node" );
}
catch( org.xml.sax.SAXException ex )
{
if ( ! curEleNodeError ) {
curEleNodeError = true;
logger.error("Could not retreive node for setting current start line: " + ex.getMessage(), ex);
}
}
if( node != null ) {
node.setUserData( Constants.LINE_NUMBER, new Integer(locator.getLineNumber() ), null ); // Save location String into node
if ( this.currentFile != null) {
node.setUserData( Constants.SOURCE_FILE, this.currentFile, null);
}
}
}
}

View File

@ -0,0 +1,236 @@
/*
* @(#)SimplePDP.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;
import com.sun.xacml.ConfigurationStore;
import com.sun.xacml.Indenter;
import com.sun.xacml.ParsingException;
import com.sun.xacml.PDP;
import com.sun.xacml.PDPConfig;
import com.sun.xacml.combine.PermitOverridesPolicyAlg;
import com.sun.xacml.ctx.RequestCtx;
import com.sun.xacml.ctx.ResponseCtx;
import com.sun.xacml.finder.AttributeFinder;
import com.sun.xacml.finder.AttributeFinderModule;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderModule;
import com.sun.xacml.finder.impl.CurrentEnvModule;
import com.sun.xacml.finder.impl.SelectorModule;
import com.sun.xacml.support.finder.StaticPolicyFinderModule;
import com.sun.xacml.support.finder.StaticRefPolicyFinderModule;
import com.sun.xacml.support.finder.URLPolicyFinderModule;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* This is a simple, command-line driven XACML PDP. It acts both as an example
* of how to write a full-featured PDP and as a sample program that lets you
* evaluate requests against policies. See the comments for the main() method
* for correct usage.
* <p>
* As of the 2.0 release, this has been moved into the new support tree of the
* codebase. It has also been updated to use several of the new finder
* modules provided in the support tree codebase, so that static and dynamic
* references are supported, policies can be loaded from URLs, top-level
* policies are wrapped in a policy set when more than one applies, etc.
* <p>
* If you don't use a configuration file, then the default modules can all
* optionally support schema validation. To turn this on, provide the filename
* of the schema file in the property "com.sun.xacml.PolicySchema". You can
* also turn this on if you use a configuration file and it includes the
* modules provided in the support package.
*
* @since 1.1
* @author Seth Proctor
*/
public class SimplePDP
{
// this is the actual PDP object we'll use for evaluation
private PDP pdp = null;
/**
* Default constructor. This creates a <code>SimplePDP</code> with a
* <code>PDP</code> based on the configuration defined by the runtime
* property com.sun.xcaml.PDPConfigFile.
*
* @throws Exception
*/
public SimplePDP() throws Exception {
// load the configuration
ConfigurationStore store = new ConfigurationStore();
// use the default factories from the configuration
store.useDefaultFactories();
// get the PDP configuration's and setup the PDP
this.pdp = new PDP(store.getDefaultPDPConfig());
}
/**
* Constructor that takes an array of filenames and URLs, each of which
* points to an XACML policy, and sets up a <code>PDP</code> with access
* to these policies only. These policies may be accessed based on
* context matching or by reference (based on their policy identifiers).
* The <code>PDP</code> is also setup to support dynamic URL references.
*
* @param policies an arry of filenames and URLs that specify policies
*
* @throws Exception
*/
public SimplePDP(String [] policies) throws Exception {
// Create the two static modules with the given policies so that
// we have context-based and reference-based access to all the
// policies provided on the command-line
List<String> policyList = Arrays.asList(policies);
StaticPolicyFinderModule staticModule =
new StaticPolicyFinderModule(PermitOverridesPolicyAlg.algId,
policyList);
StaticRefPolicyFinderModule staticRefModule =
new StaticRefPolicyFinderModule(policyList);
// also create a module that lets us get at URL-based policies
URLPolicyFinderModule urlModule = new URLPolicyFinderModule();
// next, setup the PolicyFinder that this PDP will use
PolicyFinder policyFinder = new PolicyFinder();
Set<PolicyFinderModule> policyModules = new HashSet<PolicyFinderModule>();
policyModules.add(staticModule);
policyModules.add(staticRefModule);
policyModules.add(urlModule);
policyFinder.setModules(policyModules);
// now setup attribute finder modules for the current date/time and
// AttributeSelectors (selectors are optional, but this project does
// support a basic implementation)
CurrentEnvModule envAttributeModule = new CurrentEnvModule();
SelectorModule selectorAttributeModule = new SelectorModule();
// Setup the AttributeFinder just like we setup the PolicyFinder. Note
// that unlike with the policy finder, the order matters here. See the
// the javadocs for more details.
AttributeFinder attributeFinder = new AttributeFinder();
List<AttributeFinderModule> attributeModules = new ArrayList<AttributeFinderModule>();
attributeModules.add(envAttributeModule);
attributeModules.add(selectorAttributeModule);
attributeFinder.setModules(attributeModules);
// finally, initialize our pdp
this.pdp = new PDP(new PDPConfig(attributeFinder, policyFinder,
null, null));
}
/**
* Evaluates the given request and returns the Response that the PDP
* will hand back to the PEP.
*
* @param requestFile the name of a file that contains a Request
*
* @return the result of the evaluation
*
* @throws IOException if there is a problem accessing the file
* @throws ParsingException if the Request is invalid
*/
public ResponseCtx evaluate(String requestFile)
throws IOException, ParsingException
{
// setup the request based on the file
RequestCtx request =
RequestCtx.getInstance(new FileInputStream(requestFile));
// evaluate the request
return this.pdp.evaluate(request);
}
/**
* Main-line driver for this sample code. This method lets you invoke
* the PDP directly from the command-line.
*
* @param args the input arguments to the class. They are either the
* flag "-config" followed by a request file, or a request
* file followed by one or more policy files. In the case
* that the configuration flag is used, the configuration
* file must be specified in the standard java property,
* com.sun.xacml.PDPConfigFile.
*
* @throws Exception
*/
public static void main(String [] args) throws Exception {
if (args.length < 2) {
System.out.println("Usage: -config <request>");
System.out.println(" <request> <policy> [policies]");
System.exit(1);
}
SimplePDP simplePDP = null;
String requestFile = null;
if (args[0].equals("-config")) {
requestFile = args[1];
simplePDP = new SimplePDP();
} else {
requestFile = args[0];
String [] policyFiles = new String[args.length - 1];
for (int i = 1; i < args.length; i++) {
policyFiles[i-1] = args[i];
}
simplePDP = new SimplePDP(policyFiles);
}
// evaluate the request
ResponseCtx response = simplePDP.evaluate(requestFile);
// for this sample program, we'll just print out the response
response.encode(System.out, "UTF-8", new Indenter());
}
}

View File

@ -0,0 +1,253 @@
/*
* @(#)BasicPolicyFinderModule.java
*
* Copyright 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 com.sun.xacml.AbstractPolicy;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.PolicyMetaData;
import com.sun.xacml.VersionConstraints;
import com.sun.xacml.combine.PolicyCombiningAlgorithm;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderModule;
import com.sun.xacml.finder.PolicyFinderResult;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This is a basic implementation of <code>PolicyFinderModule</code> that
* accepts already created <code>AbstractPolicy</code>s and supports
* finding by context and reference. All policies are held forever once
* added to this module, and cannot be refreshed or removed. New policies
* may be added at any point. You may optionally specify a combining
* algorithm to use when more than one applicable policy is found, and then
* a new PolicySet is wrapped around the policies using this algorithm. If
* no combining algorithm is provided, then an error is returned if more
* than one policy matches.
* <p>
* This module is provided as an example, but is still fully functional, and
* should be useful for many simple applications. This is provided in the
* <code>support</code> package rather than the core codebase because it
* implements non-standard behavior.
*
* @since 2.0
* @author Seth Proctor
*/
public class BasicPolicyFinderModule extends PolicyFinderModule
{
// the collections used to handle both kinds of policies
private PolicyCollection ctxPolicies;
private PolicyCollection refPolicies;
// the policy identifier for any policy sets we dynamically create
private static final String POLICY_ID =
"urn:com:sun:xacml:support:finder:dynamic-policy-set";
private static URI policyId = null;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(BasicPolicyFinderModule.class.getName());
static {
try {
policyId = new URI(POLICY_ID);
} catch (Exception e) {
// this can't actually happen, but just in case...
if (logger.isLoggable(Level.SEVERE)) {
logger.log(Level.SEVERE, "couldn't assign default policy id");
}
}
}
/**
* Creates a <code>BasicPolicyFinderModule</code>.
*/
public BasicPolicyFinderModule() {
this.ctxPolicies = new PolicyCollection();
this.refPolicies = new PolicyCollection();
}
/**
* Creates a <code>BasicPolicyFinderModule</code> that can combine
* multiple applicable policies under a single, dynamic PolicySet.
*
* @param combiningAlg the algorithm to use in a new PolicySet when more
* than one policy applies
*/
public BasicPolicyFinderModule(PolicyCombiningAlgorithm combiningAlg) {
this.ctxPolicies = new PolicyCollection(combiningAlg, policyId);
this.refPolicies = new PolicyCollection(combiningAlg, policyId);
}
/**
* Adds a policy that will be available both by reference and by
* matching to a context. The policy's identifier is used for finding
* by reference. If a policy with the same identifier and version is
* already handled by this module, then the policy is not added.
*
* @param policy the policy to add
*
* @return true if the policy was added, false otherwise
*/
public synchronized boolean addPolicy(AbstractPolicy policy) {
if (this.ctxPolicies.addPolicy(policy)) {
return this.refPolicies.addPolicy(policy);
}
return false;
}
/**
* Adds a policy that will be available only by matching to a context.
* If a policy with the same identifier and version is already handled
* by this module, then the policy is not added.
*
* @param policy the policy to add
*
* @return true if the policy was added, false otherwise
*/
public synchronized boolean addPolicyNoRef(AbstractPolicy policy) {
return this.ctxPolicies.addPolicy(policy);
}
/**
* Adds a policy that will be available only by reference. The policy's
* identifier is used for finding by reference. If a policy with the
* same identifier and version is already handled by this module, then
* the policy is not added.
*
* @param policy the policy to add
*
* @return true if the policy was added, false otherwise
*/
public synchronized boolean addPolicyOnlyRef(AbstractPolicy policy) {
return this.refPolicies.addPolicy(policy);
}
/**
* Always returns <code>true</code> since this module does support
* finding policies based on context matching.
*
* @return true
*/
public boolean isRequestSupported() {
return true;
}
/**
* Always returns <code>true</code> since this module does support
* finding policies based on reference.
*
* @return true
*/
public boolean isIdReferenceSupported() {
return true;
}
/**
* Initialize this module. Typically this is called by
* <code>PolicyFinder</code> when a PDP is created.
*
* @param finder the <code>PolicyFinder</code> using this module
*/
public void init(PolicyFinder finder) {
// we don't need to do anything here
}
/**
* Finds a policy based on a request's context. If more than one policy
* matches, then this either returns an error or a new policy wrapping
* the multiple policies (depending on which constructor was used to
* construct this instance).
*
* @param context the representation of the request data
*
* @return the result of trying to find an applicable policy
*/
public PolicyFinderResult findPolicy(EvaluationCtx context) {
context.newEvent(this);
try {
AbstractPolicy policy = this.ctxPolicies.getPolicy(context);
if (policy == null) {
context.closeCurrentEvent();
return new PolicyFinderResult();
}
context.closeCurrentEvent(policy.getId().toString());
return new PolicyFinderResult(policy);
} catch (TopLevelPolicyException tlpe) {
context.closeCurrentEvent();
return new PolicyFinderResult(tlpe.getStatus());
}
}
/**
* Attempts to find a policy by reference, based on the provided
* parameters.
*
* @param idReference an identifier specifying some policy
* @param type type of reference (policy or policySet) as identified by
* the fields in <code>PolicyReference</code>
* @param constraints any optional constraints on the version of the
* referenced policy (this will never be null, but
* it may impose no constraints, and in fact will
* never impose constraints when used from a pre-2.0
* XACML policy)
* @param parentMetaData the meta-data from the parent policy, which
* provides XACML version, factories, etc.
*
* @return the result of looking for a matching policy
*/
public PolicyFinderResult findPolicy(URI idReference, int type,
VersionConstraints constraints,
PolicyMetaData parentMetaData) {
AbstractPolicy policy =
this.refPolicies.getPolicy(idReference.toString(), type,
constraints);
if (policy == null) {
return new PolicyFinderResult();
}
return new PolicyFinderResult(policy);
}
}

View File

@ -0,0 +1,328 @@
/*
* @(#)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 com.sun.xacml.AbstractPolicy;
import com.sun.xacml.ConfigurationStore;
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;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* 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
*/
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
protected PolicyCollection policies;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(FilePolicyModule.class.getName());
// configuration: keep track of lines when loadig policies (slow! use only for debugging!)
protected boolean useLines = false, enf_useLines = false;
protected Map<String, String> confParams = new HashMap<String, String>();
protected static final String CONF_PREFIX = "conf:",
FILE_PREFIX = "file:",
CONF_USELINES = "useLines";
/**
* 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() {
this.fileNames = new HashSet<String>();
this.policies = new PolicyCollection();
String schemaName =
System.getProperty(PolicyReader.POLICY_SCHEMA_PROPERTY);
if (schemaName != null) {
this.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) {
this.fileNames = new HashSet<String>();
this.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) {
for ( String fileName : fileNames ) {
if ( fileName.startsWith(CONF_PREFIX) ) {
String tmp = fileName.substring(5);
try {
String confId = tmp.substring(0, tmp.indexOf(":"));
String value = tmp.substring(tmp.indexOf(":") + 1);
confParams.put(confId, value);
} catch(Exception e) {
logger.warning("Could not add configuration: " + tmp);
}
} else {
if ( fileName.startsWith(FILE_PREFIX) ) {
this.fileNames.add(fileName.substring(5));
} else {
this.fileNames.add(fileName);
}
}
}
}
if ( enf_useLines ) {
useLines = true;
} else if ( confParams.containsKey(CONF_USELINES)) {
useLines = getBool(confParams.get(CONF_USELINES));
}
}
/**
* 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
*
* @return true or false depending on the success of this operation.
*/
public boolean addPolicy(String filename) {
return this.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) {
Object o = finder.getPDPConfiguration().getCustomAttr(ConfigurationStore.BASEDIR);
String baseDir = "";
if ( o != null) {
baseDir = (String) o;
}
PolicyReader reader = new PolicyReader(finder, logger,
this.schemaFile, this.useLines);
for (String fname : this.fileNames ) {
try {
AbstractPolicy policy =
reader.readPolicy(new FileInputStream(baseDir + fname), fname);
this.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 {
context.newEvent(this);
AbstractPolicy policy = this.policies.getPolicy(context);
if (policy == null) {
context.closeCurrentEvent();
return new PolicyFinderResult();
}
context.closeCurrentEvent(policy.getId().toString());
return new PolicyFinderResult(policy);
} catch (TopLevelPolicyException tlpe) {
context.closeCurrentEvent();
return new PolicyFinderResult(tlpe.getStatus());
}
}
protected static boolean getBool(String value) {
try {
Boolean val = new Boolean(value);
return val.booleanValue();
} catch (Exception e) {
logger.log(Level.WARNING, "Could not read boolean value " + value + "; Using false as default");
return false;
}
}
/**
* this method can be used to enforce the usage of lines parsing
* programatically
* @param useLines
*/
public void enforceUseLines() {
this.enf_useLines = true;
this.useLines = true;
}
}

View File

@ -0,0 +1,376 @@
/*
* @(#)PolicyCollection.java
*
* Copyright 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 com.sun.xacml.AbstractPolicy;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.MatchResult;
import com.sun.xacml.Policy;
import com.sun.xacml.PolicyReference;
import com.sun.xacml.PolicySet;
import com.sun.xacml.PolicyTreeElement;
import com.sun.xacml.Target;
import com.sun.xacml.TargetSection;
import com.sun.xacml.VersionConstraints;
import com.sun.xacml.combine.PolicyCombiningAlgorithm;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.ctx.Status;
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.TreeSet;
/**
* This class handles collections of <code>AbstractPolicy</code> instances,
* and provides some commonly useful operations. Specifically, it lets you
* retrieve matching policies (based on reference or context), it optionally
* handles wrapping multiple matches under a single PolicySet, and it manages
* different versions of policies correctly. This class is intended for use
* as a backing store to <code>PolicyFinderModule</code>s, but in practice
* may have many uses.
* <p>
* Note that this class will accept multiple versions of the same policy. This
* means that when you retieve a policy by reference, you will get the
* correct version. It also means that when you retrieve a policy based on
* context, there may be multiple revisions of the same policy, any number
* of which may apply. Generally speaking, the correct behavior here is not
* to return all of these policies, since they are (virtually speaking) the
* same policy, but may have conflicting rules. So, as a simplification, and
* to handle the most common cases, only the most recent version of a policy
* is returned in these cases. If you need a more complex solution, you
* will need to implement it yourself. Because the support modules use this
* class as their backing store, this is true also of those modules.
* <p>
* Note that this is not a heavily optimized class. It is intended more as
* an example, support code for the finder modules, and a starting utility
* for other programmers than as an enterprise-quality implementation. That
* said, it is fully functional, and should be useful for many applications.
*
* @since 2.0
* @author Seth Proctor
*/
public class PolicyCollection
{
// the actual collection of policies
private HashMap<String, TreeSet<AbstractPolicy> > policies;
// the single instance of the comparator we'll use for managing versions
private VersionComparator versionComparator = new VersionComparator();
// the optional combining algorithm used when wrapping multiple policies
private PolicyCombiningAlgorithm combiningAlg;
// the optional policy id used when wrapping multiple policies
private URI parentId;
// default target that matches anything, used in wrapping policies
private static final Target target;
/**
* This static initializer just sets up the default target, which is
* used by all wrapping policy sets.
*/
static {
target =
new Target(new ArrayList<TargetSection>());
}
/**
* Creates a new <code>PolicyCollection</code> that will return errors
* when multiple policies match for a given request.
*/
public PolicyCollection() {
this.policies = new HashMap<String, TreeSet<AbstractPolicy>>();
this.combiningAlg = null;
}
/**
* Creates a new <code>PolicyCollection</code> that will create a new
* top-level PolicySet when multiple policies match for a given request.
*
* @param combiningAlg the algorithm to use in a new PolicySet when more
* than one policy applies
* @param parentPolicyId the identifier to use for the new PolicySet
*/
public PolicyCollection(PolicyCombiningAlgorithm combiningAlg,
URI parentPolicyId) {
this.policies = new HashMap<String, TreeSet<AbstractPolicy> >();
this.combiningAlg = combiningAlg;
this.parentId = parentPolicyId;
}
/**
* Adds a new policy to the collection, and uses the policy's identifier
* as the reference identifier. If this identifier already exists in the
* collection, and this policy does not represent a new version of the
* policy, then the policy is not added.
*
* @param policy the policy to add
*
* @return true if the policy was added, false otherwise
*/
public boolean addPolicy(AbstractPolicy policy) {
return addPolicy(policy, policy.getId().toString());
}
/**
* Adds a new policy to the collection using the given identifier as
* the reference identifier. If this identifier already exists in the
* collection, and this policy does not represent a new version of the
* policy, then the policy is not added.
*
* @param policy the policy to add
* @param identifier the identifier to use when referencing this policy
*
* @return true if the policy was added, false otherwise
*/
public boolean addPolicy(AbstractPolicy policy, String identifier) {
if (this.policies.containsKey(identifier)) {
// this identifier is already is use, so see if this version is
// already in the set
TreeSet<AbstractPolicy> set = this.policies.get(identifier);
return set.add(policy);
}
// this identifier isn't already being used, so create a new
// set in the map for it, and add the policy
TreeSet<AbstractPolicy> set = new TreeSet<AbstractPolicy> (this.versionComparator);
this.policies.put(identifier, set);
return set.add(policy);
}
/**
* Attempts to retrieve a policy based on the given context. If multiple
* policies match then this will either throw an exception or wrap the
* policies under a new PolicySet (depending on how this instance was
* constructed). If no policies match, then this will return null. See
* the comment in the class header about how this behaves when multiple
* versions of the same policy exist.
*
* @param context representation of a request
*
* @return a matching policy, or null if no policy matches
*
* @throws TopLevelPolicyException if multiple policies match but this
* instance wasn't setup to wrap policies
*/
public AbstractPolicy getPolicy(EvaluationCtx context)
throws TopLevelPolicyException
{
// setup a list of matching policies
ArrayList<PolicyTreeElement> list = new ArrayList<PolicyTreeElement>();
// get an iterator over all the identifiers
Iterator<TreeSet<AbstractPolicy>> it = this.policies.values().iterator();
while (it.hasNext()) {
// for each identifier, get only the most recent policy
AbstractPolicy policy = it.next().first();
// see if we match
context.newEvent(policy);
MatchResult match = policy.match(context);
int result = match.getResult();
// if there was an error, we stop right away
if (result == MatchResult.INDETERMINATE) {
context.closeCurrentEvent(
new Result(Result.DECISION_INDETERMINATE,
context));
throw new TopLevelPolicyException(match.getStatus());
}
if (result == MatchResult.NO_MATCH) {
context.closeCurrentEvent(
new Result(Result.DECISION_NOT_APPLICABLE));
}
// if we matched, we keep track of the matching policy...
if (result == MatchResult.MATCH) {
context.closeCurrentEvent();
// ...first checking if this is the first match and if
// we automaticlly nest policies
if ((this.combiningAlg == null) && (list.size() > 0)) {
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_PROCESSING_ERROR);
Status status = new Status(code, "too many applicable"
+ " top-level policies");
throw new TopLevelPolicyException(status);
}
list.add(policy);
}
}
// no errors happened during the search, so now take the right
// action based on how many policies we found
switch (list.size()) {
case 0:
return null;
case 1:
return ((AbstractPolicy)(list.get(0)));
default:
return new PolicySet(this.parentId, this.combiningAlg, target, list);
}
}
/**
* Attempts to retrieve a policy based on the given identifier and other
* constraints. If there are multiple versions of the identified policy
* that meet the version constraints, then the most recent version is
* returned.
*
* @param identifier an identifier specifying some policy
* @param type type of reference (policy or policySet) as identified by
* the fields in <code>PolicyReference</code>
* @param constraints any optional constraints on the version of the
* referenced policy (this will never be null, but
* it may impose no constraints, and in fact will
* never impose constraints when used from a pre-2.0
* XACML policy)
*
* @return the policy/policy set that was retrieved.
*/
public AbstractPolicy getPolicy(String identifier, int type,
VersionConstraints constraints) {
TreeSet<AbstractPolicy> set = this.policies.get(identifier);
// if we don't know about this identifier then there's nothing to do
if (set == null) {
return null;
}
// walk through the set starting with the most recent version, looking
// for a match until we exhaust all known versions
Iterator<AbstractPolicy> it = set.iterator();
while (it.hasNext()) {
AbstractPolicy policy = it.next();
if (constraints.meetsConstraint(policy.getVersion())) {
// we found a valid version, so see if it's the right kind,
// and if it is then we return it
if (type == PolicyReference.POLICY_REFERENCE) {
if (policy instanceof Policy) {
return policy;
}
} else {
if (policy instanceof PolicySet) {
return policy;
}
}
}
}
// we didn't find a match
return null;
}
/**
* A <code>Comparator</code> that is used within this class to maintain
* ordering amongst different versions of the same policy. Note that
* it actually maintains reverse-ordering, since we want to traverse the
* sets in decreasing, not increasing order.
* <p>
* Note that this comparator is only used when there are multiple versions
* of the same policy, which in practice will probably happen far less
* (from this class' point of view) than additions or fetches.
*/
static class VersionComparator implements Comparator<AbstractPolicy>, Serializable {
/**
* Serial version UID.
*/
private static final long serialVersionUID = 1L;
public int compare(AbstractPolicy o1, AbstractPolicy o2) {
// we swap the parameters so that sorting goes largest to smallest
String v1 = o2.getVersion();
String v2 = o1.getVersion();
// do a quick check to see if the strings are equal (note that
// even if the strings aren't equal, the versions can still
// be equal)
if (v1.equals(v2)) {
return 0;
}
// setup tokenizers, and walk through both strings one set of
// numeric values at a time
StringTokenizer tok1 = new StringTokenizer(v1, ".");
StringTokenizer tok2 = new StringTokenizer(v2, ".");
while (tok1.hasMoreTokens()) {
// if there's nothing left in tok2, then v1 is bigger
if (! tok2.hasMoreTokens()) {
return 1;
}
// get the next elements in the version, convert to numbers,
// and compare them (continuing with the loop only if the
// two values were equal)
int num1 = Integer.parseInt(tok1.nextToken());
int num2 = Integer.parseInt(tok2.nextToken());
if (num1 > num2) {
return 1;
}
if (num1 < num2) {
return -1;
}
}
// if there's still something left in tok2, then it's bigger
if (tok2.hasMoreTokens()) {
return -1;
}
// if we got here it means both versions had the same number of
// elements and all the elements were equal, so the versions
// are in fact equal
return 0;
}
}
}

View File

@ -0,0 +1,429 @@
/*
* @(#)PolicyReader.java
*
* Copyright 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 com.sun.xacml.AbstractPolicy;
import com.sun.xacml.ParsingException;
import com.sun.xacml.Policy;
import com.sun.xacml.PolicySet;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.support.DOMLinesParser;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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 class is provided as a utility for reading policies from common,
* simple sources: <code>InputStream</code>s, <code>File</code>s, and
* <code>URL</code>s. It can optionally schema validate the policies.
* <p>
* Note: some of this functionality was previously provided in
* <code>com.sun.xacml.finder.impl.FilePolicyModule</code>, but as of
* the 2.0 release, that class has been removed. This new
* <code>PolicyReader</code> class provides much better functionality
* for loading policies.
*
* @since 2.0
* @author Seth Proctor
*/
public class PolicyReader implements ErrorHandler
{
/**
* The property which is used to specify the schema file to validate
* against (if any). Note that this isn't used directly by
* <code>PolicyReader</code>, but is referenced by many classes that
* use this class to load policies.
*/
public static final String POLICY_SCHEMA_PROPERTY =
"com.sun.xacml.PolicySchema";
// the standard attribute for specifying the XML schema language
private static final String JAXP_SCHEMA_LANGUAGE =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage";
// the standard identifier for the XML schema specification
private static final String W3C_XML_SCHEMA =
"http://www.w3.org/2001/XMLSchema";
// the standard attribute for specifying schema source
private static final String JAXP_SCHEMA_SOURCE =
"http://java.sun.com/xml/jaxp/properties/schemaSource";
// the finder, which is used by PolicySets
private PolicyFinder finder;
// the builder used to create DOM documents
private DocumentBuilder builder;
//the parser used to create DOM documents with line information
private DOMLinesParser linesParser;
//boolean flag if the lineParser should be used (has to be activaed before parsing!)
private boolean useLineParser = false;
// the optional logger used for error reporting
private Logger logger;
/**
* Creates a <code>PolicyReader</code> that does not schema-validate
* policies.
*
* @param finder a <code>PolicyFinder</code> that is used by policy sets,
* which may be null only if no references are used
* @param logger a <code>Logger</code> used to report parsing errors
*/
public PolicyReader(PolicyFinder finder, Logger logger) {
this(finder, logger, null);
}
/**
* Creates a <code>PolicyReader</code> that may schema-validate policies.
*
* @param finder a <code>PolicyFinder</code> that is used by policy sets,
* which may be null only if no references are used
* @param logger a <code>Logger</code> used to report parsing errors
* @param schemaFile the schema file used to validate policies, or
* null if schema validation is not desired
*/
public PolicyReader(PolicyFinder finder, Logger logger, File schemaFile) {
this(finder, logger, schemaFile, false);
}
/**
* Creates a <code>PolicyReader</code> that may schema-validate policies.
*
* @param finder a <code>PolicyFinder</code> that is used by policy sets,
* which may be null only if no references are used
* @param logger a <code>Logger</code> used to report parsing errors
* @param schemaFile the schema file used to validate policies, or
* null if schema validation is not desired
*/
public PolicyReader(PolicyFinder finder, Logger logger, File schemaFile, boolean useLineParser) {
this.logger = logger;
this.finder = finder;
this.useLineParser = useLineParser;
// create the factory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringComments(true);
factory.setNamespaceAware(true);
// see if we want to schema-validate policies
if (schemaFile == null) {
factory.setValidating(false);
} else {
factory.setValidating(true);
factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
factory.setAttribute(JAXP_SCHEMA_SOURCE, schemaFile);
}
if ( useLineParser ) {
try {
Class.forName("com.sun.org.apache.xerces.internal.parsers.DOMParser");
this.useLineParser = DOMLinesParser.checkFeatureAvailable();
} catch (Exception e) {
this.useLineParser = false;
logger.warning("For the useLineParser the xerces DOMParser must be available on the classpath");
}
if ( this.useLineParser ) {
initDOMLinesParser(factory, schemaFile);
}
}
// now use the factory to create the document builder
try {
this.builder = factory.newDocumentBuilder();
this.builder.setErrorHandler(this);
} catch (ParserConfigurationException pce) {
throw new IllegalArgumentException("Filed to setup reader: " +
pce.toString());
}
}
private void initDOMLinesParser(DocumentBuilderFactory factory, File schemaFile) {
if ( schemaFile != null ) {
//TODO
logger.warning("Schema File validation not possible with active line numbers");
}
this.linesParser = new DOMLinesParser();
try {
this.linesParser.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes", false);
// only check if changes are there. do not execute in normal mode
//setFeatures(Constants.getSAXFeatures(), factory, Constants.SAX_FEATURE_PREFIX);
//setFeatures(Constants.getXercesFeatures(), factory, Constants.XERCES_FEATURE_PREFIX);
} catch( Exception e) {
logger.warning("Could not set Features for DOMLinesParser!");
}
}
// /**
// * function used to compare feature lists of DOMLinesParser and DocumentBuilderFactory for compability
// * reasons
// * @param features
// * @param factory
// * @param prefix
// */
// private void setFeatures(Enumeration features, DocumentBuilderFactory factory, String prefix) {
//
// Object feature; String sFeature;
// while ( features.hasMoreElements() ) {
// feature = features.nextElement();
// if ( feature instanceof String ) {
// sFeature = (String) feature;
// try {
// if ( factory.getFeature( prefix + sFeature) != linesParser.getFeature(prefix + sFeature)) {
// this.linesParser.setFeature( prefix + sFeature, factory.getFeature( prefix + sFeature));
// System.out.println(" SET FEATURE " + prefix+ sFeature + " to " + factory.getFeature( prefix + sFeature));
// } else {
// System.out.println(" Feature " + prefix + sFeature + " already set");
// }
// } catch (Exception e) {
// System.out.println(" ERROR: FEATURE " + prefix+ sFeature + " could not be set");
// }
// }
// }
// }
/**
* Tries to read an XACML policy or policy set from the given file.
*
* @param file the file containing the policy to read
*
* @return a (potentially schema-validated) policy loaded from the
* given file
*
* @throws ParsingException if an error occurs while reading or
* parsing the policy
*/
public synchronized AbstractPolicy readPolicy(File file)
throws ParsingException
{
try {
Document root = null;
if ( useLineParser ) {
linesParser.parse(file);
root = linesParser.getDocument();
} else {
root = this.builder.parse(file);;
}
return handleDocument(root);
} catch (IOException ioe) {
throw new ParsingException("Failed to read the file", ioe);
} catch (SAXException saxe) {
throw new ParsingException("Failed to parse the file", saxe);
}
}
/**
* Tries to read an XACML policy or policy set from the given stream.
*
* @param input the stream containing the policy to read
*
* @return a (potentially schema-validated) policy loaded from the
* given file
*
* @throws ParsingException if an error occurs while reading or
* parsing the policy
*/
public synchronized AbstractPolicy readPolicy(InputStream input, String fileName)
throws ParsingException
{
try {
Document root = null;
if ( useLineParser ) {
linesParser.parse(input, fileName);
root = linesParser.getDocument();
} else {
root = this.builder.parse(input);;
}
return handleDocument(root);
//return handleDocument(this.builder.parse(input));
} catch (IOException ioe) {
throw new ParsingException("Failed to read the stream", ioe);
} catch (SAXException saxe) {
throw new ParsingException("Failed to parse the stream", saxe);
}
}
/**
* Tries to read an XACML policy or policy set from the given stream.
*
* @param input the stream containing the policy to read
*
* @return a (potentially schema-validated) policy loaded from the
* given file
*
* @throws ParsingException if an error occurs while reading or
* parsing the policy
*/
public synchronized AbstractPolicy readPolicy(InputStream input)
throws ParsingException
{
return readPolicy(input, null);
}
/**
* Tries to read an XACML policy or policy set based on the given URL.
* This may be any resolvable URL, like a file or http pointer.
*
* @param url a URL pointing to the policy to read
*
* @return a (potentially schema-validated) policy loaded from the
* given file
*
* @throws ParsingException if an error occurs while reading or
* parsing the policy, or if the URL can't
* be resolved
*/
public synchronized AbstractPolicy readPolicy(URL url)
throws ParsingException
{
try {
return readPolicy(url.openStream());
} catch (IOException ioe) {
throw new ParsingException("Failed to resolve the URL: " +
url.toString(), ioe);
}
}
/**
* A private method that handles reading the policy and creates the
* correct kind of AbstractPolicy.
*/
private AbstractPolicy handleDocument(Document doc)
throws ParsingException
{
// handle the policy, if it's a known type
Element root = doc.getDocumentElement();
String name = root.getTagName();
try {
// see what type of policy this is
if (name.equals("Policy")) {
return Policy.getInstance(root);
} else if (name.equals("PolicySet")) {
return PolicySet.getInstance(root, this.finder);
} else {
// this isn't a root type that we know how to handle
throw new ParsingException("Unknown root document type: " + name);
}
} catch (IllegalArgumentException e) {
logger.log(Level.WARNING, "Could not parse Document (IllegalArgumentException): " + e.getMessage());
throw new ParsingException("Could not parse Document (IllegalArgumentException): " + e.getMessage(), e);
}
}
/**
* Standard handler routine for the XML parsing.
*
* @param exception information on what caused the problem
*/
public void warning(SAXParseException exception) {
if (this.logger.isLoggable(Level.WARNING)) { //startDocument
this.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 (this.logger.isLoggable(Level.WARNING)) {
this.logger.warning("Error on line " + exception.getLineNumber()
+ ": " + exception.getMessage() + " ... "
+ "Policy will not be available");
}
throw new SAXException("error parsing policy" + (exception.getLineNumber() == -1 ? "" : "at line number " + exception.getLineNumber()));
}
/**
* 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 (this.logger.isLoggable(Level.WARNING)) {
this.logger.warning("Fatal error on line "
+ exception.getLineNumber()
+ ": " + exception.getMessage() + " ... "
+ "Policy will not be available");
}
throw new SAXException("fatal error parsing policy" + (exception.getLineNumber() == -1 ? "" : "at line number " + exception.getLineNumber()));
}
}

View File

@ -0,0 +1,320 @@
/*
* @(#)StaticPolicyFinderModule.java
*
* Copyright 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 com.sun.xacml.AbstractPolicy;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.ParsingException;
import com.sun.xacml.UnknownIdentifierException;
import com.sun.xacml.combine.CombiningAlgFactory;
import com.sun.xacml.combine.PolicyCombiningAlgorithm;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderModule;
import com.sun.xacml.finder.PolicyFinderResult;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This is a simple implementation of <code>PolicyFinderModule</code> that
* supports retrieval based on context, and is designed for use with a
* run-time configuration. Its constructor accepts a <code>List</code> of
* <code>String</code>s that represent URLs or files, and these are resolved
* to policies when the module is initialized. Beyond this, there is no
* modifying or re-loading the policies represented by this class. This
* class will optionally wrap multiple applicable policies into a dynamic
* PolicySet.
* <p>
* Note that this class is designed to complement
* <code>StaticRefPolicyFinderModule</code>. It would be easy to support both
* kinds of policy retrieval in a single class, but the functionality is
* instead split between two classes. The reason is that when you define a
* configuration for your PDP, it's easier to specify the two sets of policies
* by using two different finder modules. Typically, there aren't many
* policies that exist in both sets, so loading the sets separately isn't
* a problem. If this is a concern to you, simply create your own class and
* merge the two existing classes.
* <p>
* This module is provided as an example, but is still fully functional, and
* should be useful for many simple applications. This is provided in the
* <code>support</code> package rather than the core codebase because it
* implements non-standard behavior.
*
* @since 2.0
* @author Seth Proctor
*/
public class StaticPolicyFinderModule extends PolicyFinderModule
{
// the list of policy URLs passed to the constructor
private List<String> policyList;
// the map of policies
private PolicyCollection policies;
// the optional schema file
private File schemaFile = null;
// the policy identifier for any policy sets we dynamically create
private static final String POLICY_ID =
"urn:com:sun:xacml:support:finder:dynamic-policy-set";
private static URI policyId = null;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(StaticPolicyFinderModule.class.getName());
static {
try {
policyId = new URI(POLICY_ID);
} catch (Exception e) {
// this can't actually happen, but just in case...
if (logger.isLoggable(Level.SEVERE)) {
logger.log(Level.SEVERE, "couldn't assign default policy id");
}
}
}
/**
* Creates a <code>StaticPolicyFinderModule</code> that provides
* access to the given collection of policies and returns an error when
* more than one policy matches a given context. Any policy that cannot
* be loaded will be noted in the log, but will not cause an error. The
* schema file used to validate policies is defined by the property
* <code>PolicyReader.POLICY_SCHEMA_PROPERTY</code>. If the retrieved
* property is null, then no schema validation will occur.
*
* @param policyList a <code>List</code> of <code>String</code>s that
* represent URLs or files pointing to XACML policies
*/
public StaticPolicyFinderModule(List<String> policyList) {
this.policyList = policyList;
this.policies = new PolicyCollection();
String schemaName =
System.getProperty(PolicyReader.POLICY_SCHEMA_PROPERTY);
if (schemaName != null) {
this.schemaFile = new File(schemaName);
}
}
/**
* Creates a <code>StaticPolicyFinderModule</code> that provides
* access to the given collection of policies and returns an error when
* more than one policy matches a given context. Any policy that cannot
* be loaded will be noted in the log, but will not cause an error.
*
* @param policyList a <code>List</code> of <code>String</code>s that
* represent URLs or files pointing to XACML policies
* @param schemaFile the schema file to validate policies against,
* or null if schema validation is not desired
*/
public StaticPolicyFinderModule(List<String> policyList, String schemaFile) {
this.policyList = policyList;
this.policies = new PolicyCollection();
if (schemaFile != null) {
this.schemaFile = new File(schemaFile);
}
}
/**
* Creates a <code>StaticPolicyFinderModule</code> that provides
* access to the given collection of policies. The given combining
* algorithm is used to create new PolicySets when more than one
* policy applies. Any policy that cannot be loaded will be noted in
* the log, but will not cause an error. The schema file used to
* validate policies is defined by the property
* <code>PolicyReader.POLICY_SCHEMA_PROPERTY</code>. If the retrieved
* property is null, then no schema validation will occur.
*
* @param combiningAlg the algorithm to use in a new PolicySet when more
* than one policy applies
* @param policyList a <code>List</code> of <code>String</code>s that
* represent URLs or files pointing to XACML policies
*
* @throws URISyntaxException if the combining algorithm is not a
* well-formed URI
* @throws UnknownIdentifierException if the combining algorithm identifier
* isn't known
*/
public StaticPolicyFinderModule(String combiningAlg, List<String> policyList)
throws URISyntaxException, UnknownIdentifierException
{
PolicyCombiningAlgorithm alg = (PolicyCombiningAlgorithm)
(CombiningAlgFactory.getInstance().
createAlgorithm(new URI(combiningAlg)));
this.policyList = policyList;
this.policies = new PolicyCollection(alg, policyId);
String schemaName =
System.getProperty(PolicyReader.POLICY_SCHEMA_PROPERTY);
if (schemaName != null) {
this.schemaFile = new File(schemaName);
}
}
/**
* Creates a <code>StaticPolicyFinderModule</code> that provides
* access to the given collection of policies. The given combining
* algorithm is used to create new PolicySets when more than one
* policy applies. Any policy that cannot be loaded will be noted in
* the log, but will not cause an error.
*
* @param combiningAlg the algorithm to use in a new PolicySet when more
* than one policy applies
* @param policyList a <code>List</code> of <code>String</code>s that
* represent URLs or files pointing to XACML policies
* @param schemaFile the schema file to validate policies against,
* or null if schema validation is not desired
*
* @throws URISyntaxException if the combining algorithm is not a
* well-formed URI
* @throws UnknownIdentifierException if the combining algorithm identifier
* isn't known
*/
public StaticPolicyFinderModule(String combiningAlg, List<String> policyList,
String schemaFile)
throws URISyntaxException, UnknownIdentifierException
{
PolicyCombiningAlgorithm alg = (PolicyCombiningAlgorithm)
(CombiningAlgFactory.getInstance().
createAlgorithm(new URI(combiningAlg)));
this.policyList = policyList;
this.policies = new PolicyCollection(alg, policyId);
if (schemaFile != null) {
this.schemaFile = new File(schemaFile);
}
}
/**
* Always returns <code>true</code> since this module does support
* finding policies based on context.
*
* @return true
*/
public boolean isRequestSupported() {
return true;
}
/**
* Initialize this module. Typically this is called by
* <code>PolicyFinder</code> when a PDP is created. This method is
* where the policies are actually loaded.
*
* @param finder the <code>PolicyFinder</code> using this module
*/
public void init(PolicyFinder finder) {
// now that we have the PolicyFinder, we can load the policies
PolicyReader reader = new PolicyReader(finder, logger,
this.schemaFile);
Iterator<String> it = this.policyList.iterator();
while (it.hasNext()) {
String str = it.next();
AbstractPolicy policy = null;
try {
try {
// first try to load it as a URL
URL url = new URL(str);
policy = reader.readPolicy(url);
} catch (MalformedURLException murle) {
// assume that this is a filename, and try again
policy = reader.readPolicy(new File(str));
}
// we loaded the policy, so try putting it in the collection
if (! this.policies.addPolicy(policy)) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "tried to load the same " +
"policy multiple times: " + str);
}
}
} catch (ParsingException pe) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "Error reading policy: " + str,
pe);
}
}
}
}
/**
* Finds a policy based on a request's context. If more than one policy
* matches, then this either returns an error or a new policy wrapping
* the multiple policies (depending on which constructor was used to
* construct this instance).
*
* @param context the representation of the request data
*
* @return the result of trying to find an applicable policy
*/
public PolicyFinderResult findPolicy(EvaluationCtx context) {
try {
context.newEvent(this);
AbstractPolicy policy = this.policies.getPolicy(context);
if (policy == null) {
context.closeCurrentEvent();
return new PolicyFinderResult();
}
context.closeCurrentEvent(policy.getId().toString());
return new PolicyFinderResult(policy);
} catch (TopLevelPolicyException tlpe) {
context.closeCurrentEvent();
return new PolicyFinderResult(tlpe.getStatus());
}
}
}

View File

@ -0,0 +1,226 @@
/*
* @(#)StaticRefPolicyFinderModule.java
*
* Copyright 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 com.sun.xacml.AbstractPolicy;
import com.sun.xacml.ParsingException;
import com.sun.xacml.PolicyMetaData;
import com.sun.xacml.VersionConstraints;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderModule;
import com.sun.xacml.finder.PolicyFinderResult;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This is a simple implementation of <code>PolicyFinderModule</code> that
* supports retrieval based on reference, and is designed for use with a
* run-time configuration. Its constructor accepts a <code>List</code> of
* <code>String</code>s that represent URLs or files, and these are resolved
* to policies when the module is initialized. Beyond this, there is no
* modifying or re-loading the policies represented by this class. The
* policy's identifiers are used for reference resolution.
* <p>
* Note that this class is designed to complement
* <code>StaticPolicyFinderModule</code>. It would be easy to support both
* kinds of policy retrieval in a single class, but the functionality is
* instead split between two classes. The reason is that when you define a
* configuration for your PDP, it's easier to specify the two sets of policies
* by using two different finder modules. Typically, there aren't many
* policies that exist in both sets, so loading the sets separately isn't
* a problem. If this is a concern to you, simply create your own class and
* merge the two existing classes.
* <p>
* This module is provided as an example, but is still fully functional, and
* should be useful for many simple applications. This is provided in the
* <code>support</code> package rather than the core codebase because it
* implements non-standard behavior.
*
* @since 2.0
* @author Seth Proctor
*/
public class StaticRefPolicyFinderModule extends PolicyFinderModule
{
// the list of policy URLs passed to the constructor
private List<String> policyList;
// the map of policies
private PolicyCollection policies;
// the optional schema file
private File schemaFile = null;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(StaticRefPolicyFinderModule.class.getName());
/**
* Creates a <code>StaticRefPolicyFinderModule</code> that provides
* access to the given collection of policies. Any policy that cannot
* be loaded will be noted in the log, but will not cause an error. The
* schema file used to validate policies is defined by the property
* <code>PolicyReader.POLICY_SCHEMA_PROPERTY</code>. If the retrieved
* property is null, then no schema validation will occur.
*
* @param policyList a <code>List</code> of <code>String</code>s that
* represent URLs or files pointing to XACML policies
*/
public StaticRefPolicyFinderModule(List<String> policyList) {
this.policyList = policyList;
this.policies = new PolicyCollection();
String schemaName =
System.getProperty(PolicyReader.POLICY_SCHEMA_PROPERTY);
if (schemaName != null) {
this.schemaFile = new File(schemaName);
}
}
/**
* Creates a <code>StaticRefPolicyFinderModule</code> that provides
* access to the given collection of policyList.
*
* @param policyList a <code>List</code> of <code>String</code>s that
* represent URLs or files pointing to XACML policies
* @param schemaFile the schema file to validate policies against,
* or null if schema validation is not desired
*/
public StaticRefPolicyFinderModule(List<String> policyList, String schemaFile) {
this.policyList = policyList;
this.policies = new PolicyCollection();
if (schemaFile != null) {
this.schemaFile = new File(schemaFile);
}
}
/**
* Always returns <code>true</code> since this module does support
* finding policies based on reference.
*
* @return true
*/
public boolean isIdReferenceSupported() {
return true;
}
/**
* Initialize this module. Typically this is called by
* <code>PolicyFinder</code> when a PDP is created. This method is
* where the policies are actually loaded.
*
* @param finder the <code>PolicyFinder</code> using this module
*/
public void init(PolicyFinder finder) {
// now that we have the PolicyFinder, we can load the policies
PolicyReader reader = new PolicyReader(finder, logger,
this.schemaFile);
Iterator<String> it = this.policyList.iterator();
while (it.hasNext()) {
String str = it.next();
AbstractPolicy policy = null;
try {
try {
// first try to load it as a URL
URL url = new URL(str);
policy = reader.readPolicy(url);
} catch (MalformedURLException murle) {
// assume that this is a filename, and try again
policy = reader.readPolicy(new File(str));
}
// we loaded the policy, so try putting it in the collection
if (! this.policies.addPolicy(policy)) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "tried to load the same " +
"policy multiple times: " + str);
}
}
} catch (ParsingException pe) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "Error reading policy: " + str,
pe);
}
}
}
}
/**
* Attempts to find a policy by reference, based on the provided
* parameters.
*
* @param idReference an identifier specifying some policy
* @param type type of reference (policy or policySet) as identified by
* the fields in <code>PolicyReference</code>
* @param constraints any optional constraints on the version of the
* referenced policy (this will never be null, but
* it may impose no constraints, and in fact will
* never impose constraints when used from a pre-2.0
* XACML policy)
* @param parentMetaData the meta-data from the parent policy, which
* provides XACML version, factories, etc.
*
* @return the result of looking for a matching policy
*/
public PolicyFinderResult findPolicy(URI idReference, int type,
VersionConstraints constraints,
PolicyMetaData parentMetaData) {
AbstractPolicy policy = this.policies.getPolicy(idReference.toString(),
type, constraints);
if (policy == null) {
return new PolicyFinderResult();
}
return new PolicyFinderResult(policy);
}
}

View File

@ -0,0 +1,132 @@
/*
* @(#)TopLevelPolicyException.java
*
* Copyright 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 com.sun.xacml.ctx.Status;
/**
* This is an exception thrown by the support code when there's an error
* trying to resolve a top-level policy
*
* @since 2.0
* @author Seth Proctor
*/
public class TopLevelPolicyException extends Exception
{
/**
*
*/
private static final long serialVersionUID = 1L;
// status explaining the error
private transient Status status;
/**
* Constructs a new <code>TopLevelPolicyException</code> with no message
* or cause.
*
* @param status the <code>Status</code> associated with this error
*/
public TopLevelPolicyException(Status status) {
this.status = status;
}
/**
* Constructs a new <code>TopLevelPolicyException</code> with a message,
* but no cause. The message is saved for later retrieval by the
* {@link java.lang.Throwable#getMessage() Throwable.getMessage()}
* method.
*
* @param status the <code>Status</code> associated with this error
* @param message the detail message (<code>null</code> if nonexistent
* or unknown)
*/
public TopLevelPolicyException(Status status, String message) {
super(message);
this.status = status;
}
/**
* Constructs a new <code>TopLevelPolicyException</code> with a cause,
* but no message. The cause is saved for later retrieval by the
* {@link java.lang.Throwable#getCause() Throwable.getCause()}
* method.
*
* @param status the <code>Status</code> associated with this error
* @param cause the cause (<code>null</code> if nonexistent
* or unknown)
*/
public TopLevelPolicyException(Status status, Throwable cause) {
super(cause);
this.status = status;
}
/**
* Constructs a new <code>TopLevelPolicyException</code> with a message
* and a cause. The message and cause are saved for later retrieval
* by the
* {@link java.lang.Throwable#getMessage() Throwable.getMessage()} and
* {@link java.lang.Throwable#getCause() Throwable.getCause()}
* methods.
*
* @param status the <code>Status</code> associated with this error
* @param message the detail message (<code>null</code> if nonexistent
* or unknown)
* @param cause the cause (<code>null</code> if nonexistent
* or unknown)
*/
public TopLevelPolicyException(Status status, String message,
Throwable cause) {
super(message, cause);
this.status = status;
}
/**
* Returns the status information associated with this error.
*
* @return associated status
*/
public Status getStatus() {
return this.status;
}
}

View File

@ -0,0 +1,209 @@
/*
* @(#)URLPolicyFinderModule.java
*
* Copyright 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 com.sun.xacml.AbstractPolicy;
import com.sun.xacml.ParsingException;
import com.sun.xacml.Policy;
import com.sun.xacml.PolicyMetaData;
import com.sun.xacml.PolicyReference;
import com.sun.xacml.PolicySet;
import com.sun.xacml.VersionConstraints;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderModule;
import com.sun.xacml.finder.PolicyFinderResult;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.logging.Logger;
/**
* This module supports references made with resolvable URLs (eg, http or
* file pointers). No policies are cached. Instead, all policy references are
* resolved in real-time. To make this module as generally applicable as
* possible, no errors are ever returned when attempting to resolve a
* policy. This means that if a resolved policy is invalid, a server cannot
* be contacted, etc., this module simply reports that it cannot provide a
* policy. If you need to report errors, or support any caching, you have to
* write your own implementation.
* <p>
* This module is provided as an example, but is still fully functional, and
* should be useful for many simple applications. This is provided in the
* <code>support</code> package rather than the core codebase because it
* implements non-standard behavior.
*
* @since 2.0
* @author Seth Proctor
*/
public class URLPolicyFinderModule extends PolicyFinderModule
{
// the optional schema file for validating policies
private File schemaFile;
// the reader used to load all policies
private PolicyReader reader;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(URLPolicyFinderModule.class.getName());
/**
* Creates a <code>URLPolicyFinderModule</code>. The schema file used
* to validate policies is specified by the property
* <code>PolicyReader.POLICY_SCHEMA_PROPERTY</code>. If the retrieved
* property is null, then no schema validation will occur.
*/
public URLPolicyFinderModule() {
String schemaName =
System.getProperty(PolicyReader.POLICY_SCHEMA_PROPERTY);
if (schemaName != null) {
this.schemaFile = new File(schemaName);
}
}
/**
* Creates a <code>URLPolicyFinderModule</code> that may do schema
* validation of policies.
*
* @param schemaFile the schema file to use for validation, or null if
* validation isn't desired
*/
public URLPolicyFinderModule(String schemaFile) {
this.schemaFile = new File(schemaFile);
}
/**
* Always returns <code>true</code> since this module does support
* finding policies based on reference.
*
* @return true
*/
public boolean isIdReferenceSupported() {
return true;
}
/**
* Initialize this module. Typically this is called by
* <code>PolicyFinder</code> when a PDP is created.
*
* @param finder the <code>PolicyFinder</code> using this module
*/
public void init(PolicyFinder finder) {
this.reader = new PolicyReader(finder, logger, this.schemaFile);
}
/**
* Attempts to find a policy by reference, based on the provided
* parameters. Specifically, this module will try to treat the reference
* as a URL, and resolve that URL directly. If the reference is not
* a valid URL, cannot be resolved, or does not resolve to an XACML
* policy, then no matching policy is returned. This method never
* returns an error.
*
* @param idReference an identifier specifying some policy
* @param type type of reference (policy or policySet) as identified by
* the fields in <code>PolicyReference</code>
* @param constraints any optional constraints on the version of the
* referenced policy (this will never be null, but
* it may impose no constraints, and in fact will
* never impose constraints when used from a pre-2.0
* XACML policy)
* @param parentMetaData the meta-data from the parent policy, which
* provides XACML version, factories, etc.
*
* @return the result of looking for a matching policy
*/
public PolicyFinderResult findPolicy(URI idReference, int type,
VersionConstraints constraints,
PolicyMetaData parentMetaData) {
// see if the URI is in fact a URL
URL url = null;
try {
url = new URL(idReference.toString());
} catch (MalformedURLException murle) {
// it's not a URL, so we can't handle this reference
return new PolicyFinderResult();
}
// try resolving the URL
AbstractPolicy policy = null;
try {
policy = this.reader.readPolicy(url);
} catch (ParsingException pe) {
// An error loading the policy could be many things (the URL
// doesn't actually resolve a policy, the server is down, the
// policy is invalid, etc.). This could be interpreted as an
// error case, or simply as a case where no applicable policy
// is available (as is done when we pre-load policies). This
// module chooses the latter interpretation.
return new PolicyFinderResult();
}
// check that we got the right kind of policy...if we didn't, then
// we can't handle the reference
if (type == PolicyReference.POLICY_REFERENCE) {
if (! (policy instanceof Policy)) {
return new PolicyFinderResult();
}
} else {
if (! (policy instanceof PolicySet)) {
return new PolicyFinderResult();
}
}
// finally, check that the constraints match ... note that in a more
// powerful module, you could actually have used the constraints to
// construct a more specific URL, passed the constraints to the
// server, etc., but this example module is staying simple
if (! constraints.meetsConstraint(policy.getVersion())) {
return new PolicyFinderResult();
}
// if we got here, then we successfully resolved a policy that is
// the correct type, so return it
return new PolicyFinderResult(policy);
}
}

View File

@ -0,0 +1,73 @@
/*
* @(#)AppTest.java
*
* Copyright 2005-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;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.aniketos.securebpmn.xacml</groupId>
<artifactId>eu.aniketos.securebpmn.xacml.parent</artifactId>
<version>1.0</version>
<relativePath>../eu.aniketos.securebpmn.xacml.parent/pom.xml</relativePath>
</parent>
<artifactId>com.sun.xacml</artifactId>
<packaging>jar</packaging>
<version>0.1</version>
<name>com.sun.xacml</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<version>2.3.2</version>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>[4.8,)</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>[1.2,)</version>
</dependency>
<!-- dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency -->
<!-- dependency>
<groupId>jaxb</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1.5</version>
</dependency -->
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,820 @@
/*
* @(#)AbstractPolicy.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 com.sun.xacml;
import com.sun.xacml.combine.CombinerElement;
import com.sun.xacml.combine.CombinerParameter;
import com.sun.xacml.combine.CombiningAlgorithm;
import com.sun.xacml.combine.CombiningAlgFactory;
import com.sun.xacml.combine.PolicyCombiningAlgorithm;
import com.sun.xacml.combine.RuleCombiningAlgorithm;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.PolicyIssuer;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Represents an instance of an XACML policy.
*
* @since 1.0
* @author Seth Proctor
* @author Marco Barreno
* @author Ludwig Seitz
*
*/
public abstract class AbstractPolicy implements PolicyTreeElement, Cloneable {
// atributes associated with this policy
private URI idAttr;
private CombiningAlgorithm combiningAlg;
/**
* The version number for this policy. This is _not_ the XACML or
* XPath version. This is for versioning policies/policySets.
*/
private String version;
// the elements in the policy
private String description;
private PolicyIssuer policyIssuer;
private Target target;
// the default version of XPath
private String defaultVersion;
// the meta-data associated with this policy
private PolicyMetaData metaData;
// the child elements under this policy represented simply as the
// PolicyTreeElements...
private List<PolicyTreeElement> children;
// ...or the CombinerElements that are passed to combining algorithms
private List<CombinerElement> childElements;
// any obligations held by this policy
private Set<Obligation> obligations;
// the list of combiner parameters
private List<CombinerParameter> parameters;
// the maximum delegation depth authorised by this AbstractPolicy.
private int maxDelegationDepth = Constants.MAX_DELEGATION_DEPTH_UNDEFINED;
protected RuntimeInfo src;
/**
* Constructor used by <code>PolicyReference</code>, which supplies
* its own values for the methods in this class.
*/
protected AbstractPolicy() {
// Used by PolicyRefence
}
/**
* Constructor used to create a policy from concrete components.
*
* @param id the policy id
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the XACML version identifier.
* @param combiningAlg the combining algorithm to use
* @param description describes the policy or null if there is none
* @param issuer the policy's issuer, used for delegation, can be null.
* @param target the policy's target
* @param defaultVersion the XPath version to use for selectors,
* can be null.
* @param obligations the policy's obligations, can be null.
* @param parameters the policy's combiner parameters, can be null.
* @param maxDelegationDepth the maximum depth of delegation authorised
* by this policy. A value of -1 indicates
* that this was not set.
*/
protected AbstractPolicy(URI id, String version, String xacmlVersion,
CombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer,
Target target, String defaultVersion,
Set<Obligation> obligations, List<CombinerParameter> parameters,
int maxDelegationDepth) {
this.idAttr = id;
this.combiningAlg = combiningAlg;
this.description = description;
this.target = target;
this.defaultVersion = defaultVersion;
this.policyIssuer = issuer;
if (version == null) {
this.version = "1.0";
} else {
this.version = version;
}
this.metaData = new PolicyMetaData(xacmlVersion, defaultVersion);
if (obligations == null) {
this.obligations = Obligation.EMPTY_SET;
} else {
this.obligations = Collections.
unmodifiableSet(new HashSet<Obligation>(obligations));
}
if (parameters == null) {
this.parameters = CombinerParameter.EMPTY_LIST;
} else {
this.parameters = Collections.
unmodifiableList(new ArrayList<CombinerParameter>(parameters));
}
this.maxDelegationDepth = maxDelegationDepth;
}
/**
* Constructor used by child classes to initialize the shared data from
* a DOM root node.
*
* @param root the DOM root of the policy
* @param policyPrefix either "Policy" or "PolicySet"
* @param combiningName name of the field naming the combining alg
*
* @throws ParsingException if the policy is invalid
*/
protected AbstractPolicy(Node root, String policyPrefix,
String combiningName) throws ParsingException {
// get the attributes, all of which are common to Policies
NamedNodeMap attrs = root.getAttributes();
try {
// get the attribute Id
this.idAttr = new URI(attrs.getNamedItem(policyPrefix + "Id")
.getNodeValue());
} catch (Exception e) {
throw new ParsingException("Error while parsing required "
+ "attribute " + policyPrefix + "Id of a "
+ policyPrefix, e);
}
// see if there's a version
Node versionNode = attrs.getNamedItem("Version");
if (versionNode != null) {
this.version = versionNode.getNodeValue();
} else {
// assign the default version
this.version = "1.0";
}
// see if there's a MaxDelegationDepth
Node depthNode = attrs.getNamedItem("MaxDelegationDepth");
if (depthNode != null) {
this.maxDelegationDepth
= Integer.parseInt(depthNode.getNodeValue());
} else {
this.maxDelegationDepth = Constants.MAX_DELEGATION_DEPTH_UNDEFINED;
}
// now get the combining algorithm...
try {
URI algId = new URI(attrs.getNamedItem(combiningName).
getNodeValue());
CombiningAlgFactory factory = CombiningAlgFactory.getInstance();
this.combiningAlg = factory.createAlgorithm(algId);
} catch (URISyntaxException e) {
throw new ParsingException("Error parsing combining algorithm" +
" in " + policyPrefix, e);
} catch (UnknownIdentifierException e) {
throw new ParsingException("Error parsing combining algorithm" +
" in " + policyPrefix, e);
}
// ...and make sure it's the right kind
if (policyPrefix.equals("Policy")) {
if (! (this.combiningAlg instanceof RuleCombiningAlgorithm)) {
throw new ParsingException("Policy must use a Rule " +
"Combining Algorithm");
}
} else {
if (! (this.combiningAlg instanceof PolicyCombiningAlgorithm)) {
throw new ParsingException("PolicySet must use a Policy " +
"Combining Algorithm");
}
}
// do an initial pass through the elements to pull out the
// defaults, if any, so we can setup the meta-data
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE
&& child.getLocalName().equals(
policyPrefix + "Defaults")) {
handleDefaults(child);
}
}
// with the defaults read, create the meta-data
this.metaData = new PolicyMetaData(root.getNamespaceURI(),
this.defaultVersion);
// now read the remaining policy elements
this.obligations = new HashSet<Obligation>();
this.parameters = new ArrayList<CombinerParameter>();
this.policyIssuer = null;
children = root.getChildNodes();
// now read the policy elements
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
String cname = child.getLocalName();
if (cname.equals("Description")) {
if (child.getFirstChild() != null) {
this.description = child.getFirstChild().getNodeValue();
}
} else if (cname.equals("PolicyIssuer")) {
parsePolicyIssuerAttributes(child);
} else if (cname.equals("Target")) {
this.target = Target.getInstance(child, this.metaData);
} else if (cname.equals("Obligations")) {
parseObligations(child);
} else if (cname.equals(policyPrefix + "Defaults")) {
handleDefaults(child);
} else if (cname.equals("CombinerParameters")) {
handleParameters(child);
}
}
}
// finally, make sure the obligations and parameters are immutable
this.obligations = Collections.unmodifiableSet(this.obligations);
this.parameters = Collections.unmodifiableList(this.parameters);
}
/**
* The clone method.
* FIXME: this does no deep copy on the Lists and Sets.
*
* @return a copy of this object.
*/
public Object clone() {
try {
AbstractPolicy clone = (AbstractPolicy)super.clone();
clone.idAttr = this.idAttr;
try {
clone.combiningAlg
= CombiningAlgFactory.getInstance().createAlgorithm(
this.combiningAlg.getIdentifier());
} catch (UnknownIdentifierException e) {
throw new RuntimeException("Impossible exception: "
+ e.getMessage());
}
clone.version = this.version;
clone.description = this.description;
if (this.policyIssuer != null) {
clone.policyIssuer
= (PolicyIssuer)this.policyIssuer.clone();
} else { clone.policyIssuer = null; }
clone.target = (Target)this.target.clone();
clone.defaultVersion = this.defaultVersion;
clone.metaData = this.metaData;
clone.obligations = new HashSet<Obligation>(this.obligations);
clone.parameters = new ArrayList<CombinerParameter>(this.parameters);
clone.maxDelegationDepth = this.maxDelegationDepth;
return clone;
} catch (CloneNotSupportedException e1) {// this should never happen
throw new RuntimeException("Couldn't clone AbstractPolicy");
}
}
/**
* Helper routine that parses the PolicyIssuer attributes in
* the policy or policy set
* @param root the root node of PolicyIssuer
* @throws ParsingException
*/
private void parsePolicyIssuerAttributes(Node root)
throws ParsingException {
NodeList nodes = root.getChildNodes();
Set<Attribute> issuerAttr = new HashSet<Attribute>();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getLocalName().equals("Attribute")) {
List<Attribute> attrs = Attribute.getInstances(node);
issuerAttr.addAll(attrs);
}
}
this.policyIssuer = new PolicyIssuer(issuerAttr);
}
/**
* Helper routine to parse the obligation data
*
* @param root The node containing the obligation data.
*
* @throws ParsingException
*/
private void parseObligations(Node root) throws ParsingException {
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getLocalName().equals("Obligation")) {
this.obligations.add(Obligation.getInstance(node));
}
}
}
/**
* There used to be multiple things in the defaults type, but now
* there's just the one string that must be a certain value, so it
* doesn't seem all that useful to have a class for this...we could
* always bring it back, however, if it started to do more
*
* @param root The node that contains the XPathVersion.
*/
private void handleDefaults(Node root) throws ParsingException {
this.defaultVersion = null;
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getLocalName().equals("XPathVersion")) {
if (node.getFirstChild() != null) {
this.defaultVersion = node.getFirstChild().getNodeValue();
} else {
throw new ParsingException("XPathVersion xml-attribute"
+ "didn't have a value");
}
}
}
}
/**
* Handles all the CombinerParameters in the policy or policy set
*
* @param root The node containing the CombinerParameters.
*
* @throws ParsingException
*/
private void handleParameters(Node root) throws ParsingException {
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getLocalName().equals("CombinerParameter")) {
this.parameters.add(CombinerParameter.getInstance(node));
}
}
}
/**
* Returns the id of this policy
*
* @return the policy id
*/
public URI getId() {
return this.idAttr;
}
/**
* Returns the version of this policy. If this is an XACML 1.x policy
* then this will always return <code>"1.0"</code>.
*
* @return the policy version
*/
public String getVersion() {
return this.version;
}
/**
* Returns the combining algorithm used by this policy
*
* @return the combining algorithm
*/
public CombiningAlgorithm getCombiningAlg() {
return this.combiningAlg;
}
/**
* Returns the list of input parameters for the combining algorithm. If
* this is an XACML 1.x policy then the list will always be empty.
*
* @return a <code>List</code> of <code>CombinerParameter</code>s
*/
public List<CombinerParameter> getCombiningParameters() {
return this.parameters;
}
/**
* Returns the given description of this policy or null if there is no
* description
*
* @return the description or null
*/
public String getDescription() {
return this.description;
}
/**
* Returns a <code>PolicyIssuer</code> that represents the
* PolicyIssuer for this policy.
*
* @return a <code>PolicyIssuer</code> or null
*/
public PolicyIssuer getPolicyIssuer() {
return this.policyIssuer;
}
/**
* Returns the target for this policy
*
* @return the policy's target
*/
public Target getTarget() {
return this.target;
}
/**
* Returns the XPath version to use or null if none was specified
*
* @return XPath version or null
*/
public String getDefaultVersion() {
return this.defaultVersion;
}
/**
* Returns the <code>List</code> of children under this node in the
* policy tree. Depending on what kind of policy this node represents
* the children will either be <code>AbstractPolicy</code> objects
* or <code>Rule</code>s.
*
* @return a <code>List</code> of child nodes
*/
public List<PolicyTreeElement> getChildren() {
return this.children;
}
/**
* Returns the <code>List</code> of <code>CombinerElement</code>s that
* is provided to the combining algorithm. This returns the same set
* of children that <code>getChildren</code> provides along with any
* associated combiner parameters.
*
* @return a <code>List</code> of <code>CombinerElement</code>s
*/
public List<CombinerElement> getChildElements() {
return this.childElements;
}
/**
* Returns the Set of obligations for this policy, which may be empty
*
* @return the policy's obligations
*/
public Set<Obligation> getObligations() {
return this.obligations;
}
/**
* Returns the meta-data associated with this policy
*
* @return the policy's meta data.
*/
public PolicyMetaData getMetaData() {
return this.metaData;
}
/**
*@return Returns the maximum delegation depth or
* Integer.MAX_VALUE if there is none.
*/
public int getMaxDelegationDepth() {
return this.maxDelegationDepth;
}
/**
* 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.
*
* @param context the representation of the request
*
* @return the result of trying to match the policy and the request
*/
public MatchResult match(EvaluationCtx context) {
return this.target.match(context);
}
/**
* Sets the child policy tree elements for this node, which are passed
* to the combining algorithm on evaluation. The <code>List</code> must
* contain <code>CombinerElement</code>s, which in turn will contain
* <code>Rule</code>s or <code>AbstractPolicy</code>s, but may not
* contain both types of elements.
*
* @param children1 a <code>List</code> of <code>CombinerElement</code>s
* representing the child elements used by the combining
* algorithm
*/
protected void setChildren(List<CombinerElement> children1) {
// we always want a concrete list, since we're going to pass it to
// a combiner that expects a non-null input
if (children1 == null) {
this.children = PolicyTreeElement.EMPTY_LIST;
} else {
// NOTE: since this is only getting called by known child
// classes we don't check that the types are all the same
List<PolicyTreeElement> list = new ArrayList<PolicyTreeElement>();
for ( CombinerElement element : children1 ) {
list.add(element.getElement());
}
this.children = Collections.unmodifiableList(list);
this.childElements = Collections.unmodifiableList(children1);
}
}
/**
* 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) {
//Need to this as parent policy set if this is a policy set
if (this instanceof PolicySet) {
context.saveParentPolicySet(this);
}
RuntimeInfo combSrc = null;
// check if runtime info is there and actually used
if ( src != null ) {
//combSrc = RuntimeInfo.getIndirectSourceLocator(src, ELEMENT_TYPE.COMBINING_ALG);
//combSrc = src.getIndirectSourceLocator(ELEMENT_TYPE.COMBINING_ALG);
combSrc = src.getIndirectRuntimeInfo(combiningAlg, ELEMENT_TYPE.COMBINING_ALG);
this.combiningAlg.setRuntimeInfo(combSrc);
}
//prepare result variable
Result result = this.combiningAlg.combine(context, this.parameters,
this.childElements);
if ( combSrc != null ) {
this.combiningAlg.unsetRuntimeInfo(combSrc);
}
if (this instanceof PolicySet) {
context.popParentPolicySet();
}
//create a set for collecting obligations
Set<Obligation> collectedObligations = new HashSet<Obligation>();
// Do we need to reduce this request to the trustedIssuer?
if (!hasTrustedIssuer()) {
if (result.getDecision() == Result.DECISION_NOT_APPLICABLE) {
// we do not need to process reduction for this result
return null;
}
context.createReductionGraph();
Result reductionResult = context.getReductionGraph().reduce(
context, result, this.idAttr);
if (reductionResult == null
|| reductionResult.getDecision()
== Result.DECISION_INDETERMINATE) {
//The reduction failed so we return this result now.
return reductionResult;
}
//check for obligations
collectedObligations.addAll(reductionResult.getObligations());
}
// add the obligations of the current policy
collectedObligations.addAll(this.obligations);
// if we have no obligations, we're done
if (collectedObligations.size() == 0) {
return result;
}
// now, see if we should add any obligations to the set
int effect = result.getDecision();
if ((effect == Result.DECISION_INDETERMINATE)
|| (effect == Result.DECISION_NOT_APPLICABLE)) {
// we didn't permit/deny, so we never return obligations
return result;
}
Iterator<Obligation> it = collectedObligations.iterator();
while (it.hasNext()) {
Obligation obligation = it.next();
if (obligation.getFulfillOn() == effect) {
result.addObligation(obligation.evaluate(context));
}
}
// finally, return the result
return result;
}
/**
* Routine used by <code>Policy</code> and <code>PolicySet</code> to
* encode the PolicyIssuer element.
*
* @param output a stream into which the XML-encoded data is written
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
protected void encodePolicyIssuer(OutputStream output,
String charsetName, Indenter indenter)
throws UnsupportedEncodingException {
if (this.policyIssuer != null) {
PrintStream out = new PrintStream(output);
String indent = indenter.makeString();
out.println(indent + "<PolicyIssuer>");
indenter.in();
Iterator<Map.Entry<URI, Set<Attribute>>> it = this.policyIssuer.getAttributes().entrySet()
.iterator();
while (it.hasNext()) {
Map.Entry<URI, Set<Attribute>> entry = it.next();
Iterator<Attribute> it2 = entry.getValue().iterator();
while (it2.hasNext()) {
Attribute attr = it2.next();
attr.encode(output, charsetName, indenter);
}
}
out.println(indent + "</PolicyIssuer>");
indenter.out();
}
}
/**
* Routine used by <code>Policy</code> and <code>PolicySet</code> to
* encode some common elements.
*
* @param output a stream into which the XML-encoded data is written
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
protected void encodeCommonElements(OutputStream output,
String charsetName, Indenter indenter)
throws UnsupportedEncodingException {
for ( CombinerElement element : this.childElements ) {
element.encode(output, charsetName, indenter);
}
if (this.obligations.size() != 0) {
PrintStream out = new PrintStream(output);
String indent = indenter.makeString();
out.println(indent + "<Obligations>");
indenter.in();
Iterator<Obligation> oblIt = this.obligations.iterator();
while (oblIt.hasNext()) {
oblIt.next().encode(output, charsetName, indenter);
}
out.println(indent + "</Obligations>");
indenter.out();
}
}
/**
* Method for checking if a policy was issued by the trusted issuer
*
* @return True if the PolicyIssuer is the trusted issuer
*/
public boolean hasTrustedIssuer() {
if (this.policyIssuer == null) {
return true;
}
return false;
}
/**
* Method for getting the issue date of this policy, if it was set in the
* policyIssuer member. Returns null if it has not been set.
*
* @return the date at which this policy was issued or null.
*/
public Date getIssueDate() {
if (this.policyIssuer != null) {
return this.policyIssuer.getIssueDate();
}
return null;
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
// public void setSourceLocator(RuntimeInfo src) {
// this.src = src;
// }
/**
* Returns a copy of this abstract policy with a new isser.
* This is useful when policies are rewritten, for instance after
* a digital signature is verified, in which case the issuer
* is generated based on the signature of the policy.
* Also useful for implementing some models of revocation.
*
* @param issuer The new policy issuer.
* @return A identical copy of the abstract policy with
* a new issuer.
*/
public AbstractPolicy copyWithNewPolicyIssuer(PolicyIssuer issuer) {
AbstractPolicy newPolicy = (AbstractPolicy)clone();
newPolicy.policyIssuer = issuer;
return newPolicy;
}
}

View File

@ -0,0 +1,262 @@
/*
* @(#)Constants.java
*
* Copyright 2005-2006 Swedish Institute of Computer Science 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 Swedish Institute of Computer Science 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. THE SWEDISH INSTITUE OF COMPUTER
* SCIENCE ("SICS") 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 SICS 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 SICS 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;
import java.net.URI;
/**
* A collection of XACML constants used across various classes.
*
* @since 3.0
* @author Ludwig Seitz
*/
public class Constants {
/**
* The standard URI for listing a resource's id
*/
public static final URI RESOURCE_ID =
URI.create("urn:oasis:names:tc:xacml:1.0:resource:resource-id");
/**
* The standard URI for listing a subject's id
*/
public static final URI SUBJECT_ID =
URI.create("urn:oasis:names:tc:xacml:1.0:subject:subject-id");
/**
* The standard URI for listing a subject's id
*/
public static final URI ACTION_ID =
URI.create("urn:oasis:names:tc:xacml:1.0:action:action-id");
/**
* The standard URI for listing a resource's scope
*/
public static final URI RESOURCE_SCOPE =
URI.create("urn:oasis:names:tc:xacml:1.0:resource:scope");
/**
* The standard Subject category (compatibility code
* for XACML 2.0)
*/
public static final URI SUBJECT_CAT = URI.create(
"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject");
/**
* The standard Resource category.
*/
public static final URI RESOURCE_CAT = URI.create(
"urn:oasis:names:tc:xacml:3.0:attribute-category:resource");
/**
* The standard Resource category.
*/
public static final URI ACTION_CAT = URI.create(
"urn:oasis:names:tc:xacml:3.0:attribute-category:action");
/**
* The standard Resource category.
*/
public static final URI ENVIRONMENT_CAT = URI.create(
"urn:oasis:names:tc:xacml:3.0:attribute-category:environment");
/**
* Resource scope of Immediate (only the given resource)
*/
public static final int SCOPE_IMMEDIATE = 0;
/**
* Resource scope of Children (the given resource and its direct
* children)
*/
public static final int SCOPE_CHILDREN = 1;
/**
* Resource scope of Descendants (the given resource and all descendants
* at any depth or distance)
*/
public static final int SCOPE_DESCENDANTS = 2;
/**
* Resource scope of XPath-expression (a set of nodes selected by an
* XPath expression)
*/
public static final int SCOPE_XPATH_EXPRESSION = 3;
/**
* Resource scope of EntireHierarchy (a node and all it's descendants)
*/
public static final int SCOPE_ENTIRE_HIERARCHY = 4;
/**
* Scope of multiple elements. This applies to requests with multiple
* Resources for XACML versions < 3.0 and to requests with multiple
* Attributes elements of the same category for XACML versions >= 3.0
*/
public static final int SCOPE_MULTIPE_ELEMENTS = 5;
/**
* A reserved category for delegate matching
*/
public static final URI DELEGATE = URI.create(
"urn:oasis:names:tc:xacml:3.0:attribute-category:delegate");
/**
* A reserved category for delegate information matching
*/
public static final URI DELEGATION_INFO
= URI.create("urn:oasis:names:tc:xacml:3.0:attribute-category:"
+ "delegation-info");
/**
* The reserved URI prefix for delegated attribute matching
*/
public static final String DELEGATED =
"urn:oasis:names:tc:xacml:3.0:attribute-category:delegated:";
/**
* The reserved URI for the delegation decision
*/
public static final URI DECISION = URI.create(
"urn:oasis:names:tc:xacml:3.0:delegation:decision");
/**
* The reserved URI for the delegation depth
*/
public static final URI DELEGATION_DEPTH = URI.create(
"urn:oasis:names:tc:xacml:3.0:delegation:depth");
/**
* XACML 1.0 identifier
*/
public static final String XACML_1_0_IDENTIFIER =
"urn:oasis:names:tc:xacml:1.0:policy";
/**
* XACML 1.0 context identifier
*/
public static final String XACML_1_0_CTX_ID =
"urn:oasis:names:tc:xacml:1.0:context";
/**
* XACML 2.0 identifier
*/
public static final String XACML_2_0_IDENTIFIER =
"urn:oasis:names:tc:xacml:2.0:policy:schema:os";
/**
* XACML 1.0 context identifier
*/
public static final String XACML_2_0_CTX_ID =
"urn:oasis:names:tc:xacml:2.0:context:schema:os";
/**
* XACML 3.0 identifier
*/
public static final String XACML_3_0_IDENTIFIER =
"urn:oasis:names:tc:xacml:3.0:schema:os";
/**
* Version identifier for XACML 1.0
*/
public static final int XACML_VERSION_1_0 = 0;
/**
* Version identifier for XACML 1.1 (which isn't a formal release
* so has no namespace string, but still exists as a separate
* specification)
*/
public static final int XACML_VERSION_1_1 = 1;
/**
* Version identifier for XACML 1.2
*/
public static final int XACML_VERSION_2_0 = 2;
/**
* Version identifier for XACML 3.0
*/
public static final int XACML_VERSION_3_0 = 3;
/**
* The default version of XACML, 3.0, used if no namespace string
* is specified
*/
public static final int XACML_DEFAULT_VERSION = XACML_VERSION_3_0;
/**
* XPath 1.0 identifier
*/
public static final String XPATH_1_0_IDENTIFIER =
"http://www.w3.org/TR/1999/Rec-xpath-19991116";
/**
* Version identifier for an unspecified version of XPath
*/
public static final int XPATH_VERSION_UNSPECIFIED = 0;
/**
* Version identifier for XPath 1.0
*/
public static final int XPATH_VERSION_1_0 = 1;
/**
* Max delegation delegation depth undefined
*/
public static final int MAX_DELEGATION_DEPTH_UNDEFINED = Integer.MAX_VALUE;
/**
* System specific line separator
*/
public static final String nl = System.getProperty("line.separator");
/**
* Key for User Data available from node, describing the start line of the node in the
* xml source file. Feature must be activated.
*/
public static final String LINE_NUMBER = "startLine";
/**
* Key for User Data available from node, describing the source file of the node
*/
public static final String SOURCE_FILE = "srcFile";
}

View File

@ -0,0 +1,342 @@
/*
* @(#)EvaluationCtx.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;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.DateAttribute;
import com.sun.xacml.attr.DateTimeAttribute;
import com.sun.xacml.attr.TimeAttribute;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.ctx.RequestElement;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.reduction.ReductionGraph;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.w3c.dom.Node;
/**
* Manages the context of a single policy evaluation. Typically, an instance
* is instantiated whenever the PDP gets a request and needs to perform an
* evaluation as a result. The <code>BasicEvaluationCtx</code> class
* provides a basic implementation that is used by default.
*
* @since 1.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public interface EvaluationCtx
{
/**
* Create a context for an administrative request from an
* existing context.
*
* @param decision The decision code corresponding to those in the
* <code>Result</code> class.
* @param delegate The delegate in this request (a set containing a
* single <code>RequestElement</code>).
*
* @return An administrative context for this context.
*/
public EvaluationCtx createAdminCtx(int decision, Set<RequestElement> delegate);
/**
* Creates a copy of this context with disabled attribute finder.
*
* @return A copy of this context with disabled attribute finder.
*/
public EvaluationCtx copyWithoutAttributeFinder();
/**
* Returns the DOM root of the original RequestType XML document, if
* this context is backed by an XACML Request. If this context is not
* backed by an XML representation, then an exception is thrown.
*
* @return the DOM root node
*
* @throws UnsupportedOperationException if the context is not backed
* by an XML representation
*/
public Node getRequestRoot();
/**
* Returns the resource scope, which will be one of the five fields
* denoting Immediate, Children, Descendants, XPath-expression or
* EntireHierarchy.
*
* @return the scope of the resource
*/
public int getScope();
/**
* Returns the identifier for the resource being requested.
*
* @return the resource
*/
public AttributeValue getResourceId();
/**
* Changes the value of the resource-id attribute in this context. This
* is useful when you have multiple resources (ie, a scope other than
* IMMEDIATE), and you need to keep changing only the resource-id to
* evaluate the different effective requests.
*
* @param resourceId the new resource-id value
*/
public void setResourceId(AttributeValue resourceId);
/**
* Returns the value for the current time as known by the PDP (if this
* value was also supplied in the Request, this will generally be a
* different value). Details of caching or location-based resolution
* are left to the underlying implementation.
*
* @return the current time
*/
public TimeAttribute getCurrentTime();
/**
* Returns the value for the current date as known by the PDP (if this
* value was also supplied in the Request, this will generally be a
* different value). Details of caching or location-based resolution
* are left to the underlying implementation.
*
* @return the current date
*/
public DateAttribute getCurrentDate();
/**
* Returns the value for the current dateTime as known by the PDP (if this
* value was also supplied in the Request, this will generally be a
* different value). Details of caching or location-based resolution
* are left to the underlying implementation.
*
* @return the current date
*/
public DateTimeAttribute getCurrentDateTime();
/**
* Return available attribute values of the selected category.
*
* @param category the category the attribute value(s) must be in
* @param type the type of the attribute value(s) to find
* @param id the id of the attribute value(s) to find
* @param issuer the issuer of the attribute value(s) to find or null
*
* @return a result containing a bag either empty because no values were
* found or containing at least one value, or status associated with an
* Indeterminate result
*/
public EvaluationResult getAttribute(URI category, URI type, URI id,
URI issuer);
/**
* Returns the attribute value(s) retrieved using the given XPath
* expression.
*
* @param contextPath the XPath expression to search
* @param namespaceNode the DOM node defining namespace mappings to use,
* or null if mappings come from the context root
* @param type the type of the attribute value(s) to find
* @param xpathVersion the version of XPath to use
*
* @return a result containing a bag either empty because no values were
* found or containing at least one value, or status associated with an
* Indeterminate result
*/
public EvaluationResult getAttribute(String contextPath,
Node namespaceNode, URI type,
String xpathVersion);
/**
* Get the decision.
*
* @return The <code>int</code> value of the decision according to
* the <code>Result</code> class.
*/
public int getDecision();
/**
* Get the delegation depth.
*
* @return The <code>int</code> value specifying the number of nodes
* in the reduction graph until now (not including this one).
*/
public int getDelegationDepth();
/**
* Get a whole category.
*
* @param category The name of the category.
*
* @return The <code>Set</code> of <RequestElement</code>s with
* the matching category.
*/
public Set<RequestElement> getCategory(URI category);
/**
* @return The <code>Set</code> of <code>RequestElement</code>s
* describing the attributes to be included in the result.
*/
public Set<RequestElement> getIncludedAttributes();
/**
* @return the <code>Map</code> of <code>RequestElements</code>
* defining this request.
*/
public Map<URI, Set<RequestElement>> getRequestElements();
/**
* Save the parent <code>PolicySet</code> in this evaluation context
* for doing reduction of delegated policies if that becomes necessary.
*
* @param pps the parent policy set
*/
public void saveParentPolicySet(AbstractPolicy pps);
/**
* Create a reduction graph for the current parent PolicySet.
*
*/
public void createReductionGraph();
/**
* @return The current reduction graph.
*/
public ReductionGraph getReductionGraph();
/**
* Remove the current <code>ReductionGraph</code> from the stack.
*/
public void popReductionGraph();
/**
* Get the parent <code>PolicySet</code> for this evaluation context.
*
* @return the parent policy set
*/
public AbstractPolicy getParentPolicySet();
/**
* Remove the current parent <code>PolicySet</code> from the stack
* of parent policy sets.
*/
public void popParentPolicySet();
/**
* Add new inactive PolicyId to the Map
* @param policyId the id of the new inactive policy
*/
public void addInactivePolicyId(URI policyId);
/**
* Return an unmodifiable <code>Set</code> of <code>URI</code>s of
* inactive policies
* @return the inactive policies
*/
public Set<URI> getInactivePolicyIds();
/**
* Checks whether a <code>Policy</code> or <code>PolicySet</code>
* supports a revocation of a specific Policy of PolicySet
* in this context.
*
* @param supporting The policy or policy set that could support
* a revocation.
* @param candidate The id of the policy or policy set that is candidate
* for revocation.
*
* @return true if the policy/policy set supports a revocation,
* false otherwise.
*/
public boolean supportsRevocation(AbstractPolicy supporting,
URI candidate);
/**
* Signal a new event to this EvaluationCtx.
*
* @param element The new event.
*/
public void newEvent(Object element);
/**
* Signal that an event has finished and pass the result
* which is a <code>Result</code>
*
* @param result The result of the finished event.
*/
public void closeCurrentEvent(Result result);
/**
* Signal that an event has finished and pass the result
* which is a <code>MatchResult</code>
*
* @param result The result of the finished event.
*/
public void closeCurrentEvent(MatchResult result);
/**
* Signal that an event has finished and pass the result
* which is a <code>EvaluationResult</code>
*
* @param result The result of the finished event.
*/
public void closeCurrentEvent(EvaluationResult result);
/**
* Signal that an event has finished with a <code>String</code> message.
*
* @param message The message.
*/
public void closeCurrentEvent(String message);
/**
* Signal that an event has finished with no result.
*/
public void closeCurrentEvent();
}

View File

@ -0,0 +1,139 @@
/*
* @(#)Indenter.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 com.sun.xacml;
import java.util.Arrays;
/**
* Provides flexible indenting for XML encoding. This class generates
* strings of spaces to be prepended to lines of XML. The strings are
* formed according to a specified indent width and the given depth.
*
* @since 1.0
* @author Marco Barreno
* @author Seth Proctor
*/
public class Indenter
{
/**
* The default indentation width
*/
public static final int DEFAULT_WIDTH = 2;
// The width of one indentation level
private int width;
// the current depth
private int depth;
/**
* Constructs an <code>Indenter</code> with the default indent
* width.
*/
public Indenter() {
this(DEFAULT_WIDTH);
}
/**
* Constructs an <code>Indenter</code> with a user-supplied indent
* width.
*
* @param userWidth the number of spaces to use for each indentation level
*/
public Indenter(int userWidth) {
this.width = userWidth;
this.depth = 0;
}
/**
* Move in one width.
*/
public void in() {
this.depth += this.width;
}
/**
* Move out one width.
*/
public void out() {
this.depth -= this.width;
}
/**
* Create a <code>String</code> of spaces for indentation based on the
* current depth.
*
* @return an indent string to prepend to lines of XML
*/
public String makeString() {
// Return quickly if no indenting
if (this.depth <= 0) {
return "";
}
// Make a char array and fill it with spaces
char[] array = new char[this.depth];
Arrays.fill(array, ' ');
// Now return a string built from that char array
return new String(array);
}
/**
* Indent an input that is multilined by adding the indent at
* the beginning of every line.
*
* @param input the unindented string
*
* @return the indented string
*/
public String multilineIndent(String input) {
input = input.replaceAll(Constants.nl, Constants.nl + makeString());
input = makeString() + input;
return input;
}
/**
* @return The indentation width.
*/
public int getWidth() {
return this.width;
}
}

View File

@ -0,0 +1,11 @@
package com.sun.xacml;
import com.sun.xacml.debug.Locatable;
/**
*
*
*/
public interface MatchElement extends Locatable {
public MatchResult match(EvaluationCtx context);
}

View File

@ -0,0 +1,130 @@
/*
* @(#)MatchResult.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 com.sun.xacml;
import com.sun.xacml.ctx.Status;
/**
* This is used as the return value for the various target matching functions.
* It communicates that either the target matches the input request, the
* target doesn't match the input request, or the result is Indeterminate.
*
* @since 1.0
* @author Seth Proctor
*/
public class MatchResult
{
/**
* An integer value indicating the the target matches the request
*/
public static final int MATCH = 0;
/**
* An integer value indicating that the target doesn't match the request
*/
public static final int NO_MATCH = 1;
/**
* An integer value indicating the the result is Indeterminate
*/
public static final int INDETERMINATE = 2;
/**
* The array representing the string values for these results.
*/
public static final String[] MATCH_RESULTS = { "Match", "No_Match",
"Indeterminate"};
//
private int result;
private Status status;
/**
* Constructor that creates a <code>MatchResult</code> with no Status
*
* @param result the applicable result
*/
public MatchResult(int result) {
this(result, null);
}
/**
* Constructor that creates a <code>MatchResult</code>, including Status
* data
*
* @param result the applicable result
* @param status the error information
*
* @throws IllegalArgumentException if the input result isn't a valid value
*/
public MatchResult(int result, Status status)
throws IllegalArgumentException
{
// check if input result is a valid value
if ((result != MATCH) &&
(result != NO_MATCH) &&
(result != INDETERMINATE)) {
throw new IllegalArgumentException("Input result is not a valid" +
"value");
}
this.result = result;
this.status = status;
}
/**
* Returns the applicable result
*
* @return the applicable result
*/
public int getResult() {
return this.result;
}
/**
* Returns the status if there was an error, or null if no error occurred
*
* @return the error status data or null
*/
public Status getStatus() {
return this.status;
}
}

View File

@ -0,0 +1,369 @@
/*
* @(#)Obligation.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 com.sun.xacml;
import com.sun.xacml.attr.AttributeFactory;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.debug.Locatable;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Represents the ObligationType XML type in XACML. This also stores all the
* AttriubteAssignmentType XML types.
*
* @since 1.0
* @author Seth Proctor
*/
public class Obligation implements Locatable
{
// the obligation id
private URI id;
// effect to fulfill on, as defined in Result
private int fulfillOn;
// the attribute assignments
private List<Attribute> assignments;
// if the obligation has dynamic attribute assignments, i.e., if attribute values are assigned at runtime, default is false
private boolean dynamic_attributes;
private RuntimeInfo src;
public static final Set<Obligation> EMPTY_SET = Collections.<Obligation>emptySet();
/**
* Constructor that takes all the data associated with an obligation.
* The attribute assignment list contains <code>Attribute</code> objects,
* but only the fields used by the AttributeAssignmentType are used.
*
* @param id the obligation's id
* @param fulfillOn the effect denoting when to fulfill this obligation
* @param assignments a <code>List</code> of <code>Attribute</code>s
*/
public Obligation(URI id, int fulfillOn, List<Attribute> assignments) {
init(id, fulfillOn, assignments, false);
}
public Obligation(URI id, int fulfillOn, List<Attribute> assignments, boolean dynamic) {
init(id, fulfillOn, assignments, dynamic);
}
private void init(URI id, int fulfillOn, List<Attribute> assignments, boolean dynamic) {
this.id = id;
this.fulfillOn = fulfillOn;
this.dynamic_attributes = dynamic;
this.assignments = Collections.
unmodifiableList(new ArrayList<Attribute>(assignments));
}
private Obligation(URI id, int fulfillOn, boolean dynamic) {
this.id = id;
this.fulfillOn = fulfillOn;
this.dynamic_attributes = dynamic;
}
/**
* Creates an instance of <code>Obligation</code> based on the DOM root
* node.
*
* @param root the DOM root of the ObligationType XML type
*
* @return an instance of an obligation
*
* @throws ParsingException if the structure isn't valid
*/
public static Obligation getInstance(Node root) throws ParsingException {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.OBLIGATION);
if (root.getNodeType() != Node.ELEMENT_NODE) {
throw new ParsingException("Can't create an Obligation out of"
+ " a node that is not an Element node"
+ (src != null ? src.getLocationMsgForError() : ""));
}
if (!root.getLocalName().equals("Obligation")) {
throw new ParsingException("Can't create an Obligation with a "
+ root.getLocalName() + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
URI id;
int fulfillOn = -1;
List<Attribute> assignments = new ArrayList<Attribute>();
AttributeFactory attrFactory = AttributeFactory.getInstance();
NamedNodeMap attrs = root.getAttributes();
try {
id = new URI(attrs.getNamedItem("ObligationId").getNodeValue());
} catch (Exception e) {
throw new ParsingException("Error parsing required attriubte "
+ "ObligationId" + (src != null ? src.getLocationMsgForError() : ""), e);
}
String effect = null;
try {
effect = attrs.getNamedItem("FulfillOn").getNodeValue();
} catch (Exception e) {
throw new ParsingException("Error parsing required attriubte "
+ "FulfillOn" + (src != null ? src.getLocationMsgForError() : ""), e);
}
if (effect.equals(Result.PERMIT)) {
fulfillOn = Result.DECISION_PERMIT;
} else if (effect.equals(Result.DENY)) {
fulfillOn = Result.DECISION_DENY;
} else {
throw new ParsingException("Invlid Effect type: " + effect
+ (src != null ? src.getLocationMsgForError() : ""));
}
boolean dynamic = false;
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getLocalName().equals("AttributeAssignment")) {
URI attrId = null;
try {
attrId =
new URI(node.getAttributes().
getNamedItem("AttributeId").getNodeValue());
AttributeValue attrValue = attrFactory.createValue(node);
dynamic |= attrValue.isDynamic();
assignments.add(new Attribute(attrId, null, attrValue));
} catch (URISyntaxException use) {
throw new ParsingException("Error parsing URI: " + use.getMessage()
+ (src != null ? src.getLocationMsgForError() : ""), use);
} catch (UnknownIdentifierException uie) {
throw new ParsingException("Unknown AttributeId: " + uie.getMessage()
+ (src != null ? src.getLocationMsgForError() : ""), uie);
} catch (Exception e) {
throw new ParsingException("Error parsing attribute " + attrId
+ "assignments"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
}
}
Obligation obligation = new Obligation(id, fulfillOn, assignments, dynamic);
if ( src != null ) {
obligation.src = src;
src.setXACMLObject(obligation);
}
return obligation;
}
/**
* Returns the id of this obligation
*
* @return the id
*/
public URI getId() {
return this.id;
}
/**
* Returns effect that will cause this obligation to be included in a
* response
*
* @return the fulfillOn effect
*/
public int getFulfillOn() {
return this.fulfillOn;
}
public RuntimeInfo getRuntimeInfo() {
return src;
}
/**
* Returns the attribute assignment data in this obligation. The
* <code>List</code> contains objects of type <code>Attribute</code>
* with only the correct attribute fields being used.
*
* @return the assignments
*/
public List<Attribute> getAssignments() {
return this.assignments;
}
/**
* Encodes this <code>Obligation</code> into its XML form and writes this
* out to the provided <code>OutputStream<code> with no indentation.
*
* @param output a stream into which the XML-encoded data is written
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>Obligation</code> into its XML form and writes this
* out to the provided <code>OutputStream<code> with indentation.
*
* @param output a stream into which the XML-encoded data is written
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
out.println(indent + "<Obligation ObligationId=\"" + this.id.toString()
+ "\" FulfillOn=\"" + Result.DECISIONS.get(this.fulfillOn)
+ "\">");
indenter.in();
Iterator<Attribute> it = this.assignments.iterator();
while (it.hasNext()) {
Attribute attr = it.next();
out.println(indenter.makeString()
+ "<AttributeAssignment AttributeId=\""
+ attr.getId().toString() + "\" DataType=\""
+ attr.getValue().getType().toString() + "\">"
+ attr.getValue().encode()
+ "</AttributeAssignment>");
}
indenter.out();
out.println(indent + "</Obligation>");
}
/**
* @param indenter
* @return the string representation of this obligation encoded in XML
*/
public String toString(Indenter indenter) {
String indent = indenter.makeString();
String result =indent + "<Obligation ObligationId=\""
+ this.id.toString() + "\" FulfillOn=\""
+ Result.DECISIONS.get(this.fulfillOn) + "\">" + Constants.nl;
indenter.in();
Iterator<Attribute> it = this.assignments.iterator();
while (it.hasNext()) {
Attribute attr = it.next();
result += indenter.makeString() +
"<AttributeAssignment AttributeId=\"" +
attr.getId().toString() + "\" DataType=\"" +
attr.getValue().getType().toString() + "\">" +
attr.getValue().encode() +
"</AttributeAssignment>" + Constants.nl;
}
indenter.out();
result += indent + "</Obligation>" + Constants.nl;
return result;
}
public Obligation evaluate(EvaluationCtx context) {
if ( ! dynamic_attributes ) {
return this;
} else {
Obligation obl = new Obligation(this.id, this.fulfillOn, this.dynamic_attributes);
List<Attribute> tmpAttr = new ArrayList<Attribute>();
for ( Attribute attr : this.assignments ) {
if ( attr.getValue().isDynamic()) {
EvaluationResult evaluationResult =attr.getValue().evaluate(context);
AttributeValue evaluated = evaluationResult.getAttributeValue();
tmpAttr.add(new Attribute(attr.getId(), attr.getIssuer(), evaluated));
} else {
tmpAttr.add(attr);
}
}
obl.assignments = Collections.unmodifiableList(tmpAttr);
// this.assignments = new ArrayList<Attribute>();
return obl;
}
}
public boolean isDynamic() {
return dynamic_attributes;
}
}

View File

@ -0,0 +1,480 @@
/*
* @(#)PDP.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 com.sun.xacml;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.ctx.RequestCtx;
import com.sun.xacml.ctx.RequestElement;
import com.sun.xacml.ctx.ResponseCtx;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.finder.AttributeFinder;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderResult;
import com.sun.xacml.finder.ResourceFinder;
import com.sun.xacml.finder.ResourceFinderResult;
import com.sun.xacml.finder.RevocationFinder;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.log4j.Logger;
/**
* This is the core class for the XACML engine, providing the starting point
* for request evaluation. To build an XACML policy engine, you start by
* instantiating this object.
*
* @since 1.0
* @author Seth Proctor
*/
public class PDP
{
// the single attribute finder that can be used to find external values
private AttributeFinder attributeFinder;
// the single policy finder that will be used to resolve policies
private PolicyFinder policyFinder;
// the single resource finder that will be used to resolve resources
private ResourceFinder resourceFinder;
// the single revocation finder that will be used to find and validate
// revocations
private RevocationFinder revocationFinder;
// the logger we'll use for all messages
private static final Logger logger = Logger.getLogger(PDP.class.getName());
private static String buildBy;
private static String buildTime;
static {
Properties manifest = new Properties();
try {
String classUrl = "/" + PDP.class.getCanonicalName().replaceAll("\\.", "/") + ".class";
manifest.load(new URL(PDP.class.getResource(classUrl).toString().replace(classUrl, "/META-INF/MANIFEST.MF")).openStream());
} catch (Exception e) {
// ignore.. well, doesn't work..
}
if ( manifest.containsKey("Built-By") ) {
buildBy = manifest.getProperty("Built-By");
} else {
buildBy = "unkown";
}
if ( manifest.containsKey("Built-Time") ) {
buildTime = manifest.getProperty("Built-Time");
} else {
buildTime = "unkown";
}
}
/**
* Constructs a new <code>PDP</code> object with the given configuration
* information.
*
* @param config user configuration data defining how to find policies,
* resolve external attributes, etc.
*/
public PDP(PDPConfig config) {
logger.info("creating a PDP (built by " + buildBy + " at " + buildTime + ")");
this.attributeFinder = config.getAttributeFinder();
this.policyFinder = config.getPolicyFinder();
this.policyFinder.init(config);
this.resourceFinder = config.getResourceFinder();
this.revocationFinder = config.getRevocationFinder();
}
/**
* Attempts to evaluate the request against the policies known to this
* PDP. This is really the core method of the entire XACML specification,
* and for most people will provide what you want. If you need any special
* handling, you should look at the version of this method that takes an
* <code>EvaluationCtx</code>.
* <p>
* Note that if the request is somehow invalid (it was missing a required
* attribute, it was using an unsupported scope, etc), then the result
* will be a decision of INDETERMINATE.
*
* @param request the request to evaluate
*
* @return a response paired to the request
*/
public ResponseCtx evaluate(RequestCtx request) {
// try to create the EvaluationCtx out of the request
try {
return evaluate(new BasicEvaluationCtx(request,
this.attributeFinder, this.revocationFinder));
} catch (ParsingException pe) {
logger.info("the PDP receieved an invalid request", pe);
// there was something wrong with the request, so we return
// Indeterminate with a status of syntax error...though this
// may change if a more appropriate status type exists
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_SYNTAX_ERROR);
Status status = new Status(code, pe.getMessage());
return new ResponseCtx(new Result(Result.DECISION_INDETERMINATE,
status));
}
}
/**
* Uses the given <code>EvaluationCtx</code> against the available
* policies to determine a response. If you are starting with a standard
* XACML Request, then you should use the version of this method that
* takes a <code>RequestCtx</code>. This method should be used only if
* you have a real need to directly construct an evaluation context (or
* if you need to use an <code>EvaluationCtx</code> implementation other
* than <code>BasicEvaluationCtx</code>).
*
* @param context representation of the request and the context used
* for evaluation
*
* @return a response based on the contents of the context
*/
public ResponseCtx evaluate(EvaluationCtx context) {
// see if we need to call the resource finder
if (context.getScope() != Constants.SCOPE_IMMEDIATE) {
AttributeValue parent
= context.getResourceId();
ResourceFinderResult resourceResult = null;
if (context.getScope() == Constants.SCOPE_CHILDREN) {
resourceResult =
this.resourceFinder.findChildResources(parent, context);
} else if (context.getScope() == Constants.SCOPE_DESCENDANTS) {
resourceResult =
this.resourceFinder.findDescendantResources(parent,
context);
} else if (context.getScope()
== Constants.SCOPE_XPATH_EXPRESSION) {
resourceResult =
this.resourceFinder.findXPathResources(parent, context);
} else if (context.getScope()
== Constants.SCOPE_ENTIRE_HIERARCHY) {
resourceResult =
this.resourceFinder.findHierarchyResources(parent,
context);
} else if (context.getScope()
== Constants.SCOPE_MULTIPE_ELEMENTS) {
return multipleElementsEval(context);
}
// see if we actually found anything
if (resourceResult == null || resourceResult.isEmpty()) {
// this is a problem, since we couldn't find any resources
// to work on...the spec is not explicit about what kind of
// error this is, so we're treating it as a processing error
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_PROCESSING_ERROR);
String msg = "Couldn't find any resources to work on.";
return new
ResponseCtx(new Result(Result.DECISION_INDETERMINATE,
new Status(code, msg),
context));
}
// setup a set to keep track of the results
HashSet<Result> results = new HashSet<Result>();
// at this point, we need to go through all the resources we
// successfully found and start collecting results
Iterator<AttributeValue> it = resourceResult.getResources().iterator();
while (it.hasNext()) {
// get the next resource, and set it in the EvaluationCtx
AttributeValue resource = it.next();
context.setResourceId(resource);
// do the evaluation, and set the resource in the result
Result result = evaluateContext(context);
result.setResource(resource.encode());
// add the result
results.add(result);
}
// now that we've done all the successes, we add all the failures
// from the finder result
Map<AttributeValue, Status> failureMap = resourceResult.getFailures();
Iterator<Map.Entry<AttributeValue, Status>> it2 = failureMap.entrySet().iterator();
while (it2.hasNext()) {
Map.Entry<AttributeValue, Status> entry = it2.next();
// get the next resource, and use it to get its Status data
Status status = entry.getValue();
// add a new result
results.add(new Result(Result.DECISION_INDETERMINATE,
status, context));
}
// return the set of results
return new ResponseCtx(results);
}
// the scope was IMMEDIATE (or missing), so we can just evaluate
// the request and return whatever we get back
return new ResponseCtx(evaluateContext(context));
}
/**
* Protected helper to handle multiple elements of same category in the
* request (generates several requests).
*
* @param context
* @return Collected responses for the multiple elements evaluation.
*/
protected ResponseCtx multipleElementsEval(EvaluationCtx context) {
// Collect the different Maps of request elements here
Map<URI, Set<RequestElement>> elements = context.getRequestElements();
Iterator<URI> iter = elements.keySet().iterator();
Set<Set<RequestElement>> setOfsets = new HashSet<Set<RequestElement>>();
while (iter.hasNext()) {
Set<RequestElement> reSet = context.getCategory(iter.next());
//Do the division
if (setOfsets.isEmpty()) {
//Create initial set of sets
Iterator<RequestElement> iter2 = reSet.iterator();
while (iter2.hasNext()) {
RequestElement re = iter2.next();
Set<RequestElement> newSet = new HashSet<RequestElement>();
newSet.add(re);
setOfsets.add(newSet);
}
} else {
Iterator<Set<RequestElement>> iter2 = setOfsets.iterator();
Set<Set<RequestElement>> newSetOfSets = new HashSet<Set<RequestElement>>();
while (iter2.hasNext()) {
Set<RequestElement> subset = iter2.next();
Iterator<RequestElement> iter3 = reSet.iterator();
while(iter3.hasNext()) {
RequestElement re = iter3.next();
Set<RequestElement> newSet = new HashSet<RequestElement>();
newSet.addAll(subset);
newSet.add(re);
newSetOfSets.add(newSet);
}
}
setOfsets = newSetOfSets;
}
}
if (setOfsets.size() < 2) {
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_PROCESSING_ERROR);
String msg = "Scope set to 'multipe elements' but could"
+ " only find one/zero";
return new ResponseCtx(
new Result(Result.DECISION_INDETERMINATE,
new Status(code, msg),
context));
}
// setup a set to keep track of the results
HashSet<Result> results = new HashSet<Result>();
// at this point, we need to go through all the sets we
// successfully found and start collecting creating requests
// and collect results
Iterator<Set<RequestElement>> it = setOfsets.iterator();
while (it.hasNext()) {
// get the next set of request elements, and create a
// new request for it.
Set<RequestElement> requestElements = it.next();
RequestCtx request = new RequestCtx(requestElements, null, null);
Result result = null;
try {
context = new BasicEvaluationCtx(request,
this.attributeFinder, this.revocationFinder);
} catch (ParsingException pe) {
logger.info("the PDP receieved an invalid request",
pe);
// there was something wrong with the request, so we collect
// Indeterminate with a status of syntax error...though this
// may change if a more appropriate status type exists
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_SYNTAX_ERROR);
Status status = new Status(code, pe.getMessage());
result = new Result(Result.DECISION_INDETERMINATE, status);
}
if (result == null) {// do the evaluation if nothing went wrong
result = evaluateContext(context);
}
// add the result
results.add(result);
}
// return the set of results
return new ResponseCtx(results);
}
/**
* A protected helper routine that resolves a policy for the given
* context, and then tries to evaluate based on the policy.
* Can be overrider by subclasses.
*/
protected Result evaluateContext(EvaluationCtx context) {
// first off, try to find a policy
PolicyFinderResult finderResult
= this.policyFinder.findPolicy(context);
// see if there weren't any applicable policies
if (finderResult.notApplicable()) {
return new Result(Result.DECISION_NOT_APPLICABLE,
context);
}
// see if there were any errors in trying to get a policy
if (finderResult.indeterminate()) {
return new Result(Result.DECISION_INDETERMINATE,
finderResult.getStatus(),
context);
}
// we found a valid policy
context.newEvent(finderResult.getPolicy());
Result result = finderResult.getPolicy().evaluate(context);
context.closeCurrentEvent(result);
if (result == null) {
return new Result(Result.DECISION_NOT_APPLICABLE,
context);
}
return result;
}
/**
* A utility method that wraps the functionality of the other evaluate
* method with input and output streams. This is useful if you've got
* a PDP that is taking inputs from some stream and is returning
* responses through the same stream system. If the Request is invalid,
* then this will always return a decision of INDETERMINATE.
*
* @deprecated As of 1.2 this method should not be used. Instead, you
* should do your own stream handling, and then use one of
* the other <code>evaluate</code> methods. The problem
* with this method is that it often doesn't handle stream
* termination correctly (eg, with sockets).
*
* @param input a stream that contains an XML RequestType
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform default character set
* will be used.
*
* @return a stream that contains an XML ResponseType
* @throws UnsupportedEncodingException
*/
public OutputStream evaluate(InputStream input, String charsetName)
throws UnsupportedEncodingException {
RequestCtx request = null;
ResponseCtx response = null;
try {
request = RequestCtx.getInstance(input);
} catch (Exception pe) {
// the request wasn't formed correctly
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_SYNTAX_ERROR);
Status status = new Status(code, "invalid request: " +
pe.getMessage());
response =
new ResponseCtx(new Result(Result.DECISION_INDETERMINATE,
status));
}
// if we didn't have a problem above, then we should go ahead
// with the evaluation
if (response == null) {
response = evaluate(request);
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.encode(out, charsetName, new Indenter());
return out;
}
/**
* @return The <code>AttributeFinder</code>
* (used by subclasses of the PDP).
*/
protected AttributeFinder getAttributeFinder() {
return this.attributeFinder;
}
/**
* @return The <code>RevocationFinder</code>
* (used by subclasses of the PDP).
*/
protected RevocationFinder getRevocationFinder() {
return this.revocationFinder;
}
/**
* @return The <code>PolicyFinder</code>
* (used by subclasses of the PDP).
*/
protected PolicyFinder getPolicyFinder() {
return this.policyFinder;
}
// public void setEmergencyLevel(EmergencyLevel level) {
// this.curEmgLevel = level;
// }
//
// public EmergencyLevel getEmergencyLevel() {
// return this.curEmgLevel;
// }
}

View File

@ -0,0 +1,185 @@
/*
* @(#)PDPConfig.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 com.sun.xacml;
import java.util.HashMap;
import java.util.Map;
import com.sun.xacml.finder.AttributeFinder;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.ResourceFinder;
import com.sun.xacml.finder.RevocationFinder;
/**
* This class is used as a container that holds configuration
* information for the PDP, which includes the <code>AttributeFinder</code>,
* <code>PolicyFinder</code>, <code>ResourceFinder</code>, and the
* <code>RevocationFinder</code> that the PDP should use.
*
* @since 1.0
* @author Seth Proctor
* @author Marco Barreno
* @author Ludwig Seitz
*/
public class PDPConfig
{
//
private AttributeFinder attributeFinder;
//
private PolicyFinder policyFinder;
//
private ResourceFinder resourceFinder;
//
private RevocationFinder revocationFinder;
private Map<String, Object> customAttr = new HashMap<String, Object>();
/**
* Constructor that creates a <code>PDPConfig</code> from components.
*
* @param attributeFinder the <code>AttributeFinder</code> that the PDP
* should use, or null if it shouldn't use any
* @param policyFinder the <code>PolicyFinder</code> that the PDP
* should use, or null if it shouldn't use any
* @param resourceFinder the <code>ResourceFinder</code> that the PDP
* should use, or null if it shouldn't use any
* @param revocationFinder The <code>RevocationFinder</code> that the PDP
* should use, or null if it shouldn't use any
*/
public PDPConfig(AttributeFinder attributeFinder,
PolicyFinder policyFinder,
ResourceFinder resourceFinder,
RevocationFinder revocationFinder) {
if (attributeFinder != null) {
this.attributeFinder = attributeFinder;
} else {
this.attributeFinder = new AttributeFinder();
}
if (policyFinder != null) {
this.policyFinder = policyFinder;
} else {
this.policyFinder = new PolicyFinder();
}
if (resourceFinder != null) {
this.resourceFinder = resourceFinder;
} else {
this.resourceFinder = new ResourceFinder();
}
if (revocationFinder != null) {
this.revocationFinder = revocationFinder;
} else {
this.revocationFinder = new RevocationFinder();
}
}
/**
* Returns the <code>AttributeFinder</code> that was configured, or
* null if none was configured
*
* @return the <code>AttributeFinder</code> or null
*/
public AttributeFinder getAttributeFinder() {
return this.attributeFinder;
}
/**
* Returns the <code>PolicyFinder</code> that was configured, or
* null if none was configured
*
* @return the <code>PolicyFinder</code> or null
*/
public PolicyFinder getPolicyFinder() {
return this.policyFinder;
}
/**
* Returns the <code>ResourceFinder</code> that was configured, or
* null if none was configured
*
* @return the <code>ResourceFinder</code> or null
*/
public ResourceFinder getResourceFinder() {
return this.resourceFinder;
}
/**
* Returns the <code>RevocationFinder</code> that was configured, or
* null if none was configured
*
* @return the <code>RevocationFinder</code> or null
*/
public RevocationFinder getRevocationFinder() {
return this.revocationFinder;
}
public void setCutomAttrs(Map<String, Object> attrs) {
if ( customAttr != null && customAttr.size() > 0 ) {
throw new RuntimeException("The custom attributes for PDPConfig may not be overwritten, if already values are stored!");
}
customAttr = attrs;
}
public void addCutomAttrs(Map<String, Object> attrs) {
if ( customAttr == null ) {
this.customAttr = attrs;
} else {
customAttr.putAll(attrs);
}
}
public void setCustomAttr(String key, Object value) {
customAttr.put(key, value);
}
public Object getCustomAttr(String key) {
return customAttr.get(key);
}
public Map<String, Object> getCustomAttrs() {
return customAttr;
}
}

View File

@ -0,0 +1,105 @@
/*
* @(#)ParsingException.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 com.sun.xacml;
/**
* Exception that gets thrown if any general parsing error occurs.
*
* @since 1.0
* @author Seth Proctor
*/
public class ParsingException extends Exception
{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Constructs a new <code>ParsingException</code> with no message
* or cause.
*/
public ParsingException() {
//parsing exception with no message or cause.
}
/**
* Constructs a new <code>ParsingException</code> with a message,
* but no cause. The message is saved for later retrieval by the
* {@link java.lang.Throwable#getMessage() Throwable.getMessage()}
* method.
*
* @param message the detail message (<code>null</code> if nonexistent
* or unknown)
*/
public ParsingException(String message) {
super(message);
}
/**
* Constructs a new <code>ParsingException</code> with a cause,
* but no message. The cause is saved for later retrieval by the
* {@link java.lang.Throwable#getCause() Throwable.getCause()}
* method.
*
* @param cause the cause (<code>null</code> if nonexistent
* or unknown)
*/
public ParsingException(Throwable cause) {
super(cause);
}
/**
* Constructs a new <code>ParsingException</code> with a message
* and a cause. The message and cause are saved for later retrieval
* by the
* {@link java.lang.Throwable#getMessage() Throwable.getMessage()} and
* {@link java.lang.Throwable#getCause() Throwable.getCause()}
* methods.
*
* @param message the detail message (<code>null</code> if nonexistent
* or unknown)
* @param cause the cause (<code>null</code> if nonexistent
* or unknown)
*/
public ParsingException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,819 @@
/*
* @(#)Policy.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 com.sun.xacml;
import com.sun.xacml.combine.CombinerElement;
import com.sun.xacml.combine.CombinerParameter;
import com.sun.xacml.combine.RuleCombinerElement;
import com.sun.xacml.combine.RuleCombiningAlgorithm;
import com.sun.xacml.cond.VariableDefinition;
import com.sun.xacml.cond.VariableManager;
import com.sun.xacml.ctx.PolicyIssuer;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Represents one of the two top-level constructs in XACML, the PolicyType.
* This contains rules, which in turn contain most of the logic of
* a policy.
*
* @since 1.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public class Policy extends AbstractPolicy {
/**
* The <code>Set</code> of <code>VariableDefinition</code>s in this policy
*/
private Set<VariableDefinition> definitions;
/**
* Creates a new <code>Policy</code> with only the required elements.
*
* @param id the policy identifier
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
*
* @param target the <code>Target</code> for this policy
*/
public Policy(URI id, RuleCombiningAlgorithm combiningAlg, Target target) {
this(id, null, null, combiningAlg, null, null, target, null,
null, null);
}
/**
* Creates a new <code>Policy</code> with only the required elements.
*
* @param id the policy identifier
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param issuer the <code>PolicyIssuer</code> for this policy or null
* if it is the trusted issuer
* @param target the <code>Target</code> for this policy
*/
public Policy(URI id, RuleCombiningAlgorithm combiningAlg,
PolicyIssuer issuer, Target target) {
this(id, null, null, combiningAlg, null, issuer, target, null,
null, null);
}
/**
* Creates a new <code>Policy</code> with only the required elements
* plus rules.
*
* @param id the policy identifier
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param target the <code>Target</code> for this policy
* @param rules a list of <code>Rule</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, RuleCombiningAlgorithm combiningAlg, Target target,
List<Rule> rules) {
this(id, null, null, combiningAlg, null, null, target, null,
rules, null);
}
/**
* Creates a new <code>Policy</code> with only the required elements
* plus rules.
*
* @param id the policy identifier
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param issuer the <code>PolicyIssuer</code> for this policy or null
* if it is the trusted issuer
* @param target the <code>Target</code> for this policy
* @param rules a list of <code>Rule</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, RuleCombiningAlgorithm combiningAlg,
PolicyIssuer issuer, Target target, List<Rule> rules) {
this(id, null, null, combiningAlg, null, issuer, target, null,
rules, null);
}
/**
* Creates a new <code>Policy</code> with the required elements plus
* rules and a String description.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy
* @param target the <code>Target</code> for this policy
* @param rules a list of <code>Rule</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, Target target, List<Rule> rules) {
this(id, version, xacmlVersion, combiningAlg, description, null,
target, null, rules, null);
}
/**
* Creates a new <code>Policy</code> with the required elements plus
* a version, rules, and a String description. Note that the version
* is an XACML 2.0 feature.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this must
* always be null for XACML 1.x policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy
* @param issuer the <code>PolicyIssuer</code> for this policy or null
* if it is the trusted issuer
* @param target the <code>Target</code> for this policy
* @param rules a list of <code>Rule</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer, Target target,
List<Rule> rules) {
this(id, version, xacmlVersion, combiningAlg, description, issuer,
target, null, rules, null);
}
/**
* Creates a new <code>Policy</code> with the required elements plus
* rules, a String description and policy defaults.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy
* @param target the <code>Target</code> for this policy
* @param defaultVersion the XPath version to use
* @param rules a list of <code>Rule</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, Target target, String defaultVersion,
List<Rule> rules) {
this(id, version, xacmlVersion, combiningAlg, description, null,
target, defaultVersion, rules, null);
}
/**
* Creates a new <code>Policy</code> with the required elements plus
* a version, rules, a String description and policy defaults. Note that
* the version is an XACML 2.0 feature.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this must
* always be null for XACML 1.x policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy
* @param issuer the <code>PolicyIssuer</code> for this policy or null
* if it is the trusted issuer
* @param target the <code>Target</code> for this policy
* @param defaultVersion the XPath version to use
* @param rules a list of <code>Rule</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer, Target target,
String defaultVersion, List<Rule> rules) {
this(id, version, xacmlVersion, combiningAlg, description, issuer,
target, defaultVersion, rules, null);
}
/**
* Creates a new <code>Policy</code> with the required elements plus
* a version, rules, a String description, policy defaults, and
* obligations. Note that the version is an XACML 2.0 feature.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this must
* always be null for XACML 1.x policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy
* @param target the <code>Target</code> for this policy
* @param defaultVersion the XPath version to use
* @param rules a list of <code>Rule</code> objects
* @param obligations a set of <code>Obligations</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, Target target, String defaultVersion,
List<Rule> rules, Set<Obligation> obligations) {
this(id, version, xacmlVersion, combiningAlg, description, null,
target, defaultVersion, rules, obligations, null);
}
/**
* Creates a new <code>Policy</code> with the required elements plus
* rules, a String description, policy defaults, and obligations.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy
* @param issuer the <code>PolicyIssuer</code> for this policy or null
* if it is the trusted issuer
* @param target the <code>Target</code> for this policy
* @param defaultVersion the XPath version to use
* @param rules a list of <code>Rule</code> objects
* @param obligations a set of <code>Obligations</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer, Target target,
String defaultVersion, List<Rule> rules, Set<Obligation> obligations) {
this(id, version, xacmlVersion, combiningAlg, description, issuer,
target, defaultVersion, rules, obligations, null);
}
/**
* Creates a new <code>Policy</code> with the required elements plus
* a version, rules, a String description, policy defaults, obligations,
* and variable definitions. Note that the version and definitions are
* XACML 2.0 features.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this must
* always be null for XACML 1.x policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy
* @param target the <code>Target</code> for this policy
* @param defaultVersion the XPath version to use
* @param rules a list of <code>Rule</code> objects
* @param obligations a set of <code>Obligations</code> objects
* @param definitions a set of <code>VariableDefinition</code> objects
* that must provide all definitions referenced by
* all <code>VariableReference</code>s in the policy
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, Target target, String defaultVersion,
List<Rule> rules, Set<Obligation> obligations, Set<VariableDefinition> definitions) {
this(id, version, xacmlVersion, combiningAlg, description, null, target,
defaultVersion, rules, obligations, definitions);
}
/**
* Creates a new <code>Policy</code> with the required elements plus
* rules, a String description, policy defaults, obligations, and
* variable definitions.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy
* @param issuer the <code>PolicyIssuer</code> for this policy or null
* if it is the trusted issuer
* @param target the <code>Target</code> for this policy
* @param defaultVersion the XPath version to use
* @param rules a list of <code>Rule</code> objects
* @param obligations a set of <code>Obligations</code> objects
* @param definitions a set of <code>VariableDefinition</code> objects
* that must provide all definitions referenced by
* all <code>VariableReference</code>s in the policy
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer, Target target,
String defaultVersion, List<Rule> rules, Set<Obligation> obligations,
Set<VariableDefinition> definitions) {
super(id, version, xacmlVersion, combiningAlg, description, issuer,
target, defaultVersion, obligations, null,
Constants.MAX_DELEGATION_DEPTH_UNDEFINED);
List<CombinerElement> list = null;
// check that the list contains only rules
if (rules != null) {
list = new ArrayList<CombinerElement>();
Iterator<Rule> it = rules.iterator();
while (it.hasNext()) {
// Object o = it.next();
// if (! (o instanceof Rule)) {
// throw new IllegalArgumentException("non-Rule in rules");
// }
list.add(new RuleCombinerElement(it.next()));
}
}
setChildren(list);
// save the definitions
if (definitions == null) {
this.definitions = VariableDefinition.EMPTY_SET;
} else {
this.definitions = Collections.
unmodifiableSet(new HashSet<VariableDefinition>(definitions));
}
}
/**
* Creates a new <code>Policy</code> with the required and optional
* elements. If you need to provide combining algorithm parameters, you
* need to use this constructor. Note that unlike the other constructors
* in this class, the rules list is actually a list of
* <code>CombinerElement</code>s used to match a rule with any
* combiner parameters it may have.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this must
* always be null for XACML 1.x policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy or
* null if there is no description
* @param target the <code>Target</code> for this policy
* @param defaultVersion the XPath version to use or null if there is
* no default version
* @param ruleElements a list of <code>RuleCombinerElement</code> objects
* or null if there are no rules
* @param obligations a set of <code>Obligations</code> objects or null
* if there are no obligations
* @param definitions a set of <code>VariableDefinition</code> objects
* that must provide all definitions referenced by
* all <code>VariableReference</code>s in the policy
* @param parameters the <code>List</code> of
* <code>CombinerParameter</code>s provided for general
* use by the combining algorithm
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>RuleCombinerElement</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, Target target, String defaultVersion,
List<CombinerElement> ruleElements, Set<Obligation> obligations, Set<VariableDefinition> definitions,
List<CombinerParameter> parameters) {
this(id, version, xacmlVersion, combiningAlg, description, null,
target, defaultVersion, ruleElements, obligations,
definitions, parameters,
Constants.MAX_DELEGATION_DEPTH_UNDEFINED);
}
/**
* Creates a new <code>Policy</code> with the required and optional
* elements. If you need to provide combining algorithm parameters, you
* need to use this constructor. Note that unlike the other constructors
* in this class, the rules list is actually a list of
* <code>CombinerElement</code>s used to match a rule with any
* combiner parameters it may have.
*
* @param id the policy identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy or
* null if there is no description
* @param issuer the PolicyIssuer or null if this is the trusted issuer
* @param target the <code>Target</code> for this policy
* @param defaultVersion the XPath version to use or null if there is
* no default version
* @param ruleElements a list of <code>RuleCombinerElement</code> objects
* or null if there are no rules
* @param obligations a set of <code>Obligations</code> objects or null
* if there are no obligations
* @param definitions a set of <code>VariableDefinition</code> objects
* that must provide all definitions referenced by
* all <code>VariableReference</code>s in the policy
* @param parameters the <code>List</code> of
* <code>CombinerParameter</code>s provided for general
* use by the combining algorithm
* @param maxDelegationDepth the maximum delegation depth authorised
* by this policy set.
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>RuleCombinerElement</code>
*/
public Policy(URI id, String version, String xacmlVersion,
RuleCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer, Target target,
String defaultVersion, List<CombinerElement> ruleElements, Set<Obligation> obligations,
Set<VariableDefinition> definitions, List<CombinerParameter> parameters, int maxDelegationDepth) {
super(id, version, xacmlVersion, combiningAlg, description, issuer,
target, defaultVersion, obligations, parameters,
maxDelegationDepth);
// check that the list contains only RuleCombinerElements
if (ruleElements != null) {
Iterator<CombinerElement> it = ruleElements.iterator();
while (it.hasNext()) {
CombinerElement o = it.next();
if (! (o instanceof RuleCombinerElement)) {
throw new IllegalArgumentException("non-Rule in rules");
}
}
}
setChildren(ruleElements);
// save the definitions
if (definitions == null) {
this.definitions = VariableDefinition.EMPTY_SET;
} else {
this.definitions = Collections.
unmodifiableSet(new HashSet<VariableDefinition>(definitions));
}
}
/**
* Creates a new Policy based on the given root node. This is
* private since every class is supposed to use a getInstance() method
* to construct from a Node, but since we want some common code in the
* parent class, we need this functionality in a constructor.
*/
private Policy(Node root) throws ParsingException {
super(root, "Policy", "RuleCombiningAlgId");
this.src = RuntimeInfo.getRuntimeInfo(this, root, ELEMENT_TYPE.POLICY);
List<Rule> rules = new ArrayList<Rule>();
Map<String, List<CombinerParameter>> parameters = new HashMap<String, List<CombinerParameter>>();
Map<Object, Node> variableIds = new HashMap<Object, Node>();
PolicyMetaData metaData = getMetaData();
// first off, go through and look for any definitions to get their
// identifiers up front, since before we parse any references we'll
// need to know what definitions we support
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE
&& child.getLocalName().equals("VariableDefinition")) {
String id = null;
if (child.getAttributes().getNamedItem("VariableId") != null) {
id = child.getAttributes().getNamedItem("VariableId")
.getNodeValue();
} else {
throw new ParsingException("Error while trying to parse "
+ "VariableId in a Policy");
}
// it's an error to have more than one definition with the
// same identifier
if (variableIds.containsKey(id)) {
throw new ParsingException("multiple definitions for " +
"variable " + id);
}
variableIds.put(id, child);
}
}
// now create a manager with the defined variable identifiers
VariableManager manager = new VariableManager(variableIds, metaData);
this.definitions = new HashSet<VariableDefinition>();
// next, collect the Policy-specific elements
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
String name = child.getLocalName();
if (name.equals("Rule")) {
rules.add(Rule.getInstance(child, metaData, manager));
} else if (name.equals("RuleCombinerParameters")) {
String ref = null;
if (child.getAttributes() != null) {
if (child.getAttributes().getNamedItem("RuleIdRef")
!= null) {
ref = child.getAttributes()
.getNamedItem("RuleIdRef")
.getNodeValue();
} else {
throw new ParsingException("Required xml-attribute"
+ " RuleIdRef not found");
}
} else {
throw new ParsingException("Required xml-attribute"
+ " RuleIdRef not found");
}
// if we found the parameter before than add it the end of
// the previous paramters, otherwise create a new entry
if (parameters.containsKey(ref)) {
List<CombinerParameter> list = parameters.get(ref);
parseParameters(list, child);
} else {
List<CombinerParameter> list = new ArrayList<CombinerParameter>();
parseParameters(list, child);
parameters.put(ref, list);
}
} else if (name.equals("VariableDefinition")) {
String id = null;
if (child.getAttributes() != null) {
if (child.getAttributes().getNamedItem("VariableId")
!= null) {
id = child.getAttributes()
.getNamedItem("VariableId")
.getNodeValue();
} else {
throw new ParsingException("Required xml-attribute"
+ " VariableId not found");
}
} else {
throw new ParsingException("Required xml-attribute"
+ " VariableId not found");
}
// parsing definitions is a little strange, since they can
// contain references to definitions we haven't yet parsed
// or circular references, but we still want to verify the
// references and the types...so, for each definition, we
// ask the manager though getDefinition, which takes care
// of loading any forward references, handles loops, etc.
// It also handles caching definitions, so we don't end
// up parsing the same definitions multiple times
this.definitions.add(manager.getDefinition(id));
}
}
}
this.definitions = Collections.unmodifiableSet(this.definitions);
// now make sure that we can match up any parameters we may have
// found to a cooresponding Rule...
List<CombinerElement> elements = new ArrayList<CombinerElement>();
Iterator<Rule> it = rules.iterator();
while (it.hasNext()) {
Rule rule = it.next();
String id = rule.getId().toString();
List<CombinerParameter> list = parameters.remove(id);
elements.add(new RuleCombinerElement(rule, list));
}
// ...and that there aren't extra parameters
if (! parameters.isEmpty()) {
throw new ParsingException("Unmatched parameters in Rule");
}
// finally, set the list of Rules
setChildren(elements);
}
/**
* The clone method
* FIXME: this does no deep copy on the Lists and Sets.
*
* @return a copy of this object.
*/
public Object clone() {
Policy clone = (Policy)super.clone();
clone.definitions = new HashSet<VariableDefinition>(this.definitions);
clone.setChildren(this.getChildElements());
return clone;
}
/**
* Helper method that parses out a collection of combiner parameters.
*/
private void parseParameters(List<CombinerParameter> parameters, Node root)
throws ParsingException
{
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getLocalName().equals("CombinerParameter")) {
parameters.add(CombinerParameter.getInstance(node));
}
}
}
/**
* Creates an instance of a <code>Policy</code> object based on a
* DOM node. The node must be the root of PolicyType XML object,
* otherwise an exception is thrown.
*
* @param root the DOM root of a PolicyType XML type
*
* @return A policy object.
*
* @throws ParsingException if the PolicyType is invalid
*/
public static Policy getInstance(Node root)
throws ParsingException {
// first off, check that it's the right kind of node
if (root.getNodeType() != Node.ELEMENT_NODE
|| ! root.getLocalName().equals("Policy")) {
throw new ParsingException("Cannot create Policy from root of " +
"type " + root.getLocalName());
}
return new Policy(root);
}
/**
* Returns the variable definitions in this Policy.
*
* @return a <code>Set</code> of <code>VariableDefinition</code>s
*/
public Set<VariableDefinition> getVariableDefinitions() {
return this.definitions;
}
/**
* Encodes this <code>Policy</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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>Policy</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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
out.println(indent + "<Policy xmlns=\""
+ getMetaData().getXACMLIdentifier()
+ "\" PolicyId=\"" + getId().toString()
+ "\" RuleCombiningAlgId=\""
+ getCombiningAlg().getIdentifier().toString()
+ "\"");
if (getMaxDelegationDepth()
!= Constants.MAX_DELEGATION_DEPTH_UNDEFINED) {
out.println("MaxDelegationDepth=\"" + getMaxDelegationDepth()
+ "\">");
} else {
out.println(">");
}
indenter.in();
String nextIndent = indenter.makeString();
String description = getDescription();
if (description != null) {
out.println(nextIndent + "<Description>" + description +
"</Description>");
}
encodePolicyIssuer(output, charsetName, indenter);
String version = getDefaultVersion();
if (version != null) {
out.println("<PolicyDefaults><XPathVersion>" + version +
"</XPathVersion></PolicyDefaults>");
}
getTarget().encode(output, charsetName, indenter);
Iterator<VariableDefinition> it = this.definitions.iterator();
while (it.hasNext()) {
((VariableDefinition)(it.next())).encode(output, charsetName,
indenter);
}
encodeCommonElements(output, charsetName, indenter);
indenter.out();
out.println(indent + "</Policy>");
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
}

View File

@ -0,0 +1,306 @@
/*
* @(#)PolicyMetaData.java
*
* Copyright 2005-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;
import com.sun.xacml.attr.AttributeFactory;
import com.sun.xacml.attr.AttributeFactoryProxy;
import com.sun.xacml.combine.CombiningAlgFactory;
import com.sun.xacml.combine.CombiningAlgFactoryProxy;
import com.sun.xacml.cond.FunctionFactory;
import com.sun.xacml.cond.FunctionFactoryProxy;
/**
* This is used to share polcy meta-data throughout the policy tree. Examples
* of common meta-data include the version of XACML or XPath being used in
* a policy.
*
* @since 2.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public class PolicyMetaData
{
// private mapping from XACML version number to identifier string
private static String [] xacmlIdentifiers = {
Constants.XACML_1_0_IDENTIFIER,
Constants.XACML_1_0_IDENTIFIER,
Constants.XACML_2_0_IDENTIFIER,
Constants.XACML_3_0_IDENTIFIER};
// private mapping from XPath version number to identifier string
private static String [] xpathIdentifiers = { null,
Constants.XPATH_1_0_IDENTIFIER };
// the version of XACML
private int xacmlVersion;
// the version of XPath, or null if none is specified
private int xpathVersion;
// the factories used with this policy
private AttributeFactoryProxy afProxy;
private CombiningAlgFactoryProxy cafProxy;
private FunctionFactoryProxy ffProxy;
/**
* Creates a <code>PolicyMetaData</code> instance with all the parameters
* set to their default values.
*/
public PolicyMetaData() {
this(Constants.XACML_DEFAULT_VERSION,
Constants.XPATH_VERSION_UNSPECIFIED);
}
/**
* Creates a <code>PolicyMetaData</code> instance with the given
* parameters. The default factories are assumed.
*
* @param xacmlVersion the version of XACML used in a policy
* @param xpathVersion the XPath version to use in any selectors
*/
public PolicyMetaData(int xacmlVersion, int xpathVersion) {
this(xacmlVersion, xpathVersion, null, null, null);
}
/**
* Creates a <code>PolicyMetaData</code> instance with the given
* parameters. The default factories are assumed.
*
* @param xacmlVersion the version of XACML used in a policy
* @param xpathVersion the XPath version to use in any selectors, or
* null if this is unspecified (ie, not supplied in
* the defaults section of the policy)
*
* @throws IllegalArgumentException if the identifier strings are unknown
*/
public PolicyMetaData(String xacmlVersion, String xpathVersion) {
this(xacmlVersion, xpathVersion, null, null, null);
}
/**
* Creates a <code>PolicyMetaData</code> instance with the given
* parameters. A proxy value of null implies the default factory.
*
* @param xacmlVersion the version of XACML used in a policy
* @param xpathVersion the XPath version to use in any selectors
* @param attributeFactoryProxy
* @param combiningAlgFactoryProxy
* @param functionFactoryProxy
*/
public PolicyMetaData(int xacmlVersion, int xpathVersion,
AttributeFactoryProxy attributeFactoryProxy,
CombiningAlgFactoryProxy combiningAlgFactoryProxy,
FunctionFactoryProxy functionFactoryProxy) {
this.xacmlVersion = xacmlVersion;
this.xpathVersion = xpathVersion;
proxySetup(attributeFactoryProxy, combiningAlgFactoryProxy,
functionFactoryProxy);
}
/**
* Creates a <code>PolicyMetaData</code> instance with the given
* parameters.
*
* @param xacmlVersion the version of XACML used in a policy
* @param xpathVersion the XPath version to use in any selectors, or
* null if this is unspecified (ie, not supplied in
* the defaults section of the policy)
* @param attributeFactoryProxy
* @param combiningAlgFactoryProxy
* @param functionFactoryProxy
*
* @throws IllegalArgumentException if the identifier strings are unknown
*/
public PolicyMetaData(String xacmlVersion, String xpathVersion,
AttributeFactoryProxy attributeFactoryProxy,
CombiningAlgFactoryProxy combiningAlgFactoryProxy,
FunctionFactoryProxy functionFactoryProxy) {
if (xacmlVersion == null) {
this.xacmlVersion = Constants.XACML_DEFAULT_VERSION;
} else if (xacmlVersion.equals(Constants.XACML_1_0_IDENTIFIER)) {
this.xacmlVersion = Constants.XACML_VERSION_1_0;
} else if (xacmlVersion.equals(Constants.XACML_2_0_IDENTIFIER)) {
this.xacmlVersion = Constants.XACML_VERSION_2_0;
} else if (xacmlVersion.equals(Constants.XACML_3_0_IDENTIFIER)) {
this.xacmlVersion = Constants.XACML_VERSION_3_0;
} else if (xacmlVersion.equals(Constants.XACML_1_0_CTX_ID)) {
this.xacmlVersion = Constants.XACML_VERSION_1_0;
} else if (xacmlVersion.equals(Constants.XACML_2_0_CTX_ID)) {
this.xacmlVersion = Constants.XACML_VERSION_2_0;
} else {
throw new IllegalArgumentException("Unknown XACML version " +
"string: " + xacmlVersion);
}
if (xpathVersion != null) {
if (! xpathVersion.equals(Constants.XPATH_1_0_IDENTIFIER)) {
throw new IllegalArgumentException("Unsupported XPath " +
" version: " +
xpathVersion);
}
this.xpathVersion = Constants.XPATH_VERSION_1_0;
} else {
this.xpathVersion = Constants.XPATH_VERSION_UNSPECIFIED;
}
proxySetup(attributeFactoryProxy, combiningAlgFactoryProxy,
functionFactoryProxy);
}
/**
*
*/
private void proxySetup(AttributeFactoryProxy attributeFactoryProxy,
CombiningAlgFactoryProxy combiningAlgFactoryProxy,
FunctionFactoryProxy functionFactoryProxy) {
if (attributeFactoryProxy == null) {
this.afProxy = new AttributeFactoryProxy() {
public AttributeFactory getFactory() {
return AttributeFactory.getInstance();
}
};
} else {
this.afProxy = attributeFactoryProxy;
}
if (combiningAlgFactoryProxy == null) {
this.cafProxy = new CombiningAlgFactoryProxy() {
public CombiningAlgFactory getFactory() {
return CombiningAlgFactory.getInstance();
}
};
} else {
this.cafProxy = combiningAlgFactoryProxy;
}
if (functionFactoryProxy == null) {
this.ffProxy = FunctionFactory.getInstance();
} else {
this.ffProxy = functionFactoryProxy;
}
}
/**
* Returns which version of XACML is specified in this meta-data.
*
* @return the XACML version
*/
public int getXACMLVersion() {
return this.xacmlVersion;
}
/**
* Returns the identifier string for the specified version of XACML.
*
* @return the identifier string
*/
public String getXACMLIdentifier() {
return xacmlIdentifiers[this.xacmlVersion];
}
/**
* Returns which version of XPath is specified in this meta-data.
*
* @return the XPath version or null
*/
public int getXPathVersion() {
return this.xpathVersion;
}
/**
* Returns the identifier string for the specified version of XPath, or
* null if no version is specified.
*
* @return the identifier string or null
*/
public String getXPathIdentifier() {
return xpathIdentifiers[this.xpathVersion];
}
/**
* Returns the <code>AttributeFactory</code> used by the associated
* policy.
*
* @return a <code>AttributeFactory</code>
*/
public AttributeFactory getAttributeFactory() {
return this.afProxy.getFactory();
}
/**
* Returns the <code>CombiningAlgFactory</code> used by the associated
* policy.
*
* @return a <code>CombiningAlgFactory</code>
*/
public CombiningAlgFactory getCombiningAlgFactory() {
return this.cafProxy.getFactory();
}
/**
* Returns the Target <code>FunctionFactory</code> used by the associated
* policy.
*
* @return a <code>FunctionFactory</code>
*/
public FunctionFactory getTargetFunctionFactory() {
return this.ffProxy.getTargetFactory();
}
/**
* Returns the Condition <code>FunctionFactory</code> used by the
* associated policy.
*
* @return a <code>FunctionFactory</code>
*/
public FunctionFactory getConditionFunctionFactory() {
return this.ffProxy.getConditionFactory();
}
/**
* Returns the General <code>FunctionFactory</code> used by the associated
* policy.
*
* @return a <code>FunctionFactory</code>
*/
public FunctionFactory getGeneralFunctionFactory() {
return this.ffProxy.getGeneralFactory();
}
}

View File

@ -0,0 +1,647 @@
/*
* @(#)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 com.sun.xacml;
import com.sun.xacml.combine.CombinerElement;
import com.sun.xacml.combine.CombiningAlgorithm;
import com.sun.xacml.ctx.PolicyIssuer;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderResult;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import org.apache.log4j.Logger;
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
* @author Ludwig Seitz
*/
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 referenced policy
private AbstractPolicy referencedPolicy;
// 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;
}
/**
* The clone method.
* FIXME: this does no deep copy on the
* contraints, finder and parentMetaData.
* Should probably _not_ do a deep copy on finder.
*
* @return a copy of this object.
*/
public Object clone() {
PolicyReference clone = (PolicyReference)super.clone();
clone.reference = this.reference;
clone.policyType = this.policyType;
clone.constraints = this.constraints;
clone.finder = this.finder;
clone.parentMetaData = this.parentMetaData;
return clone;
}
/**
* 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
*
* @return The PolicyReference object.
*
* @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
*
* @return The PolicyReference object.
*
* @exception ParsingException if the node is invalid
*/
public static PolicyReference getInstance(Node root, PolicyFinder finder,
PolicyMetaData metaData)
throws ParsingException
{
URI reference = null;
int policyType;
if (root.getNodeType() != Node.ELEMENT_NODE) {
throw new ParsingException("Cannot build a PolicyReference"
+ "with a: " + root.getClass().getName() +" XML node" );
}
// see what type of reference we are
String name = root.getLocalName();
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("Error while parsing Reference", e);
}
// now get any constraints
NamedNodeMap map = root.getAttributes();
String versionConstraint = null;
String earlyConstraint = null;
String lateConstraint = null;
Node versionNode = map.getNamedItem("Version");
if (versionNode != null) {
versionConstraint = versionNode.getNodeValue();
}
Node earlyNode = map.getNamedItem("EarliestVersion");
if (earlyNode != null) {
earlyConstraint = earlyNode.getNodeValue();
}
Node lateNode = map.getNamedItem("LatestVersion");
if (lateNode != null) {
lateConstraint = lateNode.getNodeValue();
}
VersionConstraints constraints =
new VersionConstraints(versionConstraint, earlyConstraint,
lateConstraint);
// finally, create the reference
PolicyReference policyReference = new PolicyReference(
reference, policyType, constraints, finder, metaData);
policyReference.src = RuntimeInfo.getRuntimeInfo(policyReference, root, ELEMENT_TYPE.POLICY_REFERENCE);
//policyReference.setSourceLocator(RuntimeInfo.getRuntimeInfo(policyReference, root, ELEMENT_TYPE.POLICY_REFERENCE));
return policyReference;
}
/**
* Returns the refernce identitfier used to resolve the policy.
*
* @return the reference <code>URI</code>
*/
public URI getReference() {
return this.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 this.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 this.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(null).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(null).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(null).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(null).getDescription();
}
/**
* Returns the PolicyIssuer if present or null if it is the trusted issuer.
*
* @return the PolicyIssuer or null
*
* @throws ProcessingException if the referenced policy can't be retrieved
*/
public PolicyIssuer getPolicyIssuer() {
return resolvePolicy(null).getPolicyIssuer();
}
/**
* 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(null).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(null).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<PolicyTreeElement> getChildren() {
return resolvePolicy(null).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<CombinerElement> getChildElements() {
return resolvePolicy(null).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<Obligation> getObligations() {
return resolvePolicy(null).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(null).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 resolvePolicy(context).match(context);
} catch (ProcessingException pe) {
// this means that we couldn't resolve the policy
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_PROCESSING_ERROR);
Status status = new Status(code, "couldn't resolve policy ref");
MatchResult match = new MatchResult(MatchResult.INDETERMINATE,
status);
return match;
}
}
/**
* Private helper method that tried to resolve the policy
*/
private AbstractPolicy resolvePolicy(EvaluationCtx context) {
if ( referencedPolicy != null ) {
return referencedPolicy;
}
// see if this reference was setup with a finder
if (this.finder == null) {
logger.warn("PolicyReference with id "
+ this.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 = this.finder.findPolicy(context,
this.reference,
this.policyType,
this.constraints,
this.parentMetaData);
if (pfr.notApplicable()) {
throw new ProcessingException("couldn't resolve the policy");
}
if (pfr.indeterminate()) {
throw new ProcessingException("error resolving the policy");
}
referencedPolicy = pfr.getPolicy();
return referencedPolicy;
}
/**
* 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) {
try {
resolvePolicy(context);
} catch (ProcessingException pe) {
logger.fatal("Evaluation was called for PolicyReference with not resolved Policy: This should not happen as no target can have been matched!");
List<String> codes = new Vector<String>();
codes.add(Status.STATUS_PROCESSING_ERROR);
Status errorStatus = new Status(codes);
return new Result(Result.DECISION_INDETERMINATE, errorStatus, context);
}
return referencedPolicy.evaluate(context);
//
// // if there is no finder, then we return NotApplicable
// if (this.finder == null) {
// return new Result(Result.DECISION_NOT_APPLICABLE,
// context);
// }
// PolicyFinderResult pfr = this.finder.findPolicy(this.reference,
// this.policyType,
// this.constraints,
// this.parentMetaData);
//
// // if we found nothing, then we return NotApplicable
// if (pfr.notApplicable()) {
// return new Result(Result.DECISION_NOT_APPLICABLE, context);
// }
// // if there was an error, we return that status data
// if (pfr.indeterminate()) {
// return new Result(Result.DECISION_INDETERMINATE,
// pfr.getStatus(),
// context);
// }
// // 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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, 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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String encoded = indenter.makeString();
if (this.policyType == POLICY_REFERENCE) {
out.println(encoded + "<PolicyIdReference xmlns=\""
+ getMetaData().getXACMLIdentifier() + "\""
+ encodeConstraints()
+ ">" + this.reference.toString()
+ "</PolicyIdReference>");
} else {
out.println(encoded + "<PolicySetIdReference"
+ encodeConstraints() + ">"
+ this.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;
}
}

View File

@ -0,0 +1,696 @@
/*
* @(#)PolicySet.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 com.sun.xacml;
import com.sun.xacml.combine.CombinerElement;
import com.sun.xacml.combine.CombinerParameter;
import com.sun.xacml.combine.PolicyCombinerElement;
import com.sun.xacml.combine.PolicyCombiningAlgorithm;
import com.sun.xacml.ctx.PolicyIssuer;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import com.sun.xacml.finder.PolicyFinder;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Represents one of the two top-level constructs in XACML, the PolicySetType.
* This can contain other policies and policy sets, and can also contain
* URIs that point to policies and policy sets.
*
* @since 1.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public class PolicySet extends AbstractPolicy {
//private static final Logger logger = Logger.getLogger(PolicySet.class);
/**
* Creates a new <code>PolicySet</code> with only the required elements.
*
* @param id the policy set identifier
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param target the <code>Target</code> for this set
*/
public PolicySet(URI id, PolicyCombiningAlgorithm combiningAlg,
Target target) {
this(id, null, null, combiningAlg, null, null, target, null, null,
null);
}
/**
* Creates a new <code>PolicySet</code> with only the required elements.
*
* @param id the policy set identifier
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param issuer the <code>PolicyIssuer</code> for this set or null if
* it is the trusted issuer
* @param target the <code>Target</code> for this set
*/
public PolicySet(URI id, PolicyCombiningAlgorithm combiningAlg,
PolicyIssuer issuer, Target target) {
this(id, null, null, combiningAlg, null, issuer, target, null, null,
null);
}
/**
* Creates a new <code>PolicySet</code> with only the required elements,
* plus some policies.
*
* @param id the policy set identifier
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param target the <code>Target</code> for this set
* @param policies a list of <code>AbstractPolicy</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of policies
* contains an object that is not an
* <code>AbstractPolicy</code>
*/
public PolicySet(URI id, PolicyCombiningAlgorithm combiningAlg,
Target target, List<PolicyTreeElement> policies) {
this(id, null, null, combiningAlg, null, null, target, policies,
null, null);
}
/**
* Creates a new <code>PolicySet</code> with only the required elements,
* plus some policies.
*
* @param id the policy set identifier
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param issuer the <code>PolicyIssuer</code> for this set or null if
* it is the trusted issuer
* @param target the <code>Target</code> for this set
* @param policies a list of <code>AbstractPolicy</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of policies
* contains an object that is not an
* <code>AbstractPolicy</code>
*/
public PolicySet(URI id, PolicyCombiningAlgorithm combiningAlg,
PolicyIssuer issuer, Target target, List<PolicyTreeElement> policies) {
this(id, null, null, combiningAlg, null, issuer, target, policies,
null, null);
}
/**
* Creates a new <code>PolicySet</code> with the required elements plus
* some policies and a String description.
*
* @param id the policy set identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param description a <code>String</code> describing the policy
* @param target the <code>Target</code> for this set
* @param policies a list of <code>AbstractPolicy</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of policies
* contains an object that is not an
* <code>AbstractPolicy</code>
*/
public PolicySet(URI id, String version, String xacmlVersion,
PolicyCombiningAlgorithm combiningAlg,
String description, Target target, List<PolicyTreeElement> policies) {
this(id, version, xacmlVersion, combiningAlg, description, null,
target, policies, null, null);
}
/**
* Creates a new <code>PolicySet</code> with the required elements plus
* some policies and a String description.
*
* @param id the policy set identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param description a <code>String</code> describing the policy
* @param issuer the <code>PolicyIssuer</code> for this set or null if
* it is the trusted issuer
* @param target the <code>Target</code> for this set
* @param policies a list of <code>AbstractPolicy</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of policies
* contains an object that is not an
* <code>AbstractPolicy</code>
*/
public PolicySet(URI id, String version, String xacmlVersion,
PolicyCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer, Target target,
List<PolicyTreeElement> policies) {
this(id, version, xacmlVersion, combiningAlg, description, issuer,
target, policies, null, null);
}
/**
* Creates a new <code>PolicySet</code> with the required elements plus
* some policies, a String description, and policy defaults.
*
* @param id the policy set identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param description a <code>String</code> describing the policy
* @param target the <code>Target</code> for this set
* @param policies a list of <code>AbstractPolicy</code> objects
* @param defaultVersion the XPath version to use
*
* @throws IllegalArgumentException if the <code>List</code> of policies
* contains an object that is not an
* <code>AbstractPolicy</code>
*/
public PolicySet(URI id, String version, String xacmlVersion,
PolicyCombiningAlgorithm combiningAlg,
String description, Target target, List<PolicyTreeElement> policies,
String defaultVersion) {
this(id, version, xacmlVersion, combiningAlg, description, null,
target, policies, defaultVersion, null);
}
/**
* Creates a new <code>PolicySet</code> with the required elements plus
* some policies, a String description, and policy defaults.
*
* @param id the policy set identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param description a <code>String</code> describing the policy
* @param issuer the <code>PolicyIssuer</code> for this set or null if
* it is the trusted issuer
* @param target the <code>Target</code> for this set
* @param policies a list of <code>AbstractPolicy</code> objects
* @param defaultVersion the XPath version to use
*
* @throws IllegalArgumentException if the <code>List</code> of policies
* contains an object that is not an
* <code>AbstractPolicy</code>
*/
public PolicySet(URI id, String version, String xacmlVersion,
PolicyCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer,
Target target, List<PolicyTreeElement> policies, String defaultVersion) {
this(id, version, xacmlVersion, combiningAlg, description, issuer,
target, policies, defaultVersion, null);
}
/**
* Creates a new <code>PolicySet</code> with the required elements plus
* some policies, a String description, policy defaults, and obligations.
*
* @param id the policy set identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param description a <code>String</code> describing the policy
* @param target the <code>Target</code> for this set
* @param policies a list of <code>AbstractPolicy</code> objects
* @param defaultVersion the XPath version to use
* @param obligations a set of <code>Obligation</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of policies
* contains an object that is not an
* <code>AbstractPolicy</code>
*/
public PolicySet(URI id, String version, String xacmlVersion,
PolicyCombiningAlgorithm combiningAlg,
String description, Target target, List<CombinerElement> policies,
String defaultVersion, Set<Obligation> obligations) {
this(id, version, xacmlVersion, combiningAlg, description, null,
target, policies, defaultVersion, obligations, null, -1);
}
/**
* Creates a new <code>PolicySet</code> with the required elements plus
* some policies, a String description, policy defaults, and obligations.
*
* @param id the policy set identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* policies in this set
* @param description a <code>String</code> describing the policy
* @param issuer the <code>PolicyIssuer</code> for this set or null if
* it is the trusted issuer
* @param target the <code>Target</code> for this set
* @param policies a list of <code>AbstractPolicy</code> objects
* @param defaultVersion the XPath version to use
* @param obligations a set of <code>Obligation</code> objects
*
* @throws IllegalArgumentException if the <code>List</code> of policies
* contains an object that is not an
* <code>AbstractPolicy</code>
*/
public PolicySet(URI id, String version, String xacmlVersion,
PolicyCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer,
Target target, List<PolicyTreeElement> policies, String defaultVersion,
Set<Obligation> obligations) {
super(id, version, xacmlVersion, combiningAlg, description, issuer,
target, defaultVersion, obligations, null,
Constants.MAX_DELEGATION_DEPTH_UNDEFINED);
List<CombinerElement> list = null;
// check that the list contains only AbstractPolicy objects
if (policies != null) {
list = new ArrayList<CombinerElement>();
Iterator<PolicyTreeElement> it = policies.iterator();
while (it.hasNext()) {
Object o = it.next();
if (! (o instanceof AbstractPolicy)) {
throw new IllegalArgumentException("non-AbstractPolicy " +
"in policies");
}
list.add(new PolicyCombinerElement((AbstractPolicy)o));
}
}
setChildren(list);
}
/**
* Creates a new <code>PolicySet</code> with the required and optional
* elements. If you need to provide combining algorithm parameters, you
* need to use this constructor. Note that unlike the other constructors
* in this class, the policies list is actually a list of
* <code>CombinerElement</code>s used to match a policy with any
* combiner parameters it may have.
*
* @param id the policy set identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy or
* null if there is no description
* @param target the <code>Target</code> for this policy
* @param policyElements a list of <code>CombinerElement</code> objects or
* null if there are no policies
* @param defaultVersion the XPath version to use or null if there is
* no default version
* @param obligations a set of <code>Obligations</code> objects or null
* if there are no obligations
* @param parameters the <code>List</code> of
* <code>CombinerParameter</code>s provided for general
* use by the combining algorithm
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public PolicySet(URI id, String version, String xacmlVersion,
PolicyCombiningAlgorithm combiningAlg,
String description, Target target,
List<CombinerElement> policyElements, String defaultVersion,
Set<Obligation> obligations, List<CombinerParameter> parameters) {
this(id, version, xacmlVersion, combiningAlg, description, null, target,
policyElements, defaultVersion, obligations, parameters,
Constants.MAX_DELEGATION_DEPTH_UNDEFINED);
}
/**
* Creates a new <code>PolicySet</code> with the required and optional
* elements. If you need to provide combining algorithm parameters, you
* need to use this constructor. Note that unlike the other constructors
* in this class, the policies list is actually a list of
* <code>CombinerElement</code>s used to match a policy with any
* combiner parameters it may have.
*
* @param id the policy set identifier
* @param version the policy version or null for the default (this is
* always null for pre-2.0 policies)
* @param xacmlVersion the xacml version identifier.
* @param combiningAlg the <code>CombiningAlgorithm</code> used on the
* rules in this set
* @param description a <code>String</code> describing the policy or
* null if there is no description
* @param issuer the <code>PolicyIssuer</code> for this set or null if
* it is the trusted issuer
* @param target the <code>Target</code> for this policy
* @param policyElements a list of <code>CombinerElement</code> objects or
* null if there are no policies
* @param defaultVersion the XPath version to use or null if there is
* no default version
* @param obligations a set of <code>Obligations</code> objects or null
* if there are no obligations
* @param parameters the <code>List</code> of
* <code>CombinerParameter</code>s provided for general
* use by the combining algorithm
* @param maxDelegationDepth the maximum delegation depth authorised
* by this policy set.
*
* @throws IllegalArgumentException if the <code>List</code> of rules
* contains an object that is not a
* <code>Rule</code>
*/
public PolicySet(URI id, String version, String xacmlVersion,
PolicyCombiningAlgorithm combiningAlg,
String description, PolicyIssuer issuer,
Target target, List<CombinerElement> policyElements,
String defaultVersion, Set<Obligation> obligations,
List<CombinerParameter> parameters, int maxDelegationDepth) {
super(id, version, xacmlVersion, combiningAlg, description, issuer,
target, defaultVersion, obligations, parameters,
maxDelegationDepth);
// check that the list contains only CombinerElements
if (policyElements != null) {
Iterator<CombinerElement> it = policyElements.iterator();
while (it.hasNext()) {
CombinerElement o = it.next();
if (! (o instanceof PolicyCombinerElement)) {
throw new IllegalArgumentException("non-AbstractPolicy " +
"in policies");
}
}
}
setChildren(policyElements);
}
/**
* Creates a new PolicySet based on the given root node. This is
* private since every class is supposed to use a getInstance() method
* to construct from a Node, but since we want some common code in the
* parent class, we need this functionality in a constructor.
*/
private PolicySet(Node root, PolicyFinder finder)
throws ParsingException {
super(root, "PolicySet", "PolicyCombiningAlgId");
List<AbstractPolicy> policies = new ArrayList<AbstractPolicy>();
Map<String, List<CombinerParameter>> policyParameters = new HashMap<String, List<CombinerParameter>>();
Map<String, List<CombinerParameter>> policySetParameters = new HashMap<String, List<CombinerParameter>>();
PolicyMetaData metaData = getMetaData();
super.src = RuntimeInfo.getRuntimeInfo(this, root, ELEMENT_TYPE.POLICY_SET);
// collect the PolicySet-specific elements
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
String name = child.getLocalName();
if (name.equals("PolicySet")) {
policies.add(PolicySet.getInstance(child, finder));
} else if (name.equals("Policy")) {
policies.add(Policy.getInstance(child));
} else if (name.equals("PolicySetIdReference")) {
policies.add(PolicyReference.getInstance(child, finder,
metaData));
} else if (name.equals("PolicyIdReference")) {
policies.add(PolicyReference.getInstance(child, finder,
metaData));
} else if (name.equals("PolicyCombinerParameters")) {
paramaterHelper(policyParameters, child, "Policy");
} else if (name.equals("PolicySetCombinerParameters")) {
paramaterHelper(policySetParameters, child, "PolicySet");
}
}
}
// now make sure that we can match up any parameters we may have
// found to a cooresponding Policy or PolicySet...
List<CombinerElement> elements = new ArrayList<CombinerElement>();
// right now we have to go though each policy and based on several
// possible cases figure out what paranmeters might apply...but
// there should be a better way to do this
for ( AbstractPolicy policy : policies ) {
List<CombinerParameter> list = null;
if (policy instanceof Policy) {
list = policyParameters.remove(policy.getId().toString());
} else if (policy instanceof PolicySet) {
list = policySetParameters.remove(policy.getId().toString());
} else {
PolicyReference ref = (PolicyReference)policy;
String id = ref.getReference().toString();
if (ref.getReferenceType() ==
PolicyReference.POLICY_REFERENCE) {
list = policyParameters.remove(id);
} else {
list = policySetParameters.remove(id);
}
}
elements.add(new PolicyCombinerElement(policy, list));
}
// ...and that there aren't extra parameters
if (! policyParameters.isEmpty()) {
throw new ParsingException("Unmatched parameters in Policy");
}
if (! policySetParameters.isEmpty()) {
throw new ParsingException("Unmatched parameters in PolicySet");
}
// finally, set the list of Rules
setChildren(elements);
}
/**
* The clone method.
* FIXME: caution this is no deep copy in the superclass.
*
* @return a copy of this object.
*/
public Object clone() {
PolicySet clone = (PolicySet)super.clone();
clone.setChildren(this.getChildElements());
return clone;
}
/**
* Private helper method that handles parsing a collection of
* parameters
*/
private void paramaterHelper(Map<String, List<CombinerParameter>> parameters, Node root,
String prefix) throws ParsingException {
String ref = null;
if (root.getAttributes().getNamedItem(prefix + "IdRef") != null) {
ref = root.getAttributes().getNamedItem(prefix + "IdRef")
.getNodeValue();
} else {
throw new ParsingException("Required xml-attribute: "
+ prefix + "IdRef not found");
}
if (parameters.containsKey(ref)) {
List<CombinerParameter> list = parameters.get(ref);
parseParameters(list, root);
} else {
List<CombinerParameter> list = new ArrayList<CombinerParameter>();
parseParameters(list, root);
parameters.put(ref, list);
}
}
/**
* Private helper method that handles parsing a single parameter.
*/
private void parseParameters(List<CombinerParameter> parameters, Node root)
throws ParsingException
{
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getLocalName().equals("CombinerParameter")) {
parameters.add(CombinerParameter.getInstance(node));
}
}
}
/**
* Creates an instance of a <code>PolicySet</code> object based on a
* DOM node. The node must be the root of PolicySetType XML object,
* otherwise an exception is thrown. This <code>PolicySet</code> will
* not support references because it has no <code>PolicyFinder</code>.
*
* @param root the DOM root of a PolicySetType XML type
*
* @return The PolicySet object.
*
* @throws ParsingException if the PolicySetType is invalid
*/
public static PolicySet getInstance(Node root)
throws ParsingException {
return getInstance(root, null);
}
/**
* Creates an instance of a <code>PolicySet</code> object based on a
* DOM node. The node must be the root of PolicySetType XML object,
* otherwise an exception is thrown. The finder is used to handle
* policy references.
*
* @param root the DOM root of a PolicySetType XML type
* @param finder the <code>PolicyFinder</code> used to handle references
*
* @return The PolicySet object.
*
* @throws ParsingException if the PolicySetType is invalid
*/
public static PolicySet getInstance(Node root, PolicyFinder finder)
throws ParsingException {
// first off, check that it's the right kind of node
if (root.getNodeType() != Node.ELEMENT_NODE
&& ! root.getLocalName().equals("PolicySet")) {
throw new ParsingException("Cannot create PolicySet from root of"
+ " type " + root.getLocalName());
}
return new PolicySet(root, finder);
}
/**
* Encodes this <code>PolicySet</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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>PolicySet</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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
out.print(indent + "<PolicySet xmlns=\""
+ getMetaData().getXACMLIdentifier()
+ "\" PolicySetId=\"" + getId().toString()
+ "\" PolicyCombiningAlgId=\""
+ getCombiningAlg().getIdentifier().toString()
+ "\"");
if (getMaxDelegationDepth()
!= Constants.MAX_DELEGATION_DEPTH_UNDEFINED) {
out.println("MaxDelegationDepth=\"" + getMaxDelegationDepth()
+ "\">");
} else {
out.println(">");
}
indenter.in();
String nextIndent = indenter.makeString();
String description = getDescription();
if (description != null) {
out.println(nextIndent + "<Description>" + description +
"</Description>");
}
encodePolicyIssuer(output, charsetName, indenter);
String version = getDefaultVersion();
if (version != null) {
out.println("<PolicySetDefaults><XPathVersion>" + version +
"</XPathVersion></PolicySetDefaults>");
}
getTarget().encode(output, charsetName, indenter);
encodeCommonElements(output, charsetName, indenter);
indenter.out();
out.println(indent + "</PolicySet>");
}
}

View File

@ -0,0 +1,149 @@
/*
* @(#)PolicyTreeElement.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 com.sun.xacml;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.debug.Locatable;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.Collections;
import java.util.List;
/**
* This represents a single node in a policy tree. A node is either a policy
* set, a policy, or a rule. This interface is used to interact with these
* node types in a general way. Note that rules are leaf nodes in a policy
* tree as they never contain children.
*
* @since 1.1
* @author seth proctor
*/
public interface PolicyTreeElement extends Locatable
{
public static List<PolicyTreeElement> EMPTY_LIST = Collections.<PolicyTreeElement>emptyList();
/**
* Returns the <code>List</code> of <code>PolicyTreeElement</code> objects
* that are the children of this node. If this node has no children then
* this list is empty. The children are returned as a <code>List</code>
* instead of some unordered collection because in cases like combining
* or evaluation the order is often important.
*
* @return the non-null <code>List</code> of children of this node
*/
public List<PolicyTreeElement> getChildren();
/**
* Returns the given description of this element or null if
* there is no description
*
* @return the description or null
*/
public String getDescription();
/**
* Returns the id of this element
*
* @return the element's identifier
*/
public URI getId();
/**
* Returns the target for this element or null if there
* is no target
*
* @return the element's target
*/
public Target getTarget();
/**
* Given the input context sees whether or not the request matches this
* element's target. The rules for matching are different depending on
* the type of element being matched.
*
* @param context the representation of the request
*
* @return the result of trying to match this element and the request
*/
public MatchResult match(EvaluationCtx context);
/**
* Evaluates this element in the policy tree, and therefore all elements
* underneath this element. The rules for evaluation are different
* depending on the type of element being evaluated.
*
* @param context the representation of the request we're evaluating
*
* @return the result of the evaluation
*/
public Result evaluate(EvaluationCtx context);
/**
* Encodes this element 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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException;
/**
* Encodes this element 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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform default character set
* will be used.
* @param indenter an object that creates indentation strings
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException;
}

View File

@ -0,0 +1,107 @@
/*
* @(#)ProcessingException.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 com.sun.xacml;
/**
* Runtime exception that's thrown if any unexpected error occurs. This could
* appear, for example, if you try to match a referernced policy that can't
* be resolved.
*
* @since 1.0
* @author Seth Proctor
*/
public class ProcessingException extends RuntimeException
{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Constructs a new <code>ProcessingException</code> with no message
* or cause.
*/
public ProcessingException() {
//Processing exception with no message or cause
}
/**
* Constructs a new <code>ProcessingException</code> with a message,
* but no cause. The message is saved for later retrieval by the
* {@link java.lang.Throwable#getMessage() Throwable.getMessage()}
* method.
*
* @param message the detail message (<code>null</code> if nonexistent
* or unknown)
*/
public ProcessingException(String message) {
super(message);
}
/**
* Constructs a new <code>ProcessingException</code> with a cause,
* but no message. The cause is saved for later retrieval by the
* {@link java.lang.Throwable#getCause() Throwable.getCause()}
* method.
*
* @param cause the cause (<code>null</code> if nonexistent
* or unknown)
*/
public ProcessingException(Throwable cause) {
super(cause);
}
/**
* Constructs a new <code>ProcessingException</code> with a message
* and a cause. The message and cause are saved for later retrieval
* by the
* {@link java.lang.Throwable#getMessage() Throwable.getMessage()} and
* {@link java.lang.Throwable#getCause() Throwable.getCause()}
* methods.
*
* @param message the detail message (<code>null</code> if nonexistent
* or unknown)
* @param cause the cause (<code>null</code> if nonexistent
* or unknown)
*/
public ProcessingException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,509 @@
/*
* @(#)Rule.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 com.sun.xacml;
import com.sun.xacml.attr.BooleanAttribute;
import com.sun.xacml.cond.Apply;
import com.sun.xacml.cond.Condition;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.cond.VariableManager;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Represents the RuleType XACML type. This has a target for matching, and
* encapsulates the condition and all sub-operations that make up the heart
* of most policies.
*
* @since 1.0
* @author Seth Proctor
*/
public class Rule implements PolicyTreeElement
{
// the attributes associated with this Rule
private URI idAttr;
private int effectAttr;
// the elements in the rule, each of which is optional
private String description = null;
private Target target = null;
private Condition condition = null;
private RuntimeInfo src = null;
/**
* Creates a new <code>Rule</code> object for XACML 1.x and 2.0.
*
* @param id the rule's identifier
* @param effect the effect to return if the rule applies (either
* Pemit or Deny) as specified in <code>Result</code>
* @param description a textual description, or null
* @param target the rule's target, or null if the target is to be
* inherited from the encompassing policy
* @param condition the rule's condition, or null if there is none
*/
public Rule(URI id, int effect, String description, Target target,
Condition condition) {
this.idAttr = id;
this.effectAttr = effect;
this.description = description;
this.target = target;
this.condition = condition;
}
/**
* Creates a new <code>Rule</code> object for XACML 1.x and 2.0.
*
* @param id the rule's identifier
* @param effect the effect to return if the rule applies (either
* Pemit or Deny) as specified in <code>Result</code>
* @param description a textual description, or null
* @param target the rule's target, or null if the target is to be
* inherited from the encompassing policy
* @param condition the rule's condition, or null if there is none
*/
public Rule(URI id, int effect, String description, Target target,
Condition condition, RuntimeInfo src) {
this.idAttr = id;
this.effectAttr = effect;
this.description = description;
this.target = target;
this.condition = condition;
this.src = src;
}
/**
* Creates a new <code>Rule</code> object for XACML 1.x only.
*
* @deprecated As of 2.0 you should use the Constructor that accepts
* the new <code>Condition</code> class.
*
* @param id the rule's identifier
* @param effect the effect to return if the rule applies (either
* Pemit or Deny) as specified in <code>Result</code>
* @param description a textual description, or null
* @param target the rule's target, or null if the target is to be
* inherited from the encompassing policy
* @param condition the rule's condition, or null if there is none
*/
public Rule(URI id, int effect, String description, Target target,
Apply condition) {
this.idAttr = id;
this.effectAttr = effect;
this.description = description;
this.target = target;
this.condition = new Condition(condition.getFunction(),
condition.getChildren());
}
/**
* Returns a new instance of the <code>Rule</code> class based on a
* DOM node. The node must be the root of an XML RuleType.
*
* @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 RuleType XML type
* @param xpathVersion the XPath version to use in any selectors or XPath
* functions, or null if this is unspecified (ie, not
* supplied in the defaults section of the policy)
*
* @return The Rule object.
*
* @throws ParsingException if the RuleType is invalid
*/
public static Rule getInstance(Node root, String xpathVersion)
throws ParsingException {
return getInstance(root,
new PolicyMetaData(
Constants.XACML_1_0_IDENTIFIER,
xpathVersion),
null);
}
/**
* Returns a new instance of the <code>Rule</code> class based on a
* DOM node. The node must be the root of an XML RuleType.
*
* @param root the DOM root of a RuleType XML type
* @param metaData the meta-data associated with this Rule's policy
* @param manager the <code>VariableManager</code> used to connect
* <code>VariableReference</code>s to their cooresponding
* <code>VariableDefinition<code>s
*
* @return The Rule object.
*
* @throws ParsingException if the RuleType is invalid
*/
public static Rule getInstance(Node root, PolicyMetaData metaData,
VariableManager manager) throws ParsingException {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.RULE);
//check if we really got a rule
if (root.getNodeType() != Node.ELEMENT_NODE) {
throw new ParsingException("Can't create a Rule from"
+ " a node that is not an element-node"
+ (src != null ? src.getLocationMsgForError() : ""));
}
if (!root.getLocalName().equals("Rule")) {
throw new ParsingException("Can't create a Rule from a "
+ root.getLocalName() + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
URI id = null;
int effect = 0;
String description = null;
Target target = null;
Condition condition = null;
// first, get the attributes
NamedNodeMap attrs = root.getAttributes();
try {
// get the two required attrs...
id = new URI(attrs.getNamedItem("RuleId").getNodeValue());
} catch (Exception e) {
throw new ParsingException("Error parsing required attribute " +
"RuleId in a Rule"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
String str = null;
if (attrs.getNamedItem("Effect") != null) {
str = attrs.getNamedItem("Effect").getNodeValue();
} else {
throw new ParsingException("Required attribute Effect missing"
+ "while parsing a Rule"
+ (src != null ? src.getLocationMsgForError() : ""));
}
if (str.equals(Result.PERMIT)) {
effect = Result.DECISION_PERMIT;
} else if (str.equals(Result.DENY)) {
effect = Result.DECISION_DENY;
} else {
throw new ParsingException("Invalid Effect: " + effect
+ (src != null ? src.getLocationMsgForError() : ""));
}
// next, get the elements
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
String cname = child.getLocalName();
if (cname.equals("Description")) {
description = child.getFirstChild().getNodeValue();
} else if (cname.equals("Target")) {
target = Target.getInstance(child, metaData);
} else if (cname.equals("Condition")) {
condition
= Condition.getInstance(child, metaData, manager);
} else {
throw new ParsingException("Found invalid element: "
+ cname + " in Rule " + id
+ (src != null ? src.getLocationMsgForError() : ""));
}
}
}
Rule rule = new Rule(id, effect, description, target, condition, src);
if ( src != null ) {
src.setXACMLObject(rule);
}
return rule;
}
/**
* Returns the effect that this <code>Rule</code> will return from
* the evaluate method (Permit or Deny) if the request applies.
*
* @return a decision effect, as defined in <code>Result</code>
*/
public int getEffect() {
return this.effectAttr;
}
/**
* Returns the id of this <code>Rule</code>
*
* @return the rule id
*/
public URI getId() {
return this.idAttr;
}
/**
* Returns the given description of this <code>Rule</code> or null if
* there is no description
*
* @return the description or null
*/
public String getDescription() {
return this.description;
}
/**
* Returns the target for this <code>Rule</code> or null if there
* is no target
*
* @return the rule's target
*/
public Target getTarget() {
return this.target;
}
/**
* Since a rule is always a leaf in a policy tree because it can have
* no children, this always returns an empty <code>List</code>.
*
* @return a <code>List</code> with no elements
*/
public List<PolicyTreeElement> getChildren() {
return PolicyTreeElement.EMPTY_LIST;
}
/**
* Returns the condition for this <code>Rule</code> or null if there
* is no condition
*
* @return the rule's condition
*/
public Condition getCondition() {
return this.condition;
}
/**
* Given the input context sees whether or not the request matches this
* <code>Rule</code>'s <code>Target</code>. Note that unlike the matching
* done by the <code>evaluate</code> method, if the <code>Target</code>
* is missing than this will return Indeterminate. This lets you write
* your own custom matching routines for rules but lets evaluation
* proceed normally.
*
* @param context the representation of the request
*
* @return the result of trying to match this rule and the request
*/
public MatchResult match(EvaluationCtx context) {
if (this.target == null) {
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_PROCESSING_ERROR);
Status status = new Status(code, "no target available for " +
"matching a rule");
return new MatchResult(MatchResult.INDETERMINATE, status);
}
return this.target.match(context);
}
/**
* Evaluates the rule against the supplied context. This will check that
* the target matches, and then try to evaluate the condition. If the
* target and condition apply, then the rule's effect is returned in
* the result.
* <p>
* Note that rules are not required to have targets. If no target is
* specified, then the rule inherits its parent's target. In the event
* that this <code>Rule</code> has no <code>Target</code> then the
* match is assumed to be true, since evaluating a policy tree to this
* level required the parent's target to match.
*
* @param context the representation of the request we're evaluating
*
* @return the result of the evaluation
*/
public Result evaluate(EvaluationCtx context) {
context.newEvent(this);
// If the Target is null then it's supposed to inherit from the
// parent policy, so we skip the matching step assuming we wouldn't
// be here unless the parent matched
if (this.target != null) {
MatchResult match = match(context);
int result = match.getResult();
// if the target didn't match, then this Rule doesn't apply
if (result == MatchResult.NO_MATCH) {
Result evalResult = new Result(Result.DECISION_NOT_APPLICABLE,
context);
context.closeCurrentEvent(evalResult);
return evalResult;
}
// if the target was indeterminate, we can't go on
if (result == MatchResult.INDETERMINATE) {
Result evalResult = new Result(Result.DECISION_INDETERMINATE,
match.getStatus(),
context);
context.closeCurrentEvent(evalResult);
return evalResult;
}
}
// if there's no condition, then we just return the effect...
if (this.condition == null) {
Result evalResult = new Result(this.effectAttr,
context);
context.closeCurrentEvent(evalResult);
return evalResult;
}
// ...otherwise we evaluate the condition
EvaluationResult result = this.condition.evaluate(context);
if (result.indeterminate()) {
// if it was INDETERMINATE, then that's what we return
Result evalResult = new Result(Result.DECISION_INDETERMINATE,
result.getStatus(),
context);
context.closeCurrentEvent(evalResult);
return evalResult;
}
// otherwise we return the effect on true, and NA on false
BooleanAttribute bool =
(BooleanAttribute)(result.getAttributeValue());
if (bool.getValue()) {
Result evalResult = new Result(this.effectAttr,
context);
context.closeCurrentEvent(evalResult);
return evalResult;
}
Result evalResult = new Result(Result.DECISION_NOT_APPLICABLE,
context);
context.closeCurrentEvent(evalResult);
return evalResult;
}
/**
* Encodes this <code>Rule</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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>Rule</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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
out.print(indent + "<Rule RuleId=\"" + this.idAttr.toString()
+ "\" Effect=\"" + Result.DECISIONS.get(this.effectAttr)
+ "\"");
if ((this.description != null) || (this.target != null)
|| (this.condition != null)) {
// there is some content in the Rule
out.println(">");
indenter.in();
String nextIndent = indenter.makeString();
if (this.description != null) {
out.println(nextIndent + "<Description>" + this.description
+ "</Description>");
}
if (this.target != null) {
this.target.encode(output, charsetName, indenter);
}
if (this.condition != null) {
this.condition.encode(output, charsetName, indenter);
}
indenter.out();
out.println(indent + "</Rule>");
} else {
// the Rule is empty, so close the tag and we're done
out.println("/>");
}
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
}

View File

@ -0,0 +1,390 @@
/*
* @(#)Target.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 com.sun.xacml;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
//import org.apache.log4j.Logger;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.xacml.PolicyMetaData;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
/**
* Represents the TargetType XML type in XACML. This also stores several
* other XML types: The matching categories (e.g. Subjects, Resources,
* Actions, Environments, Delegates). The target is used to quickly
* identify whether the parent element (a policy set, policy, or rule) is
* applicable to a given request.
*
* @since 1.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public class Target implements Cloneable, MatchElement
{
/**
* A <code>List</code> containing <code>TargetSection</code>s.
* These represent the disjunctive sections of this target.
*/
private List<TargetSection> targetElements;
/**
* The version of XACML of the policy containing this target
*/
private int xacmlVersion = Constants.XACML_DEFAULT_VERSION;
private RuntimeInfo src;
// /**
// * The logger we'll use for all messages
// */
// private static final Logger logger =
// Logger.getLogger(Target.class.getName());
/**
* Constructor that creates a <code>Target</code> from components.
*
* @param targetSections A <code>List</code> of
* <code>TargetSection</code>s can be null.
*/
public Target(List<TargetSection> targetSections) {
this(targetSections, Constants.XACML_DEFAULT_VERSION);
}
/**
* Constructor that creates a <code>Target</code> from components.
*
* @param targetSections A <code>List</code> of
* <code>TargetSection</code>s can be null.
* @param xacmlVersion The XACML version (for encoding).
*/
public Target(List<TargetSection> targetSections, int xacmlVersion) {
if (targetSections != null) {
this.targetElements = new ArrayList<TargetSection>(targetSections);
} else {
this.targetElements = TargetSection.EMPTY_LIST;
}
this.xacmlVersion = xacmlVersion;
}
/**
* The clone method constructor
*
* FIXME: this does no deep copy on the Lists and Sets.
*
* @return a copy of this object.
*/
public Object clone() {
try {
Target clone = (Target)super.clone();
clone.targetElements = new ArrayList<TargetSection>(this.targetElements);
clone.xacmlVersion = this.xacmlVersion;
return clone;
} catch (CloneNotSupportedException e) {//this should never happen
throw new RuntimeException("Couldn't clone Target");
}
}
/**
* Creates a <code>Target</code> by parsing a node.
*
* @param root The node to parse for the <code>Target</code>
* @param metaData The policy meta data.
* @return a new <code>Target</code> constructed by parsing
*
* @throws ParsingException if the DOM node is invalid
*/
public static Target getInstance(Node root, PolicyMetaData metaData)
throws ParsingException {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.TARGET);
// first check we really got a Target
if (root.getNodeType() != Node.ELEMENT_NODE) {
throw new ParsingException("Can't create a Target from"
+ " a node that is not an element-node" +
(src != null ? src.getLocationMsgForError() : ""));
}
if (!root.getLocalName().equals("Target")) {
throw new ParsingException("Can't create a Target from a "
+ root.getLocalName() + " element" +
(src != null ? src.getLocationMsgForError() : ""));
}
List<TargetSection> targetElements = new ArrayList<TargetSection>();
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
targetElements.add(TargetSection.getInstance(child, metaData));
}
}
Target target = new Target(targetElements, metaData.getXACMLVersion());
if (src != null ) {
target.src = src;
src.setXACMLObject(target);
}
return target;
}
/**
* Returns the <code>Map</code> of <code>TargetSection</code>s for
* this target, keyed by category.
*
* @return the <code>Map</code> of <code>TargetSection</code>s.
*/
public List<TargetSection> getTargetSections() {
return Collections.unmodifiableList(this.targetElements);
}
/**
* Returns whether or not this <code>Target</code> matches any request.
*
* @return true if this Target matches any request, false otherwise
*/
//TODO <start> changed function
/*public boolean matchesAny() {
return this.targetElements.isEmpty();
} */
public boolean matchesAny() {
if ( this.targetElements.isEmpty() ) {
return true;
} else {
for ( TargetSection element : targetElements ) {
if ( ! element.matchesAny() ) {
return false;
}
}
return true;
}
}
//TODO <end> changed function
/**
* Determines whether this <code>Target</code> matches
* the input request (whether it is applicable).
*
* @param context the representation of the request
*
* @return the result of trying to match the target and the request
*/
public MatchResult match(EvaluationCtx context) {
context.newEvent(this);
MatchResult result = null;
// before matching, see if this target matches any request
if (this.matchesAny()) {
result = new MatchResult(MatchResult.MATCH);
context.closeCurrentEvent(result);
return result;
}
Iterator<TargetSection> it = this.targetElements.iterator();
while (it.hasNext()) {
TargetSection section
= (TargetSection)it.next();
context.newEvent(section);
result = section.match(context);
context.closeCurrentEvent(result);
if (result.getResult() != MatchResult.MATCH) {
// logger.debug("failed to match a disjunctive section "
// + "of the target");
context.closeCurrentEvent(result);
return result;
}
}
// if we got here, then everything matched
result = new MatchResult(MatchResult.MATCH);
context.closeCurrentEvent(result);
return result;
}
/**
* Encodes this <code>Target</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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>Target</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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
indenter.out();
String indent1 = indenter.makeString();
indenter.out();
String indent2 = indenter.makeString();
indenter.in();
indenter.in();
if (this.matchesAny()) {
if (this.xacmlVersion > Constants.XACML_VERSION_1_1) {
//since 2.0, if all the sections match any request, then the Target
//element is empty and should be encoded simply as en empty tag
out.println(indent + "<Target/>");
} else {
out.println(indent + "<Target>");
out.println(indent1 + "<Subjects>");
out.println(indent2 + "<AnySubject/>");
out.println(indent1 + "</Subjects>");
out.println(indent1 + "<Resources>");
out.println(indent2 + "<AnyResource/>");
out.println(indent1 + "</Resources>");
out.println(indent1 + "<Actions>");
out.println(indent2 + "<AnyAction/>");
out.println(indent1 + "</Actions>");
out.println(indent + "</Target>");
}
} else {
out.println(indent + "<Target>");
indenter.in();
if (this.xacmlVersion < Constants.XACML_VERSION_3_0) {
TargetSection subject = null;
TargetSection resource = null;
TargetSection action = null;
TargetSection environment = null;
//fetch subject, resource and action
for (int i=0; i<this.targetElements.size(); i++) {
TargetSection section
= (TargetSection)this.targetElements.get(i);
if (section.getCategory() != null) {
if (section.getCategory().equals(
Constants.SUBJECT_CAT)) {
subject = section;
}
if (section.getCategory().equals(
Constants.RESOURCE_CAT)) {
resource = section;
}
if (section.getCategory().equals(
Constants.ACTION_CAT)) {
action = section;
}
if (section.getCategory().equals(
Constants.ENVIRONMENT_CAT)) {
environment = section;
}
}
}
if (subject != null) {
subject.encode(output, charsetName, indenter);
} else if (this.xacmlVersion < Constants.XACML_VERSION_2_0) {
out.println(indent1 + "<Subjects>");
out.println(indent2 + "<AnySubject/>");
out.println(indent1 + "</Subjects>");
}
if (resource != null) {
resource.encode(output, charsetName, indenter);
} else if (this.xacmlVersion < Constants.XACML_VERSION_2_0) {
out.println(indent1 + "<Resources>");
out.println(indent2 + "<AnyResource/>");
out.println(indent1 + "</Resources>");
}
if (action != null) {
action.encode(output, charsetName, indenter);
} else if (this.xacmlVersion < Constants.XACML_VERSION_2_0) {
out.println(indent1 + "<Actions>");
out.println(indent2 + "<AnyAction/>");
out.println(indent1 + "</Actions>");
}
if (environment != null
&& this.xacmlVersion == Constants.XACML_VERSION_2_0) {
environment.encode(output, charsetName, indenter);
}
} else {
Iterator<TargetSection> it = this.targetElements.iterator();
while (it.hasNext()) {
TargetSection section
= (TargetSection)it.next();
section.encode(output, charsetName, indenter);
}
}
indenter.out();
out.println(indent + "</Target>");
}
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
}

View File

@ -0,0 +1,537 @@
/*
* @(#)TargetMatch.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 com.sun.xacml;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.attr.AttributeDesignator;
import com.sun.xacml.attr.AttributeFactory;
import com.sun.xacml.attr.AttributeSelector;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.BagAttribute;
import com.sun.xacml.attr.BooleanAttribute;
import com.sun.xacml.cond.Evaluatable;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.cond.Expression;
import com.sun.xacml.cond.Function;
import com.sun.xacml.cond.FunctionFactory;
import com.sun.xacml.cond.FunctionTypeException;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Represents the Match XML type in XACML. This is the part of the Target that
* actually evaluates whether the specified attribute values in the Target match
* the corresponding attribute values in the request context.
*
* @since 1.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public class TargetMatch implements MatchElement
{
/**
* The function used for matching.
*/
private Function function;
/**
* The <code>AttributeDesignator</code> or
* <code>AttributeSelector</code> to be used to select
* attributes from the request context
*/
private Evaluatable eval;
/**
* The value to compare against.
*/
private AttributeValue attrValue;
/**
* The xacml version for encoding.
*/
private int xacmlVersion;
/**
* The match category. Used only for backwards compatibility.
*/
private URI category;
private RuntimeInfo src;
/**
* Constructor that creates a default version<code>TargetMatch</code>
* from components.
*
* @param function the <code>Function</code> that represents the MatchId
* @param eval the <code>AttributeDesignator</code> or
* <code>AttributeSelector</code> to be used to select
* attributes from the request context
* @param attrValue the <code>AttributeValue</code> to compare against
*
* @throws IllegalArgumentException if the input type isn't a valid value
*/
public TargetMatch(Function function, Evaluatable eval,
AttributeValue attrValue)
throws IllegalArgumentException {
this(function, eval, attrValue, Constants.XACML_DEFAULT_VERSION,
null);
}
/**
* Constructor that creates a <code>TargetMatch</code> from components.
*
* @param function the <code>Function</code> that represents the MatchId
* @param eval the <code>AttributeDesignator</code> or
* <code>AttributeSelector</code> to be used to select
* attributes from the request context
* @param attrValue the <code>AttributeValue</code> to compare against
* @param xacmlVersion The XACML version number.
* @param category The category of this match (e.g. "Subject") for
* XACML versions 2.0 and earlier. Is null for
* later versions.
*
* @throws IllegalArgumentException if the input type isn't a valid value
*/
public TargetMatch(Function function, Evaluatable eval,
AttributeValue attrValue, int xacmlVersion,
URI category)
throws IllegalArgumentException {
this.function = function;
this.eval = eval;
this.attrValue = attrValue;
this.xacmlVersion = xacmlVersion;
this.category = category;
}
/**
* Creates a <code>TargetMatch</code> by parsing a node, using the
* input prefix to determine which category of match this is.
*
* @param root The node to parse for the <code>TargetMatch</code>
* @param metaData The policy's meta-data
* @param masterCategory The category of the TargetMatchGroup, for
* checking consistency.
*
* @return a new <code>TargetMatch</code> constructed by parsing
*
* @throws ParsingException if there was an error during parsing
*/
public static TargetMatch getInstance(Node root,
PolicyMetaData metaData, URI masterCategory)
throws ParsingException {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.TARGET_MATCH);
// first make sure the node passed is indeed a TargetMatch
if (root.getNodeType() != Node.ELEMENT_NODE) {
throw new ParsingException("Can't create a TargetMatch from"
+ " a node that is not an element-node"
+ (src != null ? src.getLocationMsgForError() : ""));
}
if (!root.getLocalName().endsWith("Match")) {
throw new ParsingException("Can't create a TargetMatch from a "
+ root.getLocalName() + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
Function function;
Evaluatable eval = null;
AttributeValue attrValue = null;
AttributeFactory attrFactory = AttributeFactory.getInstance();
// get the function type, making sure that it's really a correct
// Target function
String funcName = null;
if (root.getAttributes().getNamedItem("MatchId") != null) {
funcName = root.getAttributes().getNamedItem("MatchId")
.getNodeValue();
} else {
throw new ParsingException("Required XML attribute "
+ "MatchId not found while parsing a TargetMatch"
+ (src != null ? src.getLocationMsgForError() : ""));
}
FunctionFactory factory = FunctionFactory.getTargetInstance();
try {
URI funcId = new URI(funcName);
function = factory.createFunction(funcId);
} catch (URISyntaxException use) {
throw new ParsingException("Error parsing TargetMatch"
+ (src != null ? src.getLocationMsgForError() : ""), use);
} catch (UnknownIdentifierException uie) {
throw new ParsingException("Unknown MatchId"
+ (src != null ? src.getLocationMsgForError() : ""), uie);
} catch (FunctionTypeException fte) {
// try to create an abstract function
try {
URI funcId = new URI(funcName);
function = factory.createAbstractFunction(funcId, root);
} catch (Exception e) {
// any exception here is an error
throw new ParsingException("invalid abstract function"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
}
// next, get the designator or selector being used, and the attribute
// value paired with it
NodeList nodes = root.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String name = node.getLocalName();
// endsWith() is compatibility code for XACML 2.0
if (name.endsWith("AttributeDesignator")) {
if (name.equals("AttributeDesignator")) {
if (metaData.getXACMLVersion()
< Constants.XACML_VERSION_3_0) {
throw new ParsingException(
"Can't create a < XACML 3.0 "
+ "AttributeDesignator out of a "
+ name + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
} else { // XACML 2.0 compatibility
if (metaData.getXACMLVersion()
> Constants.XACML_VERSION_2_0) {
throw new ParsingException(
"Can't create a > XACML 2.0 "
+ "AttributeDesignator out of a "
+ name + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
String categoryStr
= name.replaceAll("AttributeDesignator", "");
URI category = null;
if (categoryStr.equals("Subject")) {
category = Constants.SUBJECT_CAT;
} else if (categoryStr.equals("Resource")) {
category = Constants.RESOURCE_CAT;
} else if (categoryStr.equals("Action")) {
category = Constants.ACTION_CAT;
} else if (categoryStr.equals("Environment")){
category = Constants.ENVIRONMENT_CAT;
} else {
throw new ParsingException("Can't create a "
+ "< XACML 3.0 AttributeDesignator out of"
+ " a " + categoryStr + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
if (!category.equals(masterCategory)) {
throw new ParsingException(categoryStr + "Match"
+ " can't be located in enclosing "
+ masterCategory.toString() + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
}
eval = AttributeDesignator.getInstance(node, metaData);
} else if (name.equals("AttributeSelector")) {
eval = AttributeSelector.getInstance(node, metaData);
} else if (name.equals("AttributeValue")) {
try {
attrValue = attrFactory.createValue(node);
} catch (UnknownIdentifierException uie) {
throw new ParsingException(
"Unknown Attribute Type"
+ (src != null ? src.getLocationMsgForError() : ""), uie);
}
} else {
throw new ParsingException("Encountered: '"
+ name + "' node while parsing a TargetMatch"
+ (src != null ? src.getLocationMsgForError() : ""));
}
}
}
// finally, check that the inputs are valid for this function
List<Evaluatable> inputs = new ArrayList<Evaluatable>();
inputs.add(attrValue);
inputs.add(eval);
function.checkInputsNoBag(inputs, src);
TargetMatch targetMatch = new TargetMatch(function, eval, attrValue,
metaData.getXACMLVersion(), masterCategory);
if ( src != null ) {
targetMatch.src = src;
src.setXACMLObject(targetMatch);
}
return targetMatch;
}
/**
* Returns the <code>Function</code> used to do the matching.
*
* @return the match function
*/
public Function getMatchFunction() {
return this.function;
}
/**
* Returns the <code>AttributeValue</code> used by the matching function.
*
* @return the <code>AttributeValue</code> for the match
*/
public AttributeValue getMatchValue() {
return this.attrValue;
}
/**
* Returns the <code>AttributeDesignator</code> or
* <code>AttributeSelector</code> used by the matching function.
*
* @return the designator or selector for the match
*/
public Evaluatable getMatchEvaluatable() {
return this.eval;
}
/**
* Returns the category of this match.
*
* @return the category of this match.
*/
public URI getCategory() {
return this.category;
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
/**
* Determines whether this <code>TargetMatch</code> matches
* the input request (whether it is applicable)
*
* @param context the representation of the request
*
* @return the result of trying to match the TargetMatch and the request
*/
public MatchResult match(EvaluationCtx context) {
// start by evaluating the AD/AS
EvaluationResult result = this.eval.evaluate(context);
if (result.indeterminate()) {
// in this case, we don't ask the function for anything, and we
// simply return INDETERMINATE
return new MatchResult(MatchResult.INDETERMINATE,
result.getStatus());
}
// an AD/AS will always return a bag
BagAttribute bag = (BagAttribute)(result.getAttributeValue());
if (! bag.isEmpty()) {
// we got back a set of attributes, so we need to iterate through
// them, seeing if at least one matches
Iterator<AttributeValue> it = bag.iterator();
boolean atLeastOneError = false;
Status firstIndeterminateStatus = null;
while (it.hasNext()) {
ArrayList<Expression> inputs = new ArrayList<Expression>();
inputs.add(this.attrValue);
inputs.add(it.next());
// do the evaluation
MatchResult match = evaluateMatch(inputs, context);
// we only need one match for this whole thing to match
if (match.getResult() == MatchResult.MATCH) {
return match;
}
// if it was INDETERMINATE, we want to remember for later
if (match.getResult() == MatchResult.INDETERMINATE) {
atLeastOneError = true;
// there are no rules about exactly what status data
// should be returned here, so like in the combining
// algs, we'll just track the first error
if (firstIndeterminateStatus == null) {
firstIndeterminateStatus = match.getStatus();
}
}
}
// if we got here, then nothing matched, so we'll either return
// INDETERMINATE or NO_MATCH
if (atLeastOneError) {
return new MatchResult(MatchResult.INDETERMINATE,
firstIndeterminateStatus);
}
return new MatchResult(MatchResult.NO_MATCH);
}
// this is just an optimization, since the loop above will
// actually handle this case, but this is just a little
// quicker way to handle an empty bag
return new MatchResult(MatchResult.NO_MATCH);
}
/**
* Private helper that evaluates an individual match.
*/
private MatchResult evaluateMatch(List<Expression> inputs, EvaluationCtx context) {
RuntimeInfo funcSrc = null;
//set (context dependent) source locator for function
if ( src != null ) {
//funcSrc = RuntimeInfo.getIndirectSourceLocator(src, ELEMENT_TYPE.FUNCTION);
funcSrc = src.getIndirectRuntimeInfo(function, ELEMENT_TYPE.FUNCTION);
this.function.setRuntimeInfo(funcSrc);
}
// first off, evaluate the function
EvaluationResult result = this.function.evaluate(inputs, context);
//unset source locator
if ( funcSrc != null ) {
this.function.unsetRuntimeInfo(funcSrc) ;
}
// if it was indeterminate, then that's what we return immediately
if (result.indeterminate()) {
return new MatchResult(MatchResult.INDETERMINATE,
result.getStatus());
}
// otherwise, we figure out if it was a match
BooleanAttribute bool = (BooleanAttribute)(result.getAttributeValue());
if (bool.getValue()) {
return new MatchResult(MatchResult.MATCH);
}
return new MatchResult(MatchResult.NO_MATCH);
}
/**
* Encodes this <code>TargetMatch</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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>TargetMatch</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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
String closingTag = null;
if (this.xacmlVersion < Constants.XACML_VERSION_3_0) {
if (this.category.equals(Constants.SUBJECT_CAT)) {
out.print(indent + "<SubjectMatch ");
closingTag = "</SubjectMatch>";
} else if (this.category.equals(Constants.RESOURCE_CAT)) {
out.print(indent + "<ResourceMatch ");
closingTag = "</ResourceMatch>";
} else if (this.category.equals(Constants.ACTION_CAT)) {
out.print(indent + "<ActionMatch ");
closingTag = "</ActionMatch>";
} else if (this.category.equals(Constants.ENVIRONMENT_CAT)) {
out.print(indent + "<EnvironmentMatch ");
closingTag = "</EnvironmentMatch>";
}
} else {
out.print(indent + "<Match ");
closingTag = "</Match>";
}
out.println("MatchId=\""
+ this.function.getIdentifier().toString()+ "\">");
indenter.in();
this.attrValue.encode(output, charsetName, indenter);
this.eval.encode(output, charsetName, indenter);
indenter.out();
out.println(indent + closingTag);
}
}

View File

@ -0,0 +1,330 @@
/*
* @(#)TargetMatchGroup.java
*
* Copyright 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 com.sun.xacml;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
/**
* This class contains a group of <code>TargetMatch</code> instances and
* represents the different elements in an XACML Target (e.g. Subject)
*
* @since 2.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public class TargetMatchGroup implements MatchElement
{
/**
* The list of <code>TargetMatch</code>es.
*/
private List<TargetMatch> matches;
/**
* The XACML version number. Only used for encoding.
*/
private int xacmlVersion;
/**
* The category. Only used for encoding XACML versions < 3.0
*/
private URI category;
public static final List<TargetMatchGroup> EMPTY_LIST = Collections.<TargetMatchGroup>emptyList();
private RuntimeInfo src;
/**
* Constructor that creates a new <code>TargetMatchGroup</code> based
* on the given elements with the default XACML version.
*
* @param matchElements A <code>List</code> of <code>TargetMatch</code>.
* They should all have the same category.
*/
public TargetMatchGroup(List<TargetMatch> matchElements) {
this(matchElements, Constants.XACML_DEFAULT_VERSION, null);
}
/**
* Constructor that creates a new <code>TargetMatchGroup</code> based
* on the given elements.
*
* @param matchElements A <code>List</code> of <code>TargetMatch</code>.
* They should all have the same category.
* @param xacmlVersion The XACML version number.
* @param category The category if this match group.
* This is null for XACML version > 2.0.
*/
public TargetMatchGroup(List<TargetMatch> matchElements, int xacmlVersion,
URI category) {
if (matchElements == null) {
this.matches = Collections.unmodifiableList(new ArrayList<TargetMatch>());
} else {
this.matches =
Collections.unmodifiableList(new ArrayList<TargetMatch>(matchElements));
}
this.xacmlVersion = xacmlVersion;
this.category = category;
if (this.category == null
&& this.xacmlVersion < Constants.XACML_VERSION_3_0) {
throw new IllegalArgumentException("Can't create TargetSections"
+ " in XACML version < 3.0 without category");
}
}
/**
* Creates a <code>Target</code> based on its DOM node.
*
* @param root The node to parse for the target group.
* @param metaData Meta-data associated with the policy.
* @param masterCategory The category of the TargetSection, for
* checking consistency.
*
* @return a new <code>TargetMatchGroup</code> constructed by parsing
*
* @throws ParsingException if the DOM node is invalid
*/
public static TargetMatchGroup getInstance(Node root,
PolicyMetaData metaData,
URI masterCategory)
throws ParsingException {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.TARGET_MATCH_GROUP );
if (root.getNodeType() != Node.ELEMENT_NODE) {
throw new ParsingException("Can't create a TargetMatchGroup from"
+ " a node that is not an element-node"
+ (src != null ? src.getLocationMsgForError() : ""));
}
List<TargetMatch> matches = new ArrayList<TargetMatch>();
NodeList children = root.getChildNodes();
String categoryStr = root.getLocalName();
if (!categoryStr.equals("AllOf")) { //XACML v2.0 or lower
if (metaData.getXACMLVersion()
> Constants.XACML_VERSION_2_0) {
throw new ParsingException("Can't create a > XACML 2.0"
+ " TargetMatchGroup form a " + categoryStr
+ " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
URI category = null;
if (categoryStr.equals("Subject")) {
category = Constants.SUBJECT_CAT;
} else if (categoryStr.equals("Resource")) {
category = Constants.RESOURCE_CAT;
} else if (categoryStr.equals("Action")) {
category = Constants.ACTION_CAT;
} else if (categoryStr.equals("Environment")){
category= Constants.ENVIRONMENT_CAT;
} else {
throw new ParsingException("Can't create a < XACML 3.0"
+ " TargetMatchGroup from a " + categoryStr
+ " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
if (!category.equals(masterCategory)) {
throw new ParsingException(categoryStr + " element must"
+ " can't be in enclosing "
+ masterCategory.toString() + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
} else if (categoryStr.equals("AllOf")
&& (metaData.getXACMLVersion()
< Constants.XACML_VERSION_3_0)) {
throw new ParsingException("Can't create a < XACML 3.0"
+ " TargetMatchGroup from a " + categoryStr
+ " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
matches.add(TargetMatch.getInstance(child, metaData,
masterCategory));
}
}
TargetMatchGroup targetMatchGroup = new TargetMatchGroup(matches,
metaData.getXACMLVersion(), masterCategory);
if ( src != null ) {
targetMatchGroup.src = src;
src.setXACMLObject(targetMatchGroup);
}
return targetMatchGroup;
}
/**
* Determines whether this <code>TargetMatchGroup</code> matches
* the input request (whether it is applicable).
*
* @param context the representation of the request
*
* @return the result of trying to match the group with the context
*/
public MatchResult match(EvaluationCtx context) {
//TODO <start> changed function
if ( this.matches.size() == 0 ) {
return new MatchResult(MatchResult.MATCH);
}
//TODO <end> changed function
Iterator<TargetMatch> it = this.matches.iterator();
MatchResult result = null;
while (it.hasNext()) {
TargetMatch tm = (TargetMatch)(it.next());
context.newEvent(tm);
result = tm.match(context);
context.closeCurrentEvent(result);
if (result.getResult() != MatchResult.MATCH) {
break;
}
}
return result;
}
/**
* Returns the category of this group.
*
* @return the category of this group.
*/
public URI getCategory() {
return this.category;
}
/**
* Encodes this <code>TargetMatchGroup</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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>TargetMatchGroup</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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
Iterator<TargetMatch> it = this.matches.iterator();
String closingTag = null;
if (this.xacmlVersion > Constants.XACML_VERSION_2_0) {
out.println(indent + "<AllOf>");
closingTag = "</AllOf>";
} else { // XACML 2.0 and below compatibility code
if (this.category.equals(Constants.SUBJECT_CAT)) {
out.println(indent + "<Subject>");
closingTag = "</Subject>";
} else if (this.category.equals(Constants.RESOURCE_CAT)) {
out.println(indent + "<Resource>");
closingTag = "</Resource>";
} else if (this.category.equals(Constants.ACTION_CAT)) {
out.println(indent + "<Action>");
closingTag = "</Action>";
} else if (this.category.equals(Constants.ENVIRONMENT_CAT)) {
out.println(indent + "<Environment>");
closingTag = "</Environment>";
}
}
indenter.in();
while (it.hasNext()) {
TargetMatch tm = (TargetMatch)(it.next());
tm.encode(output, charsetName, indenter);
}
out.println(indent + closingTag);
indenter.out();
}
/**
* Returns the matches of this match group.
* @return The list of <code>TargetMatch</code>es.
*/
public List<TargetMatch> getMatches() {
return Collections.unmodifiableList(this.matches);
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
}

View File

@ -0,0 +1,382 @@
/*
* @(#)TargetSection.java
*
* Copyright 2005-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;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This is a container class for instances of <code>TargetMatchGroup</code>
* and represents the matching categories sections of an XACML Target
* (e.g. Subjects, Resources, Actions, Environments, Delegates).
* This section may apply to any request.
*
* @since 2.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public class TargetSection implements MatchElement
{
/**
* The list of match groups
*/
private List<TargetMatchGroup> matchGroups;
/**
* The XACML version of this target section
* for encoding older XACML versions
*/
private int xacmlVersion;
/**
* The category of this target section
*/
private URI category;
public static final List<TargetSection> EMPTY_LIST = Collections.<TargetSection>emptyList();
private RuntimeInfo src;
/**
* Constructor that takes a group and a version. If the group is
* null or empty, then this represents a section that matches any request.
*
* @param matchGroups A possibly null <code>List</code> of
* <code>TargetMatchGroup</code>s.
*/
public TargetSection(List<TargetMatchGroup> matchGroups) {
this(matchGroups, null, Constants.XACML_DEFAULT_VERSION);
}
/**
* Constructor that takes a group and a version. If the group is
* null or empty, then this represents a section that matches any request.
*
* @param matchGroups A possibly null <code>List</code> of
* <code>TargetMatchGroup</code>s.
* @param category The category of this target section.
* @param xacmlVersion The XACML version of this TargetSection
* (for encoding).
*/
public TargetSection(List<TargetMatchGroup> matchGroups, URI category, int xacmlVersion) {
if (matchGroups == null) {
this.matchGroups = TargetMatchGroup.EMPTY_LIST;
} else {
this.matchGroups = Collections.
unmodifiableList(new ArrayList<TargetMatchGroup>(matchGroups));
}
this.category = category;
this.xacmlVersion = xacmlVersion;
if (this.xacmlVersion < Constants.XACML_VERSION_3_0) {
if (this.category == null) {
throw new IllegalArgumentException("Can't create TargetSections"
+ " in XACML version < 3.0 without category");
}
if (!this.category.toString().startsWith(
"urn:oasis:names:tc:xacml:1.0:subject-category:")
&& !this.category.equals(Constants.RESOURCE_CAT)
&& !this.category.equals(Constants.ACTION_CAT)) {
if (this.xacmlVersion == Constants.XACML_VERSION_2_0) {
if (!this.category.equals(Constants.ENVIRONMENT_CAT)) {
throw new IllegalArgumentException("Illegal"
+ " Category: "
+ this.category.toString()
+ " for pre XACML 3.0 policy");
}
} else {
throw new IllegalArgumentException("Illegal"
+ " Category: "
+ this.category.toString()
+ " for pre XACML 3.0 policy");
}
}
}
}
/**
* Creates a <code>Target</code> by parsing a node.
*
* @param root The node to parse for the <code>Target</code>.
* @param metaData The meta-data from the enclosing policy.
*
* @return a new <code>Target</code> constructed by parsing
*
* @throws ParsingException if the DOM node is invalid
*/
public static TargetSection getInstance(Node root, PolicyMetaData metaData)
throws ParsingException {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.TARGET_SECTION);
if (root.getNodeType() != Node.ELEMENT_NODE) {
throw new ParsingException("Can't create a TargetSection from"
+ " a node that is not an element-node"
+ (src != null ? src.getLocationMsgForError() : ""));
}
List<TargetMatchGroup> groups = new ArrayList<TargetMatchGroup>();
NodeList children = root.getChildNodes();
String categoryStr = null;
URI category = null;
if (metaData.getXACMLVersion() > Constants.XACML_VERSION_2_0) {
if (!root.getLocalName().equals("AnyOf")) {
throw new ParsingException("Found: " + root.getLocalName()
+ " tag where expecting AnyOf tag"
+ (src != null ? src.getLocationMsgForError() : ""));
}
} else {
//Get node name minus the tailing 's'
categoryStr = root.getLocalName();
categoryStr = categoryStr.substring(0, categoryStr.length()-1);
if (categoryStr.equals("Subject")) {
category = Constants.SUBJECT_CAT;
} else if (categoryStr.equals("Resource")) {
category = Constants.RESOURCE_CAT;
} else if (categoryStr.equals("Action")) {
category = Constants.ACTION_CAT;
} else if (metaData.getXACMLVersion()
== Constants.XACML_VERSION_2_0
&& categoryStr.equals("Environment")) {
category = Constants.ENVIRONMENT_CAT;
} else {
throw new ParsingException("Invalid element: "
+ root.getLocalName()
+ "for XACML version:" + metaData.getXACMLVersion()
+ (src != null ? src.getLocationMsgForError() : ""));
}
}
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
//check for Any* elements as children
if (metaData.getXACMLVersion() < Constants.XACML_VERSION_2_0) {
if (child.getLocalName().startsWith("Any")) {
TargetSection targetSection = new TargetSection(groups,
category, metaData.getXACMLVersion());
targetSection.src = src;
return targetSection;
}
}
groups.add(TargetMatchGroup.getInstance(child, metaData,
category));
}
}
// at this point the list is non-empty (it has specific groups to
// match) or is empty
TargetSection targetSection = new TargetSection(groups,
category, metaData.getXACMLVersion());
if ( src != null ) {
targetSection.src = src;
src.setXACMLObject(targetSection);
}
return targetSection;
}
/**
* Returns the <code>TargetMatchGroup</code>s contained in this group.
*
* @return a <code>List</code> of <code>TargetMatchGroup</code>s
*/
public List<TargetMatchGroup> getMatchGroups() {
return this.matchGroups;
}
/**
* Returns whether this section matches any request.
*
* @return true if this section matches any request, false otherwise
*/
public boolean matchesAny() {
return this.matchGroups.isEmpty();
}
/**
* Returns the category of this section.
*
* @return the category of this section.
*/
public URI getCategory() {
return this.category;
}
/**
* Determines whether this <code>TargetSection</code> matches
* the input request (whether it is applicable).
*
* @param context the representation of the request
*
* @return the result of trying to match the target and the request
*/
public MatchResult match(EvaluationCtx context) {
// if we apply to anything, then we always match
if (this.matchGroups.isEmpty()) {
return new MatchResult(MatchResult.MATCH);
}
// there are specific matching elements, so prepare to iterate
// through the list
Iterator<TargetMatchGroup> it = this.matchGroups.iterator();
Status firstIndeterminateStatus = null;
// in order for this section to match, one of the groups must match
while (it.hasNext()) {
// get the next group and try matching it
TargetMatchGroup group = (TargetMatchGroup)(it.next());
context.newEvent(group);
MatchResult result = group.match(context);
context.closeCurrentEvent(result);
// we only need one match, so if this matched, then we're done
if (result.getResult() == MatchResult.MATCH) {
return result;
}
// if we didn't match then it was either a NO_MATCH or
// INDETERMINATE...in the second case, we need to remember
// it happened, 'cause if we don't get a MATCH, then we'll
// be returning INDETERMINATE
if (result.getResult() == MatchResult.INDETERMINATE) {
if (firstIndeterminateStatus == null) {
firstIndeterminateStatus = result.getStatus();
}
}
}
// if we got here, then none of the sub-matches passed, so
// we have to see if we got any INDETERMINATE cases
if (firstIndeterminateStatus == null) {
return new MatchResult(MatchResult.NO_MATCH);
}
return new MatchResult(MatchResult.INDETERMINATE,
firstIndeterminateStatus);
}
/**
* Encodes this <code>TargetSection</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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>TargetSection</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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
String closingTag = null;
// figure out if this section applies to any request
if (!this.matchGroups.isEmpty()) {
if (this.xacmlVersion > Constants.XACML_VERSION_2_0) {
// this has specific rules, so we can now encode them
out.println(indent + "<AnyOf>");
closingTag = "</AnyOf>";
} else { // XACML 2.0 and below compatibility code
if (this.category.equals(Constants.SUBJECT_CAT)) {
out.println(indent + "<Subjects>");
closingTag = "</Subjects>";
} else if (this.category.equals(Constants.RESOURCE_CAT)) {
out.println(indent + "<Resources>");
closingTag = "</Resources>";
} else if (this.category.equals(Constants.ACTION_CAT)) {
out.println(indent + "<Actions>");
closingTag = "</Actions>";
} else if (this.category.equals(Constants.ENVIRONMENT_CAT)) {
out.println(indent + "<Environments>");
closingTag = "</Environments>";
}
}
Iterator<TargetMatchGroup> it = this.matchGroups.iterator();
indenter.in();
while (it.hasNext()) {
TargetMatchGroup group = (TargetMatchGroup)(it.next());
group.encode(output, charsetName, indenter);
}
indenter.out();
out.println(indent + closingTag);
}
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
}

View File

@ -0,0 +1,71 @@
/*
* @(#)UnknownIdentifierException.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 com.sun.xacml;
/**
* Exception that gets thrown if an unknown identifier was used, such as the
* identifier used in any of the standard factories.
*
* @since 1.0
* @author Seth Proctor
*/
public class UnknownIdentifierException extends Exception
{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Creates an <code>UnknownIdentifierException</code> with no data
*/
public UnknownIdentifierException() {
//contains no data
}
/**
* Creates an <code>UnknownIdentifierException</code> with a message
*
* @param message the message
*/
public UnknownIdentifierException(String message) {
super(message);
}
}

View File

@ -0,0 +1,241 @@
/*
* @(#)VersionConstraints.java
*
* Copyright 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 com.sun.xacml;
import java.util.StringTokenizer;
/**
* Supports the three version constraints that can be included with a
* policy reference. This class also provides a simple set of comparison
* methods for matching against the constraints. Note that this feature
* was introduced in XACML 2.0, which means that constraints are never
* used in pre-2.0 policy references.
*
* @since 2.0
* @author Seth Proctor
*/
public class VersionConstraints
{
// internal identifiers used to specify the kind of match
private static final int COMPARE_EQUAL = 0;
private static final int COMPARE_LESS = 1;
private static final int COMPARE_GREATER = 2;
// the three constraint strings
private String version;
private String earliest;
private String latest;
/**
* Creates a <code>VersionConstraints</code> with the three optional
* constraint strings. Each of the three strings must conform to the
* VersionMatchType type defined in the XACML schema. Any of the
* strings may be null to specify that the given constraint is not
* used.
*
* @param version a matching constraint on the version or null
* @param earliest a lower-bound constraint on the version or null
* @param latest an upper-bound constraint on the version or null
*/
public VersionConstraints(String version, String earliest, String latest) {
this.version = version;
this.earliest = earliest;
this.latest = latest;
}
/**
* Returns the matching constraint string, which will be null if there
* is no constraint on matching the version.
*
* @return the version constraint
*/
public String getVersionConstraint() {
return this.version;
}
/**
* Returns the lower-bound constraint string, which will be null if there
* is no lower-bound constraint on the version.
*
* @return the lower-bound constraint
*/
public String getEarliestConstraint() {
return this.earliest;
}
/**
* Returns the upper-bound constraint string, which will be null if there
* is no upper-bound constraint on the version.
*
* @return the upper-bound constraint
*/
public String getLatestConstraint() {
return this.latest;
}
/**
* Checks if the given version string meets all three constraints.
*
* @param version the version to compare, which is formatted as a
* VersionType XACML type
*
* @return true if the given version meets all the constraints
*/
public boolean meetsConstraint(String version) {
return (matches(version, this.version)
&& isEarlier(version, this.latest)
&& isLater(version, this.earliest));
}
/**
* Checks if the given version string matches the constraint string.
*
* @param version the version string to check
* @param constraint a constraint string to use in matching
*
* @return true if the version string matches the constraint
*/
public static boolean matches(String version, String constraint) {
return compareHelper(version, constraint, COMPARE_EQUAL);
}
/**
* Checks if the given version string is less-than or equal-to the
* constraint string.
*
* @param version the version string to check
* @param constraint a constraint string to use in matching
*
* @return true if the version string is earlier than the constraint
*/
public static boolean isEarlier(String version, String constraint) {
return compareHelper(version, constraint, COMPARE_LESS);
}
/**
* Checks if the given version string is greater-than or equal-to the
* constraint string.
*
* @param version the version string to check
* @param constraint a constraint string to use in matching
*
* @return true if the version string is later than the constraint
*/
public static boolean isLater(String version, String constraint) {
return compareHelper(version, constraint, COMPARE_GREATER);
}
/**
* Private helper that handles all three comparisons.
*/
private static boolean compareHelper(String version, String constraint,
int type) {
// check that a constraint was provided...
if (constraint == null) {
return true;
}
// ...and a version too
// FIXME: this originally returned false, but I think it should
// return true, since we always match if the contstraint is
// unbound (null) ... is that right?
if (version == null) {
return true;
}
// setup tokenizers
StringTokenizer vtok = new StringTokenizer(version, ".");
StringTokenizer ctok = new StringTokenizer(constraint, ".");
while (vtok.hasMoreTokens()) {
// if there's nothing left in the constraint, then this means
// we didn't match, unless this is the greater-than function
if (! ctok.hasMoreTokens()) {
if (type == COMPARE_GREATER) {
return true;
}
return false;
}
// get the next constraint token...
String c = ctok.nextToken();
// ...and if it's a + then it's done and we match
if (c.equals("+")) {
return true;
}
String v = vtok.nextToken();
// if it's a * then we always match, otherwise...
if (! c.equals("*")) {
// if it's a match then we just keep going, otherwise...
if (! v.equals(c)) {
// if we're matching on equality, then we failed
if (type == COMPARE_EQUAL) {
return false;
}
// convert both tokens to integers...
int cint = Integer.valueOf(c).intValue();
int vint = Integer.valueOf(v).intValue();
// ...and do the right kind of comparison
if (type == COMPARE_LESS) {
return vint <= cint;
}
return vint >= cint;
}
}
}
// if we got here, then we've finished the processing the version,
// so see if there's anything more in the constrant, which would
// mean we didn't match unless we're doing less-than
if (ctok.hasMoreTokens()) {
if (type == COMPARE_LESS) {
return true;
}
return false;
}
// we got through everything, so the constraint is met
return true;
}
}

View File

@ -0,0 +1,201 @@
/*
* @(#)AnyURIAttribute.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 com.sun.xacml.attr;
import java.net.URI;
import java.net.URISyntaxException;
import org.w3c.dom.Node;
import com.sun.xacml.ParsingException;
/**
* Representation of an xs:anyURI value. This class supports parsing
* xs:anyURI values.
*
* @since 1.0
* @author Seth Proctor
*/
public class AnyURIAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.ANYURI;
//URI version of name for this type
private static URI identifierURI;
// RuntimeException that wraps an Exception thrown during the
// creation of identifierURI, null if none
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
// the URI value that this class represents
private URI value;
/**
* Creates a new <code>AnyURIAttribute</code> that represents
* the URI value supplied.
*
* @param value the <code>URI</code> value to be represented
*/
public AnyURIAttribute(URI value) {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
this.value = value;
}
/**
* Returns a new <code>AnyURIAttribute</code> that represents
* the xs:anyURI at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
*
* @return a new <code>AnyURIAttribute</code> representing the
* appropriate value (null if there is a parsing error)
*
* @throws URISyntaxException
* @throws ParsingException
*/
public static AnyURIAttribute getInstance(Node root)
throws URISyntaxException, ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a AnyURIAttribute");
}
/**
* Returns a new <code>AnyURIAttribute</code> that represents
* the xs:anyURI value indicated by the <code>String</code> provided.
*
* @param value a string representing the desired value
*
* @return a new <code>AnyURIAttribute</code> representing the
* appropriate value
*
* @throws URISyntaxException
* @throws ParsingException
*/
public static AnyURIAttribute getInstance(String value)
throws URISyntaxException, ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "AnyURIAttribute from null input");
}
return new AnyURIAttribute(new URI(value));
}
/**
* Returns the <code>URI</code> value represented by this object.
*
* @return the <code>URI</code> value
*/
public URI getValue() {
return this.value;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof AnyURIAttribute)) {
return false;
}
AnyURIAttribute other = (AnyURIAttribute)o;
return this.value.equals(other.value);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
return this.value.hashCode();
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
return "AnyURIAttribute: \"" + this.value.toString() + "\"";
}
/**
* @return The AttributeValue encoded as a <code>String</code>.
*
*/
public String encode() {
return this.value.toString();
}
}

View File

@ -0,0 +1,552 @@
/*
* @(#)AttributeDesignator.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.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.Indenter;
import com.sun.xacml.ParsingException;
import com.sun.xacml.PolicyMetaData;
import com.sun.xacml.cond.Evaluatable;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.cond.Expression;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.ctx.StatusDetail;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import com.sun.xacml.finder.RequiredAttributesModule;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* Represents Attribute Designators in XACML.
*
* @since 1.0
* @author Seth Proctor
* @author Ludwig Seitz
*/
public class AttributeDesignator implements Evaluatable
{
/**
* The category of the Designator.
*/
private URI category;
/**
* The datatype resolved by this designator
*/
private URI type;
/**
* The attribute id resolved by this designator
*/
private URI id;
/**
* The optional issuer attribute
*/
private URI issuer;
/**
* Throw an error if the resolution doesn't find something
*/
private boolean mustBePresent;
/**
* The XACML version
*/
private int xacmlVersion;
/**
* Backwards compatibility switch that indicates if the
* SubjectCategory was explicit or default.
*/
private boolean withSubjectCategory = false;
/**
* Information where the Attribute Designator has been defined in src (files)
*/
private RuntimeInfo src = null;
/**
* the logger we'll use for all messages
*/
private static final Logger logger =
Logger.getLogger(AttributeDesignator.class.getName());
private static ArrayList<RequiredAttributesModule> requiredAttrModules;
public static void setRequiredAttrModules(ArrayList<RequiredAttributesModule> requiredAttrModules) {
AttributeDesignator.requiredAttrModules = requiredAttrModules;
}
/**
* Creates a new <code>AttributeDesignator</code>.
*
* @param category the category of this designator
* @param type the data type resolved by this designator
* @param id the attribute id looked for by this designator
* @param mustBePresent whether resolution must find a value
* @param issuer the issuer of the values to search for or null if no
* issuer is specified
*
*/
public AttributeDesignator(URI category, URI type, URI id,
boolean mustBePresent, URI issuer) {
this(category, type, id, mustBePresent, issuer,
Constants.XACML_DEFAULT_VERSION, false);
}
/**
* Creates a new <code>AttributeDesignator</code>.
*
* @param category the category of this designator
* @param type the data type resolved by this designator
* @param id the attribute id looked for by this designator
* @param mustBePresent whether resolution must find a value
* @param issuer the issuer of the values to search for or null if no
* issuer is specified
* @param xacmlVersion the XACML version that is used.
* @param withSubjectCategory Backwards compatibility switch that
* indicates if the SubjectCategory is
* explicit or default.
*
*/
public AttributeDesignator(URI category, URI type, URI id,
boolean mustBePresent, URI issuer, int xacmlVersion,
boolean withSubjectCategory) {
this.category = category;
this.type = type;
this.id = id;
this.mustBePresent = mustBePresent;
this.issuer = issuer;
this.xacmlVersion = xacmlVersion;
this.withSubjectCategory = withSubjectCategory;
}
/**
* Creates a new <code>AttributeDesignator</code> based on the DOM
* root of the XML data.
*
* @param root the DOM root of the AttributeDesignatorType XML type
* @param metaData the meta-data associated with the containing policy
*
* @return the designator
*
* @throws ParsingException if the AttributeDesignatorType was invalid
*/
public static AttributeDesignator getInstance(Node root,
PolicyMetaData metaData) throws ParsingException {
URI category = null;
URI type = null;
URI id = null;
URI issuer = null;
boolean mustBePresent = false;
int xacmlVersion = metaData.getXACMLVersion();
boolean withSubjectCategory = false;
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.ATTRIBUTE_DESIGNATOR);
NamedNodeMap attrs = root.getAttributes();
if (root.getNodeType() != Node.ELEMENT_NODE) {
throw new ParsingException("Cannot build a AttributeDesignator"
+ " with this node type: " + root.getClass().getName()
+ (src != null ? src.getLocationMsgForError() : ""));
}
if (root.getLocalName().equals("SubjectAttributeDesignator")) {
if (xacmlVersion > Constants.XACML_VERSION_2_0) {
throw new ParsingException("Can't create a > XACML 2.0"
+ "AttributeDesignator from " + root.getLocalName()
+ (src != null ? src.getLocationMsgForError() : ""));
}
//compatibility code for XACML 2.0
category = Constants.SUBJECT_CAT;
if (attrs != null) {
Node catNode = attrs.getNamedItem("SubjectCategory");
if (catNode != null) {
try {
category = new URI(catNode.getNodeValue());
} catch (URISyntaxException e) {
throw new ParsingException("Error while parsing"
+ "category: " + catNode.getNodeValue()
+ (src != null ? src.getLocationMsgForError() : ""));
}
withSubjectCategory = true;
}
}
} else if (root.getLocalName().equals("ResourceAttributeDesignator")) {
if (xacmlVersion > Constants.XACML_VERSION_2_0) {
throw new ParsingException("Can't create an > XACML 2.0 "
+ "AttributeDesignator from " + root.getLocalName()
+ src.getLocationMsgForError());
}
category = Constants.RESOURCE_CAT;
} else if (root.getLocalName().equals("ActionAttributeDesignator")) {
if (xacmlVersion > Constants.XACML_VERSION_2_0) {
throw new ParsingException("Can't create an > XACML 2.0 "
+ "AttributeDesignator from " + root.getLocalName()
+ (src != null ? src.getLocationMsgForError() : ""));
}
category = Constants.ACTION_CAT;
} else if (root.getLocalName().equals(
"EnvironmentAttributeDesignator")) {
if (xacmlVersion != Constants.XACML_VERSION_2_0) {
throw new ParsingException("Can't create an XACML 2.0 "
+ "AttributeDesignator from " + root.getLocalName()
+ src.getLocationMsgForError());
}
category = Constants.ENVIRONMENT_CAT;
} else {
if (xacmlVersion < Constants.XACML_VERSION_3_0) {
throw new ParsingException("Can't create an XACML "
+ xacmlVersion + " AttributeDesignator from "
+ root.getLocalName()
+ (src != null ? src.getLocationMsgForError() : ""));
}
// there's always a category
try {
category = new URI(
attrs.getNamedItem("Category").getNodeValue());
} catch (Exception e) {
throw new ParsingException("Required Category missing or"
+ " invalid in AttributeDesignator"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
}
try {
// there's always an Id
id = new URI(attrs.getNamedItem("AttributeId").getNodeValue());
} catch (Exception e) {
throw new ParsingException("Required AttributeId missing or"
+ " invalid in AttributeDesignator"
+ src.getLocationMsgForError(), e);
}
try {
// there's always a data type
type = new URI(attrs.getNamedItem("DataType").getNodeValue());
} catch (Exception e) {
throw new ParsingException("Required DataType missing or"
+ " invalid in AttributeDesignator"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
try {
// there might be an issuer
Node node = attrs.getNamedItem("Issuer");
if (node != null) {
issuer = new URI(node.getNodeValue());
}
// there might be a mustBePresent flag
node = attrs.getNamedItem("MustBePresent");
if (node != null) {
if (node.getNodeValue().equals("true")) {
mustBePresent = true;
}
}
} catch (Exception e) {
// this shouldn't ever happen, but in theory something could go
// wrong in the code in this try block
throw new ParsingException("Error parsing AttributeDesignator " +
"optional attributes"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
AttributeDesignator attrDesgn = new AttributeDesignator(category, type,
id, mustBePresent, issuer, xacmlVersion, withSubjectCategory);
if ( src != null ) {
attrDesgn.src = src;
src.setXACMLObject(attrDesgn);
}
return attrDesgn;
}
/**
* Returns the type of attribute that is resolved by this designator.
* While an AD will always return a bag, this method will always return
* the type that is stored in the bag.
*
* @return the attribute type
*/
public URI getType() {
return this.type;
}
/**
* Returns the AttributeId of the values resolved by this designator.
*
* @return identifier for the values to resolve
*/
public URI getId() {
return this.id;
}
/**
* Returns the category for this designator.
*
* @return the category
*/
public URI getCategory() {
return this.category;
}
/**
* Returns the issuer of the values resolved by this designator if
* specified.
*
* @return the attribute issuer or null if unspecified
*/
public URI getIssuer() {
return this.issuer;
}
/**
* Returns whether or not a value is required to be resolved by this
* designator.
*
* @return true if a value is required, false otherwise
*/
public boolean mustBePresent() {
return this.mustBePresent;
}
/**
* Always returns true, since a designator always returns a bag of
* attribute values.
*
* @return true
*/
public boolean returnsBag() {
return true;
}
/**
* Always returns an empty list since designators never have children.
*
* @return an empty <code>List</code>
*/
public List<Expression> getChildren() {
return Expression.EMPTY_LIST; //Collections.<Expression>emptyList();
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
/**
* Evaluates the pre-assigned meta-data against the given context,
* trying to find some matching values.
*
* @param context the representation of the request
*
* @return a result containing a bag either empty because no values were
* found or containing at least one value, or status associated with an
* Indeterminate result
*/
public EvaluationResult evaluate(EvaluationCtx context) {
context.newEvent(this);
EvaluationResult result = null;
// look in the right section for some attribute values
result = context.getAttribute(this.category, this.type, this.id,
this.issuer);
// if the lookup was indeterminate, then we return immediately
if (result.indeterminate()) {
context.closeCurrentEvent(result);
return result;
}
BagAttribute bag = (BagAttribute)(result.getAttributeValue());
if (bag.isEmpty()) {
// if it's empty, this may be an error
if (this.mustBePresent) {
if (logger.isInfoEnabled()) {
logger.info("AttributeDesignator failed to resolve a "
+ "value for a required attribute: "
+ this.id.toString() + " (MustBePresent: " +
mustBePresent + ")");
}
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_MISSING_ATTRIBUTE);
String message = "Couldn't find "
+ "AttributeDesignator attribute";
// Note that there is a bug in the XACML spec. You can't
// specify an identifier without specifying acceptable
// values. Until this is fixed, this code will only
// return the status code, and not any hints about what
// was missing
Set<Attribute> attr = null;
for ( RequiredAttributesModule requAttrMod : requiredAttrModules ) {
attr = requAttrMod.resolveRequiredAttributes(context, this);
if ( attr != null && attr.size() > 0 ) {
break;
}
}
Status status;
if ( attr == null ) {
status = new Status(code, message);
} else {
status = new Status(code, message, new StatusDetail(attr));
}
EvaluationResult evalResult = new EvaluationResult(status);
context.closeCurrentEvent(evalResult);
return evalResult;
}
}
// if we got here the bag wasn't empty, or mustBePresent was false,
// so we just return the result
context.closeCurrentEvent(result);
return result;
}
/**
* Encodes this designator 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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this designator 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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
String tag = "";
if (this.xacmlVersion > Constants.XACML_VERSION_2_0) {
tag = "<AttributeDesignator Category=\"" + this.category.toString()
+ "\" ";
} else {
if (this.category.equals(Constants.RESOURCE_CAT)) {
tag = "<ResourceAttributeDesignator ";
} else if (this.category.equals(Constants.ACTION_CAT)) {
tag = "<ActionAttributeDesignator ";
} else if (this.xacmlVersion == Constants.XACML_VERSION_2_0
&& this.category.equals(Constants.ENVIRONMENT_CAT)) {
tag = "<EnvironmentAttributeDesignator ";
} else {
//For backwards compatibility all unknown categories are
//cast to subject categories.
if (this.withSubjectCategory) {
tag = "<SubjectAttributeDesignator SubjectCategory=\""
+ this.category.toString() + "\" ";
} else {
tag = "<SubjectAttributeDesignator ";
}
}
}
tag += "AttributeId=\"" + this.id.toString() + "\" DataType=\""
+ this.type.toString() + "\"";
if (this.issuer != null) {
tag += " Issuer=\"" + this.issuer.toString() + "\"";
}
if (this.mustBePresent) {
tag += " MustBePresent=\"true\"";
}
tag += "/>";
out.println(indent + tag);
}
}

View File

@ -0,0 +1,401 @@
/*
* @(#)AttributeFactory.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.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.ParsingException;
import com.sun.xacml.UnknownIdentifierException;
import java.net.URI;
import java.util.HashMap;
import java.util.Set;
import org.w3c.dom.Node;
/**
* This is an abstract factory class for creating XACML attribute values.
* There may be any number of factories available in the system, though
* there is always one default factory used by the core code.
*
* @since 1.0
* @author Seth Proctor
* @author Marco Barreno
*/
public abstract class AttributeFactory
{
// the proxy used to get the default factory
private static AttributeFactoryProxy defaultFactoryProxy;
// the map of registered factories
private static HashMap<String, AttributeFactoryProxy> registeredFactories;
/**
* static intialiazer that sets up the default factory proxy and
* registers the standard namespaces
*/
static {
AttributeFactoryProxy proxy = new AttributeFactoryProxy() {
public AttributeFactory getFactory() {
return StandardAttributeFactory.getFactory();
}
};
registeredFactories = new HashMap<String, AttributeFactoryProxy>();
registeredFactories.put(Constants.XACML_1_0_IDENTIFIER, proxy);
registeredFactories.put(Constants.XACML_2_0_IDENTIFIER, proxy);
defaultFactoryProxy = proxy;
}
/**
* Default constructor. Used only by subclasses.
*/
protected AttributeFactory() {
// used only by subclasses
}
/**
* Returns the default factory. Depending on the default factory's
* implementation, this may return a singleton instance or new instances
* with each invokation.
*
* @return the default <code>AttributeFactory</code>
*/
public static final AttributeFactory getInstance() {
return defaultFactoryProxy.getFactory();
}
/**
* Returns a factory based on the given identifier. You may register
* as many factories as you like, and then retrieve them through this
* interface, but a factory may only be registered once using a given
* identifier. By default, the standard XACML 1.0 and 2.0 identifiers
* are regsietered to provide the standard factory.
*
* @param identifier the identifier for a factory
*
* @return an <code>AttributeFactory</code>
*
* @throws UnknownIdentifierException if the given identifier isn't
* registered
*/
public static final AttributeFactory getInstance(String identifier)
throws UnknownIdentifierException
{
AttributeFactoryProxy proxy = registeredFactories.get(identifier);
if (proxy == null) {
throw new UnknownIdentifierException("Uknown AttributeFactory " +
"identifier: " + identifier);
}
return proxy.getFactory();
}
/**
* Sets the default factory. This does not register the factory proxy as
* an identifiable factory.
*
* @param proxy the <code>AttributeFactoryProxy</code> to set as the new
* default factory proxy
*/
public static final void setDefaultFactory(AttributeFactoryProxy proxy) {
defaultFactoryProxy = proxy;
}
/**
* Registers the given factory proxy with the given identifier. If the
* identifier is already used, then this throws an exception. If the
* identifier is not already used, then it will always be bound to the
* given proxy.
*
* @param identifier the identifier for the proxy
* @param proxy the <code>AttributeFactoryProxy</code> to register with
* the given identifier
*
* @throws IllegalArgumentException if the identifier is already used
*/
public static final void registerFactory(String identifier,
AttributeFactoryProxy proxy)
throws IllegalArgumentException
{
synchronized (registeredFactories) {
if (registeredFactories.containsKey(identifier)) {
throw new IllegalArgumentException("Identifier is already " +
"registered as " +
"AttributeFactory: " +
identifier);
}
registeredFactories.put(identifier, proxy);
}
}
/**
* Adds a proxy to the factory, which in turn will allow new attribute
* types to be created using the factory. Typically the proxy is
* provided as an anonymous class that simply calls the getInstance
* methods (or something similar) of some <code>AttributeValue</code>
* class.
*
* @param id the name of the attribute type
* @param proxy the proxy used to create new attributes of the given type
*
* @throws IllegalArgumentException if the given id is already in use
*/
public abstract void addDatatype(String id, AttributeProxy proxy);
/**
* Adds a proxy to the default factory, which in turn will allow new
* attribute types to be created using the factory. Typically the proxy
* is provided as an anonymous class that simply calls the getInstance
* methods (or something similar) of some <code>AttributeValue</code>
* class.
*
* @deprecated As of version 1.2, replaced by
* {@link #addDatatype(String,AttributeProxy)}.
* The new factory system requires you to get a factory
* instance and then call the non-static methods on that
* factory. The static versions of these methods have been
* left in for now, but are slower and will be removed in
* a future version. Note that this operates only on the
* default factory.
*
* @param id the name of the attribute type
* @param proxy the proxy used to create new attributes of the given type
*
* @throws IllegalArgumentException if the given id is already in use
*/
public static void addAttributeProxy(String id, AttributeProxy proxy) {
getInstance().addDatatype(id, proxy);
}
/**
* Returns the datatype identifiers supported by this factory.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public abstract Set<String> getSupportedDatatypes();
/**
* Creates a value based on the given DOM root node. The type of the
* attribute is assumed to be present in the node as an XAML attribute
* named <code>DataType</code>, as is the case with the
* AttributeValueType in the policy schema. The value is assumed to be
* the first child of this node.
*
* @param root the DOM root of an attribute value
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the type in the node isn't
* known to the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public abstract AttributeValue createValue(Node root)
throws UnknownIdentifierException, ParsingException;
/**
* Creates a value based on the given DOM root node. The type of the
* attribute is assumed to be present in the node as an XAML attribute
* named <code>DataType</code>, as is the case with the
* AttributeValueType in the policy schema. The value is assumed to be
* the first child of this node. This uses the default factory.
*
* @deprecated As of version 1.2, replaced by
* {@link #createValue(Node)}.
* The new factory system requires you to get a factory
* instance and then call the non-static methods on that
* factory. The static versions of these methods have been
* left in for now, but are slower and will be removed in
* a future version.
*
* @param root the DOM root of an attribute value
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the type in the node isn't
* known to the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public static AttributeValue createAttribute(Node root)
throws UnknownIdentifierException, ParsingException
{
return getInstance().createValue(root);
}
/**
* Creates a value based on the given DOM root node and data type.
*
* @param root the DOM root of an attribute value
* @param dataType the type of the attribute
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the data type isn't known to
* the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public abstract AttributeValue createValue(Node root, URI dataType)
throws UnknownIdentifierException, ParsingException;
/**
* Creates a value based on the given DOM root node and data type. This
* uses the default factory.
*
* @deprecated As of version 1.2, replaced by
* {@link #createValue(Node,URI)}.
* The new factory system requires you to get a factory
* instance and then call the non-static methods on that
* factory. The static versions of these methods have been
* left in for now, but are slower and will be removed in
* a future version.
*
* @param root the DOM root of an attribute value
* @param dataType the type of the attribute
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the data type isn't known to
* the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public static AttributeValue createAttribute(Node root, URI dataType)
throws UnknownIdentifierException, ParsingException
{
return getInstance().createValue(root, dataType);
}
/**
* Creates a value based on the given DOM root node and data type.
*
* @param root the DOM root of an attribute value
* @param type the type of the attribute
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the type isn't known to
* the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public abstract AttributeValue createValue(Node root, String type)
throws UnknownIdentifierException, ParsingException;
/**
* Creates a value based on the given DOM root node and data type. This
* uses the default factory.
*
* @deprecated As of version 1.2, replaced by
* {@link #createValue(Node,String)}.
* The new factory system requires you to get a factory
* instance and then call the non-static methods on that
* factory. The static versions of these methods have been
* left in for now, but are slower and will be removed in
* a future version.
*
* @param root the DOM root of an attribute value
* @param type the type of the attribute
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the type isn't known to
* the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public static AttributeValue createAttribute(Node root, String type)
throws UnknownIdentifierException, ParsingException
{
return getInstance().createValue(root, type);
}
/**
* Creates a value based on the given data type and text-encoded value.
* Used primarily by code that does an XPath query to get an
* attribute value, and then needs to turn the resulting value into
* an Attribute class.
*
* @param dataType the type of the attribute
* @param value the text-encoded representation of an attribute's value
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the data type isn't known to
* the factory
* @throws ParsingException if the text is invalid or can't be parsed
* by the appropriate proxy
*/
public abstract AttributeValue createValue(URI dataType, String value)
throws UnknownIdentifierException, ParsingException;
/**
* Creates a value based on the given data type and text-encoded value.
* Used primarily by code that does an XPath query to get an
* attribute value, and then needs to turn the resulting value into
* an Attribute class. This uses the default factory.
*
* @deprecated As of version 1.2, replaced by
* {@link #createValue(URI,String)}.
* The new factory system requires you to get a factory
* instance and then call the non-static methods on that
* factory. The static versions of these methods have been
* left in for now, but are slower and will be removed in
* a future version.
*
* @param dataType the type of the attribute
* @param value the text-encoded representation of an attribute's value
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the data type isn't known to
* the factory
* @throws ParsingException if the text is invalid or can't be parsed
* by the appropriate proxy
*/
public static AttributeValue createAttribute(URI dataType, String value)
throws UnknownIdentifierException, ParsingException
{
return getInstance().createValue(dataType, value);
}
}

View File

@ -0,0 +1,58 @@
/*
* @(#)AttributeFactoryProxy.java
*
* Copyright 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 com.sun.xacml.attr;
/**
* A simple proxy interface used to install new
* <code>AttributeFactory</code>s.
*
* @since 1.2
* @author Seth Proctor
*/
public interface AttributeFactoryProxy
{
/**
* Returns an instance of the <code>AttributeFactory</code> for which
* this is a proxy.
*
* @return an <code>AttributeFactory</code> instance
*/
public AttributeFactory getFactory();
}

View File

@ -0,0 +1,80 @@
/*
* @(#)AttributeProxy.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 com.sun.xacml.attr;
import org.w3c.dom.Node;
/**
* Used by the <code>AttributeFactory</code> to create new attributes.
* Typically a new proxy class is created which in turn knows how to create
* a specific kind of attribute, and then this proxy class is installed in
* the <code>AttributeFactory</code>.
*
* @since 1.0
* @author Seth Proctor
*/
public interface AttributeProxy
{
/**
* Tries to create a new <code>AttributeValue</code> based on the given
* DOM root node.
*
* @param root the DOM root of some attribute data
*
* @return an <code>AttributeValue</code> representing the given data
*
* @throws Exception if the data couldn't be used (the exception is
* typically wrapping some other exception)
*/
public AttributeValue getInstance(Node root) throws Exception;
/**
* Tries to create a new <code>AttributeValue</code> based on the given
* String data.
*
* @param value the text form of some attribute data
*
* @return an <code>AttributeValue</code> representing the given data
*
* @throws Exception if the data couldn't be used (the exception is
* typically wrapping some other exception)
*/
public AttributeValue getInstance(String value) throws Exception;
}

View File

@ -0,0 +1,421 @@
/*
* @(#)AttributeSelector.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 com.sun.xacml.attr;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.Indenter;
import com.sun.xacml.ParsingException;
import com.sun.xacml.PolicyMetaData;
import com.sun.xacml.cond.Evaluatable;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.cond.Expression;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* Supports the standard selector functionality in XACML, which uses XPath
* expressions to resolve values from the Request or elsewhere. All selector
* queries are done by <code>AttributeFinderModule</code>s so that it's easy
* to plugin different XPath implementations.
*
* @since 1.0
* @author Seth Proctor
*/
public class AttributeSelector implements Evaluatable
{
// the data type returned by this selector
private URI type;
// the XPath to search
private String contextPath;
// must resolution find something
private boolean mustBePresent;
// the xpath version we've been told to use
private String xpathVersion;
// the policy root, where we get namespace mapping details
private Node policyRoot;
private RuntimeInfo src;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(AttributeSelector.class.getName());
/**
* Creates a new <code>AttributeSelector</code> with no policy root.
*
* @param type the data type of the attribute values this selector
* looks for
* @param contextPath the XPath to query
* @param mustBePresent must resolution find a match
* @param xpathVersion the XPath version to use, which must be a valid
* XPath version string (the identifier for XPath 1.0
* is provided in <code>PolicyMetaData</code>)
*/
public AttributeSelector(URI type, String contextPath,
boolean mustBePresent, String xpathVersion) {
this(type, contextPath, null, mustBePresent, xpathVersion);
}
/**
* Creates a new <code>AttributeSelector</code>.
*
* @param type the data type of the attribute values this selector
* looks for
* @param contextPath the XPath to query
* @param policyRoot the root DOM Element for the policy containing this
* selector, which defines namespace mappings
* @param mustBePresent must resolution find a match
* @param xpathVersion the XPath version to use, which must be a valid
* XPath version string (the identifier for XPath 1.0
* is provided in <code>PolicyMetaData</code>)
*/
public AttributeSelector(URI type, String contextPath, Node policyRoot,
boolean mustBePresent, String xpathVersion) {
this.type = type;
this.contextPath = contextPath;
this.mustBePresent = mustBePresent;
this.xpathVersion = xpathVersion;
this.policyRoot = policyRoot;
}
/**
* Creates a new <code>AttributeSelector</code> based on the DOM root
* of the XML type. Note that as of XACML 1.1 the XPathVersion element
* is required in any policy that uses a selector, so if the
* <code>xpathVersion</code> string is null, then this will throw
* an exception.
*
* @param root the root of the DOM tree for the XML AttributeSelectorType
* XML type
* @param metaData the meta-data associated with the containing policy
*
* @return an <code>AttributeSelector</code>
*
* @throws ParsingException if the AttributeSelectorType was invalid
*/
public static AttributeSelector getInstance(Node root,
PolicyMetaData metaData)
throws ParsingException {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.ATTRIBUTE_SELECTOR);
if (root.getNodeType() != Node.ELEMENT_NODE ||
!root.getLocalName().equals("AttributeSelector")) {
throw new ParsingException("Can't create an AttributeSelector"
+ " from a " + root.getLocalName() + " element"
+ (src != null ? src.getLocationMsgForError() : ""));
}
URI type = null;
String contextPath = null;
boolean mustBePresent = false;
String xpathVersion = metaData.getXPathIdentifier();
// make sure we were given an xpath version
if (xpathVersion == null) {
throw new ParsingException("An XPathVersion is required for "+
"any policies that use selectors"
+ (src != null ? src.getLocationMsgForError() : ""));
}
NamedNodeMap attrs = root.getAttributes();
try {
// there's always a DataType attribute
type = new URI(attrs.getNamedItem("DataType").getNodeValue());
} catch (Exception e) {
throw new ParsingException("Error parsing required DataType " +
"attribute in AttributeSelector"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
try {
// there's always a RequestPath
contextPath =
attrs.getNamedItem("RequestContextPath").getNodeValue();
} catch (Exception e) {
throw new ParsingException("Error parsing required " +
"RequestContextPath attribute in AttributeSelector"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
try {
// there may optionally be a MustBePresent
Node node = attrs.getNamedItem("MustBePresent");
if (node != null)
if (node.getNodeValue().equals("true")) {
mustBePresent = true;
}
} catch (Exception e) {
// this shouldn't happen, since we check the cases, but still...
throw new ParsingException("Error parsing optional attributes "
+ "in AttributeSelector"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
// as of 1.2 we need the root element of the policy so we can get
// the namespace mapping, but in order to leave the APIs unchanged,
// we'll walk up the tree to find the root rather than pass this
// element around through all the code
Node policyRoot = null;
Node node = root.getParentNode();
while ((node != null) && (node.getNodeType() == Node.ELEMENT_NODE)) {
policyRoot = node;
node = node.getParentNode();
}
// create the new selector
AttributeSelector attrSelector = new AttributeSelector(type,
contextPath, policyRoot, mustBePresent, xpathVersion);
if ( src != null ) {
attrSelector.src = src;
src.setXACMLObject(attrSelector);
}
return attrSelector;
}
/**
* Returns the data type of the attribute values that this selector
* will resolve
*
* @return the data type of the values found by this selector
*/
public URI getType() {
return this.type;
}
/**
* Returns the XPath query used to resolve attribute values.
*
* @return the XPath query
*/
public String getContextPath() {
return this.contextPath;
}
/**
* Returns whether or not a value is required to be resolved by this
* selector.
*
* @return true if a value is required, false otherwise
*/
public boolean mustBePresent() {
return this.mustBePresent;
}
/**
* Always returns true, since a selector always returns a bag of
* attribute values.
*
* @return true
*/
public boolean returnsBag() {
return true;
}
/**
* Always returns an empty list since selectors never have children.
*
* @return an empty <code>List</code>
*/
public List<Expression> getChildren() {
return Expression.EMPTY_LIST;
}
/**
* Returns the XPath version this selector is supposed to use. This is
* typically provided by the defaults section of the policy containing
* this selector.
*
* @return the XPath version
*/
public String getXPathVersion() {
return this.xpathVersion;
}
/**
* Returns the policy root node, from where we get namespace
* mapping details.
*
* @return a <code>Node</code> object
*/
public Node getPolicyRoot() {
return this.policyRoot;
}
public RuntimeInfo getRuntimeInfo() {
return src;
}
/**
* Invokes the <code>AttributeFinder</code> used by the given
* <code>EvaluationCtx</code> to try to resolve an attribute value. If
* the selector is defined with MustBePresent as true, then failure
* to find a matching value will result in Indeterminate, otherwise it
* will result in an empty bag. To support the basic selector
* functionality defined in the XACML specification, use a finder that
* has only the <code>SelectorModule</code> as a module that supports
* selector finding.
*
* @param context representation of the request to search
*
* @return a result containing a bag either empty because no values were
* found or containing at least one value, or status associated with an
* Indeterminate result
*/
public EvaluationResult evaluate(EvaluationCtx context) {
context.newEvent(this);
// query the context
EvaluationResult result = context.getAttribute(this.contextPath,
this.policyRoot,
this.type,
this.xpathVersion);
// see if we got anything
if (! result.indeterminate()) {
BagAttribute bag = (BagAttribute)(result.getAttributeValue());
// see if it's an empty bag
if (bag.isEmpty()) {
// see if this is an error or not
if (this.mustBePresent) {
// this is an error
// if (logger.isLoggable(Level.INFO)) {
logger.info("AttributeSelector failed to resolve a " +
"value for a required attribute: " +
this.contextPath);
// }
ArrayList<String> code = new ArrayList<String>();
code.add(Status.STATUS_MISSING_ATTRIBUTE);
String message = "couldn't resolve XPath expression " +
this.contextPath + " for type " + this.type.toString();
EvaluationResult evaluationResult
= new EvaluationResult(new Status(code, message));
context.closeCurrentEvent(evaluationResult);
return evaluationResult;
}
// return the empty bag
context.closeCurrentEvent();
return result;
}
// return the values
context.closeCurrentEvent(result);
return result;
}
// return the error
context.closeCurrentEvent(result);
return result;
}
/**
* Encodes this selector 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
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this selector 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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
String tag = "<AttributeSelector RequestContextPath=\""
+ this.contextPath + "\" DataType=\""
+ this.type.toString() + "\"";
if (this.mustBePresent) {
tag += " MustBePresent=\"true\"";
}
tag += "/>";
out.println(indent + tag);
}
}

View File

@ -0,0 +1,254 @@
/*
* @(#)AttributeValue.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 com.sun.xacml.attr;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.Indenter;
import com.sun.xacml.cond.Evaluatable;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.cond.Expression;
import com.sun.xacml.debug.RuntimeInfo;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.List;
/**
* The base type for all datatypes used in a policy or request/response,
* this abstract class represents a value for a given attribute type.
* All the required types defined in the XACML specification are
* provided as instances of <code>AttributeValue<code>s. If you want to
* provide a new type, extend this class and implement the
* <code>equals(Object)</code> and <code>hashCode</code> methods from
* <code>Object</code>, which are used for equality checking.
*
* @since 1.0
* @author Seth Proctor
*/
public abstract class AttributeValue implements Evaluatable
{
// the type of this attribute
private URI type;
private RuntimeInfo src;
/**
* Constructor that takes the specific attribute type.
*
* @param type the attribute's type
*/
protected AttributeValue(URI type) {
this.type = type;
}
/**
* Returns the type of this attribute value. By default this always
* returns the type passed to the constructor.
*
* @return the attribute's type
*/
public URI getType() {
return this.type;
}
/**
* Returns whether or not this value is actually a bag of values. This
* is a required interface from <code>Expression</code>, but the
* more meaningful <code>isBag</code> method is used by
* <code>AttributeValue</code>s, so this method is declared as final
* and calls the <code>isBag</code> method for this value.
*
* @return true if this is a bag of values, false otherwise
*/
public final boolean returnsBag() {
return isBag();
}
/**
* Returns whether or not this value is actually a bag of values. This
* is a required interface from <code>Evaluatable</code>, but the
* more meaningful <code>isBag</code> method is used by
* <code>AttributeValue</code>s, so this method is declared as final
* and calls the <code>isBag</code> method for this value.
*
*
* @deprecated As of 2.0, you should use the <code>returnsBag</code>
* method from the super-interface <code>Expression</code>.
*
* @return true if this is a bag of values, false otherwise
*/
public final boolean evaluatesToBag() {
return isBag();
}
/**
* Always returns an empty list since values never have children.
*
* @return an empty <code>List</code>
*/
public List<Expression> getChildren() {
return Expression.EMPTY_LIST;
}
/**
* Returns whether or not this value is actually a bag of values. By
* default this returns <code>false</code>. Typically, only the
* <code>BagAttribute</code> should ever override this to return
* <code>true</code>.
*
* @return true if this is a bag of values, false otherwise
*/
public boolean isBag() {
return false;
}
/**
* Implements the required interface from <code>Evaluatable</code>.
* Since there is nothing to evaluate in an attribute value, the default
* result is just this instance. Override this method if you want
* special behavior, like a dynamic value.
*
* @param context the representation of the request
*
* @return a successful evaluation containing this value
*/
public EvaluationResult evaluate(EvaluationCtx context) {
return new EvaluationResult(this);
}
/**
* Encodes the value in a form suitable for including in XML data like
* a request or an obligation. This must return a value that could in
* turn be used by the factory to create a new instance with the same
* value.
*
* @return a <code>String</code> form of the value
*/
public abstract String encode();
/**
* Encodes this <code>AttributeValue</code> into its XML representation
* and writes this encoding to the given <code>OutputStream</code> with
* no indentation. This will always produce the version used in a
* policy rather than that used in a request, so this is equivalent
* to calling <code>encodeWithTags(true)</code> and then stuffing that
* into a stream.
*
* @param output a stream into which the XML-encoded data is written
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName)
throws UnsupportedEncodingException {
encode(output, charsetName, new Indenter(0));
}
/**
* Encodes this <code>AttributeValue</code> into its XML representation
* and writes this encoding to the given <code>OutputStream</code> with
* indentation. This will always produce the version used in a
* policy rather than that used in a request, so this is equivalent
* to calling <code>encodeWithTags(true)</code> and then stuffing that
* into a stream.
*
* @param output a stream into which the XML-encoded data is written
* @param charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
out.println(indenter.makeString() + encodeWithTags(true));
}
/**
* Encodes the value and includes the AttributeValue XML tags so that
* the resulting string can be included in a valid XACML policy or
* Request/Response. The <code>boolean</code> parameter lets you include
* the DataType attribute, which is required in a policy but not allowed
* in a Request or Response.
*
* @param includeType include the DataType XML attribute if
* <code>true</code>, exclude if <code>false</code>
*
* @return a <code>String</code> encoding including the XML tags
*/
public String encodeWithTags(boolean includeType) {
if (includeType) {
return "<AttributeValue DataType=\"" + this.type.toString() + "\">"
+ encode() + "</AttributeValue>";
}
return "<AttributeValue>" + encode() + "</AttributeValue>";
}
/**
* defines if this attribute is dynamic, i.e., if it has to be evaluated at runtime
* @return
*/
public boolean isDynamic() {
return false;
}
public RuntimeInfo getRuntimeInfo() {
return this.src;
}
public void setSrcLocFromFactory(RuntimeInfo src) {
this.src = src;
}
}

View File

@ -0,0 +1,265 @@
/*
* @(#)BagAttribute.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 com.sun.xacml.attr;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Represents a bag used in the XACML spec as return values from functions
* and designators/selectors that provide more than one value. All values in
* the bag are of the same type, and the bag may be empty. The bag is
* immutable, although its contents may not be.
* <p>
* NOTE: This is the one standard attribute type that can't be created from
* the factory, since you can't have this in an XML block (it is used only
* in return values & dynamic inputs). I think this is right, but we may need
* to add some functionality to let this go into the factory.
*
* @since 1.0
* @author Seth Proctor
* @author Steve Hanna
*/
public class BagAttribute extends AttributeValue
{
// The Collection of AttributeValues that this object encapsulates
private Collection<AttributeValue> bag;
/**
* Creates a new <code>BagAttribute</code> that represents
* the <code>Collection</code> of <code>AttributeValue</code>s supplied.
* If the set is null or empty, then the new bag is empty.
*
* @param type the data type of all the attributes in the set
* @param bag a <code>Collection</code> of <code>AttributeValue</code>s
*/
public BagAttribute(URI type, Collection<AttributeValue> bag) {
super(type);
if (type == null) {
throw new IllegalArgumentException("Bags require a non-null " +
"type be provided");
}
// see if the bag is empty/null
if ((bag == null) || (bag.size() == 0)) {
// empty bag
this.bag = new ArrayList<AttributeValue>();
} else {
// go through the collection to make sure it's a valid bag
Iterator<AttributeValue> it = bag.iterator();
while (it.hasNext()) {
AttributeValue attr = it.next();
// a bag cannot contain other bags, so make sure that each
// value isn't actually another bag
if (attr.isBag()) {
throw new IllegalArgumentException("bags cannot contain " +
"other bags");
}
// make sure that they're all the same type
if (! type.equals(attr.getType())) {
throw new
IllegalArgumentException("Bag items must all be of " +
"the same type");
}
}
// if we get here, then they're all the same type
this.bag = bag;
}
}
/**
* Overrides the default method to always return true.
*
* @return a value of true
*/
public boolean isBag() {
return true;
}
/**
* Convenience function that returns a bag with no elements
*
* @param type the types contained in the bag
*
* @return a new empty bag
*/
public static BagAttribute createEmptyBag(URI type) {
return new BagAttribute(type, null);
}
/**
* A convenience function that returns whether or not the bag is empty
* (ie, whether or not the size of the bag is zero)
*
* @return whether or not the bag is empty
*/
public boolean isEmpty() {
return (this.bag.size() == 0);
}
/**
* Returns the number of elements in this bag
*
* @return the number of elements in this bag
*/
public int size() {
return this.bag.size();
}
/**
* Returns true if this set contains the specified value. More formally,
* returns true if and only if this bag contains a value v such that
* (value==null ? v==null : value.equals(v)). Note that this will only
* work correctly if the <code>AttributeValue</code> has overridden the
* <code>equals</code> method.
*
* @param value the value to look for
*
* @return true if the value is in the bag
*/
public boolean contains(AttributeValue value) {
return this.bag.contains(value);
}
/**
* Returns true if this bag contains all of the values of the specified bag.
* Note that this will only work correctly if the
* <code>AttributeValue</code> type contained in the bag has overridden
* the <code>equals</code> method.
*
* @param bag the bag to compare
*
* @return true if the input is a subset of this bag
*/
public boolean containsAll(BagAttribute bag) {
return this.bag.containsAll(bag.bag);
}
/**
* Returns an iterator over the bag.
*
* @return The iterator.
*/
public Iterator<AttributeValue> iterator() {
return new ImmutableIterator(this.bag.iterator());
}
/**
* Returns an iterator over the bag.
*
* @return The iterator.
*/
public Iterable<AttributeValue> iterable() {
return this.bag;
}
/**
* This is a version of Iterator that overrides the <code>remove</code>
* method so that items can't be taken out of the bag.
*/
private static class ImmutableIterator implements Iterator<AttributeValue> {
// the iterator we're wrapping
private Iterator<AttributeValue> iterator;
/**
* Create a new ImmutableIterator
*
* @param iterator The iterator that shall be made immutable.
*/
public ImmutableIterator(Iterator<AttributeValue> iterator) {
this.iterator = iterator;
}
/**
* Standard hasNext method
*
* @return true of this iterator has a next element, false otherwise.
*/
public boolean hasNext() {
return this.iterator.hasNext();
}
/**
* Standard next method
*
* @return The next Object pointed to by the iterator.
*
* @throws NoSuchElementException
*/
public AttributeValue next() throws NoSuchElementException {
return this.iterator.next();
}
/**
* Makes sure that no one can remove any elements from the bag
*
* @throws UnsupportedOperationException
*/
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
}
/**
* Because a bag cannot be included in a request/response or a
* policy, this will always throw an
* <code>UnsupportedOperationException</code>.
*
* @return The String that would encode this bag.
*/
public String encode() {
throw new UnsupportedOperationException("Bags cannot be encoded");
}
}

View File

@ -0,0 +1,379 @@
/*
* @(#)Base64.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 com.sun.xacml.attr;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
/**
* Class that knows how to encode and decode Base64 values. Base64
* Content-Transfer-Encoding rules are defined in Section 6.8 of IETF RFC 2045
* <i>Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet
* Message Bodies</i>, available at <a
* href="ftp://ftp.isi.edu/in-notes/rfc2045.txt">
* <code>ftp://ftp.isi.edu/in-notes/rfc2045.txt</code></a>.
* <p>
* All methods of this class are static and thread-safe.
*
* @since 1.0
* @author Anne Anderson
*/
class Base64
{
/*
* ASCII white-space characters. These are the ones recognized by the
* C and Java language [pre-processors].
*/
private static final char SPACE = 0x20; /* space, or blank, character */
private static final char ETX = 0x04; /* end-of-text character */
private static final char VTAB = 0x0b; /* vertical tab character */
private static final char FF = 0x0c; /* form-feed character */
private static final char HTAB = 0x09; /* horizontal tab character */
private static final char LF = 0x0a; /* line feed character */
private static final char ALTLF = 0x13; /* line feed on some systems */
private static final char CR = 0x0d; /* carriage-return character */
/*
* String used for BASE64 encoding and decoding.
*
* For index values 0-63, the character at each index is the Base-64
* encoded value of the index value. Index values beyond 63 are never
* referenced during encoding, but are used in this implementation to
* help in decoding. The character at index 64 is the Base64 pad
* character '='.
*
* Charaters in index positions 0-64 MUST NOT be moved or altered, as
* this will break the implementation.
*
* The characters after index 64 are white space characters that should be
* ignored in Base64-encoded input strings while doing decoding. Note that
* the white-space character set should include values used on various
* platforms, since a Base64-encoded value may have been generated on a
* non-Java platform. The values included here are those used in Java and
* in C.
*
* The white-space character set may be modified without affecting the
* implementation of the encoding algorithm.
*/
private static final String BASE64EncodingString =
"ABCDEFGHIJ"
+ "KLMNOPQRST"
+ "UVWXYZabcd"
+ "efghijklmn"
+ "opqrstuvwx"
+ "yz01234567"
+ "89+/"
+ "="
+ SPACE + ETX + VTAB + FF + HTAB + LF + ALTLF + CR;
// Index of pad character in Base64EncodingString
private static final int PAD_INDEX = 64;
/*
* The character in Base64EncodingString with the maximum
* character value in Unicode.
*/
private static final int MAX_BASE64_CHAR = 'z';
/*
* Array for mapping encoded characters to decoded values.
* This array is initialized when needed by calling
* initDecodeArray(). Only includes entries up to
* MAX_BASE64_CHAR.
*/
private static int [] Base64DecodeArray = null;
/*
* State values used for decoding a quantum of four encoded input
* characters as follows.
*
* Initial state: NO_CHARS_DECODED
* NO_CHARS_DECODED: no characters have been decoded
* on encoded char: decode char into output quantum;
* new state: ONE_CHAR_DECODED
* otherwise: Exception
* ONE_CHAR_DECODED: one character has been decoded
* on encoded char: decode char into output quantum;
* new state: TWO_CHARS_DECODED
* otherwise: Exception
* TWO_CHARS_DECODED: two characters have been decoded
* on encoded char: decode char into output quantum;
* new state: THREE_CHARS_DECODED
* on pad: write quantum byte 0 to output;
* new state: PAD_THREE_READ
* THREE_CHARS_DECODED: three characters have been decoded
* on encoded char: decode char into output quantum;
* write quantum bytes 0-2 to output;
* new state: NO_CHARS_DECODED
* on pad: write quantum bytes 0-1 to output;
* new state: PAD_FOUR_READ
* PAD_THREE_READ: pad character has been read as 3rd of 4 chars
* on pad: new state: PAD_FOUR_READ
* otherwise: Exception
* PAD_FOUR_READ: pad character has been read as 4th of 4 char
* on any char: Exception
*
* The valid terminal states are NO_CHARS_DECODED and PAD_FOUR_READ.
*/
private static final int NO_CHARS_DECODED = 0;
private static final int ONE_CHAR_DECODED = 1;
private static final int TWO_CHARS_DECODED = 2;
private static final int THREE_CHARS_DECODED = 3;
private static final int PAD_THREE_READ = 5;
private static final int PAD_FOUR_READ = 6;
/**
* The maximum number of groups that should be encoded
* onto a single line (so we don't exceed 76 characters
* per line).
*/
private static final int MAX_GROUPS_PER_LINE = 76/4;
/**
* Encodes the input byte array into a Base64-encoded
* <code>String</code>. The output <code>String</code>
* has a CR LF (0x0d 0x0a) after every 76 bytes, but
* not at the end.
* <p>
* <b>WARNING</b>: If the input byte array is modified
* while encoding is in progress, the output is undefined.
*
* @param binaryValue the byte array to be encoded
*
* @return the Base64-encoded <code>String</code>
*/
public static String encode(byte[] binaryValue) {
int binaryValueLen = binaryValue.length;
// Estimated output length (about 1.4x input, due to CRLF)
int maxChars = (binaryValueLen * 7) / 5;
// Buffer for encoded output
StringBuffer sb = new StringBuffer(maxChars);
int groupsToEOL = MAX_GROUPS_PER_LINE;
// Convert groups of 3 input bytes, with pad if < 3 in final
for (int binaryValueNdx = 0; binaryValueNdx < binaryValueLen;
binaryValueNdx += 3) {
// Encode 1st 6-bit group
int group1 = (binaryValue[binaryValueNdx] >> 2) & 0x3F;
sb.append(BASE64EncodingString.charAt(group1));
// Encode 2nd 6-bit group
int group2 = (binaryValue[binaryValueNdx] << 4) & 0x030;
if ((binaryValueNdx+1) < binaryValueLen) {
group2 = group2
| ((binaryValue[binaryValueNdx+1] >> 4) & 0xF);
}
sb.append(BASE64EncodingString.charAt(group2));
// Encode 3rd 6-bit group
int group3;
if ((binaryValueNdx+1) < binaryValueLen) {
group3 = (binaryValue[binaryValueNdx+1] << 2) & 0x03C;
if ((binaryValueNdx+2) < binaryValueLen) {
group3 = group3
| ((binaryValue[binaryValueNdx+2] >> 6) & 0x3);
}
} else {
group3 = PAD_INDEX;
}
sb.append(BASE64EncodingString.charAt(group3));
// Encode 4th 6-bit group
int group4;
if ((binaryValueNdx+2) < binaryValueLen) {
group4 = binaryValue[binaryValueNdx+2] & 0x3F;
} else {
group4 = PAD_INDEX;
}
sb.append(BASE64EncodingString.charAt(group4));
// After every MAX_GROUPS_PER_LINE groups, insert CR LF.
// Unless this is the final line, in which case we skip that.
groupsToEOL = groupsToEOL - 1;
if (groupsToEOL == 0) {
groupsToEOL = MAX_GROUPS_PER_LINE;
if ((binaryValueNdx+3) <= binaryValueLen) {
sb.append(CR);
sb.append(LF);
}
}
}
return sb.toString();
}
/**
* Initializes Base64DecodeArray, if this hasn't already been
* done.
*/
private static synchronized void initDecodeArray() {
if (Base64DecodeArray != null) {
return;
}
int [] ourArray = new int [MAX_BASE64_CHAR+1];
for (int i = 0; i <= MAX_BASE64_CHAR; i++) {
ourArray[i] = BASE64EncodingString.indexOf(i);
}
Base64DecodeArray = ourArray;
}
/**
* Decodes a Base64-encoded <code>String</code>. The result
* is returned in a byte array that should match the original
* binary value (before encoding). Whitespace characters
* in the input <code>String</code> are ignored.
* <p>
* If the <code>ignoreBadChars</code> parameter is
* <code>true</code>, characters that are not allowed
* in a BASE64-encoded string are ignored. Otherwise,
* they cause an <code>IOException</code> to be raised.
*
* @param encoded a <code>String</code> containing a
* Base64-encoded value
* @param ignoreBadChars If <code>true</code>, bad characters
* are ignored. Otherwise, they cause
* an <code>IOException</code> to be
* raised.
*
* @return a byte array containing the decoded value
*
* @throws IOException if the input <code>String</code> is not
* a valid Base64-encoded value
*/
public static byte[] decode(String encoded, boolean ignoreBadChars)
throws IOException
{
int encodedLen = encoded.length();
int maxBytes = (encodedLen/4)*3; /* Maximum possible output bytes */
ByteArrayOutputStream ba = /* Buffer for decoded output */
new ByteArrayOutputStream(maxBytes);
byte[] quantum = new byte[3]; /* one output quantum */
// ensure Base64DecodeArray is initialized
initDecodeArray();
/*
* Every 4 encoded characters in input are converted to 3 bytes of
* output. This is called one "quantum". Each encoded character is
* mapped to one 6-bit unit of the output. Whitespace characters in
* the input are passed over; they are not included in the output.
*/
int state = NO_CHARS_DECODED;
for (int encodedNdx = 0; encodedNdx < encodedLen; encodedNdx++) {
// Turn encoded char into decoded value
int encodedChar = encoded.charAt(encodedNdx);
int decodedChar;
if (encodedChar > MAX_BASE64_CHAR) {
decodedChar = -1;
} else {
decodedChar = Base64DecodeArray[encodedChar];
}
// Handle white space and invalid characters
if (decodedChar == -1) {
if (ignoreBadChars) {
continue;
}
throw new IOException("Invalid character");
}
if (decodedChar > PAD_INDEX) { /* whitespace */
continue;
}
// Handle valid characters
switch (state) {
case NO_CHARS_DECODED:
if (decodedChar == PAD_INDEX) {
throw new IOException("Pad character in invalid position");
}
quantum[0] = (byte) ((decodedChar << 2) & 0xFC);
state = ONE_CHAR_DECODED;
break;
case ONE_CHAR_DECODED:
if (decodedChar == PAD_INDEX) {
throw new IOException("Pad character in invalid position");
}
quantum[0] = (byte) (quantum[0] | ((decodedChar >> 4) & 0x3));
quantum[1] = (byte) ((decodedChar << 4) & 0xF0);
state = TWO_CHARS_DECODED;
break;
case TWO_CHARS_DECODED:
if (decodedChar == PAD_INDEX) {
ba.write(quantum, 0, 1);
state = PAD_THREE_READ;
} else {
quantum[1] =
(byte) (quantum[1] | ((decodedChar >> 2) & 0x0F));
quantum[2] = (byte) ((decodedChar << 6) & 0xC0);
state = THREE_CHARS_DECODED;
}
break;
case THREE_CHARS_DECODED:
if (decodedChar == PAD_INDEX) {
ba.write(quantum, 0, 2);
state = PAD_FOUR_READ;
} else {
quantum[2] = (byte) (quantum[2] | decodedChar);
ba.write(quantum, 0, 3);
state = NO_CHARS_DECODED;
}
break;
case PAD_THREE_READ:
if (decodedChar != PAD_INDEX) {
throw new IOException("Missing pad character");
}
state = PAD_FOUR_READ;
break;
case PAD_FOUR_READ:
throw new IOException("Invalid input follows pad character");
}
}
// Test valid terminal states
if (state != NO_CHARS_DECODED && state != PAD_FOUR_READ) {
throw new IOException("Invalid sequence of input characters");
}
return ba.toByteArray();
}
}

View File

@ -0,0 +1,251 @@
/*
* @(#)Base64BinaryAttribute.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 com.sun.xacml.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.ParsingException;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import org.w3c.dom.Node;
/**
* Representation of an xsi:base64Binary value. This class supports parsing
* xsi:base64Binary values. All objects of this class are immutable and
* all methods of the class are thread-safe.
*
* @since 1.0
* @author Steve Hanna
*/
public class Base64BinaryAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.BASE64BINARY;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* The actual binary value that this object represents.
*/
private byte [] value;
/**
* The value returned by toString(). Cached, but only
* generated if needed.
*/
private String strValue;
/**
* Creates a new <code>Base64BinaryAttribute</code> that represents
* the byte [] value supplied.
*
* @param value the <code>byte []</code> value to be represented
*/
public Base64BinaryAttribute(byte [] value) {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
// This will throw a NullPointerException if value == null.
// That's what we want in that case.
this.value = (byte[])value.clone();
}
/**
* Returns a new <code>Base64BinaryAttribute</code> that represents
* the xsi:base64Binary at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>Base64BinaryAttribute</code> representing the
* appropriate value
* @exception ParsingException if a parsing error occurs
*/
public static Base64BinaryAttribute getInstance(Node root)
throws ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a Base64BinaryAttribute");
}
/**
* Returns a new <code>Base64BinaryAttribute</code> that represents
* the xsi:base64Binary value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>Base64BinaryAttribute</code> representing the
* desired value
* @exception ParsingException if a parsing error occurs
*/
public static Base64BinaryAttribute getInstance(String value)
throws ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "Base64BinaryAttribute from null input");
}
byte [] bytes = null;
try {
bytes = Base64.decode(value, false);
} catch (IOException e) {
throw new ParsingException("Couldn't parse purported " +
"Base64 string: " + value, e);
}
return new Base64BinaryAttribute(bytes);
}
/**
* Returns the <code>byte []</code> value represented by this object.
* Note that this value is cloned before returning to prevent
* unauthorized modifications.
*
* @return the <code>byte []</code> value
*/
public byte [] getValue() {
return (byte[])this.value.clone();
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof Base64BinaryAttribute)) {
return false;
}
Base64BinaryAttribute other = (Base64BinaryAttribute)o;
return Arrays.equals(this.value, other.value);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
int code = this.value[0];
for (int i = 1; i < this.value.length; i++) {
code *= 31;
code += this.value[i];
}
return code;
}
/**
* Make the String representation of this object.
*
* @return the String representation
*/
private String makeStringRep() {
return Base64.encode(this.value);
}
/**
* Returns a String representation.
*
* @return the String representation
*/
public String toString() {
if (this.strValue == null) {
this.strValue = makeStringRep();
}
return "Base64BinaryAttribute: [" + Constants.nl
+ this.strValue + "]" + Constants.nl;
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
if (this.strValue == null) {
this.strValue = makeStringRep();
}
return this.strValue;
}
}

View File

@ -0,0 +1,267 @@
/*
* @(#)BaseAttributeFactory.java
*
* Copyright 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 com.sun.xacml.attr;
import com.sun.xacml.ParsingException;
import com.sun.xacml.UnknownIdentifierException;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.w3c.dom.Node;
/**
* This is a basic implementation of <code>AttributeFactory</code>. It
* implements the insertion and retrieval methods, but doesn't actually
* setup the factory with any datatypes.
* <p>
* Note that while this class is thread-safe on all creation methods, it
* is not safe to add support for a new datatype while creating an instance
* of a value. This follows from the assumption that most people will
* initialize these factories up-front, and then start processing without
* ever modifying the factories. If you need these mutual operations to
* be thread-safe, then you should write a wrapper class that implements
* the right synchronization.
*
* @since 1.2
* @author Seth Proctor
*/
public class BaseAttributeFactory extends AttributeFactory
{
// the map of proxies
private HashMap<String, AttributeProxy> attributeMap;
/**
* Default constructor.
*/
public BaseAttributeFactory() {
this.attributeMap = new HashMap<String, AttributeProxy>();
}
/**
* Constructor that configures this factory with an initial set of
* supported datatypes.
*
* @param attributes a <code>Map</code> of <code>String</code>s to
* </code>AttributeProxy</code>s
*
* @throws IllegalArgumentException if any elements of the Map are not
* </code>AttributeProxy</code>s
*/
public BaseAttributeFactory(Map<String, AttributeProxy> attributes) {
this.attributeMap = new HashMap<String, AttributeProxy>();
Iterator<String> it = attributes.keySet().iterator();
while (it.hasNext()) {
try {
String id = it.next();
AttributeProxy proxy = attributes.get(id);
this.attributeMap.put(id, proxy);
} catch (ClassCastException cce) {
throw new IllegalArgumentException("an element of the map " +
"was not an instance of " +
"AttributeProxy");
}
}
}
/**
* Adds a proxy to the factory, which in turn will allow new attribute
* types to be created using the factory. Typically the proxy is
* provided as an anonymous class that simply calls the getInstance
* methods (or something similar) of some <code>AttributeValue</code>
* class.
*
* @param id the name of the attribute type
* @param proxy the proxy used to create new attributes of the given type
*/
public void addDatatype(String id, AttributeProxy proxy) {
// make sure this doesn't already exist
if (this.attributeMap.containsKey(id)) {
throw new IllegalArgumentException("datatype already exists");
}
this.attributeMap.put(id, proxy);
}
/**
* Returns the datatype identifiers supported by this factory.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public Set<String> getSupportedDatatypes() {
return Collections.unmodifiableSet(this.attributeMap.keySet());
}
/**
* Creates a value based on the given DOM root node. The type of the
* attribute is assumed to be present in the node as an XACML attribute
* named <code>DataType</code>, as is the case with the
* AttributeValueType in the policy schema. The value is assumed to be
* the first child of this node.
*
* @param root the DOM root of an attribute value
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the type in the node isn't
* known to the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public AttributeValue createValue(Node root)
throws UnknownIdentifierException, ParsingException {
if (root.getNodeType() != Node.ELEMENT_NODE ||
root.getAttributes().getNamedItem("DataType") == null) {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.ATTRIBUTE_VALUE);
String message = "";
if ( root.getNodeType() != Node.ELEMENT_NODE ) {
message = ": received element is not a node (" + root.toString() + ")";
} else if ( root.getAttributes().getNamedItem("DataType") == null) {
message = ": missing attribute \"DataType\"";
}
throw new ParsingException("Error while parsing AttributeValue" + message +
( src == null ? "" : src.getLocationMsgForError()));
}
Node node = root.getAttributes().getNamedItem("DataType");
return createValue(root, node.getNodeValue());
}
/**
* Creates a value based on the given DOM root node and data type.
*
* @param root the DOM root of an attribute value
* @param dataType the type of the attribute
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the data type isn't known to
* the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public AttributeValue createValue(Node root, URI dataType)
throws UnknownIdentifierException, ParsingException
{
return createValue(root, dataType.toString());
}
/**
* Creates a value based on the given DOM root node and data type.
*
* @param root the DOM root of an attribute value
* @param type the type of the attribute
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the type isn't known to
* the factory
* @throws ParsingException if the node is invalid or can't be parsed
* by the appropriate proxy
*/
public AttributeValue createValue(Node root, String type)
throws UnknownIdentifierException, ParsingException
{
AttributeProxy proxy = (AttributeProxy)(this.attributeMap.get(type));
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.ATTRIBUTE_VALUE);
if (proxy != null) {
try {
AttributeValue val = proxy.getInstance(root);
if ( src != null ) {
val.setSrcLocFromFactory(src);
src.setXACMLObject(val);
}
return val;
} catch (Exception e) {
throw new ParsingException("couldn't create " + type
+ " attribute based on DOM node"
+ (src != null ? src.getLocationMsgForError() : ""), e);
}
}
throw new UnknownIdentifierException("Attributes of type " + type
+ " aren't supported."
+ (src != null ? src.getLocationMsgForError() : ""));
}
/**
* Creates a value based on the given data type and text-encoded value.
* Used primarily by code that does an XPath query to get an
* attribute value, and then needs to turn the resulting value into
* an Attribute class.
*
* @param dataType the type of the attribute
* @param value the text-encoded representation of an attribute's value
*
* @return a new <code>AttributeValue</code>
*
* @throws UnknownIdentifierException if the data type isn't known to
* the factory
* @throws ParsingException if the text is invalid or can't be parsed
* by the appropriate proxy
*/
public AttributeValue createValue(URI dataType, String value)
throws UnknownIdentifierException, ParsingException
{
String type = dataType.toString();
AttributeProxy proxy = (AttributeProxy)(this.attributeMap.get(type));
if (proxy != null) {
try {
return proxy.getInstance(value);
} catch (Exception e) {
throw new ParsingException("couldn't create " + type
+ " attribute from input: " + value, e);
}
}
throw new UnknownIdentifierException("Attributes of type " + type
+ " aren't supported.");
}
}

View File

@ -0,0 +1,308 @@
/*
* @(#)BooleanAttribute.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 com.sun.xacml.attr;
import com.sun.xacml.ParsingException;
import java.net.URI;
import org.w3c.dom.Node;
/**
* Representation of an xs:boolean value. This class supports parsing
* xs:boolean values. All objects of this class are immutable and
* all methods of the class are thread-safe.
*
* @since 1.0
* @author Marco Barreno
* @author Steve Hanna
*/
public class BooleanAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier = TypeIdentifierConstants.BOOLEAN;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Single instance of BooleanAttribute that represents true.
* Initialized by the static initializer below.
*/
private static BooleanAttribute trueInstance;
/**
* Single instance of BooleanAttribute that represents false.
* Initialized by the static initializer below.
*/
private static BooleanAttribute falseInstance;
/**
* TODO hack? required for null value for defining missing
* attributes in the statusDetail
*/
private static BooleanAttribute invalidInstance;
/**
* Static initializer that initializes many static fields.
* <p>
* It is possible identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
trueInstance = new BooleanAttribute(true);
falseInstance = new BooleanAttribute(false);
invalidInstance = new BooleanAttribute();
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* The actual boolean value that this object represents.
*/
private boolean value;
private boolean valid = true;
/**
* Creates a new <code>BooleanAttribute</code> that represents
* the boolean value supplied.
* <p>
* This constructor is private because it should not be used by
* anyone other than the static initializer in this class.
* Instead, please use one of the getInstance methods, which
* will ensure that only two BooleanAttribute objects are created,
* thus avoiding excess object creation.
*/
protected BooleanAttribute(boolean value) {
super(identifierURI);
this.value = value;
}
private BooleanAttribute() {
super(identifierURI);
this.valid = false;
this.value = false;
}
/**
* Returns a <code>BooleanAttribute</code> that represents
* the xs:boolean at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a <code>BooleanAttribute</code> representing the
* appropriate value (null if there is a parsing error)
*
* @throws ParsingException
*/
public static BooleanAttribute getInstance(Node root)
throws ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a BooleanAttribute");
}
/**
* Returns a <code>BooleanAttribute</code> that represents
* the xs:boolean value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a <code>BooleanAttribute</code> representing the
* appropriate value (null if there is a parsing error)
*
* @throws ParsingException
*/
public static BooleanAttribute getInstance(String value)
throws ParsingException {
if (value == null) {
return invalidInstance;
// throw new ParsingException("Can't create a "
// + "BooleanAttribute from null input");
}
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
if (value.equals("true")) {
return trueInstance;
}
if (value.equals("false")) {
return falseInstance;
}
if (value.equals("")) {
return invalidInstance;
}
throw new ParsingException("Boolean string must be true or false");
}
/**
* Returns a <code>BooleanAttribute</code> that represents
* the boolean value provided.
*
* @param value a boolean representing the desired value
* @return a <code>BooleanAttribute</code> representing the
* appropriate value
*/
public static BooleanAttribute getInstance(boolean value) {
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
if (value) {
return trueInstance;
}
return falseInstance;
}
/**
* Returns a <code>BooleanAttribute</code> that represents
* a true value.
*
* @return a <code>BooleanAttribute</code> representing a
* true value
*/
public static BooleanAttribute getTrueInstance() {
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
return trueInstance;
}
/**
* Returns a <code>BooleanAttribute</code> that represents
* a false value.
*
* @return a <code>BooleanAttribute</code> representing a
* false value
*/
public static BooleanAttribute getFalseInstance() {
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
return falseInstance;
}
/**
* Returns the <code>boolean</code> value represented by this object.
*
* @return the <code>boolean</code> value
*/
public boolean getValue() {
if (!valid) {
throw new RuntimeException("Accessing invalid attribute");
}
return this.value;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof BooleanAttribute)) {
return false;
}
BooleanAttribute other = (BooleanAttribute)o;
return (this.value == other.value && this.valid == other.valid);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
// these numbers come from the javadoc for java.lang.Boolean...no,
// really, they do. I can't imagine what they were thinking...
return (this.value ? 1231 : 1237);
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
if (valid ) {
return (this.value ? "true" : "false");
} else {
return "";
}
}
}

View File

@ -0,0 +1,292 @@
/*
* @(#)DNSNameAttribute.java
*
* Copyright 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 com.sun.xacml.attr;
import java.net.URI;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import com.sun.xacml.ParsingException;
/**
* Represents the DNSName datatype introduced in XACML 2.0. All objects of
* this class are immutable and all methods of the class are thread-safe.
*
* @since 2.0
* @author Seth Proctor
*/
public class DNSNameAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.DNSNAME;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = new URI(identifier);
} catch (Exception e) {
earlyException = new IllegalArgumentException();
earlyException.initCause(e);
}
}
// the required hostname
private String hostname;
// the optional port range
private PortRange range;
// true if the hostname starts with a '*'
private boolean isSubdomain = false;
/**
* Creates the new <code>DNSNameAttribute</code> with only the required
* hostname component.
*
* @param hostname the host name component of the address
*/
public DNSNameAttribute(String hostname) {
this(hostname, new PortRange());
}
/**
* Creates the new <code>DNSNameAttribute</code> with the optional
* port range component.
*
* @param hostname the host name component of the address
* @param range the port range
*/
public DNSNameAttribute(String hostname, PortRange range) {
super(identifierURI);
// shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
// verify that the hostname is valid before we store it
if (! isValidHostName(hostname)) {
System.err.println("FIXME: throw error about bad hostname");
}
// see if it started with a '*' character
if (hostname.charAt(0) == '*') {
this.isSubdomain = true;
}
this.hostname = hostname;
this.range = range;
}
/**
* Private helper that tests whether the given string is valid.
*/
private boolean isValidHostName(String hostname) {
/*
hostname = *( domainlabel "." ) toplabel [ "." ]
domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
toplabel = alpha | alpha *( alphanum | "-" ) alphanum
*/
String domainlabel = "\\w[[\\w|\\-]*\\w]?";
String toplabel = "[a-zA-Z][[\\w|\\-]*\\w]?";
String pattern = "[\\*\\.]?[" + domainlabel + "\\.]*" + toplabel +
"\\.?";
return hostname.matches(pattern);
}
/**
* Returns a new <code>DNSNameAttribute</code> that represents
* the name at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
*
* @return a new <code>DNSNameAttribute</code> representing the
* appropriate value (null if there is a parsing error)
* @throws ParsingException
* @throws DOMException
*/
public static DNSNameAttribute getInstance(Node root)
throws DOMException, ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a DNSNameAttribute");
}
/**
* Returns a new <code>DNSNameAttribute</code> that represents
* the name indicated by the <code>String</code> provided.
*
* @param value a string representing the name
*
* @return a new <code>DNSNameAttribute</code>
* @throws ParsingException
*/
public static DNSNameAttribute getInstance(String value)
throws ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "DNSNameAttribute from null input");
}
int portSep = value.indexOf(':');
if (portSep == -1) {
// there is no port range, so just use the name
return new DNSNameAttribute(value);
}
// split the name and the port range
String hostname = value.substring(0, portSep);
PortRange range =
PortRange.getInstance(value.substring(portSep + 1,
value.length()));
return new DNSNameAttribute(hostname, range);
}
/**
* Returns the host name represented by this object.
*
* @return the host name
*/
public String getHostName() {
return this.hostname;
}
/**
* Returns the port range represented by this object which will be
* unbound if no range was specified.
*
* @return the port range
*/
public PortRange getPortRange() {
return this.range;
}
/**
* Returns true if the leading character in the hostname is a '*', and
* therefore represents a matching subdomain, or false otherwise.
*
* @return true if the name represents a subdomain, false otherwise
*/
public boolean isSubdomain() {
return this.isSubdomain;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof DNSNameAttribute)) {
return false;
}
DNSNameAttribute other = (DNSNameAttribute)o;
if (! this.hostname.toUpperCase().equals(
other.hostname.toUpperCase())) {
return false;
}
if (! this.range.equals(other.range)) {
return false;
}
return true;
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type.
*
* @return the object's hashcode value
*/
public int hashCode() {
return encode().hashCode();
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
return "DNSNameAttribute: \"" + encode() + "\"";
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
if (this.range.isUnbound()) {
return this.hostname;
}
return this.hostname + ":" + this.range.encode();
}
}

View File

@ -0,0 +1,714 @@
/*
* @(#)DateAttribute.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 com.sun.xacml.attr;
import java.net.URI;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.w3c.dom.Node;
import com.sun.xacml.Constants;
import com.sun.xacml.ParsingException;
/**
* Representation of an xs:date value. This class supports parsing
* xs:date values. All objects of this class are immutable and
* thread-safe. The <code>Date</code> objects returned are not, but
* these objects are cloned before being returned.
*
* @since 1.0
* @author Marco Barreno
* @author Seth Proctor
* @author Steve Hanna
*/
public class DateAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier = TypeIdentifierConstants.DATE;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
* <p>
* This object is used for synchronization whenever we need
* protection across this whole class.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Parser for dates with no time zones
* <p>
* This field is only initialized if needed (by initParsers()).
* <p>
* NOTE: This object should only be accessed from code that
* has synchronized on it, since SimpleDateFormat objects are not
* thread-safe.
*/
private DateFormat simpleParser;
/**
* Parser for dates with RFC 822 time zones (like +0300)
* <p>
* This field is only initialized if needed (by initParsers()).
* <p>
* NOTE: This object should only be accessed from code that
* has a lock on it, since SimpleDateFormat objects are not
* thread-safe.
*/
private DateFormat zoneParser;
/**
* Calendar for GMT
* <p>
* NOTE: This object should only be accessed from code that
* has a lock on it, since Calendar objects are not generally
* thread-safe.
*/
private Calendar gmtCalendar;
/**
* Number of nanoseconds per millisecond
* (shared by other classes in this package)
*/
static final int NANOS_PER_MILLI = 1000000;
/**
* Number of milliseconds per second
* (shared by other classes in this package)
*/
static final int MILLIS_PER_SECOND = 1000;
/**
* Number of seconds in a minute
* (shared by other classes in this package)
*/
static final int SECONDS_PER_MINUTE = 60;
/**
* Number of minutes in an hour
* (shared by other classes in this package)
*/
static final int MINUTES_PER_HOUR = 60;
/**
* Number of hours in a day
* (shared by other classes in this package)
*/
static final int HOURS_PER_DAY = 24;
/**
* Number of nanoseconds per second
* (shared by other classes in this package)
*/
static final int NANOS_PER_SECOND = NANOS_PER_MILLI * MILLIS_PER_SECOND;
/**
* Number of milliseconds in a minute
* (shared by other classes in this package)
*/
static final int MILLIS_PER_MINUTE =
MILLIS_PER_SECOND * SECONDS_PER_MINUTE;
/**
* Number of milliseconds in an hour
* (shared by other classes in this package)
*/
static final int MILLIS_PER_HOUR =
MILLIS_PER_MINUTE * MINUTES_PER_HOUR;
/**
* Number of milliseconds in a day
* (shared by other classes in this package)
*/
static final long MILLIS_PER_DAY = MILLIS_PER_HOUR * HOURS_PER_DAY;
/**
* Time zone value that indicates that the time zone was not
* specified.
*/
public static final int TZ_UNSPECIFIED = -1000000;
/**
* The instant (in GMT) at which the specified date began (midnight)
* in the specified time zone. If no time zone was specified,
* the local time zone is used.
*/
private Date value;
/**
* The time zone specified for this object (or TZ_UNSPECIFIED if
* unspecified). The offset to GMT, in minutes.
*/
private int timeZone;
/**
* The time zone actually used for this object (if it was
* originally unspecified, the default time zone used).
* The offset to GMT, in minutes.
*/
private int defaultedTimeZone;
/**
* Cached encoded value (null if not cached yet).
*/
private String encodedValue = null;
/**
* Creates a new <code>TimeAttribute</code> that represents
* the current date in the default time zone.
*/
public DateAttribute() {
this(new Date());
}
/**
* Creates a new <code>TimeAttribute</code> that represents
* the given date with default timezone values.
*
* @param date a <code>Date</code> object representing the
* instant at which the specified date began (midnight)
* in the specified time zone (the actual time value
* will be forced to midnight)
*/
public DateAttribute(Date date) {
super(identifierURI);
// Get the current time and GMT offset
int currOffset = DateTimeAttribute.getDefaultTZOffset(date);
long millis = date.getTime();
// Now find out the last time it was midnight local time
// (actually the last time it was midnight with the current
// GMT offset, but that's good enough).
// Skip back by time zone offset.
// Multiplication with 1L to avoid overflows in the
// integer multiplication, since it's converted to long anyway
millis += 1L * currOffset * MILLIS_PER_MINUTE;
// Reset to last GMT midnight
millis -= millis % MILLIS_PER_DAY;
// Skip forward by time zone offset.
// Multiplication with 1L to avoid overflows in the
// integer multiplication, since it's converted to long anyway
millis -= 1L * currOffset * MILLIS_PER_MINUTE;
date.setTime(millis);
init(date, currOffset, currOffset);
}
/**
* Creates a new <code>DateAttribute</code> that represents
* the date supplied.
*
* @param date a <code>Date</code> object representing the
* instant at which the specified date began (midnight)
* in the specified time zone
* @param timeZone the time zone specified for this object
* (or TZ_UNSPECIFIED if unspecified). The
* offset to GMT, in minutes.
* @param defaultedTimeZone the time zone actually used for this
* object (if it was originally unspecified,
* the default time zone used).
* The offset to GMT, in minutes.
*/
public DateAttribute(Date date, int timeZone, int defaultedTimeZone) {
super(identifierURI);
init(date, timeZone, defaultedTimeZone);
}
/**
* Initialization code shared by constructors.
*
* @param date a <code>Date</code> object representing the
* instant at which the specified date began (midnight)
* in the specified time zone.
* @param timeZone the time zone specified for this object
* (or TZ_UNSPECIFIED if unspecified). The
* offset to GMT, in minutes.
* @param defaultedTimeZone the time zone actually used for this
* object (if it was originally unspecified,
* the default time zone used).
* The offset to GMT, in minutes.
*/
private void init(Date date, int timeZone, int defaultedTimeZone) {
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
this.value = (Date) date.clone();
this.timeZone = timeZone;
this.defaultedTimeZone = defaultedTimeZone;
}
/**
* Returns a new <code>DateAttribute</code> that represents
* the xs:date at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>DateAttribute</code> representing the
* appropriate value (null if there is a parsing error)
*
* @throws ParseException
* @throws ParsingException
*/
public static DateAttribute getInstance(Node root)
throws ParseException, ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a DateAttribute");
}
/**
* Returns a new <code>DateAttribute</code> that represents
* the xs:date value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>DateAttribute</code> representing the
* desired value (null if there is a parsing error)
*
* @throws ParseException
* @throws ParsingException
*/
public static DateAttribute getInstance(String value)
throws ParseException, ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "DateAttribute from null input");
}
Date dateValue = null;
int timeZone;
int defaultedTimeZone;
// This simple parser has no time zone
DateFormat simpleParser = new SimpleDateFormat("yyyy-MM-dd");
simpleParser.setLenient(false);
// This parser has a four digit offset to GMT with sign
DateFormat zoneParser = new SimpleDateFormat("yyyy-MM-ddZ");
// FIXME: temporarily we need to set this to true
// this is a problem with Java 1.5, if you now
// of good documentation about the differnces between
// SimpleDateFormat in 1.4 and 1.5 let me (ludwig) know.
zoneParser.setLenient(true);
// If string ends with Z, it's in GMT. Chop off the Z and
// add +0000 to make the time zone explicit, then parse it
// with the timezone parser.
if (value.endsWith("Z")) {
value = value.substring(0, value.length()-1) + "+0000";
dateValue = strictParse(zoneParser, value);
timeZone = 0;
defaultedTimeZone = 0;
} else {
// If string ends with :XX, it must have a time zone
// or be invalid. Strip off the possible time zone and
// make sure what's left is a valid simple date. If so,
// reformat the time zone by stripping out the colon
// and parse the whole thing with the timezone parser.
int len = value.length();
if ((len > 6) && (value.charAt(len-3) == ':')) {
Date gmtValue = strictParse(zoneParser,
value.substring(0,len-6) +
"+0000");
value = value.substring(0, len-3) +
value.substring(len-2, len);
dateValue = strictParse(zoneParser, value);
timeZone =
(int) (gmtValue.getTime() - dateValue.getTime());
timeZone = timeZone / 60000;
defaultedTimeZone = timeZone;
} else {
// No funny business. This must be a simple date.
dateValue = strictParse(simpleParser, value);
timeZone = TZ_UNSPECIFIED;
Date gmtValue = strictParse(zoneParser, value + "+0000");
defaultedTimeZone =
(int) (gmtValue.getTime() - dateValue.getTime());
defaultedTimeZone = defaultedTimeZone / 60000;
}
}
// If parsing went OK, create a new DateAttribute object and
// return it.
DateAttribute attr = new DateAttribute(dateValue, timeZone,
defaultedTimeZone);
return attr;
}
/**
* Parse a String using a DateFormat parser, requiring that
* the entire String be consumed by the parser. On success,
* return a Date. On failure, throw a ParseException.
* <p>
* Synchronize on the parser object when using it, since we
* assume they're the shared static objects in this class.
*/
private static Date strictParse(DateFormat parser, String str)
throws ParseException {
ParsePosition pos = new ParsePosition(0);
Date ret;
synchronized (parser) {
ret = parser.parse(str, pos);
}
if (pos.getIndex() != str.length()) {
throw new ParseException("", 0);
}
return ret;
}
/**
* Initialize the parser objects.
*/
private void initParsers() {
// If simpleParser is already set, we're done.
if (this.simpleParser != null) {
return;
}
// Make sure that identifierURI is not null
if (earlyException != null) {
throw earlyException;
}
// Synchronize on identifierURI while initializing parsers
// so we don't end up using a half-way initialized parser
synchronized (identifierURI) {
// This simple parser has no time zone
this.simpleParser = new SimpleDateFormat("yyyy-MM-dd");
this.simpleParser.setLenient(false);
// This parser has a four digit offset to GMT with sign
this.zoneParser = new SimpleDateFormat("yyyy-MM-ddZ");
// FIXME: temporarily we need to set this to true
// this is a problem with Java 1.5, if you now
// of good documentation about the differnces between
// SimpleDateFormat in 1.4 and 1.5 let me (ludwig) know.
this.zoneParser.setLenient(true);
}
}
/**
* Gets the date represented by this object. The return value is
* a <code>Date</code> object representing the
* instant at which the specified date began (midnight)
* in the time zone.
* <p>
* <b>NOTE:</b> The <code>Date</code> object is cloned before it
* is returned to avoid unauthorized changes.
*
* @return a <code>Date</code> object representing the instant
* at which the date began
*/
public Date getValue() {
return (Date) this.value.clone();
}
/**
* Gets the specified time zone of this object (or
* TZ_UNSPECIFIED if unspecified).
*
* @return the offset to GMT in minutes (positive or negative)
*/
public int getTimeZone() {
return this.timeZone;
}
/**
* Gets the time zone actually used for this object (if it was
* originally unspecified, the default time zone used).
*
* @return the offset to GMT in minutes (positive or negative)
*/
public int getDefaultedTimeZone() {
return this.defaultedTimeZone;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
* <p>
* Two <code>DateAttribute</code>s are equal if and only if the
* instant on which the date began is equal. This means that they
* must have the same time zone.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof DateAttribute)) {
return false;
}
DateAttribute other = (DateAttribute)o;
return this.value.equals(other.value);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type.
*
* @return the object's hashcode value
*/
public int hashCode() {
// Only the value field is considered by the equals method, so only
// that field should be considered by this method.
return this.value.hashCode();
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("DateAttribute: [" + Constants.nl);
sb.append(" Date: " + this.value + " local time");
sb.append(" TimeZone: " + this.timeZone);
sb.append(" Defaulted TimeZone: " + this.defaultedTimeZone);
sb.append("]");
return sb.toString();
}
/**
* Encodes the value in a form suitable for including in XML data like
* a request or an obligation. This must return a value that could in
* turn be used by the factory to create a new instance with the same
* value.
*
* @return a <code>String</code> form of the value
*/
public String encode() {
if (this.encodedValue != null) {
return this.encodedValue;
}
if (this.timeZone == TZ_UNSPECIFIED) {
// If no time zone was specified, format Date value in
// local time with no time zone string.
initParsers();
synchronized (this.simpleParser) {
this.encodedValue = this.simpleParser.format(this.value);
}
} else {
// If a time zone was specified, don't use SimpleParser
// because it can only format dates in the local (default)
// time zone. And the offset between that time zone and the
// time zone we need to display can vary in complicated ways.
// Instead, do it ourselves using our formatDateWithTZ method.
this.encodedValue = formatDateWithTZ();
}
return this.encodedValue;
}
/**
* Encodes the value of this object as an xsi:date.
* Only for use when the time zone is specified.
*
* @return a <code>String</code> form of the value
*/
private String formatDateWithTZ() {
if (this.gmtCalendar == null) {
TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
// Locale doesn't make much difference here. We don't use
// any of the strings in the Locale and we don't do anything
// that depends on week count conventions. We use the US
// locale because it's always around and it ensures that we
// will always get a Gregorian calendar, which is necessary
// for compliance with ISO 8501.
this.gmtCalendar = Calendar.getInstance(gmtTimeZone, Locale.US);
}
// "YYYY-MM-DD+hh:mm".length() = 16
// Length may be longer if years < -999 or > 9999
StringBuffer buf = new StringBuffer(16);
// Start with the GMT instant when the date started in the
// specified time zone (would be 7:00 PM the preceding day
// if the specified time zone was +0500).
this.gmtCalendar.setTime(this.value);
// Bump by the timeZone (so we get the right date/time that
// that we want to format)
this.gmtCalendar.add(Calendar.MINUTE, this.timeZone);
// Now, assemble the string
int year = this.gmtCalendar.get(Calendar.YEAR);
buf.append(zeroPadInt(year, 4));
buf.append('-');
// JANUARY is 0
int month = this.gmtCalendar.get(Calendar.MONTH) + 1;
buf.append(zeroPadInt(month, 2));
buf.append('-');
int dom = this.gmtCalendar.get(Calendar.DAY_OF_MONTH);
buf.append(zeroPadInt(dom, 2));
int tzNoSign = this.timeZone;
if (this.timeZone < 0) {
tzNoSign = -tzNoSign;
buf.append('-');
} else {
buf.append('+');
}
int tzHours = tzNoSign / 60;
buf.append(zeroPadInt(tzHours, 2));
buf.append(':');
int tzMinutes = tzNoSign % 60;
buf.append(zeroPadInt(tzMinutes, 2));
return buf.toString();
}
/**
* Takes a String representation of an integer (an optional
* sign followed by digits) and pads it with zeros on the left
* until it has at least the specified number of digits.
* Note that this function will work for an integer of
* any size: int, long, etc.
*
* @param unpadded the unpadded <code>String</code>
* (must have length of at least one)
* @param minDigits the minimum number of digits desired
* @return the padded <code>String</code>
*/
static String zeroPadIntString(String unpadded, int minDigits) {
int len = unpadded.length();
// Get the sign character (or 0 if none)
char sign = unpadded.charAt(0);
if ((sign != '-') && (sign != '+')) {
sign = 0;
}
// The number of characters required is the number of digits,
// plus one for the sign if present.
int minChars = minDigits;
if (sign != 0) {
minChars++;
}
// If we already have that many characters, we're done.
if (len >= minChars) {
return unpadded;
}
// Otherwise, create the buffer
StringBuffer buf = new StringBuffer();
// Copy in the sign first, if present
if (sign != 0) {
buf.append(sign);
}
// Add the zeros
int zerosNeeded = minChars - len;
while (zerosNeeded-- != 0) {
buf.append('0');
}
// Copy the rest of the unpadded string
if (sign != 0) {
// Skip sign
buf.append(unpadded.substring(1, len));
} else {
buf.append(unpadded);
}
return buf.toString();
}
/**
* Converts an integer to a base 10 string and pads it with
* zeros on the left until it has at least the specified
* number of digits. Note that the length of the resulting
* string will be greater than minDigits if the number is
* negative since the string will start with a minus sign.
*
* @param intValue the integer to convert
* @param minDigits the minimum number of digits desired
* @return the padded <code>String</code>
*/
static String zeroPadInt(int intValue, int minDigits) {
return zeroPadIntString(Integer.toString(intValue), minDigits);
}
}

View File

@ -0,0 +1,754 @@
/*
* @(#)DateTimeAttribute.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.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.ParsingException;
import java.net.URI;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.w3c.dom.Node;
/**
* Representation of an xs:dateTime value. This class supports parsing
* xs:dateTime values. All objects of this class are immutable and
* thread-safe. The <code>Date</code> objects returned are not, but
* these objects are cloned before being returned.
*
* @since 1.0
* @author Marco Barreno
* @author Seth Proctor
* @author Steve Hanna
* @author Ludwig Seitz
*/
public class DateTimeAttribute extends AttributeValue implements Cloneable
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.DATETIME;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
* <p>
* This object is used for synchronization whenever we need
* protection across this whole class.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Parser for dates with no time zones
* <p>
* This field is only initialized if needed (by initParsers()).
* <p>
* NOTE: This object should only be accessed from code that
* has synchronized on it, since SimpleDateFormat objects are not
* thread-safe.
*/
private DateFormat simpleParser;
/**
* Parser for dates with RFC 822 time zones (like +0300)
* <p>
* This field is only initialized if needed (by initParsers()).
* <p>
* NOTE: This object should only be accessed from code that
* has synchronized on it, since SimpleDateFormat objects are not
* thread-safe.
*/
private DateFormat zoneParser;
/**
* Calendar for GMT
* <p>
* NOTE: This object should only be accessed from code that
* has a lock on it, since Calendar objects are not generally
* thread-safe.
*/
private Calendar gmtCalendar;
/**
* Time zone value that indicates that the time zone was not
* specified.
*/
public static final int TZ_UNSPECIFIED = -1000000;
/**
* The actual date and time that this object represents (in GMT,
* as with all Date objects). If no time zone was specified, the
* local time zone is used to convert to GMT.
* <p>
* This Date does not include fractions of a second. Those are
* handled by the separate nanoseconds field, since Date only
* provides millisecond accuracy and the XML Query spec requires
* at least 100 nanosecond accuracy.
*/
private Date value;
/**
* The number of nanoseconds beyond the Date given by the value
* field. The XML Query document says that fractional seconds
* must be supported down to at least 100 nanosecond resolution.
* The Date class only supports milliseconds, so we include here
* support for nanosecond resolution.
*/
private int nanoseconds;
/**
* The time zone specified for this object (or TZ_UNSPECIFIED if
* unspecified). The offset to GMT, in minutes.
*/
private int timeZone;
/**
* The time zone actually used for this object (if it was
* originally unspecified, the default time zone used).
* The offset to GMT, in minutes.
*/
private int defaultedTimeZone;
/**
* Cached encoded value (null if not cached yet).
*/
private String encodedValue = null;
/**
* Creates a new <code>DateTimeAttribute</code> that represents
* the current date in the default time zone.
*/
public DateTimeAttribute() {
this(new Date());
}
/**
* Creates a new <code>DateTimeAttribute</code> that represents
* the supplied date but uses default timezone and offset values.
*
* @param dateTime a <code>Date</code> object representing the
* specified date and time down to second
* resolution. If this object has non-zero
* milliseconds, they are combined
* with the nanoseconds parameter.
*/
public DateTimeAttribute(Date dateTime) {
super(identifierURI);
int currOffset = getDefaultTZOffset(dateTime);
init(dateTime, 0, currOffset, currOffset);
}
/**
* Creates a new <code>DateTimeAttribute</code> that represents
* the date supplied.
*
* @param dateTime a <code>Date</code> object representing the
* specified date and time down to second
* resolution. If this object has non-zero
* milliseconds, they are combined
* with the nanoseconds parameter.
* @param nanoseconds the number of nanoseconds beyond the
* Date specified in the date parameter
* @param timeZone the time zone specified for this object
* (or TZ_UNSPECIFIED if unspecified). The
* offset to GMT, in minutes.
* @param defaultedTimeZone the time zone actually used for this
* object (if it was originally unspecified,
* the default time zone used).
* The offset to GMT, in minutes.
*/
public DateTimeAttribute(Date dateTime, int nanoseconds, int timeZone,
int defaultedTimeZone) {
super(identifierURI);
init(dateTime, nanoseconds, timeZone, defaultedTimeZone);
}
/**
* The clone method.
*
* @return a copy of this object.
*/
public Object clone() {
try {
DateTimeAttribute clone = (DateTimeAttribute)super.clone();
clone.value = (Date)this.value.clone();
clone.nanoseconds = this.nanoseconds;
clone.timeZone = this.timeZone;
clone.defaultedTimeZone = this.defaultedTimeZone;
clone.encodedValue = this.encodedValue;
return clone;
} catch (CloneNotSupportedException e) {//this should never happen
throw new RuntimeException("Couldn't clone DateTimeAttribute");
}
}
/**
* Initialization code shared by constructors.
*
* @param date a <code>Date</code> object representing the
* specified date and time down to second
* resolution. If this object has non-zero
* milliseconds, they are combined
* with the nanoseconds parameter.
* @param nanoseconds the number of nanoseconds beyond the
* Date specified in the date parameter
* @param timeZone the time zone specified for this object
* (or TZ_UNSPECIFIED if unspecified). The
* offset to GMT, in minutes.
* @param defaultedTimeZone the time zone actually used for this
* object (if it was originally unspecified,
* the default time zone used).
* The offset to GMT, in minutes.
*/
private void init(Date date, int nanoseconds, int timeZone,
int defaultedTimeZone) {
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
// Make a new Date object
this.value = (Date) date.clone();
// Combine the nanoseconds so they are between 0 and 999,999,999
this.nanoseconds = combineNanos(this.value, nanoseconds);
this.timeZone = timeZone;
this.defaultedTimeZone = defaultedTimeZone;
}
/**
* Returns a new <code>DateTimeAttribute</code> that represents
* the xs:dateTime at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>DateTimeAttribute</code> representing the
* appropriate value
*
* @throws ParsingException if any problems occurred while parsing
* @throws NumberFormatException
* @throws ParseException
*/
public static DateTimeAttribute getInstance(Node root)
throws ParsingException, NumberFormatException, ParseException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a DayTimeAttribute");
}
/**
* Returns a new <code>DateTimeAttribute</code> that represents
* the xs:dateTime value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>DateTimeAttribute</code> representing the
* desired value
* @throws ParsingException if the text is formatted incorrectly
* @throws NumberFormatException if the nanosecond format is incorrect
* @throws ParseException
*/
public static DateTimeAttribute getInstance(String value)
throws ParsingException, NumberFormatException, ParseException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "DayTimeAttribute from null input");
}
Date dateValue = null;
int nanoseconds = 0;
int timeZone;
int defaultedTimeZone;
// This simple parser has no time zone
DateFormat simpleParser
= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
simpleParser.setLenient(false);
// This parser has a four digit offset to GMT with sign
DateFormat zoneParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
//FIXME: temporarily we need to set this to true
// this is a problem with Java 1.5, if you now
// of good documentation about the differnces between SimpleDateFormat
// in 1.4 and 1.5 let me (ludwig) know.
zoneParser.setLenient(true);
// If string ends with Z, it's in GMT. Chop off the Z and
// add +00:00 to make the time zone explicit.
if (value.endsWith("Z")) {
value = value.substring(0, value.length()-1) + "+00:00";
}
// Figure out if the string has a time zone.
// If string ends with +XX:XX or -XX:XX, it must have
// a time zone or be invalid.
int len = value.length(); // This variable is often not up-to-date
boolean hasTimeZone = ((value.charAt(len-3) == ':') &&
((value.charAt(len-6) == '-') ||
(value.charAt(len-6) == '+')));
// If string contains a period, it must have fractional
// seconds (or be invalid). Strip them out and put the
// value in nanoseconds.
int dotIndex = value.indexOf('.');
if (dotIndex != -1) {
// Decide where fractional seconds end.
int secondsEnd = value.length();
if (hasTimeZone) {
secondsEnd -= 6;
}
// Copy the fractional seconds out of the string.
String nanoString = value.substring(dotIndex+1, secondsEnd);
// Check that all those characters are ASCII digits.
for (int i = nanoString.length()-1; i >= 0; i--) {
char c = nanoString.charAt(i);
if ((c < '0') || (c > '9')) {
throw new ParsingException("non-ascii digit found");
}
}
// If there are less than 9 digits in the fractional seconds,
// pad with zeros on the right so it's nanoseconds.
while (nanoString.length() < 9) {
nanoString += "0";
}
// If there are more than 9 digits in the fractional seconds,
// drop the least significant digits.
if (nanoString.length() > 9) {
nanoString = nanoString.substring(0, 9);
}
// Parse the fractional seconds.
nanoseconds = Integer.parseInt(nanoString);
// Remove the fractional seconds from the string.
value = value.substring(0, dotIndex) +
value.substring(secondsEnd, value.length());
}
// this is the code that may trow a ParseException
if (hasTimeZone) {
// Strip off the purported time zone and make sure what's
// left is a valid unzoned date and time (by parsing in GMT).
// If so, reformat the time zone by stripping out the colon
// and parse the revised string with the timezone parser.
len = value.length();
Date gmtValue = strictParse(zoneParser,
value.substring(0,len-6) + "+0000");
value = value.substring(0, len-3) +
value.substring(len-2, len);
dateValue = strictParse(zoneParser, value);
timeZone =
(int) (gmtValue.getTime() - dateValue.getTime());
timeZone = timeZone / 60000;
defaultedTimeZone = timeZone;
} else {
// No funny business. This must be a simple date and time.
dateValue = strictParse(simpleParser, value);
timeZone = TZ_UNSPECIFIED;
// Figure out what time zone was used.
Date gmtValue = strictParse(zoneParser, value + "+0000");
defaultedTimeZone =
(int) (gmtValue.getTime() - dateValue.getTime());
defaultedTimeZone = defaultedTimeZone / 60000;
}
// If parsing went OK, create a new DateTimeAttribute object and
// return it.
DateTimeAttribute attr = new DateTimeAttribute(dateValue, nanoseconds,
timeZone,
defaultedTimeZone);
return attr;
}
/**
* Parse a String using a DateFormat parser, requiring that
* the entire String be consumed by the parser. On success,
* return a Date. On failure, throw a ParseException.
* <p>
* Synchronize on the parser object when using it, since we
* assume they're the shared static objects in this class.
*/
private static Date strictParse(DateFormat parser, String str)
throws ParseException {
ParsePosition pos = new ParsePosition(0);
Date ret;
synchronized (parser) {
ret = parser.parse(str, pos);
}
if (pos.getIndex() != str.length()) {
throw new ParseException("", 0);
}
return ret;
}
/**
* Initialize the parser objects.
*/
private void initParsers() {
// If simpleParser is already set, we're done.
if (this.simpleParser != null) {
return;
}
// Make sure that identifierURI is not null
if (earlyException != null) {
throw earlyException;
}
// Synchronize on identifierURI while initializing parsers
// so we don't end up using a half-way initialized parser
synchronized (identifierURI) {
// This simple parser has no time zone
this.simpleParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
this.simpleParser.setLenient(false);
// This parser has a four digit offset to GMT with sign
this.zoneParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
//FIXME: temporarily we need to set this to true
// this is a problem with Java 1.5, if you now
// of good documentation about the differnces between SimpleDateFormat
// in 1.4 and 1.5 let me (ludwig) know.
this.zoneParser.setLenient(true);
}
}
/**
* Gets the date and time represented by this object. The return
* value is a <code>Date</code> object representing the
* specified date and time down to second resolution.
* Subsecond values are handled by the
* {@link #getNanoseconds getNanoseconds} method.
* <p>
* <b>NOTE:</b> The <code>Date</code> object is cloned before it
* is returned to avoid unauthorized changes.
*
* @return a <code>Date</code> object representing the date and
* time represented by this object
*/
public Date getValue() {
return (Date) this.value.clone();
}
/**
* Gets the nanoseconds of this object.
*
* @return the number of nanoseconds
*/
public int getNanoseconds() {
return this.nanoseconds;
}
/**
* Gets the time zone of this object (or TZ_UNSPECIFIED if
* unspecified).
*
* @return the offset to GMT in minutes (positive or negative)
*/
public int getTimeZone() {
return this.timeZone;
}
/**
* Gets the time zone actually used for this object (if it was
* originally unspecified, the default time zone used).
*
* @return the offset to GMT in minutes (positive or negative)
*/
public int getDefaultedTimeZone() {
return this.defaultedTimeZone;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
* <p>
* Two <code>DateTimeAttribute</code>s are equal if and only if the
* dates and times represented are identical (down to the nanosecond).
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof DateTimeAttribute)) {
return false;
}
DateTimeAttribute other = (DateTimeAttribute)o;
// Since the value field is normalized into GMT, this is a
// good way to compare.
return (this.value.equals(other.value) &&
(this.nanoseconds == other.nanoseconds));
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type.
*
* @return the object's hashcode value
*/
public int hashCode() {
// Both the value field and the nanoseconds field are considered
// by the equals method, so it's best if the hashCode is derived
// from both of those fields.
int hashCode = this.value.hashCode();
hashCode = 31*hashCode + this.nanoseconds;
return hashCode;
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("DateTimeAttribute: [" + Constants.nl);
sb.append(" Date: " + this.value + " local time");
sb.append(" Nanoseconds: " + this.nanoseconds);
sb.append(" TimeZone: " + this.timeZone);
sb.append(" Defaulted TimeZone: " + this.defaultedTimeZone);
sb.append("]");
return sb.toString();
}
/**
* Encodes the value in a form suitable for including in XML data like
* a request or an obligation. This must return a value that could in
* turn be used by the factory to create a new instance with the same
* value.
*
* @return a <code>String</code> form of the value
*/
public String encode() {
if (this.encodedValue != null) {
return this.encodedValue;
}
if (this.timeZone == TZ_UNSPECIFIED) {
// If no time zone was specified, format Date value in
// local time with no time zone string.
initParsers();
synchronized (this.simpleParser) {
this.encodedValue = this.simpleParser.format(this.value);
}
if (this.nanoseconds != 0) {
this.encodedValue = this.encodedValue + "." +
DateAttribute.zeroPadInt(this.nanoseconds, 9);
}
} else {
// If a time zone was specified, don't use SimpleParser
// because it can only format dates in the local (default)
// time zone. And the offset between that time zone and the
// time zone we need to display can vary in complicated ways.
// Instead, do it ourselves using our formatDateWithTZ method.
this.encodedValue = formatDateTimeWithTZ();
}
return this.encodedValue;
}
/**
* Encodes the value of this object as an xsi:dateTime.
* Only for use when the time zone is specified.
*
* @return a <code>String</code> form of the value
*/
private String formatDateTimeWithTZ() {
if (this.gmtCalendar == null) {
TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
// Locale doesn't make much difference here. We don't use
// any of the strings in the Locale and we don't do anything
// that depends on week count conventions. We use the US
// locale because it's always around and it ensures that we
// will always get a Gregorian calendar, which is necessary
// for compliance with ISO 8501.
this.gmtCalendar = Calendar.getInstance(gmtTimeZone, Locale.US);
}
// "YYYY-MM-DDThh:mm:ss.sssssssss+hh:mm".length() = 35
// Length may be longer if years < -999 or > 9999
StringBuffer buf = new StringBuffer(35);
// Start with the proper time in GMT.
this.gmtCalendar.setTime(this.value);
// Bump by the timeZone, since we're going to be extracting
// the value in GMT
this.gmtCalendar.add(Calendar.MINUTE, this.timeZone);
// Now, assemble the string
int year = this.gmtCalendar.get(Calendar.YEAR);
buf.append(DateAttribute.zeroPadInt(year, 4));
buf.append('-');
// JANUARY is 0
int month = this.gmtCalendar.get(Calendar.MONTH) + 1;
buf.append(DateAttribute.zeroPadInt(month, 2));
buf.append('-');
int dom = this.gmtCalendar.get(Calendar.DAY_OF_MONTH);
buf.append(DateAttribute.zeroPadInt(dom, 2));
buf.append('T');
int hour = this.gmtCalendar.get(Calendar.HOUR_OF_DAY);
buf.append(DateAttribute.zeroPadInt(hour, 2));
buf.append(':');
int minute = this.gmtCalendar.get(Calendar.MINUTE);
buf.append(DateAttribute.zeroPadInt(minute, 2));
buf.append(':');
int second = this.gmtCalendar.get(Calendar.SECOND);
buf.append(DateAttribute.zeroPadInt(second, 2));
if (this.nanoseconds != 0) {
buf.append('.');
buf.append(DateAttribute.zeroPadInt(this.nanoseconds, 9));
}
int tzNoSign = this.timeZone;
if (this.timeZone < 0) {
tzNoSign = -tzNoSign;
buf.append('-');
} else {
buf.append('+');
}
int tzHours = tzNoSign / 60;
buf.append(DateAttribute.zeroPadInt(tzHours, 2));
buf.append(':');
int tzMinutes = tzNoSign % 60;
buf.append(DateAttribute.zeroPadInt(tzMinutes, 2));
return buf.toString();
}
/**
* Gets the offset in minutes between the default time zone and
* UTC for the specified date.
*
* @param date the <code>Date</code> whose offset is desired
*
* @return the offset in minutes
*/
static int getDefaultTZOffset(Date date) {
int offset = TimeZone.getDefault().getOffset(date.getTime());
offset = offset / DateAttribute.MILLIS_PER_MINUTE;
return offset;
}
/**
* Combines a number of nanoseconds with a <code>Date</code>
* so that the Date has no fractional seconds and the number
* of nanoseconds is non-negative and less than a second.
* <p>
* <b>WARNING</b>: This function changes the value stored in
* the date parameter!
*
* @param date the <code>Date</code> to be combined
* (<b>value may be modified!</b>)
* @param nanoseconds the nanoseconds to be combined
*
* @return the resulting number of nanoseconds
*/
static int combineNanos(Date date, int nanoseconds) {
long millis = date.getTime();
int milliCarry = (int) (millis % DateAttribute.MILLIS_PER_SECOND);
// If nothing needs fixing, get out quick
if ((milliCarry == 0) && (nanoseconds > 0)
&& (nanoseconds < DateAttribute.NANOS_PER_SECOND)) {
return nanoseconds;
}
// Remove any non-zero milliseconds from the date.
millis -= milliCarry;
// Add them into the nanoseconds.
long nanoTemp = nanoseconds;
// Multiplication with 1L to avoid overflows in the
// integer multiplication, since it's converted to long anyway
nanoTemp += 1L * milliCarry * DateAttribute.NANOS_PER_MILLI;
// Get the nanoseconds that represent fractional seconds.
// This we'll return.
int nanoResult = (int) (nanoTemp % DateAttribute.NANOS_PER_SECOND);
// Get nanoseconds that represent whole seconds.
nanoTemp -= nanoResult;
// Convert that to milliseconds and add it back to the date.
millis += nanoTemp / DateAttribute.NANOS_PER_MILLI;
date.setTime(millis);
return nanoResult;
}
}

View File

@ -0,0 +1,585 @@
/*
* @(#)DayTimeDurationAttribute.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 com.sun.xacml.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.ParsingException;
import java.math.BigInteger;
import java.net.URI;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.regex.Matcher;
import org.w3c.dom.Node;
/**
* Representation of an xf:dayTimeDuration value. This class supports parsing
* xd:dayTimeDuration values. All objects of this class are immutable and
* thread-safe. The <code>Date</code> objects returned are not, but
* these objects are cloned before being returned.
*
* @since 1.0
* @author Steve Hanna
*/
public class DayTimeDurationAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.DAYTIMEDURATION;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Regular expression for dayTimeDuration (a la java.util.regex)
*/
private static final String patternString =
"(\\-)?P((\\d+)?D)?(T((\\d+)?H)?((\\d+)?M)?((\\d+)?(.(\\d+)?)?S)?)?";
/**
* The index of the capturing group for the negative sign.
*/
private static final int GROUP_SIGN = 1;
/**
* The index of the capturing group for the number of days.
*/
private static final int GROUP_DAYS = 3;
/**
* The index of the capturing group for the number of hours.
*/
private static final int GROUP_HOURS = 6;
/**
* The index of the capturing group for the number of minutes.
*/
private static final int GROUP_MINUTES = 8;
/**
* The index of the capturing group for the number of seconds.
*/
private static final int GROUP_SECONDS = 10;
/**
* The index of the capturing group for the number of nanoseconds.
*/
private static final int GROUP_NANOSECONDS = 12;
/**
* Static BigInteger values. We only use these if one of
* the components is bigger than Integer.MAX_LONG and we
* want to detect overflow.
*/
private static BigInteger big24 = BigInteger.valueOf(24);
private static BigInteger big60 = BigInteger.valueOf(60);
private static BigInteger big1000 = BigInteger.valueOf(1000);
private static BigInteger bigMaxLong = BigInteger.valueOf(Long.MAX_VALUE);
/**
* A shared Pattern object, only initialized if needed
*/
private static Pattern pattern;
/**
* Negative flag. true if duration is negative, false otherwise
*/
private boolean negative;
/**
* Number of days
*/
private long days;
/**
* Number of hours
*/
private long hours;
/**
* Number of minutes
*/
private long minutes;
/**
* Number of seconds
*/
private long seconds;
/**
* Number of nanoseconds
*/
private int nanoseconds;
/**
* Total number of round seconds (in milliseconds)
*/
private long totalMillis;
/**
* Cached encoded value (null if not cached yet).
*/
private String encodedValue = null;
/**
* Creates a new <code>DayTimeDurationAttribute</code> that represents
* the duration supplied.
*
* @param negative true if the duration is negative, false otherwise
* @param days the number of days in the duration
* @param hours the number of hours in the duration
* @param minutes the number of minutes in the duration
* @param seconds the number of seconds in the duration
* @param nanoseconds the number of nanoseconds in the duration
* @throws IllegalArgumentException if the total number of milliseconds
* exceeds Long.MAX_LONG
*/
public DayTimeDurationAttribute(boolean negative, long days, long hours,
long minutes, long seconds,
int nanoseconds)
throws IllegalArgumentException {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
this.negative = negative;
this.days = days;
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.nanoseconds = nanoseconds;
// Convert all the components except nanoseconds to milliseconds
// If any of the components is big (too big to be an int),
// use the BigInteger class to do the math so we can detect
// overflow.
if ((days > Integer.MAX_VALUE) || (hours > Integer.MAX_VALUE) ||
(minutes > Integer.MAX_VALUE) || (seconds > Integer.MAX_VALUE)) {
BigInteger bigDays = BigInteger.valueOf(days);
BigInteger bigHours = BigInteger.valueOf(hours);
BigInteger bigMinutes = BigInteger.valueOf(minutes);
BigInteger bigSeconds = BigInteger.valueOf(seconds);
BigInteger bigTotal = bigDays.multiply(big24).add(bigHours)
.multiply(big60).add(bigMinutes).multiply(big60)
.add(bigSeconds).multiply(big1000);
// If the result is bigger than Long.MAX_VALUE, we have an
// overflow. Indicate an error (should be a processing error,
// since it can be argued that we should handle gigantic
// values for this).
if (bigTotal.compareTo(bigMaxLong) == 1) {
throw new IllegalArgumentException("total number of " +
"milliseconds " +
"exceeds Long.MAX_VALUE");
}
// If no overflow, convert to a long.
this.totalMillis = bigTotal.longValue();
} else {
// The numbers are small, so do it the fast way.
this.totalMillis = ((((((days * 24) + hours) * 60) + minutes) * 60)
+ seconds) * 1000;
}
}
/**
* Returns a new <code>DayTimeDurationAttribute</code> that represents
* the xf:dayTimeDuration at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>DayTimeDurationAttribute</code> representing the
* appropriate value (null if there is a parsing error)
*
* @throws ParsingException
* @throws NumberFormatException
*/
public static DayTimeDurationAttribute getInstance(Node root)
throws ParsingException, NumberFormatException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a DayTimeDurationAttribute");
}
/**
* Returns the long value for the capturing group groupNumber.
* This method takes a Matcher that has been used to match a
* Pattern against a String, fetches the value for the specified
* capturing group, converts that value to an long, and returns
* the value. If that group did not match, 0 is returned.
* If the matched value is not a valid long, NumberFormatException
* is thrown.
*
* @param matcher the Matcher from which to fetch the group
* @param groupNumber the group number to fetch
* @return the long value for that groupNumber
* @throws NumberFormatException if the string value for that
* groupNumber is not a valid long
*/
private static long parseGroup(Matcher matcher, int groupNumber)
throws NumberFormatException {
long groupLong = 0;
if (matcher.start(groupNumber) != -1) {
String groupString = matcher.group(groupNumber);
groupLong = Long.parseLong(groupString);
}
return groupLong;
}
/**
* Returns a new <code>DayTimeDurationAttribute</code> that represents
* the xf:dayTimeDuration value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>DayTimeDurationAttribute</code> representing the
* desired value (null if there is a parsing error)
*
* @throws ParsingException
* @throws NumberFormatException
*/
public static DayTimeDurationAttribute getInstance(String value)
throws ParsingException, NumberFormatException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "DayTimeDurationAttribute from null input");
}
boolean negative = false;
long days = 0;
long hours = 0;
long minutes = 0;
long seconds = 0;
int nanoseconds = 0;
// Compile the pattern, if not already done.
// No thread-safety problem here. The worst that can
// happen is that we initialize pattern several times.
if (pattern == null) {
try {
pattern = Pattern.compile(patternString);
} catch (PatternSyntaxException e) {
// This should never happen
throw new ParsingException("unexpected pattern match error");
}
}
// See if the value matches the pattern.
Matcher matcher = pattern.matcher(value);
boolean matches = matcher.matches();
// If not, syntax error!
if (!matches) {
throw new ParsingException("Syntax error in dayTimeDuration");
}
// If the negative group matched, the value is negative.
if (matcher.start(GROUP_SIGN) != -1) {
negative = true;
}
try {
// If the days group matched, parse that value.
days = parseGroup(matcher, GROUP_DAYS);
// If the hours group matched, parse that value.
hours = parseGroup(matcher, GROUP_HOURS);
// If the minutes group matched, parse that value.
minutes = parseGroup(matcher, GROUP_MINUTES);
// If the seconds group matched, parse that value.
seconds = parseGroup(matcher, GROUP_SECONDS);
// Special handling for fractional seconds, since
// they can have any resolution.
if (matcher.start(GROUP_NANOSECONDS) != -1) {
String nanosecondString = matcher.group(GROUP_NANOSECONDS);
// If there are less than 9 digits in the fractional seconds,
// pad with zeros on the right so it's nanoseconds.
while (nanosecondString.length() < 9) {
nanosecondString += "0";
}
// If there are more than 9 digits in the fractional seconds,
// drop the least significant digits.
if (nanosecondString.length() > 9) {
nanosecondString = nanosecondString.substring(0, 9);
}
nanoseconds = Integer.parseInt(nanosecondString);
}
} catch (NumberFormatException e) {
// If we run into a number that's too big to be a long
// that's an error. Really, it's a processing error,
// since one can argue that we should handle that.
throw e;
}
// Here's a requirement that's not checked for in the pattern.
// The designator 'T' must be absent if all the time
// items are absent. So the string can't end in 'T'.
// Note that we don't have to worry about a zero length
// string, since the pattern won't allow that.
if (value.charAt(value.length()-1) == 'T') {
throw new ParsingException("'T' must be absent if all" +
"time items are absent");
}
// If parsing went OK, create a new DayTimeDurationAttribute object and
// return it.
return new DayTimeDurationAttribute(negative, days, hours, minutes,
seconds, nanoseconds);
}
/**
* Returns true if the duration is negative.
*
* @return true if the duration is negative, false otherwise
*/
public boolean isNegative() {
return this.negative;
}
/**
* Gets the number of days.
*
* @return the number of days
*/
public long getDays() {
return this.days;
}
/**
* Gets the number of hours.
*
* @return the number of hours
*/
public long getHours() {
return this.hours;
}
/**
* Gets the number of minutes.
*
* @return the number of minutes
*/
public long getMinutes() {
return this.minutes;
}
/**
* Gets the number of seconds.
*
* @return the number of seconds
*/
public long getSeconds() {
return this.seconds;
}
/**
* Gets the number of nanoseconds.
*
* @return the number of nanoseconds
*/
public int getNanoseconds() {
return this.nanoseconds;
}
/**
* Gets the total number of round seconds (in milliseconds).
*
* @return the total number of seconds (in milliseconds)
*/
public long getTotalSeconds() {
return this.totalMillis;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof DayTimeDurationAttribute)) {
return false;
}
DayTimeDurationAttribute other = (DayTimeDurationAttribute)o;
return ((this.totalMillis == other.totalMillis) &&
(this.nanoseconds == other.nanoseconds) &&
(this.negative == other.negative));
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
// The totalMillis, nanoseconds, and negative fields are all considered
// by the equals method, so it's best if the hashCode is derived
// from all of those fields.
int hashCode = (int) this.totalMillis ^ (int) (this.totalMillis >> 32);
hashCode = 31*hashCode + this.nanoseconds;
if (this.negative) {
hashCode = -hashCode;
}
return hashCode;
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("DayTimeDurationAttribute: [" + Constants.nl);
sb.append(" Negative: " + this.negative);
sb.append(" Days: " + this.days);
sb.append(" Hours: " + this.hours);
sb.append(" Minutes: " + this.minutes);
sb.append(" Seconds: " + this.seconds);
sb.append(" Nanoseconds: " + this.nanoseconds);
sb.append(" TotalSeconds: " + this.totalMillis);
sb.append("]");
return sb.toString();
}
/**
* Encodes the value in a form suitable for including in XML data like
* a request or an obligation. This must return a value that could in
* turn be used by the factory to create a new instance with the same
* value.
*
* @return a <code>String</code> form of the value
*/
public String encode() {
if (this.encodedValue != null) {
return this.encodedValue;
}
// Length is quite variable
StringBuffer buf = new StringBuffer(10);
if (this.negative) {
buf.append('-');
}
buf.append('P');
if (this.days != 0) {
buf.append(Long.toString(this.days));
buf.append('D');
}
if ((this.hours != 0) || (this.minutes != 0)
|| (this.seconds != 0) || (this.nanoseconds != 0)) {
// Only include the T if there are some time fields
buf.append('T');
} else {
// Make sure that there's always at least one field specified
if (this.days == 0) {
buf.append("0D");
}
}
if (this.hours != 0) {
buf.append(Long.toString(this.hours));
buf.append('H');
}
if (this.minutes != 0) {
buf.append(Long.toString(this.minutes));
buf.append('M');
}
if ((this.seconds != 0) || (this.nanoseconds != 0)) {
buf.append(Long.toString(this.seconds));
if (this.nanoseconds != 0) {
buf.append('.');
buf.append(DateAttribute.zeroPadInt(this.nanoseconds, 9));
}
buf.append('S');
}
this.encodedValue = buf.toString();
return this.encodedValue;
}
}

View File

@ -0,0 +1,99 @@
/*
* @(#)DecisionAttribute.java
*
* Copyright 2005-2006 Swedish Institute of Computer Science 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 Swedish Institute of Computer Science 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. THE SWEDISH INSTITUE OF COMPUTER
* SCIENCE ("SICS") 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 SICS 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 SICS 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.attr;
import java.net.URI;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.Result;
/**
* Convenience class that represents the Decision attribute.
*
* @author Ludwig Seitz
*
*/
public class DecisionAttribute extends Attribute {
/**
* The static id URI of the Decision attribute
*/
private static URI idURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of idURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
idURI = URI.create(TypeIdentifierConstants.DECISION);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Constructor that creates a Decision Attribute.
*
* @param decision The decision code from the <code>Result</code> class.
*/
public DecisionAttribute(int decision) {
super(DecisionAttribute.idURI, null,
new StringAttribute((String)Result.DECISIONS.get(decision)));
if (earlyException != null) {
throw earlyException;
}
if (decision != Result.DECISION_DENY
&& decision != Result.DECISION_PERMIT) {
throw new IllegalArgumentException("Decision attribute value must"
+ " be 'PERMIT' or 'DENY'");
}
}
}

View File

@ -0,0 +1,218 @@
/*
* @(#)DoubleAttribute.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 com.sun.xacml.attr;
import java.net.URI;
import org.w3c.dom.Node;
import com.sun.xacml.ParsingException;
/**
* Representation of an xsi:double value. This class supports parsing
* xsi:double values. All objects of this class are immutable and
* all methods of the class are thread-safe.
*
* @since 1.0
* @author Marco Barreno
* @author Seth Proctor
* @author Steve Hanna
*/
public class DoubleAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.DOUBLE;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* The actual double value that this object represents.
*/
private double value;
/**
* Creates a new <code>DoubleAttribute</code> that represents
* the double value supplied.
*
* @param value the <code>double</code> value to be represented
*/
public DoubleAttribute(double value) {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
this.value = value;
}
/**
* Returns a new <code>DoubleAttribute</code> that represents
* the xsi:double at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>DoubleAttribute</code> representing the
* appropriate value (null if there is a parsing error)
* @throws NumberFormatException if the string form is not a double
* @throws ParsingException
*/
public static DoubleAttribute getInstance(Node root)
throws NumberFormatException, ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a DoubleAttribute");
}
/**
* Returns a new <code>DoubleAttribute</code> that represents
* the xsi:double value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>DoubleAttribute</code> representing the
* desired value (null if there is a parsing error)
* @throws ParsingException
* @throws NumberFormatException if the value is not a double
*/
public static DoubleAttribute getInstance(String value)
throws ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "DoubleAttribute from null input");
}
// Convert "INF" to "Infinity"
if (value.endsWith("INF")) {
int infIndex = value.lastIndexOf("INF");
value = value.substring(0, infIndex) + "Infinity";
}
return new DoubleAttribute(Double.parseDouble(value));
}
/**
* Returns the <code>double</code> value represented by this object.
*
* @return the <code>double</code> value
*/
public double getValue() {
return this.value;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof DoubleAttribute)) {
return false;
}
DoubleAttribute other = (DoubleAttribute)o;
// Handle the NaN case, where Java says NaNs are never
// equal and XML Query says they always are
if (Double.isNaN(this.value)) {
// this is a NaN, so see if the other is as well
if (Double.isNaN(other.value)) {
// they're both NaNs, so they're equal
return true;
}
// they're not both NaNs, so they're not equal
return false;
}
// not NaNs, so we can do a normal comparison
return (this.value == other.value);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
long v = Double.doubleToLongBits(this.value);
return (int)(v ^ (v >>> 32));
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
return String.valueOf(this.value);
}
}

View File

@ -0,0 +1,326 @@
/*
* @(#)HexBinaryAttribute.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 com.sun.xacml.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.ParsingException;
import java.net.URI;
import java.util.Arrays;
import org.w3c.dom.Node;
/**
* Representation of an xsi:hexBinary value. This class supports parsing
* xsi:hexBinary values. All objects of this class are immutable and
* all methods of the class are thread-safe.
*
* @since 1.0
* @author Steve Hanna
*/
public class HexBinaryAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.HEXBINARY;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* The actual binary value that this object represents.
*/
private byte [] value;
/**
* The value returned by toString(). Cached, but only
* generated if needed.
*/
private String strValue;
/**
* Creates a new <code>HexBinaryAttribute</code> that represents
* the byte [] value supplied.
*
* @param value the <code>byte []</code> value to be represented
*/
public HexBinaryAttribute(byte [] value) {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
// This will throw a NullPointerException if value == null.
// That's what we want in that case.
this.value = (byte[])value.clone();
}
/**
* Returns a new <code>HexBinaryAttribute</code> that represents
* the xsi:hexBinary at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>HexBinaryAttribute</code> representing the
* appropriate value
* @exception ParsingException if a parsing error occurs
*/
public static HexBinaryAttribute getInstance(Node root)
throws ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a HexBinaryAttribute");
}
/**
* Returns a new <code>HexBinaryAttribute</code> that represents
* the xsi:hexBinary value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>HexBinaryAttribute</code> representing the
* desired value
* @exception ParsingException if a parsing error occurs
*/
public static HexBinaryAttribute getInstance(String value)
throws ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "HexBinaryAttribute from null input");
}
byte [] bytes = hexToBin(value);
if (bytes == null) {
throw new ParsingException("Couldn't parse purported " +
"hex string: " + value);
}
return new HexBinaryAttribute(bytes);
}
/**
* Returns the <code>byte []</code> value represented by this object.
* Note that this value is cloned before returning to prevent
* unauthorized modifications.
*
* @return the <code>byte []</code> value
*/
public byte [] getValue() {
return (byte[])this.value.clone();
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
int code = this.value[0];
for (int i = 1; i < this.value.length; i++) {
code *= 31;
code += this.value[i];
}
return code;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof HexBinaryAttribute)) {
return false;
}
HexBinaryAttribute other = (HexBinaryAttribute)o;
return Arrays.equals(this.value, other.value);
}
/**
* Return the int value of a hex character. Return -1 if the
* character is not a valid hex character.
*/
private static int hexToBinNibble(char c) {
int result = -1;
if ((c >= '0') && (c <= '9')) {
result = (c - '0');
} else {
if ((c >= 'a') && (c <= 'f')) {
result = (c - 'a') + 10;
} else {
if ((c >= 'A') && (c <= 'F')) {
result = (c - 'A') + 10;
}
// else pick up the -1 value set above
}
}
return result;
}
/**
* Parse a hex string, returning a new byte array containing the
* value. Return null in case of a parsing error.
*
* @param hex the hex string
* @return a new byte array containing the value (or null)
*/
private static byte [] hexToBin(String hex) {
int len = hex.length();
// Must have an even number of hex digits
if (len % 2 != 0) {
return null;
}
int byteCount = len / 2;
byte [] bytes = new byte [byteCount];
int charIndex = 0;
for (int byteIndex = 0; byteIndex < byteCount; byteIndex++) {
int hiNibble = hexToBinNibble(hex.charAt(charIndex++));
int loNibble = hexToBinNibble(hex.charAt(charIndex++));
if ((hiNibble < 0) || (loNibble < 0)) {
return null;
}
bytes[byteIndex] = (byte) (hiNibble * 16 + loNibble);
}
return bytes;
}
/**
* Return the hex character for a particular nibble (half a byte).
*
* @param nibble a value 0-15
* @return hex character for that nibble (using A-F for 10-15)
*/
private static char binToHexNibble(int nibble) {
char result = (char) 0;
if (nibble < 10) {
result = (char) (nibble + '0');
} else {
result = (char) ((nibble - 10) + 'A');
}
return result;
}
/**
* Return a straight hexadecimal conversion of a byte array.
* This is a String containing only hex digits.
*
* @param bytes the byte array
* @return the hex version
*/
private static String binToHex(byte [] bytes) {
int byteLength = bytes.length;
char [] chars = new char [byteLength * 2];
int charIndex = 0;
for (int byteIndex = 0; byteIndex < byteLength; byteIndex++) {
byte b = bytes[byteIndex];
chars[charIndex++] = binToHexNibble((b >> 4) & 0xf);
chars[charIndex++] = binToHexNibble(b & 0xf);
}
return new String(chars);
}
/**
* Returns a String representation.
*
* @return the String representation
*/
public String toString() {
if (this.strValue == null) {
this.strValue = binToHex(this.value);
}
return "HexBinaryAttribute: [" + Constants.nl
+ this.strValue + "]" + Constants.nl;
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
if (this.strValue == null) {
this.strValue = binToHex(this.value);
}
return this.strValue;
}
}

View File

@ -0,0 +1,269 @@
/*
* @(#)IPAddressAttribute.java
*
* Copyright 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 com.sun.xacml.attr;
import com.sun.xacml.ParsingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.URI;
import org.w3c.dom.Node;
/**
* Represents the IPAddress datatype introduced in XACML 2.0. All objects of
* this class are immutable and all methods of the class are thread-safe.
* <p>
* To create an instance of an ipAddress from an encoded String or a DOM
* Node you should use the <code>getInstance</code> methods provided by
* this class. To construct an ipAddress instance directly, you must use
* the constructors provided by <code>IPv4AddressAttribute</code> and
* <code>IPv6AddressAttribute</code>. These will both create an attribute
* of XACML type ipAddress, but will handle the differences in these
* two representations correctly.
*
* @since 2.0
* @author Seth Proctor
*/
public abstract class IPAddressAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.IPADDRESS;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = new URI(identifier);
} catch (Exception e) {
earlyException = new IllegalArgumentException();
earlyException.initCause(e);
}
}
// the required address
private InetAddress address;
// the optional mask
private InetAddress mask;
// this is the optional port-range
private PortRange range;
/**
* Creates the new <code>IPAddressAttribute</code> with all the optional
* components.
*
* @param address a non-null <code>InetAddress</code>
* @param mask an <code>InetAddress</code> or null if there is no mask
* @param range a non-null <code>PortRange</code>
*/
protected IPAddressAttribute(InetAddress address, InetAddress mask,
PortRange range) {
super(identifierURI);
// shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
this.address = address;
this.mask = mask;
this.range = range;
}
/**
* Returns a new <code>IPAddressAttribute</code> that represents
* the name at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
*
* @return a new <code>IPAddressAttribute</code> representing the
* appropriate value (null if there is a parsing error)
*
* @throws ParsingException if any of the address components is invalid
*/
public static IPAddressAttribute getInstance(Node root)
throws ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a IPAddressAttribute");
}
/**
* Returns a new <code>IPAddressAttribute</code> that represents
* the name indicated by the <code>String</code> provided.
*
* @param value a string representing the address
*
* @return a new <code>IPAddressAttribute</code>
*
* @throws ParsingException if any of the address components is invalid
*/
public static IPAddressAttribute getInstance(String value)
throws ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "IPAddressAttribute from null input");
}
try {
// an IPv6 address starts with a '['
if (value.indexOf('[') == 0) {
return IPv6AddressAttribute.getV6Instance(value);
}
return IPv4AddressAttribute.getV4Instance(value);
} catch (UnknownHostException uhe) {
throw new ParsingException("Failed to parse an IPAddress", uhe);
}
}
/**
* Returns the address represented by this object.
*
* @return the address
*/
public InetAddress getAddress() {
return this.address;
}
/**
* Returns the mask represented by this object, or null if there is no
* mask.
*
* @return the mask or null
*/
public InetAddress getMask() {
return this.mask;
}
/**
* Returns the port range represented by this object which will be
* unbound if no range was specified.
*
* @return the range
*/
public PortRange getRange() {
return this.range;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof IPAddressAttribute)) {
return false;
}
IPAddressAttribute other = (IPAddressAttribute)o;
if (! this.address.equals(other.address)) {
return false;
}
if (this.mask != null) {
if (other.mask == null) {
return false;
}
if (! this.mask.equals(other.mask)) {
return false;
}
} else {
if (other.mask != null) {
return false;
}
}
if (! this.range.equals(other.range)) {
return false;
}
return true;
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type.
*
* @return the object's hashcode value
*/
public int hashCode() {
return encode().hashCode();
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
return "IPAddressAttribute: \"" + encode() + "\"";
}
}

View File

@ -0,0 +1,179 @@
/*
* @(#)IPv4AddressAttribute.java
*
* Copyright 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.attr;
import java.net.InetAddress;
import java.net.UnknownHostException;
import com.sun.xacml.ParsingException;
/**
* Subclass of <code>IPAddressAttribute</code> that handles the specifics
* of IPv4. In general, you shouldn't need to interact with this class
* except to create an instance directly.
*
* @since 2.0
* @author Seth Proctor
*/
public class IPv4AddressAttribute extends IPAddressAttribute
{
/**
* Creates the new <code>IPv4AddressAttribute</code> with just the required
* address component.
*
* @param address a non-null <code>InetAddress</code>
*/
public IPv4AddressAttribute(InetAddress address) {
this(address, null, new PortRange());
}
/**
* Creates the new <code>IPv4AddressAttribute</code> with the optional
* address mask.
*
* @param address a non-null <code>InetAddress</code>
* @param mask an <code>InetAddress</code> or null if there is no mask
*/
public IPv4AddressAttribute(InetAddress address, InetAddress mask) {
this(address, mask, new PortRange());
}
/**
* Creates the new <code>IPv4AddressAttribute</code> with the optional
* port range.
*
* @param address a non-null <code>InetAddress</code>
* @param range a non-null <code>PortRange</code>
*/
public IPv4AddressAttribute(InetAddress address, PortRange range) {
this(address, null, range);
}
/**
* Creates the new <code>IPv4AddressAttribute</code> with all the optional
* components.
*
* @param address a non-null <code>InetAddress</code>
* @param mask an <code>InetAddress</code> or null if there is no mask
* @param range a non-null <code>PortRange</code>
*/
public IPv4AddressAttribute(InetAddress address, InetAddress mask,
PortRange range) {
super(address, mask, range);
}
/**
* Returns a new <code>IPv4AddressAttribute</code> that represents
* the name indicated by the <code>String</code> provided. This is a
* protected method because you should never call it directly.
* Instead, you should call <code>getInstance</code> on
* <code>IPAddressAttribute</code> which provides versions that
* take both a <code>String</code> and a <code>Node</code> and
* will determine the protocol version correctly.
*
* @param value a string representing the address
*
* @return a new <code>IPAddressAttribute</code>
*
* @throws UnknownHostException if the address components is invalid
* @throws ParsingException
*/
protected static IPAddressAttribute getV4Instance(String value)
throws UnknownHostException, ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "IPv4AddressAttribute from null input");
}
InetAddress address = null;
InetAddress mask = null;
PortRange range = null;
// start out by seeing where the delimiters are
int maskPos = value.indexOf("/");
int rangePos = value.indexOf(":");
// now check to see which components we have
if (maskPos == rangePos) {
// the sting is just an address
address = InetAddress.getByName(value);
} else if (maskPos != -1) {
// there is also a mask (and maybe a range)
address = InetAddress.getByName(value.substring(0, maskPos));
if (rangePos != -1) {
// there's a range too, so get it and the mask
mask =
InetAddress.getByName(value.substring(maskPos + 1,
rangePos));
range =
PortRange.getInstance(value.substring(rangePos + 1,
value.length()));
} else {
// there's no range, so just get the mask
mask = InetAddress.getByName(value.substring(maskPos + 1,
value.length()));
}
} else {
// there is a range, but no mask
address = InetAddress.getByName(value.substring(0, rangePos));
range = PortRange.getInstance(value.substring(rangePos + 1,
value.length()));
}
// if the range is null, then create it as unbound
range = new PortRange();
return new IPv4AddressAttribute(address, mask, range);
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
String str = getAddress().getHostAddress();
if (getMask() != null) {
str += getMask().getHostAddress();
}
if (! getRange().isUnbound()) {
str += ":" + getRange().encode();
}
return str;
}
}

View File

@ -0,0 +1,170 @@
/*
* @(#)IPv6AddressAttribute.java
*
* Copyright 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.attr;
import java.net.InetAddress;
import java.net.UnknownHostException;
import com.sun.xacml.ParsingException;
/**
* Subclass of <code>IPAddressAttribute</code> that handles the specifics
* of IPv6. In general, you shouldn't need to interact with this class
* except to create an instance directly.
*
* @since 2.0
* @author Seth Proctor
*/
public class IPv6AddressAttribute extends IPAddressAttribute
{
/**
* Creates the new <code>IPv6AddressAttribute</code> with just the required
* address component.
*
* @param address a non-null <code>InetAddress</code>
*/
public IPv6AddressAttribute(InetAddress address) {
this(address, null, new PortRange());
}
/**
* Creates the new <code>IPv6AddressAttribute</code> with the optional
* address mask.
*
* @param address a non-null <code>InetAddress</code>
* @param mask an <code>InetAddress</code> or null if there is no mask
*/
public IPv6AddressAttribute(InetAddress address, InetAddress mask) {
this(address, mask, new PortRange());
}
/**
* Creates the new <code>IPv6AddressAttribute</code> with the optional
* port range.
*
* @param address a non-null <code>InetAddress</code>
* @param range a non-null <code>PortRange</code>
*/
public IPv6AddressAttribute(InetAddress address, PortRange range) {
this(address, null, range);
}
/**
* Creates the new <code>IPv6AddressAttribute</code> with all the optional
* components.
*
* @param address a non-null <code>InetAddress</code>
* @param mask an <code>InetAddress</code> or null if there is no mask
* @param range a non-null <code>PortRange</code>
*/
public IPv6AddressAttribute(InetAddress address, InetAddress mask,
PortRange range) {
super(address, mask, range);
}
/**
* Returns a new <code>IPv6AddressAttribute</code> that represents
* the name indicated by the <code>String</code> provided. This is a
* protected method because you should never call it directly.
* Instead, you should call <code>getInstance</code> on
* <code>IPAddressAttribute</code> which provides versions that
* take both a <code>String</code> and a <code>Node</code> and
* will determine the protocol version correctly.
*
* @param value a string representing the address
*
* @return a new <code>IPAddressAttribute</code>
*
* @throws UnknownHostException if the address components is invalid
* @throws ParsingException
*/
protected static IPAddressAttribute getV6Instance(String value)
throws UnknownHostException, ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "IPv6AddressAttribute from null input");
}
InetAddress address = null;
InetAddress mask = null;
PortRange range = null;
int len = value.length();
// get the required address component
int endIndex = value.indexOf(']');
address = InetAddress.getByName(value.substring(1, endIndex));
// see if there's anything left in the string
if (endIndex != (len - 1)) {
// if there's a mask, it's also an IPv6 address
if (value.charAt(endIndex + 1) == '/') {
int startIndex = endIndex + 3;
endIndex = value.indexOf(']', startIndex);
mask = InetAddress.getByName(value.substring(startIndex,
endIndex));
}
// finally, see if there's a port range, if we're not finished
if ((endIndex != (len - 1)) && (value.charAt(endIndex + 1) == ':')) {
range = PortRange.getInstance(value.substring(endIndex + 2,
len));
}
}
// if the range is null, then create it as unbound
range = new PortRange();
return new IPv6AddressAttribute(address, mask, range);
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
String str = "[" + getAddress().getHostAddress() + "]";
if (getMask() != null) {
str += "/[" + getMask().getHostAddress() + "]";
}
if (! getRange().isUnbound()) {
str += ":" + getRange().encode();
}
return str;
}
}

View File

@ -0,0 +1,202 @@
/*
* @(#)IntegerAttribute.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 com.sun.xacml.attr;
import java.net.URI;
import org.w3c.dom.Node;
import com.sun.xacml.ParsingException;
/**
* Representation of an xs:integer value. This class supports parsing
* xs:integer values. All objects of this class are immutable and
* all methods of the class are thread-safe.
*
* @since 1.0
* @author Marco Barreno
* @author Steve Hanna
*/
public class IntegerAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.INTEGER;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* The actual long value that this object represents.
*/
private long value;
/**
* Creates a new <code>IntegerAttribute</code> that represents
* the long value supplied.
*
* @param value the <code>long</code> value to be represented
*/
public IntegerAttribute(long value) {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
this.value = value;
}
/**
* Returns a new <code>IntegerAttribute</code> that represents
* the xs:integer at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>IntegerAttribute</code> representing the
* appropriate value (null if there is a parsing error)
* @throws NumberFormatException if the string form isn't a number
* @throws ParsingException
*/
public static IntegerAttribute getInstance(Node root)
throws NumberFormatException, ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "an IntegerAttribute");
}
/**
* Returns a new <code>IntegerAttribute</code> that represents
* the xs:integer value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>IntegerAttribute</code> representing the
* appropriate value (null if there is a parsing error)
* @throws NumberFormatException if the string isn't a number
* @throws ParsingException
*/
public static IntegerAttribute getInstance(String value)
throws NumberFormatException, ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "IntegerAttribute from null input");
}
// Leading '+' is allowed per XML schema and not
// by Long.parseLong. Strip it, if present.
if ((value.length() >= 1) && (value.charAt(0) == '+')) {
value = value.substring(1);
}
return new IntegerAttribute(Long.parseLong(value));
}
/**
* Returns the <code>long</code> value represented by this object.
*
* @return the <code>long</code> value
*/
public long getValue() {
return this.value;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof IntegerAttribute)) {
return false;
}
IntegerAttribute other = (IntegerAttribute)o;
return (this.value == other.value);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
return (int)this.value;
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
return String.valueOf(this.value);
}
}

View File

@ -0,0 +1,264 @@
/*
* @(#)PortRange.java
*
* Copyright 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 com.sun.xacml.attr;
import com.sun.xacml.ParsingException;
/**
* This class represents a port range as specified in the XACML 2.0 description
* of <code>dnsName</code> and <code>ipAddress</code>. The range may have
* upper and lower bounds, be specified by a single port number, or may be
* unbound.
*
* @since 2.0
* @author Seth Proctor
*/
public class PortRange
{
/**
* Constant used to specify that the range is unbound on one side.
*/
public static final int UNBOUND = -1;
// the port bound values
private int lowerBound;
private int upperBound;
/**
* Default constructor used to represent an unbound range. This is
* typically used when an address has no port information.
*/
public PortRange() {
this(UNBOUND, UNBOUND);
}
/**
* Creates a <code>PortRange</code> that represents a single port value
* instead of a range of values.
*
* @param singlePort the single port number
*/
public PortRange(int singlePort) {
this(singlePort, singlePort);
}
/**
* Creates a <code>PortRange</code> with upper and lower bounds. Either
* of the parameters may have the value <code>UNBOUND</code> meaning
* that there is no bound at the respective end.
*
* @param lowerBound the lower-bound port number or <code>UNBOUND</code>
* @param upperBound the upper-bound port number or <code>UNBOUND</code>
*/
public PortRange(int lowerBound, int upperBound) {
this.lowerBound = lowerBound;
this.upperBound = upperBound;
}
/**
* Creates an instance of <code>PortRange</code> based on the given value.
*
* @param value a <code>String</code> representing the range
*
* @return a new <code>PortRange</code>
*
* @throws NumberFormatException if a port value isn't an integer
*/
public static PortRange getInstance(String value)
throws ParsingException {
if (value == null) {
throw new ParsingException("Can't create PortRange"
+ " from null input");
}
int lowerBound = UNBOUND;
int upperBound = UNBOUND;
// first off, make sure there's actually content here
if ((value.length() == 0) || (value.equals("-"))) {
return new PortRange();
}
// there's content, so figure where the '-' is, if at all
int dashPos = value.indexOf('-');
if (dashPos == -1) {
// there's no dash, so it's just a single number
lowerBound = upperBound = Integer.parseInt(value);
} else if (dashPos == 0) {
// it starts with a dash, so it's just upper-range bound
upperBound = Integer.parseInt(value.substring(1));
} else {
// it's a number followed by a dash, so get the lower-bound...
lowerBound = Integer.parseInt(value.substring(0, dashPos));
int len = value.length();
// ... and see if there is a second port number
if (dashPos != (len - 1)) {
// the dash wasn't at the end, so there's an upper-bound
upperBound = Integer.parseInt(value.substring(dashPos + 1,
len));
}
}
return new PortRange(lowerBound, upperBound);
}
/**
* Returns the lower-bound port value. If the range is not lower-bound,
* then this returns <code>UNBOUND</code>. If the range is actually a
* single port number, then this returns the same value as
* <code>getUpperBound</code>.
*
* @return the upper-bound
*/
public int getLowerBound() {
return this.lowerBound;
}
/**
* Returns the upper-bound port value. If the range is not upper-bound,
* then this returns <code>UNBOUND</code>. If the range is actually a
* single port number, then this returns the same value as
* <code>getLowerBound</code>.
*
* @return the upper-bound
*/
public int getUpperBound() {
return this.upperBound;
}
/**
* Returns whether the range is bounded by a lower port number.
*
* @return true if lower-bounded, false otherwise
*/
public boolean isLowerBounded() {
return (this.lowerBound != -1);
}
/**
* Returns whether the range is bounded by an upper port number.
*
* @return true if upper-bounded, false otherwise
*/
public boolean isUpperBounded() {
return (this.upperBound != -1);
}
/**
* Returns whether the range is actually a single port number.
*
* @return true if the range is a single port number, false otherwise
*/
public boolean isSinglePort() {
return ((this.lowerBound == this.upperBound)
&& (this.lowerBound != UNBOUND));
}
/**
* Returns whether the range is unbound, which means that it specifies
* no port number or range. This is typically used with addresses that
* include no port information.
*
* @return true if the range is unbound, false otherwise
*/
public boolean isUnbound() {
return ((this.lowerBound == UNBOUND) && (this.upperBound == UNBOUND));
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof PortRange)) {
return false;
}
PortRange other = (PortRange)o;
if (this.lowerBound != other.lowerBound) {
return false;
}
if (this.upperBound != other.upperBound) {
return false;
}
return true;
}
/**
* Override the hashCode method.
*
* @return The hashCode.
*/
public int hashCode() {
return this.upperBound + this.lowerBound;
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
if (isUnbound()) {
return "";
}
if (isSinglePort()) {
return String.valueOf(this.lowerBound);
}
if (! isLowerBounded()) {
return "-" + String.valueOf(this.upperBound);
}
if (! isUpperBounded()) {
return String.valueOf(this.lowerBound) + "-";
}
return String.valueOf(this.lowerBound) + "-"
+ String.valueOf(this.upperBound);
}
}

View File

@ -0,0 +1,199 @@
/*
* @(#)RFC822NameAttribute.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 com.sun.xacml.attr;
import java.net.URI;
import org.w3c.dom.Node;
import com.sun.xacml.ParsingException;
/**
* Representation of an rfc822Name (ie, an email address).
*
* @since 1.0
* @author Seth Proctor
*/
public class RFC822NameAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.RFC822NAME;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
// the actual value being stored
private String value;
/**
* Creates a new <code>RFC822NameAttribute</code> that represents the
* value supplied.
*
* @param value the email address to be represented
*/
public RFC822NameAttribute(String value) {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
if (value == null) {
throw new IllegalArgumentException("Can't create RFC822Name from"
+ "null input");
}
// check that the string is an address, ie, that it has one and only
// one '@' character in it
String [] parts = value.split("@");
if (parts.length != 2) {
// this is malformed input
throw new IllegalArgumentException("invalid RFC822Name: " + value);
}
// cannonicalize the name
this.value = parts[0] + "@" + parts[1].toLowerCase();
}
/**
* Returns a new <code>RFC822NameAttribute</code> that represents
* the email address at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>RFC822NameAttribute</code> representing the
* appropriate value
* @throws ParsingException
*/
public static RFC822NameAttribute getInstance(Node root)
throws ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a RFC822NameAttribute");
}
/**
* Returns a new <code>RFC822NameAttribute</code> that represents
* the email address value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>RFC822NameAttribute</code> representing the
* appropriate value
*/
public static RFC822NameAttribute getInstance(String value) {
return new RFC822NameAttribute(value);
}
/**
* Returns the name value represented by this object
*
* @return the name
*/
public String getValue() {
return this.value;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof RFC822NameAttribute)) {
return false;
}
RFC822NameAttribute other = (RFC822NameAttribute)o;
return this.value.equals(other.value);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
return this.value.hashCode();
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
return this.value;
}
}

View File

@ -0,0 +1,265 @@
/*
* @(#)StandardAttributeFactory
*
* Copyright 2004-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.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.UnknownIdentifierException;
import com.sun.xacml.attr.proxy.AnyURIAttributeProxy;
import com.sun.xacml.attr.proxy.Base64BinaryAttributeProxy;
import com.sun.xacml.attr.proxy.BooleanAttributeProxy;
import com.sun.xacml.attr.proxy.DateAttributeProxy;
import com.sun.xacml.attr.proxy.DateTimeAttributeProxy;
import com.sun.xacml.attr.proxy.DayTimeDurationAttributeProxy;
import com.sun.xacml.attr.proxy.DNSNameAttributeProxy;
import com.sun.xacml.attr.proxy.DoubleAttributeProxy;
import com.sun.xacml.attr.proxy.HexBinaryAttributeProxy;
import com.sun.xacml.attr.proxy.IntegerAttributeProxy;
import com.sun.xacml.attr.proxy.IPAddressAttributeProxy;
import com.sun.xacml.attr.proxy.RFC822NameAttributeProxy;
import com.sun.xacml.attr.proxy.StringAttributeProxy;
import com.sun.xacml.attr.proxy.TimeAttributeProxy;
import com.sun.xacml.attr.proxy.YearMonthDurationAttributeProxy;
import com.sun.xacml.attr.proxy.X500NameAttributeProxy;
//import foo.xacml.attr.proxy.EmergencyLevelAttributeProxy;
//import foo.xacml.attr.proxy.EvaluationIdAttributeProxy;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
/**
* This factory supports the standard set of datatypes specified in XACML
! * 1.x and 2.0. It is the default factory used by the system, and imposes
* a singleton pattern insuring that there is only ever one instance of
* this class.
* <p>
* Note that because this supports only the standard datatypes, this
* factory does not allow the addition of any other datatypes. If you call
* <code>addDatatype</code> on an instance of this class, an exception
* will be thrown. If you need a standard factory that is modifiable, you
* should create a new <code>BaseAttributeFactory</code> (or some other
* <code>AttributeFactory</code>) and configure it with the standard
* datatypes using <code>addStandardDatatypes</code> (or, in the case of
* <code>BaseAttributeFactory</code>, by providing the datatypes in the
* constructor).
*
* @since 1.2
* @author Seth Proctor
*/
public class StandardAttributeFactory extends BaseAttributeFactory
{
// the one instance of this factory
private static StandardAttributeFactory factoryInstance = null;
// the datatypes supported by this factory
private static HashMap<String, AttributeProxy> supportedDatatypes = null;
// the supported identifiers for each version of XACML
private static Set<String> supportedV1Identifiers;
private static Set<String> supportedV2Identifiers;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(StandardAttributeFactory.class.getName());
/**
* Private constructor that sets up proxies for all of the standard
* datatypes.
*/
private StandardAttributeFactory() {
super(supportedDatatypes);
}
/**
* Private initializer for the supported datatypes. This isn't called
* until something needs these values, and is only called once.
*/
private static void initDatatypes() {
logger.debug("Initializing standard datatypes");
supportedDatatypes = new HashMap<String, AttributeProxy>();
// the 1.x datatypes
supportedDatatypes.put(BooleanAttribute.identifier,
new BooleanAttributeProxy());
supportedDatatypes.put(StringAttribute.identifier,
new StringAttributeProxy());
supportedDatatypes.put(DateAttribute.identifier,
new DateAttributeProxy());
supportedDatatypes.put(TimeAttribute.identifier,
new TimeAttributeProxy());
supportedDatatypes.put(DateTimeAttribute.identifier,
new DateTimeAttributeProxy());
supportedDatatypes.put(DayTimeDurationAttribute.identifier,
new DayTimeDurationAttributeProxy());
supportedDatatypes.put(YearMonthDurationAttribute.identifier,
new YearMonthDurationAttributeProxy());
supportedDatatypes.put(DoubleAttribute.identifier,
new DoubleAttributeProxy());
supportedDatatypes.put(IntegerAttribute.identifier,
new IntegerAttributeProxy());
supportedDatatypes.put(AnyURIAttribute.identifier,
new AnyURIAttributeProxy());
supportedDatatypes.put(HexBinaryAttribute.identifier,
new HexBinaryAttributeProxy());
supportedDatatypes.put(Base64BinaryAttribute.identifier,
new Base64BinaryAttributeProxy());
supportedDatatypes.put(X500NameAttribute.identifier,
new X500NameAttributeProxy());
supportedDatatypes.put(RFC822NameAttribute.identifier,
new RFC822NameAttributeProxy());
/*
supportedDatatypes.put(EmergencyLevelAttribute.identifier,
new EmergencyLevelAttributeProxy());
supportedDatatypes.put(EvaluationIdAttribute.identifier,
new EvaluationIdAttributeProxy());
*/
supportedV1Identifiers =
Collections.unmodifiableSet(supportedDatatypes.keySet());
// the 2.0 datatypes
supportedDatatypes.put(DNSNameAttribute.identifier,
new DNSNameAttributeProxy());
supportedDatatypes.put(IPAddressAttribute.identifier,
new IPAddressAttributeProxy());
supportedV2Identifiers =
Collections.unmodifiableSet(supportedDatatypes.keySet());
}
/**
* Returns an instance of this factory. This method enforces a singleton
* model, meaning that this always returns the same instance, creating
* the factory if it hasn't been requested before. This is the default
* model used by the <code>AttributeFactory</code>, ensuring quick
* access to this factory.
*
* @return the factory instance
*/
public static synchronized StandardAttributeFactory getFactory() {
if (factoryInstance == null) {
initDatatypes();
factoryInstance = new StandardAttributeFactory();
}
return factoryInstance;
}
/**
* A convenience method that returns a new instance of an
* <codeAttributeFactory</code> that supports all of the standard
* datatypes. The new factory allows adding support for new datatypes.
* This method should only be used when you need a new, mutable instance
* (eg, when you want to create a new factory that extends the set of
* supported datatypes). In general, you should use
* <code>getFactory</code> which is more efficient and enforces a
* singleton pattern.
*
* @return a new factory supporting the standard datatypes
*/
public static AttributeFactory getNewFactory() {
// first we make sure that everything has been initialized...
getFactory();
// ...then we create the new instance
return new BaseAttributeFactory(supportedDatatypes);
}
/**
* Returns the identifiers supported for the given version of XACML.
* Because this factory supports identifiers from all versions of the
* XACML specifications, this method is useful for getting a list of
* which specific identifiers are supported by a given version of XACML.
*
* @param xacmlVersion a standard XACML identifier string, as provided
* in <code>PolicyMetaData</code>
*
* @return a <code>Set</code> of identifiers
*
* @throws UnknownIdentifierException if the version string is unknown
*/
public static Set<String> getStandardDatatypes(String xacmlVersion)
throws UnknownIdentifierException
{
if (xacmlVersion.equals(Constants.XACML_1_0_IDENTIFIER)) {
return supportedV1Identifiers;
} else if (xacmlVersion.equals(Constants.XACML_2_0_IDENTIFIER)) {
return supportedV2Identifiers;
} else if (xacmlVersion.equals(Constants.XACML_3_0_IDENTIFIER)) {
return supportedV2Identifiers;
}
throw new UnknownIdentifierException("Unknown XACML version: " +
xacmlVersion);
}
/**
* Returns all supported datatypes.
*
*
* @return a <code>Map</code> of attribute proxys keyed by their
* identifier.
*/
public static Map<String, AttributeProxy> getStandardDatatypes() {
StandardAttributeFactory.initDatatypes();
return new HashMap<String, AttributeProxy>(StandardAttributeFactory.supportedDatatypes);
}
/**
* Throws an <code>UnsupportedOperationException</code> since you are not
* allowed to modify what a standard factory supports.
*
* @param id the name of the attribute type
* @param proxy the proxy used to create new attributes of the given type
*
* @throws UnsupportedOperationException always
*/
public void addDatatype(String id, AttributeProxy proxy) {
throw new UnsupportedOperationException("a standard factory cannot " +
"support new datatypes");
}
}

View File

@ -0,0 +1,228 @@
/*
* @(#)StringAttribute.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 com.sun.xacml.attr;
import java.net.URI;
import org.w3c.dom.Node;
import com.sun.xacml.ParsingException;
/**
* Representation of an xs:string value. This class supports parsing
* xs:string values. All objects of this class are immutable and
* all methods of the class are thread-safe.
* <p>
* Note that there was some confusion in the XACML specification
* about whether this datatype should be able to handle XML elements (ie,
* whether &lt;AttributeValue DataType="...string"&gt;&lt;foo/&gt;
* &lt;/AttributeValue&gt; is valid). This has been clarified to provide
* the correct requirement that a string may not contain mixed content (ie,
* the example provided here is invalid). If you need to specify something
* like this with the string datatype, then you must escape the
* <code>&lt;</code> and <code>&gt;</code> characters.
*
* @since 1.0
* @author Marco Barreno
* @author Seth Proctor
* @author Steve Hanna
*/
public class StringAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.STRING;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* The actual String value that this object represents.
*/
private String value;
/**
* Creates a new <code>StringAttribute</code> that represents
* the String value supplied.
*
* @param value the <code>String</code> value to be represented
*/
public StringAttribute(String value) {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
if (value == null) {
this.value = "";
} else {
this.value = value;
}
}
/**
* Returns a new <code>StringAttribute</code> that represents
* the xs:string at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>StringAttribute</code> representing the
* appropriate value (null if there is a parsing error)
* @throws ParsingException
*/
public static StringAttribute getInstance(Node root)
throws ParsingException {
Node node = root.getFirstChild();
// Strings are allowed to have an empty AttributeValue element and are
// just treated as empty strings...we have to handle this case
if (node == null) {
return new StringAttribute("");
}
// get the type of the node
short type = node.getNodeType();
// now see if we have (effectively) a simple string value
if ((type == Node.TEXT_NODE) || (type == Node.CDATA_SECTION_NODE) ||
(type == Node.COMMENT_NODE)) {
return getInstance(node.getNodeValue());
}
// there is some confusion in the specifications about what should
// happen at this point, but the strict reading of the XMLSchema
// specification suggests that this should be an error
throw new ParsingException("Can't create a StringAttribute from "
+ "given xml node type: " + root.getNodeType());
}
/**
* Returns a new <code>StringAttribute</code> that represents
* the xs:string value indicated by the <code>String</code> provided.
*
* @param value a string representing the desired value
* @return a new <code>StringAttribute</code> representing the
* appropriate value
*/
public static StringAttribute getInstance(String value) {
return new StringAttribute(value);
}
/**
* Returns the <code>String</code> value represented by this object.
*
* @return the <code>String</code> value
*/
public String getValue() {
return this.value;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof StringAttribute)) {
return false;
}
StringAttribute other = (StringAttribute)o;
return this.value.equals(other.value);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
return this.value.hashCode();
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
return "StringAttribute: \"" + this.value + "\"";
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
return this.value;
}
}

View File

@ -0,0 +1,522 @@
/*
* @(#)TimeAttribute.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.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.ParsingException;
import com.sun.xacml.ProcessingException;
import java.net.URI;
import java.text.ParseException;
import java.util.Date;
import org.w3c.dom.Node;
/**
* Representation of an xs:time value. This class supports parsing
* xs:time values. All objects of this class are immutable and
* thread-safe. The <code>Date</code> objects returned are not, but
* these objects are cloned before being returned.
*
* @since 1.0
* @author Steve Hanna
* @author Seth Proctor
*/
public class TimeAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.TIME;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
* <p>
* This object is used for synchronization whenever we need
* protection across this whole class.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Time zone value that indicates that the time zone was not
* specified.
*/
public static final int TZ_UNSPECIFIED = -1000000;
/**
* The time that this object represents in second resolution, in
* milliseconds GMT, with zero being midnight. If no time zone was
* specified, the local time zone is used to convert to milliseconds
* relative to GMT.
*/
private long timeGMT;
/**
* The number of nanoseconds beyond the time given by the timeGMT
* field. The XML Query document says that fractional seconds
* must be supported down to at least 100 nanosecond resolution.
* The Date class only supports milliseconds, so we include here
* support for nanosecond resolution.
*/
private int nanoseconds;
// NOTE: now that we're not using a Date object, the above two variables
// could be condensed, and the interface could be changed so we don't
// need to worry about tracking the time values separately
/**
* The time zone specified for this object (or TZ_UNSPECIFIED if
* unspecified). The offset to GMT, in minutes.
*/
private int timeZone;
/**
* The time zone actually used for this object (if it was
* originally unspecified, the default time zone used).
* The offset to GMT, in minutes.
*/
private int defaultedTimeZone;
/**
* Cached encoded value (null if not cached yet).
*/
private String encodedValue = null;
/**
* Creates a new <code>TimeAttribute</code> that represents
* the current time in the current time zone.
*/
public TimeAttribute() {
this(new Date());
}
/**
* Creates a new <code>TimeAttribute</code> that represents
* the given time but uses the default timezone and offset values.
*
* @param time a <code>Date</code> object representing the
* specified time down to second resolution. This
* date should have a date of 01/01/1970. If it does
* not, such a date will be forced. If this object
* has non-zero milliseconds, they are combined
* with the nanoseconds parameter.
*/
public TimeAttribute(Date time) {
super(identifierURI);
int currOffset = DateTimeAttribute.getDefaultTZOffset(time);
init(time, 0, currOffset, currOffset);
}
/**
* Creates a new <code>TimeAttribute</code> that represents
* the time supplied.
*
* @param time a <code>Date</code> object representing the
* specified time down to second resolution. This
* date should have a date of 01/01/1970. If it does
* not, such a date will be forced. If this object
* has non-zero milliseconds, they are combined
* with the nanoseconds parameter.
* @param nanoseconds the number of nanoseconds beyond the
* Date specified in the date parameter
* @param timeZone the time zone specified for this object
* (or TZ_UNSPECIFIED if unspecified). The
* offset to GMT, in minutes.
* @param defaultedTimeZone the time zone actually used for this
* object, which must be specified.
* The offset to GMT, in minutes.
*/
public TimeAttribute(Date time, int nanoseconds, int timeZone,
int defaultedTimeZone) {
super(identifierURI);
// if the timezone is unspecified, it's illegal for the defaulted
// timezone to also be unspecified
if ((timeZone == TZ_UNSPECIFIED) &&
(defaultedTimeZone == TZ_UNSPECIFIED)) {
throw new ProcessingException("default timezone must be specified"
+ "when a timezone is provided");
}
init(time, nanoseconds, timeZone, defaultedTimeZone);
}
/**
* Initialization code shared by constructors.
*
* @param date a <code>Date</code> object representing the
* specified time down to second resolution. This
* date should have a date of 01/01/1970. If it does
* not, such a date will be forced. If this object
* has non-zero milliseconds, they are combined
* with the nanoseconds parameter.
* @param nanoseconds the number of nanoseconds beyond the
* Date specified in the date parameter
* @param timeZone the time zone specified for this object
* (or TZ_UNSPECIFIED if unspecified). The
* offset to GMT, in minutes.
* @param defaultedTimeZone the time zone actually used for this
* object (if it was originally unspecified,
* the default time zone used).
* The offset to GMT, in minutes.
*/
private void init(Date date, int nanoseconds, int timeZone,
int defaultedTimeZone) {
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
// get a temporary copy of the date
Date tmpDate = (Date)(date.clone());
// Combine the nanoseconds so they are between 0 and 999,999,999
this.nanoseconds =
DateTimeAttribute.combineNanos(tmpDate, nanoseconds);
// now that the date has been (potentially) updated, store the time
this.timeGMT = tmpDate.getTime();
// keep track of the timezone values
this.timeZone = timeZone;
this.defaultedTimeZone = defaultedTimeZone;
// Check that the date is normalized to 1/1/70
if ((this.timeGMT >= DateAttribute.MILLIS_PER_DAY)
|| (this.timeGMT < 0)) {
this.timeGMT = this.timeGMT % DateAttribute.MILLIS_PER_DAY;
// if we had a negative value then we need to shift by a day
if (this.timeGMT < 0) {
this.timeGMT += DateAttribute.MILLIS_PER_DAY;
}
}
}
/**
* Returns a new <code>TimeAttribute</code> that represents
* the xs:time at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>TimeAttribute</code> representing the
* appropriate value (null if there is a parsing error)
*
* @throws ParsingException
* @throws NumberFormatException
* @throws ParseException
*/
public static TimeAttribute getInstance(Node root)
throws ParsingException, NumberFormatException, ParseException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new IllegalArgumentException("Error while parsing"
+ "a TimeAttribute");
}
/**
* Returns a new <code>TimeAttribute</code> that represents
* the xs:time value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>TimeAttribute</code> representing the
* desired value (null if there is a parsing error)
*
* @throws ParsingException if any problems occurred while parsing
* @throws NumberFormatException
* @throws ParseException
*/
public static TimeAttribute getInstance(String value)
throws ParsingException, NumberFormatException, ParseException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "TimeAttribute from empty input");
}
// Prepend date string for Jan 1 1970 and use the
// DateTimeAttribute parsing code.
value = "1970-01-01T" + value;
DateTimeAttribute dateTime = DateTimeAttribute.getInstance(value);
// if there was no explicit TZ provided, then we want to make sure
// the that the defaulting is done correctly, especially since 1/1/70
// is always out of daylight savings time
Date dateValue = dateTime.getValue();
int defaultedTimeZone = dateTime.getDefaultedTimeZone();
if (dateTime.getTimeZone() == TZ_UNSPECIFIED) {
int newDefTimeZone =
DateTimeAttribute.getDefaultTZOffset(new Date());
// Multiplication with 1L to avoid overflows in the
// integer multiplication, since it's converted to long anyway
dateValue = new Date(dateValue.getTime() -
1L *(newDefTimeZone - defaultedTimeZone) *
DateAttribute.MILLIS_PER_MINUTE);
defaultedTimeZone = newDefTimeZone;
}
return new TimeAttribute(dateValue,
dateTime.getNanoseconds(),
dateTime.getTimeZone(),
defaultedTimeZone);
}
/**
* Gets the time represented by this object. The return
* value is a <code>Date</code> object representing the
* specified time down to second resolution with a date
* of January 1, 1970. Subsecond values are handled by the
* {@link #getNanoseconds getNanoseconds} method.
*
* @return a <code>Date</code> object representing the
* time represented by this object
*/
public Date getValue() {
return new Date(this.timeGMT);
}
/**
* Gets the number of milliseconds since midnight GMT that this attribute
* value represents. This is the same time returned by
* <code>getValue</code>, and likewise the milliseconds are provided
* with second resolution.
*
* @return milliseconds since midnight GMT
*/
public long getMilliseconds() {
return this.timeGMT;
}
/**
* Gets the nanoseconds of this object.
*
* @return the number of nanoseconds
*/
public int getNanoseconds() {
return this.nanoseconds;
}
/**
* Gets the time zone of this object (or TZ_UNSPECIFIED if
* unspecified).
*
* @return the offset to GMT in minutes (positive or negative)
*/
public int getTimeZone() {
return this.timeZone;
}
/**
* Gets the time zone actually used for this object (if it was
* originally unspecified, the default time zone used).
*
* @return the offset to GMT in minutes (positive or negative)
*/
public int getDefaultedTimeZone() {
return this.defaultedTimeZone;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof TimeAttribute)) {
return false;
}
TimeAttribute other = (TimeAttribute)o;
return (this.timeGMT == other.timeGMT &&
(this.nanoseconds == other.nanoseconds));
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
// the standard Date hashcode is used here...
int hashCode = (int)(this.timeGMT ^ (this.timeGMT >>> 32));
// ...but both the timeGMT and the nanoseconds fields are considered
// by the equals method, so it's best if the hashCode is derived
// from both of those fields.
hashCode = (31 * hashCode) + this.nanoseconds;
return hashCode;
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("TimeAttribute: [" + Constants.nl);
// calculate the GMT value of this time
long secsGMT = this.timeGMT / 1000;
long minsGMT = secsGMT / 60;
secsGMT = secsGMT % 60;
long hoursGMT = minsGMT / 60;
minsGMT = minsGMT % 60;
// put the right number of zeros in place
String hoursStr = (hoursGMT < 10) ? "0" + hoursGMT : "" + hoursGMT;
String minsStr = (minsGMT < 10) ? "0" + minsGMT : "" + minsGMT;
String secsStr = (secsGMT < 10) ? "0" + secsGMT : "" + secsGMT;
sb.append(" Time GMT: " + hoursStr + ":" + minsStr + ":" + secsStr);
sb.append(" Nanoseconds: " + this.nanoseconds);
sb.append(" TimeZone: " + this.timeZone);
sb.append(" Defaulted TimeZone: " + this.defaultedTimeZone);
sb.append("]");
return sb.toString();
}
/**
* Encodes the value in a form suitable for including in XML data like
* a request or an obligation. This returns a time value that could in
* turn be used by the factory to create a new instance with the same
* value.
*
* @return a <code>String</code> form of the value
*/
public String encode() {
if (this.encodedValue != null) {
return this.encodedValue;
}
// "hh:mm:ss.sssssssss+hh:mm".length() = 27
StringBuffer buf = new StringBuffer(27);
// get the correct time for the timezone being used
int millis = (int)this.timeGMT;
if (this.timeZone == TZ_UNSPECIFIED) {
millis += (this.defaultedTimeZone
* DateAttribute.MILLIS_PER_MINUTE);
} else {
millis += (this.timeZone * DateAttribute.MILLIS_PER_MINUTE);
}
if (millis < 0) {
millis += DateAttribute.MILLIS_PER_DAY;
} else if (millis >= DateAttribute.MILLIS_PER_DAY) {
millis -= DateAttribute.MILLIS_PER_DAY;
}
// now generate the time string
int hour = millis / DateAttribute.MILLIS_PER_HOUR;
millis = millis % DateAttribute.MILLIS_PER_HOUR;
buf.append(DateAttribute.zeroPadInt(hour, 2));
buf.append(':');
int minute = millis / DateAttribute.MILLIS_PER_MINUTE;
millis = millis % DateAttribute.MILLIS_PER_MINUTE;
buf.append(DateAttribute.zeroPadInt(minute, 2));
buf.append(':');
int second = millis / DateAttribute.MILLIS_PER_SECOND;
buf.append(DateAttribute.zeroPadInt(second, 2));
// add any nanoseconds
if (this.nanoseconds != 0) {
buf.append('.');
buf.append(DateAttribute.zeroPadInt(this.nanoseconds, 9));
}
// if there is a specified timezone, then include that in the encoding
if (this.timeZone != TZ_UNSPECIFIED) {
int tzNoSign = this.timeZone;
if (this.timeZone < 0) {
tzNoSign = -tzNoSign;
buf.append('-');
} else {
buf.append('+');
}
int tzHours = tzNoSign / 60;
buf.append(DateAttribute.zeroPadInt(tzHours, 2));
buf.append(':');
int tzMinutes = tzNoSign % 60;
buf.append(DateAttribute.zeroPadInt(tzMinutes, 2));
}
// remember the encoding for later
this.encodedValue = buf.toString();
return this.encodedValue;
}
}

View File

@ -0,0 +1,78 @@
package com.sun.xacml.attr;
import java.net.URI;
public class TypeIdentifierConstants {
public static final String ANYURI =
"http://www.w3.org/2001/XMLSchema#anyURI";
public static final String BASE64BINARY =
"http://www.w3.org/2001/XMLSchema#base64Binary";
public static final String BOOLEAN =
"http://www.w3.org/2001/XMLSchema#boolean";
public static final String DATE =
"http://www.w3.org/2001/XMLSchema#date";
public static final String DATETIME =
"http://www.w3.org/2001/XMLSchema#dateTime";
public static final String DAYTIMEDURATION =
"http://www.w3.org/TR/2002/WD-xquery-operators-20020816#dayTimeDuration";
public static final String DECISION =
"urn:oasis:names:tc:xacml:3.0:delegation:decision";
public static final String DNSNAME =
"urn:oasis:names:tc:xacml:2.0:data-type:dnsName";
public static final String DOUBLE =
"http://www.w3.org/2001/XMLSchema#double";
public static final String HEXBINARY =
"http://www.w3.org/2001/XMLSchema#hexBinary";
public static final String INTEGER =
"http://www.w3.org/2001/XMLSchema#integer";
public static final String IPADDRESS =
"urn:oasis:names:tc:xacml:2.0:data-type:ipAddress";
public static final String RFC822NAME =
"urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name";
public static final String STRING =
"http://www.w3.org/2001/XMLSchema#string";
public static final String TIME =
"http://www.w3.org/2001/XMLSchema#time";
public static final String X500NAME =
"urn:oasis:names:tc:xacml:1.0:data-type:x500Name";
public static final String YEARMONTHDURATION =
"http://www.w3.org/TR/2002/WD-xquery-operators-20020816#yearMonthDuration";
public static final URI ANYURI_URI =
URI.create(ANYURI);
public static final URI BASE64BINARY_URI =
URI.create(BASE64BINARY);
public static final URI BOOLEAN_URI =
URI.create(BOOLEAN);
public static final URI DATE_URI =
URI.create(DATE);
public static final URI DATETIME_URI =
URI.create(DATETIME);
public static final URI DAYTIMEDURATION_URI =
URI.create(DAYTIMEDURATION);
public static final URI DECISION_URI =
URI.create(DECISION);
public static final URI DNSNAME_URI =
URI.create(DNSNAME);
public static final URI DOUBLE_URI =
URI.create(DOUBLE);
public static final URI HEXBINARY_URI =
URI.create(HEXBINARY);
public static final URI INTEGER_URI =
URI.create(INTEGER);
public static final URI IPADDRESS_URI =
URI.create(IPADDRESS);
public static final URI RFC822NAME_URI =
URI.create(RFC822NAME);
public static final URI STRING_URI =
URI.create(STRING);
public static final URI TIME_URI =
URI.create(TIME);
public static final URI X500NAME_URI =
URI.create(X500NAME);
public static final URI YEARMONTHDURATION_URI =
URI.create(YEARMONTHDURATION);
}

View File

@ -0,0 +1,203 @@
/*
* @(#)X500NameAttribute.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 com.sun.xacml.attr;
import java.net.URI;
import javax.security.auth.x500.X500Principal;
import org.w3c.dom.Node;
import com.sun.xacml.ParsingException;
/**
* Representation of an X500 Name.
*
* @since 1.0
* @author Marco Barreno
* @author Seth Proctor
*/
public class X500NameAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.X500NAME;
// the actual value being stored
private X500Principal value;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Creates a new <code>X500NameAttribute</code> that represents the
* value supplied.
*
* @param value the X500 Name to be represented
*/
public X500NameAttribute(X500Principal value) {
super(identifierURI);
if (earlyException != null) {
throw earlyException;
}
this.value = value;
}
/**
* Returns a new <codeX500NameAttribute</code> that represents
* the X500 Name at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>X500NameAttribute</code> representing the
* appropriate value
* @throws IllegalArgumentException if value is improperly specified
*/
public static X500NameAttribute getInstance(Node root)
throws ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing"
+ "a X500NameAttribute");
}
/**
* Returns a new <code>X500NameAttribute</code> that represents
* the X500 Name value indicated by the string provided.
*
* @param value a string representing the desired value
* @return a new <code>X500NameAttribute</code> representing the
* appropriate value
* @throws IllegalArgumentException if value is improperly specified
*/
public static X500NameAttribute getInstance(String value)
throws IllegalArgumentException, ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "X500NameAttribute from null input");
}
return new X500NameAttribute(new X500Principal(value));
}
/**
* Returns the name value represented by this object
*
* @return the name
*/
public X500Principal getValue() {
return this.value;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class. This method
* deviates slightly from the XACML spec in the way that it handles
* RDNs with multiple attributeTypeAndValue pairs and some
* additional canonicalization steps. This method uses
* the procedure used by
* <code>javax.security.auth.x500.X500Principal.equals()</code>, while the
* XACML spec uses a slightly different procedure. In practice, it is
* expected that this difference will not be noticeable. For more
* details, refer to the javadoc for <code>X500Principal.equals()</code>
* and the XACML specification.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof X500NameAttribute)) {
return false;
}
X500NameAttribute other = (X500NameAttribute)o;
return this.value.equals(other.value);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
return this.value.hashCode();
}
/**
* @return The String encoding this AttributeValue.
*/
public String encode() {
return this.value.getName();
}
}

View File

@ -0,0 +1,428 @@
/*
* @(#)YearMonthDurationAttribute.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 com.sun.xacml.attr;
import com.sun.xacml.Constants;
import com.sun.xacml.ParsingException;
import java.math.BigInteger;
import java.net.URI;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.regex.Matcher;
import org.w3c.dom.Node;
/**
* Representation of an xf:yearMonthDuration value. This class supports parsing
* xd:yearMonthDuration values. All objects of this class are immutable and
* thread-safe. The <code>Date</code> objects returned are not, but
* these objects are cloned before being returned.
*
* @since 1.0
* @author Steve Hanna
*/
public class YearMonthDurationAttribute extends AttributeValue
{
/**
* Official name of this type
*/
public static final String identifier =
TypeIdentifierConstants.YEARMONTHDURATION;
/**
* URI version of name for this type
* <p>
* This field is initialized by a static initializer so that
* we can catch any exceptions thrown by URI(String) and
* transform them into a RuntimeException, since this should
* never happen but should be reported properly if it ever does.
*/
private static URI identifierURI;
/**
* RuntimeException that wraps an Exception thrown during the
* creation of identifierURI, null if none.
*/
private static RuntimeException earlyException;
/**
* Static initializer that initializes the identifierURI
* class field so that we can catch any exceptions thrown
* by URI(String) and transform them into a RuntimeException.
* Such exceptions should never happen but should be reported
* properly if they ever do.
*/
static {
try {
identifierURI = URI.create(identifier);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Regular expression for yearMonthDuration (a la java.util.regex)
*/
private static final String patternString =
"(\\-)?P((\\d+)?Y)?((\\d+)?M)?";
/**
* The index of the capturing group for the negative sign.
*/
private static final int GROUP_SIGN = 1;
/**
* The index of the capturing group for the number of years.
*/
private static final int GROUP_YEARS = 3;
/**
* The index of the capturing group for the number of months.
*/
private static final int GROUP_MONTHS = 5;
/**
* Static BigInteger values. We only use these if one of
* the components is bigger than Integer.MAX_LONG and we
* want to detect overflow.
*/
private static BigInteger big12 = BigInteger.valueOf(12);
private static BigInteger bigMaxLong = BigInteger.valueOf(Long.MAX_VALUE);
/**
* A shared Pattern object, only initialized if needed
*/
private static Pattern pattern;
/**
* Negative flag. true if duration is negative, false otherwise
*/
private boolean negative;
/**
* Number of years
*/
private long years;
/**
* Number of months
*/
private long months;
/**
* Total number of months (used for equals)
*/
private long totalMonths;
/**
* Cached encoded value (null if not cached yet).
*/
private String encodedValue = null;
/**
* Creates a new <code>YearMonthDurationAttribute</code> that represents
* the duration supplied.
*
* @param negative true if the duration is negative, false otherwise
* @param years the number of years in the duration (must be positive)
* @param months the number of months in the duration (must be positive)
* @throws IllegalArgumentException if the total number of months
* exceeds Long.MAX_LONG or the number
* of months or years is negative
*/
public YearMonthDurationAttribute(boolean negative, long years,
long months)
throws IllegalArgumentException {
super(identifierURI);
// Shouldn't happen, but just in case...
if (earlyException != null) {
throw earlyException;
}
this.negative = negative;
this.years = years;
this.months = months;
// Convert all the components except nanoseconds to milliseconds
// If any of the components is big (too big to be an int),
// use the BigInteger class to do the math so we can detect
// overflow.
if ((years > Integer.MAX_VALUE) || (months > Integer.MAX_VALUE)) {
BigInteger bigMonths = BigInteger.valueOf(months);
BigInteger bigYears = BigInteger.valueOf(years);
BigInteger bigTotal = bigYears.multiply(big12).add(bigMonths);
// If the result is bigger than Long.MAX_VALUE, we have an
// overflow. Indicate an error (should be a processing error,
// since it can be argued that we should handle gigantic
// values for this).
if (bigTotal.compareTo(bigMaxLong) == 1) {
throw new IllegalArgumentException("total number of " +
"months " +
"exceeds Long.MAX_VALUE");
}
// If no overflow, convert to a long.
this.totalMonths = bigTotal.longValue();
if (negative) {
this.totalMonths = - this.totalMonths;
}
} else {
// The numbers are small, so do it the fast way.
this.totalMonths = ((years * 12) + months) * (negative ? -1 : 1);
}
}
/**
* Returns a new <code>YearMonthDurationAttribute</code> that represents
* the xf:yearMonthDuration at a particular DOM node.
*
* @param root the <code>Node</code> that contains the desired value
* @return a new <code>YearMonthDurationAttribute</code> representing the
* appropriate value
* @throws ParsingException if any problems occurred while parsing
*/
public static YearMonthDurationAttribute getInstance(Node root)
throws ParsingException {
if (root.getFirstChild() != null) {
return getInstance(root.getFirstChild().getNodeValue());
}
throw new ParsingException("Error while parsing a "
+ "YearMonthDurationAttribute");
}
/**
* Returns the long value for the capturing group groupNumber.
* This method takes a Matcher that has been used to match a
* Pattern against a String, fetches the value for the specified
* capturing group, converts that value to an long, and returns
* the value. If that group did not match, 0 is returned.
* If the matched value is not a valid long, NumberFormatException
* is thrown.
*
* @param matcher the Matcher from which to fetch the group
* @param groupNumber the group number to fetch
* @return the long value for that groupNumber
* @throws NumberFormatException if the string value for that
* groupNumber is not a valid long
*/
private static long parseGroup(Matcher matcher, int groupNumber)
throws NumberFormatException {
long groupLong = 0;
if (matcher.start(groupNumber) != -1) {
String groupString = matcher.group(groupNumber);
groupLong = Long.parseLong(groupString);
}
return groupLong;
}
/**
* Returns a new <code>YearMonthDurationAttribute</code> that represents
* the xf:yearMonthDuration value indicated by the string provided.
*
* @param value a string representing the desired value
*
* @return a new <code>YearMonthDurationAttribute</code> representing the
* desired value
*
* @throws ParsingException if any problems occurred while parsing
*/
public static YearMonthDurationAttribute getInstance(String value)
throws ParsingException {
if (value == null) {
throw new ParsingException("Can't create a "
+ "YearMonthDurationAttribute from empty input");
}
boolean negative = false;
long years = 0;
long months = 0;
// Compile the pattern, if not already done.
if (pattern == null) {
try {
pattern = Pattern.compile(patternString);
} catch (PatternSyntaxException e) {
// This should never happen
throw new ParsingException("unexpected pattern syntax error");
}
}
// See if the value matches the pattern.
Matcher matcher = pattern.matcher(value);
boolean matches = matcher.matches();
// If not, syntax error!
if (!matches) {
throw new ParsingException("Syntax error in yearMonthDuration");
}
// If the negative group matched, the value is negative.
if (matcher.start(GROUP_SIGN) != -1) {
negative = true;
}
try {
// If the years group matched, parse that value.
years = parseGroup(matcher, GROUP_YEARS);
// If the months group matched, parse that value.
months = parseGroup(matcher, GROUP_MONTHS);
} catch (NumberFormatException e) {
// If we run into a number that's too big to be a long
// that's an error. Really, it's a processing error,
// since one can argue that we should handle that.
throw new ParsingException("Unable to handle number size");
}
// If parsing went OK, create a new YearMonthDurationAttribute
// object and return it.
return new YearMonthDurationAttribute(negative, years, months);
}
/**
* Returns true if the duration is negative.
*
* @return true if the duration is negative, false otherwise
*/
public boolean isNegative() {
return this.negative;
}
/**
* Gets the number of years.
*
* @return the number of years
*/
public long getYears() {
return this.years;
}
/**
* Gets the number of months.
*
* @return the number of months
*/
public long getMonths() {
return this.months;
}
/**
* Returns true if the input is an instance of this class and if its
* value equals the value contained in this class.
*
* @param o the object to compare
*
* @return true if this object and the input represent the same value
*/
public boolean equals(Object o) {
if (! (o instanceof YearMonthDurationAttribute)) {
return false;
}
YearMonthDurationAttribute other = (YearMonthDurationAttribute)o;
return (this.totalMonths == other.totalMonths);
}
/**
* Returns the hashcode value used to index and compare this object with
* others of the same type. Typically this is the hashcode of the backing
* data object.
*
* @return the object's hashcode value
*/
public int hashCode() {
return (int) this.totalMonths ^ (int) (this.totalMonths >> 32);
}
/**
* Converts to a String representation.
*
* @return the String representation
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("YearMonthDurationAttribute: [" + Constants.nl);
sb.append(" Negative: " + this.negative);
sb.append(" Years: " + this.years);
sb.append(" Months: " + this.months);
sb.append("]");
return sb.toString();
}
/**
* Encodes the value in a form suitable for including in XML data like
* a request or an obligation. This must return a value that could in
* turn be used by the factory to create a new instance with the same
* value.
*
* @return a <code>String</code> form of the value
*/
public String encode() {
if (this.encodedValue != null) {
return this.encodedValue;
}
// Length is variable
StringBuffer buf = new StringBuffer(10);
if (this.negative) {
buf.append('-');
}
buf.append('P');
if ((this.years != 0) || (this.months == 0)) {
buf.append(Long.toString(this.years));
buf.append('Y');
}
if (this.months != 0) {
buf.append(Long.toString(this.months));
buf.append('M');
}
this.encodedValue = buf.toString();
return this.encodedValue;
}
}

View File

@ -0,0 +1,7 @@
<body>
Contains many of the classes related to attributes and attribute
retrieval. This package contains the base class for all attributes, as
well as implementations of all of the standard attribute types. The
AttributeDesignatorType and the AttributeSelectorType are also
represented here.
</body>

View File

@ -0,0 +1,70 @@
/*
* @(#)AnyURIAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AnyURIAttribute;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class AnyURIAttributeProxy implements AttributeProxy
{
/**
* @see com.sun.xacml.attr.AttributeProxy#getInstance(org.w3c.dom.Node)
*/
public AttributeValue getInstance(Node root) throws Exception {
return AnyURIAttribute.getInstance(root);
}
/**
* @see com.sun.xacml.attr.AttributeProxy#getInstance(java.lang.String)
*/
public AttributeValue getInstance(String value) throws Exception {
return AnyURIAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)Base64BinaryAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.Base64BinaryAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class Base64BinaryAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return Base64BinaryAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return Base64BinaryAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)BooleanAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.BooleanAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class BooleanAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return BooleanAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return BooleanAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,65 @@
/*
* @(#)DNSNameAttributeProxy.java
*
* Copyright 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.attr.proxy;
import com.sun.xacml.ParsingException;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.DNSNameAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 2.0
* @author Seth Proctor
*/
public class DNSNameAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return DNSNameAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws ParsingException {
return DNSNameAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)DateAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.DateAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class DateAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return DateAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return DateAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)DateTimeAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.DateTimeAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class DateTimeAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return DateTimeAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return DateTimeAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)DayTimeDurationAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.DayTimeDurationAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class DayTimeDurationAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return DayTimeDurationAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return DayTimeDurationAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)DoubleAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.DoubleAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class DoubleAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return DoubleAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return DoubleAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)HexBinaryAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.HexBinaryAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class HexBinaryAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return HexBinaryAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return HexBinaryAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,66 @@
/*
* @(#)IPAddressAttributeProxy.java
*
* Copyright 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.attr.proxy;
import com.sun.xacml.ParsingException;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.IPAddressAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 2.0
* @author Seth Proctor
*/
public class IPAddressAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws ParsingException {
return IPAddressAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws ParsingException {
return IPAddressAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)IntegerAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.IntegerAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class IntegerAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return IntegerAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return IntegerAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)RFC822NameAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.RFC822NameAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class RFC822NameAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return RFC822NameAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return RFC822NameAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,65 @@
/*
* @(#)StringAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.ParsingException;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.StringAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class StringAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws ParsingException {
return StringAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) {
return StringAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)TimeAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.TimeAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class TimeAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return TimeAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return TimeAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)X500NameAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.X500NameAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class X500NameAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return X500NameAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return X500NameAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,64 @@
/*
* @(#)YearMonthDurationAttributeProxy.java
*
* Copyright 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 com.sun.xacml.attr.proxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.YearMonthDurationAttribute;
import org.w3c.dom.Node;
/**
* A proxy class that is provided mainly for the run-time configuration
* code to use.
*
* @since 1.2
* @author Seth Proctor
*/
public class YearMonthDurationAttributeProxy implements AttributeProxy
{
public AttributeValue getInstance(Node root) throws Exception {
return YearMonthDurationAttribute.getInstance(root);
}
public AttributeValue getInstance(String value) throws Exception {
return YearMonthDurationAttribute.getInstance(value);
}
}

View File

@ -0,0 +1,8 @@
<body>
This package defines proxy classes for all of the standard
datatypes. This package was introduced in version 1.2 with the new
run-time configuration code, which needs concrete proxy classes to add
datatype support to a factory. Before 1.2, the
<code>AttributeFactory</code> used annonymous classes to cut down on
the total number of files in this project.
</body>

View File

@ -0,0 +1,156 @@
/*
* @(#)BaseCombiningAlgFactory.java
*
* Copyright 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 com.sun.xacml.combine;
import com.sun.xacml.UnknownIdentifierException;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/**
* This is a basic implementation of <code>CombiningAlgFactory</code>. It
* implements the insertion and retrieval methods, but doesn't actually
* setup the factory with any algorithms.
* <p>
* Note that while this class is thread-safe on all creation methods, it
* is not safe to add support for a new algorithm while creating an instance
* of an algorithm. This follows from the assumption that most people will
* initialize these factories up-front, and then start processing without
* ever modifying the factories. If you need these mutual operations to
* be thread-safe, then you should write a wrapper class that implements
* the right synchronization.
*
* @since 1.2
* @author Seth Proctor
*/
public class BaseCombiningAlgFactory extends CombiningAlgFactory
{
// the map of available combining algorithms
private HashMap<String, CombiningAlgorithm> algMap;
/**
* Default constructor.
*/
public BaseCombiningAlgFactory() {
this.algMap = new HashMap<String, CombiningAlgorithm>();
}
/**
* Constructor that configures this factory with an initial set of
* supported algorithms.
*
* @param algorithms a <code>Set</code> of
* </code>CombiningAlgorithm</code>s
*
* @throws IllegalArgumentException if any elements of the set are not
* </code>CombiningAlgorithm</code>s
*/
public BaseCombiningAlgFactory(Set<CombiningAlgorithm> algorithms) {
this.algMap = new HashMap<String, CombiningAlgorithm>();
Iterator<CombiningAlgorithm> it = algorithms.iterator();
while (it.hasNext()) {
try {
CombiningAlgorithm alg = it.next();
this.algMap.put(alg.getIdentifier().toString(), alg);
} catch (ClassCastException cce) {
throw new IllegalArgumentException("an element of the set " +
"was not an instance of " +
"CombiningAlgorithm");
}
}
}
/**
* Adds a combining algorithm to the factory. This single instance will
* be returned to anyone who asks the factory for an algorithm with the
* id given here.
*
* @param alg the combining algorithm to add
*
* @throws IllegalArgumentException if the algId is already registered
*/
public void addAlgorithm(CombiningAlgorithm alg) {
String algId = alg.getIdentifier().toString();
// check that the id doesn't already exist in the factory
if (this.algMap.containsKey(algId)) {
throw new IllegalArgumentException("algorithm already registered: "
+ algId);
}
// add the algorithm
this.algMap.put(algId, alg);
}
/**
* Returns the algorithm identifiers supported by this factory.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public Set<String> getSupportedAlgorithms() {
return Collections.unmodifiableSet(this.algMap.keySet());
}
/**
* Tries to return the correct combinging algorithm based on the
* given algorithm ID.
*
* @param algId the identifier by which the algorithm is known
*
* @return a combining algorithm
*
* @throws UnknownIdentifierException algId is unknown
*/
public CombiningAlgorithm createAlgorithm(URI algId)
throws UnknownIdentifierException
{
String id = algId.toString();
if (this.algMap.containsKey(id)) {
return (CombiningAlgorithm)(this.algMap.get(algId.toString()));
}
throw new UnknownIdentifierException("unknown combining algId: "
+ id);
}
}

View File

@ -0,0 +1,130 @@
/*
* @(#)CombinerElement.java
*
* Copyright 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 com.sun.xacml.combine;
import com.sun.xacml.Indenter;
import com.sun.xacml.PolicyTreeElement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/**
* Represents one input (a Rule, Policy, PolicySet, or reference) to a
* combining algorithm and combiner parameters associated with that input.
*
* @since 2.0
* @author Seth Proctor
*/
public abstract class CombinerElement
{
// the element to be combined
private PolicyTreeElement element;
// the parameters used with this element
private List<CombinerParameter> parameters;
/**
* Constructor that only takes an element. No parameters are associated
* with this element when combining.
*
* @param element a <code>PolicyTreeElement</code> to use in combining
*/
public CombinerElement(PolicyTreeElement element) {
this(element, null);
}
/**
* Constructor that takes both the element to combine and its associated
* combiner parameters.
*
* @param element a <code>PolicyTreeElement</code> to use in combining
* @param parameters a (possibly empty) non-null <code>List</code> of
* <code>CombinerParameter<code>s provided for general
* use (for all pre-2.0 policies this must be empty)
*/
public CombinerElement(PolicyTreeElement element, List<CombinerParameter> parameters) {
this.element = element;
if (parameters == null) {
this.parameters = Collections.unmodifiableList(new ArrayList<CombinerParameter>());
} else {
this.parameters = Collections.
unmodifiableList(new ArrayList<CombinerParameter>(parameters));
}
}
/**
* Returns the <code>PolicyTreeElement</code> in this element.
*
* @return the <code>PolicyTreeElement</code>
*/
public PolicyTreeElement getElement() {
return this.element;
}
/**
* Returns the <code>CombinerParameter</code>s associated with this
* element.
*
* @return a <code>List</code> of <code>CombinerParameter</code>s
*/
public List<CombinerParameter> getParameters() {
return this.parameters;
}
/**
* Encodes the element and parameters in this <code>CombinerElement</code>
* into their 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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*/
public abstract void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException;
}

View File

@ -0,0 +1,204 @@
/*
* @(#)CombinerParameter.java
*
* Copyright 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 com.sun.xacml.combine;
import com.sun.xacml.Indenter;
import com.sun.xacml.ParsingException;
import com.sun.xacml.UnknownIdentifierException;
import com.sun.xacml.attr.AttributeFactory;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.debug.Locatable;
import com.sun.xacml.debug.RuntimeInfo;
import com.sun.xacml.debug.RuntimeInfo.ELEMENT_TYPE;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.List;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Represents a single named parameter to a combining algorithm. Parameters
* are only used by XACML 2.0 and later policies.
*
* @since 2.0
* @author Seth Proctor
*/
public class CombinerParameter implements Locatable
{
// the name of this parameter
private String name;
// the value of this parameter
private AttributeValue value;
public static final List<CombinerParameter> EMPTY_LIST = Collections.<CombinerParameter>emptyList();
private RuntimeInfo src;
/**
* Creates a new CombinerParameter.
*
* @param name the parameter's name
* @param value the parameter's value
*/
public CombinerParameter(String name, AttributeValue value) {
this.name = name;
this.value = value;
}
/**
* Returns a new instance of the <code>CombinerParameter</code> class
* based on a DOM node. The node must be the root of an XML
* CombinerParameterType.
*
* @param root the DOM root of a CombinerParameterType XML type
*
* @return The combiner parameter.
*
* @throws ParsingException if the CombinerParameterType is invalid
*/
public static CombinerParameter getInstance(Node root)
throws ParsingException {
RuntimeInfo src = RuntimeInfo.getRuntimeInfo(root, ELEMENT_TYPE.COMBINER_PARAMETER);
// check if this really is a CombinerParameter
if (root.getNodeType() != Node.ELEMENT_NODE
|| !root.getLocalName().equals("CombinerParameter")) {
throw new ParsingException("Can't create a CombinerParameter "
+ "from a " + root.getLocalName() + " element"
+ ( src == null ? "" : src.getLocationMsgForError()));
}
// get the name, which is a required attribute
String name = null;
if (root.getAttributes().getNamedItem("ParameterName") != null) {
name = root.getAttributes().getNamedItem("ParameterName")
.getNodeValue();
} else {
throw new ParsingException("Required XML attribute ParameterName"
+ " not found while parsing a CombinerParameter"
+ ( src == null ? "" : src.getLocationMsgForError()));
}
// get the attribute value, the only child of this element
AttributeFactory attrFactory = AttributeFactory.getInstance();
AttributeValue value = null;
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if ( child.getNodeType() == Node.ELEMENT_NODE ) {
try {
value = attrFactory.createValue(child);
break;
} catch (UnknownIdentifierException uie) {
throw new ParsingException("Unknown AttributeId"
+ ( src == null ? "" : src.getLocationMsgForError()), uie);
}
}
}
if ( value == null ) {
throw new ParsingException("Missing AttributeValue for CombinerParameter" +
( src == null ? "" : src.getLocationMsgForError()));
}
CombinerParameter param = new CombinerParameter(name, value);
param.src = src;
return param;
}
/**
* Returns the name of this parameter.
*
* @return the name of this parameter
*/
public String getName() {
return this.name;
}
/**
* Returns the value provided by this parameter.
*
* @return the value provided by this parameter
*/
public AttributeValue getValue() {
return this.value;
}
/**
* Encodes this parameter 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 charsetName the character set to use in encoding of strings.
* This may be null in which case the platform
* default character set will be used.
* @param indenter an object that creates indentation strings
*
* @throws UnsupportedEncodingException
*/
public void encode(OutputStream output, String charsetName,
Indenter indenter)
throws UnsupportedEncodingException {
PrintStream out;
if(charsetName == null) {
out = new PrintStream(output);
} else {
out = new PrintStream(output, false, charsetName);
}
String indent = indenter.makeString();
out.println(indent + "<CombinerParameter ParameterName=\"" +
getName() + "\">");
indenter.in();
getValue().encode(output, charsetName, indenter);
out.println(indent + "</CombinerParameter>");
indenter.out();
}
public RuntimeInfo getRuntimeInfo() {
return src;
}
}

View File

@ -0,0 +1,273 @@
/*
* @(#)CombiningAlgFactory.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.combine;
import com.sun.xacml.Constants;
import com.sun.xacml.UnknownIdentifierException;
import java.net.URI;
import java.util.HashMap;
import java.util.Set;
/**
* Provides a factory mechanism for installing and retrieving combining
* algorithms.
*
* @since 1.0
* @author Seth Proctor
*/
public abstract class CombiningAlgFactory
{
// the proxy used to get the default factory
private static CombiningAlgFactoryProxy defaultFactoryProxy;
// the map of registered factories
private static HashMap<String, CombiningAlgFactoryProxy> registeredFactories
= new HashMap<String, CombiningAlgFactoryProxy>();
// <BUG> ignores the configuration, i.e., <combiningAlgFactory useStandardAlgorithms="false">
// /**
// * static intialiazer that sets up the default factory proxy and
// * registers the standard namespaces
// */
// static {
// CombiningAlgFactoryProxy proxy = new CombiningAlgFactoryProxy() {
// public CombiningAlgFactory getFactory() {
// return StandardCombiningAlgFactory.getFactory();
// }
// };
//
// registeredFactories = new HashMap<String, CombiningAlgFactoryProxy>();
// registeredFactories.put(Constants.XACML_1_0_IDENTIFIER, proxy);
// registeredFactories.put(Constants.XACML_2_0_IDENTIFIER, proxy);
// registeredFactories.put(Constants.XACML_3_0_IDENTIFIER, proxy);
//
// defaultFactoryProxy = proxy;
// }
// </BUG>
/**
* Default constructor. Used only by subclasses.
*/
protected CombiningAlgFactory() {
//used only by subclasses
}
/**
* Returns the default factory. Depending on the default factory's
* implementation, this may return a singleton instance or new instances
* with each invokation.
*
* @return the default <code>CombiningAlgFactory</code>
*/
public static final CombiningAlgFactory getInstance() {
return defaultFactoryProxy.getFactory();
}
/**
* Returns a factory based on the given identifier. You may register
* as many factories as you like, and then retrieve them through this
* interface, but a factory may only be registered once using a given
* identifier. By default, the standard XACML 1.0, 2.0 and 3.0 identifiers
* are regsietered to provide the standard factory.
*
* @param identifier the identifier for a factory
*
* @return a <code>CombiningAlgFactory</code>
*
* @throws UnknownIdentifierException if the given identifier isn't
* registered
*/
public static final CombiningAlgFactory getInstance(String identifier)
throws UnknownIdentifierException
{
CombiningAlgFactoryProxy proxy =
(CombiningAlgFactoryProxy)(registeredFactories.get(identifier));
if (proxy == null) {
throw new UnknownIdentifierException("Uknown CombiningAlgFactory "
+ "identifier: " +
identifier);
}
return proxy.getFactory();
}
/**
* Sets the default factory. This does not register the factory proxy as
* an identifiable factory.
*
* @param proxy the <code>CombiningAlgFactoryProxy</code> to set as the
* new default factory proxy
*/
public static final void setDefaultFactory(CombiningAlgFactoryProxy proxy)
{
defaultFactoryProxy = proxy;
}
public static final void setAllFactories(CombiningAlgFactory factory) {
CombiningAlgFactoryProxyImpl proxy = new CombiningAlgFactoryProxyImpl(factory);
registeredFactories.put(Constants.XACML_1_0_IDENTIFIER, proxy);
registeredFactories.put(Constants.XACML_2_0_IDENTIFIER, proxy);
registeredFactories.put(Constants.XACML_3_0_IDENTIFIER, proxy);
defaultFactoryProxy = proxy;
}
/**
* Registers the given factory proxy with the given identifier. If the
* identifier is already used, then this throws an exception. If the
* identifier is not already used, then it will always be bound to the
* given proxy.
*
* @param identifier the identifier for the proxy
* @param proxy the <code>CombiningAlgFactoryProxy</code> to register with
* the given identifier
*
* @throws IllegalArgumentException if the identifier is already used
*/
public static final void registerFactory(String identifier,
CombiningAlgFactoryProxy proxy)
throws IllegalArgumentException
{
synchronized (registeredFactories) {
if (registeredFactories.containsKey(identifier)) {
throw new IllegalArgumentException("Identifier is already " +
"registered as " +
"CombiningAlgFactory: " +
identifier);
}
registeredFactories.put(identifier, proxy);
}
}
/**
* Adds a combining algorithm to the factory. This single instance will
* be returned to anyone who asks the factory for an algorithm with the
* id given here.
*
* @param alg the combining algorithm to add
*
* @throws IllegalArgumentException if the algorithm is already registered
*/
public abstract void addAlgorithm(CombiningAlgorithm alg);
/**
* Adds a combining algorithm to the factory. This single instance will
* be returned to anyone who asks the factory for an algorithm with the
* id given here.
*
* @deprecated As of version 1.2, replaced by
* {@link #addAlgorithm(CombiningAlgorithm)}.
* The new factory system requires you to get a factory
* instance and then call the non-static methods on that
* factory. The static versions of these methods have been
* left in for now, but are slower and will be removed in
* a future version.
*
* @param alg the combining algorithm to add
*
* @throws IllegalArgumentException if the algorithm is already registered
*/
public static void addCombiningAlg(CombiningAlgorithm alg) {
getInstance().addAlgorithm(alg);
}
/**
* Returns the algorithm identifiers supported by this factory.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public abstract Set<String> getSupportedAlgorithms();
/**
* Tries to return the correct combinging algorithm based on the
* given algorithm ID.
*
* @param algId the identifier by which the algorithm is known
*
* @return a combining algorithm
*
* @throws UnknownIdentifierException algId is unknown
*/
public abstract CombiningAlgorithm createAlgorithm(URI algId)
throws UnknownIdentifierException;
/**
* Tries to return the correct combinging algorithm based on the
* given algorithm ID.
*
* @deprecated As of version 1.2, replaced by
* {@link #createAlgorithm(URI)}.
* The new factory system requires you to get a factory
* instance and then call the non-static methods on that
* factory. The static versions of these methods have been
* left in for now, but are slower and will be removed in
* a future version.
*
* @param algId the identifier by which the algorithm is known
*
* @return a combining algorithm
*
* @throws UnknownIdentifierException algId is unknown
*/
public static CombiningAlgorithm createCombiningAlg(URI algId)
throws UnknownIdentifierException
{
return getInstance().createAlgorithm(algId);
}
private static class CombiningAlgFactoryProxyImpl implements CombiningAlgFactoryProxy {
CombiningAlgFactory factory;
CombiningAlgFactoryProxyImpl(CombiningAlgFactory factory) {
this.factory = factory;
}
public CombiningAlgFactory getFactory() {
return factory;
}
}
}

View File

@ -0,0 +1,58 @@
/*
* @(#)CombiningAlgFactoryProxy.java
*
* Copyright 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 com.sun.xacml.combine;
/**
* A simple proxy interface used to install new
* <code>CombiningAlgFactory</code>s.
*
* @since 1.2
* @author Seth Proctor
*/
public interface CombiningAlgFactoryProxy
{
/**
* Returns an instance of the <code>CombiningAlgFactory</code> for which
* this is a proxy.
*
* @return a <code>CombiningAlgFactory</code> instance
*/
public CombiningAlgFactory getFactory();
}

View File

@ -0,0 +1,161 @@
/*
* @(#)CombiningAlgorithm.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 com.sun.xacml.combine;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.ctx.Result;
import com.sun.xacml.debug.IndirectLocatable;
import com.sun.xacml.debug.RuntimeInfo;
import java.net.URI;
import java.util.List;
import java.util.Stack;
import org.apache.log4j.Logger;
/**
* The base type for all combining algorithms. It provides one method that
* must be implemented.
*
* @since 1.0
* @author Seth Proctor
*/
public abstract class CombiningAlgorithm implements IndirectLocatable
{
// the identifier for the algorithm
private URI identifier;
//private RuntimeInfo src;
private Stack<RuntimeInfo> src;
private static Logger logger = Logger.getLogger(CombiningAlgorithm.class);
/**
* Constructor that takes the algorithm's identifier.
*
* @param identifier the algorithm's identifier
*/
public CombiningAlgorithm(URI identifier) {
this.identifier = identifier;
}
/**
* Combines the results of the inputs based on the context to produce
* some unified result. This is the one function of a combining algorithm.
*
* @param context the representation of the request
* @param parameters a (possibly empty) non-null <code>List</code> of
* <code>CombinerParameter<code>s provided for general
* use (for all pre-2.0 policies this must be empty)
* @param inputs a <code>List</code> of <code>CombinerElements</code>s to
* evaluate and combine
*
* @return a single unified result based on the combining logic
*/
public abstract Result combine(EvaluationCtx context, List<CombinerParameter> parameters,
List<CombinerElement> inputs);
/**
* Returns the identifier for this algorithm.
*
* @return the algorithm's identifier
*/
public URI getIdentifier() {
return this.identifier;
}
public RuntimeInfo getRuntimeInfo() {
if ( this.src != null && this.src.size() > 0 ) {
return this.src.get(this.src.size()-1);
} else {
return null;
}
//return this.src;
}
/**
* Implements the IndirectLocatable interface
*/
public void setRuntimeInfo(RuntimeInfo src) {
if ( this.src == null ) {
this.src = new Stack<RuntimeInfo>();
}
this.src.push(src);
// if ( this.src != null ) {
// logger.warn("Overwriting SourceLocator! This indicates that " +
// "serveral threads are used to query the enginge which " +
// "should NOT be the case when the source locator feature " +
// "is enabled (overwrite" +
// ( this.src == null ? "null" : this.src.getLocationMsgForError()) + " with " +
// ( src == null ? "null" : src.getLocationMsgForError()));
// try {
// throw new Exception();
// } catch(Exception e) {
// e.printStackTrace();
// }
// }
// this.src = src;
}
/**
* Implements the IndirectLocatable interface
*/
public void unsetRuntimeInfo(RuntimeInfo src) {
if ( this.src != null ) {
RuntimeInfo src_pop = this.src.pop();
if ( src_pop != src ) {
logger.warn("Unset Source Locator Object which did not match the current "
+ "element on the stack");
this.src.removeAllElements();
}
}
// if ( src != this.src ) {
// logger.warn("Unset Source Locator Object which is currently unvalid! (from " +
// ( this.src == null ? "null" : this.src.getLocationMsgForError()) + " with " +
// ( src == null ? "null" : src.getLocationMsgForError()));
// }
// this.src = null;
}
}

View File

@ -0,0 +1,179 @@
/*
* @(#)DenyOverridesPolicyAlg.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 com.sun.xacml.combine;
import com.sun.xacml.AbstractPolicy;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.MatchResult;
import com.sun.xacml.Obligation;
import com.sun.xacml.ctx.Result;
import java.net.URI;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* This is the standard Deny Overrides policy combining algorithm. It
* allows a single evaluation of Deny to take precedence over any number
* of permit, not applicable or indeterminate results. Note that since
* this implementation does an ordered evaluation, this class also
* supports the Ordered Deny Overrides algorithm.
*
* @since 1.0
* @author Seth Proctor
*/
public class DenyOverridesPolicyAlg extends PolicyCombiningAlgorithm
{
/**
* The standard URN used to identify this algorithm
*/
public static final String algId =
"urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:" +
"deny-overrides";
// a URI form of the identifier
private static URI identifierURI;
// exception if the URI was invalid, which should never be a problem
private static RuntimeException earlyException;
static {
try {
identifierURI = URI.create(algId);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Standard constructor.
*/
public DenyOverridesPolicyAlg() {
super(identifierURI);
if (earlyException != null) {
throw earlyException;
}
}
/**
* Protected constructor used by the ordered version of this algorithm.
*
* @param identifier the algorithm's identifier
*/
protected DenyOverridesPolicyAlg(URI identifier) {
super(identifier);
}
/**
* Applies the combining rule to the set of policies based on the
* evaluation context.
*
* @param context the context from the request
* @param parameters a (possibly empty) non-null <code>List</code> of
* <code>CombinerParameter<code>s
* @param policyElements the policies to combine
*
* @return the result of running the combining algorithm
*/
public Result combine(EvaluationCtx context, List<CombinerParameter> parameters,
List<CombinerElement> policyElements) {
boolean atLeastOnePermit = false;
Set<Obligation> permitObligations = new HashSet<Obligation>();
Iterator<CombinerElement> it = policyElements.iterator();
while (it.hasNext()) {
AbstractPolicy policy = ((PolicyCombinerElement) it.next()).getPolicy();
// make sure that the policy matches the context
context.newEvent(policy);
MatchResult match = policy.match(context);
if (match.getResult() == MatchResult.INDETERMINATE) {
Result result = new Result(Result.DECISION_DENY, context);
context.closeCurrentEvent(result);
return result;
}
if (match.getResult() == MatchResult.NO_MATCH) {
context.closeCurrentEvent(
new Result(Result.DECISION_NOT_APPLICABLE));
}
if (match.getResult() == MatchResult.MATCH) {
// evaluate the policy
Result result = policy.evaluate(context);
context.closeCurrentEvent(result);
// do not treat the discarded values
if (result != null) {
int effect = result.getDecision();
// unlike in the RuleCombining version of this alg, we
// always return DENY if any Policy returns DENY or
// INDETERMINATE
if ((effect == Result.DECISION_DENY) ||
(effect == Result.DECISION_INDETERMINATE)) {
return new Result(Result.DECISION_DENY,
context,
result.getObligations());
}
// remember if at least one Policy said PERMIT
if (effect == Result.DECISION_PERMIT) {
atLeastOnePermit = true;
permitObligations.addAll(result.getObligations());
}
}
}
}
// if we got a PERMIT, return it, otherwise it's NOT_APPLICABLE
if (atLeastOnePermit) {
return new Result(Result.DECISION_PERMIT,
context,
permitObligations);
}
return new Result(Result.DECISION_NOT_APPLICABLE,
context);
}
}

View File

@ -0,0 +1,184 @@
/*
* @(#)DenyOverridesRuleAlg.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 com.sun.xacml.combine;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.Rule;
import com.sun.xacml.ctx.Result;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
/**
* This is the standard Deny Overrides rule combining algorithm. It
* allows a single evaluation of Deny to take precedence over any number
* of permit, not applicable or indeterminate results. Note that since
* this implementation does an ordered evaluation, this class also
* supports the Ordered Deny Overrides algorithm.
*
* @since 1.0
* @author Seth Proctor
*/
public class DenyOverridesRuleAlg extends RuleCombiningAlgorithm
{
/**
* The standard URN used to identify this algorithm
*/
public static final String algId =
"urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:" +
"deny-overrides";
// a URI form of the identifier
private static URI identifierURI;
// exception if the URI was invalid, which should never be a problem
private static RuntimeException earlyException;
static {
try {
identifierURI = URI.create(algId);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Standard constructor.
*/
public DenyOverridesRuleAlg() {
super(identifierURI);
if (earlyException != null) {
throw earlyException;
}
}
/**
* Protected constructor used by the ordered version of this algorithm.
*
* @param identifier the algorithm's identifier
*/
protected DenyOverridesRuleAlg(URI identifier) {
super(identifier);
}
/**
* Applies the combining rule to the set of rules based on the
* evaluation context.
*
* @param context the context from the request
* @param parameters a (possibly empty) non-null <code>List</code> of
* <code>CombinerParameter<code>s
* @param ruleElements the rules to combine
*
* @return the result of running the combining algorithm
*/
public Result combine(EvaluationCtx context, List<CombinerParameter> parameters,
List<CombinerElement> ruleElements) {
boolean atLeastOneError = false;
boolean potentialDeny = false;
boolean atLeastOnePermit = false;
Result firstIndeterminateResult = null;
Iterator<CombinerElement> it = ruleElements.iterator();
while (it.hasNext()) {
Rule rule = ((RuleCombinerElement)(it.next())).getRule();
Result result = rule.evaluate(context);
int value = result.getDecision();
// if there was a value of DENY, then regardless of what else
// we've seen, we always return DENY
if (value == Result.DECISION_DENY) {
return result;
}
// if it was INDETERMINATE, then we couldn't figure something
// out, so we keep track of these cases...
if (value == Result.DECISION_INDETERMINATE) {
atLeastOneError = true;
// there are no rules about what to do if multiple cases
// cause errors, so we'll just return the first one
if (firstIndeterminateResult == null) {
firstIndeterminateResult = result;
}
// if the Rule's effect is DENY, then we can't let this
// alg return PERMIT, since this Rule might have denied
// if it could do its stuff
if (rule.getEffect() == Result.DECISION_DENY) {
potentialDeny = true;
}
} else {
// keep track of whether we had at least one rule that
// actually pertained to the request
if (value == Result.DECISION_PERMIT) {
atLeastOnePermit = true;
}
}
}
// we didn't explicitly DENY, but we might have had some Rule
// been evaluated, so we have to return INDETERMINATE
if (potentialDeny) {
return firstIndeterminateResult;
}
// some Rule said PERMIT, so since nothing could have denied,
// we return PERMIT
if (atLeastOnePermit) {
return new Result(Result.DECISION_PERMIT,
context);
}
// we didn't find anything that said PERMIT, but if we had a
// problem with one of the Rules, then we're INDETERMINATE
if (atLeastOneError) {
return firstIndeterminateResult;
}
// if we hit this point, then none of the rules actually applied
// to us, so we return NOT_APPLICABLE
return new Result(Result.DECISION_NOT_APPLICABLE,
context);
}
}

View File

@ -0,0 +1,152 @@
/*
* @(#)FirstApplicablePolicyAlg.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 com.sun.xacml.combine;
import com.sun.xacml.AbstractPolicy;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.MatchResult;
import com.sun.xacml.ctx.Result;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
/**
* This is the standard First Applicable policy combining algorithm. It looks
* through the set of policies, finds the first one that applies, and returns
* that evaluation result.
*
* @since 1.0
* @author Seth Proctor
*/
public class FirstApplicablePolicyAlg extends PolicyCombiningAlgorithm
{
/**
* The standard URN used to identify this algorithm
*/
public static final String algId =
"urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:" +
"first-applicable";
// a URI form of the identifier
private static URI identifierURI;
// exception if the URI was invalid, which should never be a problem
private static RuntimeException earlyException;
static {
try {
identifierURI = URI.create(algId);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Standard constructor.
*/
public FirstApplicablePolicyAlg() {
super(identifierURI);
if (earlyException != null) {
throw earlyException;
}
}
/**
* Applies the combining rule to the set of policies based on the
* evaluation context.
*
* @param context the context from the request
* @param parameters a (possibly empty) non-null <code>List</code> of
* <code>CombinerParameter<code>s
* @param policyElements the policies to combine
*
* @return the result of running the combining algorithm
*/
public Result combine(EvaluationCtx context, List<CombinerParameter> parameters,
List<CombinerElement> policyElements) {
Iterator<CombinerElement> it = policyElements.iterator();
while (it.hasNext()) {
AbstractPolicy policy =
((PolicyCombinerElement)(it.next())).getPolicy();
// make sure that the policy matches the context
context.newEvent(policy);
MatchResult match = policy.match(context);
if (match.getResult() == MatchResult.INDETERMINATE) {
Result result = new Result(Result.DECISION_INDETERMINATE,
match.getStatus(),
context);
context.closeCurrentEvent(result);
return result;
}
if (match.getResult() == MatchResult.NO_MATCH) {
context.closeCurrentEvent(
new Result(Result.DECISION_NOT_APPLICABLE));
}
if (match.getResult() == MatchResult.MATCH) {
// evaluate the policy
Result result = policy.evaluate(context);
context.closeCurrentEvent(result);
// do not treat the discarded values
if (result != null) {
int effect = result.getDecision();
// in the case of PERMIT, DENY, or INDETERMINATE, we always
// just return that result, so only on a rule that doesn't
// apply do we keep going...
if (effect != Result.DECISION_NOT_APPLICABLE) {
return result;
}
}
}
}
// if we got here, then none of the rules applied
return new Result(Result.DECISION_NOT_APPLICABLE,
context);
}
}

View File

@ -0,0 +1,128 @@
/*
* @(#)FirstApplicableRuleAlg.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 com.sun.xacml.combine;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.Rule;
import com.sun.xacml.ctx.Result;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
/**
* This is the standard First Applicable rule combining algorithm. It looks
* through the set of rules, finds the first one that applies, and returns
* that evaluation result.
*
* @since 1.0
* @author Seth Proctor
*/
public class FirstApplicableRuleAlg extends RuleCombiningAlgorithm
{
/**
* The standard URN used to identify this algorithm
*/
public static final String algId =
"urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:" +
"first-applicable";
// a URI form of the identifier
private static URI identifierURI;
// exception if the URI was invalid, which should never be a problem
private static RuntimeException earlyException;
static {
try {
identifierURI = URI.create(algId);
} catch (IllegalArgumentException e) {
earlyException = e;
}
}
/**
* Standard constructor.
*/
public FirstApplicableRuleAlg() {
super(identifierURI);
if (earlyException != null) {
throw earlyException;
}
}
/**
* Applies the combining rule to the set of rules based on the
* evaluation context.
*
* @param context the context from the request
* @param parameters a (possibly empty) non-null <code>List</code> of
* <code>CombinerParameter<code>s
* @param ruleElements the rules to combine
*
* @return the result of running the combining algorithm
*/
public Result combine(EvaluationCtx context, List<CombinerParameter> parameters,
List<CombinerElement> ruleElements) {
Iterator<CombinerElement> it = ruleElements.iterator();
while (it.hasNext()) {
Rule rule = ((RuleCombinerElement)(it.next())).getRule();
Result result = rule.evaluate(context);
int value = result.getDecision();
// in the case of PERMIT, DENY, or INDETERMINATE, we always
// just return that result, so only on a rule that doesn't
// apply do we keep going...
if (value != Result.DECISION_NOT_APPLICABLE) {
return result;
}
}
// if we got here, then none of the rules applied
return new Result(Result.DECISION_NOT_APPLICABLE,
context);
}
}

Some files were not shown because too many files have changed in this diff Show More