001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.services.validation;
066:
067: import com.jcorporate.expresso.core.db.DBException;
068: import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
069: import com.jcorporate.expresso.core.job.Job;
070: import com.jcorporate.expresso.core.job.ServerException;
071: import com.jcorporate.expresso.core.misc.ConfigManager;
072: import com.jcorporate.expresso.core.misc.CookieBase64;
073: import com.jcorporate.expresso.core.misc.DateTime;
074: import com.jcorporate.expresso.core.misc.EMailSender;
075: import com.jcorporate.expresso.core.misc.StringUtil;
076: import com.jcorporate.expresso.core.security.CryptoManager;
077: import com.jcorporate.expresso.core.security.User;
078: import com.jcorporate.expresso.kernel.exception.ChainedException;
079: import com.jcorporate.expresso.kernel.util.ClassLocator;
080: import com.jcorporate.expresso.kernel.util.FastStringBuffer;
081: import com.jcorporate.expresso.services.dbobj.JobQueue;
082: import com.jcorporate.expresso.services.dbobj.JobQueueParam;
083: import com.jcorporate.expresso.services.dbobj.Setup;
084: import com.jcorporate.expresso.services.dbobj.ValidationQueue;
085: import com.jcorporate.expresso.services.dbobj.ValidationQueueParam;
086: import org.apache.log4j.Logger;
087:
088: import java.io.Serializable;
089: import java.util.Calendar;
090: import java.util.Date;
091: import java.util.Enumeration;
092: import java.util.Hashtable;
093: import java.util.Iterator;
094: import java.util.List;
095: import java.util.StringTokenizer;
096: import java.util.Vector;
097:
098: /**
099: * This class abstracts the storing of the data that goes along with any
100: * particular validation operation. This class also provides functions for a
101: * validation request to be created in the first place. In this first
102: * incarnation, this class stores all the data using DBObjects. If warranted
103: * at a later time, the ideal way to change the functionality by making this
104: * class abstract and then implementing DBValidationEntry and
105: * XMLValidationEntry or whatever. Most of the methods in this class are
106: * "protected", so that minor changes can be handled by simply extending this
107: * class and overridining the necessary methods.
108: *
109: * @author Shash Chatterjee
110: * @version $Revision: 1.25 $ $Date: 2004/11/17 20:48:22 $
111: * @since Expresso 4.0
112: */
113: public class ValidationEntry implements Serializable {
114: /**
115: * Parameter for validator
116: */
117: public static final String PRM_VALIDATOR = "$$$Validator";
118:
119: /**
120: * PArameter for 'Expires After'
121: */
122: public static final String PRM_EXPIRES_AFTER = "$$$ExpiresAfter";
123:
124: /**
125: * Parameter for 'Validation Title'
126: */
127: public static final String PRM_VAL_TITLE = "$$$ValTitle";
128:
129: /**
130: * Parameter for 'Validation Description'
131: */
132: public static final String PRM_VAL_DESC = "$$$ValDesc";
133:
134: /**
135: * Parameter for 'Validation Server'
136: */
137: public static final String PRM_VAL_SERVER = "$$$ValDServer";
138:
139: /**
140: * Parameter for 'Validation Port'
141: */
142: public static final String PRM_VAL_PORT = "$$$ValPort";
143:
144: /**
145: * Parameter for 'Validation webapp context'
146: */
147: public static final String PRM_VAL_CTX = "$$$ValContext";
148:
149: /**
150: * Status for new
151: */
152: public static final String NEW = "N";
153:
154: /**
155: * Status for waiting
156: */
157: public static final String WAITING = "W";
158:
159: /**
160: * Status for available
161: */
162: public static final String AVAILABLE = "A";
163:
164: /**
165: * Status for Validated
166: */
167: public static final String VALIDATED = "V";
168:
169: /**
170: * Status for Expired
171: */
172: public static final String EXPIRED = "E";
173:
174: /**
175: * Session validation key
176: */
177: public static final String SESSION_KEY = "expresso.services.validation.ValidationEntry";
178:
179: /**
180: * The log4j logger
181: */
182: private static Logger log = Logger.getLogger(ValidationEntry.class);
183:
184: /**
185: * JobQueue
186: */
187: protected JobQueue jq = null;
188:
189: /**
190: * JobQueue parameter data object
191: */
192: protected JobQueueParam jqp = null;
193:
194: /**
195: * default data context
196: */
197: protected String dataContext = "default";
198:
199: /**
200: * Time it expires after
201: */
202: protected String expiresAfter = "120:0:0"; // five days
203:
204: /**
205: * The Job class name
206: */
207: protected String jobClassName = com.jcorporate.expresso.services.job.ValidationJob.class
208: .getName();
209:
210: /**
211: * The Job Number
212: */
213: protected String jobNumber = null;
214:
215: /**
216: * The validation context path
217: */
218: protected String valContextPath = null;
219:
220: /**
221: * The default description
222: */
223: protected String valDesc = "Validation Job";
224:
225: /**
226: * The validation port
227: */
228: protected String valPort = null;
229:
230: /**
231: * The validation server
232: */
233: protected String valServer = null;
234:
235: /**
236: * The validation job title
237: */
238: protected String valTitle = "Validation Job";
239:
240: /**
241: * ?
242: */
243: protected String valType = "default";
244:
245: /**
246: * The validator class name
247: */
248: protected String validationClassName = null;
249:
250: /**
251: * The validation queue
252: */
253: protected ValidationQueue vq = null;
254:
255: /**
256: * current parameter number
257: */
258: protected int paramNum = 0;
259:
260: /**
261: * This constructor is used by classes that submit a validation request
262: * into the system. It creates a Job Queue Entry for the validation
263: * request. Application specific parameters are added using the
264: * addParam(...) method, and the request finally committed using the
265: * submit(...) method. Creation date: (9/23/2001 9:41:06 PM) Author: Shash
266: * Chatterjee
267: *
268: * @param newDbName newDbName The database context to create the validation
269: * Job/Entry in.
270: */
271: public ValidationEntry(String newDbName)
272: throws AuthValidationException {
273: super ();
274:
275: // What DB context to use?
276: if ((newDbName == null) || (newDbName.equals(""))) {
277: newDbName = "default";
278: }
279:
280: dataContext = newDbName;
281:
282: try {
283: int uid = User.getAdminId(newDbName);
284:
285: // Create the job queue entry
286: jq = new JobQueue();
287: jq.setDataContext(dataContext);
288: jq.setField(JobQueue.FLD_UID, uid);
289: jq.setField(JobQueue.FLD_JOBCODE, jobClassName);
290: jq.setField(JobQueue.FLD_STATUS_CODE, "N");
291: jq.add();
292:
293: // Store the job queue number for later use...
294: jobNumber = jq.getField("JobNumber");
295:
296: // Create a job queue parameter instance for later use in addParam()
297: jqp = new JobQueueParam();
298: jqp.setDataContext(dataContext);
299: } catch (DBException dbe) {
300: throw new AuthValidationException(
301: "Database error creating job or parameters", dbe);
302: }
303:
304: if (log.isDebugEnabled()) {
305: log.debug("New entry started with job number " + jobNumber);
306: }
307: }
308:
309: /**
310: * This constructor is used, after a validation request comes in, to
311: * resurrect a validation entry from the DB. Creation date: (9/23/2001
312: * 9:41:06 PM) Author: Shash Chatterjee
313: *
314: * @param dbName dbName The DB context to retrieve the validation entry
315: * from
316: * @param id id The validation request id/seq. number
317: * @throws AuthValidationException AuthValidationException
318: */
319: public ValidationEntry(String dbName, String id)
320: throws AuthValidationException {
321: super ();
322:
323: try {
324: // Read back the validation entry from persistent storage
325: vq = new ValidationQueue(SecuredDBObject.SYSTEM_ACCOUNT);
326: vq.setDataContext(dbName);
327: vq.setField(ValidationQueue.FLD_ID, id);
328:
329: if (!vq.find()) {
330: throw new AuthValidationException(
331: "Validation queue id \"" + id
332: + "\" not found in db \"" + dbName
333: + "\"");
334: }
335: } catch (DBException dbe) {
336: throw new AuthValidationException("DB error", dbe);
337: }
338: }
339:
340: /**
341: * This constructor is used by the validation job to create a validation
342: * entry from the job parameters. Application classes should have no need
343: * to use this class/ Creation date: (9/23/2001 9:41:06 PM) Author: Shash
344: * Chatterjee
345: *
346: * @param context context The DB context to use for the validation entry
347: * @param paramsVector paramsVector All the params passed in to the job
348: * @param jq jq The job queue entry in its entirety
349: * @throws AuthValidationException AuthValidationException
350: */
351: public ValidationEntry(String context, List paramsVector,
352: JobQueue jq) throws AuthValidationException {
353: super ();
354:
355: String id = null;
356:
357: try {
358: // The time-delta for expiry is passed in as "hours:minutes:seconds"
359: // It is parsed here and then added on to the current time
360: String expiresAfter = jq
361: .getParamValue(ValidationEntry.PRM_EXPIRES_AFTER);
362: Calendar now = Calendar.getInstance();
363: StringTokenizer stk = new StringTokenizer(expiresAfter, ":");
364: int hr = Integer.parseInt((String) stk.nextElement());
365: int mn = Integer.parseInt((String) stk.nextElement());
366: int sc = Integer.parseInt((String) stk.nextElement());
367: now.add(Calendar.HOUR, hr);
368: now.add(Calendar.MINUTE, mn);
369: now.add(Calendar.SECOND, sc);
370:
371: // Create the server/port/context-path variables
372: valServer = jq
373: .getParamValue(ValidationEntry.PRM_VAL_SERVER);
374: valPort = jq.getParamValue(ValidationEntry.PRM_VAL_PORT);
375: valContextPath = jq
376: .getParamValue(ValidationEntry.PRM_VAL_CTX);
377:
378: // Create the validation entry
379: vq = new ValidationQueue();
380: vq.setDataContext(context);
381: vq.setField(ValidationQueue.FLD_STATUS_CODE, "N"); //Mark it as "new", won't be used until marked as "available"
382: vq.setField(ValidationQueue.FLD_EXPIRES_AT, DateTime
383: .getDateTimeForDB(now.getTime(), context));
384: vq.setField(ValidationQueue.FLD_VAL_CODE,
385: createValidationCode()); // Here's where the validation code is calculated
386: vq.setField(ValidationQueue.FLD_VAL_HANDLER, jq
387: .getParamValue(ValidationEntry.PRM_VALIDATOR));
388: vq.setField(ValidationQueue.FLD_PROCESSED_BY, "1");
389: vq.add();
390:
391: // Store the id of the validation entry for later use
392: id = vq.getField(ValidationQueue.FLD_ID);
393:
394: // Loop through the job parameters and add them as validation entry parameters
395: int paramNum = 0;
396: ValidationQueueParam vqp = new ValidationQueueParam();
397: vqp.setDataContext(context);
398:
399: for (Iterator i = paramsVector.iterator(); i.hasNext();) {
400: JobQueueParam jqp = (JobQueueParam) i.next();
401: String key = jqp.getField("ParamCode");
402: String val = jqp.getField("ParamValue");
403: vqp.clear();
404: vqp.setField(ValidationQueueParam.FLD_QUEUE_ID, id);
405: vqp.setField(ValidationQueueParam.FLD_PARAM_NUM,
406: Integer.toString(++paramNum));
407: vqp.setField(ValidationQueueParam.FLD_PARAM_CODE, key);
408: vqp.setField(ValidationQueueParam.FLD_PARAM_VAL, val);
409: vqp.add();
410: }
411:
412: // All done....mark the entry as "available"
413: vq.setField(ValidationQueue.FLD_STATUS_CODE, "A");
414: vq.update();
415: } catch (DBException dbe) {
416: throw new AuthValidationException(
417: "Database error storing validation entry", dbe);
418: }
419: }
420:
421: /**
422: * This default constructor should never be used, and is marked private and
423: * protected with an exception just for that reason. Creation date:
424: * (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
425: */
426: private ValidationEntry() throws AuthValidationException {
427: throw new AuthValidationException(
428: "Please do not use the default constructor");
429: }
430:
431: /**
432: * @param path
433: */
434: public void setContextPath(String path) {
435: valContextPath = path;
436: }
437:
438: /**
439: * Sets the description for the validation job Creation date: (9/23/2001
440: * 9:41:06 PM) Author: Shash Chatterjee
441: *
442: * @param desc desc The description
443: */
444: public void setDesc(String desc) {
445: valDesc = desc;
446: }
447:
448: /**
449: * Method to retrieve the absolute date/time when the request expires.
450: * Creation date: (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
451: *
452: * @return The expiry date/time
453: */
454: public Date getExpiresAt() throws AuthValidationException {
455: if (vq == null) {
456: throw new AuthValidationException(
457: "Use loadQueueEntry(...) method first");
458: }
459:
460: try {
461: Date ex = vq.getFieldDate(ValidationQueue.FLD_EXPIRES_AT);
462:
463: return ex;
464: } catch (DBException dbe) {
465: throw new AuthValidationException("DB error", dbe);
466: }
467: }
468:
469: /**
470: * Sets the name of the job class for validation requests. Currently the
471: * only job that should be specified is ValidationJob Creation date:
472: * (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
473: *
474: * @param name name Class name of validation job
475: * @throws AuthValidationException AuthValidationException if the class
476: * isn't an Expresso Job class
477: */
478: public void setJobClassName(String name)
479: throws AuthValidationException {
480: try {
481: Job.instantiate(name);
482: } catch (ServerException se) {
483: throw new AuthValidationException("Class \"" + name
484: + "\" is not an Expresso Job", se);
485: }
486:
487: jobClassName = name;
488: }
489:
490: /**
491: * Method to return all the application-specific parameters associated with
492: * this validation request Creation date: (9/23/2001 9:41:06 PM) Author:
493: * Shash Chatterjee
494: *
495: * @return Hashtable of all the parameters, keyed by parameter name
496: */
497: public Hashtable getParams() throws AuthValidationException {
498: if (vq == null) {
499: throw new AuthValidationException(
500: "Use loadQueueEntry(...) method first");
501: }
502:
503: Hashtable params = new Hashtable(8);
504:
505: try {
506: String id = vq.getField(ValidationQueue.FLD_ID);
507: ValidationQueueParam vqp = new ValidationQueueParam();
508: vqp.setField(ValidationQueueParam.FLD_QUEUE_ID, id);
509: vqp.setDataContext(dataContext);
510:
511: for (Iterator i = vqp.searchAndRetrieveList().iterator(); i
512: .hasNext();) {
513: ValidationQueueParam oneParam = (ValidationQueueParam) i
514: .next();
515: params
516: .put(
517: oneParam
518: .getField(ValidationQueueParam.FLD_PARAM_CODE),
519: oneParam
520: .getField(ValidationQueueParam.FLD_PARAM_VAL));
521: }
522: } catch (DBException dbe) {
523: throw new AuthValidationException("DB error", dbe);
524: }
525:
526: return params;
527: }
528:
529: /**
530: * @param port
531: */
532: public void setPort(String port) {
533: valPort = port;
534: }
535:
536: /**
537: * @param server
538: */
539: public void setServer(String server) {
540: valServer = server;
541: }
542:
543: /**
544: * Sets the current status of the validation entry Creation date:
545: * (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
546: *
547: * @param newStatus newStatus = "A"=available, "N"=new, "W"=waiting,
548: * "V"=validated, "E"=expired
549: * @throws AuthValidationException AuthValidationException
550: */
551: public void setStatus(String newStatus)
552: throws AuthValidationException {
553: if (vq == null) {
554: throw new AuthValidationException(
555: "Use loadQueueEntry(...) method first");
556: }
557:
558: try {
559: vq.setField(ValidationQueue.FLD_STATUS_CODE, newStatus);
560: vq.update();
561: } catch (DBException dbe) {
562: throw new AuthValidationException("DB error", dbe);
563: }
564: }
565:
566: /**
567: * Returns the current status of the validation request Creation date:
568: * (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
569: *
570: * @return "N","A","V","E" - for "new", "available", "validated", "expired"
571: * @throws AuthValidationException AuthValidationException
572: */
573: public String getStatus() throws AuthValidationException {
574: if (vq == null) {
575: throw new AuthValidationException(
576: "Use loadQueueEntry(...) method first");
577: }
578:
579: try {
580: String status = vq
581: .getField(ValidationQueue.FLD_STATUS_CODE);
582:
583: return status;
584: } catch (DBException dbe) {
585: throw new AuthValidationException("DB error", dbe);
586: }
587: }
588:
589: /**
590: * Set's the title of the validation entry job Creation date: (9/23/2001
591: * 9:41:06 PM) Author: Shash Chatterjee
592: *
593: * @param title title The title
594: */
595: public void setTitle(String title) {
596: valTitle = title;
597: }
598:
599: /**
600: * Method to set the app-specific validation handler associated with this
601: * validation request Creation date: (9/23/2001 9:41:06 PM) Author: Shash
602: * Chatterjee
603: *
604: * @param className className Class name of a class that implements
605: * ValidationHandler interface
606: * @throws AuthValidationException AuthValidationException if the handler
607: * is not of the correct class, or if the instantiation fails
608: */
609: public void setValidationHandler(String className)
610: throws AuthValidationException {
611: StringUtil.assertNotBlank(className,
612: "ValidationHandler class name "
613: + " may not be blank or null here");
614:
615: try {
616: Class c = ClassLocator.loadClass(className);
617: c.newInstance();
618: } catch (ClassNotFoundException cn) {
619: throw new AuthValidationException(
620: "ValidationHandler object '" + className
621: + "' not found", cn);
622: } catch (InstantiationException ie) {
623: throw new AuthValidationException(
624: "ValidationHandler object '" + className
625: + "' cannot be instantiated", ie);
626: } catch (IllegalAccessException iae) {
627: throw new AuthValidationException("Illegal access loading "
628: + "ValidationHandler object '" + className + "'",
629: iae);
630: }
631:
632: validationClassName = className;
633: }
634:
635: /**
636: * Method to set the app-specific validation handler associated with this
637: * validation request
638: *
639: * @param clazz Class that implements
640: * ValidationHandler interface
641: * @throws AuthValidationException AuthValidationException if the handler
642: * is not of the correct class, or if the instantiation fails
643: */
644: public void setValidationHandler(Class clazz)
645: throws AuthValidationException {
646: try {
647: clazz.newInstance();
648: } catch (IllegalAccessException ex) {
649: throw new AuthValidationException("Illegal access loading "
650: + "ValidationHandler object '" + clazz.getName()
651: + "'", ex);
652: } catch (InstantiationException ex) {
653: throw new AuthValidationException(
654: "ValidationHandler object '" + clazz.getName()
655: + "' cannot be instantiated", ex);
656: }
657:
658: validationClassName = clazz.getName();
659: }
660:
661: /**
662: * Adds an application specific parameter into the validation entry
663: * Creation date: (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
664: *
665: * @param name name Name of the parameter
666: * @param value value Value of the parameter
667: */
668: public void addParam(String name, String value)
669: throws AuthValidationException {
670: try {
671:
672: jqp.clear();
673: jqp.setField("JobNumber", jobNumber);
674: paramNum++;
675: jqp.setField("ParamNumber", Integer.toString(paramNum));
676: jqp.setField("ParamCode", name);
677: jqp.setField("ParamValue", value);
678: jqp.add();
679: } catch (DBException dbe) {
680: throw new AuthValidationException(
681: "Database error adding job parameter", dbe);
682: }
683:
684: if (log.isDebugEnabled()) {
685: log.debug("Job id= " + jobNumber + ": Adding param name="
686: + name + " value=" + value);
687: }
688: }
689:
690: /**
691: * Function to match the code in the DB versus the code in the request.
692: * Creation date: (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
693: *
694: * @param code code Code in the request URL
695: * @return true if code matches, false otherwise
696: * @throws AuthValidationException AuthValidationException
697: */
698: public boolean codeMatches(String code)
699: throws AuthValidationException {
700: try {
701: String storedCode = vq
702: .getField(ValidationQueue.FLD_VAL_CODE);
703:
704: if (storedCode.equals(code)) {
705: return true;
706: } else {
707: return false;
708: }
709: } catch (DBException dbe) {
710: throw new AuthValidationException("DB error", dbe);
711: }
712: }
713:
714: /**
715: * Deletes the validation entry and all the connected parameters
716: *
717: * @throws AuthValidationException if no record is loaded OR there's an
718: * error deleting the records.
719: */
720: public void delete() throws AuthValidationException {
721: if (vq == null) {
722: throw new AuthValidationException(
723: "Use loadQueueEntry(...) method first");
724: }
725:
726: try {
727: vq.delete(true);
728: vq = null;
729: } catch (DBException dbe) {
730: throw new AuthValidationException("DB error", dbe);
731: }
732: }
733:
734: /**
735: * Method to set the time delta from current time when the request will
736: * expire if unused Creation date: (9/23/2001 9:41:06 PM) Author: Shash
737: * Chatterjee
738: *
739: * @param hr hr Delta hours
740: * @param min min Delta minutes
741: * @param sec sec Delta seconds
742: */
743: public void expiresAfter(int hr, int min, int sec) {
744: FastStringBuffer fsb = FastStringBuffer.getInstance();
745:
746: try {
747: fsb.append(hr);
748: fsb.append(":");
749: fsb.append(min);
750: fsb.append(":");
751: fsb.append(sec);
752:
753: //Stored internally as "hours:minutes:seconds"
754: expiresAfter = fsb.toString();
755: } finally {
756: fsb.release();
757: fsb = null;
758: }
759: }
760:
761: /**
762: * Utility function to instantiate the app-specific validation handler
763: * Creation date: (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
764: *
765: * @return Object of class ValidationHandler
766: * @throws AuthValidationException AuthValidationException
767: */
768: public ValidationHandler instantiateHandler()
769: throws AuthValidationException {
770: ValidationHandler vh = null;
771: String className = null;
772:
773: try {
774: className = vq.getField(ValidationQueue.FLD_VAL_HANDLER);
775: } catch (DBException dbe) {
776: throw new AuthValidationException("DB error", dbe);
777: }
778:
779: StringUtil.assertNotBlank(className,
780: "ValidationHandler class name "
781: + " may not be blank or null here");
782:
783: try {
784: Class c = ClassLocator.loadClass(className);
785: vh = (ValidationHandler) c.newInstance();
786: } catch (ClassNotFoundException cn) {
787: throw new AuthValidationException(
788: "ValidationHandler object '" + className
789: + "' not found", cn);
790: } catch (InstantiationException ie) {
791: throw new AuthValidationException(
792: "ValidationHandler object '" + className
793: + "' cannot be instantiated", ie);
794: } catch (IllegalAccessException iae) {
795: throw new AuthValidationException("llegal access loading "
796: + "ValidationHandler object '" + className + "'",
797: iae);
798: }
799:
800: return vh;
801: }
802:
803: /**
804: * Insert the method's description here. Creation date: (9/23/2001 9:41:06
805: * PM) Author: Shash Chatterjee
806: *
807: * @param dbName The data context to use
808: * @param from the "From" email field.
809: * @param addresses the email addresses to notify
810: * @param subject the subject of the email
811: * @param content The body of the email message
812: */
813: public static void notifyByEmail(String dbName, String from,
814: Vector addresses, String subject, String content)
815: throws AuthValidationException {
816: EMailSender ems = new EMailSender();
817: ems.setFromAddress(from);
818: ems.setDBName(dbName);
819:
820: for (Enumeration e = addresses.elements(); e.hasMoreElements();) {
821: String oneAddr = (String) e.nextElement();
822:
823: try {
824: ems.send(oneAddr, subject, content);
825: } catch (Exception exc) {
826: throw new AuthValidationException(
827: "Email error sending to \"" + oneAddr + "\"",
828: exc);
829: }
830: }
831: }
832:
833: /**
834: * Insert the method's description here. Creation date: (9/23/2001 9:41:06
835: * PM) Author: Shash Chatterjee
836: *
837: * @throws AuthValidationException upon error
838: */
839: public void submit() throws AuthValidationException {
840: try {
841: if ((valServer == null) || valServer.equals("")) {
842: valServer = Setup.getValue(dataContext, "HTTPServ");
843: }
844:
845: if ((valPort == null) || valPort.equals("")) {
846: valPort = Setup.getValue(dataContext, "ServletPort");
847: }
848:
849: if ((valContextPath == null) || valContextPath.equals("")) {
850: valContextPath = Setup.getValue(dataContext,
851: "ContextPath");
852: }
853:
854: addParam(PRM_VALIDATOR, validationClassName);
855: addParam(PRM_EXPIRES_AFTER, expiresAfter);
856: addParam(PRM_VAL_TITLE, valTitle);
857: addParam(PRM_VAL_DESC, valDesc);
858: addParam(PRM_VAL_SERVER, valServer);
859: addParam(PRM_VAL_PORT, valPort);
860: addParam(PRM_VAL_CTX, valContextPath);
861: jq.setField(JobQueue.FLD_STATUS_CODE, AVAILABLE);
862: jq.update();
863: } catch (DBException dbe) {
864: throw new AuthValidationException(
865: "Database error updating job status to active", dbe);
866: }
867: }
868:
869: /**
870: * Utility function to create a URL based on the webapp context, and setup
871: * values such as the http server/port etc. It tags on the db context,
872: * the validation entry id and the validation code as request parameters.
873: * Creation date: (9/23/2001 9:41:06 PM) Author: Shash Chatterjee
874: *
875: * @return The URL for use by the validator to approve the validation
876: * request
877: * @throws AuthValidationException upon error
878: */
879: public String validationURL() throws AuthValidationException {
880: FastStringBuffer authURL = FastStringBuffer.getInstance();
881: String returnValue = null;
882:
883: try {
884: try {
885: String db = vq.getDataContext();
886: if (valPort.equals(ConfigManager.getConfig()
887: .getSslPort())) {
888: authURL.append("https://");
889: } else {
890: authURL.append("http://");
891: }
892: authURL.append(valServer);
893: authURL.append(":" + valPort);
894: authURL.append(valContextPath);
895: authURL.append("/Validate.do?");
896: authURL.append("ctx=" + db);
897: authURL.append("&id="
898: + vq.getField(ValidationQueue.FLD_ID));
899: authURL.append("&code="
900: + vq.getField(ValidationQueue.FLD_VAL_CODE));
901: } catch (DBException dbe) {
902: throw new AuthValidationException("DB error", dbe);
903: }
904:
905: returnValue = authURL.toString();
906: } finally {
907: authURL.release();
908: }
909:
910: return returnValue;
911: }
912:
913: /**
914: * Create a cryptographically sound validation code for use in the
915: * validation operation [Currently generates a 256-bit random number]
916: * Creation date: (9/23/2001 9:41:06 PM) Author: Shash Chatterjee,
917: * strengthened by Mike Rimov
918: *
919: * @return The validation code
920: */
921: protected static String createValidationCode() {
922: final int length = 256 / 8; //256 Bit random number
923:
924: byte[] possibleNumbers;
925:
926: try {
927: possibleNumbers = CryptoManager.getInstance()
928: .getRandomGenerator().getRandomBytes(length);
929: } catch (ChainedException e) {
930: possibleNumbers = new byte[length];
931:
932: //If an error occurs, just fill it with Math.random() after logging the
933: //exception.
934: Logger.getLogger("com.jcorporate.expresso.core.security.")
935: .error("Create Validation Code", e);
936:
937: for (int i = 0; i < length; i++) {
938: possibleNumbers[i] = (byte) (Math.random() * 256);
939: }
940: }
941:
942: return CookieBase64.encodeNoPadding(possibleNumbers);
943: }
944: }
|