Home » geronimo-2.2-source-release » org.apache.geronimo.security.util » [javadoc | source]

    1   /**
    2    *
    3    * Copyright 2003-2004 The Apache Software Foundation
    4    *
    5    *  Licensed under the Apache License, Version 2.0 (the "License");
    6    *  you may not use this file except in compliance with the License.
    7    *  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package org.apache.geronimo.security.util;
   19   
   20   import java.util.Collection;
   21   import java.util.HashSet;
   22   import java.util.Iterator;
   23   import java.util.Set;
   24   
   25   
   26   /**
   27    * Utility class for <code>ModuleConfiguration</code>.  This class is used to generate qualified patterns, HTTP
   28    * method sets, complements of HTTP method sets, and HTTP method sets w/ transport restrictions for URL patterns that
   29    * are found in the web deployment descriptor.
   30    * @version $Rev: 111239 $ $Date: 2004-12-08 01:29:11 -0800 (Wed, 08 Dec 2004) $
   31    */
   32   public class URLPattern {
   33       private final static String[] HTTP_METHODS = {"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "TRACE"};
   34       private final static int[] HTTP_MASKS = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40};
   35       private final static int NA = 0x00;
   36       private final static int INTEGRAL = 0x01;
   37       private final static int CONFIDENTIAL = 0x02;
   38   
   39       private final URLPatternCheck type;
   40       private final String pattern;
   41       private int httpMethodsMask;
   42       private int transport;
   43       private final HashSet roles = new HashSet();
   44   
   45       /**
   46        * Construct an instance of the utility class for <code>WebModuleConfiguration</code>.
   47        * @param pat the URL pattern that this instance is to collect information on
   48        * @see "JSR 115, section 3.1.3" Translating Servlet Deployment Descriptors
   49        */
   50       public URLPattern(String pat) {
   51           if (pat == null) throw new java.lang.IllegalArgumentException("URL pattern cannot be null");
   52           if (pat.length() == 0) throw new java.lang.IllegalArgumentException("URL pattern cannot be empty");
   53   
   54           if (pat.equals("/") || pat.equals("/*")) {
   55               type = DEFAULT;
   56           } else if (pat.charAt(0) == '/' && pat.endsWith("/*")) {
   57               type = PATH_PREFIX;
   58           } else if (pat.charAt(0) == '*') {
   59               type = EXTENSION;
   60           } else {
   61               type = EXACT;
   62           }
   63           pattern = pat;
   64       }
   65   
   66       /**
   67        * Get a qualifed URL pattern relative to a particular set of URL patterns.  This algorithm is described in
   68        * JSR 115, section 3.1.3.1 "Qualified URL Pattern Names".
   69        * @param patterns the set of possible URL patterns that could be used to qualify this pattern
   70        * @return a qualifed URL pattern
   71        */
   72       public String getQualifiedPattern(Set patterns) {
   73           if (type == EXACT) {
   74               return pattern;
   75           } else {
   76               HashSet bucket = new HashSet();
   77               StringBuffer result = new StringBuffer(pattern);
   78               Iterator iter = patterns.iterator();
   79   
   80               // Collect a set of qualifying patterns, depending on the type of this pattern.
   81               while (iter.hasNext()) {
   82                   URLPattern p = (URLPattern) iter.next();
   83                   if (type.check(this, p)) {
   84                       bucket.add(p.pattern);
   85                   }
   86               }
   87   
   88               // append the set of qualifying patterns
   89               iter = bucket.iterator();
   90               while (iter.hasNext()) {
   91                   result.append(':');
   92                   result.append((String) iter.next());
   93               }
   94               return result.toString();
   95           }
   96       }
   97   
   98       /**
   99        * Add a method to the union of HTTP methods associated with this URL pattern.  An empty string is short hand for
  100        * the set of all HTTP methods.
  101        * @param method the HTTP method to be added to the set.
  102        */
  103       public void addMethod(String method) {
  104           if (method.length() == 0) {
  105               httpMethodsMask = 0xFF;
  106               return;
  107           }
  108   
  109           boolean found = false;
  110           for (int j = 0; j < HTTP_METHODS.length; j++) {
  111               if (method.equals(HTTP_METHODS[j])) {
  112                   httpMethodsMask |= HTTP_MASKS[j];
  113                   found = true;
  114   
  115                   break;
  116               }
  117           }
  118           if (!found) throw new IllegalArgumentException("Invalid HTTP method");
  119       }
  120   
  121       /**
  122        * Return the set of HTTP methods that have been associated with this URL pattern.
  123        * @return a set of HTTP methods
  124        */
  125       public String getMethods() {
  126           StringBuffer buffer = null;
  127   
  128           for (int i = 0; i < HTTP_MASKS.length; i++) {
  129               if ((httpMethodsMask & HTTP_MASKS[i]) > 0) {
  130                   if (buffer == null) {
  131                       buffer = new StringBuffer();
  132                   } else {
  133                       buffer.append(",");
  134                   }
  135                   buffer.append(HTTP_METHODS[i]);
  136               }
  137           }
  138   
  139           return (buffer == null ? "" : buffer.toString());
  140       }
  141   
  142       public String getComplementedMethods() {
  143           StringBuffer buffer = null;
  144   
  145           for (int i = 0; i < HTTP_MASKS.length; i++) {
  146               if ((httpMethodsMask & HTTP_MASKS[i]) == 0) {
  147                   if (buffer == null) {
  148                       buffer = new StringBuffer();
  149                   } else {
  150                       buffer.append(",");
  151                   }
  152                   buffer.append(HTTP_METHODS[i]);
  153               }
  154           }
  155   
  156           return (buffer == null ? "" : buffer.toString());
  157       }
  158   
  159       public String getMethodsWithTransport() {
  160           StringBuffer buffer = new StringBuffer(getMethods());
  161   
  162   
  163           if (transport != NA) {
  164               buffer.append(":");
  165   
  166               if (transport != 0x03) {
  167                   if (transport == INTEGRAL) {
  168                       buffer.append("INTEGRAL");
  169                   } else {
  170                       buffer.append("CONFIDENTIAL");
  171                   }
  172               }
  173           }
  174   
  175           return buffer.toString();
  176       }
  177   
  178       public void setTransport(String trans) {
  179           switch (transport) {
  180               case NA:
  181                   {
  182                       if ("INTEGRAL".equals(trans)) {
  183                           transport = INTEGRAL;
  184                       } else if ("CONFIDENTIAL".equals(trans)) {
  185                           transport = CONFIDENTIAL;
  186                       }
  187                       break;
  188                   }
  189   
  190               case INTEGRAL:
  191                   {
  192                       if ("CONFIDENTIAL".equals(trans)) {
  193                           transport = CONFIDENTIAL;
  194                       }
  195                       break;
  196                   }
  197           }
  198       }
  199   
  200       public void addRole(String role) {
  201           roles.add(role);
  202       }
  203   
  204       public void addAllRoles(Collection collection) {
  205           roles.addAll(collection);
  206       }
  207   
  208       public HashSet getRoles() {
  209           return roles;
  210       }
  211   
  212       public boolean equals(Object obj) {
  213           if (!(obj instanceof URLPattern)) return false;
  214   
  215           URLPattern test = (URLPattern) obj;
  216   
  217           return pattern.equals(test.pattern);
  218       }
  219   
  220       public int hashCode() {
  221           return pattern.hashCode();
  222       }
  223   
  224       boolean matches(URLPattern p) {
  225           String test = p.pattern;
  226   
  227           // their pattern values are String equivalent
  228           if (pattern.equals(test)) return true;
  229   
  230           return type.matches(pattern, test);
  231       }
  232   
  233       private final static URLPatternCheck EXACT = new URLPatternCheck() {
  234           public boolean check(URLPattern base, URLPattern test) {
  235               return matches(base.pattern, test.pattern);
  236           }
  237   
  238           public boolean matches(String base, String test) {
  239               return base.equals(test);
  240           }
  241       };
  242   
  243       private final static URLPatternCheck PATH_PREFIX = new URLPatternCheck() {
  244           public boolean check(URLPattern base, URLPattern test) {
  245               return ((test.type == PATH_PREFIX || test.type == EXACT)
  246                       && base.matches(test)
  247                       && !base.equals(test));
  248           }
  249   
  250           /**
  251            * This pattern is a path-prefix pattern (that is, it starts with "/" and ends with "/*") and the argument
  252            * pattern starts with the substring of this pattern, minus its last 2 characters, and the next character of
  253            * the argument pattern, if there is one, is "/"
  254            * @param base the base pattern
  255            * @param test the pattern to be tested
  256            * @return <code>true</code> if <code>test</code> is matched by <code>base</code>
  257            */
  258           public boolean matches(String base, String test) {
  259               int length = base.length() - 2;
  260               if (length > test.length()) return false;
  261   
  262               for (int i = 0; i < length; i++) {
  263                   if (base.charAt(i) != test.charAt(i)) return false;
  264               }
  265   
  266               if (test.length() == length)
  267                   return true;
  268               else if (test.charAt(length) != '/') return false;
  269   
  270               return true;
  271           }
  272       };
  273   
  274       private final static URLPatternCheck EXTENSION = new URLPatternCheck() {
  275           public boolean check(URLPattern base, URLPattern test) {
  276               if (test.type == PATH_PREFIX) return true;
  277   
  278               if (test.type == EXACT) return matches(base.pattern, test.pattern);
  279   
  280               return false;
  281           }
  282   
  283           /**
  284            * This pattern is an extension pattern (that is, it startswith "*.") and the argument pattern ends with
  285            * this pattern.
  286            * @param base the base pattern
  287            * @param test the pattern to be tested
  288            * @return <code>true</code> if <code>test</code> is matched by <code>base</code>
  289            */
  290           public boolean matches(String base, String test) {
  291               return test.endsWith(base.substring(1));
  292           }
  293       };
  294   
  295       private final static URLPatternCheck DEFAULT = new URLPatternCheck() {
  296           public boolean check(URLPattern base, URLPattern test) {
  297               return base.matches(test) && !base.equals(test);
  298           }
  299   
  300           /**
  301            * This pattern is the path-prefix pattern "/*" or the reference pattern is the special default pattern,
  302            * "/", which matches all argument patterns.
  303            * @param base the base pattern
  304            * @param test the pattern to be tested
  305            * @return <code>true</code> if <code>test</code> is matched by <code>base</code>
  306            * @see "JSR 115"
  307            */
  308           public boolean matches(String base, String test) {
  309               return true;
  310           }
  311       };
  312   }

Home » geronimo-2.2-source-release » org.apache.geronimo.security.util » [javadoc | source]