001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.scheduling.commonj; 018 019import javax.naming.NamingException; 020 021import commonj.timers.TimerManager; 022 023import org.springframework.beans.factory.DisposableBean; 024import org.springframework.beans.factory.InitializingBean; 025import org.springframework.context.Lifecycle; 026import org.springframework.jndi.JndiLocatorSupport; 027 028/** 029 * Base class for classes that are accessing a CommonJ {@link commonj.timers.TimerManager} 030 * Defines common configuration settings and common lifecycle handling. 031 * 032 * @author Juergen Hoeller 033 * @since 3.0 034 * @see commonj.timers.TimerManager 035 */ 036public abstract class TimerManagerAccessor extends JndiLocatorSupport 037 implements InitializingBean, DisposableBean, Lifecycle { 038 039 private TimerManager timerManager; 040 041 private String timerManagerName; 042 043 private boolean shared = false; 044 045 046 /** 047 * Specify the CommonJ TimerManager to delegate to. 048 * <p>Note that the given TimerManager's lifecycle will be managed 049 * by this FactoryBean. 050 * <p>Alternatively (and typically), you can specify the JNDI name 051 * of the target TimerManager. 052 * @see #setTimerManagerName 053 */ 054 public void setTimerManager(TimerManager timerManager) { 055 this.timerManager = timerManager; 056 } 057 058 /** 059 * Set the JNDI name of the CommonJ TimerManager. 060 * <p>This can either be a fully qualified JNDI name, or the JNDI name relative 061 * to the current environment naming context if "resourceRef" is set to "true". 062 * @see #setTimerManager 063 * @see #setResourceRef 064 */ 065 public void setTimerManagerName(String timerManagerName) { 066 this.timerManagerName = timerManagerName; 067 } 068 069 /** 070 * Specify whether the TimerManager obtained by this FactoryBean 071 * is a shared instance ("true") or an independent instance ("false"). 072 * The lifecycle of the former is supposed to be managed by the application 073 * server, while the lifecycle of the latter is up to the application. 074 * <p>Default is "false", i.e. managing an independent TimerManager instance. 075 * This is what the CommonJ specification suggests that application servers 076 * are supposed to offer via JNDI lookups, typically declared as a 077 * {@code resource-ref} of type {@code commonj.timers.TimerManager} 078 * in {@code web.xml}, with {@code res-sharing-scope} set to 'Unshareable'. 079 * <p>Switch this flag to "true" if you are obtaining a shared TimerManager, 080 * typically through specifying the JNDI location of a TimerManager that 081 * has been explicitly declared as 'Shareable'. Note that WebLogic's 082 * cluster-aware Job Scheduler is a shared TimerManager too. 083 * <p>The sole difference between this FactoryBean being in shared or 084 * non-shared mode is that it will only attempt to suspend / resume / stop 085 * the underlying TimerManager in case of an independent (non-shared) instance. 086 * This only affects the {@link org.springframework.context.Lifecycle} support 087 * as well as application context shutdown. 088 * @see #stop() 089 * @see #start() 090 * @see #destroy() 091 * @see commonj.timers.TimerManager 092 */ 093 public void setShared(boolean shared) { 094 this.shared = shared; 095 } 096 097 098 @Override 099 public void afterPropertiesSet() throws NamingException { 100 if (this.timerManager == null) { 101 if (this.timerManagerName == null) { 102 throw new IllegalArgumentException("Either 'timerManager' or 'timerManagerName' must be specified"); 103 } 104 this.timerManager = lookup(this.timerManagerName, TimerManager.class); 105 } 106 } 107 108 protected final TimerManager getTimerManager() { 109 return this.timerManager; 110 } 111 112 113 //--------------------------------------------------------------------- 114 // Implementation of Lifecycle interface 115 //--------------------------------------------------------------------- 116 117 /** 118 * Resumes the underlying TimerManager (if not shared). 119 * @see commonj.timers.TimerManager#resume() 120 */ 121 @Override 122 public void start() { 123 if (!this.shared) { 124 this.timerManager.resume(); 125 } 126 } 127 128 /** 129 * Suspends the underlying TimerManager (if not shared). 130 * @see commonj.timers.TimerManager#suspend() 131 */ 132 @Override 133 public void stop() { 134 if (!this.shared) { 135 this.timerManager.suspend(); 136 } 137 } 138 139 /** 140 * Considers the underlying TimerManager as running if it is 141 * neither suspending nor stopping. 142 * @see commonj.timers.TimerManager#isSuspending() 143 * @see commonj.timers.TimerManager#isStopping() 144 */ 145 @Override 146 public boolean isRunning() { 147 return (!this.timerManager.isSuspending() && !this.timerManager.isStopping()); 148 } 149 150 151 //--------------------------------------------------------------------- 152 // Implementation of DisposableBean interface 153 //--------------------------------------------------------------------- 154 155 /** 156 * Stops the underlying TimerManager (if not shared). 157 * @see commonj.timers.TimerManager#stop() 158 */ 159 @Override 160 public void destroy() { 161 // Stop the entire TimerManager, if necessary. 162 if (!this.shared) { 163 // May return early, but at least we already cancelled all known Timers. 164 this.timerManager.stop(); 165 } 166 } 167 168}