/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://oss.oracle.com/licenses/CDDL+GPL-1.1 * or LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.s1asdev.ejb31.timer.schedule_exp; import javax.ejb.*; import javax.interceptor.AroundTimeout; import javax.interceptor.InvocationContext; import javax.annotation.Resource; import java.util.Map; import java.util.Set; import java.util.Collection; import java.util.HashSet; import java.util.HashMap; import java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; @Stateless public class StlesEJB implements Stles { @Resource private TimerService timerSvc; private static Map<String, ScheduleExpression> hm = new HashMap<String, ScheduleExpression>(); private static Set<String> callers = new HashSet<String>(); private static Set<String> expected_callers = new HashSet<String>(); public void createTimers() throws Exception { Calendar now = new GregorianCalendar(); int month = (now.get(Calendar.MONTH) + 1); // Calendar starts with 0 int dayOfMonth = now.get(Calendar.DAY_OF_MONTH); System.out.println("createTimers(): creating timer with 5 sec "); ScheduleExpression se = new ScheduleExpression().second("*/5").minute("*").hour("*"); TimerConfig tc = new TimerConfig("timer-5-sec", true); createTimer(se, tc); expected_callers.add("" + tc.getInfo()); int dayOfWeek = (now.get(Calendar.DAY_OF_WEEK) - 1); // SUN is 1 System.out.println("createTimers(): creating timer with dayOfWeek=today-today (" + dayOfWeek + "-" + dayOfWeek + ") "); se = new ScheduleExpression().second("2 / 5").minute("*").hour("*"). dayOfWeek("" + dayOfWeek+" - " + dayOfWeek); tc = new TimerConfig("timer-dayOfWeek=" + dayOfWeek + "-" + dayOfWeek, false); createTimer(se, tc); expected_callers.add("" + tc.getInfo()); System.out.println("createTimers(): creating timer with dayOfWeek=0-7 "); se = new ScheduleExpression().second("2/2").minute(" * ").hour("*").dayOfWeek("0-7"); tc = new TimerConfig("timer-dayOfWeek=0-7", true); createTimer(se, tc); expected_callers.add("" + tc.getInfo()); int hour = now.get(Calendar.HOUR_OF_DAY); int h0 = (hour < 2) ? 24 : hour; int h1 = (hour > 21) ? hour - 24 : hour; String s = "" + (h0 - 1) + " - " + (h1 + 2); int second = now.get(Calendar.SECOND); if (second >= 55) { second -= 60; } System.out.println("createTimers(): creating timer with second=" + (second + 5) + ", hour=" + s ); se = new ScheduleExpression().second(second + 5).minute("*").hour(s); String s1 = "" + (h0 - 1) + "-" + (h1 + 2); tc = new TimerConfig("timer-hour=" + s1, false); createTimer(se, tc); expected_callers.add("" + tc.getInfo()); System.out.println("createTimers(): creating timer with year=3000,2007, 4096 "); se = new ScheduleExpression().second("*").minute("*").hour("*").year("3000,2007, 4096"); tc = new TimerConfig("timer-year=3000,2007, 4096", true); createTimer(se, tc); System.out.println("createTimers(): creating timer with dayOfMonth=Last "); se = new ScheduleExpression().second("*").minute("*").hour("*").dayOfMonth("Last"); tc = new TimerConfig("timer-dayOfMonth=Last", false); createTimer(se, tc); System.out.println("createTimers(): creating timer with dayOfMonth=Last Sun "); se = new ScheduleExpression().second("*").minute("*").hour("*").dayOfMonth("Last Sun"); tc = new TimerConfig("timer-dayOfMonth=Last Sun", true); createTimer(se, tc); System.out.println("createTimers(): creating timer with dayOfMonth=-4--2 "); se = new ScheduleExpression().second("*").minute("*").hour("*").dayOfMonth("-4--2"); tc = new TimerConfig("timer-dayOfMonth=-4--2", false); createTimer(se, tc); System.out.println("createTimers(): creating never expired (Feb 29 non-leap year) timer "); se = new ScheduleExpression().dayOfMonth(29).month("FEB"). year("2007-2011, 2013-2015, 2017-2019"); tc = new TimerConfig("timer-02-29-non-leap-year", true); createTimer(se, tc); try { System.out.println("createTimers(): creating wrong (year before 1971) timer "); se = new ScheduleExpression().year("1966"); tc = new TimerConfig("timer-1966", true); createTimer(se, tc); throw new EJBException("Timer with year before 1971 was created"); } catch (IllegalArgumentException e) { System.out.println("createTimers(): caught expected IllegalArgumentException"); } try { System.out.println("createTimers(): creating wrong (month 1/5) timer "); se = new ScheduleExpression().month("1/5"); tc = new TimerConfig("timer-1/5", true); createTimer(se, tc); throw new EJBException("Timer with month 1/5 was created"); } catch (IllegalArgumentException e) { System.out.println("createTimers(): caught expected IllegalArgumentException"); } try { System.out.println("createTimers(): creating wrong (seconds -5) timer "); se = new ScheduleExpression().second("-5"); tc = new TimerConfig("timer-negative-seconds-5", true); createTimer(se, tc); throw new EJBException("Timer with negative 5 seconds was created"); } catch (IllegalArgumentException e) { System.out.println("createTimers(): caught expected IllegalArgumentException"); } try { System.out.println("createTimers(): creating wrong (seconds AB) timer "); se = new ScheduleExpression().second("AB"); tc = new TimerConfig("timer-negative-secondsAB", true); createTimer(se, tc); throw new EJBException("Timer with seconds AB was created"); } catch (IllegalArgumentException e) { System.out.println("createTimers(): caught expected IllegalArgumentException"); } try { System.out.println("createTimers(): creating wrong (month ABC) timer "); se = new ScheduleExpression().month("ABC"); tc = new TimerConfig("timer-month-ABC", true); createTimer(se, tc); throw new EJBException("Timer with month ABC was created"); } catch (IllegalArgumentException e) { System.out.println("createTimers(): caught expected IllegalArgumentException"); } } public void verifyTimers() { Collection<Timer> ts = timerSvc.getTimers(); Set<String> errors = new HashSet<String>(); for(Timer t : ts) { ScheduleExpression s = hm.remove("" + t.getInfo()); if (s == null) { errors.add("" + t.getInfo()); } t.cancel(); } if (!expected_callers.isEmpty()) { StringBuffer sb = new StringBuffer(); for (String c : expected_callers) { sb.append(c).append(", "); } throw new EJBException("Timers DID NOT expire for infos: " + sb.toString() ); } if (callers.isEmpty()) { throw new EJBException("NO Timers expired!"); } else { StringBuffer sb = new StringBuffer(); for (String c : callers) { sb.append(c).append(", "); } System.out.println("Timers expired for infos: " + sb.toString() ); } if (!errors.isEmpty()) { StringBuffer sb = new StringBuffer(); for (String e : errors) { sb.append("" + e).append(", "); } throw new EJBException("Internal error: ScheduleExpressions for infos: " + sb.toString() + " were not available at verify!"); } if (timerSvc.getTimers().size() != 0) { throw new EJBException("After cencel, timerSvc.getTimers().size() = " + timerSvc.getTimers().size()); } } private void createTimer(ScheduleExpression se, TimerConfig tc) throws Exception { Timer t = timerSvc.createCalendarTimer(se, tc); verifyTimer(t, se, tc); hm.put("" + tc.getInfo(), se); System.out.println("Created timer #" + timerSvc.getTimers().size()); } private void verifyTimer(Timer t) { verifyTimer(t, hm.get("" + t.getInfo()), null); } private void verifyTimer(Timer t, ScheduleExpression se0, TimerConfig tc0) { String info = "" + t.getInfo(); if (tc0 != null) { boolean p = t.isPersistent(); if (p != tc0.isPersistent()) { throw new IllegalStateException("Timer " + info + " persistence is not as expected"); } assertSame(info, tc0.getInfo(), "" + info, "INFO"); } ScheduleExpression tse = t.getSchedule(); if (!tse.getSecond().trim().equals(se0.getSecond().trim()) ) { throw new IllegalStateException("Timer " + info + " SECONDS is not as expected: " + tse.getSecond()); } if (!tse.getMinute().trim().equals(se0.getMinute().trim()) ) { throw new IllegalStateException("Timer " + info + " MINUTES is not as expected: " + tse.getMinute()); } if (!tse.getHour().trim().equals(se0.getHour().trim()) ) { throw new IllegalStateException("Timer " + info + " HOUR is not as expected: " + tse.getHour()); } if (!tse.getDayOfMonth().trim().equals(se0.getDayOfMonth().trim()) ) { throw new IllegalStateException("Timer " + info + " DAY_OF_MONTH is not as expected: " + tse.getDayOfMonth()); } if (!tse.getMonth().trim().equals(se0.getMonth().trim()) ) { throw new IllegalStateException("Timer " + info + " MONTH is not as expected: " + tse.getMonth()); } if (!tse.getDayOfWeek().trim().equals(se0.getDayOfWeek().trim()) ) { throw new IllegalStateException("Timer " + info + " DAY_OF_WEEK is not as expected: " + tse.getDayOfWeek()); } if (!tse.getYear().trim().equals(se0.getYear().trim()) ) { throw new IllegalStateException("Timer " + info + " YEAR is not as expected: " + tse.getYear()); } assertSame(tse.getTimezone(), se0.getTimezone(), "" + info, "TZ"); assertSame(tse.getStart(), se0.getStart(), "" + info, "START"); assertSame(tse.getEnd(), se0.getEnd(), "" + info, "END"); } private void assertSame(Object test, Object orig, String info, String name) { if (test != null && orig == null) { throw new IllegalStateException("Timer " + info + " " + name + " is not null as expected"); } if (test == null && orig != null) { throw new IllegalStateException("Timer " + info + " " + name + " is null"); } if (test != null && !test.equals(orig)) { throw new IllegalStateException("Timer " + info + " " + name + " is not as expected: " + test); } } @Timeout public void timeout(Timer t) { System.out.println("in StlesEJB:timeout " + t.getInfo() + " - persistent: " + t.isPersistent()); if (!t.isCalendarTimer()) { throw new IllegalStateException("Timer " + t.getInfo() + " is not schedule based timer"); } verifyTimer(t); callers.add("" + t.getInfo()); expected_callers.remove("" + t.getInfo()); } @AroundTimeout private Object xxx(InvocationContext ctx) throws Exception { System.out.println("in StlesEJB:xxx " + ((Timer)ctx.getTimer()).getInfo() ); return ctx.proceed(); } }