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", "");
    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             // Attempt to load a ServiceFactory for the user.
    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         // Handle array'd types.
    315         if (className.endsWith("[]"))
    316         {
    317             className = "[L" + className.substring(0, className.length() - 2) + ";";
    318         }
    319
    320         return ClassLoaderUtils.loadClass(className, getClass());
    321     }
    322 }