1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts2;
22
23 import javax.servlet.Servlet;
24 import java.util.concurrent.*;
25
26 /***
27 * Caches servlet instances by jsp location. If a requested jsp is not in the cache, "get"
28 * will block and wait for the jsp to be loaded
29 */
30 public class ServletCache {
31 protected final ConcurrentMap<String, Future<Servlet>> cache
32 = new ConcurrentHashMap<String, Future<Servlet>>();
33
34 private final JSPLoader jspLoader = new JSPLoader();
35
36 public void clear() {
37 cache.clear();
38 }
39
40 public Servlet get(final String location) throws InterruptedException {
41 while (true) {
42 Future<Servlet> future = cache.get(location);
43 if (future == null) {
44 Callable<Servlet> loadJSPCallable = new Callable<Servlet>() {
45 public Servlet call() throws Exception {
46 return jspLoader.load(location);
47 }
48 };
49 FutureTask<Servlet> futureTask = new FutureTask<Servlet>(loadJSPCallable);
50 future = cache.putIfAbsent(location, futureTask);
51 if (future == null) {
52 future = futureTask;
53 futureTask.run();
54 }
55 }
56 try {
57 return future.get();
58 } catch (CancellationException e) {
59 cache.remove(location, future);
60 } catch (ExecutionException e) {
61 throw launderThrowable(e.getCause());
62 }
63 }
64 }
65
66 public static RuntimeException launderThrowable(Throwable t) {
67 if (t instanceof RuntimeException)
68 return (RuntimeException) t;
69 else if (t instanceof Error)
70 throw (Error) t;
71 else
72 throw new IllegalStateException(t);
73 }
74
75 }
76