Update of /cvsroot/sunxacml/sunxacml/com/sun/xacml/cond
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16626/com/sun/xacml/cond
Modified Files:
BaseFunctionFactory.java StandardFunctionFactory.java
Log Message:
re-factored so standard factories are immutable
Index: StandardFunctionFactory.java
===================================================================
RCS file: /cvsroot/sunxacml/sunxacml/com/sun/xacml/cond/StandardFunctionFactory.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** StandardFunctionFactory.java 18 Mar 2004 21:13:09 -0000 1.4
--- StandardFunctionFactory.java 24 May 2004 20:55:08 -0000 1.5
***************
*** 63,74 ****
import java.net.URISyntaxException;
import java.util.Iterator;
/**
* This factory supports the standard set of functions specified in XACML
! * 1.0 and 1.1. It is the default factory used by the system. Like the other
! * standard factories, there is only one instance used, so changing the
! * contents of one instance will affect all other instances.
*
* @since 1.2
--- 63,89 ----
import java.net.URISyntaxException;
+ import java.util.Collections;
+ import java.util.HashSet;
+ import java.util.HashMap;
import java.util.Iterator;
+ import java.util.Map;
+ import java.util.Set;
/**
* This factory supports the standard set of functions specified in XACML
! * 1.0 and 1.1. 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 functions, this
! * factory does not allow the addition of any other functions. If you call
! * <code>addFunction</code> on an instance of this class, an exception
! * will be thrown. If you need a standard factory that is modifiable,
! * you can either create a new <code>BaseFunctionFactory</code> (or some
! * other implementation of <code>FunctionFactory</code>) populated with
! * the standard functions from <code>getStandardFunctions</code> or
! * you can use <code>getNewFactoryProxy</code> to get a proxy containing
! * a new, modifiable set of factories.
*
* @since 1.2
***************
*** 78,190 ****
{
- // internal identifiers for the three kinds of factories
- private static final int TARGET_FACTORY = 0;
- private static final int CONDITION_FACTORY = 1;
- private static final int GENERAL_FACTORY = 2;
-
// the three singleton instances
! private static FunctionFactory targetFactory = null;
! private static FunctionFactory conditionFactory = null;
! private static FunctionFactory generalFactory = null;
! // dummy object used as a lock for the getFactory routines
! // FIXME: this needs a better mechanism
! private static Object factoryLock = new Object();
/**
* Creates a new StandardFunctionFactory, making sure that the default
! * maps are initialized correctly.
*/
! private StandardFunctionFactory(int type, FunctionFactory superset) {
! super(superset);
! switch (type) {
! case TARGET_FACTORY:
! // add EqualFunction
! addFunctions((new EqualFunctionCluster()).getSupportedFunctions().
! iterator());
! // add LogicalFunction
! addFunctions((new LogicalFunctionCluster()).
! getSupportedFunctions().iterator());
! // add NOfFunction
! addFunctions((new NOfFunctionCluster()).getSupportedFunctions().
! iterator());
! // add NotFunction
! addFunctions((new NotFunctionCluster()).getSupportedFunctions().
! iterator());
! // add ComparisonFunction
! addFunctions((new ComparisonFunctionCluster()).
! getSupportedFunctions().iterator());
! // add MatchFunction
! addFunctions((new MatchFunctionCluster()).getSupportedFunctions().
! iterator());
! break;
! case CONDITION_FACTORY:
! // add condition functions from BagFunction
! addFunctions((new ConditionBagFunctionCluster()).
! getSupportedFunctions().iterator());
! // add condition functions from SetFunction
! addFunctions((new ConditionSetFunctionCluster()).
! getSupportedFunctions().iterator());
! // add condition functions from HigherOrderFunction
! addFunctions((new HigherOrderFunctionCluster()).
! getSupportedFunctions().iterator());
! break;
! case GENERAL_FACTORY:
! // add AddFunction
! addFunctions((new AddFunctionCluster()).getSupportedFunctions().
! iterator());
! // add SubtractFunction
! addFunctions((new SubtractFunctionCluster()).
! getSupportedFunctions().iterator());
! // add MultiplyFunction
! addFunctions((new MultiplyFunctionCluster()).
! getSupportedFunctions().iterator());
! // add DivideFunction
! addFunctions((new DivideFunctionCluster()).getSupportedFunctions().
! iterator());
! // add ModFunction
! addFunctions((new ModFunctionCluster()).getSupportedFunctions().
! iterator());
! // add AbsFunction
! addFunctions((new AbsFunctionCluster()).getSupportedFunctions().
! iterator());
! // add RoundFunction
! addFunctions((new RoundFunctionCluster()).getSupportedFunctions().
! iterator());
! // add FloorFunction
! addFunctions((new FloorFunctionCluster()).getSupportedFunctions().
! iterator());
! // add DateMathFunction
! addFunctions((new DateMathFunctionCluster()).
! getSupportedFunctions().iterator());
! // add general functions from BagFunction
! addFunctions((new GeneralBagFunctionCluster()).
! getSupportedFunctions().iterator());
! // add NumericConvertFunction
! addFunctions((new NumericConvertFunctionCluster()).
! getSupportedFunctions().iterator());
! // add StringNormalizeFunction
! addFunctions((new StringNormalizeFunctionCluster()).
! getSupportedFunctions().iterator());
! // add general functions from SetFunction
! addFunctions((new GeneralSetFunctionCluster()).
! getSupportedFunctions().iterator());
!
! // add the map function's proxy
! try {
! addAbstractFunction(new MapFunctionProxy(),
! new URI(MapFunction.NAME_MAP));
! } catch (URISyntaxException e) {
! // this shouldn't ever happen, but just in case...
! throw new IllegalArgumentException("invalid function name");
! }
! break;
! }
}
! private void addFunctions(Iterator it) {
! while (it.hasNext()) {
! addFunction((Function)(it.next()));
}
}
--- 93,239 ----
{
// the three singleton instances
! private static StandardFunctionFactory targetFactory = null;
! private static StandardFunctionFactory conditionFactory = null;
! private static StandardFunctionFactory generalFactory = null;
! // the three function sets/maps that we use internally
! private static Set targetFunctions = null;
! private static Set conditionFunctions = null;
! private static Set generalFunctions = null;
!
! private static Map targetAbstractFunctions = null;
! private static Map conditionAbstractFunctions = null;
! private static Map generalAbstractFunctions = null;
!
! // the set/map used by each singleton factory instance
! private Set supportedFunctions = null;
! private Map supportedAbstractFunctions = null;
/**
* Creates a new StandardFunctionFactory, making sure that the default
! * maps are initialized correctly. Standard factories can't be modified,
! * so there is no notion of supersetting since that's only used for
! * correctly propagating new functions.
*/
! private StandardFunctionFactory(Set supportedFunctions,
! Map supportedAbstractFunctions) {
! super(supportedFunctions, supportedAbstractFunctions);
! this.supportedFunctions = supportedFunctions;
! this.supportedAbstractFunctions = supportedAbstractFunctions;
}
! /**
! * Private initializer for the target functions. This is only ever
! * called once.
! */
! private static void initTargetFunctions() {
! targetFunctions = new HashSet();
!
! // add EqualFunction
! targetFunctions.addAll((new EqualFunctionCluster()).
! getSupportedFunctions());
! // add LogicalFunction
! targetFunctions.addAll((new LogicalFunctionCluster()).
! getSupportedFunctions());
! // add NOfFunction
! targetFunctions.addAll((new NOfFunctionCluster()).
! getSupportedFunctions());
! // add NotFunction
! targetFunctions.addAll((new NotFunctionCluster()).
! getSupportedFunctions());
! // add ComparisonFunction
! targetFunctions.addAll((new ComparisonFunctionCluster()).
! getSupportedFunctions());
! // add MatchFunction
! targetFunctions.addAll((new MatchFunctionCluster()).
! getSupportedFunctions());
!
! targetAbstractFunctions = new HashMap();
! }
!
! /**
! * Private initializer for the condition functions. This is only ever
! * called once.
! */
! private static void initConditionFunctions() {
! if (targetFunctions == null)
! initTargetFunctions();
!
! conditionFunctions = new HashSet(targetFunctions);
!
! // add condition functions from BagFunction
! conditionFunctions.addAll((new ConditionBagFunctionCluster()).
! getSupportedFunctions());
! // add condition functions from SetFunction
! conditionFunctions.addAll((new ConditionSetFunctionCluster()).
! getSupportedFunctions());
! // add condition functions from HigherOrderFunction
! conditionFunctions.addAll((new HigherOrderFunctionCluster()).
! getSupportedFunctions());
!
! conditionAbstractFunctions = new HashMap(targetAbstractFunctions);
! }
!
! /**
! * Private initializer for the general functions. This is only ever
! * called once.
! */
! private static void initGeneralFunctions() {
! if (conditionFunctions == null)
! initConditionFunctions();
!
! generalFunctions = new HashSet(conditionFunctions);
!
! // add AddFunction
! generalFunctions.addAll((new AddFunctionCluster()).
! getSupportedFunctions());
! // add SubtractFunction
! generalFunctions.addAll((new SubtractFunctionCluster()).
! getSupportedFunctions());
! // add MultiplyFunction
! generalFunctions.addAll((new MultiplyFunctionCluster()).
! getSupportedFunctions());
! // add DivideFunction
! generalFunctions.addAll((new DivideFunctionCluster()).
! getSupportedFunctions());
! // add ModFunction
! generalFunctions.addAll((new ModFunctionCluster()).
! getSupportedFunctions());
! // add AbsFunction
! generalFunctions.addAll((new AbsFunctionCluster()).
! getSupportedFunctions());
! // add RoundFunction
! generalFunctions.addAll((new RoundFunctionCluster()).
! getSupportedFunctions());
! // add FloorFunction
! generalFunctions.addAll((new FloorFunctionCluster()).
! getSupportedFunctions());
! // add DateMathFunction
! generalFunctions.addAll((new DateMathFunctionCluster()).
! getSupportedFunctions());
! // add general functions from BagFunction
! generalFunctions.addAll((new GeneralBagFunctionCluster()).
! getSupportedFunctions());
! // add NumericConvertFunction
! generalFunctions.addAll((new NumericConvertFunctionCluster()).
! getSupportedFunctions());
! // add StringNormalizeFunction
! generalFunctions.addAll((new StringNormalizeFunctionCluster()).
! getSupportedFunctions());
! // add general functions from SetFunction
! generalFunctions.addAll((new GeneralSetFunctionCluster()).
! getSupportedFunctions());
!
! generalAbstractFunctions = new HashMap(conditionAbstractFunctions);
!
! // add the map function's proxy
! try {
! generalAbstractFunctions.put(new URI(MapFunction.NAME_MAP),
! new MapFunctionProxy());
! } catch (URISyntaxException e) {
! // this shouldn't ever happen, but just in case...
! throw new IllegalArgumentException("invalid function name");
}
}
***************
*** 196,209 ****
* the factory if it hasn't been requested before. This is the default
* model used by the <code>FunctionFactory</code>, ensuring quick
! * access to this factory. If you need a new instance of this factory
! * you should use the <code>getNewFactory</code> method.
*
* @return a <code>FunctionFactory</code> for target functions
*/
! public static FunctionFactory getTargetFactory() {
if (targetFactory == null) {
! synchronized (factoryLock) {
if (targetFactory == null)
! setupFactories();
}
}
--- 245,261 ----
* the factory if it hasn't been requested before. This is the default
* model used by the <code>FunctionFactory</code>, ensuring quick
! * access to this factory.
*
* @return a <code>FunctionFactory</code> for target functions
*/
! public static StandardFunctionFactory getTargetFactory() {
if (targetFactory == null) {
! synchronized (StandardFunctionFactory.class) {
! if (targetFunctions == null)
! initTargetFunctions();
if (targetFactory == null)
! targetFactory =
! new StandardFunctionFactory(targetFunctions,
! targetAbstractFunctions);
}
}
***************
*** 219,232 ****
* the factory if it hasn't been requested before. This is the default
* model used by the <code>FunctionFactory</code>, ensuring quick
! * access to this factory. If you need a new instance of this factory
! * you should use the <code>getNewFactory</code> method.
*
* @return a <code>FunctionFactory</code> for condition functions
*/
! public static FunctionFactory getConditionFactory() {
if (conditionFactory == null) {
! synchronized (factoryLock) {
if (conditionFactory == null)
! setupFactories();
}
}
--- 271,287 ----
* the factory if it hasn't been requested before. This is the default
* model used by the <code>FunctionFactory</code>, ensuring quick
! * access to this factory.
*
* @return a <code>FunctionFactory</code> for condition functions
*/
! public static StandardFunctionFactory getConditionFactory() {
if (conditionFactory == null) {
! synchronized (StandardFunctionFactory.class) {
! if (conditionFunctions == null)
! initConditionFunctions();
if (conditionFactory == null)
! conditionFactory =
! new StandardFunctionFactory(conditionFunctions,
! conditionAbstractFunctions);
}
}
***************
*** 241,254 ****
* instance, creating the factory if it hasn't been requested before.
* This is the default model used by the <code>FunctionFactory</code>,
! * ensuring quick access to this factory. If you need a new instance of
! * this factory you should use the <code>getNewFactory</code> method.
*
* @return a <code>FunctionFactory</code> for all functions
*/
! public static FunctionFactory getGeneralFactory() {
if (generalFactory == null) {
! synchronized (factoryLock) {
! if (generalFactory == null)
! setupFactories();
}
}
--- 296,312 ----
* instance, creating the factory if it hasn't been requested before.
* This is the default model used by the <code>FunctionFactory</code>,
! * ensuring quick access to this factory.
*
* @return a <code>FunctionFactory</code> for all functions
*/
! public static StandardFunctionFactory getGeneralFactory() {
if (generalFactory == null) {
! synchronized (StandardFunctionFactory.class) {
! if (generalFunctions == null) {
! initGeneralFunctions();
! generalFactory =
! new StandardFunctionFactory(generalFunctions,
! generalAbstractFunctions);
! }
}
}
***************
*** 258,285 ****
/**
! * Returns a new instance of <code>FunctionFactoryProxy</code> with
! * new factories that support all the standard functions.
*/
! public static FunctionFactoryProxy getNewFactory() {
StandardFunctionFactory general =
! new StandardFunctionFactory(GENERAL_FACTORY, null);
StandardFunctionFactory condition =
! new StandardFunctionFactory(CONDITION_FACTORY, general);
StandardFunctionFactory target =
! new StandardFunctionFactory(TARGET_FACTORY, condition);
! return new BasicFunctionFactoryProxy(target, condition, general);
}
/**
! * Private helper that sets up the three factory instances with the
! * right dependencies on each other.
*/
! private static void setupFactories() {
! generalFactory = new StandardFunctionFactory(GENERAL_FACTORY, null);
! conditionFactory = new StandardFunctionFactory(CONDITION_FACTORY,
! generalFactory);
! targetFactory = new StandardFunctionFactory(TARGET_FACTORY,
! conditionFactory);
}
--- 316,402 ----
/**
! * Returns the set of functions that this standard factory supports.
! *
! * @return a <code>Set</code> of <code>Function</code>s
*/
! public Set getStandardFunctions() {
! return Collections.unmodifiableSet(supportedFunctions);
! }
!
! /**
! * Returns the set of abstract functions that this standard factory
! * supports as a mapping of identifier to proxy.
! *
! * @return a <code>Map</code> mapping <code>URI</code>s to
! * <code>FunctionProxy</code>s
! */
! public Map getStandardAbstractFunctions() {
! return Collections.unmodifiableMap(supportedAbstractFunctions);
! }
!
! /**
! * A convenience method that returns a proxy containing newly created
! * instances of <code>BaseFunctionFactory</code>s that are correctly
! * supersetted and contain the standard functions and abstract functions.
! * These factories allow adding support for new functions.
! *
! * @return a new proxy containing new factories supporting the standard
! * functions
! */
! public static FunctionFactoryProxy getNewFactoryProxy() {
StandardFunctionFactory general =
! StandardFunctionFactory.getGeneralFactory();
! FunctionFactory newGeneral =
! new BaseFunctionFactory(general.getStandardFunctions(),
! general.getStandardAbstractFunctions());
!
StandardFunctionFactory condition =
! StandardFunctionFactory.getConditionFactory();
! FunctionFactory newCondition =
! new BaseFunctionFactory(newGeneral,
! condition.getStandardFunctions(),
! condition.getStandardAbstractFunctions());
!
StandardFunctionFactory target =
! StandardFunctionFactory.getTargetFactory();
! FunctionFactory newTarget =
! new BaseFunctionFactory(newCondition,
! target.getStandardFunctions(),
! target.getStandardAbstractFunctions());
! return new BasicFunctionFactoryProxy(newTarget, newCondition,
! newGeneral);
}
/**
! * Always throws an exception, since support for new functions may not be
! * added to a standard factory.
! *
! * @param function the <code>Function</code> to add to the factory
! *
! * @throws UnsupportedOperationException always
*/
! public void addFunction(Function function)
! throws IllegalArgumentException
! {
! throw new UnsupportedOperationException("a standard factory cannot " +
! "support new functions");
! }
!
! /**
! * Always throws an exception, since support for new functions may not be
! * added to a standard factory.
! *
! * @param proxy the <code>FunctionProxy</code> to add to the factory
! * @param identity the function's identifier
! *
! * @throws UnsupportedOperationException always
! */
! public void addAbstractFunction(FunctionProxy proxy,
! URI identity)
! throws IllegalArgumentException
! {
! throw new UnsupportedOperationException("a standard factory cannot " +
! "support new functions");
}
Index: BaseFunctionFactory.java
===================================================================
RCS file: /cvsroot/sunxacml/sunxacml/com/sun/xacml/cond/BaseFunctionFactory.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** BaseFunctionFactory.java 17 May 2004 20:33:45 -0000 1.3
--- BaseFunctionFactory.java 24 May 2004 20:55:07 -0000 1.4
***************
*** 44,47 ****
--- 44,49 ----
import java.util.HashMap;
import java.util.HashSet;
+ import java.util.Iterator;
+ import java.util.Map;
import java.util.Set;
***************
*** 57,60 ****
--- 59,70 ----
* may want to extend FunctionFactory directly, if you're writing a new
* factory implementation.
+ * <p>
+ * Note that while this class is thread-safe on all creation methods, it
+ * is not safe to add support for a new function while creating an instance
+ * of a function. 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
***************
*** 93,96 ****
--- 103,152 ----
/**
+ * Constructor that defines the initial functions supported by this
+ * factory but doesn't use a superset factory.
+ *
+ * @param supportedFunctions a <code>Set</code> of <code>Function</code>s
+ * @param supportedAbstractFunctions a mapping from <code>URI</code> to
+ * <code>FunctionProxy</code>
+ */
+ public BaseFunctionFactory(Set supportedFunctions,
+ Map supportedAbstractFunctions) {
+ this(null, supportedFunctions, supportedAbstractFunctions);
+ }
+
+ /**
+ * Constructor that defines the initial functions supported by this
+ * factory and uses a superset factory. Note that the functions
+ * supplied here are not propagated up to the superset factory, so
+ * you must either make sure the superst factory is correctly
+ * initialized or use <code>BaseFunctionFactory(FunctionFactory)</code>
+ * and then manually add each function.
+ *
+ * @param superset the superset factory or null
+ * @param supportedFunctions a <code>Set</code> of <code>Function</code>s
+ * @param supportedAbstractFunctions a mapping from <code>URI</code> to
+ * <code>FunctionProxy</code>
+ */
+ public BaseFunctionFactory(FunctionFactory superset,
+ Set supportedFunctions,
+ Map supportedAbstractFunctions) {
+ this(superset);
+
+ Iterator it = supportedFunctions.iterator();
+ while (it.hasNext()) {
+ Function function = (Function)(it.next());
+ functionMap.put(function.getIdentifier().toString(), function);
+ }
+
+ it = supportedAbstractFunctions.keySet().iterator();
+ while (it.hasNext()) {
+ URI id = (URI)(it.next());
+ FunctionProxy proxy =
+ (FunctionProxy)(supportedAbstractFunctions.get(id));
+ functionMap.put(id.toString(), proxy);
+ }
+ }
+
+ /**
* Adds the function to the factory. Most functions have no state, so
* the singleton model used here is typically desireable. The factory will
|