1 /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 package org.acegisecurity.vote;
17
18 import org.acegisecurity.AccessDeniedException;
19 import org.acegisecurity.Authentication;
20 import org.acegisecurity.ConfigAttributeDefinition;
21
22 import java.util.Iterator;
23
24
25 /**
26 * Simple concrete implementation of {@link org.acegisecurity.AccessDecisionManager} that uses a consensus-based
27 * approach.
28 */
29 public class ConsensusBased extends AbstractAccessDecisionManager {
30 //~ Instance fields ================================================================================================
31
32 private boolean allowIfEqualGrantedDeniedDecisions = true;
33
34 //~ Methods ========================================================================================================
35
36 /**
37 * This concrete implementation simply polls all configured {@link AccessDecisionVoter}s and upon
38 * completion determines the consensus of granted vs denied responses.<p>If there were an equal number of
39 * grant and deny votes, the decision will be based on the {@link #isAllowIfEqualGrantedDeniedDecisions()}
40 * property (defaults to true).</p>
41 * <p>If every <code>AccessDecisionVoter</code> abstained from voting, the decision will be based on the
42 * {@link #isAllowIfAllAbstainDecisions()} property (defaults to false).</p>
43 *
44 * @param authentication the caller invoking the method
45 * @param object the secured object
46 * @param config the configuration attributes associated with the method being invoked
47 *
48 * @throws AccessDeniedException if access is denied
49 */
50 public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
51 throws AccessDeniedException {
52 Iterator iter = this.getDecisionVoters().iterator();
53 int grant = 0;
54 int deny = 0;
55 int abstain = 0;
56
57 while (iter.hasNext()) {
58 AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
59 int result = voter.vote(authentication, object, config);
60
61 switch (result) {
62 case AccessDecisionVoter.ACCESS_GRANTED:
63 grant++;
64
65 break;
66
67 case AccessDecisionVoter.ACCESS_DENIED:
68 deny++;
69
70 break;
71
72 default:
73 abstain++;
74
75 break;
76 }
77 }
78
79 if (grant > deny) {
80 return;
81 }
82
83 if (deny > grant) {
84 throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
85 "Access is denied"));
86 }
87
88 if ((grant == deny) && (grant != 0)) {
89 if (this.allowIfEqualGrantedDeniedDecisions) {
90 return;
91 } else {
92 throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
93 "Access is denied"));
94 }
95 }
96
97 // To get this far, every AccessDecisionVoter abstained
98 checkAllowIfAllAbstainDecisions();
99 }
100
101 public boolean isAllowIfEqualGrantedDeniedDecisions() {
102 return allowIfEqualGrantedDeniedDecisions;
103 }
104
105 public void setAllowIfEqualGrantedDeniedDecisions(boolean allowIfEqualGrantedDeniedDecisions) {
106 this.allowIfEqualGrantedDeniedDecisions = allowIfEqualGrantedDeniedDecisions;
107 }
108 }