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.common.endpoints;
018
019 import java.util.Date;
020
021 import javax.jbi.JBIException;
022 import javax.jbi.servicedesc.ServiceEndpoint;
023 import javax.xml.namespace.QName;
024
025 import org.apache.servicemix.common.DefaultComponent;
026 import org.apache.servicemix.common.ServiceUnit;
027 import org.apache.servicemix.components.varscheduler.ScheduleIterator;
028 import org.apache.servicemix.components.varscheduler.Scheduler;
029 import org.apache.servicemix.components.varscheduler.SchedulerTask;
030 import org.apache.servicemix.executors.Executor;
031
032 /**
033 * An implementation inheritence class for an endpoint which polls some resource at periodic intervals to decide if
034 * there is an event to process.
035 *
036 * @version $Revision: 464478 $
037 */
038 public abstract class PollingEndpoint extends ConsumerEndpoint {
039
040 private Executor executor;
041 private Scheduler scheduler;
042 private Date firstTime;
043 private long period = 5000;
044 private long delay;
045 private SchedulerTask schedulerTask;
046 private ScheduleIterator scheduleIterator;
047 private boolean started;
048 private boolean scheduleExecutedFlag;
049
050 public PollingEndpoint() {
051 }
052
053 public PollingEndpoint(ServiceUnit serviceUnit, QName service, String endpoint) {
054 super(serviceUnit, service, endpoint);
055 }
056
057 public PollingEndpoint(DefaultComponent component, ServiceEndpoint endpoint) {
058 super(component.getServiceUnit(), endpoint.getServiceName(), endpoint.getEndpointName());
059 }
060
061 /**
062 * Polls the underlying resource to see if some event is required
063 *
064 * @throws JBIException
065 */
066 public abstract void poll() throws Exception;
067
068
069 // Properties
070 // -------------------------------------------------------------------------
071 public Executor getExecutor() {
072 return executor;
073 }
074
075 public long getDelay() {
076 return delay;
077 }
078
079 public void setDelay(long delay) {
080 this.delay = delay;
081 }
082
083 public Date getFirstTime() {
084 return firstTime;
085 }
086
087 public void setFirstTime(Date firstTime) {
088 this.firstTime = firstTime;
089 }
090
091 public long getPeriod() {
092 return period;
093 }
094
095 public void setPeriod(long period) {
096 this.period = period;
097 }
098
099 public Scheduler getScheduler() {
100 return scheduler;
101 }
102
103 public void setScheduler(Scheduler scheduler) {
104 this.scheduler = scheduler;
105 }
106
107 public synchronized void start() throws Exception {
108 if (!started) {
109 started = true;
110
111 if (scheduler == null) {
112 scheduler = new Scheduler(true);
113 }
114 if (scheduleIterator == null) {
115 scheduleIterator = new PollingEndpoint.PollScheduleIterator();
116 }
117
118 if (executor == null) {
119 executor = getServiceUnit().getComponent().getExecutor();
120 }
121 if (schedulerTask != null) {
122 schedulerTask.cancel();
123 }
124 schedulerTask = new PollingEndpoint.PollSchedulerTask();
125 this.scheduler.schedule(schedulerTask, scheduleIterator);
126 }
127 super.start();
128 }
129
130 public synchronized void stop() throws Exception {
131 if (schedulerTask != null) {
132 schedulerTask.cancel();
133 schedulerTask = null;
134 }
135 scheduleExecutedFlag = false;
136 started = false;
137 scheduler.cancel();
138 scheduler = null;
139 scheduleIterator = null;
140 executor = null;
141 super.stop();
142 }
143
144 // Implementation methods
145 // -------------------------------------------------------------------------
146
147 private class PollSchedulerTask extends SchedulerTask {
148 public void run() {
149 try {
150 // lets run the work inside the JCA worker pools to ensure
151 // the threads are setup correctly when we actually do stuff
152 getExecutor().execute(new Runnable() {
153 public void run() {
154 try {
155 poll();
156 }
157 catch (Exception e) {
158 handlePollException(e);
159 }
160 }
161 });
162 }
163 catch (Throwable e) {
164 logger.error("Failed to schedule work: " + e, e);
165 }
166 }
167 }
168
169 protected void handlePollException(Exception e) {
170 logger.error("Caught exception while polling: " + e, e);
171 }
172
173
174 private class PollScheduleIterator implements ScheduleIterator {
175 public Date nextExecution() {
176 long nextTime = System.currentTimeMillis();
177 if (scheduleExecutedFlag) {
178 nextTime += period;
179 }
180 else {
181 if (firstTime != null) {
182 nextTime = firstTime.getTime();
183 }
184 nextTime += delay;
185 scheduleExecutedFlag = true;
186 }
187 return (started) ? new Date(nextTime) : null;
188 }
189 }
190 }