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