1 package org.codehaus.xfire.util;
2
3 import java.io.InputStream;
4 import java.lang.reflect.Constructor;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.Collections;
8 import java.util.List;
9
10 import javax.xml.stream.XMLInputFactory;
11 import javax.xml.stream.XMLStreamException;
12 import javax.xml.stream.XMLStreamReader;
13
14 import org.apache.commons.logging.Log;
15 import org.apache.commons.logging.LogFactory;
16 import org.codehaus.xfire.XFire;
17 import org.codehaus.xfire.XFireRuntimeException;
18 import org.codehaus.xfire.handler.Handler;
19 import org.codehaus.xfire.service.Service;
20 import org.codehaus.xfire.service.ServiceRegistry;
21 import org.codehaus.xfire.service.binding.BindingProvider;
22 import org.codehaus.xfire.service.binding.ObjectInvoker;
23 import org.codehaus.xfire.service.binding.ObjectServiceFactory;
24 import org.codehaus.xfire.soap.Soap11;
25 import org.codehaus.xfire.soap.Soap12;
26 import org.codehaus.xfire.soap.SoapVersion;
27 import org.codehaus.xfire.transport.TransportManager;
28 import org.codehaus.yom.Document;
29 import org.codehaus.yom.Element;
30 import org.codehaus.yom.Elements;
31 import org.codehaus.yom.stax.StaxBuilder;
32
33 /***
34 * Builds services from an xml configuration file.
35 *
36 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
37 */
38 public class XMLServiceBuilder
39 {
40 private static final Log log = LogFactory.getLog(XMLServiceBuilder.class);
41
42 private XFire xfire;
43
44 public XMLServiceBuilder(XFire xfire)
45 {
46 this.xfire = xfire;
47 }
48
49 protected XFire getXFire()
50 {
51 return xfire;
52 }
53
54 public Collection buildServices(InputStream stream)
55 throws Exception
56 {
57 try
58 {
59 XMLInputFactory ifactory = XMLInputFactory.newInstance();
60 XMLStreamReader reader = ifactory.createXMLStreamReader(stream);
61 StaxBuilder builder = new StaxBuilder();
62 Document doc = builder.build(reader);
63 Element root = doc.getRootElement();
64
65 List serviceList = new ArrayList();
66 Elements contents = root.getChildElements();
67 for (int i = 0; i < contents.size(); i++)
68 {
69 Element element = contents.get(i);
70 Elements services = element.getChildElements();
71 for (int n = 0; n < services.size(); n++)
72 {
73 Element service = services.get(n);
74
75 serviceList.add(loadService(service));
76 }
77 }
78 return serviceList;
79 }
80 catch (XMLStreamException e1)
81 {
82 log.error("Could not parse META-INF/xfire/services.xml!", e1);
83 throw e1;
84 }
85 }
86
87 protected Service loadService(Element service)
88 throws Exception
89 {
90 ServiceRegistry registry = getXFire().getServiceRegistry();
91
92 String name = getElementValue(service, "name", null);
93 String namespace = getElementValue(service, "namespace", null);
94 String style = getElementValue(service, "style", "");
95 String use = getElementValue(service, "use", "");
96 String serviceClass = getElementValue(service, "serviceClass", "");
97 String implClassName = getElementValue(service, "implementationClass", "");
98 String bindingProviderName = getElementValue(service, "bindingProvider", "");
99
100 String soapVersionValue = getElementValue(service, "soapVersion", "1.1");
101 SoapVersion soapVersion;
102 if (soapVersionValue.equals("1.2"))
103 {
104 soapVersion = Soap12.getInstance();
105 }
106 else
107 {
108 soapVersion = Soap11.getInstance();
109 }
110
111 Class clazz = null;
112 try
113 {
114 clazz = loadClass(serviceClass);
115 }
116 catch (Exception e)
117 {
118 throw new XFireRuntimeException("Could not load service class: " + serviceClass, e);
119 }
120
121 BindingProvider bindingProvider = loadBindingProvider(bindingProviderName);
122
123 String serviceFactory = getElementValue(service, "serviceFactory", "");
124 ObjectServiceFactory factory;
125 if (serviceFactory.equals("jsr181") || serviceFactory.equals("commons-attributes"))
126 factory = getAnnotationServiceFactory(serviceFactory, bindingProvider);
127 else
128 factory = loadServiceFactory(bindingProvider, serviceFactory);
129
130 if (style.length() > 0) factory.setStyle(style);
131 if (use.length() > 0) factory.setUse(use);
132
133 factory.setSoapVersion(soapVersion);
134
135 Service svc = null;
136 if (name != null || namespace != null)
137 {
138 svc = factory.create(clazz, name, namespace, null);
139 }
140 else
141 {
142 svc = factory.create(clazz);
143 }
144
145 if (implClassName.length() > 0)
146 {
147 Class implClazz = null;
148 try
149 {
150 implClazz = loadClass(implClassName);
151 }
152 catch (Exception e)
153 {
154 throw new XFireRuntimeException("Could not load implementation class: " + serviceClass, e);
155 }
156
157 svc.setProperty(ObjectInvoker.SERVICE_IMPL_CLASS, implClazz);
158
159 if (log.isInfoEnabled())
160 {
161 log.info("Created Service " + name + " with impl " + implClazz
162 + ", soap version: " + soapVersionValue + ", style: " + style + ", use: "
163 + use + ", namespace " + svc.getServiceInfo().getName().getNamespaceURI());
164 }
165 }
166 else
167 {
168 if (log.isInfoEnabled())
169 {
170 log.info("Created Service " + name + " with impl " + clazz
171 + ", soap version: " + soapVersionValue + ", style: " + style + ", use: "
172 + use + ", namespace " + svc.getServiceInfo().getName().getNamespaceURI());
173 }
174 }
175
176 if (svc.getInHandlers() == null) svc.setInHandlers(new ArrayList());
177 if (svc.getOutHandlers() == null) svc.setOutHandlers(new ArrayList());
178 if (svc.getFaultHandlers() == null) svc.setFaultHandlers(new ArrayList());
179
180 svc.getInHandlers().addAll(createHandlerPipeline(service.getFirstChildElement("inHandlers")));
181 svc.getOutHandlers().addAll(createHandlerPipeline(service.getFirstChildElement("outHandlers")));
182 svc.getFaultHandlers().addAll(createHandlerPipeline(service.getFirstChildElement("faultHandlers")));
183
184 registry.register(svc);
185
186 return svc;
187 }
188
189 protected ObjectServiceFactory loadServiceFactory(BindingProvider bindingProvider,
190 String serviceFactoryName)
191 {
192 ObjectServiceFactory factory = null;
193 if (serviceFactoryName.length() > 0)
194 {
195
196 try
197 {
198 Class clz = loadClass(serviceFactoryName);
199 TransportManager tman = getXFire().getTransportManager();
200
201 Constructor con = null;
202 Object[] arguments = null;
203
204 try
205 {
206 con = clz.getConstructor( new Class[] {TransportManager.class, BindingProvider.class} );
207 arguments = new Object[] { tman, bindingProvider };
208 }
209 catch (NoSuchMethodException e)
210 {
211 try
212 {
213 con = clz.getConstructor( new Class[] {TransportManager.class} );
214 arguments = new Object[] { tman };
215 }
216 catch (NoSuchMethodException e1)
217 {
218 con = clz.getConstructor( new Class[0] );
219 arguments = new Object[0];
220 }
221 }
222
223 return (ObjectServiceFactory) con.newInstance(arguments);
224 }
225 catch (Exception e)
226 {
227 throw new XFireRuntimeException("Could not load service factory: " + serviceFactoryName, e);
228 }
229 }
230 else
231 {
232 factory = new ObjectServiceFactory(getXFire().getTransportManager(), bindingProvider);
233 }
234
235 return factory;
236 }
237
238 protected ObjectServiceFactory getAnnotationServiceFactory(String annotationType,
239 BindingProvider bindingProvider)
240 throws Exception
241 {
242 Class annotsClz = null;
243 Class clz = loadClass("org.codehaus.xfire.annotations.AnnotationServiceFactory");
244
245 if (annotationType.equals("jsr181"))
246 {
247 annotsClz = loadClass("org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations");
248 }
249 else if (annotationType.equals("commons-attributes"))
250 {
251 annotsClz = loadClass("org.codehaus.xfire.annotations.commons.CommonsWebAttributes");
252 }
253
254 Class webAnnot = loadClass("org.codehaus.xfire.annotations.WebAnnotations");
255
256 Constructor con =
257 clz.getConstructor( new Class[] {webAnnot, TransportManager.class, BindingProvider.class} );
258
259 return (ObjectServiceFactory)
260 con.newInstance(new Object[] {annotsClz.newInstance(),
261 getXFire().getTransportManager(),
262 bindingProvider });
263 }
264
265 protected BindingProvider loadBindingProvider(String bindingProviderName)
266 {
267 BindingProvider bindingProvider = null;
268 if (bindingProviderName.length() > 0)
269 {
270 try
271 {
272 bindingProvider = (BindingProvider) loadClass(bindingProviderName).newInstance();
273 }
274 catch (Exception e)
275 {
276 throw new XFireRuntimeException("Could not load binding provider: " + bindingProvider, e);
277 }
278 }
279 return bindingProvider;
280 }
281
282 private List createHandlerPipeline(Element child)
283 throws Exception
284 {
285 if (child == null)
286 return Collections.EMPTY_LIST;
287
288 Elements handlers = child.getChildElements("handler");
289 if (handlers.size() == 0)
290 return Collections.EMPTY_LIST;
291
292 List pipe = new ArrayList();
293
294 for (int i = 0; i < handlers.size(); i++)
295 {
296 pipe.add(getHandler(handlers.get(i).getValue()));
297 }
298
299 return pipe;
300 }
301
302 protected Handler getHandler(String name)
303 throws Exception
304 {
305 return (Handler) loadClass(name).newInstance();
306 }
307
308 public String getElementValue(Element root, String name, String def)
309 {
310 Element child = root.getFirstChildElement(name);
311 if (child != null)
312 {
313 String value = child.getValue();
314 if (value != null && value.length() > 0)
315 return value;
316 }
317
318 return def;
319 }
320
321 /***
322 * Load a class from the class loader.
323 *
324 * @param className
325 * The name of the class.
326 * @return The class.
327 * @throws Exception
328 */
329 protected Class loadClass(String className)
330 throws Exception
331 {
332
333 if (className.endsWith("[]"))
334 {
335 className = "[L" + className.substring(0, className.length() - 2) + ";";
336 }
337
338 return ClassLoaderUtils.loadClass(className, getClass());
339 }
340 }