001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.components.util;
018
019 import java.util.Date;
020
021 import javax.jbi.JBIException;
022 import javax.resource.spi.work.Work;
023
024 import org.apache.commons.logging.Log;
025 import org.apache.commons.logging.LogFactory;
026 import org.apache.servicemix.components.varscheduler.ScheduleIterator;
027 import org.apache.servicemix.components.varscheduler.Scheduler;
028 import org.apache.servicemix.components.varscheduler.SchedulerTask;
029 import org.apache.servicemix.executors.Executor;
030 import org.apache.servicemix.executors.ExecutorFactory;
031 import org.apache.servicemix.jbi.framework.ComponentContextImpl;
032
033 /**
034 * An implementation inheritence class for a component which polls some resource
035 * at periodic intervals to decide if there is an event to process.
036 *
037 * @version $Revision: 564374 $
038 */
039 public abstract class PollingComponentSupport extends ComponentSupport implements Work {
040
041 private static final Log LOG = LogFactory.getLog(PollingComponentSupport.class);
042
043 private Executor executor;
044 private Scheduler scheduler;
045 private Date firstTime;
046 private long period = 5000;
047 private long delay;
048 private SchedulerTask schedulerTask;
049 private ScheduleIterator scheduleIterator;
050 private boolean started;
051 private boolean scheduleExecutedFlag;
052
053 /**
054 * Polls the underlying resource to see if some event is required
055 *
056 * @throws JBIException
057 */
058 public abstract void poll() throws Exception;
059
060 public void release() {
061 }
062
063 public void run() {
064 try {
065 poll();
066 } catch (Exception e) {
067 LOG.error("Caught exception while polling: " + e, e);
068 }
069 }
070
071 // Properties
072 // -------------------------------------------------------------------------
073 public Executor getExecutor() {
074 return executor;
075 }
076
077 public long getDelay() {
078 return delay;
079 }
080
081 public void setDelay(long delay) {
082 this.delay = delay;
083 }
084
085 public Date getFirstTime() {
086 return firstTime;
087 }
088
089 public void setFirstTime(Date firstTime) {
090 this.firstTime = firstTime;
091 }
092
093 public long getPeriod() {
094 return period;
095 }
096
097 public void setPeriod(long period) {
098 this.period = period;
099 }
100
101 public Scheduler getScheduler() {
102 return scheduler;
103 }
104
105 public void setScheduler(Scheduler scheduler) {
106 this.scheduler = scheduler;
107 }
108
109 public synchronized void start() throws JBIException {
110 if (!started) {
111 started = true;
112 if (schedulerTask != null) {
113 schedulerTask.cancel();
114 }
115 schedulerTask = new PollSchedulerTask();
116 this.scheduler.schedule(schedulerTask, scheduleIterator);
117 }
118 super.start();
119 }
120
121 public synchronized void stop() throws JBIException {
122 if (schedulerTask != null) {
123 schedulerTask.cancel();
124 schedulerTask = null;
125 }
126 scheduleExecutedFlag = false;
127 started = false;
128 super.stop();
129 }
130
131 public synchronized void shutDown() throws JBIException {
132 stop();
133 scheduler.cancel();
134 executor.shutdown();
135 scheduler = null;
136 scheduleIterator = null;
137 executor = null;
138 super.shutDown();
139 }
140
141 // Implementation methods
142 // -------------------------------------------------------------------------
143 protected void init() throws JBIException {
144 if (scheduler == null) {
145 scheduler = new Scheduler(true);
146 }
147 if (scheduleIterator == null) {
148 scheduleIterator = new PollScheduleIterator();
149 }
150 if (executor == null) {
151 ComponentContextImpl context = (ComponentContextImpl) getContext();
152 ExecutorFactory factory = context.getContainer()
153 .getExecutorFactory();
154 executor = factory.createExecutor("component."
155 + context.getComponentName());
156 }
157 super.init();
158
159 }
160
161 private class PollSchedulerTask extends SchedulerTask {
162 public void run() {
163 try {
164 // lets run the work inside the JCA worker pools to ensure
165 // the threads are setup correctly when we actually do stuff
166 getExecutor().execute(PollingComponentSupport.this);
167 } catch (Throwable e) {
168 LOG.error("Failed to schedule work: " + e, e);
169 }
170 }
171 }
172
173 private class PollScheduleIterator implements ScheduleIterator {
174 public Date nextExecution() {
175 long nextTime = System.currentTimeMillis();
176 if (scheduleExecutedFlag) {
177 nextTime += period;
178 } else {
179 if (firstTime != null) {
180 nextTime = firstTime.getTime();
181 }
182 nextTime += delay;
183 scheduleExecutedFlag = true;
184 }
185 return started ? new Date(nextTime) : null;
186 }
187 }
188 }