001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package javax.security.jacc;
023:
024: import java.util.HashSet;
025: import java.util.StringTokenizer;
026: import java.util.Iterator;
027:
028: /** Encapsulation of the URLPatternSpec defined in the WebResourcePermission
029: * and WebUserDataPermission.
030: *
031: * @link WebResourcePermission(String, String)
032: * @link WebUserDataPermission(String, String)
033: *
034: * @author Scott.Stark@jboss.org
035: * @version $Revison:$
036: */
037: class URLPatternSpec {
038: /** The first or only URLPattern in the spec */
039: URLPattern urlPattern;
040: /** */
041: HashSet urlPatternList;
042:
043: /** The spec contains a URLPatternSpec that identifies the web resources to
044: which the permissions applies. The syntax of a URLPatternSpec is as follows:
045:
046: URLPatternList ::= URLPattern | URLPatternList colon URLPattern
047: URLPatternSpec ::= null | URLPattern | URLPattern colon URLPatternList
048:
049: A null URLPatternSpec is translated to the default URLPattern, "/", by the
050: permission constructor. The empty string is an exact URLPattern, and may
051: occur anywhere in a URLPatternSpec that an exact URLPattern may occur. The
052: first URLPattern in a URLPatternSpec may be any of the pattern types, exact,
053: path-prefix, extension, or default as defined in the Java Servlet
054: Specification). When a URLPatternSpec includes a URLPatternList, the
055: patterns of the URLPatternList identify the resources to which the
056: permission does NOT apply and depend on the pattern type and value of the
057: first pattern as follows:
058:
059: - No pattern may exist in the URLPatternList that matches the first pattern.
060: - If the first pattern is a path-prefix pattern, only exact patterns matched
061: by the first pattern and path-prefix patterns matched by, but different
062: from, the first pattern may occur in the URLPatternList.
063: - If the first pattern is an extension pattern, only exact patterns that are
064: matched by the first pattern and path-prefix patterns may occur in the
065: URLPatternList.
066: - If the first pattern is the default pattern, "/", any pattern except the
067: default pattern may occur in the URLPatternList.
068: - If the first pattern is an exact pattern a URLPatternList must not be
069: present in the URLPatternSpec.
070:
071: @param spec
072: */
073: URLPatternSpec(String spec) {
074: if (spec == null)
075: urlPattern = new URLPattern("/");
076: else if (spec.indexOf(':') > 0) {
077: StringTokenizer tokenizer = new StringTokenizer(spec, ":");
078: urlPatternList = new HashSet();
079: while (tokenizer.hasMoreTokens()) {
080: String pattern = tokenizer.nextToken();
081: URLPattern p = new URLPattern(pattern);
082: if (urlPattern == null)
083: urlPattern = p;
084: else {
085: // Enforce the constraints
086: if (p.matches(urlPattern)) {
087: /* No pattern may exist in the URLPatternList that matches
088: the first pattern.
089: */
090: String msg = "1: URLPatternList item: "
091: + pattern + " matches: "
092: + urlPattern.getPattern();
093: throw new IllegalArgumentException(msg);
094: } else if (urlPattern.isPrefix()) {
095: /* If the first pattern is a path-prefix pattern, only exact
096: patterns matched by the first pattern and path-prefix patterns
097: matched by, but different from, the first pattern may occur
098: in the URLPatternList.
099: */
100: if (p.isPrefix() == false
101: && p.isExact() == false) {
102: String msg = "2: URLPatternList item: "
103: + pattern
104: + " is not an exact or prefix pattern";
105: throw new IllegalArgumentException(msg);
106: }
107: } else if (urlPattern.isExtension()) {
108: /* If the first pattern is an extension pattern, only exact
109: patterns that are matched by the first pattern and path-prefix
110: patterns may occur in the URLPatternList.
111: */
112: if (p.isPrefix() == false
113: && p.isExact() == false) {
114: String msg = "3: URLPatternList item: "
115: + pattern
116: + " is not an exact or prefix pattern";
117: throw new IllegalArgumentException(msg);
118: }
119: } else if (urlPattern.isDefault()) {
120: /* If the first pattern is the default pattern, "/", any
121: pattern except the default pattern may occur in the
122: URLPatternList.
123: */
124: if (p.isDefault()) {
125: String msg = "4: URLPatternList item: "
126: + pattern
127: + " cannot be the default pattern";
128: throw new IllegalArgumentException(msg);
129: }
130: } else if (urlPattern.isExact()) {
131: /* If the first pattern is an exact pattern a URLPatternList
132: must not be present in the URLPatternSpec.
133: */
134: String msg = "5: URLPatternList item: "
135: + pattern
136: + " is not allowed in an exact pattern";
137: throw new IllegalArgumentException(msg);
138: }
139: urlPatternList.add(p);
140: }
141: }
142: } else {
143: urlPattern = new URLPattern(spec);
144: }
145: }
146:
147: /** Perform the permission URLPattern matching
148: - The first URLPattern in the name of the argument permission is matched
149: by the first URLPattern in the name of this permission.
150: - The first URLPattern in the name of the argument permission is NOT
151: matched by any URLPattern in the URLPatternList of the URLPatternSpec
152: of this permission.
153: - If the first URLPattern in the name of the argument permission matches
154: the first URLPattern in the URLPatternSpec of this permission, then every
155: URLPattern in the URLPatternList of the URLPatternSpec of this permission
156: is matched by a URLPattern in the URLPatternList of the argument permission.
157:
158: URLPattern matching is performed using the Servlet matching rules where
159: two URL patterns match if they are related as follows:
160: - their pattern values are String equivalent, or
161: - this pattern is the path-prefix pattern "/*", or
162: - this pattern is a path-prefix pattern (that is, it starts with "/" and
163: ends with "/*") and the argument pattern starts with the substring of this
164: pattern, minus its last 2 characters, and the next character of the argument
165: pattern, if there is one, is "/", or
166: - this pattern is an extension pattern (that is, it starts with "*.") and
167: the argument pattern ends with this pattern, or
168: - the reference pattern is the special default pattern, "/", which matches
169: all argument patterns.
170:
171: All of the comparisons described above are case sensitive.
172: @param spec
173: @return true if this implies spec, false otherwise
174: */
175: boolean implies(URLPatternSpec spec) {
176: /* The first URLPattern in the name of the argument permission is matched
177: by the first URLPattern in the name of this permission.
178: */
179: boolean implies = urlPattern.matches(spec.urlPattern);
180: if (implies) {
181: /* The first URLPattern in the name of the argument permission is NOT
182: matched by any URLPattern in the URLPatternList of the URLPatternSpec
183: of this permission.
184: */
185: if (urlPatternList != null) {
186: Iterator iter = urlPatternList.iterator();
187: while (iter.hasNext()) {
188: URLPattern p = (URLPattern) iter.next();
189: if (p.matches(spec.urlPattern))
190: return false;
191: }
192: }
193:
194: /* If the first URLPattern in the name of the argument permission
195: matches the first URLPattern in the URLPatternSpec of this permission,
196: then every URLPattern in the URLPatternList of the URLPatternSpec of
197: this permission is matched by a URLPattern in the URLPatternList of the
198: argument permission.
199: */
200: if (urlPatternList != null && spec.urlPatternList != null) {
201: Iterator iter = urlPatternList.iterator();
202: while (iter.hasNext()) {
203: URLPattern p = (URLPattern) iter.next();
204: boolean hasMatch = false;
205: Iterator iter2 = spec.urlPatternList.iterator();
206: while (iter2.hasNext()) {
207: URLPattern p2 = (URLPattern) iter2.next();
208: if (p.matches(p2)) {
209: hasMatch = true;
210: break;
211: }
212: }
213: if (hasMatch == false)
214: return false;
215: }
216: }
217: }
218: return implies;
219: }
220:
221: int hash() {
222: int hashCode = urlPattern.hashCode();
223: if (urlPatternList != null)
224: hashCode += urlPatternList.hashCode();
225: return hashCode;
226: }
227:
228: boolean equals(URLPatternSpec spec) {
229: if (urlPattern.equals(spec.urlPattern) == true) {
230: if (urlPatternList == null
231: || urlPatternList.equals(spec.urlPatternList)) {
232: return true;
233: }
234: }
235:
236: return false;
237: }
238: }
|