001: /*______________________________________________________________________________
002: *
003: * Macker http://innig.net/macker/
004: *
005: * Copyright 2002-2003 Paul Cantrell
006: *
007: * This program is free software; you can redistribute it and/or modify it under
008: * the terms of the GNU General Public License version 2, as published by the
009: * Free Software Foundation. See the file LICENSE.html for more information.
010: *
011: * This program is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
013: * FOR A PARTICULAR PURPOSE. See the license for more details.
014: *
015: * You should have received a copy of the GNU General Public License along with
016: * this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
017: * Place, Suite 330 / Boston, MA 02111-1307 / USA.
018: *______________________________________________________________________________
019: */
020:
021: package net.innig.macker.rule;
022:
023: import net.innig.macker.structure.ClassManager;
024: import net.innig.macker.structure.ClassInfo;
025: import net.innig.macker.util.IncludeExcludeLogic;
026: import net.innig.macker.util.IncludeExcludeNode;
027: import net.innig.macker.event.AccessRuleViolation;
028: import net.innig.macker.event.MackerIsMadException;
029: import net.innig.macker.event.ListenerException;
030:
031: import java.util.*;
032: import net.innig.collect.MultiMap;
033:
034: public class AccessRule extends Rule {
035: //--------------------------------------------------------------------------
036: // Constructors
037: //--------------------------------------------------------------------------
038:
039: public AccessRule(RuleSet parent) {
040: super (parent);
041: type = AccessRuleType.DENY;
042: from = to = Pattern.ALL;
043: }
044:
045: //--------------------------------------------------------------------------
046: // Properties
047: //--------------------------------------------------------------------------
048:
049: public AccessRuleType getType() {
050: return type;
051: }
052:
053: public void setType(AccessRuleType type) {
054: if (type == null)
055: throw new NullPointerException(
056: "type parameter cannot be null");
057: this .type = type;
058: }
059:
060: public Pattern getFrom() {
061: return from;
062: }
063:
064: public void setFrom(Pattern from) {
065: this .from = from;
066: }
067:
068: public String getMessage() {
069: return message;
070: }
071:
072: public void setMessage(String message) {
073: this .message = message;
074: }
075:
076: public Pattern getTo() {
077: return to;
078: }
079:
080: public void setTo(Pattern to) {
081: this .to = to;
082: }
083:
084: public AccessRule getChild() {
085: return child;
086: }
087:
088: public void setChild(AccessRule child) {
089: this .child = child;
090: }
091:
092: public AccessRule getNext() {
093: return next;
094: }
095:
096: public void setNext(AccessRule next) {
097: this .next = next;
098: }
099:
100: private AccessRuleType type;
101: private Pattern from, to;
102: private String message;
103: private boolean bound;
104: private AccessRule child, next;
105:
106: //--------------------------------------------------------------------------
107: // Evaluation
108: //--------------------------------------------------------------------------
109:
110: public void check(EvaluationContext context, ClassManager classes)
111: throws RulesException, MackerIsMadException,
112: ListenerException {
113: EvaluationContext localContext = new EvaluationContext(context);
114: for (Iterator refIter = classes.getReferences().entrySet()
115: .iterator(); refIter.hasNext();) {
116: MultiMap.Entry entry = (MultiMap.Entry) refIter.next();
117: ClassInfo from = (ClassInfo) entry.getKey();
118: ClassInfo to = (ClassInfo) entry.getValue();
119: if (from.equals(to))
120: continue;
121: if (!localContext.getRuleSet().isInSubset(localContext,
122: from))
123: continue;
124:
125: localContext.setVariableValue("from", from.getClassName());
126: localContext.setVariableValue("to", to.getClassName());
127: localContext.setVariableValue("from-package", from
128: .getPackageName());
129: localContext.setVariableValue("to-package", to
130: .getPackageName());
131: localContext.setVariableValue("from-full", from
132: .getFullName());
133: localContext.setVariableValue("to-full", to.getFullName());
134:
135: if (!checkAccess(localContext, from, to)) {
136: List messages;
137: if (getMessage() == null)
138: messages = Collections.EMPTY_LIST;
139: else
140: messages = Collections.singletonList(VariableParser
141: .parse(localContext, getMessage()));
142:
143: context.broadcastEvent(new AccessRuleViolation(this ,
144: from, to, messages));
145: }
146: }
147: }
148:
149: public boolean checkAccess(EvaluationContext context,
150: ClassInfo fromClass, ClassInfo toClass)
151: throws RulesException {
152: return IncludeExcludeLogic.apply(makeIncludeExcludeNode(this ,
153: context, fromClass, toClass));
154: }
155:
156: private static IncludeExcludeNode makeIncludeExcludeNode(
157: final AccessRule rule, final EvaluationContext context,
158: final ClassInfo fromClass, final ClassInfo toClass) {
159: return (rule == null) ? null : new IncludeExcludeNode() {
160: public boolean isInclude() {
161: return rule.getType() == AccessRuleType.ALLOW;
162: }
163:
164: public boolean matches() throws RulesException {
165: return rule.getFrom().matches(context, fromClass)
166: && rule.getTo().matches(context, toClass);
167: }
168:
169: public IncludeExcludeNode getChild() {
170: return makeIncludeExcludeNode(rule.getChild(), context,
171: fromClass, toClass);
172: }
173:
174: public IncludeExcludeNode getNext() {
175: return makeIncludeExcludeNode(rule.getNext(), context,
176: fromClass, toClass);
177: }
178: };
179: }
180: }
|