View Javadoc

1   /*
2    * $Id: AbstractPollingMessageReceiver.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.providers;
12  
13  import org.mule.config.i18n.CoreMessages;
14  import org.mule.umo.UMOComponent;
15  import org.mule.umo.UMOException;
16  import org.mule.umo.endpoint.UMOEndpoint;
17  import org.mule.umo.lifecycle.InitialisationException;
18  import org.mule.umo.provider.UMOConnector;
19  import org.mule.util.ObjectUtils;
20  
21  import java.util.Iterator;
22  import java.util.LinkedList;
23  import java.util.List;
24  
25  import edu.emory.mathcs.backport.java.util.concurrent.ScheduledFuture;
26  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
27  
28  /**
29   * <code>AbstractPollingMessageReceiver</code> implements a base class for polling
30   * message receivers. The receiver provides a {@link #poll()} method that implementations
31   * must implement to execute their custom code. Note that the receiver will not poll if
32   * the associated connector is not started.
33   */
34  public abstract class AbstractPollingMessageReceiver extends AbstractMessageReceiver
35  {
36      public static final long DEFAULT_POLL_FREQUENCY = 1000;
37      public static final TimeUnit DEFAULT_POLL_TIMEUNIT = TimeUnit.MILLISECONDS;
38  
39      public static final long DEFAULT_STARTUP_DELAY = 1000;
40  
41      private long frequency = DEFAULT_POLL_FREQUENCY;
42      private TimeUnit timeUnit = DEFAULT_POLL_TIMEUNIT;
43  
44      // @GuardedBy(itself)
45      protected final List schedules = new LinkedList();
46  
47      public AbstractPollingMessageReceiver(UMOConnector connector,
48                                            UMOComponent component,
49                                            final UMOEndpoint endpoint) throws InitialisationException
50      {
51          super(connector, component, endpoint);
52      }
53  
54      protected void doStart() throws UMOException
55      {
56          try
57          {
58              synchronized (schedules)
59              {
60                  // we use scheduleWithFixedDelay to prevent queue-up of tasks when
61                  // polling takes longer than the specified frequency, e.g. when the
62                  // polled database or network is slow or returns large amounts of
63                  // data.
64                  ScheduledFuture schedule = connector.getScheduler().scheduleWithFixedDelay(
65                      new PollingReceiverWorkerSchedule(this.createWork()), DEFAULT_STARTUP_DELAY,
66                      this.getFrequency(), this.getTimeUnit());
67                  schedules.add(schedule);
68  
69                  if (logger.isDebugEnabled())
70                  {
71                      logger.debug(ObjectUtils.identityToShortString(this) + " scheduled "
72                                   + ObjectUtils.identityToShortString(schedule) + " with " + frequency
73                                   + " " + getTimeUnit() + " polling frequency");
74                  }
75              }
76          }
77          catch (Exception ex)
78          {
79              this.stop();
80              throw new InitialisationException(CoreMessages.failedToScheduleWork(), ex, this);
81          }
82      }
83  
84      protected void doStop() throws UMOException
85      {
86          synchronized (schedules)
87          {
88              // cancel our schedules gently: do not interrupt when polling is in
89              // progress
90              for (Iterator i = schedules.iterator(); i.hasNext();)
91              {
92                  ScheduledFuture schedule = (ScheduledFuture)i.next();
93                  schedule.cancel(false);
94                  i.remove();
95  
96                  if (logger.isDebugEnabled())
97                  {
98                      logger.debug(ObjectUtils.identityToShortString(this) + " cancelled polling schedule: "
99                                   + ObjectUtils.identityToShortString(schedule));
100                 }
101             }
102         }
103     }
104 
105     protected PollingReceiverWorker createWork()
106     {
107         return new PollingReceiverWorker(this);
108     }
109 
110     public long getFrequency()
111     {
112         return frequency;
113     }
114 
115     // TODO a nifty thing would be on-the-fly adjustment (via JMX?) of the
116     // polling frequency by rescheduling without explicit stop()
117     public void setFrequency(long value)
118     {
119         if (value <= 0)
120         {
121             frequency = DEFAULT_POLL_FREQUENCY;
122         }
123         else
124         {
125             frequency = value;
126         }
127     }
128 
129     public TimeUnit getTimeUnit()
130     {
131         return timeUnit;
132     }
133 
134     public void setTimeUnit(TimeUnit timeUnit)
135     {
136         this.timeUnit = timeUnit;
137     }
138 
139     public abstract void poll() throws Exception;
140 
141 }