1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.nuiton.util;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import javax.xml.transform.Source;
29 import javax.xml.transform.Transformer;
30 import javax.xml.transform.TransformerFactory;
31 import javax.xml.transform.URIResolver;
32 import javax.xml.transform.stream.StreamSource;
33 import java.net.URL;
34 import java.net.URLClassLoader;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Set;
38 import java.util.SortedMap;
39 import java.util.TreeMap;
40 import java.util.regex.Matcher;
41 import java.util.regex.Pattern;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public class ResourceResolver implements URIResolver {
73
74
75 private static final Log log = LogFactory.getLog(ResourceResolver.class);
76
77
78 protected static final SortedMap<String, Source> sourceCache =
79 new TreeMap<String, Source>();
80
81
82 protected static final Set<String> unresolvedCache = new HashSet<String>();
83
84
85 public static final Pattern HREF_PATTERN =
86 Pattern.compile("([a-zA-Z]+)\\:\\/\\/(.+)");
87
88
89 public static synchronized void clearCache() {
90 sourceCache.clear();
91 unresolvedCache.clear();
92 }
93
94 protected String base;
95
96
97 protected boolean verbose = log.isDebugEnabled();
98
99
100 protected ClassLoader cl = getClass().getClassLoader();
101
102 public ResourceResolver() {
103 this(null);
104 }
105
106 public ResourceResolver(String base) {
107 if (base != null && base.endsWith("/") && base.length() > 1) {
108 base = base.substring(0, base.length() - 1);
109 }
110 this.base = base;
111 if (log.isTraceEnabled()) {
112 log.trace(this + ", base : " + this.base);
113 }
114 }
115
116
117
118
119
120
121 @Override
122 public synchronized Source resolve(String href, String base) {
123
124 if (unresolvedCache.contains(href)) {
125
126
127 if (verbose) {
128 log.info("Skip unresolved " + href);
129 }
130 return null;
131 }
132
133 if (sourceCache.containsKey(href)) {
134
135 if (verbose) {
136 log.info("use cached source " + href);
137 }
138 return sourceCache.get(href);
139 }
140
141
142
143
144 if (verbose) {
145 log.info("Resolving " + href);
146 }
147
148
149
150
151
152
153
154
155 Source source;
156
157
158 Matcher matcher = HREF_PATTERN.matcher(href);
159 if (matcher.matches()) {
160
161 String path = matcher.group(2);
162
163
164 source = findHrefSource(path);
165 } else {
166
167
168 source = findRelativeSource(href);
169 }
170
171 if (source == null) {
172
173 if (verbose) {
174 log.info("detect unresolved source " + href);
175 }
176 unresolvedCache.add(href);
177 } else {
178
179 if (verbose) {
180 log.info("detect cacheable source " + href);
181 }
182 sourceCache.put(href, source);
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197 return source;
198 }
199
200 public void setVerbose(boolean verbose) {
201 this.verbose = verbose;
202 }
203
204 public void setCl(ClassLoader cl) {
205 this.cl = cl;
206 }
207
208 protected Source findHrefSource(String path) {
209 long t0 = System.nanoTime();
210 String filename;
211 int beginIndex = path.lastIndexOf('/');
212 if (beginIndex > -1) {
213 filename = path.substring(beginIndex + 1);
214 } else {
215 filename = path;
216 }
217 if (filename == null || filename.isEmpty()) {
218 return null;
219 }
220 String resource;
221
222 resource = ".*/" + filename;
223
224 if (verbose) {
225 log.info("will discover " + resource);
226 }
227
228 URL url = null;
229
230
231 List<URL> urls = null;
232 URLClassLoader ucl = null;
233 if (cl == null) {
234 ClassLoader cl2 = getClass().getClassLoader();
235 if (cl2 instanceof URLClassLoader) {
236 ucl = (URLClassLoader) cl2;
237 }
238 }
239 if (cl instanceof URLClassLoader) {
240 ucl = (URLClassLoader) cl;
241 }
242 try {
243 urls = Resource.getURLs(resource, ucl);
244 } catch (ResourceNotFoundException rnfe) {
245
246 }
247
248 if (urls != null && !urls.isEmpty()) {
249 url = urls.get(0);
250 }
251
252
253 Source source = null;
254
255 if (url != null) {
256 if (verbose) {
257 log.info(url.toString());
258 }
259 source = new StreamSource(url.toString());
260 }
261 if (verbose) {
262 String time = StringUtil.convertTime(System.nanoTime() - t0);
263 log.info("resolved in " + time);
264 }
265 return source;
266 }
267
268 protected Source findRelativeSource(String path) {
269 long t0 = System.nanoTime();
270 String filename = path;
271
272
273
274
275
276
277
278
279
280 String resource;
281 if (base != null) {
282 resource = base + "/" + filename;
283 } else {
284 resource = filename;
285 }
286
287 if (verbose) {
288 log.info("will discover " + resource);
289 }
290
291 URL url = Resource.getURLOrNull(resource);
292
293 Source source = null;
294
295 if (url != null) {
296 if (verbose) {
297 log.info(url.toString());
298 }
299 source = new StreamSource(url.toString());
300 }
301 if (verbose) {
302 String time = StringUtil.convertTime(System.nanoTime() - t0);
303 log.info("resolved in " + time);
304 }
305 return source;
306 }
307 }