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.List;
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 static class Entry
37      {
38          public String classpath = null;
39          public boolean result = false;
40          public boolean partial = false;      
41      }
42      
43      final private List<String> _patterns = new ArrayList<String>();
44      final private List<Entry> _entries = new ArrayList<Entry>();
45      
46      /* ------------------------------------------------------------ */
47      public ClasspathPattern()
48      {
49      }
50      
51      /* ------------------------------------------------------------ */
52      public ClasspathPattern(String[] patterns)
53      {
54          setPatterns(patterns);
55      }
56      
57      /* ------------------------------------------------------------ */
58      public ClasspathPattern(String pattern)
59      {
60          setPattern(pattern);
61      }
62      
63  
64      /* ------------------------------------------------------------ */
65      /**
66       * Initialize the matcher by parsing each classpath pattern in an array
67       * 
68       * @param patterns array of classpath patterns
69       */
70      private void setPatterns(String[] patterns)
71      {
72          _patterns.clear();
73          _entries.clear();
74          addPatterns(patterns);
75      }
76      
77      /* ------------------------------------------------------------ */
78      /**
79       * Initialize the matcher by parsing each classpath pattern in an array
80       * 
81       * @param patterns array of classpath patterns
82       */
83      private void addPatterns(String[] patterns)
84      {
85          if (patterns != null)
86          {
87              Entry entry = null; 
88              for (String pattern : patterns)
89              {
90                  entry = createEntry(pattern);
91                  if (entry != null) {
92                      _patterns.add(pattern);
93                      _entries.add(entry);
94                  }
95              }
96          }
97      }
98      
99      /* ------------------------------------------------------------ */
100     /**
101      * Create an entry object containing information about 
102      * a single classpath pattern
103      * 
104      * @param pattern single classpath pattern
105      * @return corresponding Entry object
106      */
107     private Entry createEntry(String pattern)
108     {
109         Entry entry = null;
110         
111         if (pattern != null)
112         {
113             String item = pattern.trim();
114             if (item.length() > 0)
115             {
116                 entry = new Entry();
117                 entry.result = !item.startsWith("-");
118                 entry.partial = item.endsWith(".");
119                 entry.classpath = entry.result ? item : item.substring(1).trim();
120             }
121         }
122         return entry;
123     }
124     
125     /* ------------------------------------------------------------ */
126     /**
127      * Initialize the matcher by parsing a classpath pattern string
128      * 
129      * @param pattern classpath pattern string
130      */
131     public void setPattern(String pattern)
132     {
133         _patterns.clear();
134         _entries.clear();
135         addPattern(pattern);
136     }
137 
138     /* ------------------------------------------------------------ */
139     /**
140      * Parse a classpath pattern string and appending the result
141      * to the existing configuration.
142      * 
143      * @param pattern classpath pattern string
144      */
145     public void addPattern(String pattern)
146     {
147         ArrayList<String> patterns = new ArrayList<String>();
148         StringTokenizer entries = new StringTokenizer(pattern, ":,");
149         while (entries.hasMoreTokens())
150         {
151             patterns.add(entries.nextToken());
152         }
153         
154         addPatterns((String[])patterns.toArray(new String[patterns.size()]));
155     }   
156     
157     /* ------------------------------------------------------------ */
158     /**
159      * @return array of classpath patterns
160      */
161     public String[] getPatterns()
162     {
163         String[] patterns = null;
164         
165         if (_patterns!=null && _patterns.size() > 0)
166         {
167             patterns = _patterns.toArray(new String[_patterns.size()]);
168         }
169         
170         return patterns;
171     }
172     
173     /* ------------------------------------------------------------ */
174     /**
175      * Match the class name against the pattern
176      *
177      * @param name name of the class to match
178      * @return true if class matches the pattern
179      */
180     public boolean match(String name)
181     {       
182         boolean result=false;
183 
184         if (_entries != null)
185         {
186             name = name.replace('/','.');
187             name = name.replaceFirst("^[.]+","");
188             name = name.replaceAll("\\$.*$","");
189             
190             for (Entry entry : _entries)
191             {
192                 if (entry != null)
193                 {               
194                     if (entry.partial)
195                     {
196                         if (name.startsWith(entry.classpath))
197                         {
198                             result = entry.result;
199                             break;
200                         }
201                     }
202                     else
203                     {
204                         if (name.equals(entry.classpath))
205                         {
206                             result = entry.result;
207                             break;
208                         }
209                     }
210                 }
211             }
212         }
213         return result;
214     }
215 }