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

Quick Search    Search Deep

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


1   
2   /*
3    * @(#)StandardFunctionFactory.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.cond.cluster.AbsFunctionCluster;
40  import com.sun.xacml.cond.cluster.AddFunctionCluster;
41  import com.sun.xacml.cond.cluster.ComparisonFunctionCluster;
42  import com.sun.xacml.cond.cluster.ConditionBagFunctionCluster;
43  import com.sun.xacml.cond.cluster.ConditionSetFunctionCluster;
44  import com.sun.xacml.cond.cluster.DateMathFunctionCluster;
45  import com.sun.xacml.cond.cluster.DivideFunctionCluster;
46  import com.sun.xacml.cond.cluster.EqualFunctionCluster;
47  import com.sun.xacml.cond.cluster.FloorFunctionCluster;
48  import com.sun.xacml.cond.cluster.GeneralBagFunctionCluster;
49  import com.sun.xacml.cond.cluster.GeneralSetFunctionCluster;
50  import com.sun.xacml.cond.cluster.HigherOrderFunctionCluster;
51  import com.sun.xacml.cond.cluster.LogicalFunctionCluster;
52  import com.sun.xacml.cond.cluster.MatchFunctionCluster;
53  import com.sun.xacml.cond.cluster.ModFunctionCluster;
54  import com.sun.xacml.cond.cluster.MultiplyFunctionCluster;
55  import com.sun.xacml.cond.cluster.NOfFunctionCluster;
56  import com.sun.xacml.cond.cluster.NotFunctionCluster;
57  import com.sun.xacml.cond.cluster.NumericConvertFunctionCluster;
58  import com.sun.xacml.cond.cluster.RoundFunctionCluster;
59  import com.sun.xacml.cond.cluster.StringNormalizeFunctionCluster;
60  import com.sun.xacml.cond.cluster.SubtractFunctionCluster;
61  
62  import java.net.URI;
63  import java.net.URISyntaxException;
64  
65  import java.util.Collections;
66  import java.util.HashSet;
67  import java.util.HashMap;
68  import java.util.Iterator;
69  import java.util.Map;
70  import java.util.Set;
71  
72  import java.util.logging.Logger;
73  
74  
75  /**
76   * This factory supports the standard set of functions specified in XACML
77   * 1.0 and 1.1. It is the default factory used by the system, and imposes
78   * a singleton pattern insuring that there is only ever one instance of
79   * this class.
80   * <p>
81   * Note that because this supports only the standard functions, this
82   * factory does not allow the addition of any other functions. If you call
83   * <code>addFunction</code> on an instance of this class, an exception
84   * will be thrown. If you need a standard factory that is modifiable,
85   * you can either create a new <code>BaseFunctionFactory</code> (or some
86   * other implementation of <code>FunctionFactory</code>) populated with
87   * the standard functions from <code>getStandardFunctions</code> or
88   * you can use <code>getNewFactoryProxy</code> to get a proxy containing
89   * a new, modifiable set of factories.
90   *
91   * @since 1.2
92   * @author Seth Proctor
93   */
94  public class StandardFunctionFactory extends BaseFunctionFactory
95  {
96  
97      // the three singleton instances
98      private static StandardFunctionFactory targetFactory = null;
99      private static StandardFunctionFactory conditionFactory = null;
100     private static StandardFunctionFactory generalFactory = null;
101 
102     // the three function sets/maps that we use internally
103     private static Set targetFunctions = null;
104     private static Set conditionFunctions = null;
105     private static Set generalFunctions = null;
106 
107     private static Map targetAbstractFunctions = null;
108     private static Map conditionAbstractFunctions = null;
109     private static Map generalAbstractFunctions = null;
110 
111     // the set/map used by each singleton factory instance
112     private Set supportedFunctions = null;
113     private Map supportedAbstractFunctions = null;
114 
115     // the logger we'll use for all messages
116     private static final Logger logger =
117         Logger.getLogger(StandardFunctionFactory.class.getName());
118 
119     /**
120      * Creates a new StandardFunctionFactory, making sure that the default
121      * maps are initialized correctly. Standard factories can't be modified,
122      * so there is no notion of supersetting since that's only used for
123      * correctly propagating new functions.
124      */
125     private StandardFunctionFactory(Set supportedFunctions,
126                                     Map supportedAbstractFunctions) {
127         super(supportedFunctions, supportedAbstractFunctions);
128 
129         this.supportedFunctions = supportedFunctions;
130         this.supportedAbstractFunctions = supportedAbstractFunctions;
131     }
132 
133     /**
134      * Private initializer for the target functions. This is only ever
135      * called once.
136      */
137     private static void initTargetFunctions() {
138         logger.config("Initializing standard Target functions");
139 
140         targetFunctions = new HashSet();
141 
142         // add EqualFunction
143         targetFunctions.addAll((new EqualFunctionCluster()).
144                                getSupportedFunctions());
145         // add LogicalFunction
146         targetFunctions.addAll((new LogicalFunctionCluster()).
147                                getSupportedFunctions());
148         // add NOfFunction
149         targetFunctions.addAll((new NOfFunctionCluster()).
150                                getSupportedFunctions());
151         // add NotFunction
152         targetFunctions.addAll((new NotFunctionCluster()).
153                                getSupportedFunctions());
154         // add ComparisonFunction
155         targetFunctions.addAll((new ComparisonFunctionCluster()).
156                                getSupportedFunctions());
157         // add MatchFunction
158         targetFunctions.addAll((new MatchFunctionCluster()).
159                                getSupportedFunctions());
160 
161         targetAbstractFunctions = new HashMap();
162     }
163 
164     /**
165      * Private initializer for the condition functions. This is only ever
166      * called once.
167      */
168     private static void initConditionFunctions() {
169         logger.config("Initializing standard Condition functions");
170 
171         if (targetFunctions == null)
172             initTargetFunctions();
173 
174         conditionFunctions = new HashSet(targetFunctions);
175 
176         // add condition functions from BagFunction
177         conditionFunctions.addAll((new ConditionBagFunctionCluster()).
178                                   getSupportedFunctions());
179         // add condition functions from SetFunction
180         conditionFunctions.addAll((new ConditionSetFunctionCluster()).
181                                   getSupportedFunctions());
182         // add condition functions from HigherOrderFunction
183         conditionFunctions.addAll((new HigherOrderFunctionCluster()).
184                                   getSupportedFunctions());
185 
186         conditionAbstractFunctions = new HashMap(targetAbstractFunctions);
187     }
188 
189     /**
190      * Private initializer for the general functions. This is only ever
191      * called once.
192      */
193     private static void initGeneralFunctions() {
194         logger.config("Initializing standard General functions");
195 
196         if (conditionFunctions == null)
197             initConditionFunctions();
198 
199         generalFunctions = new HashSet(conditionFunctions);
200 
201         // add AddFunction
202         generalFunctions.addAll((new AddFunctionCluster()).
203                                 getSupportedFunctions());
204         // add SubtractFunction
205         generalFunctions.addAll((new SubtractFunctionCluster()).
206                                 getSupportedFunctions());
207         // add MultiplyFunction
208         generalFunctions.addAll((new MultiplyFunctionCluster()).
209                                 getSupportedFunctions());
210         // add DivideFunction
211         generalFunctions.addAll((new DivideFunctionCluster()).
212                                 getSupportedFunctions());
213         // add ModFunction
214         generalFunctions.addAll((new ModFunctionCluster()).
215                                 getSupportedFunctions());
216         // add AbsFunction
217         generalFunctions.addAll((new AbsFunctionCluster()).
218                                 getSupportedFunctions());
219         // add RoundFunction
220         generalFunctions.addAll((new RoundFunctionCluster()).
221                                 getSupportedFunctions());
222         // add FloorFunction
223         generalFunctions.addAll((new FloorFunctionCluster()).
224                                 getSupportedFunctions());
225         // add DateMathFunction
226         generalFunctions.addAll((new DateMathFunctionCluster()).
227                                 getSupportedFunctions());
228         // add general functions from BagFunction
229         generalFunctions.addAll((new GeneralBagFunctionCluster()).
230                                 getSupportedFunctions());
231         // add NumericConvertFunction
232         generalFunctions.addAll((new NumericConvertFunctionCluster()).
233                                 getSupportedFunctions());
234         // add StringNormalizeFunction
235         generalFunctions.addAll((new StringNormalizeFunctionCluster()).
236                                 getSupportedFunctions());
237         // add general functions from SetFunction
238         generalFunctions.addAll((new GeneralSetFunctionCluster()).
239                                 getSupportedFunctions());
240             
241         generalAbstractFunctions = new HashMap(conditionAbstractFunctions);
242 
243         // add the map function's proxy
244         try {
245             generalAbstractFunctions.put(new URI(MapFunction.NAME_MAP),
246                                          new MapFunctionProxy());
247         } catch (URISyntaxException e) {
248             // this shouldn't ever happen, but just in case...
249             throw new IllegalArgumentException("invalid function name");
250         }
251     }
252 
253     /**
254      * Returns a FunctionFactory that will only provide those functions that
255      * are usable in Target matching. This method enforces a singleton
256      * model, meaning that this always returns the same instance, creating
257      * the factory if it hasn't been requested before. This is the default
258      * model used by the <code>FunctionFactory</code>, ensuring quick
259      * access to this factory.
260      *
261      * @return a <code>FunctionFactory</code> for target functions
262      */
263     public static StandardFunctionFactory getTargetFactory() {
264         if (targetFactory == null) {
265             synchronized (StandardFunctionFactory.class) {
266                 if (targetFunctions == null)
267                     initTargetFunctions();
268                 if (targetFactory == null)
269                     targetFactory =
270                         new StandardFunctionFactory(targetFunctions,
271                                                     targetAbstractFunctions);
272             }
273         }
274 
275         return targetFactory;
276     }
277 
278     /**
279      * Returns a FuntionFactory that will only provide those functions that
280      * are usable in the root of the Condition. These Functions are a
281      * superset of the Target functions. This method enforces a singleton
282      * model, meaning that this always returns the same instance, creating
283      * the factory if it hasn't been requested before. This is the default
284      * model used by the <code>FunctionFactory</code>, ensuring quick
285      * access to this factory.
286      *
287      * @return a <code>FunctionFactory</code> for condition functions
288      */
289     public static StandardFunctionFactory getConditionFactory() {
290         if (conditionFactory == null) {
291             synchronized (StandardFunctionFactory.class) {
292                 if (conditionFunctions == null)
293                     initConditionFunctions();
294                 if (conditionFactory == null)
295                     conditionFactory =
296                         new StandardFunctionFactory(conditionFunctions,
297                                                     conditionAbstractFunctions);
298             }
299         }
300 
301         return conditionFactory;
302     }
303 
304     /**
305      * Returns a FunctionFactory that provides access to all the functions.
306      * These Functions are a superset of the Condition functions. This method
307      * enforces a singleton model, meaning that this always returns the same
308      * instance, creating the factory if it hasn't been requested before.
309      * This is the default model used by the <code>FunctionFactory</code>,
310      * ensuring quick access to this factory.
311      *
312      * @return a <code>FunctionFactory</code> for all functions
313      */
314     public static StandardFunctionFactory getGeneralFactory() {
315         if (generalFactory == null) {
316             synchronized (StandardFunctionFactory.class) {
317                 if (generalFunctions == null) {
318                     initGeneralFunctions();
319                     generalFactory =
320                         new StandardFunctionFactory(generalFunctions,
321                                                     generalAbstractFunctions);
322                 }
323             }
324         }
325         
326         return generalFactory;
327     }
328 
329     /**
330      * Returns the set of functions that this standard factory supports.
331      *
332      * @return a <code>Set</code> of <code>Function</code>s
333      */
334     public Set getStandardFunctions() {
335         return Collections.unmodifiableSet(supportedFunctions);
336     }
337 
338     /**
339      * Returns the set of abstract functions that this standard factory
340      * supports as a mapping of identifier to proxy.
341      *
342      * @return a <code>Map</code> mapping <code>URI</code>s to
343      *         <code>FunctionProxy</code>s
344      */
345     public Map getStandardAbstractFunctions() {
346         return Collections.unmodifiableMap(supportedAbstractFunctions);
347     }
348 
349     /**
350      * A convenience method that returns a proxy containing newly created
351      * instances of <code>BaseFunctionFactory</code>s that are correctly
352      * supersetted and contain the standard functions and abstract functions.
353      * These factories allow adding support for new functions.
354      *
355      * @return a new proxy containing new factories supporting the standard
356      *         functions
357      */
358     public static FunctionFactoryProxy getNewFactoryProxy() {
359         StandardFunctionFactory general =
360             StandardFunctionFactory.getGeneralFactory();
361         FunctionFactory newGeneral =
362             new BaseFunctionFactory(general.getStandardFunctions(),
363                                     general.getStandardAbstractFunctions());
364 
365         StandardFunctionFactory condition =
366             StandardFunctionFactory.getConditionFactory();
367         FunctionFactory newCondition =
368             new BaseFunctionFactory(newGeneral,
369                                     condition.getStandardFunctions(),
370                                     condition.getStandardAbstractFunctions());
371 
372         StandardFunctionFactory target =
373             StandardFunctionFactory.getTargetFactory();
374         FunctionFactory newTarget =
375             new BaseFunctionFactory(newCondition,
376                                     target.getStandardFunctions(),
377                                     target.getStandardAbstractFunctions());
378 
379         return new BasicFunctionFactoryProxy(newTarget, newCondition,
380                                              newGeneral);
381     }
382 
383     /**
384      * Always throws an exception, since support for new functions may not be
385      * added to a standard factory.
386      *
387      * @param function the <code>Function</code> to add to the factory
388      *
389      * @throws UnsupportedOperationException always
390      */
391     public void addFunction(Function function)
392         throws IllegalArgumentException
393     {
394         throw new UnsupportedOperationException("a standard factory cannot " +
395                                                 "support new functions");
396     }
397 
398     /**
399      * Always throws an exception, since support for new functions may not be
400      * added to a standard factory.
401      *
402      * @param proxy the <code>FunctionProxy</code> to add to the factory
403      * @param identity the function's identifier
404      *
405      * @throws UnsupportedOperationException always
406      */
407     public void addAbstractFunction(FunctionProxy proxy,
408                                     URI identity)
409         throws IllegalArgumentException
410     {
411         throw new UnsupportedOperationException("a standard factory cannot " +
412                                                 "support new functions");
413     }
414 
415 }