1 | |
package org.apache.turbine.services.assemblerbroker; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
import java.util.ArrayList; |
25 | |
import java.util.HashMap; |
26 | |
import java.util.Iterator; |
27 | |
import java.util.List; |
28 | |
import java.util.Map; |
29 | |
|
30 | |
import org.apache.commons.collections.map.LRUMap; |
31 | |
import org.apache.commons.configuration.Configuration; |
32 | |
import org.apache.commons.logging.Log; |
33 | |
import org.apache.commons.logging.LogFactory; |
34 | |
import org.apache.turbine.Turbine; |
35 | |
import org.apache.turbine.TurbineConstants; |
36 | |
import org.apache.turbine.annotation.AnnotationProcessor; |
37 | |
import org.apache.turbine.modules.Assembler; |
38 | |
import org.apache.turbine.modules.Loader; |
39 | |
import org.apache.turbine.services.InitializationException; |
40 | |
import org.apache.turbine.services.TurbineBaseService; |
41 | |
import org.apache.turbine.services.assemblerbroker.util.AssemblerFactory; |
42 | |
import org.apache.turbine.util.TurbineException; |
43 | |
|
44 | |
|
45 | |
|
46 | |
|
47 | |
|
48 | |
|
49 | |
|
50 | |
|
51 | |
|
52 | |
|
53 | |
|
54 | 33 | public class TurbineAssemblerBrokerService |
55 | |
extends TurbineBaseService |
56 | |
implements AssemblerBrokerService |
57 | |
{ |
58 | |
|
59 | 33 | private static Log log |
60 | |
= LogFactory.getLog(TurbineAssemblerBrokerService.class); |
61 | |
|
62 | |
|
63 | 33 | private Map<Class<?>, List<?>> factories = null; |
64 | |
|
65 | |
|
66 | 33 | private Map<String, Assembler> assemblerCache = null; |
67 | |
|
68 | |
|
69 | 33 | private Map<Class<?>, Loader<? extends Assembler>> loaderCache = null; |
70 | |
|
71 | |
|
72 | |
private boolean isCaching; |
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
|
79 | |
|
80 | |
|
81 | |
|
82 | |
|
83 | |
@SuppressWarnings("unchecked") |
84 | |
private <T extends Assembler> List<AssemblerFactory<T>> getFactoryGroup(Class<T> type) |
85 | |
{ |
86 | 819 | if (!factories.containsKey(type)) |
87 | |
{ |
88 | 258 | factories.put(type, new ArrayList<AssemblerFactory<T>>()); |
89 | |
} |
90 | 819 | return (List<AssemblerFactory<T>>) factories.get(type); |
91 | |
} |
92 | |
|
93 | |
|
94 | |
|
95 | |
|
96 | |
|
97 | |
|
98 | |
|
99 | |
private void registerFactories(String type) |
100 | |
throws TurbineException |
101 | |
{ |
102 | 258 | List<Object> names = getConfiguration().getList(type); |
103 | |
|
104 | 258 | log.info("Registering " + names.size() + " " + type + " factories."); |
105 | |
|
106 | 258 | for (Iterator<Object> it = names.iterator(); it.hasNext(); ) |
107 | |
{ |
108 | 258 | String factory = (String) it.next(); |
109 | |
try |
110 | |
{ |
111 | |
@SuppressWarnings("unchecked") |
112 | 258 | AssemblerFactory<? extends Assembler> af = |
113 | |
(AssemblerFactory<? extends Assembler>) Class.forName(factory).newInstance(); |
114 | 258 | registerFactory(af); |
115 | |
} |
116 | |
|
117 | 0 | catch (ThreadDeath e) |
118 | |
{ |
119 | 0 | throw e; |
120 | |
} |
121 | 0 | catch (OutOfMemoryError e) |
122 | |
{ |
123 | 0 | throw e; |
124 | |
} |
125 | |
|
126 | |
|
127 | 0 | catch (Throwable t) |
128 | |
{ |
129 | 0 | throw new TurbineException("Failed registering " + type |
130 | |
+ " factory: " + factory, t); |
131 | 258 | } |
132 | 258 | } |
133 | 258 | } |
134 | |
|
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | |
|
141 | |
@SuppressWarnings("unchecked") |
142 | |
@Override |
143 | |
public void init() |
144 | |
throws InitializationException |
145 | |
{ |
146 | 43 | factories = new HashMap<Class<?>, List<?>>(); |
147 | |
|
148 | |
try |
149 | |
{ |
150 | 43 | Configuration conf = getConfiguration(); |
151 | |
|
152 | 43 | for (Iterator<String> i = conf.getKeys(); i.hasNext();) |
153 | |
{ |
154 | 301 | String type = i.next(); |
155 | |
|
156 | 301 | if (!"classname".equalsIgnoreCase(type)) |
157 | |
{ |
158 | 258 | registerFactories(type); |
159 | |
} |
160 | 301 | } |
161 | |
} |
162 | 0 | catch (TurbineException e) |
163 | |
{ |
164 | 0 | throw new InitializationException( |
165 | |
"AssemblerBrokerService failed to initialize", e); |
166 | 43 | } |
167 | |
|
168 | 43 | isCaching = Turbine.getConfiguration() |
169 | |
.getBoolean(TurbineConstants.MODULE_CACHE_KEY, |
170 | |
TurbineConstants.MODULE_CACHE_DEFAULT); |
171 | |
|
172 | 43 | if (isCaching) |
173 | |
{ |
174 | 16 | int cacheSize = Turbine.getConfiguration() |
175 | |
.getInt(TurbineConstants.MODULE_CACHE_SIZE_KEY, |
176 | |
TurbineConstants.MODULE_CACHE_SIZE_DEFAULT); |
177 | |
|
178 | 16 | assemblerCache = new LRUMap(cacheSize); |
179 | 16 | loaderCache = new LRUMap(cacheSize); |
180 | |
} |
181 | |
|
182 | 43 | setInit(true); |
183 | 43 | } |
184 | |
|
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
|
190 | |
|
191 | |
|
192 | |
|
193 | |
@Override |
194 | |
public <T extends Assembler> void registerFactory(AssemblerFactory<T> factory) |
195 | |
{ |
196 | 258 | getFactoryGroup(factory.getManagedClass()).add(factory); |
197 | 258 | } |
198 | |
|
199 | |
|
200 | |
|
201 | |
|
202 | |
|
203 | |
|
204 | |
|
205 | |
|
206 | |
|
207 | |
|
208 | |
|
209 | |
|
210 | |
|
211 | |
|
212 | |
|
213 | |
@Override |
214 | |
@SuppressWarnings("unchecked") |
215 | |
public <T extends Assembler> T getAssembler(Class<T> type, String name) |
216 | |
throws TurbineException |
217 | |
{ |
218 | 166 | String key = type + ":" + name; |
219 | 166 | T assembler = null; |
220 | |
|
221 | 166 | if (isCaching && assemblerCache.containsKey(key)) |
222 | |
{ |
223 | 6 | assembler = (T) assemblerCache.get(key); |
224 | 6 | log.debug("Found " + key + " in the cache!"); |
225 | |
} |
226 | |
else |
227 | |
{ |
228 | 160 | log.debug("Loading " + key); |
229 | 160 | List<AssemblerFactory<T>> facs = getFactoryGroup(type); |
230 | |
|
231 | 160 | for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (assembler == null) && it.hasNext();) |
232 | |
{ |
233 | 160 | AssemblerFactory<T> fac = it.next(); |
234 | |
|
235 | |
try |
236 | |
{ |
237 | 160 | assembler = fac.getAssembler(name); |
238 | |
} |
239 | 0 | catch (Exception e) |
240 | |
{ |
241 | 0 | throw new TurbineException("Failed to load an assembler for " |
242 | |
+ name + " from the " |
243 | |
+ type + " factory " |
244 | |
+ fac.getClass().getName(), e); |
245 | 160 | } |
246 | |
|
247 | 160 | if (assembler != null) |
248 | |
{ |
249 | 98 | AnnotationProcessor.process(assembler); |
250 | |
|
251 | 98 | if (isCaching) |
252 | |
{ |
253 | 15 | assemblerCache.put(key, assembler); |
254 | |
} |
255 | |
} |
256 | 160 | } |
257 | |
} |
258 | |
|
259 | 166 | return assembler; |
260 | |
} |
261 | |
|
262 | |
|
263 | |
|
264 | |
|
265 | |
|
266 | |
|
267 | |
|
268 | |
|
269 | |
|
270 | |
|
271 | |
@Override |
272 | |
@SuppressWarnings("unchecked") |
273 | |
public <T extends Assembler> Loader<T> getLoader(Class<T> type) |
274 | |
{ |
275 | 481 | Loader<T> loader = null; |
276 | |
|
277 | 481 | if (isCaching && loaderCache.containsKey(type)) |
278 | |
{ |
279 | 80 | loader = (Loader<T>) loaderCache.get(type); |
280 | 80 | log.debug("Found " + type + " loader in the cache!"); |
281 | |
} |
282 | |
else |
283 | |
{ |
284 | 401 | log.debug("Getting Loader for " + type); |
285 | 401 | List<AssemblerFactory<T>> facs = getFactoryGroup(type); |
286 | |
|
287 | 401 | for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (loader == null) && it.hasNext();) |
288 | |
{ |
289 | 401 | AssemblerFactory<T> fac = it.next(); |
290 | 401 | loader = fac.getLoader(); |
291 | 401 | } |
292 | |
|
293 | 401 | if (isCaching && loader != null) |
294 | |
{ |
295 | 64 | loaderCache.put(type, loader); |
296 | |
} |
297 | |
} |
298 | |
|
299 | 481 | if (loader == null) |
300 | |
{ |
301 | 0 | log.warn("Loader for " + type + " is null."); |
302 | |
} |
303 | |
|
304 | 481 | return loader; |
305 | |
} |
306 | |
} |