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", "");
94 String namespace = getElementValue(service, "namespace", "");
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.length() > 0 || namespace.length() > 0)
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
201 Constructor con =
202 clz.getConstructor( new Class[] {TransportManager.class, BindingProvider.class} );
203
204 return (ObjectServiceFactory)
205 con.newInstance(new Object[] { getXFire().getTransportManager(), bindingProvider });
206 }
207 catch (Exception e)
208 {
209 throw new XFireRuntimeException("Could not load service factory: " + serviceFactoryName, e);
210 }
211 }
212 else
213 {
214 factory = new ObjectServiceFactory(getXFire().getTransportManager(), bindingProvider);
215 }
216
217 return factory;
218 }
219
220 protected ObjectServiceFactory getAnnotationServiceFactory(String annotationType,
221 BindingProvider bindingProvider)
222 throws Exception
223 {
224 Class annotsClz = null;
225 Class clz = loadClass("org.codehaus.xfire.annotations.AnnotationServiceFactory");
226
227 if (annotationType.equals("jsr181"))
228 {
229 annotsClz = loadClass("org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations");
230 }
231 else if (annotationType.equals("commons-attributes"))
232 {
233 annotsClz = loadClass("org.codehaus.xfire.annotations.commons.CommonsWebAttributes");
234 }
235
236 Class webAnnot = loadClass("org.codehaus.xfire.annotations.WebAnnotations");
237
238 Constructor con =
239 clz.getConstructor( new Class[] {webAnnot, TransportManager.class, BindingProvider.class} );
240
241 return (ObjectServiceFactory)
242 con.newInstance(new Object[] {annotsClz.newInstance(),
243 getXFire().getTransportManager(),
244 bindingProvider });
245 }
246
247 protected BindingProvider loadBindingProvider(String bindingProviderName)
248 {
249 BindingProvider bindingProvider = null;
250 if (bindingProviderName.length() > 0)
251 {
252 try
253 {
254 bindingProvider = (BindingProvider) loadClass(bindingProviderName).newInstance();
255 }
256 catch (Exception e)
257 {
258 throw new XFireRuntimeException("Could not load binding provider: " + bindingProvider, e);
259 }
260 }
261 return bindingProvider;
262 }
263
264 private List createHandlerPipeline(Element child)
265 throws Exception
266 {
267 if (child == null)
268 return Collections.EMPTY_LIST;
269
270 Elements handlers = child.getChildElements("handler");
271 if (handlers.size() == 0)
272 return Collections.EMPTY_LIST;
273
274 List pipe = new ArrayList();
275
276 for (int i = 0; i < handlers.size(); i++)
277 {
278 pipe.add(getHandler(handlers.get(i).getValue()));
279 }
280
281 return pipe;
282 }
283
284 protected Handler getHandler(String name)
285 throws Exception
286 {
287 return (Handler) loadClass(name).newInstance();
288 }
289
290 public String getElementValue(Element root, String name, String def)
291 {
292 Element child = root.getFirstChildElement(name);
293 if (child != null)
294 {
295 String value = child.getValue();
296 if (value != null && value.length() > 0)
297 return value;
298 }
299
300 return def;
301 }
302
303 /***
304 * Load a class from the class loader.
305 *
306 * @param className
307 * The name of the class.
308 * @return The class.
309 * @throws Exception
310 */
311 protected Class loadClass(String className)
312 throws Exception
313 {
314
315 if (className.endsWith("[]"))
316 {
317 className = "[L" + className.substring(0, className.length() - 2) + ";";
318 }
319
320 return ClassLoaderUtils.loadClass(className, getClass());
321 }
322 }