You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by xu...@apache.org on 2011/05/03 07:53:36 UTC

svn commit: r1098924 - in /openejb/trunk/openejb3/container/openejb-core/src: main/java/org/apache/openejb/core/timer/EJBCronTrigger.java test/java/org/apache/openejb/timer/EJBCronTriggerTest.java

Author: xuhaihong
Date: Tue May  3 05:53:36 2011
New Revision: 1098924

URL: http://svn.apache.org/viewvc?rev=1098924&view=rev
Log:
OPENEJB-1537 Add complete validation logic to shedule expressions. (Patch from Shawn Jiang)

Modified:
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java
    openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java?rev=1098924&r1=1098923&r2=1098924&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/timer/EJBCronTrigger.java Tue May  3 05:53:36 2011
@@ -48,15 +48,45 @@ public class EJBCronTrigger extends Trig
 
     private static final Pattern INCREMENTS = Pattern.compile("(\\d+|\\*)/(\\d+)*");
 
-	private static final Pattern LIST = Pattern.compile("(([A-Za-z0-9]+)(-[A-Za-z0-9]+)?)?((1ST|2ND|3RD|4TH|5TH|LAST)([A-za-z]+))?(-([0-9]+))?(LAST)?" +
-			"(?:,(([A-Za-z0-9]+)(-[A-Za-z0-9]+)?)?((1ST|2ND|3RD|4TH|5TH|LAST)([A-za-z]+))?(-([0-9]+))?(LAST)?)*");
+	private static final Pattern LIST = Pattern.compile("(([A-Za-z0-9]+)(-[A-Za-z0-9]+)?)?((1ST|2ND|3RD|4TH|5TH|LAST)([A-za-z]+))?(-([0-7]+))?(LAST)?" +
+			"(?:,(([A-Za-z0-9]+)(-[A-Za-z0-9]+)?)?((1ST|2ND|3RD|4TH|5TH|LAST)([A-za-z]+))?(-([0-7]+))?(LAST)?)*");
 	
 	private static final Pattern RANGE = Pattern.compile("([A-Za-z0-9]+)-([A-Za-z0-9]+)");
-	private static final Pattern WEEKDAY = Pattern.compile("(1ST|2ND|3RD|4TH|5TH|LAST)([A-za-z]+)");
-	private static final Pattern DAYS_TO_LAST = Pattern.compile("-([0-9]+)");
+	private static final Pattern WEEKDAY = Pattern.compile("(1ST|2ND|3RD|4TH|5TH|LAST)(SUN|MON|TUE|WED|THU|FRI|SAT)");
+	private static final Pattern DAYS_TO_LAST = Pattern.compile("-([0-7]+)");
+	
+	private static final Pattern VALID_YEAR = Pattern.compile("([0-9][0-9][0-9][0-9])|\\*");
+	private static final Pattern VALID_MONTH = Pattern.compile("(([0]?[1-9])|(1[0-2]))|\\*");
+	private static final Pattern VALID_DAYS_OF_WEEK = Pattern.compile("[0-7]|\\*");
+	private static final Pattern VALID_DAYS_OF_MONTH = Pattern.compile("((1ST|2ND|3RD|4TH|5TH|LAST)(SUN|MON|TUE|WED|THU|FRI|SAT))|(([1-9])|(0[1-9])|([12])([0-9]?)|(3[01]?))|(LAST)|-([0-7])|[*]");
+	private static final Pattern VALID_HOUR = Pattern.compile("(([0-1]?[0-9])|([2][0-3]))|\\*");
+	private static final Pattern VALID_MINUTE = Pattern.compile("([0-5]?[0-9])|\\*");
+	private static final Pattern VALID_SECOND = Pattern.compile("([0-5]?[0-9])|\\*");
+	
+
 
 	private static final String LAST_IDENTIFIER = "LAST";
+	
+	private static final String RANGE_CHAR="-";
+	
+	private static final String INCREMENTS_CHAR="/";
+	
+    private static final Map<String, Integer> MONTHS_MAP = new HashMap<String, Integer>();
+    private static final Map<String, Integer> WEEKDAYS_MAP = new HashMap<String, Integer>();
 
+    static {
+        int i = 1;
+        // Jan -> 1
+        for (String month : new DateFormatSymbols(Locale.US).getShortMonths()) {
+            MONTHS_MAP.put(month.toUpperCase(Locale.US), i++);
+        }
+        i = 0;
+        // SUN -> 1
+        for (String weekday : new DateFormatSymbols(Locale.US).getShortWeekdays()) {
+            WEEKDAYS_MAP.put(weekday.toUpperCase(Locale.US), i++);
+        }
+    }
+	
     private static final int[] ORDERED_CALENDAR_FIELDS = { Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND };
 
     private static final Map<Integer, Integer> CALENDAR_FIELD_TYPE_ORDERED_INDEX_MAP = new LinkedHashMap<Integer, Integer>();
@@ -71,6 +101,9 @@ public class EJBCronTrigger extends Trig
         CALENDAR_FIELD_TYPE_ORDERED_INDEX_MAP.put(Calendar.MINUTE, 5);
         CALENDAR_FIELD_TYPE_ORDERED_INDEX_MAP.put(Calendar.SECOND, 6);
     }
+    
+    
+    
 
 	private final FieldExpression[] expressions = new FieldExpression[7];
 
@@ -131,8 +164,29 @@ public class EJBCronTrigger extends Trig
 	 *             are out of range
 	 */
 	protected FieldExpression parseExpression(int field, String expr) throws ParseException {
+	    
+	    if (expr == null || expr.isEmpty()){
+	        throw new ParseException(field, expr, "expression can't be null");
+	    }
+	    
 		// Get rid of whitespace and convert to uppercase
 		expr = expr.replaceAll("\\s+", "").toUpperCase();
+		
+		
+        if (expr.length() > 1 && expr.indexOf(",") > 0) {
+
+            String[] expressions = expr.split(",");
+
+            for (String sub_expression : expressions) {
+                validateExpression(field, sub_expression);
+            }
+
+        } else {
+
+            validateExpression(field, expr);
+
+        }
+		
 
 		if (expr.equals("*")) {
 		    return new AsteriskExpression(field);
@@ -147,6 +201,7 @@ public class EJBCronTrigger extends Trig
 		case Calendar.HOUR_OF_DAY:
 		case Calendar.MINUTE:
 		case Calendar.SECOND:
+		    	    
 			m = INCREMENTS.matcher(expr);
 			if (m.matches()) {
 				return new IncrementExpression(m, field);
@@ -169,14 +224,101 @@ public class EJBCronTrigger extends Trig
 			}
 			break;
 		}
+		
+       
 
 		m = LIST.matcher(expr);
+		
 		if (m.matches()) {
 			return new ListExpression(m, field);
 		}
 
 		throw new ParseException(field, expr, "Unparseable time expression");
 	}
+        
+	
+	private void validateExpression(int field, String expression) throws ParseException {
+	    
+
+        if (expression.length() > 2 && expression.indexOf(RANGE_CHAR) > 0) {
+            
+            for (String sub_expression : expression.split(RANGE_CHAR)) {
+                validateSingleToken(field, sub_expression);
+            }
+            
+        } else if (expression.length() > 2 && expression.indexOf(INCREMENTS_CHAR) > 0) {
+            
+            for (String sub_expression : expression.split(INCREMENTS_CHAR)) {
+                validateSingleToken(field, sub_expression);
+            }
+            
+        } else {
+            
+            validateSingleToken(field, expression);
+            
+        }
+	    
+	}
+        
+    private void validateSingleToken(int field, String token) throws ParseException{
+        
+        if(token==null || token.isEmpty()) {
+          throw new ParseException(field, token, "expression can't be null");
+        }
+        
+        switch (field) {
+        
+        case Calendar.YEAR:
+            Matcher m = VALID_YEAR.matcher(token);
+            if (!m.matches()) {
+                throw new ParseException(field, token, "Valid YEAR is four digit");
+            }
+            break;               
+            
+        case Calendar.MONTH:
+            m = VALID_MONTH.matcher(token);
+            if (!(m.matches() || MONTHS_MAP.containsKey(token))) {
+                throw new ParseException(field, token, "Valid MONTH is 1-12 or {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', Dec'}");
+            }
+            break;
+            
+        case Calendar.DAY_OF_MONTH:
+            m = VALID_DAYS_OF_MONTH.matcher(token);
+            if (!m.matches()) {
+                throw new ParseException(field, token, "Valid DAYS_OF_MONTH is 0-7 or {'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'} ");
+            }
+            break;
+            
+        case Calendar.DAY_OF_WEEK:
+            m = VALID_DAYS_OF_WEEK.matcher(token);
+            if (!(m.matches() || WEEKDAYS_MAP.containsKey(token))) {
+                throw new ParseException(field, token, "Valid DAYS_OF_WEEK is 1-31  -(1-7) or {'1st', '2nd', '3rd', '4th',  '5th', 'Last'} + {'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'} ");
+            }
+            break;
+        
+        case Calendar.HOUR_OF_DAY:
+            m = VALID_HOUR.matcher(token);
+            if (!m.matches()) {
+                throw new ParseException(field, token, "Valid HOUR_OF_DAY value is 0-23");
+            }
+            break;
+        case Calendar.MINUTE:
+            m = VALID_MINUTE.matcher(token);
+            if (!m.matches()) {
+                throw new ParseException(field, token, "Valid MINUTE value is 0-59");
+            }
+            break;
+        case Calendar.SECOND:
+            m = VALID_SECOND.matcher(token);
+            if (!m.matches()) {
+                throw new ParseException(field, token, "Valid SECOND value is 0-59");
+            }
+            break;
+            
+        }
+    
+    }
+        
 
 	@Override
 	public Date computeFirstFireTime(org.quartz.Calendar calendar) {
@@ -225,7 +367,7 @@ public class EJBCronTrigger extends Trig
 	@Override
 	public Date getFinalFireTime() {
 		Calendar calendar = new GregorianCalendar(timezone);
-		calendar.setLenient(false);
+		//calendar.setLenient(false);
 		calendar.setFirstDayOfWeek(Calendar.SUNDAY);
 
 		if (endTime == null) {
@@ -284,7 +426,7 @@ public class EJBCronTrigger extends Trig
 	@Override
 	public Date getFireTimeAfter(Date afterTime) {
 		Calendar calendar = new GregorianCalendar(timezone);
-		calendar.setLenient(false);
+		// calendar.setLenient(false);
 		calendar.setFirstDayOfWeek(Calendar.SUNDAY);
 
 		// Calculate starting time
@@ -459,7 +601,9 @@ public class EJBCronTrigger extends Trig
 
 	public static class ParseException extends Exception {
 
-		private final Map<Integer, ParseException> children;
+
+
+        private final Map<Integer, ParseException> children;
 		private final Integer field;
 		private final String value;
 		private final String error;
@@ -493,29 +637,24 @@ public class EJBCronTrigger extends Trig
 		public String getError() {
 			return error;
 		}
+		
+        @Override
+        public String toString() {
+            return "ParseException [field=" + field + ", value=" + value + ", error=" + error + "]";
+        }		
 
 	}
 
 	private abstract static class FieldExpression {
 
-		private static final Map<String, Integer> MONTHS_MAP = new HashMap<String, Integer>();
-		private static final Map<String, Integer> WEEKDAYS_MAP = new HashMap<String, Integer>();
+
 		protected static final Calendar CALENDAR = new GregorianCalendar(Locale.US); // For getting min/max field values
 
-		static {
-			int i = 1;
-			//Jan -> 1
-			for (String month : new DateFormatSymbols(Locale.US).getShortMonths()) {
-				MONTHS_MAP.put(month.toUpperCase(Locale.US), i++);
-			}
-			i = 0;
-			//SUN -> 1
-			for (String weekday : new DateFormatSymbols(Locale.US).getShortWeekdays()) {
-				WEEKDAYS_MAP.put(weekday.toUpperCase(Locale.US), i++);
-			}
-		}
+	   
 
 		protected static int convertValue(String value, int field) throws ParseException {
+		    
+		    
 			// If the value begins with a digit, parse it as a number
 			if (Character.isDigit(value.charAt(0))) {
 				int numValue;

Modified: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java?rev=1098924&r1=1098923&r2=1098924&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/timer/EJBCronTriggerTest.java Tue May  3 05:53:36 2011
@@ -19,6 +19,7 @@ package org.apache.openejb.timer;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import java.util.Calendar;
 import java.util.Date;
@@ -32,7 +33,7 @@ import org.junit.Test;
 
 public class EJBCronTriggerTest {
 
-	@Test(timeout = 1000)
+	@Test(timeout = 1000000)
 	public void testSimpleDate() throws ParseException {
 		ScheduleExpression expr = new ScheduleExpression().year(2008).month(12).dayOfMonth(1).start(new Date(0));
 		EJBCronTrigger trigger = new EJBCronTrigger(expr);
@@ -63,6 +64,8 @@ public class EJBCronTriggerTest {
 		Date expectedTime = calendar.getTime();
 		assertEquals(expectedTime, trigger.getFinalFireTime());
 	}
+	
+	
 
 	@Test(timeout = 1000)
 	public void testIncrements() throws ParseException {
@@ -88,6 +91,7 @@ public class EJBCronTriggerTest {
 		assertNull(trigger.getFireTimeAfter(startTime));
 	}
 
+	
 	@Test(timeout = 1000)
 	public void testEndTime() throws ParseException {
 		ScheduleExpression expr = new ScheduleExpression().dayOfMonth(20).dayOfWeek("sat").start(new Date(0));
@@ -144,7 +148,7 @@ public class EJBCronTriggerTest {
         assertEquals(new GregorianCalendar(2000,1,27,23,1,59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2000, 1, 26, 0, 0, 0).getTime()));
     }
 
-	@Test(timeout = 5000)
+	@Test(timeout = 5000000)
     public void testOrdinalNumbersDayOfMonth() throws ParseException {
         ScheduleExpression expr = new ScheduleExpression().dayOfMonth("2nd mon").hour(23).minute(1).second(59).start(new Date(0));
         EJBCronTrigger trigger = new EJBCronTrigger(expr);
@@ -173,6 +177,19 @@ public class EJBCronTriggerTest {
         assertEquals(new GregorianCalendar(2010, 6, 27, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 27, 23, 0, 0).getTime()));
         assertEquals(new GregorianCalendar(2010, 6, 28, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 27, 23, 2, 0).getTime()));
     }
+	
+    @Test(timeout = 5000000)
+    public void testRangeCDayOfMonth() throws ParseException {
+        ScheduleExpression expr = new ScheduleExpression().dayOfMonth("Last Fri - 1st Mon").hour(23).minute(1).second(59).start(new Date(0));
+        EJBCronTrigger trigger = new EJBCronTrigger(expr);
+        assertEquals(new GregorianCalendar(2010, 6, 1, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 1, 23, 0, 0).getTime()));
+        assertEquals(new GregorianCalendar(2010, 6, 2, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 1, 23, 2, 0).getTime()));
+        assertEquals(new GregorianCalendar(2010, 6, 27, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 26, 23, 0, 0).getTime()));
+        assertEquals(new GregorianCalendar(2010, 6, 27, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 27, 23, 0, 0).getTime()));
+        assertEquals(new GregorianCalendar(2010, 6, 28, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 27, 23, 2, 0).getTime()));
+    }	
+	
+	
 
 	@Test(timeout = 5000)
     public void testRangeADayOfWeek() throws ParseException {
@@ -288,4 +305,228 @@ public class EJBCronTriggerTest {
             assertEquals(new GregorianCalendar(2010, 6, 6, 23, 1, 59).getTime(), trigger.getFireTimeAfter(new GregorianCalendar(2010, 6, 2, 23, 2, 0).getTime()));
         }
 	}
+	
+	
+	@Test(timeout = 50000000)
+    public void testInvalidSingleInputs1() throws ParseException {
+    
+    // invalid  hour
+    ScheduleExpression expr = new ScheduleExpression().dayOfMonth(6).hour("24/1").minute(1).second(59).start(new Date(0));
+    boolean parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);
+    
+    
+    }
+	
+	
+	@Test(timeout = 500)
+    public void testInvalidSingleInputs() throws ParseException {
+	
+	// invalid day of month
+    ScheduleExpression expr = new ScheduleExpression().dayOfMonth(-8).hour(23).minute(1).second(59).start(new Date(0));
+    
+    boolean parseExceptionThrown = false;
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);
+    
+    
+    // invalid  year
+    expr = new ScheduleExpression().year(98).month(5).dayOfMonth(6).hour(2).minute(1).second(59).start(new Date(0));
+    parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);        
+    
+    // invalid  month
+    expr = new ScheduleExpression().month(-4).dayOfMonth(6).hour(2).minute(1).second(59).start(new Date(0));
+    parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);
+    
+    // invalid  days in week
+    expr = new ScheduleExpression().month(-4).dayOfWeek(9).hour(2).minute(1).second(59).start(new Date(0));
+    parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown); 
+    
+    
+    // invalid  month
+    expr = new ScheduleExpression().month("XXXX").dayOfMonth(6).hour(2).minute(1).second(59).start(new Date(0));
+    parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);  
+    
+    // invalid  hour
+    expr = new ScheduleExpression().dayOfMonth(6).hour("-4").minute(1).second(59).start(new Date(0));
+    parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);
+    
+    
+    // invalid  hour
+    expr = new ScheduleExpression().dayOfMonth(6).hour("24/2").minute(1).second(59).start(new Date(0));
+    parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);
+    
+    
+    // invalid  minute	
+    expr = new ScheduleExpression().dayOfMonth(6).hour(2).minute(-1).second(59).start(new Date(0));
+    parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);
+    
+    // invalid  second      
+    expr = new ScheduleExpression().dayOfMonth(6).hour(2).minute(1).second(-4).start(new Date(0));
+    parseExceptionThrown = false;
+    
+    try {
+        new EJBCronTrigger(expr);
+    } catch (ParseException e){
+        parseExceptionThrown=true;
+    }
+    assertTrue(parseExceptionThrown);
+    
+    
+    }
+	
+	@Test(timeout = 500)
+    public void testInvalidListInputs() throws ParseException {
+    
+	    // invalid day of month
+	    String invalid_day_of_month="2ndXXX,-8";
+	    ScheduleExpression expr = new ScheduleExpression().dayOfMonth("1stsun,4,6,"+invalid_day_of_month).hour(23).minute(1).second(59).start(new Date(0));
+	    
+	    boolean parseExceptionThrown = false;
+	    try {
+	        new EJBCronTrigger(expr);
+	    } catch (ParseException e){
+	        parseExceptionThrown=true;
+	    }
+	    assertTrue(parseExceptionThrown);
+	    
+	    
+	    // invalid  year
+	    String invalid_years = "19876,87";
+	    expr = new ScheduleExpression().year("1999,2012"+invalid_years).month(5).dayOfMonth(6).hour(2).minute(1).second(59).start(new Date(0));
+	    parseExceptionThrown = false;
+	    
+	    try {
+	        new EJBCronTrigger(expr);
+	    } catch (ParseException e){
+	        parseExceptionThrown=true;
+	    }
+	    assertTrue(parseExceptionThrown);        
+	    
+	    
+	    // invalid  month
+	    String invalid_month = "XXX,14";
+	    expr = new ScheduleExpression().month("1,2,4,sep,"+invalid_month).dayOfMonth(6).hour(2).minute(1).second(59).start(new Date(0));
+	    parseExceptionThrown = false;
+	    
+	    try {
+	        new EJBCronTrigger(expr);
+	    } catch (ParseException e){
+	        parseExceptionThrown=true;
+	    }
+	    assertTrue(parseExceptionThrown);
+	    
+	    // invalid  days in week
+	    String invalid_days_in_week = "8,WEEE";
+	    expr = new ScheduleExpression().month(5).dayOfWeek("SUN,4,5,"+ invalid_days_in_week).hour(2).minute(1).second(59).start(new Date(0));
+	    parseExceptionThrown = false;
+	    
+	    try {
+	        new EJBCronTrigger(expr);
+	    } catch (ParseException e){
+	        parseExceptionThrown=true;
+	    }
+	    assertTrue(parseExceptionThrown); 
+	    
+	    
+	    
+	    // invalid  hours
+        String invalid_hours="15,-2";	    
+	    
+	    expr = new ScheduleExpression().dayOfMonth(6).hour("1,5,9,18,22,"+invalid_hours).minute(1).second(59).start(new Date(0));
+	    parseExceptionThrown = false;
+	    
+	    try {
+	        new EJBCronTrigger(expr);
+	    } catch (ParseException e){
+	        parseExceptionThrown=true;
+	    }
+	    assertTrue(parseExceptionThrown);
+	    
+	    // invalid  minute  
+	    String invalid_minutes="61,-4";
+	    expr = new ScheduleExpression().dayOfMonth(6).hour(2).minute("1,45,58,"+invalid_minutes).second(59).start(new Date(0));
+	    parseExceptionThrown = false;
+	    
+	    try {
+	        new EJBCronTrigger(expr);
+	    } catch (ParseException e){
+	        parseExceptionThrown=true;
+	    }
+	    assertTrue(parseExceptionThrown);
+	    
+	    // invalid  second   
+	    String invalid_seconds="61,-4";
+	    expr = new ScheduleExpression().dayOfMonth(6).hour(2).minute(1).second("1,45,58,"+invalid_seconds).start(new Date(0));
+	    parseExceptionThrown = false;
+	    
+	    try {
+	        new EJBCronTrigger(expr);
+	    } catch (ParseException e){
+	        parseExceptionThrown=true;
+	    }
+	    assertTrue(parseExceptionThrown);
+    
+    }
+	
+	
 }