View Javadoc

1   /*
2    * $Id: AbstractConnectionStrategy.java 11278 2008-03-07 20:26:34Z dfeist $
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.transport;
12  
13  import org.mule.api.context.WorkManager;
14  import org.mule.api.transport.Connectable;
15  import org.mule.api.transport.ConnectionStrategy;
16  import org.mule.api.transport.Connector;
17  import org.mule.api.transport.MessageReceiver;
18  import org.mule.config.i18n.MessageFactory;
19  import org.mule.util.ClassUtils;
20  
21  import javax.resource.spi.work.Work;
22  import javax.resource.spi.work.WorkException;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  
27  /**
28   * TODO document
29   */
30  public abstract class AbstractConnectionStrategy implements ConnectionStrategy
31  {
32      /**
33       * logger used by this class
34       */
35      protected transient Log logger = LogFactory.getLog(getClass());
36  
37      private volatile boolean doThreading = false;
38  
39      private WorkManager workManager;
40  
41      private final Object reconnectLock = new Object();
42  
43      public final void connect(final Connectable connectable) throws FatalConnectException
44      {
45          if (doThreading)
46          {
47              try
48              {
49                  WorkManager wm = getWorkManager();
50                  if (wm == null)
51                  {
52                      throw new FatalConnectException(MessageFactory.createStaticMessage("No WorkManager is available"), connectable);
53                  }
54                  
55                  wm.scheduleWork(new Work()
56                  {
57                      public void release()
58                      {
59                          // nothing to do
60                      }
61  
62                      public void run()
63                      {
64                          try
65                          {
66                              synchronized (reconnectLock)
67                              {
68                                  doConnect(connectable);
69                              }
70                          }
71                          catch (FatalConnectException e)
72                          {
73                              synchronized (reconnectLock)
74                              {
75                                  resetState();
76                              }
77                              // TODO should really extract an interface for
78                              // classes capable of handling an exception
79                              if (connectable instanceof Connector)
80                              {
81                                  ((Connector) connectable).handleException(e);
82                              }
83                              // TODO: this cast is evil
84                              else if (connectable instanceof AbstractMessageReceiver)
85                              {
86                                  ((AbstractMessageReceiver) connectable).handleException(e);
87                              }
88                              // if it's none of the above, it's not handled and Mule just sits doing nothing
89                          }
90                      }
91                  });
92              }
93              catch (WorkException e)
94              {
95                  synchronized (reconnectLock)
96                  {
97                      resetState();
98                  }
99                  throw new FatalConnectException(e, connectable);
100             }
101         }
102         else
103         {
104             try
105             {
106                 synchronized (reconnectLock)
107                 {
108                     doConnect(connectable);
109                 }
110             }
111             finally
112             {
113                 synchronized (reconnectLock)
114                 {
115                     resetState();
116                 }
117             }
118         }
119     }
120 
121     public boolean isDoThreading()
122     {
123         return doThreading;
124     }
125 
126     public void setDoThreading(boolean doThreading)
127     {
128         this.doThreading = doThreading;
129     }
130 
131 
132     public WorkManager getWorkManager()
133     {
134         return workManager;
135     }
136 
137     public void setWorkManager(WorkManager workManager)
138     {
139         this.workManager = workManager;
140     }
141 
142     protected abstract void doConnect(Connectable connectable) throws FatalConnectException;
143 
144     /**
145      * Resets any state stored in the retry strategy
146      */
147     public abstract void resetState();
148 
149     protected String getDescription(Connectable connectable)
150     {
151         if (connectable instanceof MessageReceiver)
152         {
153             return ((MessageReceiver) connectable).getEndpointURI().toString();
154         }
155         else
156         {
157             return connectable.toString();
158         }
159     }
160 
161     public int hashCode()
162     {
163         return ClassUtils.hash(new Object[]{doThreading ? Boolean.TRUE : Boolean.FALSE, workManager});
164     }
165 
166     public boolean equals(Object obj)
167     {
168         if (this == obj) return true;
169         if (obj == null || getClass() != obj.getClass()) return false;
170 
171         final AbstractConnectionStrategy other = (AbstractConnectionStrategy) obj;
172         return ClassUtils.equal(new Boolean(doThreading), new Boolean(other.doThreading))
173                && ClassUtils.equal(workManager, other.workManager);
174 
175     }
176 
177 }