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 }