1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.wotonomy.web;
20
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23
24 import javax.servlet.http.HttpSession;
25
26 import net.wotonomy.foundation.NSArray;
27 import net.wotonomy.foundation.NSSelector;
28 import net.wotonomy.foundation.internal.Introspector;
29 import net.wotonomy.foundation.internal.ValueConverter;
30
31 /***
32 * A pure java implementation of WODirectAction.
33 * This class provides a number of services to subclasses,
34 * including access to the query parameters, the request,
35 * the session, and logging and debugging facilities.
36 * A new instance of the class is created and then destroyed
37 * for every request-response cycle.<br><br>
38 *
39 * Subclass this to implement direct actions for your
40 * application. Subclasses would typically override the
41 * constructor to initialize state based on the request,
42 * and then provide additional methods that would be invoked
43 * based on the value at the end of the URI. <br><br>
44 *
45 * Example: "http://www/MyApp.woa/MyActions/search" would call
46 * the method named "searchAction" on the DirectAction subclass
47 * named "MyActions". If the subclass name is omitted, a subclass
48 * named "DirectAction" is assumed to exist within the application.
49 *
50 * @author michael@mpowers.net
51 * @author $Author: cgruber $
52 * @version $Revision: 905 $
53 */
54 public class WODirectAction
55 {
56 private WORequest request;
57 WOContext context;
58
59 /***
60 * Default constructor. This is called implicitly by
61 * subclasses in all cases. Package access only.
62 */
63 WODirectAction ()
64 {
65
66 }
67
68 /***
69 * Request constructor. This is the constructor used
70 * to create an action in response to a user request.
71 * Override to perform any necessary initialization in
72 * your subclass.
73 */
74 public WODirectAction (WORequest aRequest)
75 {
76 this();
77 request = aRequest;
78 }
79
80 /***
81 * Returns the response from the component named "Main".
82 */
83 public WOActionResults defaultAction()
84 {
85 return pageWithName("Main").generateResponse();
86 }
87
88 /***
89 * Returns the WORequest object for the current request.
90 */
91 public WORequest request ()
92 {
93 return request;
94 }
95
96 /***
97 * Returns the existing session, or null if no session exists.
98 */
99 public WOSession existingSession ()
100 {
101
102 HttpSession session = request.servletRequest().getSession();
103 if ( session == null ) return null;
104 WOSession wosession = new WOSession();
105 wosession.setServletSession( session );
106 return wosession;
107 }
108
109 /***
110 * Returns the existing session if it exists. If no session
111 * exists, returns a newly created session. Note that if the
112 * user client does not support session ids/cookies, this will
113 * create a new session with each request.
114 */
115 public WOSession session ()
116 {
117
118 WOSession wosession = new WOSession();
119 wosession.setServletSession(
120 request.servletRequest().getSession( true ) );
121 return wosession;
122 }
123
124 /***
125 * Returns the named WOComponent.
126 */
127 public WOComponent pageWithName (String aString)
128 {
129 return request.application().pageWithName( aString, context );
130 }
131
132 /***
133 * Appends "Action" to the specified string and tries to invoke
134 * method with that name and no arguments. Returns null if
135 * the method does not exist. If anAction is null, "defaultAction"
136 * will be assumed.
137 */
138 public WOActionResults performActionNamed (String anAction)
139 {
140 if ( anAction == null ) anAction = "default";
141 try
142 {
143 NSSelector sel = new NSSelector( anAction+"Action" );
144 return (WOActionResults) sel.invoke( this );
145 }
146 catch ( NoSuchMethodException exc )
147 {
148
149 }
150 catch ( InvocationTargetException exc )
151 {
152 Throwable e = exc.getTargetException();
153 exc.printStackTrace();
154 throw new RuntimeException( e.toString() );
155 }
156 catch ( Exception exc )
157 {
158 exc.printStackTrace();
159 throw new RuntimeException( exc.toString() );
160 }
161 WOResponse error = new WOResponse();
162 error.setStatus( 404 );
163 error.appendContentString(
164 "Could not find method named \"" + anAction + "Action\"." );
165 return error;
166 }
167
168 /***
169 * Assigns the arrays of form values for the specified keys
170 * to properties on this object with matching names whose type
171 * is NSArray or is convertable from a Collection.
172 */
173 public void takeFormValueArraysForKeyArray (NSArray anArray)
174 {
175 if ( anArray == null ) return;
176
177 Method m;
178 Object key;
179 Object value;
180 java.util.Enumeration e = anArray.objectEnumerator();
181 while ( e.hasMoreElements() )
182 {
183 key = e.nextElement();
184 value = request.formValuesForKey( key.toString() );
185 try
186 {
187
188 m = Introspector.getPropertyWriteMethod(
189 this.getClass(), key.toString(),
190 new Class[] { Introspector.WILD } );
191 if ( m != null )
192 {
193
194 if ( value != null )
195 {
196 Class[] paramTypes = m.getParameterTypes();
197 if ( ! paramTypes[0].isAssignableFrom(
198 value.getClass() ) )
199 {
200
201
202
203 }
204 }
205
206 m.invoke( this, new Object[] { value } );
207 }
208 }
209 catch ( Exception exc )
210 {
211
212 debugString( "WODirectAction.takeFormValuesForKeyArray: " + exc );
213 }
214 }
215
216 }
217
218 /***
219 * Assigns the form values for the specified keys to properties
220 * on this object with matching names.
221 */
222 public void takeFormValuesForKeyArray (NSArray anArray)
223 {
224 if ( anArray == null ) return;
225
226 Method m;
227 Object key;
228 Object value;
229 java.util.Enumeration e = anArray.objectEnumerator();
230 while ( e.hasMoreElements() )
231 {
232 key = e.nextElement();
233 value = request.formValueForKey( key.toString() );
234 try
235 {
236
237 m = Introspector.getPropertyWriteMethod(
238 this.getClass(), key.toString(),
239 new Class[] { Introspector.WILD } );
240 if ( m != null )
241 {
242
243 if ( value != null )
244 {
245 Class[] paramTypes = m.getParameterTypes();
246 Object convertedValue =
247 ValueConverter.convertObjectToClass(
248 value, paramTypes[0] );
249 if ( convertedValue != null )
250 {
251 value = convertedValue;
252 }
253 }
254
255 m.invoke( this, new Object[] { value } );
256 }
257 }
258 catch ( Exception exc )
259 {
260
261 debugString( "WODirectAction.takeFormValuesForKeyArray: " + exc );
262 }
263 }
264
265 }
266
267 /***
268 * Writes a message to the standard error stream.
269 */
270 public static void logString (String aString)
271 {
272 System.err.println( aString );
273 }
274
275 /***
276 * Writes a message to the standard error stream
277 * if debugging is activated.
278 */
279 public static void debugString (String aString)
280 {
281
282 System.err.println( aString );
283 }
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317