/* * 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_ann; import javax.ejb.*; import javax.annotation.Resource; import java.util.Map; import java.util.Set; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.HashMap; import java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.concurrent.atomic.AtomicBoolean; @Stateless public class StlesEJB implements Stles { @Resource private TimerService timerSvc; private static Map<String, ScheduleExpression> hm = Collections.synchronizedMap(new HashMap<String, ScheduleExpression>()); private static Set<String> callers = Collections.synchronizedSet(new HashSet<String>()); private static Set<String> expected_callers = Collections.synchronizedSet(new HashSet<String>()); private static Set<String> errors = Collections.synchronizedSet(new HashSet<String>()); private static AtomicBoolean verifying = new AtomicBoolean(false); static { ScheduleExpression se = new ScheduleExpression().second("*/5").minute("*").hour("*"); expected_callers.add("timer-5-sec"); hm.put("timer-5-sec", se); se = new ScheduleExpression().second("*").minute("*").hour("*"); expected_callers.add("timer-every-sec"); hm.put("timer-every-sec", se); se = new ScheduleExpression().second("2/2").minute(" * ").hour("*").dayOfWeek("0-7"); expected_callers.add("another-timer-dayOfWeek=0-7"); hm.put("another-timer-dayOfWeek=0-7", se); se = new ScheduleExpression().second("3/2").minute(" * ").hour("12-11"); expected_callers.add("timer-NO-ARG-hour=12-11"); hm.put("timer-NO-ARG-hour=12-11", se); se = new ScheduleExpression().second("*/2").minute(" * ").hour("*"); expected_callers.add("dd_timer1"); hm.put("dd_timer1", se); se = new ScheduleExpression().second("*/4").minute(" * ").hour("*"); expected_callers.add("dd_timer2"); hm.put("dd_timer2", se); se = new ScheduleExpression().second("*").minute("*").hour("*").year("3000,2007, 4096"); hm.put("timer-year=3000,2007, 4096", se); se = new ScheduleExpression().second("*").minute("*").hour("*").dayOfMonth("Last"); hm.put("timer-dayOfMonth=Last", se); se = new ScheduleExpression().second("*").minute("*").hour("*").dayOfMonth("Last Sun"); hm.put("timer-dayOfMonth=Last Sun", se); se = new ScheduleExpression().second("*").minute("*").hour("*").dayOfMonth("-4--2"); hm.put("timer-dayOfMonth=-4--2", se); se = new ScheduleExpression().dayOfMonth(29).month("FEB"). year("2007-2011, 2013-2015, 2017-2019"); hm.put("timer-02-29-non-leap-year", se); } public void verifyTimers() { verifying.set(true); if (!errors.isEmpty()) { StringBuffer sb = new StringBuffer(); for (String e : errors) { sb.append("" + e).append(", "); } throw new EJBException("Timers SHOULD NOT expire for infos: " + sb.toString() ); } Collection<Timer> ts = timerSvc.getTimers(); for(Timer t : ts) { String info = "" + t.getInfo(); t.cancel(); ScheduleExpression s = hm.remove(info); if (s == null) { errors.add(info); } } if (!expected_callers.isEmpty()) { System.out.println("Missed info count: " + expected_callers.size()); StringBuffer sb = new StringBuffer(); for (String c : expected_callers) { System.out.println("Missed info: " + c); 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 verifyTimer(Timer t) { System.out.println("in StlesEJB:timeout " + t.getInfo() + " - persistent: " + t.isPersistent()); verifyTimer(t, hm.get("" + t.getInfo()), null); callers.add("" + t.getInfo()); expected_callers.remove("" + t.getInfo()); } private void verifyTimer(Timer t, ScheduleExpression se0, TimerConfig tc0) { String info = "" + t.getInfo(); if (!t.isCalendarTimer()) { throw new IllegalStateException("Timer " + info + " is not schedule based timer"); } 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 == null) { throw new IllegalStateException("Timer Schedule for " + info + " is NULL!"); } if (se0 == null) { throw new IllegalStateException("Unknown Schedule for " + info ); } 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); } } @Schedules ({ @Schedule(second="*/5", minute="*", hour="*", info="timer-5-sec"), @Schedule(second="*", minute="*", hour="*", info="timer-every-sec"), @Schedule(second="*", minute="*", hour="*", year="3000,2007, 4096", info="timer-year=3000,2007, 4096"), @Schedule(second="*", minute="*", hour="*", dayOfMonth="Last", info="timer-dayOfMonth=Last"), @Schedule(second="*", minute="*", hour="*", dayOfMonth="Last Sun", info="timer-dayOfMonth=Last Sun"), @Schedule(second="*", minute="*", hour="*", dayOfMonth="-4--2", info="timer-dayOfMonth=-4--2"), @Schedule(dayOfMonth="29", month="FEB", year="2007-2011, 2013-2015, 2017-2019", info="timer-02-29-non-leap-year") }) private void timeout(Timer t) { if (("" + t.getInfo()).startsWith("another") || ("" + t.getInfo()).startsWith("dd")) { errors.add("" + t.getInfo()); throw new IllegalStateException("Timer " + t.getInfo() + " is wrong for this timeout"); } if (!verifying.get()) { // skip if we are verifying calls at this time verifyTimer(t); } } @Schedule(second="2/2", minute="*", hour="*", dayOfWeek="0-7", info="another-timer-dayOfWeek=0-7") private void anothertimeout(Timer t) { if (!("" + t.getInfo()).startsWith("another")) { errors.add("" + t.getInfo()); throw new IllegalStateException("Timer " + t.getInfo() + " is wrong for this timeout"); } if (!verifying.get()) { // skip if we are verifying calls at this time verifyTimer(t); } } @Schedule(second="3/2", minute=" * ", hour="12-11", info="timer-NO-ARG-hour=12-11") private void timeout() { System.out.println("in StlesEJB:NO-ARG timeout " ); if (!verifying.get()) { // skip if we are verifying calls at this time ScheduleExpression se = hm.get("timer-NO-ARG-hour=12-11"); if (se != null) { callers.add("timer-NO-ARG-hour=12-11"); expected_callers.remove("timer-NO-ARG-hour=12-11"); } } } @Schedule(second="4/2", minute="*", hour="*", dayOfWeek="0-7", info="overridden-timer") private void ddTimeout(Timer t) { if (!("" + t.getInfo()).startsWith("dd_timer")) { errors.add("" + t.getInfo()); throw new IllegalStateException("Timer " + t.getInfo() + " is wrong for this timeout"); } if (!verifying.get()) { // skip if we are verifying calls at this time verifyTimer(t); } } }