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