001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.security.util;
017:
018: import java.util.Collection;
019: import java.util.HashSet;
020: import java.util.Set;
021:
022: /**
023: * Utility class for <code>ModuleConfiguration</code>. This class is used to generate qualified patterns, HTTP
024: * method sets, complements of HTTP method sets, and HTTP method sets w/ transport restrictions for URL patterns that
025: * are found in the web deployment descriptor.
026: *
027: * @version $Rev: 497904 $ $Date: 2007-01-19 10:49:13 -0800 (Fri, 19 Jan 2007) $
028: */
029: public class URLPattern {
030: public final static int NA = 0x00;
031: public final static int INTEGRAL = 0x01;
032: public final static int CONFIDENTIAL = 0x02;
033:
034: private final URLPatternCheck type;
035: private final String pattern;
036: private final HTTPMethods httpMethods = new HTTPMethods();
037: private int transport;
038: private final HashSet<String> roles = new HashSet<String>();
039:
040: /**
041: * Construct an instance of the utility class for <code>WebModuleConfiguration</code>.
042: *
043: * @param pat the URL pattern that this instance is to collect information on
044: * @see "JSR 115, section 3.1.3" Translating Servlet Deployment Descriptors
045: */
046: public URLPattern(String pat) {
047: if (pat == null)
048: throw new java.lang.IllegalArgumentException(
049: "URL pattern cannot be null");
050: if (pat.length() == 0)
051: throw new java.lang.IllegalArgumentException(
052: "URL pattern cannot be empty");
053:
054: if (pat.equals("/") || pat.equals("/*")) {
055: type = DEFAULT;
056: pat = "/";
057: } else if (pat.charAt(0) == '/' && pat.endsWith("/*")) {
058: type = PATH_PREFIX;
059: } else if (pat.charAt(0) == '*') {
060: type = EXTENSION;
061: } else {
062: type = EXACT;
063: }
064: pattern = pat;
065: }
066:
067: /**
068: * Get a qualifed URL pattern relative to a particular set of URL patterns. This algorithm is described in
069: * JSR 115, section 3.1.3.1 "Qualified URL Pattern Names".
070: *
071: * @param patterns the set of possible URL patterns that could be used to qualify this pattern
072: * @return a qualifed URL pattern
073: */
074: public String getQualifiedPattern(Set<URLPattern> patterns) {
075: if (type == EXACT) {
076: return pattern;
077: } else {
078: HashSet<String> bucket = new HashSet<String>();
079: StringBuffer result = new StringBuffer(pattern);
080:
081: // Collect a set of qualifying patterns, depending on the type of this pattern.
082: for (URLPattern p : patterns) {
083: if (type.check(this , p)) {
084: bucket.add(p.pattern);
085: }
086: }
087:
088: // append the set of qualifying patterns
089: for (String aBucket : bucket) {
090: result.append(':');
091: result.append(aBucket);
092: }
093: return result.toString();
094: }
095: }
096:
097: /**
098: * Add a method to the union of HTTP methods associated with this URL pattern. An empty string is short hand for
099: * the set of all HTTP methods.
100: *
101: * @param method the HTTP method to be added to the set.
102: */
103: public void addMethod(String method) {
104: httpMethods.add(method);
105: }
106:
107: /**
108: * Return the set of HTTP methods that have been associated with this URL pattern.
109: *
110: * @return a set of HTTP methods
111: */
112: public String getMethods() {
113: return httpMethods.getHttpMethods();
114: }
115:
116: public String getComplementedMethods() {
117: return httpMethods.getComplementedHttpMethods();
118: }
119:
120: public HTTPMethods getHTTPMethods() {
121: return httpMethods;
122: }
123:
124: public HTTPMethods getComplementedHTTPMethods() {
125: return new HTTPMethods(httpMethods, true);
126: }
127:
128: public String getMethodsWithTransport() {
129: return getMethodsWithTransport(httpMethods, transport);
130: }
131:
132: public static String getMethodsWithTransport(HTTPMethods methods,
133: int transport) {
134: StringBuffer buffer = methods.getHttpMethodsBuffer();
135:
136: if (transport != NA) {
137: buffer.append(":");
138:
139: if (transport != 0x03) {
140: if (transport == INTEGRAL) {
141: buffer.append("INTEGRAL");
142: } else {
143: buffer.append("CONFIDENTIAL");
144: }
145: }
146: }
147:
148: return buffer.toString();
149: }
150:
151: public void setTransport(String trans) {
152: switch (transport) {
153: case NA: {
154: if ("INTEGRAL".equals(trans)) {
155: transport = INTEGRAL;
156: } else if ("CONFIDENTIAL".equals(trans)) {
157: transport = CONFIDENTIAL;
158: }
159: break;
160: }
161:
162: case INTEGRAL: {
163: if ("CONFIDENTIAL".equals(trans)) {
164: transport = CONFIDENTIAL;
165: }
166: break;
167: }
168: }
169: }
170:
171: public int getTransport() {
172: return transport;
173: }
174:
175: public void addRole(String role) {
176: roles.add(role);
177: }
178:
179: public void addAllRoles(Collection<String> collection) {
180: roles.addAll(collection);
181: }
182:
183: public HashSet<String> getRoles() {
184: return roles;
185: }
186:
187: /**
188: * TODO this is kinda weird without an explanation
189: * @param obj object to compare with
190: * @return if this equals obj
191: */
192: public boolean equals(Object obj) {
193: if (!(obj instanceof URLPattern))
194: return false;
195:
196: URLPattern test = (URLPattern) obj;
197:
198: return pattern.equals(test.pattern);
199: }
200:
201: public int hashCode() {
202: return pattern.hashCode();
203: }
204:
205: boolean matches(URLPattern p) {
206: String test = p.pattern;
207:
208: // their pattern values are String equivalent
209: if (pattern.equals(test))
210: return true;
211:
212: return type.matches(pattern, test);
213: }
214:
215: private final static URLPatternCheck EXACT = new URLPatternCheck() {
216: public boolean check(URLPattern base, URLPattern test) {
217: return matches(base.pattern, test.pattern);
218: }
219:
220: public boolean matches(String base, String test) {
221: return base.equals(test);
222: }
223: };
224:
225: private final static URLPatternCheck PATH_PREFIX = new URLPatternCheck() {
226: public boolean check(URLPattern base, URLPattern test) {
227: return ((test.type == PATH_PREFIX || test.type == EXACT)
228: && base.matches(test) && !base.equals(test));
229: }
230:
231: /**
232: * This pattern is a path-prefix pattern (that is, it starts with "/" and ends with "/*") and the argument
233: * pattern starts with the substring of this pattern, minus its last 2 characters, and the next character of
234: * the argument pattern, if there is one, is "/"
235: *
236: * @param base the base pattern
237: * @param test the pattern to be tested
238: * @return <code>true</code> if <code>test</code> is matched by <code>base</code>
239: */
240: public boolean matches(String base, String test) {
241: int length = base.length() - 2;
242: if (length > test.length())
243: return false;
244:
245: for (int i = 0; i < length; i++) {
246: if (base.charAt(i) != test.charAt(i))
247: return false;
248: }
249:
250: if (test.length() == length)
251: return true;
252: else if (test.charAt(length) != '/')
253: return false;
254:
255: return true;
256: }
257: };
258:
259: private final static URLPatternCheck EXTENSION = new URLPatternCheck() {
260: public boolean check(URLPattern base, URLPattern test) {
261: if (test.type == PATH_PREFIX)
262: return true;
263:
264: if (test.type == EXACT)
265: return matches(base.pattern, test.pattern);
266:
267: return false;
268: }
269:
270: /**
271: * This pattern is an extension pattern (that is, it startswith "*.") and the argument pattern ends with
272: * this pattern.
273: *
274: * @param base the base pattern
275: * @param test the pattern to be tested
276: * @return <code>true</code> if <code>test</code> is matched by <code>base</code>
277: */
278: public boolean matches(String base, String test) {
279: return test.endsWith(base.substring(1));
280: }
281: };
282:
283: private final static URLPatternCheck DEFAULT = new URLPatternCheck() {
284: public boolean check(URLPattern base, URLPattern test) {
285: return base.matches(test) && !base.equals(test);
286: }
287:
288: /**
289: * This pattern is the path-prefix pattern "/*" or the reference pattern is the special default pattern,
290: * "/", which matches all argument patterns.
291: *
292: * @param base the base pattern
293: * @param test the pattern to be tested
294: * @return <code>true</code> if <code>test</code> is matched by <code>base</code>
295: * @see "JSR 115"
296: */
297: public boolean matches(String base, String test) {
298: return true;
299: }
300: };
301: }
|