1 package org.codehaus.xfire.java;
2
3 import java.lang.reflect.Method;
4 import java.lang.reflect.Modifier;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.Hashtable;
8 import java.util.List;
9
10 import org.codehaus.xfire.MessageContext;
11 import org.codehaus.xfire.SOAPConstants;
12 import org.codehaus.xfire.fault.XFireFault;
13 import org.codehaus.xfire.java.mapping.TypeMapping;
14 import org.codehaus.xfire.java.mapping.TypeMappingRegistry;
15 import org.codehaus.xfire.service.SimpleService;
16 import org.codehaus.xfire.session.Session;
17
18 /***
19 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
20 */
21 public class DefaultJavaService
22 extends SimpleService
23 implements JavaService
24 {
25 private TypeMappingRegistry typeMappingRegistry;
26
27 private TypeMapping typeMapping;
28
29 private List allowedMethods;
30
31 private Class serviceClass;
32
33 private Hashtable operations;
34
35 protected static final String SERVICE_CLASS = "serviceClass";
36
37 protected static final String ALLOWED_METHODS= "allowedMethods";
38
39 private boolean autoTyped = false;
40
41 private int scope = JavaService.SCOPE_APPLICATION;
42
43 /*** The object if the scope is APPLICATION. */
44 private Object appObj;
45
46 public DefaultJavaService()
47 {
48 super();
49 allowedMethods = new ArrayList();
50 operations = new Hashtable();
51 }
52
53 /***
54 * @param className
55 * @param string
56 */
57 public void setServiceClass( String className )
58 throws ClassNotFoundException
59 {
60 serviceClass = getClass().getClassLoader().loadClass( className );
61
62 initializeOperations();
63 }
64
65 /***
66 * @param serviceClass2
67 */
68 private void initializeOperations()
69 {
70 Method[] methods = serviceClass.getDeclaredMethods();
71
72
73
74 for ( int i = 0; i < methods.length; i++ )
75 {
76 Method method = methods[i];
77
78 String methodName = method.getName();
79
80 int modifiers = method.getModifiers();
81 if ( isAllowed( methodName )
82 &&
83 Modifier.isPublic(modifiers)
84 &&
85 !Modifier.isStatic(modifiers) )
86 {
87 addOperation( method );
88 }
89 }
90 }
91
92 /***
93 * @param i
94 * @param method
95 * @param methodName
96 */
97 private void addOperation( Method method )
98 {
99 Operation op = new Operation(method, this);
100
101 operations.put( method.getName(), op );
102 }
103
104 /***
105 * Determines whether or not to expose the specified method.
106 *
107 * @param methodName
108 * @return
109 */
110 private boolean isAllowed(String methodName)
111 {
112 return ( allowedMethods.size() == 0 || allowedMethods.contains(methodName) );
113 }
114
115 /***
116 * @see org.codehaus.xfire.java.JavaService#getOperation(java.lang.String, java.lang.String)
117 */
118 public Operation getOperation( String localName, String namespace )
119 {
120 return (Operation) operations.get( localName );
121 }
122
123 /***
124 * @see org.codehaus.xfire.java.JavaService#getOperations()
125 */
126 public Collection getOperations()
127 {
128 return operations.values();
129 }
130
131 /***
132 * @return Returns the allowedMethods.
133 */
134 public List getAllowedMethods()
135 {
136 return allowedMethods;
137 }
138
139 /***
140 * @param allowedMethods The allowedMethods to set.
141 */
142 public void setAllowedMethods(List allowedMethods)
143 {
144 this.allowedMethods = allowedMethods;
145 }
146
147 /***
148 * @return Returns the typeMapping.
149 */
150 public TypeMapping getTypeMapping()
151 {
152 return typeMapping;
153 }
154
155 /***
156 * @param typeMapping The typeMapping to set.
157 */
158 public void setTypeMapping(TypeMapping typeMapping)
159 {
160 this.typeMapping = typeMapping;
161 }
162
163 /***
164 * @return
165 */
166 public Class getServiceClass()
167 {
168 return serviceClass;
169 }
170
171 /***
172 * Load a class from the class loader.
173 *
174 * @param className The name of the class.
175 * @return The class.
176 * @throws Exception
177 */
178 protected Class loadClass( String className )
179 throws Exception
180 {
181
182 if ( className.endsWith("[]") )
183 {
184 className = "[L" + className.substring(0, className.length() - 2 ) + ";";
185 }
186
187 return getClass().getClassLoader().loadClass( className );
188 }
189
190 /***
191 * @see org.apache.avalon.framework.activity.Initializable#initialize()
192 */
193 public void initialize() throws Exception
194 {
195 TypeMapping tm = null;
196
197
198 if ( getUse() != null )
199 {
200 if ( getUse().equals(SOAPConstants.USE_ECNODED) )
201 {
202 tm = getTypeMappingRegistry().createTypeMapping( SOAPConstants.SOAP11_ENCODED, autoTyped );
203 }
204 else
205 {
206 tm = getTypeMappingRegistry().createTypeMapping( SOAPConstants.XSD, autoTyped );
207 }
208 setTypeMapping( tm );
209 getTypeMappingRegistry().register( getDefaultNamespace(), tm );
210 }
211 }
212
213 /***
214 * Creates and returns a service object depending on the
215 * scope.
216 */
217 public Object getServiceObject(MessageContext context)
218 throws XFireFault
219 {
220 if ( scope == JavaService.SCOPE_APPLICATION )
221 {
222 if ( appObj == null )
223 {
224 synchronized( DefaultJavaService.class )
225 {
226 appObj = createServiceObject();
227 }
228 }
229 return appObj;
230 }
231 else if ( scope == JavaService.SCOPE_SESSION )
232 {
233 Session session = context.getSession();
234 String key = "service."+getName();
235
236 Object sessObj = session.get(key);
237 if ( sessObj == null )
238 {
239 synchronized( DefaultJavaService.class )
240 {
241 sessObj = createServiceObject();
242 session.put(key, sessObj);
243 }
244 }
245 return sessObj;
246 }
247 else if ( scope == JavaService.SCOPE_REQUEST )
248 {
249 return createServiceObject();
250 }
251 else
252 {
253 throw new UnsupportedOperationException("Scope " + scope + " is invalid.");
254 }
255 }
256
257 public Object createServiceObject() throws XFireFault
258 {
259 try
260 {
261 return getServiceClass().newInstance();
262 }
263 catch (InstantiationException e)
264 {
265 throw new XFireFault( "Couldn't instantiate service object.", e, XFireFault.RECEIVER );
266 }
267 catch (IllegalAccessException e)
268 {
269 throw new XFireFault( "Couldn't access service object.", e, XFireFault.RECEIVER );
270 }
271 }
272
273 public boolean isAutoTyped()
274 {
275 return autoTyped;
276 }
277
278 public void setAutoTyped(boolean autoTyped)
279 {
280 this.autoTyped = autoTyped;
281 }
282
283 public TypeMappingRegistry getTypeMappingRegistry()
284 {
285 return typeMappingRegistry;
286 }
287
288 public void setTypeMappingRegistry(TypeMappingRegistry typeMappingRegistry)
289 {
290 this.typeMappingRegistry = typeMappingRegistry;
291 }
292
293 public int getScope()
294 {
295 return scope;
296 }
297
298 public void setScope(int scope)
299 {
300 this.scope = scope;
301 }
302 }