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 public class TurbineAssemblerBrokerService
55 extends TurbineBaseService
56 implements AssemblerBrokerService
57 {
58
59 private static Log log
60 = LogFactory.getLog(TurbineAssemblerBrokerService.class);
61
62
63 private Map<Class<?>, List<?>> factories = null;
64
65
66 private Map<String, Assembler> assemblerCache = null;
67
68
69 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 if (!factories.containsKey(type))
87 {
88 factories.put(type, new ArrayList<AssemblerFactory<T>>());
89 }
90 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 List<Object> names = getConfiguration().getList(type);
103
104 log.info("Registering " + names.size() + " " + type + " factories.");
105
106 for (Iterator<Object> it = names.iterator(); it.hasNext(); )
107 {
108 String factory = (String) it.next();
109 try
110 {
111 @SuppressWarnings("unchecked")
112 AssemblerFactory<? extends Assembler> af =
113 (AssemblerFactory<? extends Assembler>) Class.forName(factory).newInstance();
114 registerFactory(af);
115 }
116
117 catch (ThreadDeath e)
118 {
119 throw e;
120 }
121 catch (OutOfMemoryError e)
122 {
123 throw e;
124 }
125
126
127 catch (Throwable t)
128 {
129 throw new TurbineException("Failed registering " + type
130 + " factory: " + factory, t);
131 }
132 }
133 }
134
135
136
137
138
139
140
141 @SuppressWarnings("unchecked")
142 @Override
143 public void init()
144 throws InitializationException
145 {
146 factories = new HashMap<Class<?>, List<?>>();
147
148 try
149 {
150 Configuration conf = getConfiguration();
151
152 for (Iterator<String> i = conf.getKeys(); i.hasNext();)
153 {
154 String type = i.next();
155
156 if (!"classname".equalsIgnoreCase(type))
157 {
158 registerFactories(type);
159 }
160 }
161 }
162 catch (TurbineException e)
163 {
164 throw new InitializationException(
165 "AssemblerBrokerService failed to initialize", e);
166 }
167
168 isCaching = Turbine.getConfiguration()
169 .getBoolean(TurbineConstants.MODULE_CACHE_KEY,
170 TurbineConstants.MODULE_CACHE_DEFAULT);
171
172 if (isCaching)
173 {
174 int cacheSize = Turbine.getConfiguration()
175 .getInt(TurbineConstants.MODULE_CACHE_SIZE_KEY,
176 TurbineConstants.MODULE_CACHE_SIZE_DEFAULT);
177
178 assemblerCache = new LRUMap(cacheSize);
179 loaderCache = new LRUMap(cacheSize);
180 }
181
182 setInit(true);
183 }
184
185
186
187
188
189
190
191
192
193 @Override
194 public <T extends Assembler> void registerFactory(AssemblerFactory<T> factory)
195 {
196 getFactoryGroup(factory.getManagedClass()).add(factory);
197 }
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 String key = type + ":" + name;
219 T assembler = null;
220
221 if (isCaching && assemblerCache.containsKey(key))
222 {
223 assembler = (T) assemblerCache.get(key);
224 log.debug("Found " + key + " in the cache!");
225 }
226 else
227 {
228 log.debug("Loading " + key);
229 List<AssemblerFactory<T>> facs = getFactoryGroup(type);
230
231 for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (assembler == null) && it.hasNext();)
232 {
233 AssemblerFactory<T> fac = it.next();
234
235 try
236 {
237 assembler = fac.getAssembler(name);
238 }
239 catch (Exception e)
240 {
241 throw new TurbineException("Failed to load an assembler for "
242 + name + " from the "
243 + type + " factory "
244 + fac.getClass().getName(), e);
245 }
246
247 if (assembler != null)
248 {
249 AnnotationProcessor.process(assembler);
250
251 if (isCaching)
252 {
253 assemblerCache.put(key, assembler);
254 }
255 }
256 }
257 }
258
259 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 Loader<T> loader = null;
276
277 if (isCaching && loaderCache.containsKey(type))
278 {
279 loader = (Loader<T>) loaderCache.get(type);
280 log.debug("Found " + type + " loader in the cache!");
281 }
282 else
283 {
284 log.debug("Getting Loader for " + type);
285 List<AssemblerFactory<T>> facs = getFactoryGroup(type);
286
287 for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (loader == null) && it.hasNext();)
288 {
289 AssemblerFactory<T> fac = it.next();
290 loader = fac.getLoader();
291 }
292
293 if (isCaching && loader != null)
294 {
295 loaderCache.put(type, loader);
296 }
297 }
298
299 if (loader == null)
300 {
301 log.warn("Loader for " + type + " is null.");
302 }
303
304 return loader;
305 }
306 }