View Javadoc

1   // ========================================================================
2   // Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  
15  package org.eclipse.jetty.webapp;
16  
17  import java.util.ArrayList;
18  import java.util.Arrays;
19  import java.util.List;
20  import java.util.StringTokenizer;
21  
22  
23  /* ------------------------------------------------------------ */
24  /**
25   * ClasspathPattern performs sequential pattern matching of a class name 
26   * against an internal array of classpath pattern entries.
27   * 
28   * When an entry starts with '-' (minus), reverse matching is performed.
29   * When an entry ends with '.' (period), prefix matching is performed.
30   * 
31   * When class is initialized from a classpath pattern string, entries 
32   * in this string should be separated by ':' (semicolon) or ',' (comma).
33   */
34  
35  public class ClasspathPattern
36  {
37      private static class Entry
38      {
39          public String classpath = null;
40          public boolean result = false;
41          public boolean partial = false;      
42      }
43      
44      final private List<String> _patterns = new ArrayList<String>();
45      final private List<Entry> _entries = new ArrayList<Entry>();
46      
47      /* ------------------------------------------------------------ */
48      public ClasspathPattern()
49      {
50      }
51      
52      /* ------------------------------------------------------------ */
53      public ClasspathPattern(String[] patterns)
54      {
55          setPatterns(patterns);
56      }
57      
58      /* ------------------------------------------------------------ */
59      public ClasspathPattern(String pattern)
60      {
61          setPattern(pattern);
62      }
63      
64  
65      /* ------------------------------------------------------------ */
66      /**
67       * Initialize the matcher by parsing each classpath pattern in an array
68       * 
69       * @param patterns array of classpath patterns
70       */
71      private void setPatterns(String[] patterns)
72      {
73          _patterns.clear();
74          _entries.clear();
75          addPatterns(patterns);
76      }
77      
78      /* ------------------------------------------------------------ */
79      /**
80       * Initialize the matcher by parsing each classpath pattern in an array
81       * 
82       * @param patterns array of classpath patterns
83       */
84      private void addPatterns(String[] patterns)
85      {
86          if (patterns != null)
87          {
88              Entry entry = null; 
89              for (String pattern : patterns)
90              {
91                  entry = createEntry(pattern);
92                  if (entry != null) {
93                      _patterns.add(pattern);
94                      _entries.add(entry);
95                  }
96              }
97          }
98      }
99      
100     /* ------------------------------------------------------------ */
101     /**
102      * Create an entry object containing information about 
103      * a single classpath pattern
104      * 
105      * @param pattern single classpath pattern
106      * @return corresponding Entry object
107      */
108     private Entry createEntry(String pattern)
109     {
110         Entry entry = null;
111         
112         if (pattern != null)
113         {
114             String item = pattern.trim();
115             if (item.length() > 0)
116             {
117                 entry = new Entry();
118                 entry.result = !item.startsWith("-");
119                 entry.partial = item.endsWith(".");
120                 entry.classpath = entry.result ? item : item.substring(1).trim();
121             }
122         }
123         return entry;
124     }
125     
126     /* ------------------------------------------------------------ */
127     /**
128      * Initialize the matcher by parsing a classpath pattern string
129      * 
130      * @param pattern classpath pattern string
131      */
132     public void setPattern(String pattern)
133     {
134         _patterns.clear();
135         _entries.clear();
136         addPattern(pattern);
137     }
138 
139     /* ------------------------------------------------------------ */
140     /**
141      * Parse a classpath pattern string and appending the result
142      * to the existing configuration.
143      * 
144      * @param pattern classpath pattern string
145      */
146     public void addPattern(String pattern)
147     {
148         ArrayList<String> patterns = new ArrayList<String>();
149         StringTokenizer entries = new StringTokenizer(pattern, ":,");
150         while (entries.hasMoreTokens())
151         {
152             patterns.add(entries.nextToken());
153         }
154         
155         addPatterns((String[])patterns.toArray(new String[patterns.size()]));
156     }   
157     
158     /* ------------------------------------------------------------ */
159     /**
160      * @return array of classpath patterns
161      */
162     public String[] getPatterns()
163     {
164         String[] patterns = null;
165         
166         if (_patterns!=null)
167         {
168             patterns = _patterns.toArray(new String[_patterns.size()]);
169         }
170         
171         return patterns;
172     }
173     
174     /* ------------------------------------------------------------ */
175     /**
176      * Match the class name against the pattern
177      *
178      * @param name name of the class to match
179      * @return true if class matches the pattern
180      */
181     public boolean match(String name)
182     {       
183         boolean result=false;
184 
185         if (_entries != null)
186         {
187             name = name.replace('/','.');
188             name = name.replaceFirst("^[.]+","");
189             name = name.replaceAll("\\$.*$","");
190             
191             for (Entry entry : _entries)
192             {
193                 if (entry != null)
194                 {               
195                     if (entry.partial)
196                     {
197                         if (name.startsWith(entry.classpath))
198                         {
199                             result = entry.result;
200                             break;
201                         }
202                     }
203                     else
204                     {
205                         if (name.equals(entry.classpath))
206                         {
207                             result = entry.result;
208                             break;
209                         }
210                     }
211                 }
212             }
213         }
214         return result;
215     }
216 }