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 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.concurrent.ConcurrentMap;
31
32 import org.apache.commons.configuration2.Configuration;
33 import org.apache.logging.log4j.LogManager;
34 import org.apache.logging.log4j.Logger;
35 import org.apache.turbine.Turbine;
36 import org.apache.turbine.TurbineConstants;
37 import org.apache.turbine.annotation.AnnotationProcessor;
38 import org.apache.turbine.modules.Assembler;
39 import org.apache.turbine.modules.Loader;
40 import org.apache.turbine.services.InitializationException;
41 import org.apache.turbine.services.TurbineBaseService;
42 import org.apache.turbine.services.assemblerbroker.util.AssemblerFactory;
43 import org.apache.turbine.util.TurbineException;
44
45
46
47
48
49
50
51
52
53
54
55 public class TurbineAssemblerBrokerService
56 extends TurbineBaseService
57 implements AssemblerBrokerService
58 {
59
60 private static Logger log
61 = LogManager.getLogger(TurbineAssemblerBrokerService.class);
62
63
64 private Map<Class<?>, List<?>> factories = null;
65
66
67 private ConcurrentMap<String, Assembler> assemblerCache = null;
68
69
70 private ConcurrentMap<Class<?>, Loader<? extends Assembler>> loaderCache = null;
71
72
73 private boolean isCaching;
74
75
76
77
78
79
80
81
82
83
84 @SuppressWarnings("unchecked")
85 private <T extends Assembler> List<AssemblerFactory<T>> getFactoryGroup(Class<T> type)
86 {
87 if (!factories.containsKey(type))
88 {
89 factories.put(type, new ArrayList<AssemblerFactory<T>>());
90 }
91 return (List<AssemblerFactory<T>>) factories.get(type);
92 }
93
94
95
96
97
98
99
100 private void registerFactories(String type)
101 throws TurbineException
102 {
103 List<Object> names = getConfiguration().getList(type);
104
105 log.info("Registering {} {} factories.", Integer.valueOf(names.size()), type);
106
107 for (Iterator<Object> it = names.iterator(); it.hasNext(); )
108 {
109 String factory = (String) it.next();
110 try
111 {
112 @SuppressWarnings("unchecked")
113 AssemblerFactory<? extends Assembler> af =
114 (AssemblerFactory<? extends Assembler>) Class.forName(factory).newInstance();
115 registerFactory(af);
116 }
117
118 catch (ThreadDeath | 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 @Override
139 public void init()
140 throws InitializationException
141 {
142 factories = new HashMap<Class<?>, List<?>>();
143
144 try
145 {
146 Configuration conf = getConfiguration();
147
148 for (Iterator<String> i = conf.getKeys(); i.hasNext();)
149 {
150 String type = i.next();
151
152 if (!"classname".equalsIgnoreCase(type))
153 {
154 registerFactories(type);
155 }
156 }
157 }
158 catch (TurbineException e)
159 {
160 throw new InitializationException(
161 "AssemblerBrokerService failed to initialize", e);
162 }
163
164 isCaching = Turbine.getConfiguration()
165 .getBoolean(TurbineConstants.MODULE_CACHE_KEY,
166 TurbineConstants.MODULE_CACHE_DEFAULT);
167
168 if (isCaching)
169 {
170 int cacheSize = Turbine.getConfiguration()
171 .getInt(TurbineConstants.MODULE_CACHE_SIZE_KEY,
172 TurbineConstants.MODULE_CACHE_SIZE_DEFAULT);
173
174 assemblerCache = new ConcurrentHashMap<String, Assembler>(cacheSize);
175 loaderCache = new ConcurrentHashMap<Class<?>, Loader<? extends Assembler>>(cacheSize);
176 }
177
178 setInit(true);
179 }
180
181
182
183
184
185
186
187
188
189 @Override
190 public <T extends Assembler> void registerFactory(AssemblerFactory<T> factory)
191 {
192 getFactoryGroup(factory.getManagedClass()).add(factory);
193 }
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 @Override
210 @SuppressWarnings("unchecked")
211 public <T extends Assembler> T getAssembler(Class<T> type, String name)
212 throws TurbineException
213 {
214 String key = type + ":" + name;
215 T assembler = null;
216
217 if (isCaching && assemblerCache.containsKey(key))
218 {
219 assembler = (T) assemblerCache.get(key);
220 log.debug("Found {} in the cache!", key);
221 }
222 else
223 {
224 log.debug("Loading {}", key);
225 List<AssemblerFactory<T>> facs = getFactoryGroup(type);
226
227 for (Iterator<AssemblerFactory<T>> it = facs.iterator(); (assembler == null) && it.hasNext();)
228 {
229 AssemblerFactory<T> fac = it.next();
230
231 try
232 {
233 assembler = fac.getAssembler(name);
234 }
235 catch (Exception e)
236 {
237 throw new TurbineException("Failed to load an assembler for "
238 + name + " from the "
239 + type + " factory "
240 + fac.getClass().getName(), e);
241 }
242
243 if (assembler != null)
244 {
245 AnnotationProcessor.process(assembler);
246
247 if (isCaching)
248 {
249 T oldAssembler = (T) assemblerCache.putIfAbsent(key, assembler);
250 if (oldAssembler != null)
251 {
252 assembler = oldAssembler;
253 }
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 {} loader in the cache!", type);
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 {} is null.", type);
302 }
303
304 return loader;
305 }
306 }