1
2
3
4 package org.rcfaces.core.internal;
5
6 import java.io.CharArrayReader;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.net.URL;
10 import java.util.Enumeration;
11 import java.util.HashMap;
12 import java.util.Map;
13
14 import org.apache.commons.digester.Digester;
15 import org.apache.commons.digester.Rule;
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.xml.sax.Attributes;
19 import org.xml.sax.EntityResolver;
20 import org.xml.sax.InputSource;
21 import org.xml.sax.SAXException;
22
23
24
25
26
27
28 public class Services {
29 private static final String REVISION = "$Revision: 1.1 $";
30
31 private static final Log LOG = LogFactory.getLog(Services.class);
32
33 private static final Services SINGLETON = new Services();
34
35 private static final String RESOURCE_NAME = "META-INF/rcfaces-services.xml";
36
37 private boolean servicesLoaded = false;
38
39 private final Map services = new HashMap(32);
40
41 public static Services get() {
42 return SINGLETON;
43 }
44
45 private Services() {
46 }
47
48 public Object getService(String id) {
49 synchronized (services) {
50 if (servicesLoaded == false) {
51 servicesLoaded = true;
52
53 loadServices();
54 }
55 }
56
57 Object service = services.get(id);
58
59 if (LOG.isDebugEnabled()) {
60 LOG.debug("Service '" + id + "' => " + service);
61 }
62
63 return service;
64 }
65
66 private void loadServices() {
67 LOG.info("Load services ...");
68
69 ClassLoader threadClassLoader = Thread.currentThread()
70 .getContextClassLoader();
71
72 ClassLoader classLoader = Services.class.getClassLoader();
73
74 if (threadClassLoader != null) {
75 loadServices(threadClassLoader);
76 }
77
78 if (classLoader != threadClassLoader) {
79 loadServices(classLoader);
80 }
81
82 LOG.info(services.size() + " service(s) loaded.");
83 }
84
85 private void loadServices(ClassLoader classLoader) {
86 LOG.info("Load services using '" + classLoader + "'");
87
88 Enumeration enumeration;
89 try {
90 enumeration = classLoader.getResources(RESOURCE_NAME);
91
92 } catch (IOException ex) {
93 LOG.error("Can not get Resources '" + RESOURCE_NAME + "'.", ex);
94 return;
95 }
96
97 for (; enumeration.hasMoreElements();) {
98 URL url = (URL) enumeration.nextElement();
99
100 loadService(classLoader, url);
101 }
102 }
103
104 private void loadService(final ClassLoader classLoader, URL url) {
105 LOG.info("Load service '" + url + "'");
106
107 Digester digester = new Digester();
108 digester.setUseContextClassLoader(true);
109
110 digester.setEntityResolver(new EntityResolver() {
111 private static final String REVISION = "$Revision: 1.1 $";
112
113 public InputSource resolveEntity(String string, String string1) {
114 return new InputSource(new CharArrayReader(new char[0]));
115 }
116
117 });
118
119 digester.addRule("rcfaces-services/service", new Rule() {
120 private static final String REVISION = "$Revision: 1.1 $";
121
122 public void begin(String namespace, String name,
123 Attributes attributes) throws Exception {
124
125 super.digester.push(new Service());
126 }
127
128 public void end(String namespace, String name) throws Exception {
129 Service service = (Service) super.digester.pop();
130
131 LOG.debug("Load service '" + service.getId() + "' className='"
132 + service.getClassName() + "'");
133
134 if (service.getClassName() == null) {
135 return;
136 }
137
138 Class clazz;
139 try {
140 clazz = classLoader.loadClass(service.getClassName());
141
142 } catch (Exception ex) {
143 LOG.error("Can not load class '" + service.getClassName()
144 + "'.", ex);
145 return;
146 }
147
148 Object serviceObject;
149 try {
150 serviceObject = clazz.newInstance();
151
152 } catch (Exception ex) {
153 LOG.error("Can not instanciate class '" + clazz + "'.", ex);
154 return;
155 }
156
157 services.put(service.getId(), serviceObject);
158
159 LOG.info("Service '" + service.getId() + "' loaded: "
160 + serviceObject);
161 }
162 });
163
164 digester.addBeanPropertySetter("rcfaces-services/service/service-id",
165 "id");
166
167 digester.addBeanPropertySetter(
168 "rcfaces-services/service/service-class", "className");
169
170 InputStream ins;
171 try {
172 ins = url.openStream();
173
174 } catch (IOException ex) {
175 LOG.error("Can not open stream from '" + url + "'.", ex);
176 return;
177 }
178
179 if (ins == null) {
180 LOG.info("Can not open stream from '" + url + "'.");
181 return;
182 }
183
184 try {
185 try {
186
187 digester.parse(ins);
188
189 } finally {
190 ins.close();
191 }
192 } catch (IOException ex) {
193 LOG.error("Can not load stream from '" + url + "'.", ex);
194
195 } catch (SAXException ex) {
196 LOG.error("Invalid XML resource '" + url + "'.", ex);
197 }
198 }
199
200
201
202
203
204
205 public static class Service {
206 private String id;
207
208 private String className;
209
210 public final String getId() {
211 return id;
212 }
213
214 public final void setId(String id) {
215 this.id = id;
216 }
217
218 public final String getClassName() {
219 return className;
220 }
221
222 public final void setClassName(String className) {
223 this.className = className;
224 }
225
226 }
227 }