/*
* @(#)ConfigurationStore.java
*
* 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;
import com.sun.xacml.attr.AttributeFactory;
import com.sun.xacml.attr.AttributeFactoryProxy;
import com.sun.xacml.attr.AttributeProxy;
import com.sun.xacml.attr.BaseAttributeFactory;
import com.sun.xacml.attr.StandardAttributeFactory;
import com.sun.xacml.combine.BaseCombiningAlgFactory;
import com.sun.xacml.combine.CombiningAlgFactory;
import com.sun.xacml.combine.CombiningAlgFactoryProxy;
import com.sun.xacml.combine.CombiningAlgorithm;
import com.sun.xacml.combine.StandardCombiningAlgFactory;
import com.sun.xacml.cond.BaseFunctionFactory;
import com.sun.xacml.cond.BasicFunctionFactoryProxy;
import com.sun.xacml.cond.Function;
import com.sun.xacml.cond.FunctionProxy;
import com.sun.xacml.cond.FunctionFactory;
import com.sun.xacml.cond.FunctionFactoryProxy;
import com.sun.xacml.cond.StandardFunctionFactory;
import com.sun.xacml.cond.cluster.FunctionCluster;
import com.sun.xacml.finder.AttributeFinder;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.ResourceFinder;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
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.Set;
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.xml.sax.SAXException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This class supports run-time loading of configuration data. It loads the
* configurations from an XML file that conforms to the configuration schema.
* By design this class does not get used automatically, nor does it change
* the state of the system directly. A programmer must choose to support this
* mechanism in their program, and then must explicitly use loaded elements.
* This way, the programmer still has full control over their security model,
* but also has the convenience of re-using a common configuration
* mechanism. See http://sunxacml.sourceforge.net/schema/config-0.4.xsd for
* the valid schema.
* <p>
* Note that becuase this doesn't tie directly into the rest of the code, you
* are still free to design your own run-time configuration mechanisms. This
* is simply provided as a convenience, and so that all programmers can start
* from a common point.
*
* @since 1.2
* @author Seth Proctor
*/
public class ConfigurationStore
{
/**
* Property used to specify the configuration file.
*/
public static final String PDP_CONFIG_PROPERTY =
"com.sun.xacml.PDPConfigFile";
// pdp elements
private PDPConfig defaultPDPConfig;
private HashMap pdpConfigMap;
// attribute factory elements
private AttributeFactory defaultAttributeFactory;
private HashMap attributeMap;
// combining algorithm factory elements
private CombiningAlgFactory defaultCombiningFactory;
private HashMap combiningMap;
// function factory elements
private FunctionFactoryProxy defaultFunctionFactoryProxy;
private HashMap functionMap;
// the classloader we'll use for loading classes
private ClassLoader loader;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(ConfigurationStore.class.getName());
/**
* Default constructor. This constructor uses the
* <code>PDP_CONFIG_PROPERTY</code> property to load the configuration.
* If the property isn't set, if it names a file that can't be accessed,
* or if the file is invalid, then an exception is thrown.
*
* @throws ParsingException if anything goes wrong during the parsing
* of the configuration file, the class loading,
* or the factory and pdp setup
*/
public ConfigurationStore() throws ParsingException {
String configFile = System.getProperty(PDP_CONFIG_PROPERTY);
// make sure that the right property was set
if (configFile == null) {
logger.severe("A property defining a config file was expected, " +
"but none was provided");
throw new ParsingException("Config property " +
PDP_CONFIG_PROPERTY +
" needs to be set");
}
try {
setupConfig(new File(configFile));
} catch (ParsingException pe) {
logger.log(Level.SEVERE, "Runtime config file couldn't be loaded" +
" so no configurations will be available", pe);
throw pe;
}
}
/**
* Constructor that explicitly specifies the configuration file to load.
* This is useful if your security model doesn't allow the use of
* properties, if you don't want to use a property to specify a
* configuration file, or if you want to use more then one configuration
* file. If the file can't be accessed, or if the file is invalid, then
* an exception is thrown.
*
* @throws ParsingException if anything goes wrong during the parsing
* of the configuration file, the class loading,
* or the factory and pdp setup
*/
public ConfigurationStore(File configFile) throws ParsingException {
try {
setupConfig(configFile);
} catch (ParsingException pe) {
logger.log(Level.SEVERE, "Runtime config file couldn't be loaded" +
" so no configurations will be available", pe);
throw pe;
}
}
/**
* Private helper function used by both constructors to actually load the
* configuration data. This is the root of several private methods used
* to setup all the pdps and factories.
*/
private void setupConfig(File configFile) throws ParsingException {
logger.config("Loading runtime configuration");
// load our classloader
loader = getClass().getClassLoader();
// get the root node from the configuration file
Node root = getRootNode(configFile);
// initialize all the maps
pdpConfigMap = new HashMap();
attributeMap = new HashMap();
combiningMap = new HashMap();
functionMap = new HashMap();
// get the default names
NamedNodeMap attrs = root.getAttributes();
String defaultPDP = attrs.getNamedItem("defaultPDP").getNodeValue();
String defaultAF = getDefaultFactory(attrs, "defaultAttributeFactory");
String defaultCAF = getDefaultFactory(attrs,
"defaultCombiningAlgFactory");
String defaultFF = getDefaultFactory(attrs, "defaultFunctionFactory");
// loop through all the root-level elements, for each one getting its
// name and then loading the right kind of element
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
String childName = child.getNodeName();
String elementName = null;
// get the element's name
if (child.getNodeType() == Node.ELEMENT_NODE)
elementName = child.getAttributes().
getNamedItem("name").getNodeValue();
// see if this is a pdp or a factory, and load accordingly,
// putting the new element into the respective map...make sure
// that we're never loading something with the same name twice
if (childName.equals("pdp")) {
if (logger.isLoggable(Level.CONFIG))
logger.config("Loading PDP: " + elementName);
if (pdpConfigMap.containsKey(elementName))
throw new ParsingException("more that one pdp with " +
"name \"" + elementName +"\"");
pdpConfigMap.put(elementName, parsePDPConfig(child));
} else if (childName.equals("attributeFactory")) {
if (logger.isLoggable(Level.CONFIG))
logger.config("Loading AttributeFactory: " + elementName);
if (attributeMap.containsKey(elementName))
throw new ParsingException("more that one " +
"attributeFactory with name " +
elementName +"\"");
attributeMap.put(elementName, parseAttributeFactory(child));
} else if (childName.equals("combiningAlgFactory")) {
if (logger.isLoggable(Level.CONFIG))
logger.config("Loading CombiningAlgFactory: " +
elementName);
if (combiningMap.containsKey(elementName))
throw new ParsingException("more that one " +
"combiningAlgFactory with " +
"name \"" + elementName +"\"");
combiningMap.put(elementName, parseCombiningAlgFactory(child));
} else if (childName.equals("functionFactory")) {
if (logger.isLoggable(Level.CONFIG))
logger.config("Loading FunctionFactory: " + elementName);
if (functionMap.containsKey(elementName))
throw new ParsingException("more that one functionFactory"
+ " with name \"" +
elementName +"\"");
functionMap.put(elementName, parseFunctionFactory(child));
}
}
// finally, extract the default elements
defaultPDPConfig = (PDPConfig)(pdpConfigMap.get(defaultPDP));
defaultAttributeFactory = (AttributeFactory)
(attributeMap.get(defaultAF));
if (defaultAttributeFactory == null) {
try {
defaultAttributeFactory =
AttributeFactory.getInstance(defaultAF);
} catch (Exception e) {
throw new ParsingException("Unknown AttributeFactory", e);
}
}
defaultCombiningFactory = (CombiningAlgFactory)
(combiningMap.get(defaultCAF));
if (defaultCombiningFactory == null) {
try {
defaultCombiningFactory =
CombiningAlgFactory.getInstance(defaultCAF);
} catch (Exception e) {
throw new ParsingException("Unknown CombininAlgFactory", e);
}
}
defaultFunctionFactoryProxy = (FunctionFactoryProxy)
(functionMap.get(defaultFF));
if (defaultFunctionFactoryProxy == null) {
try {
defaultFunctionFactoryProxy =
FunctionFactory.getInstance(defaultFF);
} catch (Exception e) {
throw new ParsingException("Unknown FunctionFactory", e);
}
}
}
/**
* Private helper that gets a default factory identifier, or fills in
* the default value if no identifier is provided.
*/
private String getDefaultFactory(NamedNodeMap attrs, String factoryName) {
Node node = attrs.getNamedItem(factoryName);
if (node != null)
return node.getNodeValue();
else
return PolicyMetaData.XACML_1_0_IDENTIFIER;
}
/**
* Private helper that parses the file and sets up the DOM tree.
*/
private Node getRootNode(File configFile) throws ParsingException {
DocumentBuilderFactory dbFactory =
DocumentBuilderFactory.newInstance();
dbFactory.setIgnoringComments(true);
dbFactory.setNamespaceAware(false);
dbFactory.setValidating(false);
DocumentBuilder db = null;
try {
db = dbFactory.newDocumentBuilder();
} catch (ParserConfigurationException pce) {
throw new ParsingException("couldn't get a document builder", pce);
}
Document doc = null;
try {
doc = db.parse(new FileInputStream(configFile));
} catch (IOException ioe) {
throw new ParsingException("failed to load the file ", ioe);
} catch (SAXException saxe) {
throw new ParsingException("error parsing the XML tree", saxe);
} catch (IllegalArgumentException iae) {
throw new ParsingException("no data to parse", iae);
}
Element root = doc.getDocumentElement();
if (! root.getTagName().equals("config"))
throw new ParsingException("unknown document type: " +
root.getTagName());
return root;
}
/**
* Private helper that handles the pdp elements.
*/
private PDPConfig parsePDPConfig(Node root) throws ParsingException {
ArrayList attrModules = new ArrayList();
HashSet policyModules = new HashSet();
ArrayList rsrcModules = new ArrayList();
// go through all elements of the pdp, loading the specified modules
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
String name = child.getNodeName();
if (name.equals("policyFinderModule")) {
policyModules.add(loadClass("module", child));
} else if (name.equals("attributeFinderModule")) {
attrModules.add(loadClass("module", child));
} else if (name.equals("resourceFinderModule")) {
rsrcModules.add(loadClass("module", child));
}
}
// after loading the modules, use the collections to setup a
// PDPConfig based on this pdp element
AttributeFinder attrFinder = new AttributeFinder();
attrFinder.setModules(attrModules);
PolicyFinder policyFinder = new PolicyFinder();
policyFinder.setModules(policyModules);
ResourceFinder rsrcFinder = new ResourceFinder();
rsrcFinder.setModules(rsrcModules);
return new PDPConfig(attrFinder, policyFinder, rsrcFinder);
}
/**
* Private helper that handles the attributeFactory elements.
*/
private AttributeFactory parseAttributeFactory(Node root)
throws ParsingException
{
AttributeFactory factory = null;
// check if we're starting with the standard factory setup
if (useStandard(root, "useStandardDatatypes")) {
logger.config("Starting with standard Datatypes");
factory = StandardAttributeFactory.getNewFactory();
} else {
factory = new BaseAttributeFactory();
}
// now look for all datatypes specified for this factory, adding
// them as we go
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeName().equals("datatype")) {
// a datatype is a class with an identifier
String identifier = child.getAttributes().
getNamedItem("identifier").getNodeValue();
AttributeProxy proxy =
(AttributeProxy)(loadClass("datatype", child));
try {
factory.addDatatype(identifier, proxy);
} catch (IllegalArgumentException iae) {
throw new ParsingException("duplicate datatype: " +
identifier, iae);
}
}
}
return factory;
}
/**
* Private helper that handles the combiningAlgFactory elements.
*/
private CombiningAlgFactory parseCombiningAlgFactory(Node root)
throws ParsingException
{
CombiningAlgFactory factory = null;
// check if we're starting with the standard factory setup
if (useStandard(root, "useStandardAlgorithms")) {
logger.config("Starting with standard Combining Algorithms");
factory = StandardCombiningAlgFactory.getNewFactory();
} else {
factory = new BaseCombiningAlgFactory();
}
// now look for all algorithms specified for this factory, adding
// them as we go
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeName().equals("algorithm")) {
// an algorithm is a simple class element
CombiningAlgorithm alg =
(CombiningAlgorithm)(loadClass("algorithm", child));
try {
factory.addAlgorithm(alg);
} catch (IllegalArgumentException iae) {
throw new ParsingException("duplicate combining " +
"algorithm: " +
alg.getIdentifier().toString(),
iae);
}
}
}
return factory;
}
/**
* Private helper that handles the functionFactory elements. This one
* is a little more complex than the other two factory helper methods,
* since it consists of three factories (target, condition, and general).
*/
private FunctionFactoryProxy parseFunctionFactory(Node root)
throws ParsingException
{
FunctionFactoryProxy proxy = null;
FunctionFactory generalFactory = null;
FunctionFactory conditionFactory = null;
FunctionFactory targetFactory = null;
// check if we're starting with the standard factory setup, and
// make sure that the proxy is pre-configured
if (useStandard(root, "useStandardFunctions")) {
logger.config("Starting with standard Functions");
proxy = StandardFunctionFactory.getNewFactoryProxy();
targetFactory = proxy.getTargetFactory();
conditionFactory = proxy.getConditionFactory();
generalFactory = proxy.getGeneralFactory();
} else {
generalFactory = new BaseFunctionFactory();
conditionFactory = new BaseFunctionFactory(generalFactory);
targetFactory = new BaseFunctionFactory(conditionFactory);
proxy = new BasicFunctionFactoryProxy(targetFactory,
conditionFactory,
generalFactory);
}
// go through and load the three sections, putting the loaded
// functions into the appropriate factory
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
String name = child.getNodeName();
if (name.equals("target")) {
logger.config("Loading [TARGET] functions");
functionParserHelper(child, targetFactory);
} else if (name.equals("condition")) {
logger.config("Loading [CONDITION] functions");
functionParserHelper(child, conditionFactory);
} else if (name.equals("general")) {
logger.config("Loading [GENERAL] functions");
functionParserHelper(child, generalFactory);
}
}
return proxy;
}
/**
* Private helper used by the function factory code to load a specific
* target, condition, or general section.
*/
private void functionParserHelper(Node root, FunctionFactory factory)
throws ParsingException
{
// go through all elements in the section
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
String name = child.getNodeName();
if (name.equals("function")) {
// a function section is a simple class element
Function function =
(Function)(loadClass("function", child));
try {
factory.addFunction(function);
} catch (IllegalArgumentException iae) {
throw new ParsingException("duplicate function", iae);
}
} else if (name.equals("abstractFunction")) {
// an abstract function is a class with an identifier
URI identifier = null;
try {
identifier = new URI(child.getAttributes().
getNamedItem("identifier").
getNodeValue());
} catch (URISyntaxException urise) {
throw new ParsingException("invalid function identifier",
urise);
}
FunctionProxy proxy =
(FunctionProxy)(loadClass("abstract function", child));
try {
factory.addAbstractFunction(proxy, identifier);
} catch (IllegalArgumentException iae) {
throw new ParsingException("duplicate abstract function",
iae);
}
} else if (name.equals("functionCluster")) {
// a cluster is a class that will give us a collection of
// functions that need to be added one by one into the factory
FunctionCluster cluster =
(FunctionCluster)(loadClass("function cluster", child));
Iterator it = cluster.getSupportedFunctions().iterator();
while (it.hasNext()) {
try {
factory.addFunction((Function)(it.next()));
} catch (IllegalArgumentException iae) {
throw new ParsingException("duplicate function", iae);
}
}
}
}
}
/**
* Private helper that is used by all the code to load an instance of
* the given class...this assumes that the class is in the classpath,
* both for simplicity and for stronger security
*/
private Object loadClass(String prefix, Node root)
throws ParsingException
{
// get the name of the class
String className =
root.getAttributes().getNamedItem("class").getNodeValue();
if (logger.isLoggable(Level.CONFIG))
logger.config("Loading [ " + prefix + ": " + className + " ]");
// load the given class using the local classloader
Class c = null;
try {
c = loader.loadClass(className);
} catch (ClassNotFoundException cnfe) {
throw new ParsingException("couldn't load class " + className,
cnfe);
}
Object instance = null;
// figure out if there are any parameters to the constructor
if (! root.hasChildNodes()) {
// we're using a null constructor, so this is easy
try {
instance = c.newInstance();
} catch (InstantiationException ie) {
throw new ParsingException("couldn't instantiate " + className
+ " with empty constructor", ie);
} catch (IllegalAccessException iae) {
throw new ParsingException("couldn't get access to instance " +
"of " + className, iae);
}
} else {
// parse the arguments to the constructor
List args = null;
try {
args = getArgs(root);
} catch (IllegalArgumentException iae) {
throw new ParsingException("illegal class arguments", iae);
}
int argLength = args.size();
// next we need to see if there's a constructor that matches the
// arguments provided...this has to be done by hand since
// Class.getConstructor(Class []) doesn't handle sub-classes and
// generic types (for instance, a constructor taking List won't
// match a parameter list containing ArrayList)
// get the list of all available constructors
Constructor [] cons = c.getConstructors();
Constructor constructor = null;
for (int i = 0; i < cons.length; i++) {
// get the parameters for this constructor
Class [] params = cons[i].getParameterTypes();
if (params.length == argLength) {
Iterator it = args.iterator();
int j = 0;
// loop through the parameters and see if each one is
// assignable from the coresponding input argument
while (it.hasNext()) {
if (! params[j].isAssignableFrom(it.next().getClass()))
break;
j++;
}
// if we looked at all the parameters, then this
// constructor matches the input
if (j == argLength)
constructor = cons[i];
}
// if we've found a matching constructor then stop looping
if (constructor != null)
break;
}
// make sure we found a matching constructor
if (constructor == null)
throw new ParsingException("couldn't find a matching " +
"constructor");
// finally, instantiate the class
try {
instance = constructor.newInstance(args.toArray());
} catch (InstantiationException ie) {
throw new ParsingException("couldn't instantiate " + className,
ie);
} catch (IllegalAccessException iae) {
throw new ParsingException("couldn't get access to instance " +
"of " + className, iae);
} catch (InvocationTargetException ite) {
throw new ParsingException("couldn't create " + className,
ite);
}
}
return instance;
}
/**
* Private helper that gets the constructor arguments for a given class.
* Right now this just supports String and List, but it's trivial to
* add support for other types should that be needed. Right now, it's not
* clear that there's any need for other types.
*/
private List getArgs(Node root) {
List args = new ArrayList();
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
String name = child.getNodeName();
if (child.getNodeType() == Node.ELEMENT_NODE) {
if (name.equals("string")) {
args.add(child.getFirstChild().getNodeValue());
} else if (name.equals("list")) {
args.add(getArgs(child));
} else {
throw new IllegalArgumentException("unkown arg type: " +
name);
}
}
}
return args;
}
/**
* Private helper used by the three factory routines to see if the
* given factory should be based on the standard setup
*/
private boolean useStandard(Node node, String attributeName) {
NamedNodeMap map = node.getAttributes();
if (map == null)
return true;
Node attrNode = map.getNamedItem(attributeName);
if (attrNode == null)
return true;
return attrNode.getNodeValue().equals("true");
}
/**
* Returns the default PDP configuration. If no default was specified
* then this throws an exception.
*
* @return the default PDP configuration
*
* @throws UnknownIdentifierException if there is no default config
*/
public PDPConfig getDefaultPDPConfig() throws UnknownIdentifierException {
if (defaultPDPConfig == null)
throw new UnknownIdentifierException("no default available");
return defaultPDPConfig;
}
/**
* Returns the PDP configuration with the given name. If no such
* configuration exists then an exception is thrown.
*
* @return the matching PDP configuation
*
* @throws UnknownIdentifierException if the name is unknown
*/
public PDPConfig getPDPConfig(String name)
throws UnknownIdentifierException
{
Object object = pdpConfigMap.get(name);
if (object == null)
throw new UnknownIdentifierException("unknown pdp: " + name);
return (PDPConfig)object;
}
/**
* Returns a set of identifiers representing each PDP configuration
* available.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public Set getSupportedPDPConfigurations() {
return Collections.unmodifiableSet(pdpConfigMap.keySet());
}
/**
* Returns the default attribute factory.
*
* @return the default attribute factory
*/
public AttributeFactory getDefaultAttributeFactory() {
return defaultAttributeFactory;
}
/**
* Returns the attribute factory with the given name. If no such
* factory exists then an exception is thrown.
*
* @return the matching attribute factory
*
* @throws UnknownIdentifierException if the name is unknown
*/
public AttributeFactory getAttributeFactory(String name)
throws UnknownIdentifierException
{
Object object = attributeMap.get(name);
if (object == null)
throw new UnknownIdentifierException("unknown factory: " + name);
return (AttributeFactory)object;
}
/**
* Returns a set of identifiers representing each attribute factory
* available.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public Set getSupportedAttributeFactories() {
return Collections.unmodifiableSet(attributeMap.keySet());
}
/**
* Registers all the supported factories with the given identifiers. If
* a given identifier is already in use, then that factory is not
* registered. This method is provided only as a convenience, and
* any registration that may involve identifier clashes should be done
* by registering each factory individually.
*/
public void registerAttributeFactories() {
Iterator it = attributeMap.keySet().iterator();
while (it.hasNext()) {
String id = (String)(it.next());
AttributeFactory af = (AttributeFactory)(attributeMap.get(id));
try {
AttributeFactory.registerFactory(id, new AFProxy(af));
} catch (IllegalArgumentException iae) {
logger.log(Level.WARNING, "Couldn't register AttributeFactory:"
+ id + " (already in use)", iae);
}
}
}
/**
* Returns the default combiningAlg factory.
*
* @return the default combiningAlg factory
*/
public CombiningAlgFactory getDefaultCombiningAlgFactory() {
return defaultCombiningFactory;
}
/**
* Returns the combiningAlg factory with the given name. If no such
* factory exists then an exception is thrown.
*
* @return the matching combiningAlg factory
*
* @throws UnknownIdentifierException if the name is unknown
*/
public CombiningAlgFactory getCombiningAlgFactory(String name)
throws UnknownIdentifierException
{
Object object = combiningMap.get(name);
if (object == null)
throw new UnknownIdentifierException("unknown factory: " + name);
return (CombiningAlgFactory)object;
}
/**
* Returns a set of identifiers representing each combiningAlg factory
* available.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public Set getSupportedCombiningAlgFactories() {
return Collections.unmodifiableSet(combiningMap.keySet());
}
/**
* Registers all the supported factories with the given identifiers. If
* a given identifier is already in use, then that factory is not
* registered. This method is provided only as a convenience, and
* any registration that may involve identifier clashes should be done
* by registering each factory individually.
*/
public void registerCombiningAlgFactories() {
Iterator it = combiningMap.keySet().iterator();
while (it.hasNext()) {
String id = (String)(it.next());
CombiningAlgFactory cf =
(CombiningAlgFactory)(combiningMap.get(id));
try {
CombiningAlgFactory.registerFactory(id, new CAFProxy(cf));
} catch (IllegalArgumentException iae) {
logger.log(Level.WARNING, "Couldn't register " +
"CombiningAlgFactory: " + id + " (already in use)",
iae);
}
}
}
/**
* Returns the default function factory proxy.
*
* @return the default function factory proxy
*/
public FunctionFactoryProxy getDefaultFunctionFactoryProxy() {
return defaultFunctionFactoryProxy;
}
/**
* Returns the function factory proxy with the given name. If no such
* proxy exists then an exception is thrown.
*
* @return the matching function factory proxy
*
* @throws UnknownIdentifierException if the name is unknown
*/
public FunctionFactoryProxy getFunctionFactoryProxy(String name)
throws UnknownIdentifierException
{
Object object = functionMap.get(name);
if (object == null)
throw new UnknownIdentifierException("unknown factory: " + name);
return (FunctionFactoryProxy)object;
}
/**
* Returns a set of identifiers representing each function factory proxy
* available.
*
* @return a <code>Set</code> of <code>String</code>s
*/
public Set getSupportedFunctionFactories() {
return Collections.unmodifiableSet(functionMap.keySet());
}
/**
* Registers all the supported factories with the given identifiers. If
* a given identifier is already in use, then that factory is not
* registered. This method is provided only as a convenience, and
* any registration that may involve identifier clashes should be done
* by registering each factory individually.
*/
public void registerFunctionFactories() {
Iterator it = functionMap.keySet().iterator();
while (it.hasNext()) {
String id = (String)(it.next());
FunctionFactoryProxy ffp =
(FunctionFactoryProxy)(functionMap.get(id));
try {
FunctionFactory.registerFactory(id, ffp);
} catch (IllegalArgumentException iae) {
logger.log(Level.WARNING, "Couldn't register FunctionFactory: "
+ id + " (already in use)", iae);
}
}
}
/**
* Uses the default configuration to re-set the default factories used
* by the system (attribute, combining algorithm, and function). If
* a default is not provided for a given factory, then that factory
* will not be set as the system's default.
*/
public void useDefaultFactories() {
logger.fine("Switching to default factories from configuration");
// set the default attribute factory, if it exists here
if (defaultAttributeFactory != null) {
AttributeFactory.
setDefaultFactory(new AFProxy(defaultAttributeFactory));
}
// set the default combining algorithm factory, if it exists here
if (defaultCombiningFactory != null) {
CombiningAlgFactory.
setDefaultFactory(new CAFProxy(defaultCombiningFactory));
}
// set the default function factories, if they exists here
if (defaultFunctionFactoryProxy != null)
FunctionFactory.setDefaultFactory(defaultFunctionFactoryProxy);
}
/**
*
*/
class AFProxy implements AttributeFactoryProxy {
private AttributeFactory factory;
public AFProxy(AttributeFactory factory) {
this.factory = factory;
}
public AttributeFactory getFactory() {
return factory;
}
}
/**
*
*/
class CAFProxy implements CombiningAlgFactoryProxy {
private CombiningAlgFactory factory;
public CAFProxy(CombiningAlgFactory factory) {
this.factory = factory;
}
public CombiningAlgFactory getFactory() {
return factory;
}
}
}