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.StringTokenizer;
20  
21  
22  /* ------------------------------------------------------------ */
23  /**
24   * ClasspathPattern performs sequential pattern matching of a class name 
25   * against an internal array of classpath pattern entries.
26   * 
27   * When an entry starts with '-' (minus), reverse matching is performed.
28   * When an entry ends with '.' (period), prefix matching is performed.
29   * 
30   * When class is initialized from a classpath pattern string, entries 
31   * in this string should be separated by ':' (semicolon) or ',' (comma).
32   */
33  
34  public class ClasspathPattern
35  {
36      private class Entry
37      {
38          public String classpath = null;
39          public boolean result = false;
40          public boolean partial = false;      
41      }
42      
43      private ArrayList<String> _patterns = null;
44      private ArrayList<Entry> _entries = null;
45  
46      public ClasspathPattern(String[] patterns)
47      {
48          setPatterns(patterns);
49      }
50      
51      public ClasspathPattern(String pattern)
52      {
53          setPattern(pattern);
54      }
55      
56      /* ------------------------------------------------------------ */
57      /**
58       * Create a new instance from a String array of classpath patterns
59       * 
60       * @param patterns array of classpath patterns
61       * @return
62       */
63      public static ClasspathPattern fromArray(String[] patterns)
64      {
65          return new ClasspathPattern(patterns);
66      }
67  
68      /* ------------------------------------------------------------ */
69      /**
70       * Create a new instance from a classpath pattern sring
71       * 
72       * @param patterns classpath pattern string
73       * @return
74       */
75      public static ClasspathPattern fromString(String patterns)
76      {
77          return new ClasspathPattern(patterns);
78      }
79  
80      /* ------------------------------------------------------------ */
81      /**
82       * Initialize the matcher by parsing each classpath pattern in an array
83       * 
84       * @param patterns array of classpath patterns
85       */
86      private void setPatterns(String[] patterns)
87      {
88          if (patterns == null)
89          {
90              _patterns = null;
91              _entries  = null;
92          }
93          else
94          {
95              _patterns = new ArrayList<String>();
96              _entries = new ArrayList<Entry>();
97          }
98          
99          if (_patterns != null) {
100             Entry entry = null; 
101             for (String pattern : patterns)
102             {
103                 entry = createEntry(pattern);
104                 if (entry != null) {
105                     _patterns.add(pattern);
106                     _entries.add(entry);
107                 }
108             }
109         }
110     }
111     
112     /* ------------------------------------------------------------ */
113     /**
114      * Initialize the matcher by parsing each classpath pattern in an array
115      * 
116      * @param patterns array of classpath patterns
117      */
118     private void addPatterns(String[] patterns)
119     {
120         if (patterns != null)
121         {
122             if (_patterns == null)
123             {
124                 setPatterns(patterns);
125             }
126             else
127             {
128                 Entry entry = null; 
129                 for (String pattern : patterns)
130                 {
131                     entry = createEntry(pattern);
132                     if (entry != null) {
133                         _patterns.add(pattern);
134                         _entries.add(entry);
135                     }
136                 }
137             }
138         }
139     }
140     
141     /* ------------------------------------------------------------ */
142     /**
143      * Create an entry object containing information about 
144      * a single classpath pattern
145      * 
146      * @param pattern single classpath pattern
147      * @return corresponding Entry object
148      */
149     private Entry createEntry(String pattern)
150     {
151         Entry entry = null;
152         
153         if (pattern != null)
154         {
155             String item = pattern.trim();
156             if (item.length() > 0)
157             {
158                 entry = new Entry();
159                 entry.result = !item.startsWith("-");
160                 entry.partial = item.endsWith(".");
161                 entry.classpath = entry.result ? item : item.substring(1).trim();
162             }
163         }
164         return entry;
165     }
166     
167     /* ------------------------------------------------------------ */
168     /**
169      * Initialize the matcher by parsing a classpath pattern string
170      * 
171      * @param pattern classpath pattern string
172      */
173     public void setPattern(String pattern)
174     {
175         ArrayList<String> patterns = new ArrayList<String>();
176         StringTokenizer entries = new StringTokenizer(pattern, ":,");
177         while (entries.hasMoreTokens())
178         {
179             patterns.add(entries.nextToken());
180         }
181         
182         setPatterns((String[])patterns.toArray());
183     }
184 
185     /* ------------------------------------------------------------ */
186     /**
187      * Parse a classpath pattern string and appending the result
188      * to the existing configuration.
189      * 
190      * @param pattern classpath pattern string
191      */
192     public void addPattern(String pattern)
193     {
194         ArrayList<String> patterns = new ArrayList<String>();
195         StringTokenizer entries = new StringTokenizer(pattern, ":,");
196         while (entries.hasMoreTokens())
197         {
198             patterns.add(entries.nextToken());
199         }
200         
201         addPatterns((String[])patterns.toArray());
202     }   
203     
204     /* ------------------------------------------------------------ */
205     /**
206      * @return array of classpath patterns
207      */
208     public String[] getPatterns()
209     {
210         String[] patterns = null;
211         
212         if (_patterns!=null)
213         {
214             patterns = _patterns.toArray(new String[_patterns.size()]);
215         }
216         
217         return patterns;
218     }
219     
220     /* ------------------------------------------------------------ */
221     /**
222      * Match the class name against the pattern
223      *
224      * @param name name of the class to match
225      * @return true if class matches the pattern
226      */
227     public boolean match(String name)
228     {       
229         boolean result=false;
230 
231         if (_entries != null)
232         {
233             int startIdx = 0;
234             name = name.replace('/','.');
235             name = name.replaceFirst("^[.]+","");
236 
237             for (Entry entry : _entries)
238             {
239                 if (entry != null)
240                 {               
241                     if (entry.partial)
242                     {
243                         if (name.startsWith(entry.classpath))
244                         {
245                             result = entry.result;
246                             break;
247                         }
248                     }
249                     else
250                     {
251                         if (name.equals(entry.classpath))
252                         {
253                             result = entry.result;
254                             break;
255                         }
256                     }
257                 }
258             }
259         }
260         return result;
261     }
262 }