2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

Coverage Report - org.apache.shale.remoting.impl.FilteringProcessor
 
Classes in this File Line Coverage Branch Coverage Complexity
FilteringProcessor
100%
59/59
N/A
5.857
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to you under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  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.shale.remoting.impl;
 19  
 
 20  
 import java.io.IOException;
 21  
 import java.io.StreamTokenizer;
 22  
 import java.io.StringReader;
 23  
 import java.util.ArrayList;
 24  
 import java.util.List;
 25  
 import org.apache.shale.remoting.Processor;
 26  
 
 27  
 /**
 28  
  * <p>Abstract base class for {@link Processor} implementations that filter
 29  
  * requests based on matching the resource identifier against a set of
 30  
  * <code>includes</code> and <code>excludes</code> regular expressions.</p>
 31  
  *
 32  
  * @since 1.0.4
 33  
  */
 34  30
 public abstract class FilteringProcessor implements Processor {
 35  
     
 36  
 
 37  
     // ------------------------------------------------------ Instance Variables
 38  
 
 39  
 
 40  
     /**
 41  
      * <p>Comma-delimited regular expression patterns to exclude remote host
 42  
      * names that match.</p>
 43  
      */
 44  30
     private String excludes = null;
 45  
 
 46  
 
 47  
     /**
 48  
      * <p>Array of regular expression patterns for the excludes list.</p>
 49  
      */
 50  30
     private String excludesPatterns[] = new String[0];
 51  
 
 52  
 
 53  
     /**
 54  
      * <p>Comma-delimited regular expression patterns to include remote host
 55  
      * names that match.</p>
 56  
      */
 57  30
     private String includes = null;
 58  
 
 59  
 
 60  
     /**
 61  
      * <p>Array of regular expression patterns for the includes list.</p>
 62  
      */
 63  30
     private String includesPatterns[] = new String[0];
 64  
 
 65  
 
 66  
     // -------------------------------------------------------------- Properties
 67  
 
 68  
 
 69  
     /**
 70  
      * <p>Return the comma-delimited regular expresson patterns to exclude
 71  
      * remote host names that match, if any; otherwise, return
 72  
      * <code>null</code>.</p>
 73  
      */
 74  4
     public String getExcludes() { return this.excludes; }
 75  
 
 76  
 
 77  
     /**
 78  
      * <p>Set the comma-delimited regular expression patterns to exclude
 79  
      * remote host names that match, if any; or <code>null</code> for no
 80  
      * restrictions.</p>
 81  
      *
 82  
      * @param excludes New exclude pattern(s)
 83  
      */
 84  
     public void setExcludes(String excludes) {
 85  36
         this.excludes = excludes;
 86  36
         this.excludesPatterns = precompile(excludes);
 87  35
     }
 88  
 
 89  
 
 90  
     /**
 91  
      * <p>Return the comma-delimited regular expresson patterns to include
 92  
      * remote host names that match, if any; otherwise, return
 93  
      * <code>null</code>.</p>
 94  
      */
 95  4
     public String getIncludes() { return this.includes; }
 96  
 
 97  
 
 98  
     /**
 99  
      * <p>Set the comma-delimited regular expression patterns to include
 100  
      * remote host names that match, if any; or <code>null</code> for no
 101  
      * restrictions.</p>
 102  
      *
 103  
      * @param includes New include pattern(s)
 104  
      */
 105  
     public void setIncludes(String includes) {
 106  34
         this.includes = includes;
 107  34
         this.includesPatterns = precompile(includes);
 108  33
     }
 109  
 
 110  
 
 111  
     // ------------------------------------------------------- Protected Methods
 112  
 
 113  
 
 114  
     /**
 115  
      * <p>Return <code>true</code> if we should accept a request for the
 116  
      * specified resource identifier, based upon our configured includes
 117  
      * and excludes patterns (if any).</p>
 118  
      *
 119  
      * @param resourceId Resource identifier to validate
 120  
      */
 121  
     protected boolean accept(String resourceId) {
 122  
 
 123  
         // Check for a match on the excluded list
 124  18
         if (matches(resourceId, excludesPatterns, false)) {
 125  5
             return false;
 126  
         }
 127  
 
 128  
         // Check for a match on the included list
 129  13
         if (matches(resourceId, includesPatterns, true)) {
 130  13
             return true;
 131  
         }
 132  
 
 133  
         // If there was at least one include pattern,
 134  
         // unconditionally reject this request
 135  
         if ((includesPatterns != null) && (includesPatterns.length > 0)) {
 136  
             return false;
 137  
         }
 138  
 
 139  
         // Unconditionally accept this request
 140  
         return true;
 141  
 
 142  
     }
 143  
 
 144  
 
 145  
     // --------------------------------------------------------- Private Methods
 146  
 
 147  
 
 148  
     /**
 149  
      * <p>Match the specified expression against the specified precompiled
 150  
      * patterns.  If there are no patterns, return the specified unrestricted
 151  
      * return value; otherwise, return <code>true</code> if the expression
 152  
      * matches one of the patterns, or <code>false</code> otherwise.</p>
 153  
      *
 154  
      * @param expr Expression to be tested
 155  
      * @param patterns Array of <code>Pattern</code> to be tested against
 156  
      * @param unrestricted Result to be returned if there are no matches
 157  
      */
 158  
     private boolean matches(String expr, String patterns[],
 159  
                             boolean unrestricted) {
 160  
 
 161  
         // Check for the unrestricted case
 162  31
         if ((patterns == null) || (patterns.length == 0)) {
 163  6
             return unrestricted;
 164  
         }
 165  
 
 166  
         // Compare each pattern in turn for a match
 167  221
         for (int i = 0; i < patterns.length; i++) {
 168  208
             if (patterns[i].startsWith("*")) {
 169  58
                 if (expr.endsWith(patterns[i].substring(1))) {
 170  8
                     return true;
 171  
                 }
 172  150
             } else if (patterns[i].endsWith("*")) {
 173  150
                 if (expr.startsWith(patterns[i].substring(0, patterns[i].length() - 1))) {
 174  4
                     return true;
 175  
                 }
 176  
             } else {
 177  
                 if (patterns[i].equals(expr)) {
 178  
                     return true;
 179  
                 }
 180  
             }
 181  
         }
 182  
 
 183  
         // No match found, so return false
 184  13
         return false;
 185  
 
 186  
     }
 187  
 
 188  
 
 189  
     /**
 190  
      * <p>Parse the specified string of comma-delimited URL pattern
 191  
      * matching expressions into an array of patterns that can be processed
 192  
      * at runtime more quickly.  Valid patterns are the same as those
 193  
      * supported for matching a request URI to a Processor instance:</p>
 194  
      * <ul>
 195  
      * <li>Must not be null or zero-length string</li>
 196  
      * <li>EITHER must start with "/" and end with "/*"</li>
 197  
      * <li>OR must start with "*." and not have any other period</li>
 198  
      * </ul>
 199  
      *
 200  
      * @param expr Comma-delimited URL pattern matching expressions
 201  
      *
 202  
      * @exception IllegalArgumentException if an invalid pattern is encountered
 203  
      */
 204  
      private String[] precompile(String expr) {
 205  
 
 206  70
         if (expr == null) {
 207  14
             return new String[0];
 208  
         }
 209  
 
 210  
         // Set up to parse the specified expression
 211  56
         String pattern = null;
 212  56
         StreamTokenizer st =
 213  
           new StreamTokenizer(new StringReader(expr));
 214  56
         st.eolIsSignificant(false);
 215  56
         st.lowerCaseMode(false);
 216  56
         st.slashSlashComments(false);
 217  56
         st.slashStarComments(false);
 218  56
         st.wordChars(0x00, 0xff);
 219  56
         st.quoteChar('\'');
 220  56
         st.quoteChar('"');
 221  56
         st.whitespaceChars(0, ' ');
 222  56
         st.whitespaceChars(',', ',');
 223  56
         List list = new ArrayList();
 224  56
         int type = 0;
 225  
 
 226  
         // Parse and validate each included pattern
 227  
         while (true) {
 228  
 
 229  
             // Parse the next pattern
 230  
             try {
 231  566
                 type = st.nextToken();
 232  
             } catch (IOException e) {
 233  
                 ; // Can not happen
 234  566
             }
 235  566
             if (type == StreamTokenizer.TT_EOF) {
 236  54
                 break;
 237  512
             } else if (type == StreamTokenizer.TT_NUMBER) {
 238  
                 pattern = "" + st.nval;
 239  
             } else if (type == StreamTokenizer.TT_WORD) {
 240  512
                 pattern = st.sval.trim();
 241  512
             } else {
 242  
                 throw new IllegalArgumentException(expr);
 243  
             }
 244  
 
 245  
             // Validate this pattern
 246  512
             if (pattern.length() < 1) {
 247  
                 throw new IllegalArgumentException(pattern);
 248  
             }
 249  512
             if (pattern.startsWith("/")) {
 250  294
                 if (!pattern.endsWith("/*")) {
 251  1
                     throw new IllegalArgumentException(pattern);
 252  
                 }
 253  218
             } else if (pattern.startsWith("*.")) {
 254  218
                 if (pattern.substring(2).indexOf('.') > 0) {
 255  1
                     throw new IllegalArgumentException(pattern);
 256  
                 }
 257  
             } else {
 258  
                 throw new IllegalArgumentException(pattern);
 259  
             }
 260  
 
 261  
             // Add this pattern to our list
 262  510
             list.add(pattern);
 263  
 
 264  510
         }
 265  
 
 266  
         // Return the precompiled patterns as an array
 267  54
         return (String[]) list.toArray(new String[list.size()]);
 268  
 
 269  
     }
 270  
 
 271  
 
 272  
 }