KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > services > controller > ValidationController


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65
66 package com.jcorporate.expresso.services.controller;
67
68 import com.jcorporate.expresso.core.controller.ControllerException;
69 import com.jcorporate.expresso.core.controller.ControllerRequest;
70 import com.jcorporate.expresso.core.controller.ControllerResponse;
71 import com.jcorporate.expresso.core.controller.DBController;
72 import com.jcorporate.expresso.core.controller.ErrorCollection;
73 import com.jcorporate.expresso.core.controller.Input;
74 import com.jcorporate.expresso.core.controller.NonHandleableException;
75 import com.jcorporate.expresso.core.controller.State;
76 import com.jcorporate.expresso.core.controller.Transition;
77 import com.jcorporate.expresso.core.db.DBException;
78 import com.jcorporate.expresso.services.validation.AuthValidationException;
79 import com.jcorporate.expresso.services.validation.ValidationEntry;
80 import com.jcorporate.expresso.services.validation.ValidationHandler;
81 import org.apache.log4j.Logger;
82
83 import java.util.Date JavaDoc;
84
85
86 /**
87  * This is an Expresso controller that responds to the validator
88  * clicking on an URL provided to him from the notification
89  * from the validation job. It has the responsibility of
90  * extracting the parameters from the request, resurrecting
91  * the Validation entry using the validation-db-context and the
92  * validation id. It then compares the code provided in the
93  * request with that stored in the validation entry. If the code
94  * matches, then the application-supplied validation handler is called
95  * to allow the validated-process to go through.
96  *
97  * @author Shash Chatterjee
98  */

99 public class ValidationController
100         extends DBController {
101     private static Logger log =
102             Logger.getLogger(ValidationController.class.getName());
103
104     /**
105      * Typical default constructor for a controller, defines
106      * all the states handled by this controller and also
107      * sets the initial state if no "state=..." parameter
108      * is provided when this controller is invoked.
109      * <p/>
110      * Creation date: (9/23/2001 9:53:01 AM)
111      * Author: Shash Chatterjee
112      */

113     public ValidationController() {
114         super();
115         addState(new State("validate", "Validate"));
116         addState(new State("promptValidation", "ValidationCode"));
117         setInitialState("validate");
118         this.setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
119     }
120
121     /**
122      * A short title for this controller, used mainly in UI screens.
123      * <p/>
124      * Creation date: (9/23/2001 9:54:30 AM)
125      * Author: Shash Chatterjee
126      *
127      * @return The title
128      */

129     public String JavaDoc getTitle() {
130         return ("AuthorizationProcessing");
131     }
132
133     /**
134      * This method simply provides an UI for the three parameters
135      * found in a validation URL. It is onlyu used when there is
136      * an error found processing the link with the runValidateState(...)
137      * method.
138      * <p/>
139      * Creation date: (9/23/2001 9:56:25 AM)
140      * Author: Shash Chatterjee
141      *
142      * @param request All the request parameters
143      * @param response The response created by this state
144      * @throws ControllerException Some of the objects used generate this
145      */

146     protected void runPromptValidationState(ControllerRequest request,
147                                             ControllerResponse response)
148             throws ControllerException {
149
150         // The name of the context used for the validation entry
151
Input ctx = new Input("ctx", "Validation Context");
152         ctx.setDefaultValue(response.getFormCache("ctx"));
153         response.add(ctx);
154
155         // The sequence/ID number of the validation entry
156
Input id = new Input("id", "ID");
157         id.setDefaultValue(response.getFormCache("id"));
158         response.add(id);
159
160         // The validation code
161
Input code = new Input("code", "Code");
162         code.setDefaultValue(response.getFormCache("code"));
163         response.add(code);
164
165         // A button to go back to the rubValidateState
166
Transition val = new Transition("validate", this);
167         val.setLabel("RetryValidation");
168         response.add(val);
169     }
170
171     /**
172      * This method simply provides an UI for the three parameters
173      * found in a validation URL. It is onlyu used when there is
174      * an error found processing the link with the runValidateState(...)
175      * method.
176      * <p/>
177      * Creation date: (9/23/2001 9:56:25 AM)
178      * Author: Shash Chatterjee
179      *
180      * @param request All the request parameters
181      * @param response The response created by this state
182      * @return ControllerResponse
183      * @throws ControllerException If there as an exception thrown by the
184      * validation classes, also some of the objects used generate this
185      * @throws DBException Some of the objects used generate this
186      * @throws NonHandleableException Some of the objects used generate this
187      */

188     protected ControllerResponse runValidateState(ControllerRequest request,
189                                                   ControllerResponse response)
190             throws ControllerException,
191             DBException,
192             NonHandleableException {
193         ValidationEntry ve = null;
194         try {
195             ErrorCollection errors = new ErrorCollection();
196
197             // Context for the validation entry
198
String JavaDoc dbName = request.getParameter("ctx");
199
200             if ((dbName == null) || (dbName.equals(""))) {
201                 errors.addError("Validation operation needs a db context");
202             } else {
203                 response.setFormCache("ctx", dbName);
204             }
205
206             // Unique id/seq. # for the validation entry
207
String JavaDoc id = request.getParameter("id");
208
209             if ((id == null) || (id.equals(""))) {
210                 errors.addError("Validation operation needs an ID");
211             } else {
212                 response.setFormCache("id", id);
213             }
214
215             // The validation code
216
String JavaDoc code = request.getParameter("code");
217
218             if ((code == null) || (code.equals(""))) {
219                 errors.addError("Validation operation needs a code.");
220             } else {
221                 response.setFormCache("code", code);
222             }
223
224             // Resurrect the validation entry, given the context/id
225
try {
226                 ve = new ValidationEntry(dbName, id);
227             } catch (AuthValidationException e) {
228                 errors.addError("This validation link could not be found");
229             }
230
231             // Do some error checking here...
232
if (errors.isEmpty()) {
233                 String JavaDoc state = ve.getStatus();
234
235                 // Only process the validation entry if it is "available"
236
if (state.equals(ValidationEntry.EXPIRED)) {
237                     errors.addError("This validation link has expired");
238                 } else if (state.equals(ValidationEntry.VALIDATED)) {
239                     errors.addError("This validation link is no longer available, it was already validated");
240                 } else {
241
242                     // Make sure the entry hasn't expired already
243
Date JavaDoc now = new Date JavaDoc();
244                     Date JavaDoc expiresAt = ve.getExpiresAt();
245
246                     if (now.after(expiresAt)) {
247                         ve.setStatus(ValidationEntry.EXPIRED);
248                         errors.addError("This validation link has expired");
249                     }
250                 }
251             }
252             // Check if the supplied code matches that in the validation entry
253
if (errors.isEmpty()) {
254                 if (!ve.codeMatches(code)) {
255                     errors.addError("Specified code is invalid, validation failed");
256                     log.warn("Received invalid validation code. " + code);
257                 }
258             }
259             // If errors were found so far, display the error and prompt mfor corrected input
260
if (!errors.isEmpty()) {
261                 response.saveErrors(errors);
262                 response = this.newState("promptValidation", request);
263                 log.warn("error in validation for code: " + code);
264                 return response;
265             }
266
267 // Get the application-specific handler and call the "validated" method on it.
268
ValidationHandler vh = ve.instantiateHandler();
269
270 // If we get here...everything went smoothly
271
ve.setStatus(ValidationEntry.VALIDATED);
272
273 //
274
//Save the validation entry in the session.
275
//
276
request.getSession().setPersistentAttribute(ValidationEntry.SESSION_KEY, ve);
277
278             // Get the application-specific handler and call the "validated" method on it.
279
response = vh.validated(ve.getParams(), request, response, this);
280             if (log.isInfoEnabled()) {
281                 log.info("Successfully validated code" + code +
282                         " for validation handler: " + vh.getClass().getName());
283             }
284
285             return response;
286         } catch (AuthValidationException vex) {
287             log.error("Error processing validation", vex);
288
289             try {
290 //We had an error. Reset the validation entry to 'waiting'
291
//to allow a retry.
292
ve.setStatus(ValidationEntry.WAITING);
293             } catch (AuthValidationException ex) {
294                 log.error("There is an error validating code: "
295                         + request.getParameter("code") +
296                         "it could not be reset to a waiting state." + ex);
297             }
298
299             throw new ControllerException("Validation error", vex);
300         } catch (Throwable JavaDoc t) {
301             try {
302 //We had an error. Reset the validation entry to 'waiting'
303
//to allow a retry.
304
ve.setStatus(ValidationEntry.WAITING);
305             } catch (AuthValidationException ex) {
306                 log.error("There is an error validating code: "
307                         + request.getParameter("code") +
308                         "it could not be reset to a waiting state." + ex);
309             }
310
311             log.error("Error processing validation", t);
312             throw new ControllerException("Validation error", t);
313         }
314     }
315
316     /**
317      * This method allows access to all states of this controller to everybody. The goal
318      * of preventing 'hack' attacks here is to require the tough random numbers. Currently
319      * we are doing 160 Bit random numbers. Makes for quite a long random URL
320      * <p/>
321      * Creation date: (9/23/2001 2:19:02 PM)
322      * Author: Shash Chatterjee
323      *
324      * @param newState The state to check permissions for
325      * @param params The request parameters
326      * @return true if the current is allowed to execute this state, false otherwise
327      * @throws ControllerException upon error (this implementation does not)
328      */

329     public synchronized boolean stateAllowed(String JavaDoc newState,
330                                              ControllerRequest params)
331             throws ControllerException {
332         return true;
333     } /* stateAllowed(String) */
334
335
336 }
Popular Tags