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    }