1
2
3
4 package org.rcfaces.core.internal.config;
5
6 import java.lang.reflect.Constructor;
7 import java.lang.reflect.Modifier;
8 import java.util.ArrayList;
9 import java.util.HashSet;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14 import java.util.TreeMap;
15
16 import javax.faces.FacesException;
17 import javax.faces.context.FacesContext;
18
19 import org.apache.commons.digester.Digester;
20 import org.apache.commons.digester.Rule;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.rcfaces.core.internal.util.ClassLocator;
24 import org.rcfaces.core.provider.IProvider;
25 import org.xml.sax.Attributes;
26
27
28
29
30
31
32 public class ProvidersRegistry implements IProvidersRegistry {
33 private static final String REVISION = "$Revision: 1.18 $";
34
35 private static final Log LOG = LogFactory.getLog(ProvidersRegistry.class);
36
37 private static final Class[] PARENT_PROVIDER_PARAMETER_TYPES = new Class[] { IProvider.class };
38
39 private final Map providersById = new TreeMap();
40
41 private Digester digester;
42
43 public ProvidersRegistry() {
44 }
45
46 public IProvider getProvider(String providerId) {
47 ProviderBean providerBean = (ProviderBean) providersById
48 .get(providerId);
49 if (providerBean == null) {
50 return null;
51 }
52
53 return providerBean.getProvider();
54 }
55
56 public void addProvider(ProviderBean providerBean) {
57
58 String id = providerBean.getId();
59
60 String providerId = providerBean.getProviderId();
61 if (providerId == null) {
62 throw new FacesException("You must specify a provider identifier.");
63 }
64
65 String className = providerBean.getProviderClassName();
66 if (className == null) {
67 throw new FacesException(
68 "You must specify the className of the provider. (id='"
69 + id + "' providerId='" + providerId + "')");
70 }
71
72 if (LOG.isDebugEnabled()) {
73 LOG.debug("Initialize provider '" + id + "'. (providerId='"
74 + providerId + "', classname='" + className + "'");
75 }
76
77 Class clazz;
78 try {
79 clazz = ClassLocator.load(className, null, FacesContext
80 .getCurrentInstance());
81
82 } catch (ClassNotFoundException ex) {
83 throw new FacesException("Can not load class '" + className
84 + "' specified by provider id='" + id + "' (providerId='"
85 + providerId + "').", ex);
86 }
87
88 if (IProvider.class.isAssignableFrom(clazz) == false) {
89 throw new FacesException("Class '" + className
90 + "' specified by provider id='" + id + "' (providerId='"
91 + providerId + "') must implement interface 'IProvider'.");
92 }
93
94 if ((clazz.getModifiers() & Modifier.ABSTRACT) > 0) {
95 throw new FacesException("Class '" + className
96 + "' specified by provider id='" + id + "' (providerId='"
97 + providerId + "') is abstract !");
98 }
99
100 Constructor constructor;
101 Object parameters[];
102
103 try {
104 constructor = clazz.getConstructor(PARENT_PROVIDER_PARAMETER_TYPES);
105 parameters = new Object[] { null };
106
107 } catch (NoSuchMethodException ex) {
108 LOG.trace(
109 "Can not get constructor with provider parameter for class '"
110 + className + "' specified by provider id='" + id
111 + "' (providerId='" + providerId
112 + "'), TRY with no parameter !", ex);
113
114 try {
115 constructor = clazz.getConstructor((Class[]) null);
116 parameters = null;
117
118 } catch (NoSuchMethodException ex2) {
119 throw new FacesException(
120 "Can not find accessible (public) constructor of class '"
121 + className + "' specified by provider id='"
122 + id + "' (providerId='" + providerId + "').",
123 ex2);
124 }
125 }
126
127 LOG.debug("Use constructor '" + constructor
128 + "' to instanciate provider '" + id + "'. (providerId='"
129 + providerId + "', classname='" + className + "'");
130
131
132
133
134
135
136
137 IProvider provider;
138 try {
139 provider = (IProvider) constructor.newInstance(parameters);
140
141 } catch (Throwable ex) {
142 throw new FacesException("Can not instanciate class '" + className
143 + "' specified by provider id='" + id + "' (providerId='"
144 + providerId + "') using constructor '" + constructor
145 + "'.", ex);
146 }
147
148 LOG.trace("addProvider(" + providerId + "," + provider + ")");
149
150 providerBean.setProvider(provider);
151
152 providersById.put(providerId, providerBean);
153 }
154
155 public void configureRules(Digester digester) {
156
157 digester.addRule("rcfaces-config/providers", new Rule() {
158 private static final String REVISION = "$Revision: 1.18 $";
159
160 public void begin(String namespace, String name,
161 Attributes attributes) throws Exception {
162
163 super.digester.push(ProvidersRegistry.this);
164 }
165
166 public void end(String namespace, String name) throws Exception {
167 super.digester.pop();
168 }
169 });
170
171 digester.addObjectCreate("rcfaces-config/providers/provider",
172 ProviderBean.class);
173 digester.addSetProperties("rcfaces-config/providers/provider", "id",
174 "id");
175 digester.addBeanPropertySetter(
176 "rcfaces-config/providers/provider/provider-id", "providerId");
177 digester.addBeanPropertySetter(
178 "rcfaces-config/providers/provider/provider-class",
179 "providerClassName");
180
181 digester.addRule("rcfaces-config/providers/provider/requires",
182 new Rule() {
183
184 public void body(String namespace, String name, String text)
185 throws Exception {
186
187 ProviderBean providerBean = (ProviderBean) super.digester
188 .peek();
189
190 providerBean.addRequired(text);
191 }
192
193 });
194
195 digester.addSetNext("rcfaces-config/providers/provider", "addProvider");
196 }
197
198
199
200
201
202
203 public static class ProviderBean {
204 private static final String REVISION = "$Revision: 1.18 $";
205
206 private String id;
207
208 private String providerClassName;
209
210 private String providerId;
211
212 private List requirements;
213
214 private IProvider provider;
215
216 public String getProviderId() {
217 return providerId;
218 }
219
220 public void addRequired(String required) {
221 if (requirements == null) {
222 requirements = new ArrayList();
223 }
224
225 requirements.add(required);
226 }
227
228 public String[] listRequirements() {
229 if (requirements == null) {
230 return new String[0];
231 }
232 return (String[]) requirements.toArray(new String[requirements
233 .size()]);
234 }
235
236 public void setProviderId(String providerId) {
237 this.providerId = providerId;
238 }
239
240 public final String getProviderClassName() {
241 return providerClassName;
242 }
243
244 public final void setProviderClassName(String className) {
245 this.providerClassName = className;
246 }
247
248 public final String getId() {
249 return id;
250 }
251
252 public final void setId(String id) {
253 this.id = id;
254 }
255
256 public IProvider getProvider() {
257 return provider;
258 }
259
260 public void setProvider(IProvider provider) {
261 this.provider = provider;
262 }
263
264 }
265
266 public Digester getConfigDigester() {
267 return digester;
268 }
269
270 public void loadProvidersConfiguration(IProvidersConfigurator configurator) {
271 Digester digester = new Digester();
272
273 for (Iterator it = providersById.entrySet().iterator(); it.hasNext();) {
274 Map.Entry entry = (Map.Entry) it.next();
275
276 ProviderBean providerBean = (ProviderBean) entry.getValue();
277 IProvider provider = providerBean.getProvider();
278
279 provider.configureRules(digester);
280 }
281
282 if (digester.getRules().rules().isEmpty()) {
283 return;
284 }
285
286 configurator.parseConfiguration(digester);
287 }
288
289 public void startupProviders(FacesContext facesContext) {
290
291 Set started = new HashSet();
292
293 boolean startedProcess = true;
294
295 for (; startedProcess;) {
296 startedProcess = false;
297
298 next_provider: for (Iterator it = providersById.entrySet()
299 .iterator(); it.hasNext();) {
300 Map.Entry entry = (Map.Entry) it.next();
301
302 String providerId = (String) entry.getKey();
303 if (started.contains(providerId)) {
304 continue;
305 }
306
307 ProviderBean providerBean = (ProviderBean) entry.getValue();
308
309 String requirements[] = providerBean.listRequirements();
310 for (int i = 0; i < requirements.length; i++) {
311 String requirement = requirements[i];
312
313 if (providersById.containsKey(requirement) == false) {
314 LOG.error("Invalid dependency provider='" + providerId
315 + "' requires unknown provider '" + requirement
316 + "'.");
317 } else if (started.contains(requirement) == false) {
318 continue next_provider;
319 }
320 }
321
322 startedProcess = true;
323 started.add(providerId);
324
325 IProvider provider = providerBean.getProvider();
326
327 try {
328 LOG.debug("Start provider '" + providerId + "' ...");
329
330 provider.startup(facesContext);
331
332 LOG.debug("Start provider '" + providerId + "' done");
333
334 } catch (Throwable ex) {
335 it.remove();
336
337 LOG.error("Exception when starting up provider '"
338 + providerId + "', remove it !", ex);
339
340
341 }
342 }
343 }
344
345 if (started.size() != providersById.size()) {
346 List l = new ArrayList(providersById.keySet());
347 l.removeAll(started);
348
349 LOG.error("Providers are failed to startup: " + l);
350 }
351 }
352 }