View Javadoc

    1   package org.codehaus.xfire.service.binding;
    2
    3   import java.lang.reflect.InvocationTargetException;
    4   import java.lang.reflect.Method;
    5   import java.lang.reflect.Modifier;
    6
    7   import org.apache.commons.logging.Log;
    8   import org.apache.commons.logging.LogFactory;
    9   import org.codehaus.xfire.MessageContext;
    10  import org.codehaus.xfire.XFireRuntimeException;
    11  import org.codehaus.xfire.fault.XFireFault;
    12  import org.codehaus.xfire.service.Service;
    13  import org.codehaus.xfire.transport.Session;
    14
    15  /***
    16   * An invoker which instantiates classes automatically based on the Service's scope.
    17   * The default scope is SCOPE_APPLICATION, which creates once instance to use
    18   * for the lifetime of the invoker.
    19   *
    20   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
    21   * @since Nov 16, 2004
    22   */
    23  public class ObjectInvoker
    24          implements Invoker
    25  {
    26      private static final Log logger = LogFactory.getLog(ObjectInvoker.class.getName());
    27
    28      /***
    29       * Scope to denote that a single implementation instance should exist for the lifetime
    30       * of this invoker and should be reused for every request.
    31       */
    32      public final static int SCOPE_APPLICATION = 1;
    33
    34      /***
    35       * Scope to denote that a new instance of the service implementation should be created
    36       * on every call.
    37       */
    38      public final static int SCOPE_REQUEST = 3;
    39
    40      /***
    41       * Scope for storing one object per session. An example of a session implementation is
    42       * an http session, whereby one object is created per session and stored in the session scope.
    43       */
    44      public final static int SCOPE_SESSION = 2;
    45
    46      /***
    47       * Constant to denote the implementation class for the service.
    48       */
    49      public static final String SERVICE_IMPL_CLASS = "xfire.serviceImplClass";
    50
    51      private int scope = ObjectInvoker.SCOPE_APPLICATION;
    52
    53      /***
    54       * The object if the scope is SCOPE_APPLICATION.
    55       */
    56      private Object appObj;
    57
    58      public Object invoke(final Method method, final Object[] params, final MessageContext context)
    59              throws XFireFault
    60      {
    61          try
    62          {
    63              final Object serviceObject = getServiceObject(context);
    64
    65              Object[] newParams = params;
    66              for (int i = 0; i < method.getParameterTypes().length; i++)
    67              {
    68                  if (method.getParameterTypes()[i].equals(MessageContext.class))
    69                  {
    70                      newParams = new Object[params.length+1];
    71
    72                      for (int j = 0; j < newParams.length; j++)
    73                      {
    74                          if (j == i)
    75                          {
    76                              newParams[j] = context;
    77                          }
    78                          else if (j > i)
    79                          {
    80                              newParams[j] = params[j-1];
    81                          }
    82                          else
    83                          {
    84                              newParams[j] = params[j];
    85                          }
    86                      }
    87                  }
    88              }
    89
    90              return method.invoke(serviceObject, newParams);
    91          }
    92          catch (IllegalArgumentException e)
    93          {
    94              throw new XFireFault("Illegal argument.", e, XFireFault.SENDER);
    95          }
    96          catch (InvocationTargetException e)
    97          {
    98              final Throwable t = e.getTargetException();
    99
    100             if (t instanceof XFireFault)
    101             {
    102                 throw (XFireFault) t;
    103             }
    104             else if (t instanceof Exception)
    105             {
    106                 logger.warn("Error invoking service.", t);
    107                 throw new XFireFault(t, XFireFault.SENDER);
    108             }
    109             else
    110             {
    111                 logger.warn("Error invoking service.", e);
    112                 throw new XFireRuntimeException("Error invoking service.", e);
    113             }
    114         }
    115         catch (IllegalAccessException e)
    116         {
    117             throw new XFireFault("Couldn't access service object.", e, XFireFault.RECEIVER);
    118         }
    119     }
    120
    121     /***
    122      * Creates and returns a service object depending on the scope.
    123      */
    124     public Object getServiceObject(final MessageContext context)
    125             throws XFireFault
    126     {
    127         final Service service = context.getService();
    128
    129         if (scope == ObjectInvoker.SCOPE_APPLICATION)
    130         {
    131             if (appObj == null)
    132             {
    133                 synchronized (Service.class)
    134                 {
    135                     appObj = createServiceObject(service);
    136                 }
    137             }
    138             return appObj;
    139         }
    140         else if (scope == ObjectInvoker.SCOPE_SESSION)
    141         {
    142             final Session session = context.getSession();
    143             final String key = "service." + service.getName();
    144
    145             Object sessObj = session.get(key);
    146             if (sessObj == null)
    147             {
    148                 synchronized (Service.class)
    149                 {
    150                     sessObj = createServiceObject(service);
    151                     session.put(key, sessObj);
    152                 }
    153             }
    154             return sessObj;
    155         }
    156         else if (scope == ObjectInvoker.SCOPE_REQUEST)
    157         {
    158             return createServiceObject(service);
    159         }
    160         else
    161         {
    162             throw new UnsupportedOperationException("Scope " + scope + " is invalid.");
    163         }
    164     }
    165
    166     /***
    167      * Override this method to control how XFire creates the service object.
    168      *
    169      * @param service
    170      * @return
    171      * @throws XFireFault
    172      */
    173     public Object createServiceObject(final Service service)
    174             throws XFireFault
    175     {
    176         try
    177         {
    178             Class svcClass = (Class) service.getProperty(ObjectInvoker.SERVICE_IMPL_CLASS);
    179
    180             if (svcClass == null)
    181             {
    182                 svcClass = service.getServiceInfo().getServiceClass();
    183                 if(svcClass.isInterface())
    184                 {
    185                     throw new XFireFault("ObjectInvoker.SERVICE_IMPL_CLASS not set for interface '" + svcClass.getName() + "'", XFireFault.RECEIVER);
    186                 }
    187             }
    188
    189             if(svcClass.isInterface())
    190             {
    191                 throw new XFireFault("Service class '" + svcClass.getName() + "' is an interface", XFireFault.RECEIVER);
    192             }
    193
    194           if(Modifier.isAbstract(svcClass.getModifiers()))
    195           {
    196               throw new XFireFault("Service class '" + svcClass.getName() + "' is abstract", XFireFault.RECEIVER);
    197           }
    198             return svcClass.newInstance();
    199         }
    200         catch (InstantiationException e)
    201         {
    202             throw new XFireFault("Couldn't instantiate service object.", e, XFireFault.RECEIVER);
    203         }
    204         catch (IllegalAccessException e)
    205         {
    206             throw new XFireFault("Couldn't access service object.", e, XFireFault.RECEIVER);
    207         }
    208     }
    209
    210     public int getScope()
    211     {
    212         return scope;
    213     }
    214
    215     public void setScope(int scope)
    216     {
    217         this.scope = scope;
    218     }
    219 }