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 TransportManager tman = getXFire().getTransportManager();
92
93 String name = getElementValue(service, "name", null);
94 String namespace = getElementValue(service, "namespace", null);
95 String style = getElementValue(service, "style", "");
96 String use = getElementValue(service, "use", "");
97 String serviceClass = getElementValue(service, "serviceClass", "");
98 String implClassName = getElementValue(service, "implementationClass", "");
99 String bindingProviderName = getElementValue(service, "bindingProvider", "");
100
101 String soapVersionValue = getElementValue(service, "soapVersion", "1.1");
102 SoapVersion soapVersion;
103 if (soapVersionValue.equals("1.2"))
104 {
105 soapVersion = Soap12.getInstance();
106 }
107 else
108 {
109 soapVersion = Soap11.getInstance();
110 }
111
112 Class clazz = null;
113 try
114 {
115 clazz = loadClass(serviceClass);
116 }
117 catch (Exception e)
118 {
119 throw new XFireRuntimeException("Could not load service class: " + serviceClass, e);
120 }
121
122 BindingProvider bindingProvider = loadBindingProvider(bindingProviderName);
123
124 String serviceFactory = getElementValue(service, "serviceFactory", "");
125 ObjectServiceFactory factory;
126 if (serviceFactory.equals("jsr181") || serviceFactory.equals("commons-attributes"))
127 factory = getAnnotationServiceFactory(serviceFactory, bindingProvider);
128 else
129 factory = loadServiceFactory(bindingProvider, serviceFactory);
130
131 if (style.length() > 0) factory.setStyle(style);
132 if (use.length() > 0) factory.setUse(use);
133
134 factory.setSoapVersion(soapVersion);
135
136 Service svc = null;
137 if (name != null || namespace != null)
138 {
139 svc = factory.create(clazz, name, namespace, null);
140 }
141 else
142 {
143 svc = factory.create(clazz);
144 }
145
146 if (implClassName.length() > 0)
147 {
148 Class implClazz = null;
149 try
150 {
151 implClazz = loadClass(implClassName);
152 }
153 catch (Exception e)
154 {
155 throw new XFireRuntimeException("Could not load implementation class: " + serviceClass, e);
156 }
157
158 svc.setProperty(ObjectInvoker.SERVICE_IMPL_CLASS, implClazz);
159
160 if (log.isInfoEnabled())
161 {
162 log.info("Created Service " + name + " with impl " + implClazz
163 + ", soap version: " + soapVersionValue + ", style: " + style + ", use: "
164 + use + ", namespace " + svc.getServiceInfo().getName().getNamespaceURI());
165 }
166 }
167 else
168 {
169 if (log.isInfoEnabled())
170 {
171 log.info("Created Service " + name + " with impl " + clazz
172 + ", soap version: " + soapVersionValue + ", style: " + style + ", use: "
173 + use + ", namespace " + svc.getServiceInfo().getName().getNamespaceURI());
174 }
175 }
176
177 if (svc.getInHandlers() == null) svc.setInHandlers(new ArrayList());
178 if (svc.getOutHandlers() == null) svc.setOutHandlers(new ArrayList());
179 if (svc.getFaultHandlers() == null) svc.setFaultHandlers(new ArrayList());
180
181 svc.getInHandlers().addAll(createHandlerPipeline(service.getFirstChildElement("inHandlers")));
182 svc.getOutHandlers().addAll(createHandlerPipeline(service.getFirstChildElement("outHandlers")));
183 svc.getFaultHandlers().addAll(createHandlerPipeline(service.getFirstChildElement("faultHandlers")));
184
185 registry.register(svc);
186
187 return svc;
188 }
189
190 protected ObjectServiceFactory loadServiceFactory(BindingProvider bindingProvider,
191 String serviceFactoryName)
192 {
193 ObjectServiceFactory factory = null;
194 if (serviceFactoryName.length() > 0)
195 {
196
197 try
198 {
199 Class clz = loadClass(serviceFactoryName);
200 TransportManager tman = getXFire().getTransportManager();
201
202 Constructor con = null;
203 Object[] arguments = null;
204
205 try
206 {
207 con = clz.getConstructor( new Class[] {TransportManager.class, BindingProvider.class} );
208 arguments = new Object[] { tman, bindingProvider };
209 }
210 catch (NoSuchMethodException e)
211 {
212 try
213 {
214 con = clz.getConstructor( new Class[] {TransportManager.class} );
215 arguments = new Object[] { tman };
216 }
217 catch (NoSuchMethodException e1)
218 {
219 con = clz.getConstructor( new Class[0] );
220 arguments = new Object[0];
221 }
222 }
223
224 return (ObjectServiceFactory) con.newInstance(arguments);
225 }
226 catch (Exception e)
227 {
228 throw new XFireRuntimeException("Could not load service factory: " + serviceFactoryName, e);
229 }
230 }
231 else
232 {
233 factory = new ObjectServiceFactory(getXFire().getTransportManager(), bindingProvider);
234 }
235
236 return factory;
237 }
238
239 protected ObjectServiceFactory getAnnotationServiceFactory(String annotationType,
240 BindingProvider bindingProvider)
241 throws Exception
242 {
243 Class annotsClz = null;
244 Class clz = loadClass("org.codehaus.xfire.annotations.AnnotationServiceFactory");
245
246 if (annotationType.equals("jsr181"))
247 {
248 annotsClz = loadClass("org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations");
249 }
250 else if (annotationType.equals("commons-attributes"))
251 {
252 annotsClz = loadClass("org.codehaus.xfire.annotations.commons.CommonsWebAttributes");
253 }
254
255 Class webAnnot = loadClass("org.codehaus.xfire.annotations.WebAnnotations");
256
257 Constructor con =
258 clz.getConstructor( new Class[] {webAnnot, TransportManager.class, BindingProvider.class} );
259
260 return (ObjectServiceFactory)
261 con.newInstance(new Object[] {annotsClz.newInstance(),
262 getXFire().getTransportManager(),
263 bindingProvider });
264 }
265
266 protected BindingProvider loadBindingProvider(String bindingProviderName)
267 {
268 BindingProvider bindingProvider = null;
269 if (bindingProviderName.length() > 0)
270 {
271 try
272 {
273 bindingProvider = (BindingProvider) loadClass(bindingProviderName).newInstance();
274 }
275 catch (Exception e)
276 {
277 throw new XFireRuntimeException("Could not load binding provider: " + bindingProvider, e);
278 }
279 }
280 return bindingProvider;
281 }
282
283 private List createHandlerPipeline(Element child)
284 throws Exception
285 {
286 if (child == null)
287 return Collections.EMPTY_LIST;
288
289 Elements handlers = child.getChildElements("handler");
290 if (handlers.size() == 0)
291 return Collections.EMPTY_LIST;
292
293 List pipe = new ArrayList();
294
295 for (int i = 0; i < handlers.size(); i++)
296 {
297 pipe.add(getHandler(handlers.get(i).getValue()));
298 }
299
300 return pipe;
301 }
302
303 protected Handler getHandler(String name)
304 throws Exception
305 {
306 return (Handler) loadClass(name).newInstance();
307 }
308
309 public String getElementValue(Element root, String name, String def)
310 {
311 Element child = root.getFirstChildElement(name);
312 if (child != null)
313 {
314 String value = child.getValue();
315 if (value != null && value.length() > 0)
316 return value;
317 }
318
319 return def;
320 }
321
322 /***
323 * Load a class from the class loader.
324 *
325 * @param className
326 * The name of the class.
327 * @return The class.
328 * @throws Exception
329 */
330 protected Class loadClass(String className)
331 throws Exception
332 {
333
334 if (className.endsWith("[]"))
335 {
336 className = "[L" + className.substring(0, className.length() - 2) + ";";
337 }
338
339 return ClassLoaderUtils.loadClass(className, getClass());
340 }
341 }