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}