KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > tools > guiframework > util > PermissionChecker


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.tools.guiframework.util;
25
26 import com.sun.enterprise.tools.guiframework.exception.FrameworkException;
27 import com.sun.enterprise.tools.guiframework.view.descriptors.ViewDescriptor;
28
29 import java.util.ArrayList JavaDoc;
30 import java.util.EmptyStackException JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Stack JavaDoc;
36 import java.util.StringTokenizer JavaDoc;
37
38
39 /**
40  * This class takes a "Permission String" and is cabable of determining if
41  * a user passes the permission check. Supported "checks" are:
42  *
43  * <UL><LI>Boolean -- "true" or "false"</LI>
44  * </UL>
45  *
46  * The format of the "Permission String" must be an equation that results in a
47  * boolean answer. The supported functions/operators are:
48  *
49  * --
50  * <UL><LI>$(<attribute>) -- To read a Boolean value from an attribute
51  * (false if attribute is not present) </LI>
52  * <LI>'(' and ')' can be used to define order of operation </LI>
53  * <LI>'!' may be used to negate a value </LI>
54  * <LI>'|' may be used as a logical OR </LI>
55  * <LI>'&' may be used as a logical AND </LI>
56  * <LI>'=' may be used as a String equals </LI>
57  * </UL>
58  *
59  *
60  * Operator Precedence (for infix notation) is:
61  * <UL><LI> () -- Highest </LI>
62  * <LI> ! </LI>
63  * <LI> & </LI>
64  * <LI> | </LI>
65  * <LI> = </LI>
66  * </UL>
67  */

68 public class PermissionChecker implements java.io.Serializable JavaDoc {
69
70     /**
71      * This is the constructor method that is required to create this object.
72      */

73     public PermissionChecker(String JavaDoc infixStr, ViewDescriptor vd) {
74     setViewDescriptor(vd);
75     setInfix(stripWhiteSpace(infixStr));
76     }
77
78
79     /**
80      * This method sets the ViewDescriptor that is associated with the 'if'
81      * check being evaluated. This is not normally needed, it is only needed
82      * if the 'if' check contains an expression which requires a
83      * ViewDescriptor to be properly evaluated.
84      *
85      * NOTE: The parser substitutes expressions (that may need a
86      * ViewDescriptor) at constructor-time. Setting the ViewDescriptor
87      * later has no effect.
88      */

89     protected void setViewDescriptor(ViewDescriptor vd) {
90     _vd = vd;
91     }
92
93
94     /**
95      * Retreives the ViewDescriptor associated with this PermissionChecker
96      * (only needed in cases where a expression requires a ViewDescriptor for
97      * evaluation).
98      *
99      * NOTE: The parser substitutes expressions (that may need a
100      * ViewDescriptor) at constructor-time. Setting the ViewDescriptor
101      * later has no effect.
102      */

103     public ViewDescriptor getViewDescriptor() {
104     return _vd;
105     }
106
107
108     /**
109      * <p> This method returns the precedence of the given operator. This only
110      * applies to infix notation (of course) and is needed to correctly
111      * order the operators when converting to postfix.</p>
112      *
113      * <UL><LI> ! (not) has the highest precedence
114      * <LI> & (and)
115      * <LI> | (and)
116      * </UL>
117      *
118      * <p> Of course '(' and ')' can be used to override the order of
119      * operations in infix notation.</p>
120      *
121      * @param op The operator to evaluate.
122      *
123      * @return A number that can be used to compare its precedence.
124      */

125     private static int getPrecedence(char op) {
126     switch (op) {
127         case LEFT_PAREN:
128         return 2;
129         case RIGHT_PAREN:
130         return 999;
131         case EQUALS_OPERATOR:
132         return 3;
133         case OR_OPERATOR:
134         return 4;
135         case AND_OPERATOR:
136         return 5;
137         case NOT_OPERATOR:
138         return 6;
139     }
140     return 1;
141     }
142
143
144     /**
145      * This method replaces all "true" / "false" strings w/ 't'/'f'. It
146      * converts the String into a char[]. It replaces all user defined
147      * functions w/ 'F' and places a Function in a list per the registered
148      * user-defined function. All other strings are converted to an 'F' and
149      * a StringFunction is added to the function list.
150      */

151     protected char[] preProcessString(String JavaDoc source) {
152     // First, handle variable substitution "$...(...)"
153
source = substituteVariables(source, getViewDescriptor());
154
155         char arr[] = source.toCharArray();
156     int sourceLen = arr.length;
157     int destLen = 0;
158     String JavaDoc str = null;
159
160     // Loop through the String, char by char
161
for (int idx=0; idx<sourceLen ; idx++) {
162         switch (arr[idx]) {
163         case POST_TRUE:
164         case POST_TRUE_CAP:
165             if (((idx + TRUE.length()) <= sourceLen) &&
166                         TRUE.equalsIgnoreCase(new String JavaDoc(arr, idx, TRUE.length()))) {
167             arr[destLen++] = POST_TRUE;
168             idx += TRUE.length()-1;
169             } else {
170             idx = storeFunction(arr, idx);
171                         arr[destLen++] = FUNCTION_MARKER;
172                     }
173             break;
174         case POST_FALSE:
175         case POST_FALSE_CAP:
176             if (((idx + FALSE.length()) <= sourceLen) &&
177                         FALSE.equalsIgnoreCase(new String JavaDoc(arr, idx, FALSE.length()))) {
178             arr[destLen++] = POST_FALSE;
179             idx += FALSE.length()-1;
180             } else {
181             idx = storeFunction(arr, idx);
182                         arr[destLen++] = FUNCTION_MARKER;
183                     }
184             break;
185         case OR_OPERATOR:
186         case EQUALS_OPERATOR:
187         case AND_OPERATOR:
188         case NOT_OPERATOR:
189         case LEFT_PAREN:
190         case RIGHT_PAREN:
191             arr[destLen++] = arr[idx];
192             break;
193         default:
194             idx = storeFunction(arr, idx);
195             arr[destLen++] = FUNCTION_MARKER;
196         }
197     }
198     char dest[] = new char[destLen];
199     for (int idx=0; idx<destLen; idx++) {
200         dest[idx] = arr[idx];
201     }
202     return dest;
203     }
204
205
206     /**
207      * This method searches for "$...(...)" in given string and replaces them
208      * with FUNCTION_MARKER's. It adds a Function to the _tmpFunctionStack
209      * for each of these so that it can be inserted in the proper place during
210      * preProcessing. If the "$()" evaluates to (null), it is replaced with
211      * false (BooleanFunction); if it evalutes to "false", it also will use a
212      * false BooleanFunction. In all other cases, it will be replaced with a
213      * StringFunction which evaluates to true.
214      */

215     protected String JavaDoc substituteVariables(String JavaDoc string, ViewDescriptor vd) {
216 // FIXME: Consider reworking this to be an inline substitution... since nested
217
// FIXME: $()'s aren't supported, a single-pass forward replacement may
218
// FIXME: simplify this.
219
int stringLen = string.length();
220     int startTokenLen = Util.SUB_START.length();
221     int delimLen = Util.SUB_TYPE_DELIM.length();
222     int endTokenLen = Util.SUB_END.length();
223     int endIndex, delimIndex;
224     int parenSemi;
225     char firstEndChar = Util.SUB_END.charAt(0);
226     char firstDelimChar = Util.SUB_TYPE_DELIM.charAt(0);
227     char currChar;
228     Object JavaDoc obj = null;
229
230     // Temporary Function List (functions here will be inserted correctly
231
// during preProcessing)
232
_tmpFunctionStack = new Stack JavaDoc();
233     _currTmpFunction = 0;
234
235     // Iterate through the String backwards looking for substitutions
236
for (int startIndex = string.lastIndexOf(Util.SUB_START);
237          startIndex != -1;
238              startIndex = string.lastIndexOf(Util.SUB_START, startIndex-1)) {
239
240         // Find make sure we have a typeDelim
241
delimIndex = string.indexOf(Util.SUB_TYPE_DELIM, startIndex+startTokenLen);
242         if (delimIndex == -1) {
243         continue;
244         }
245
246         // Next find the end token
247
parenSemi = 0;
248         endIndex = -1;
249         for (int curr = delimIndex+delimLen; curr<stringLen; ) {
250         currChar = string.charAt(curr);
251         if ((currChar == firstDelimChar) && Util.SUB_TYPE_DELIM.equals(string.substring(curr, curr+delimLen))) {
252             parenSemi++;
253             curr += delimLen;
254             continue;
255         }
256         if ((currChar == firstEndChar) && Util.SUB_END.equals(string.substring(curr, curr+endTokenLen))) {
257             parenSemi--;
258             if (parenSemi < 0) {
259             endIndex = curr;
260             break;
261             }
262             curr += endTokenLen;
263             continue;
264         }
265         curr++;
266         }
267         if (endIndex == -1) {
268         continue;
269         }
270
271         // increment the endIndex to point just after it
272
endIndex += endTokenLen;
273
274         // We found a match! Evaluate the whole substring ('$' to ')')
275
obj = Util.replaceVariablesWithAttributes(string.substring(startIndex, endIndex), vd);
276         if (obj == null) {
277         // if match evalutes to null, add a "false" to equation
278
obj = FALSE_BOOLEAN_FUNCTION;
279         } else {
280         String JavaDoc str = obj.toString();
281         if (str.equals("") || str.equalsIgnoreCase("false")) {
282             // Add a Boolean (false) function b/c the string == "false"
283
obj = FALSE_BOOLEAN_FUNCTION;
284         } else {
285             // Add a StringFunction to the equation
286
obj = new StringFunction(str);
287         }
288         }
289
290         // Add the function
291
_tmpFunctionStack.push(obj);
292
293         // Make new string
294
string = string.substring(0, startIndex) + // Before replacement
295
FUNCTION_MARKER + // Replacement
296
string.substring(endIndex); // After
297
}
298
299     // Return the (new) string
300
return string;
301     }
302
303
304     /**
305      * <P>This method looks at the given char array starting at index and
306      * continues until an operator (or end of String) is encountered. It then
307      * uses this string to lookup a registered function (if any), it stores
308      * that function (with parameters)... or if the function is not found, it
309      * registers a "String function" (which always returns true).</P>
310      */

311     protected int storeFunction(char arr[], int idx) {
312     // Find string...
313
int start = idx;
314     int len = arr.length;
315     while ((idx < len) && !isOperator(arr[idx])) {
316         idx++;
317     }
318
319     // Create String...
320
String JavaDoc str = new String JavaDoc(arr, start, idx-start);
321
322     // Check to see if it is a registered function...
323
Function function = getFunction(str);
324     if (function != null) {
325         // Find the left paren...
326
int left = idx;
327         if ((left >= len) || (arr[left] != LEFT_PAREN)) {
328         throw new FrameworkException("Function '"+str+
329             "' is expected to have a '"+LEFT_PAREN+
330             "' immediately following it. Equation: '"+
331             new String JavaDoc(arr)+"'.");
332         }
333
334         ArrayList JavaDoc arguments = new ArrayList JavaDoc();
335
336         // Find the right Paren...
337
while ((++idx < len) && (arr[idx] != RIGHT_PAREN)) {
338         if (arr[idx] == ARGUMENT_SEPARATOR) {
339             left++;
340             arguments.add(new String JavaDoc(arr, left, idx-left));
341             left = idx;
342         }
343         }
344
345         // Make sure we don't have ()
346
left++;
347         if (idx > left) {
348         arguments.add(new String JavaDoc(arr, left, idx-left));
349         }
350
351         // Set the arguments...
352
function.setArguments(arguments);
353     } else {
354         // Not a registered function...
355
idx--; // In this case, there are no ()'s to consume, backup 1
356
if ((str.charAt(0) == FUNCTION_MARKER) && (str.length() == 1) &&
357             !_tmpFunctionStack.empty()) {
358         // We have a function added during the subtitute() phase
359
function = (Function)_tmpFunctionStack.pop();
360         } else {
361         // Create a StringFunction (always true)
362
function = new StringFunction(str);
363         }
364     }
365
366     // Add the function to the function list
367
_functionList.add(function);
368
369     // Return the number of characters that we consumed...
370
return idx;
371     }
372
373
374     /**
375      * This method is a factory method for constructing a new function based
376      * on the function name passed in. The function must be registered prior
377      * to invoking this method.
378      */

379     protected static Function getFunction(String JavaDoc functionName) {
380     // Get the Function class
381
Class JavaDoc functionClass = (Class JavaDoc)_functions.get(functionName);
382     if (functionClass == null) {
383         return null;
384     }
385
386     // Create a new instance
387
Function function = null;
388     try {
389         function = (Function)functionClass.newInstance();
390     } catch (Exception JavaDoc ex) {
391         throw new FrameworkException("Unable to instantiate '"+
392         functionClass.getName()+"' for '"+functionName+"'", ex);
393     }
394
395     // Return the instance
396
return function;
397     }
398
399
400     /**
401      * <P>This method allows arbitrary functions to be registered. Function
402      * names should only contain letters or numbers, other characters or
403      * whitespace may cause problems. No checking is done to ensure this,
404      * however.</P>
405      *
406      * <P>Functions will be expressed in an equation as follows:</P>
407      *
408      * <UL><LI>function_name(param1,param2)</LI></UL>
409      *
410      * <P>Function parameters also should only contain alpha-numeric
411      * characters.</P>
412      *
413      * <P>Functions must implement PermissionChecker.Function interface</P>
414      */

415     public static void registerFunction(String JavaDoc functionName, Class JavaDoc function) {
416     if (function == null) {
417         _functions.remove(functionName);
418     }
419     if (!Function.class.isAssignableFrom(function)) {
420         throw new FrameworkException("'"+function.getName()+
421         "' must implement '"+Function.class.getName()+"'");
422     }
423     _functions.put(functionName, function);
424     }
425
426
427     /**
428      * This method returns true if the given character is a valid operator.
429      */

430     public boolean isOperator(char ch) {
431     switch (ch) {
432         case LEFT_PAREN:
433         case RIGHT_PAREN:
434         case EQUALS_OPERATOR:
435         case OR_OPERATOR:
436         case AND_OPERATOR:
437         case NOT_OPERATOR:
438 // To allow the Appserver Admin GUI to function correctly, these have been
439
// removed as a precaution... the appserver needs to escape their 'if' strings
440
// before re-enabling the following:
441
// case LESS_THAN_OPERATOR:
442
// case MORE_THAN_OPERATOR:
443
// case AT_OPERATOR:
444
// case POUND_OPERATOR:
445
// case DOLLAR_OPERATOR:
446
// case UP_OPERATOR:
447
// case STAR_OPERATOR:
448
// case TILDA_OPERATOR:
449
// case ARGUMENT_SEPARATOR:
450
return true;
451     }
452     return false;
453     }
454
455
456     /**
457      * This method calculates the postfix representation of the infix equation
458      * passed in. It returns the postfix equation as a char[].
459      *
460      * @param infixStr The infix representation of the equation.
461      *
462      * @return postfix representation of the equation as a char[] (the f()'s
463      * are removed and stored in _functionList).
464      */

465     protected char [] generatePostfix(String JavaDoc infixStr) {
466     // Reset the _functionList
467
_functionList = new ArrayList JavaDoc();
468
469     // Convert string to our parsable format
470
char result[] = preProcessString(infixStr);
471 //System.out.println("DEBUG: Initial String: '"+infixStr+"'");
472
//System.out.println("DEBUG: After Pre-process: '"+new String(result)+"'");
473
int resultLen = result.length;
474     int postIdx = 0;
475     int precedence = 0;
476     Stack JavaDoc opStack = new Stack JavaDoc();
477
478     // Put f()'s directly into result, push operators into right order
479
for (int idx=0; idx<resultLen; idx++) {
480         switch(result[idx]) {
481         case FUNCTION_MARKER:
482         case POST_TRUE:
483         case POST_FALSE:
484             result[postIdx++] = result[idx];
485             break;
486         case LEFT_PAREN:
487             opStack.push(new Character JavaDoc(LEFT_PAREN));
488             break;
489         case RIGHT_PAREN:
490             while (!opStack.empty() && (((Character JavaDoc)opStack.peek()).charValue() != LEFT_PAREN)) {
491             result[postIdx++] = ((Character JavaDoc)opStack.pop()).charValue();
492             }
493             if (!opStack.empty()) {
494             // Throw away the LEFT_PAREN that should still be there
495
opStack.pop();
496             }
497             break;
498         default:
499             // clear stuff
500
precedence = getPrecedence(result[idx]);
501             while (!opStack.empty() && (getPrecedence(((Character JavaDoc)opStack.peek()).charValue()) >= precedence)) {
502             result[postIdx++] = ((Character JavaDoc)opStack.pop()).charValue();
503             }
504
505             /* Put it on the stack */
506             opStack.push(new Character JavaDoc(result[idx]));
507             break;
508         }
509     }
510
511     // empty the rest of the stack to the result
512
while (!opStack.empty()) {
513         result[postIdx++] = ((Character JavaDoc)opStack.pop()).charValue();
514     }
515     // Copy the result to the postfixStr
516
char postfixStr[] = new char[postIdx];
517     for (int idx=0; idx<postIdx; idx++) {
518         postfixStr[idx] = result[idx];
519     }
520 //System.out.println("DEBUG: Postfix String: '"+new String(postfixStr)+"'");
521
return postfixStr;
522     }
523
524     /**
525      * This method is invoked to determine if the equation evaluates to true
526      * or false.
527      */

528     public boolean hasPermission() {
529     char postfixArr[] = getPostfixArr();
530     int len = postfixArr.length;
531     Stack JavaDoc result = new Stack JavaDoc();
532     result.push(FALSE_BOOLEAN_FUNCTION); // Default to false
533
boolean val1, val2;
534     Iterator JavaDoc it = _functionList.iterator();
535     Function func = null;
536
537     // Iterate through the postfix array
538
for (int idx=0; idx<len; idx++) {
539         switch (postfixArr[idx]) {
540         case POST_TRUE:
541             result.push(TRUE_BOOLEAN_FUNCTION);
542             break;
543         case POST_FALSE:
544             result.push(FALSE_BOOLEAN_FUNCTION);
545             break;
546         case FUNCTION_MARKER:
547             if (!it.hasNext()) {
548             throw new FrameworkException("Unable to evaluate: '"+
549                 toString()+"' -- found function marker w/o "+
550                 "cooresponding function!");
551             }
552             result.push(it.next());
553             break;
554         case EQUALS_OPERATOR:
555             try {
556             val1 = result.pop().toString().equals(result.pop().toString());
557             } catch (EmptyStackException JavaDoc ex) {
558             throw new FrameworkException("Unable to evaluate: '"+toString()+"'.", ex);
559             }
560             result.push(val1 ? TRUE_BOOLEAN_FUNCTION :
561                     FALSE_BOOLEAN_FUNCTION);
562             break;
563         case OR_OPERATOR:
564             try {
565             val1 = ((Function)result.pop()).evaluate();
566             val2 = ((Function)result.pop()).evaluate();
567             } catch (EmptyStackException JavaDoc ex) {
568             throw new FrameworkException("Unable to evaluate: '"+toString()+"'.", ex);
569             }
570             result.push( (val1 || val2) ? TRUE_BOOLEAN_FUNCTION :
571                             FALSE_BOOLEAN_FUNCTION);
572             break;
573         case AND_OPERATOR:
574             try {
575             val1 = ((Function)result.pop()).evaluate();
576             val2 = ((Function)result.pop()).evaluate();
577             } catch (EmptyStackException JavaDoc ex) {
578             throw new FrameworkException("Unable to evaluate: '"+toString()+"'.", ex);
579             }
580             result.push( (val1 && val2) ? TRUE_BOOLEAN_FUNCTION :
581                             FALSE_BOOLEAN_FUNCTION);
582             break;
583         case NOT_OPERATOR:
584             try {
585             val1 = ((Function)result.pop()).evaluate();
586             } catch (EmptyStackException JavaDoc ex) {
587             throw new FrameworkException("Unable to evaluate: '"+toString()+"'.", ex);
588             }
589             result.push( (!val1) ? TRUE_BOOLEAN_FUNCTION :
590                         FALSE_BOOLEAN_FUNCTION);
591             break;
592         }
593     }
594
595     // Return the only element on the stack (hopefully)
596
try {
597         val1 = ((Function)result.pop()).evaluate();
598     } catch (EmptyStackException JavaDoc ex) {
599         throw new FrameworkException("Unable to evaluate: '"+
600         toString()+"'.", ex);
601     }
602     if (!result.empty()) {
603         result.pop(); // We added a false that wasn't needed
604
if (!result.empty()) {
605         throw new FrameworkException("Unable to evaluate: '"+
606             toString()+"' -- values left on the stack.");
607         }
608     }
609     return val1;
610     }
611
612
613     /**
614      * This method returns the infix representation of the equation, in other
615      * words: the original String passed in.
616      */

617     public String JavaDoc getInfix() {
618     return _infixStr;
619     }
620
621
622     /**
623      * This method sets the equation and forces a re-evaluation of the
624      * equation. It returns the postfix representation of the equation.
625      *
626      * @param equation The infix equation to use
627      */

628     public void setInfix(String JavaDoc equation) {
629     _infixStr = equation;
630     setPostfixArr(generatePostfix(equation));
631     }
632
633
634     /**
635      *
636      */

637     public char [] getPostfixArr() {
638     if (_postfixArr == null) {
639         _postfixArr = new char[] {' '};
640     }
641     return _postfixArr;
642     }
643
644
645     /**
646      *
647      */

648     protected void setPostfixArr(char postfix[]) {
649     _postfixArr = postfix;
650     }
651
652
653     /**
654      *
655      */

656     public String JavaDoc getPostfix() {
657     if (getPostfixArr() == null) {
658         return "";
659     }
660     return new String JavaDoc(getPostfixArr());
661     }
662
663
664     /**
665      * Displays the infix and postfix version of the equation.
666      */

667     public String JavaDoc toString() {
668         return _infixStr + " = " + toString(getPostfixArr());
669     }
670
671
672     /**
673      * This toString(...) method generates just the postfix representation of
674      * the equation. The postfix notation is stored as a char[] and it has
675      * the functions removed from the char[]. This method iterates through
676      * the char[] and generates a String with the functions put back into the
677      * equation.
678      *
679      * @param post The char[] representation of the postfix equation
680      */

681     private String JavaDoc toString(char post[]) {
682     int len = post.length;
683     String JavaDoc result = "";
684     Iterator JavaDoc it = _functionList.iterator();
685
686     for (int idx=0; idx<len; idx++) {
687         switch (post[idx]) {
688         case POST_TRUE:
689             result += TRUE;
690             break;
691         case POST_FALSE:
692             result += FALSE;
693             break;
694         case FUNCTION_MARKER:
695             result += ((Function)it.next()).toString();
696             break;
697         default:
698             result += post[idx];
699         }
700     }
701
702     return result;
703     }
704
705
706     /**
707      * This method removes all whitespace from the given String
708      */

709     public static String JavaDoc stripWhiteSpace(String JavaDoc input) {
710     char arr[] = input.toCharArray();
711     int len = arr.length;
712     int destLen = 0;
713
714     // Loop through the array skipping whitespace
715
for (int idx=0; idx<len; idx++) {
716         if (Character.isWhitespace(arr[idx])) {
717         continue;
718         }
719         arr[destLen++] = arr[idx];
720     }
721
722     // Return the result
723
return new String JavaDoc(arr, 0, destLen);
724     }
725
726
727
728
729     /**
730      * This class must be implemented by all user defined Functions.
731      *
732      * <P>In addition to these methods, a toString() should be implemented
733      * that reconstructs the original format of the function (i.e.
734      * function_name(arg1,arg2...)).
735      */

736     public static interface Function {
737
738     /**
739      * This method returns the List of arguments.
740      */

741     public List JavaDoc getArguments();
742
743     /**
744      * This method is invoked be the PermissionChecker to set the
745      * arguments.
746      */

747     public void setArguments(List JavaDoc args);
748
749     /**
750      * This method is invoked by the PermissionCheck to evaluate the
751      * function to true or false.
752      */

753     public boolean evaluate();
754     }
755
756
757     /**
758      * StringFunction implements Function and serves as the default function.
759      * This function is special in that it is NEVER registered and is the
760      * only function that SHOULD NOT be followed by ()'s. This function
761      * always returns true and ignores all arguments (arguments only apply if
762      * it is registered, which shouldn't ever be the case anyway).
763      */

764     protected static class StringFunction implements PermissionChecker.Function {
765     public StringFunction(String JavaDoc value) {
766         _value = value;
767     }
768
769     public List JavaDoc getArguments() {
770         return null;
771     }
772
773     public void setArguments(List JavaDoc args) {
774     }
775
776     public boolean evaluate() {
777         return true;
778     }
779
780     public String JavaDoc toString() {
781         return _value;
782     }
783
784     private String JavaDoc _value;
785     }
786
787
788     /**
789      * BooleanFunction is either true or false. It is used internally by
790      * PermissionChecker and is not needed outside PermissionChecker since
791      * "true" and "false" used in an equation are equivalent.
792      */

793     protected static class BooleanFunction implements PermissionChecker.Function {
794     public BooleanFunction() {
795     }
796
797     public BooleanFunction(boolean value) {
798         _value = value;
799     }
800
801     public List JavaDoc getArguments() {
802         return null;
803     }
804
805     public void setArguments(List JavaDoc args) {
806     }
807
808     public boolean evaluate() {
809         return _value;
810     }
811
812     public String JavaDoc toString() {
813         return _value ? "true" : "false";
814     }
815
816     private boolean _value;
817     }
818
819
820
821     /**
822      * This is here to provide some test cases. It only tests the conversion
823      * to postfix notation.
824      */

825     public static void main(String JavaDoc args[]) {
826         PermissionChecker checker;
827     if (args.length > 0) {
828         for (int count=0; count<args.length; count++) {
829         checker = new PermissionChecker(args[count], null);
830         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
831         }
832     } else {
833         boolean success = true;
834         checker = new PermissionChecker("true |false", null);
835         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
836         if (!checker.toString().equals("true|false = truefalse|")) {
837         System.out.println("\tFAILED!");
838         System.out.println("Should have been:\n"+"true|false = truefalse|");
839         success = false;
840         }
841         if (!checker.hasPermission()) {
842         System.out.println("\tFAILED!");
843         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
844         success = false;
845         }
846
847         checker = new PermissionChecker("true&(false|true)", null);
848         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
849         if (!checker.toString().equals("true&(false|true) = truefalsetrue|&")) {
850         System.out.println("\tFAILED!");
851         System.out.println("Should have been:\n"+"true&(false|true) = truefalsetrue|&");
852         success = false;
853         }
854         if (!checker.hasPermission()) {
855         System.out.println("\tFAILED!");
856         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
857         success = false;
858         }
859
860         checker = new PermissionChecker("true&false|true", null);
861         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
862         if (!checker.toString().equals("true&false|true = truefalse&true|")) {
863         System.out.println("\tFAILED!");
864         System.out.println("Should have been:\n"+"true&false|true = truefalse&true|");
865         success = false;
866         }
867         if (!checker.hasPermission()) {
868         System.out.println("\tFAILED!");
869         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
870         success = false;
871         }
872
873         checker = new PermissionChecker("true&true|false&true", null);
874         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
875         if (!checker.toString().equals("true&true|false&true = truetrue&falsetrue&|")) {
876         System.out.println("\tFAILED!");
877         System.out.println("Should have been:\n"+"true&true|false&true = truetrue&falsetrue&|");
878         success = false;
879         }
880         if (!checker.hasPermission()) {
881         System.out.println("\tFAILED!");
882         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
883         success = false;
884         }
885
886         checker = new PermissionChecker("!true|false&!(false|true)", null);
887         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
888         if (!checker.toString().equals("!true|false&!(false|true) = true!falsefalsetrue|!&|")) {
889         System.out.println("\tFAILED!");
890         System.out.println("Should have been:\n"+"!true|false&!(false|true) = true!falsefalsetrue|!&|");
891         success = false;
892         }
893         if (checker.hasPermission()) {
894         System.out.println("\tFAILED!");
895         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
896         success = false;
897         }
898
899         checker = new PermissionChecker("!(!(true&!true)|!(false|false))|(true|false)&true", null);
900         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
901         if (!checker.toString().equals("!(!(true&!true)|!(false|false))|(true|false)&true = truetrue!&!falsefalse|!|!truefalse|true&|")) {
902
903         System.out.println("\tFAILED!");
904         System.out.println("Should have been:\n"+"!(!(true&!true)|!(false|false))|(true|false)&true = truetrue!&!falsefalse|!|!truefalse|true&|");
905         success = false;
906         }
907         if (!checker.hasPermission()) {
908         System.out.println("\tFAILED!");
909         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
910         success = false;
911         }
912
913         // Test '='
914
checker = new PermissionChecker("false =false", null);
915         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
916         if (!checker.toString().equals("false=false = falsefalse=")) {
917         System.out.println("\tFAILED!");
918         System.out.println("Should have been:\n"+"false=false = falsefalse=");
919         success = false;
920         }
921         if (!checker.hasPermission()) {
922         System.out.println("\tFAILED!");
923         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
924         success = false;
925         }
926
927         checker = new PermissionChecker(" test= me ", null);
928         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
929         if (!checker.toString().equals("test=me = testme=")) {
930         System.out.println("\tFAILED!");
931         System.out.println("Should have been:\n"+"test=me = testme=");
932         success = false;
933         }
934         if (checker.hasPermission()) {
935         System.out.println("\tFAILED!");
936         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
937         success = false;
938         }
939
940         checker = new PermissionChecker(" this should work=thisshouldwork", null);
941         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
942         if (!checker.toString().equals("thisshouldwork=thisshouldwork = thisshouldworkthisshouldwork=")) {
943         System.out.println("\tFAILED!");
944         System.out.println("Should have been:\n"+"thisshouldwork=thisshouldwork = thisshouldworkthisshouldwork=");
945         success = false;
946         }
947         if (!checker.hasPermission()) {
948         System.out.println("\tFAILED!");
949         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
950         success = false;
951         }
952
953         checker = new PermissionChecker("false|ab=true", null);
954         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
955         if (!checker.toString().equals("false|ab=true = falseab|true=")) {
956         System.out.println("\tFAILED!");
957         System.out.println("Should have been:\n"+"false|ab=true = falseab|true=");
958         success = false;
959         }
960         if (!checker.hasPermission()) {
961         System.out.println("\tFAILED!");
962         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
963         success = false;
964         }
965
966         checker = new PermissionChecker("false|(ab=true)", null);
967         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
968         if (!checker.toString().equals("false|(ab=true) = falseabtrue=|")) {
969         System.out.println("\tFAILED!");
970         System.out.println("Should have been:\n"+"false|ab=true = falseab|true=");
971         success = false;
972         }
973         if (checker.hasPermission()) {
974         System.out.println("\tFAILED!");
975         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
976         success = false;
977         }
978
979         checker = new PermissionChecker("false|(ab=ab)", null);
980         System.out.println("Output:\n" + checker.toString()+" ("+checker.hasPermission()+")");
981         if (!checker.toString().equals("false|(ab=ab) = falseabab=|")) {
982         System.out.println("\tFAILED!");
983         System.out.println("Should have been:\n"+"false|ab=true = falseab|true=");
984         success = false;
985         }
986         if (!checker.hasPermission()) {
987         System.out.println("\tFAILED!");
988         System.out.println("hasPermission("+checker.toString(checker.getPostfixArr())+") returned the wrong result!");
989         success = false;
990         }
991
992
993         if (success) {
994         System.out.println("\n\tALL TESTS PASSED!");
995         } else {
996         System.out.println("\n\tNOT ALL TESTS PASSED!");
997         }
998     }
999     }
1000
1001
1002    protected static final char POST_TRUE = 't';
1003    protected static final char POST_FALSE = 'f';
1004    protected static final char POST_TRUE_CAP = 'T';
1005    protected static final char POST_FALSE_CAP = 'F';
1006
1007    public static final String JavaDoc TRUE = "true";
1008    public static final String JavaDoc FALSE = "false";
1009
1010    // Function representation in postfix String
1011
public static final char FUNCTION_MARKER = 'F';
1012
1013    // Operator constants
1014
public static final char LEFT_PAREN = '(';
1015    public static final char RIGHT_PAREN = ')';
1016    public static final char EQUALS_OPERATOR = '=';
1017    public static final char OR_OPERATOR = '|';
1018    public static final char AND_OPERATOR = '&';
1019    public static final char NOT_OPERATOR = '!';
1020
1021    // The COMMA separates function arguments... not really an operator
1022
public static final char ARGUMENT_SEPARATOR = ',';
1023
1024    // Reserved operators, although not currently used...
1025
/*
1026 * These will be added eventually, but currently they are commented out to
1027 * enable the AppServer AdminGUI to function correctly
1028 *
1029 * public static final char LESS_THAN_OPERATOR = '<';
1030 * public static final char MORE_THAN_OPERATOR = '>';
1031 * public static final char AT_OPERATOR = '@';
1032 * public static final char POUND_OPERATOR = '#';
1033 * public static final char DOLLAR_OPERATOR = '$';
1034 * public static final char UP_OPERATOR = '^';
1035 * public static final char STAR_OPERATOR = '*';
1036 * public static final char TILDA_OPERATOR = '~';
1037 */

1038
1039    /**
1040     * This variable represents a "false" BooleanFunction.
1041     */

1042    public static final BooleanFunction FALSE_BOOLEAN_FUNCTION =
1043    new BooleanFunction(false);
1044
1045    /**
1046     * This variable represents a "true" BooleanFunction.
1047     */

1048    public static final BooleanFunction TRUE_BOOLEAN_FUNCTION =
1049    new BooleanFunction(true);
1050
1051    /**
1052     * This holds the infix equation
1053     */

1054    private String JavaDoc _infixStr = null;
1055
1056    /**
1057     * This holds the postfix equation
1058     */

1059    private char _postfixArr[] = null;
1060
1061    /**
1062     * This is a Map of Class objects which are user-registered functions.
1063     */

1064    private static Map JavaDoc _functions = new HashMap JavaDoc();
1065
1066    /**
1067     * This List holds the actual Function objects that correspond to the 'F'
1068     * markers in the postfix string.
1069     */

1070    private List JavaDoc _functionList = null;
1071
1072    /**
1073     * This List of functions maintains variableSubstitution Functions which
1074     * happen out-of-order. They will be pulled from this list as placed into
1075     * the actual _functionList when the are encountered during the
1076     * preProcessing.
1077     */

1078    private Stack JavaDoc _tmpFunctionStack = null;
1079    private int _currTmpFunction = 0;
1080    private ViewDescriptor _vd = null;
1081}
1082
Popular Tags