KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > core > model > approval > ApprovalExecutorUtil


1 /*************************************************************************
2  * *
3  * EJBCA: The OpenSource Certificate Authority *
4  * *
5  * This software is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or any later version. *
9  * *
10  * See terms of license at gnu.org. *
11  * *
12  *************************************************************************/

13 package org.ejbca.core.model.approval;
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.StringTokenizer JavaDoc;
17
18 import org.apache.log4j.Logger;
19 import org.ejbca.core.model.ca.caadmin.CAInfo;
20
21 /**
22  * Util class with methods to get information about calling classes
23  * Used to avoid cirkular method invocations
24
25 Approval configuration
26 ======================
27
28 There are three levels of configuration for approval.
29
30 1. Globally excluded classes. When these call functions that normally require approval, approval is not required. This is configured, as a comma separated list, in the ejbca.properties property approval.excludedClasses (for example approval.excludedClasses=org.ejbca.extra.caservice.ExtRACAProcess).
31 The check for these globally excluded classes are done in ApprovalExecutorUtil. The list of globally excluded classes are kept as a String in ApprovalExecutorUtil.
32
33 2. Fine grained excluded classes/methods. This is configured, hard coded, within a session bean that uses approval. These fine grained classes and methods uses an array of ApprovalOverridableClassName, which is passed to ApprovalExecutorUtil. The check itself is also done in ApprovalExecutorUtil. The array can be defined per approval function.
34 For example:
35 private static final ApprovalOveradableClassName[] NONAPPROVABLECLASSNAMES_SETUSERSTATUS = {
36         new ApprovalOveradableClassName("org.ejbca.core.ejb.ra.LocalUserAdminSessionBean","revokeUser"),
37         new ApprovalOveradableClassName("org.ejbca.core.ejb.ra.LocalUserAdminSessionBean","revokeCert"),
38         new ApprovalOveradableClassName("org.ejbca.ui.web.admin.rainterface.RAInterfaceBean","unrevokeCert"),
39         new ApprovalOveradableClassName("org.ejbca.ui.web.admin.rainterface.RAInterfaceBean","markForRecovery"),
40         new ApprovalOveradableClassName("se.primeKey.cardPersonalization.ra.connection.ejbca.EjbcaConnection",null)
41     };
42     
43 3. Transitions that are always allowed. For some approval methods there are transitions that never require approval. For example when status for a user changes from new->inprocess, or inprocess->generated.
44 These rules are configured, hard coded, within the ApprovalRequest, which is the entity that knows about the transitions best.
45 For example in ChangeStatusEndEntityApprovalRequest the status transitions from new->inprocess or inprocess->generated never required approval.
46 The code checking used by the programmer to determine if approval is required is once again ApprovalExecutorUtil.
47
48 Checking rules
49 --------------
50 To check all these rules is simple:
51
52 int numOfApprovalsRequired = getNumOfApprovalRequired(admin, CAInfo.REQ_APPROVAL_ADDEDITENDENTITY, caid);
53 ChangeStatusEndEntityApprovalRequest ar = new ChangeStatusEndEntityApprovalRequest(username, data1.getStatus(), status, admin, null, numOfApprovalsRequired, data1.getCaId(), data1.getEndEntityProfileId());
54 if (ApprovalExecutorUtil.requireApproval(ar,NONAPPROVABLECLASSNAMES_SETUSERSTATUS)) {
55     approvalsession.addApprovalRequest(admin, ar);
56     throw new WaitingForApprovalException("Edit Endity Action have been added for approval by authorized adminstrators");
57 }
58
59 The method ApprovalExecutorUtil.requireApproval checks first if the caller class is one of the globally exluded. Then it checks the passed in array ApprovalOveradableClassName, and last it calls the ApprovalRequest itself to see if it is a alwaysAllowedTransition (ApprovalRequest.isAlwaysAlloedTransition).
60
61 ApprovalExecutorUtil.requireApproval checks all the rules and returns true or false.
62
63  *
64  * @author Philip Vendil
65  * @version $Id: ApprovalExecutorUtil.java,v 1.10 2006/09/29 13:46:21 anatom Exp $
66  */

67 public class ApprovalExecutorUtil {
68       
69     private static final Logger log = Logger.getLogger(ApprovalExecutorUtil.class);
70     
71     /** These variables are protected to enable JUnit testing */
72     protected static String JavaDoc globallyAllowedString = "@approval.excludedClasses@";
73     protected static ApprovalOveradableClassName[] globallyAllowed = null;
74     
75      /** Method that checks if the request requires approval or not.
76      *
77      *
78      * @param req the request to check
79      * @param overridableClassNames containing an array of classnamnes/mehtods that shouldn't
80      * be involved in the approvalprocess, i.e their calls to the original method
81      * shouldn't require an approval even though approvals is configured for this method.
82      * Null means no classes should be overridable.
83      * @return true if the request requires approval, false otherwise
84      */

85     public static boolean requireApproval(ApprovalRequest req, ApprovalOveradableClassName[] overridableClassNames) {
86         if (req == null) return false;
87         if (log.isDebugEnabled()) {
88             log.debug(">requireApproval: "+req.getClass().getName());
89         }
90         boolean ret = true;
91         if (req.getNumOfRequiredApprovals() > 0) {
92             ret = !isCalledByOveridableClassnames(getGloballyAllowed());
93             // If we were not found in the globally allowed list, check the passed in list
94
if (ret && (overridableClassNames != null)) {
95                 ret = !isCalledByOveridableClassnames(overridableClassNames);
96             }
97             // If we were not found in any allowed list, check if it is an allowed transition
98
if (ret && req.isAllowedTransition()) {
99                 ret = false;
100             }
101         } else {
102             ret = false;
103         }
104         
105         if (log.isDebugEnabled()) {
106             log.debug("<requireApproval: "+ret);
107         }
108         return ret;
109     }
110     
111     private static ApprovalOveradableClassName[] getGloballyAllowed() {
112         if (globallyAllowed == null) {
113             ArrayList JavaDoc arr = new ArrayList JavaDoc();
114             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(globallyAllowedString, ",", false);
115             while (tokenizer.hasMoreTokens()) {
116                 String JavaDoc t = tokenizer.nextToken();
117                 ApprovalOveradableClassName o = new ApprovalOveradableClassName(t.trim(), null);
118                 arr.add(o);
119             }
120             globallyAllowed = (ApprovalOveradableClassName[])arr.toArray(new ApprovalOveradableClassName[0]);
121         }
122         return globallyAllowed;
123     }
124     
125     private static boolean isCalledByOveridableClassnames(ApprovalOveradableClassName[] overridableClassNames){
126         boolean retval = false;
127         try{
128             throw new Exception JavaDoc();
129         }catch(Exception JavaDoc e){
130             if(overridableClassNames != null){
131                 Throwable JavaDoc next = e;
132                 while(next != null){
133                   for(int j=0;j< overridableClassNames.length;j++){
134                     retval = overridableClassNames[j].isInStackTrace(e.getStackTrace());
135                     if(retval == true){
136                         break;
137                     }
138                   }
139                   if(retval == true){
140                         break;
141                   }
142                   next = e.getCause();
143                 }
144             }
145         }
146         
147         return retval;
148     }
149     
150     /**
151      * Help method that checks the CA data config if specified action
152      * requires approvals and how many
153      * @param action one of CAInfo.REQ_APPROVAL_ constants
154      * @param caid of the ca to check
155      * @return 0 of no approvals is required othervise the number of approvals
156      */

157     public static int getNumOfApprovalRequired(int action, CAInfo cainfo) {
158         int retval = 0;
159         if(cainfo.isApprovalRequired(action)){
160             retval = cainfo.getNumOfReqApprovals();
161         }
162         
163         return retval;
164     }
165 }
166
Popular Tags