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 @SuppressWarnings("unchecked")
81 private <T extends Assembler> List<AssemblerFactory<T>> getFactoryGroup(Class<T> type)
82 {
83 if (!factories.containsKey(type))
84 {
85 factories.put(type, new ArrayList<AssemblerFactory<T>>());
86 }
87 return (List<AssemblerFactory<T>>) factories.get(type);
88 }
89
90
91
92
93
94
95
96 private void registerFactories(String type)
97 throws TurbineException
98 {
99 List<Object> names = getConfiguration().getList(type);
100
101 log.info("Registering " + names.size() + " " + type + " factories.");
102
103 for (Iterator<Object> it = names.iterator(); it.hasNext(); )
104 {
105 String factory = (String) it.next();
106 try
107 {
108 @SuppressWarnings("unchecked")
109 AssemblerFactory<? extends Assembler> af =
110 (AssemblerFactory<? extends Assembler>) Class.forName(factory).newInstance();
111 registerFactory(af);
112 }
113
114 catch (ThreadDeath e)
115 {
116 throw e;
117 }
118 catch (OutOfMemoryError e)
119 {
120 throw e;
121 }
122
123
124 catch (Throwable t)
125 {
126 throw new TurbineException("Failed registering " + type
127 + " factory: " + factory, t);
128 }
129 }
130 }
131
132
133
134
135
136
137
138 @SuppressWarnings("unchecked")
139 @Override
140 public void init()
141 throws InitializationException
142 {
143 factories = new HashMap<Class<?>, List<?>>();
144
145 try
146 {
147 Configuration conf = getConfiguration();
148
149 for (Iterator<String> i = conf.getKeys(); i.hasNext();)
150 {
151 String type = i.next();
152
153 if (!"classname".equalsIgnoreCase(type))
154 {
155 registerFactories(type);
156 }
157 }
158 }
159 catch (TurbineException e)
160 {
161 throw new InitializationException(
162 "AssemblerBrokerService failed to initialize", e);
163 }
164
165 isCaching = Turbine.getConfiguration()
166 .getBoolean(TurbineConstants.MODULE_CACHE_KEY,
167 TurbineConstants.MODULE_CACHE_DEFAULT);
168
169 if (isCaching)
170 {
171 int cacheSize = Turbine.getConfiguration()
172 .getInt(TurbineConstants.MODULE_CACHE_SIZE_KEY,
173 TurbineConstants.MODULE_CACHE_SIZE_DEFAULT);
174
175 assemblerCache = new LRUMap(cacheSize);
176 loaderCache = new LRUMap(cacheSize);
177 }
178
179 setInit(true);
180 }
181
182
183
184
185
186
187 public <T extends Assembler> void registerFactory(AssemblerFactory<T> factory)
188 {
189 getFactoryGroup(factory.getManagedClass()).add(factory);
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203 @SuppressWarnings("unchecked")
204 public <T extends Assembler> T getAssembler(Class<T> type, String name)
205 throws TurbineException
206 {
207 String key = type + ":" + name;
208 T assembler = null;
209
210 if (isCaching && assemblerCache.containsKey(key))
211 {
212 assembler = (T) assemblerCache.get(key);
213 log.debug("Found " + key + " in the cache!");
214 }
215 else
216 {
217 log.debug("Loading " + key);
218 List<AssemblerFactory<T>> facs = getFactoryGroup(type);
219
220 for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (assembler == null) && it.hasNext();)
221 {
222 AssemblerFactory<T> fac = it.next();
223
224 try
225 {
226 assembler = fac.getAssembler(name);
227 }
228 catch (Exception e)
229 {
230 throw new TurbineException("Failed to load an assembler for "
231 + name + " from the "
232 + type + " factory "
233 + fac.getClass().getName(), e);
234 }
235
236 if (assembler != null)
237 {
238 AnnotationProcessor.process(assembler);
239
240 if (isCaching)
241 {
242 assemblerCache.put(key, assembler);
243 }
244 }
245 }
246 }
247
248 return assembler;
249 }
250
251
252
253
254
255
256
257 @SuppressWarnings("unchecked")
258 public <T extends Assembler> Loader<T> getLoader(Class<T> type)
259 {
260 Loader<T> loader = null;
261
262 if (isCaching && loaderCache.containsKey(type))
263 {
264 loader = (Loader<T>) loaderCache.get(type);
265 log.debug("Found " + type + " loader in the cache!");
266 }
267 else
268 {
269 log.debug("Getting Loader for " + type);
270 List<AssemblerFactory<T>> facs = getFactoryGroup(type);
271
272 for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (loader == null) && it.hasNext();)
273 {
274 AssemblerFactory<T> fac = it.next();
275 loader = fac.getLoader();
276 }
277
278 if (isCaching && loader != null)
279 {
280 loaderCache.put(type, loader);
281 }
282 }
283
284 if (loader == null)
285 {
286 log.warn("Loader for " + type + " is null.");
287 }
288
289 return loader;
290 }
291 }