1 package org.codehaus.xfire.service.object;
2
3 import java.lang.reflect.InvocationTargetException;
4 import java.lang.reflect.Method;
5
6 import org.apache.commons.logging.Log;
7 import org.apache.commons.logging.LogFactory;
8
9 import org.codehaus.xfire.MessageContext;
10 import org.codehaus.xfire.XFireRuntimeException;
11 import org.codehaus.xfire.fault.XFireFault;
12 import org.codehaus.xfire.transport.Session;
13
14 /***
15 * An invoker which instantiates classes automatically based on the Service's
16 * scope.
17 *
18 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
19 * @since Nov 16, 2004
20 */
21 public class ObjectInvoker implements Invoker
22 {
23 private static final Log logger = LogFactory.getLog( ObjectInvoker.class.getName() );
24
25 /***
26 * The object if the scope is SCOPE_APPLICATION.
27 */
28 private Object appObj;
29
30 public Object invoke( final Method method, final Object[] params, final MessageContext context )
31 throws XFireFault
32 {
33 try
34 {
35 final Object serviceObject = getServiceObject( context );
36
37 return method.invoke( serviceObject, params );
38 }
39 catch( IllegalArgumentException e )
40 {
41 throw new XFireFault( "Illegal argument.", e, XFireFault.SENDER );
42 }
43 catch( InvocationTargetException e )
44 {
45 final Throwable t = e.getTargetException();
46
47 if( t instanceof XFireFault )
48 {
49 throw (XFireFault)t;
50 }
51 else if( t instanceof Exception )
52 {
53 logger.warn( "Error invoking service.", t );
54 throw new XFireFault( t, XFireFault.SENDER );
55 }
56 else
57 {
58 logger.warn( "Error invoking service.", e );
59 throw new XFireRuntimeException( "Error invoking service.", e );
60 }
61 }
62 catch( IllegalAccessException e )
63 {
64 throw new XFireFault( "Couldn't access service object.", e, XFireFault.RECEIVER );
65 }
66 }
67
68 /***
69 * Creates and returns a service object depending on the scope.
70 */
71 public Object getServiceObject( final MessageContext context )
72 throws XFireFault
73 {
74 final ObjectService service = (ObjectService)context.getService();
75 final int scope = service.getScope();
76 if( scope == ObjectService.SCOPE_APPLICATION )
77 {
78 if( appObj == null )
79 {
80 synchronized( DefaultObjectService.class )
81 {
82 appObj = createServiceObject( service );
83 }
84 }
85 return appObj;
86 }
87 else if( scope == ObjectService.SCOPE_SESSION )
88 {
89 final Session session = context.getSession();
90 final String key = "service." + service.getName();
91
92 Object sessObj = session.get( key );
93 if( sessObj == null )
94 {
95 synchronized( DefaultObjectService.class )
96 {
97 sessObj = createServiceObject( service );
98 session.put( key, sessObj );
99 }
100 }
101 return sessObj;
102 }
103 else if( scope == ObjectService.SCOPE_REQUEST )
104 {
105 return createServiceObject( service );
106 }
107 else
108 {
109 throw new UnsupportedOperationException( "Scope " + scope + " is invalid." );
110 }
111 }
112
113 /***
114 * Override this method to control how XFire creates the service object.
115 * @param service
116 * @return
117 * @throws XFireFault
118 */
119 public Object createServiceObject( final ObjectService service ) throws XFireFault
120 {
121 try
122 {
123 Class svcClass = (Class) service.getProperty(ObjectService.SERVICE_IMPL_CLASS);
124
125 if (svcClass == null)
126 {
127 svcClass = service.getServiceClass();
128 }
129
130 return svcClass.newInstance();
131 }
132 catch( InstantiationException e )
133 {
134 throw new XFireFault( "Couldn't instantiate service object.", e, XFireFault.RECEIVER );
135 }
136 catch( IllegalAccessException e )
137 {
138 throw new XFireFault( "Couldn't access service object.", e, XFireFault.RECEIVER );
139 }
140 }
141 }