View Javadoc

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          // TODO: go through superclasses, stopping at Object.class
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         // Handle array'd types.
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         // If we are a enocded, use the encoded type mapping, else just use XSD
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 }