View Javadoc

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             // Attempt to load a ServiceFactory for the user.
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         // Handle array'd types.
334         if (className.endsWith("[]"))
335         {
336             className = "[L" + className.substring(0, className.length() - 2) + ";";
337         }
338 
339         return ClassLoaderUtils.loadClass(className, getClass());
340     }
341 }