001: /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.acegisecurity.vote;
017:
018: import org.acegisecurity.AccessDeniedException;
019: import org.acegisecurity.Authentication;
020: import org.acegisecurity.ConfigAttributeDefinition;
021:
022: import java.util.Iterator;
023:
024: /**
025: * Simple concrete implementation of {@link org.acegisecurity.AccessDecisionManager} that uses a consensus-based
026: * approach.
027: */
028: public class ConsensusBased extends AbstractAccessDecisionManager {
029: //~ Instance fields ================================================================================================
030:
031: private boolean allowIfEqualGrantedDeniedDecisions = true;
032:
033: //~ Methods ========================================================================================================
034:
035: /**
036: * This concrete implementation simply polls all configured {@link AccessDecisionVoter}s and upon
037: * completion determines the consensus of granted vs denied responses.<p>If there were an equal number of
038: * grant and deny votes, the decision will be based on the {@link #isAllowIfEqualGrantedDeniedDecisions()}
039: * property (defaults to true).</p>
040: * <p>If every <code>AccessDecisionVoter</code> abstained from voting, the decision will be based on the
041: * {@link #isAllowIfAllAbstainDecisions()} property (defaults to false).</p>
042: *
043: * @param authentication the caller invoking the method
044: * @param object the secured object
045: * @param config the configuration attributes associated with the method being invoked
046: *
047: * @throws AccessDeniedException if access is denied
048: */
049: public void decide(Authentication authentication, Object object,
050: ConfigAttributeDefinition config)
051: throws AccessDeniedException {
052: Iterator iter = this .getDecisionVoters().iterator();
053: int grant = 0;
054: int deny = 0;
055: int abstain = 0;
056:
057: while (iter.hasNext()) {
058: AccessDecisionVoter voter = (AccessDecisionVoter) iter
059: .next();
060: int result = voter.vote(authentication, object, config);
061:
062: switch (result) {
063: case AccessDecisionVoter.ACCESS_GRANTED:
064: grant++;
065:
066: break;
067:
068: case AccessDecisionVoter.ACCESS_DENIED:
069: deny++;
070:
071: break;
072:
073: default:
074: abstain++;
075:
076: break;
077: }
078: }
079:
080: if (grant > deny) {
081: return;
082: }
083:
084: if (deny > grant) {
085: throw new AccessDeniedException(messages.getMessage(
086: "AbstractAccessDecisionManager.accessDenied",
087: "Access is denied"));
088: }
089:
090: if ((grant == deny) && (grant != 0)) {
091: if (this .allowIfEqualGrantedDeniedDecisions) {
092: return;
093: } else {
094: throw new AccessDeniedException(messages.getMessage(
095: "AbstractAccessDecisionManager.accessDenied",
096: "Access is denied"));
097: }
098: }
099:
100: // To get this far, every AccessDecisionVoter abstained
101: checkAllowIfAllAbstainDecisions();
102: }
103:
104: public boolean isAllowIfEqualGrantedDeniedDecisions() {
105: return allowIfEqualGrantedDeniedDecisions;
106: }
107:
108: public void setAllowIfEqualGrantedDeniedDecisions(
109: boolean allowIfEqualGrantedDeniedDecisions) {
110: this.allowIfEqualGrantedDeniedDecisions = allowIfEqualGrantedDeniedDecisions;
111: }
112: }
|