1
2 package org.objectledge.scheduler.cron;
3
4 import java.io.StringReader;
5 import java.io.FileInputStream;
6 import java.io.InputStreamReader;
7 import java.io.PrintWriter;
8 import java.io.Reader;
9
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.Iterator;
13 import java.util.Collections;
14
15 public class CronParser implements CronParserConstants {
16
17
18 private static final String[] monthName = new String[] {
19 "",
20 "jan" , "feb" , "mar" , "apr" , "may" , "jun" ,
21 "jul" , "aug" , "sep" , "oct" , "nov" , "dec" };
22
23 private static final String[] weekdayName = new String[] {
24 "sun", "mon" , "tue" , "wed" , "thu" , "fri" , "sat" };
25
26 private static final int[][] spec_reboot = new int[][] {};
27
28 private static final int[][] spec_yearly = new int[][]
29 { { 0 }, { 0 }, { 1 }, { 1 }, { } };
30
31 private static final int[][] spec_monthly = new int[][]
32 { { 0 }, { 0 }, { 1 }, { }, { } };
33
34 private static final int[][] spec_weekly = new int[][]
35 { { 0 }, { 0 }, { }, { }, { 0 } };
36
37 private static final int[][] spec_daily = new int[][]
38 { { 0 }, { 0 }, { }, { }, { } };
39
40 private static final int[][] spec_hourly = new int[][]
41 { { 0 }, { }, { }, { }, { } };
42
43 public int[][] parse(String config)
44 throws ParseException,
45 ValueOutOfRangeException
46 {
47 StringReader sr = new StringReader(config);
48 ReInit(sr);
49 return cron_config();
50 }
51
52
53
54 public static void main(String[] args)
55 throws Exception
56 {
57 FileInputStream fis = new FileInputStream(args[0]);
58 Reader reader = new InputStreamReader(fis, "ISO-8859-2");
59 CronParser parser = new CronParser(reader);
60 parser.test();
61 }
62
63 public static void dump(int[][] config)
64 {
65 if(config.length == 0)
66 {
67 System.out.print("@reboot");
68 }
69 else
70 {
71 for(int i=0; i<config.length; i++)
72 {
73 if(config[i].length == 0)
74 {
75 System.out.print("*");
76 }
77 else
78 {
79 for(int j=0; j<config[i].length; j++)
80 {
81 System.out.print(config[i][j]);
82 if(j < config[i].length - 1)
83 {
84 System.out.print(",");
85 }
86 }
87 }
88 if(i < config.length - 1)
89 {
90 System.out.print(" ");
91 }
92 }
93 }
94 System.out.println();
95 }
96
97
98 final public int number(int min, int max) throws ParseException {
99 Token t;
100 t = jj_consume_token(NUMBER);
101 int v = Integer.parseInt(t.image);
102 if(min > 0 && max > 0 && (v < min || v > max))
103 {
104 {if (true) throw new ValueOutOfRangeException(t, v, min, max);}
105 }
106 {if (true) return v;}
107 throw new Error("Missing return statement in function");
108 }
109
110 final public List range(int min, int max) throws ParseException {
111 int start, end;
112 int step = -1;
113 start = number(min,max);
114 jj_consume_token(5);
115 end = number(min,max);
116 switch (jj_nt.kind) {
117 case 6:
118 jj_consume_token(6);
119 step = number(-1,-1);
120 break;
121 default:
122 jj_la1[0] = jj_gen;
123 ;
124 }
125 List result = new ArrayList();
126 if(step < 0)
127 {
128 step = 1;
129 }
130 for(int i=start; i<=end; i+=step)
131 {
132 result.add(new Integer(i));
133 }
134 {if (true) return result;}
135 throw new Error("Missing return statement in function");
136 }
137
138 final public List value_or_range(int min, int max) throws ParseException {
139 Token value = null;
140 List range = null;
141 if (jj_2_1(2)) {
142 range = range(min, max);
143 } else {
144 switch (jj_nt.kind) {
145 case NUMBER:
146 value = jj_consume_token(NUMBER);
147 break;
148 default:
149 jj_la1[1] = jj_gen;
150 jj_consume_token(-1);
151 throw new ParseException();
152 }
153 }
154 if(value != null)
155 {
156 List result = new ArrayList();
157 result.add(new Integer(value.image));
158 {if (true) return result;}
159 }
160 else
161 {
162 {if (true) return range;}
163 }
164 throw new Error("Missing return statement in function");
165 }
166
167 final public List list_of_values(int min, int max) throws ParseException {
168 List temp = new ArrayList();
169 List var;
170 var = value_or_range(min, max);
171 temp.add(var);
172 label_1:
173 while (true) {
174 switch (jj_nt.kind) {
175 case 7:
176 ;
177 break;
178 default:
179 jj_la1[2] = jj_gen;
180 break label_1;
181 }
182 jj_consume_token(7);
183 var = value_or_range(min, max);
184 temp.add(var);
185 }
186 List result = new ArrayList();
187 Iterator i = temp.iterator();
188 while(i.hasNext())
189 {
190 result.addAll((List)i.next());
191 }
192 Collections.sort(result);
193 {if (true) return result;}
194 throw new Error("Missing return statement in function");
195 }
196
197 final public int[] value_spec(int min, int max) throws ParseException {
198 List list=null;
199 switch (jj_nt.kind) {
200 case 8:
201 jj_consume_token(8);
202 break;
203 case NUMBER:
204 list = list_of_values(min, max);
205 break;
206 default:
207 jj_la1[3] = jj_gen;
208 jj_consume_token(-1);
209 throw new ParseException();
210 }
211 if(list == null)
212 {
213 {if (true) return new int[0];}
214 }
215 else
216 {
217 int[] result = new int[list.size()];
218 for(int i=0; i < list.size(); i++)
219 {
220 result[i] = ((Integer)list.get(i)).intValue();
221 }
222 {if (true) return result;}
223 }
224 throw new Error("Missing return statement in function");
225 }
226
227 final public int[] month_name() throws ParseException {
228 switch (jj_nt.kind) {
229 case 9:
230 jj_consume_token(9);
231 break;
232 case 10:
233 jj_consume_token(10);
234 break;
235 case 11:
236 jj_consume_token(11);
237 break;
238 case 12:
239 jj_consume_token(12);
240 break;
241 case 13:
242 jj_consume_token(13);
243 break;
244 case 14:
245 jj_consume_token(14);
246 break;
247 case 15:
248 jj_consume_token(15);
249 break;
250 case 16:
251 jj_consume_token(16);
252 break;
253 case 17:
254 jj_consume_token(17);
255 break;
256 case 18:
257 jj_consume_token(18);
258 break;
259 case 19:
260 jj_consume_token(19);
261 break;
262 case 20:
263 jj_consume_token(20);
264 break;
265 default:
266 jj_la1[4] = jj_gen;
267 jj_consume_token(-1);
268 throw new ParseException();
269 }
270 String t = getToken(0).image;
271 for(int i=0; i<12; i++)
272 if(monthName[i].equals(t))
273 {
274 {if (true) return new int[] { i };}
275 }
276 {if (true) throw new InternalError();}
277 throw new Error("Missing return statement in function");
278 }
279
280 final public int[] weekday_name() throws ParseException {
281 switch (jj_nt.kind) {
282 case 21:
283 jj_consume_token(21);
284 break;
285 case 22:
286 jj_consume_token(22);
287 break;
288 case 23:
289 jj_consume_token(23);
290 break;
291 case 24:
292 jj_consume_token(24);
293 break;
294 case 25:
295 jj_consume_token(25);
296 break;
297 case 26:
298 jj_consume_token(26);
299 break;
300 case 27:
301 jj_consume_token(27);
302 break;
303 default:
304 jj_la1[5] = jj_gen;
305 jj_consume_token(-1);
306 throw new ParseException();
307 }
308 String t = getToken(0).image;
309 for(int i=0; i<7; i++)
310 if(weekdayName[i].equals(t))
311 {
312 {if (true) return new int[] { i };}
313 }
314 {if (true) throw new InternalError();}
315 throw new Error("Missing return statement in function");
316 }
317
318 final public int[][] special_config() throws ParseException {
319 switch (jj_nt.kind) {
320 case 28:
321 jj_consume_token(28);
322 {if (true) return spec_reboot;}
323 break;
324 case 29:
325 jj_consume_token(29);
326 {if (true) return spec_yearly;}
327 break;
328 case 30:
329 jj_consume_token(30);
330 {if (true) return spec_yearly;}
331 break;
332 case 31:
333 jj_consume_token(31);
334 {if (true) return spec_monthly;}
335 break;
336 case 32:
337 jj_consume_token(32);
338 {if (true) return spec_daily;}
339 break;
340 case 33:
341 jj_consume_token(33);
342 {if (true) return spec_daily;}
343 break;
344 case 34:
345 jj_consume_token(34);
346 {if (true) return spec_hourly;}
347 break;
348 default:
349 jj_la1[6] = jj_gen;
350 jj_consume_token(-1);
351 throw new ParseException();
352 }
353 throw new Error("Missing return statement in function");
354 }
355
356 final public int[][] cron_config() throws ParseException {
357 int[] minute = null;
358 int[] hour = null;
359 int[] day = null;
360 int[] month = null;
361 int[] weekday = null;
362 int[][] special = null;
363 switch (jj_nt.kind) {
364 case 28:
365 case 29:
366 case 30:
367 case 31:
368 case 32:
369 case 33:
370 case 34:
371 special = special_config();
372 break;
373 case NUMBER:
374 case 8:
375 minute = value_spec(0,59);
376 hour = value_spec(0,23);
377 day = value_spec(1,31);
378 switch (jj_nt.kind) {
379 case 9:
380 case 10:
381 case 11:
382 case 12:
383 case 13:
384 case 14:
385 case 15:
386 case 16:
387 case 17:
388 case 18:
389 case 19:
390 case 20:
391 month = month_name();
392 break;
393 case NUMBER:
394 case 8:
395 month = value_spec(1,12);
396 break;
397 default:
398 jj_la1[7] = jj_gen;
399 jj_consume_token(-1);
400 throw new ParseException();
401 }
402 switch (jj_nt.kind) {
403 case 21:
404 case 22:
405 case 23:
406 case 24:
407 case 25:
408 case 26:
409 case 27:
410 weekday = weekday_name();
411 break;
412 case NUMBER:
413 case 8:
414 weekday = value_spec(0,7);
415 break;
416 default:
417 jj_la1[8] = jj_gen;
418 jj_consume_token(-1);
419 throw new ParseException();
420 }
421 break;
422 default:
423 jj_la1[9] = jj_gen;
424 jj_consume_token(-1);
425 throw new ParseException();
426 }
427 if(special != null)
428 {
429 {if (true) return special;}
430 }
431 else
432 {
433 int[][] result = new int[5][];
434 result[0] = minute;
435 result[1] = hour;
436 result[2] = day;
437 for(int i=0; i<month.length; i++)
438 {
439 month[i] -= 1;
440 }
441 result[3] = month;
442 for(int i=0; i<weekday.length; i++)
443 {
444 weekday[i] = (weekday[i] % 7) + 1;
445 }
446 result[4] = weekday;
447 {if (true) return result;}
448 }
449 throw new Error("Missing return statement in function");
450 }
451
452 final public void test() throws ParseException {
453 int[][] config;
454 config = cron_config();
455 dump(config);
456 label_2:
457 while (true) {
458 switch (jj_nt.kind) {
459 case 35:
460 ;
461 break;
462 default:
463 jj_la1[10] = jj_gen;
464 break label_2;
465 }
466 jj_consume_token(35);
467 config = cron_config();
468 dump(config);
469 }
470 }
471
472 final private boolean jj_2_1(int xla) {
473 jj_la = xla; jj_lastpos = jj_scanpos = token;
474 try { return !jj_3_1(); }
475 catch(LookaheadSuccess ls) { return true; }
476 finally { jj_save(0, xla); }
477 }
478
479 final private boolean jj_3_1() {
480 if (jj_3R_3()) return true;
481 return false;
482 }
483
484 final private boolean jj_3R_3() {
485 if (jj_3R_4()) return true;
486 if (jj_scan_token(5)) return true;
487 return false;
488 }
489
490 final private boolean jj_3R_4() {
491 if (jj_scan_token(NUMBER)) return true;
492 return false;
493 }
494
495 public CronParserTokenManager token_source;
496 JavaCharStream jj_input_stream;
497 public Token token, jj_nt;
498 private Token jj_scanpos, jj_lastpos;
499 private int jj_la;
500 public boolean lookingAhead = false;
501 private boolean jj_semLA;
502 private int jj_gen;
503 final private int[] jj_la1 = new int[11];
504 static private int[] jj_la1_0;
505 static private int[] jj_la1_1;
506 static {
507 jj_la1_0();
508 jj_la1_1();
509 }
510 private static void jj_la1_0() {
511 jj_la1_0 = new int[] {0x40,0x10,0x80,0x110,0x1ffe00,0xfe00000,0xf0000000,0x1fff10,0xfe00110,0xf0000110,0x0,};
512 }
513 private static void jj_la1_1() {
514 jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x7,0x8,};
515 }
516 final private JJCalls[] jj_2_rtns = new JJCalls[1];
517 private boolean jj_rescan = false;
518 private int jj_gc = 0;
519
520 public CronParser(java.io.InputStream stream) {
521 jj_input_stream = new JavaCharStream(stream, 1, 1);
522 token_source = new CronParserTokenManager(jj_input_stream);
523 token = new Token();
524 token.next = jj_nt = token_source.getNextToken();
525 jj_gen = 0;
526 for (int i = 0; i < 11; i++) jj_la1[i] = -1;
527 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
528 }
529
530 public void ReInit(java.io.InputStream stream) {
531 jj_input_stream.ReInit(stream, 1, 1);
532 token_source.ReInit(jj_input_stream);
533 token = new Token();
534 token.next = jj_nt = token_source.getNextToken();
535 jj_gen = 0;
536 for (int i = 0; i < 11; i++) jj_la1[i] = -1;
537 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
538 }
539
540 public CronParser(java.io.Reader stream) {
541 jj_input_stream = new JavaCharStream(stream, 1, 1);
542 token_source = new CronParserTokenManager(jj_input_stream);
543 token = new Token();
544 token.next = jj_nt = token_source.getNextToken();
545 jj_gen = 0;
546 for (int i = 0; i < 11; i++) jj_la1[i] = -1;
547 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
548 }
549
550 public void ReInit(java.io.Reader stream) {
551 jj_input_stream.ReInit(stream, 1, 1);
552 token_source.ReInit(jj_input_stream);
553 token = new Token();
554 token.next = jj_nt = token_source.getNextToken();
555 jj_gen = 0;
556 for (int i = 0; i < 11; i++) jj_la1[i] = -1;
557 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
558 }
559
560 public CronParser(CronParserTokenManager tm) {
561 token_source = tm;
562 token = new Token();
563 token.next = jj_nt = token_source.getNextToken();
564 jj_gen = 0;
565 for (int i = 0; i < 11; i++) jj_la1[i] = -1;
566 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
567 }
568
569 public void ReInit(CronParserTokenManager tm) {
570 token_source = tm;
571 token = new Token();
572 token.next = jj_nt = token_source.getNextToken();
573 jj_gen = 0;
574 for (int i = 0; i < 11; i++) jj_la1[i] = -1;
575 for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
576 }
577
578 final private Token jj_consume_token(int kind) throws ParseException {
579 Token oldToken = token;
580 if ((token = jj_nt).next != null) jj_nt = jj_nt.next;
581 else jj_nt = jj_nt.next = token_source.getNextToken();
582 if (token.kind == kind) {
583 jj_gen++;
584 if (++jj_gc > 100) {
585 jj_gc = 0;
586 for (int i = 0; i < jj_2_rtns.length; i++) {
587 JJCalls c = jj_2_rtns[i];
588 while (c != null) {
589 if (c.gen < jj_gen) c.first = null;
590 c = c.next;
591 }
592 }
593 }
594 return token;
595 }
596 jj_nt = token;
597 token = oldToken;
598 jj_kind = kind;
599 throw generateParseException();
600 }
601
602 static private final class LookaheadSuccess extends java.lang.Error { }
603 final private LookaheadSuccess jj_ls = new LookaheadSuccess();
604 final private boolean jj_scan_token(int kind) {
605 if (jj_scanpos == jj_lastpos) {
606 jj_la--;
607 if (jj_scanpos.next == null) {
608 jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
609 } else {
610 jj_lastpos = jj_scanpos = jj_scanpos.next;
611 }
612 } else {
613 jj_scanpos = jj_scanpos.next;
614 }
615 if (jj_rescan) {
616 int i = 0; Token tok = token;
617 while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
618 if (tok != null) jj_add_error_token(kind, i);
619 }
620 if (jj_scanpos.kind != kind) return true;
621 if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
622 return false;
623 }
624
625 final public Token getNextToken() {
626 if ((token = jj_nt).next != null) jj_nt = jj_nt.next;
627 else jj_nt = jj_nt.next = token_source.getNextToken();
628 jj_gen++;
629 return token;
630 }
631
632 final public Token getToken(int index) {
633 Token t = lookingAhead ? jj_scanpos : token;
634 for (int i = 0; i < index; i++) {
635 if (t.next != null) t = t.next;
636 else t = t.next = token_source.getNextToken();
637 }
638 return t;
639 }
640
641 private java.util.Vector jj_expentries = new java.util.Vector();
642 private int[] jj_expentry;
643 private int jj_kind = -1;
644 private int[] jj_lasttokens = new int[100];
645 private int jj_endpos;
646
647 private void jj_add_error_token(int kind, int pos) {
648 if (pos >= 100) return;
649 if (pos == jj_endpos + 1) {
650 jj_lasttokens[jj_endpos++] = kind;
651 } else if (jj_endpos != 0) {
652 jj_expentry = new int[jj_endpos];
653 for (int i = 0; i < jj_endpos; i++) {
654 jj_expentry[i] = jj_lasttokens[i];
655 }
656 boolean exists = false;
657 for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) {
658 int[] oldentry = (int[])(e.nextElement());
659 if (oldentry.length == jj_expentry.length) {
660 exists = true;
661 for (int i = 0; i < jj_expentry.length; i++) {
662 if (oldentry[i] != jj_expentry[i]) {
663 exists = false;
664 break;
665 }
666 }
667 if (exists) break;
668 }
669 }
670 if (!exists) jj_expentries.addElement(jj_expentry);
671 if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
672 }
673 }
674
675 public ParseException generateParseException() {
676 jj_expentries.removeAllElements();
677 boolean[] la1tokens = new boolean[36];
678 for (int i = 0; i < 36; i++) {
679 la1tokens[i] = false;
680 }
681 if (jj_kind >= 0) {
682 la1tokens[jj_kind] = true;
683 jj_kind = -1;
684 }
685 for (int i = 0; i < 11; i++) {
686 if (jj_la1[i] == jj_gen) {
687 for (int j = 0; j < 32; j++) {
688 if ((jj_la1_0[i] & (1<<j)) != 0) {
689 la1tokens[j] = true;
690 }
691 if ((jj_la1_1[i] & (1<<j)) != 0) {
692 la1tokens[32+j] = true;
693 }
694 }
695 }
696 }
697 for (int i = 0; i < 36; i++) {
698 if (la1tokens[i]) {
699 jj_expentry = new int[1];
700 jj_expentry[0] = i;
701 jj_expentries.addElement(jj_expentry);
702 }
703 }
704 jj_endpos = 0;
705 jj_rescan_token();
706 jj_add_error_token(0, 0);
707 int[][] exptokseq = new int[jj_expentries.size()][];
708 for (int i = 0; i < jj_expentries.size(); i++) {
709 exptokseq[i] = (int[])jj_expentries.elementAt(i);
710 }
711 return new ParseException(token, exptokseq, tokenImage);
712 }
713
714 final public void enable_tracing() {
715 }
716
717 final public void disable_tracing() {
718 }
719
720 final private void jj_rescan_token() {
721 jj_rescan = true;
722 for (int i = 0; i < 1; i++) {
723 JJCalls p = jj_2_rtns[i];
724 do {
725 if (p.gen > jj_gen) {
726 jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
727 switch (i) {
728 case 0: jj_3_1(); break;
729 }
730 }
731 p = p.next;
732 } while (p != null);
733 }
734 jj_rescan = false;
735 }
736
737 final private void jj_save(int index, int xla) {
738 JJCalls p = jj_2_rtns[index];
739 while (p.gen > jj_gen) {
740 if (p.next == null) { p = p.next = new JJCalls(); break; }
741 p = p.next;
742 }
743 p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
744 }
745
746 static final class JJCalls {
747 int gen;
748 Token first;
749 int arg;
750 JJCalls next;
751 }
752
753 }