Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/sun/xacml/cond/BaseFunctionFactory.java


1   
2   /*
3    * @(#)BaseCombiningAlgFactory.java
4    *
5    * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
6    *
7    * Redistribution and use in source and binary forms, with or without
8    * modification, are permitted provided that the following conditions are met:
9    *
10   *   1. Redistribution of source code must retain the above copyright notice,
11   *      this list of conditions and the following disclaimer.
12   * 
13   *   2. Redistribution in binary form must reproduce the above copyright
14   *      notice, this list of conditions and the following disclaimer in the
15   *      documentation and/or other materials provided with the distribution.
16   *
17   * Neither the name of Sun Microsystems, Inc. or the names of contributors may
18   * be used to endorse or promote products derived from this software without
19   * specific prior written permission.
20   * 
21   * This software is provided "AS IS," without a warranty of any kind. ALL
22   * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
23   * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
24   * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
25   * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
26   * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
27   * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
28   * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
29   * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
30   * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
31   * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32   *
33   * You acknowledge that this software is not designed or intended for use in
34   * the design, construction, operation or maintenance of any nuclear facility.
35   */
36  
37  package com.sun.xacml.cond;
38  
39  import com.sun.xacml.ParsingException;
40  import com.sun.xacml.UnknownIdentifierException;
41  
42  import java.net.URI;
43  
44  import java.util.HashMap;
45  import java.util.HashSet;
46  import java.util.Iterator;
47  import java.util.Map;
48  import java.util.Set;
49  
50  import org.w3c.dom.Node;
51  
52  
53  /**
54   * This is a basic implementation of <code>FunctionFactory</code>. It
55   * implements the insertion and retrieval methods, but it doesn't actually
56   * setup the factory with any functions. It also assumes a certain model
57   * with regard to the different kinds of functions (Target, Condition, and
58   * General). For this reason, you may want to re-use this class, or you 
59   * may want to extend FunctionFactory directly, if you're writing a new
60   * factory implementation.
61   * <p>
62   * Note that while this class is thread-safe on all creation methods, it
63   * is not safe to add support for a new function while creating an instance
64   * of a function. This follows from the assumption that most people will
65   * initialize these factories up-front, and then start processing without
66   * ever modifying the factories. If you need these mutual operations to
67   * be thread-safe, then you should write a wrapper class that implements
68   * the right synchronization.
69   *
70   * @since 1.2
71   * @author Seth Proctor
72   */
73  public class BaseFunctionFactory extends FunctionFactory
74  {
75  
76      // the backing maps for the Function objects
77      private HashMap functionMap = null;
78  
79      // the superset factory chained to this factory
80      private FunctionFactory superset = null;
81  
82      /**
83       * Default constructor. No superset factory is used.
84       */
85      public BaseFunctionFactory() {
86          this(null);
87      }
88  
89      /**
90       * Constructor that sets a "superset factory". This is useful since
91       * the different function factories (Target, Condition, and General)
92       * have a superset relationship (Condition functions are a superset
93       * of Target functions, etc.). Adding a function to this factory will
94       * automatically add the same function to the superset factory.
95       *
96       * @param superset the superset factory or null
97       */
98      public BaseFunctionFactory(FunctionFactory superset) {
99          functionMap = new HashMap();
100 
101         this.superset = superset;
102     }
103 
104     /**
105      * Constructor that defines the initial functions supported by this
106      * factory but doesn't use a superset factory.
107      *
108      * @param supportedFunctions a <code>Set</code> of <code>Function</code>s
109      * @param supportedAbstractFunctions a mapping from <code>URI</code> to
110      *                                   <code>FunctionProxy</code>
111      */
112     public BaseFunctionFactory(Set supportedFunctions,
113                                Map supportedAbstractFunctions) {
114         this(null, supportedFunctions, supportedAbstractFunctions);
115     }
116 
117     /**
118      * Constructor that defines the initial functions supported by this
119      * factory and uses a superset factory. Note that the functions
120      * supplied here are not propagated up to the superset factory, so
121      * you must either make sure the superst factory is correctly
122      * initialized or use <code>BaseFunctionFactory(FunctionFactory)</code>
123      * and then manually add each function.
124      *
125      * @param superset the superset factory or null
126      * @param supportedFunctions a <code>Set</code> of <code>Function</code>s
127      * @param supportedAbstractFunctions a mapping from <code>URI</code> to
128      *                                   <code>FunctionProxy</code>
129      */
130     public BaseFunctionFactory(FunctionFactory superset,
131                                Set supportedFunctions,
132                                Map supportedAbstractFunctions) {
133         this(superset);
134 
135         Iterator it = supportedFunctions.iterator();
136         while (it.hasNext()) {
137             Function function = (Function)(it.next());
138             functionMap.put(function.getIdentifier().toString(), function);
139         }
140 
141         it = supportedAbstractFunctions.keySet().iterator();
142         while (it.hasNext()) {
143             URI id = (URI)(it.next());
144             FunctionProxy proxy =
145                 (FunctionProxy)(supportedAbstractFunctions.get(id));
146             functionMap.put(id.toString(), proxy);
147         }
148     }
149 
150     /**
151      * Adds the function to the factory. Most functions have no state, so
152      * the singleton model used here is typically desireable. The factory will
153      * not enforce the requirement that a Target or Condition matching function
154      * must be boolean.
155      *
156      * @param function the <code>Function</code> to add to the factory
157      *
158      * @throws IllegalArgumentException if the function's identifier is already
159      *                                  used or if the function is non-boolean
160      *                                  (when this is a Target or Condition
161      *                                  factory)
162      */
163     public void addFunction(Function function)
164         throws IllegalArgumentException
165     {
166         String id = function.getIdentifier().toString();
167 
168         // make sure this doesn't already exist
169         if (functionMap.containsKey(id))
170             throw new IllegalArgumentException("function already exists");
171 
172         // add to the superset factory
173         if (superset != null)
174             superset.addFunction(function);
175 
176         // finally, add to this factory
177         functionMap.put(id, function);
178     }
179 
180     /**
181      * Adds the abstract function proxy to the factory. This is used for
182      * those functions which have state, or change behavior (for instance
183      * the standard map function, which changes its return type based on
184      * how it is used). 
185      *
186      * @param proxy the <code>FunctionProxy</code> to add to the factory
187      * @param identity the function's identifier
188      *
189      * @throws IllegalArgumentException if the function's identifier is already
190      *                                  used
191      */
192     public void addAbstractFunction(FunctionProxy proxy,
193                                     URI identity)
194         throws IllegalArgumentException
195     {
196         String id = identity.toString();
197 
198         // make sure this doesn't already exist
199         if (functionMap.containsKey(id))
200             throw new IllegalArgumentException("function already exists");
201 
202         // add to the superset factory
203         if (superset != null)
204             superset.addAbstractFunction(proxy, identity);
205 
206         // finally, add to this factory
207         functionMap.put(id, proxy);
208     }
209 
210     /**
211      * Returns the function identifiers supported by this factory.
212      *
213      * @return a <code>Set</code> of <code>String</code>s
214      */
215     public Set getSupportedFunctions() {
216         Set set = new HashSet(functionMap.keySet());
217 
218         if (superset != null)
219             set.addAll(superset.getSupportedFunctions());
220 
221         return set;
222     }
223 
224     /**
225      * Tries to get an instance of the specified function.
226      *
227      * @param identity the name of the function
228      *
229      * @throws UnknownIdentifierException if the name isn't known
230      * @throws FunctionTypeException if the name is known to map to an
231      *                               abstract function, and should therefore
232      *                               be created through createAbstractFunction
233      */
234     public Function createFunction(URI identity)
235         throws UnknownIdentifierException, FunctionTypeException
236     {
237         return createFunction(identity.toString());
238     }
239 
240     /**
241      * Tries to get an instance of the specified function.
242      *
243      * @param identity the name of the function
244      *
245      * @throws UnknownIdentifierException if the name isn't known
246      * @throws FunctionTypeException if the name is known to map to an
247      *                               abstract function, and should therefore
248      *                               be created through createAbstractFunction
249      */
250     public Function createFunction(String identity)
251         throws UnknownIdentifierException, FunctionTypeException
252     {
253         Object entry = functionMap.get(identity);
254 
255         if (entry != null) {
256             if (entry instanceof Function) {
257                 return (Function)entry;
258             } else {
259                 // this is actually a proxy, which means the other create
260                 // method should have been called
261                 throw new FunctionTypeException("function is abstract");
262             }
263         } else {
264             // we couldn't find a match
265             throw new UnknownIdentifierException("functions of type " +
266                                                  identity + " are not "+
267                                                  "supported by this factory");
268         }
269     }
270 
271     /**
272      * Tries to get an instance of the specified abstract function.
273      *
274      * @param identity the name of the function
275      * @param root the DOM root containing info used to create the function
276      *
277      * @throws UnknownIdentifierException if the name isn't known
278      * @throws FunctionTypeException if the name is known to map to a
279      *                               concrete function, and should therefore
280      *                               be created through createFunction
281      * @throws ParsingException if the function can't be created with the
282      *                          given inputs
283      */
284     public Function createAbstractFunction(URI identity, Node root)
285         throws UnknownIdentifierException, ParsingException,
286                FunctionTypeException
287     {
288         return createAbstractFunction(identity.toString(), root, null);
289     }
290 
291     /**
292      * Tries to get an instance of the specified abstract function.
293      *
294      * @param identity the name of the function
295      * @param root the DOM root containing info used to create the function
296      * @param xpathVersion the version specified in the contianing policy, or
297      *                     null if no version was specified
298      *
299      * @throws UnknownIdentifierException if the name isn't known
300      * @throws FunctionTypeException if the name is known to map to a
301      *                               concrete function, and should therefore
302      *                               be created through createFunction
303      * @throws ParsingException if the function can't be created with the
304      *                          given inputs
305      */
306     public Function createAbstractFunction(URI identity, Node root,
307                                            String xpathVersion)
308         throws UnknownIdentifierException, ParsingException,
309                FunctionTypeException
310     {
311         return createAbstractFunction(identity.toString(), root, xpathVersion);
312     }
313 
314     /**
315      * Tries to get an instance of the specified abstract function.
316      *
317      * @param identity the name of the function
318      * @param root the DOM root containing info used to create the function
319      *
320      * @throws UnknownIdentifierException if the name isn't known
321      * @throws FunctionTypeException if the name is known to map to a
322      *                               concrete function, and should therefore
323      *                               be created through createFunction
324      * @throws ParsingException if the function can't be created with the
325      *                          given inputs
326      */
327     public Function createAbstractFunction(String identity, Node root)
328         throws UnknownIdentifierException, ParsingException,
329                FunctionTypeException
330     {
331         return createAbstractFunction(identity, root, null);
332     }
333 
334     /**
335      * Tries to get an instance of the specified abstract function.
336      *
337      * @param identity the name of the function
338      * @param root the DOM root containing info used to create the function
339      * @param xpathVersion the version specified in the contianing policy, or
340      *                     null if no version was specified
341      *
342      * @throws UnknownIdentifierException if the name isn't known
343      * @throws FunctionTypeException if the name is known to map to a
344      *                               concrete function, and should therefore
345      *                               be created through createFunction
346      * @throws ParsingException if the function can't be created with the
347      *                          given inputs
348      */
349     public Function createAbstractFunction(String identity, Node root,
350                                            String xpathVersion)
351         throws UnknownIdentifierException, ParsingException,
352                FunctionTypeException
353     {
354         Object entry = functionMap.get(identity);
355         
356         if (entry != null) {
357             if (entry instanceof FunctionProxy) {
358                 try {
359                     return ((FunctionProxy)entry).getInstance(root,
360                                                               xpathVersion);
361                 } catch (Exception e) {
362                     throw new ParsingException("couldn't create abstract" +
363                                                " function " + identity, e);
364                 }
365             } else {
366                 // this is actually a concrete function, which means that
367                 // the other create method should have been called
368                 throw new FunctionTypeException("function is concrete");
369             }
370         } else {
371             // we couldn't find a match
372             throw new UnknownIdentifierException("abstract functions of " +
373                                                  "type " + identity +
374                                                  " are not supported by " +
375                                                  "this factory");
376         }
377     }
378 
379 }