View Javadoc

    1   package org.codehaus.xfire.annotations;
    2
    3   import java.lang.reflect.Method;
    4   import java.util.Map;
    5
    6   import javax.xml.namespace.QName;
    7
    8   import org.codehaus.xfire.annotations.soap.SOAPBindingAnnotation;
    9   import org.codehaus.xfire.service.OperationInfo;
    10  import org.codehaus.xfire.service.Service;
    11  import org.codehaus.xfire.service.ServiceFactory;
    12  import org.codehaus.xfire.service.binding.BindingProvider;
    13  import org.codehaus.xfire.service.binding.ObjectInvoker;
    14  import org.codehaus.xfire.service.binding.ObjectServiceFactory;
    15  import org.codehaus.xfire.soap.SoapConstants;
    16  import org.codehaus.xfire.transport.TransportManager;
    17  import org.codehaus.xfire.util.NamespaceHelper;
    18  import org.codehaus.xfire.util.ClassLoaderUtils;
    19  import org.codehaus.xfire.wsdl11.builder.WSDLBuilderInfo;
    20
    21  /***
    22   * Annotations-bases implementation of the {@link ServiceFactory} interface.
    23   *
    24   * @author Arjen Poutsma
    25   */
    26  public class AnnotationServiceFactory
    27          extends ObjectServiceFactory
    28          implements ServiceFactory
    29  {
    30      private WebAnnotations webAnnotations;
    31
    32      /***
    33       * Initializes a new instance of the <code>AnnotationServiceFactory</code> with the given annotations facade,
    34       * transport manager and type mapping registry.
    35       *
    36       * @param webAnnotations   the annotations facade
    37       * @param transportManager the transport manager
    38       * @param provider         the registry
    39       */
    40      public AnnotationServiceFactory(WebAnnotations webAnnotations,
    41                                      final TransportManager transportManager,
    42                                      final BindingProvider provider)
    43      {
    44          super(transportManager, provider);
    45          this.webAnnotations = webAnnotations;
    46      }
    47
    48      /***
    49       * Creates a service from the specified class. If the class has a
    50       * {@link SOAPBindingAnnotation}, it will be used to define the style and
    51       * use of the service. If the class has a {@link WebServiceAnnotation}, it will be used to
    52       * define the name, service name, target namespace. If the annotation
    53       * defines an endpoint interface, all methods of that interface are exposed
    54       * as operations. If no endpoint interface is defined, all methods that have
    55       * the {@link WebMethodAnnotation} are exposed.
    56       *
    57       * @param clazz
    58       *            The service class used to populate the operations and
    59       *            parameters.
    60       * @return The service.
    61       */
    62      public Service create(final Class clazz, final Map properties)
    63      {
    64          String style = null;
    65          String use = null;
    66
    67          if (webAnnotations.hasSOAPBindingAnnotation(clazz))
    68          {
    69              SOAPBindingAnnotation soapBindingAnnotation = webAnnotations.getSOAPBindingAnnotation(clazz);
    70
    71              style = soapBindingAnnotation.getStyleString();
    72              use =  soapBindingAnnotation.getUseString();
    73          }
    74
    75          if (webAnnotations.hasWebServiceAnnotation(clazz))
    76          {
    77              WebServiceAnnotation webServiceAnnotation = webAnnotations.getWebServiceAnnotation(clazz);
    78
    79              String serviceName = createServiceName(clazz, webServiceAnnotation);
    80
    81              /* Attempt to load the endpoint interface if there is one. If there is an endpoint
    82               * interface the attribute WebService.serviceName is the only valid one for the
    83               * implementing bean class.
    84               */
    85              String tns = null;
    86              String portType = null;
    87              Class endpointInterface = clazz;
    88              if (webServiceAnnotation.getEndpointInterface() != null &&
    89                      webServiceAnnotation.getEndpointInterface().length() != 0)
    90              {
    91                  try
    92                  {
    93                      endpointInterface = loadClass(webServiceAnnotation.getEndpointInterface());
    94                      if (!webAnnotations.hasWebServiceAnnotation(endpointInterface))
    95                      {
    96                          throw new AnnotationException("Endpoint interface " + endpointInterface.getName() +
    97                                                        " does not have a WebService annotation");
    98                      }
    99                      WebServiceAnnotation endpointWSAnnotation =
    100                             webAnnotations.getWebServiceAnnotation(endpointInterface);
    101
    102                     tns = createServiceNamespace(endpointInterface, endpointWSAnnotation);
    103                     portType = createPortType(serviceName, endpointWSAnnotation);
    104                 }
    105                 catch (ClassNotFoundException e)
    106                 {
    107                     throw new AnnotationException("Couldn't find endpoint interface " +
    108                                                   webServiceAnnotation.getEndpointInterface(), e);
    109                 }
    110             }
    111             else
    112             {
    113                 tns = createServiceNamespace(endpointInterface, webServiceAnnotation);
    114                 portType = createPortType(serviceName, webServiceAnnotation);
    115             }
    116
    117             Service service = create(endpointInterface, serviceName, tns, null, style, use, properties);
    118
    119             // Fill in WSDL Builder metadata from annotations.
    120             WSDLBuilderInfo info = new WSDLBuilderInfo(service);
    121             info.setTargetNamespace(tns);
    122             info.setServiceName(serviceName);
    123             info.setPortType(portType);
    124             service.setProperty(WSDLBuilderInfo.KEY, info);
    125
    126             if (clazz != endpointInterface)
    127             {
    128                 service.setProperty(ObjectInvoker.SERVICE_IMPL_CLASS, clazz);
    129             }
    130
    131             return service;
    132         }
    133         else
    134         {
    135             throw new AnnotationException("Class " + clazz.getName() + " does not have a WebService annotation");
    136         }
    137     }
    138
    139     /***
    140      * Attempt to load a class first from this class's ClassLoader, then from the context classloader.
    141      *
    142      * @param endpointInterface
    143      * @return
    144      * @throws ClassNotFoundException
    145      */
    146     protected Class loadClass(String endpointInterface)
    147             throws ClassNotFoundException
    148     {
    149         return ClassLoaderUtils.loadClass(endpointInterface, getClass());
    150     }
    151
    152     protected String createServiceNamespace(Class clazz, WebServiceAnnotation webServiceAnnotation)
    153     {
    154         String ns = null;
    155         if (webServiceAnnotation.getTargetNamespace().length() > 0)
    156         {
    157             ns = webServiceAnnotation.getTargetNamespace();
    158         }
    159         else
    160         {
    161             ns = NamespaceHelper.makeNamespaceFromClassName(clazz.getName(), "http");
    162         }
    163         return ns;
    164     }
    165
    166     protected String createServiceName(Class clazz, WebServiceAnnotation webServiceAnnotation)
    167     {
    168         String name = null;
    169         if (webServiceAnnotation.getServiceName().length() > 0)
    170         {
    171             name = webServiceAnnotation.getServiceName();
    172         }
    173         else
    174         {
    175             name = makeServiceNameFromClassName(clazz);
    176         }
    177         return name;
    178     }
    179
    180     protected String createPortType(String serviceName, WebServiceAnnotation webServiceAnnotation)
    181     {
    182         String portType = null;
    183         if (webServiceAnnotation.getName().length() > 0)
    184         {
    185             portType = webServiceAnnotation.getName();
    186         }
    187         else
    188         {
    189             portType = serviceName + "PortType";
    190         }
    191
    192         return portType;
    193     }
    194
    195     protected String getAction(OperationInfo op)
    196     {
    197         if (webAnnotations.hasWebMethodAnnotation(op.getMethod()))
    198         {
    199             WebMethodAnnotation wma = webAnnotations.getWebMethodAnnotation(op.getMethod());
    200             if (wma.getAction().length() > 0)
    201                 return wma.getAction();
    202         }
    203
    204         return super.getAction(op);
    205     }
    206
    207     /***
    208      * Returns <code>true</code> if the specified method is valid for a SOAP operation.
    209      *
    210      * @param method the method.
    211      * @return <code>true</code> if valid; <code>false</code> otherwise.
    212      */
    213     protected boolean isValidMethod(Method method)
    214     {
    215         if (!super.isValidMethod(method))
    216             return false;
    217
    218         // All methods on endpoint interfaces are valid WebMethods.
    219         if (method.getDeclaringClass().isInterface())
    220             return true;
    221
    222         return webAnnotations.hasWebMethodAnnotation(method);
    223     }
    224
    225     protected boolean isHeader(Method method, int paramNumber)
    226     {
    227         if (paramNumber != -1)
    228         {
    229             if (webAnnotations.hasWebParamAnnotation(method, paramNumber))
    230             {
    231                 final WebParamAnnotation webParamAnnotation =
    232                     webAnnotations.getWebParamAnnotation(method, paramNumber);
    233
    234                 return webParamAnnotation.isHeader();
    235             }
    236         }
    237
    238         return super.isHeader(method, paramNumber);
    239     }
    240
    241     protected QName getInParameterName(Service endpoint, Method method, int paramNumber, boolean doc)
    242     {
    243         if (webAnnotations.hasWebParamAnnotation(method, paramNumber))
    244         {
    245             final WebParamAnnotation webParamAnnotation = webAnnotations.getWebParamAnnotation(method, paramNumber);
    246
    247             String name = webParamAnnotation.getName();
    248             String ns = webParamAnnotation.getTargetNamespace();
    249
    250             if (ns == null || ns.length() == 0)
    251             {
    252                 ns = endpoint.getServiceInfo().getName().getNamespaceURI();
    253             }
    254
    255             return new QName(ns, name);
    256         }
    257         else
    258         {
    259             return super.getInParameterName(endpoint, method, paramNumber, doc);
    260         }
    261     }
    262
    263     protected QName getOutParameterName(Service endpoint, Method method, boolean doc)
    264     {
    265         if (webAnnotations.hasWebResultAnnotation(method))
    266         {
    267             final WebResultAnnotation webResultAnnotation = webAnnotations.getWebResultAnnotation(method);
    268
    269             String name = webResultAnnotation.getName();
    270             String ns = webResultAnnotation.getTargetNamespace();
    271
    272             if (ns == null || ns.length() == 0)
    273             {
    274                 ns = endpoint.getServiceInfo().getName().getNamespaceURI();
    275             }
    276
    277             return new QName(ns, name);
    278         }
    279         else
    280         {
    281             return super.getOutParameterName(endpoint, method, doc);
    282         }
    283     }
    284
    285     protected boolean isAsync(Method method)
    286     {
    287         return webAnnotations.hasOnewayAnnotation(method);
    288     }
    289
    290     protected String getMEP(Method method)
    291     {
    292         if (webAnnotations.hasOnewayAnnotation(method))
    293         {
    294             return SoapConstants.MEP_IN;
    295         }
    296
    297         return super.getMEP(method);
    298     }
    299
    300 }