View Javadoc

1   /*
2    * $Id: MuleManagedConnection.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.module.jca;
12  
13  import org.mule.module.jca.i18n.JcaMessages;
14  import org.mule.security.MuleCredentials;
15  
16  import java.io.PrintWriter;
17  import java.util.ArrayList;
18  import java.util.HashSet;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.Set;
22  
23  import javax.resource.NotSupportedException;
24  import javax.resource.ResourceException;
25  import javax.resource.spi.ConnectionEvent;
26  import javax.resource.spi.ConnectionEventListener;
27  import javax.resource.spi.ConnectionRequestInfo;
28  import javax.resource.spi.ManagedConnection;
29  import javax.resource.spi.ManagedConnectionMetaData;
30  import javax.resource.spi.security.PasswordCredential;
31  import javax.security.auth.Subject;
32  import javax.transaction.xa.XAResource;
33  
34  /**
35   * <code>MuleManagedConnection</code> TODO
36   */
37  public class MuleManagedConnection implements ManagedConnection
38  {
39      private MuleManagedConnectionFactory mcf;
40      private List listeners = new ArrayList();
41      private Set connectionSet;
42      private PrintWriter logWriter;
43      private boolean destroyed;
44  
45      private PasswordCredential passCred;
46  
47      /**
48       * Constructor.
49       * 
50       * @param mcf the ManagedConnectionFactory that created this instance
51       * @param subject security context as JAAS subject
52       * @param cxRequestInfo ConnectionRequestInfo instance
53       * @throws javax.resource.ResourceException in case of any error
54       */
55  
56      MuleManagedConnection(MuleManagedConnectionFactory mcf,
57                            Subject subject,
58                            ConnectionRequestInfo cxRequestInfo) throws ResourceException
59      {
60          this.mcf = mcf;
61  
62          // Note: this will select the credential that matches this MC's MCF.
63          // The credential's MCF is set by the application server.
64          this.passCred = RaHelper.getPasswordCredential(mcf, subject, cxRequestInfo);
65  
66          connectionSet = new HashSet();
67      }
68  
69      /**
70       * Creates a new connection handle to the Mail Server represented by the
71       * ManagedConnection instance. This connection handle is used by the application
72       * code to refer to the underlying physical connection.
73       * 
74       * @param subject security context as JAAS subject
75       * @param connectionRequestInfo ConnectionRequestInfo instance
76       * @return Connection instance representing the connection handle
77       * @throws ResourceException if the method fails to get a connection
78       */
79  
80      public Object getConnection(Subject subject, ConnectionRequestInfo connectionRequestInfo)
81          throws ResourceException
82      {
83  
84          checkIfDestroyed();
85  
86          PasswordCredential pc = RaHelper.getPasswordCredential(mcf, subject, connectionRequestInfo);
87  
88          if (!passCred.equals(pc))
89          {
90              // TODO change the message, we are not dealing with an endpoint here
91              throw new javax.resource.spi.SecurityException(
92                  JcaMessages.authDeniedOnEndpoint(this).getMessage());
93          }
94  
95          String user;
96          String password;
97          MuleConnectionRequestInfo info = (MuleConnectionRequestInfo)connectionRequestInfo;
98  
99          user = info.getUserName();
100         password = info.getPassword();
101         if (user == null)
102         {
103             // Use default values
104             user = mcf.getUsername();
105             password = mcf.getPassword();
106         }
107         MuleCredentials creds = null;
108         if (user != null)
109         {
110             if (password == null)
111             {
112                 password = "";
113             }
114             creds = new MuleCredentials(user, password.toCharArray());
115         }
116 
117         // TODO Get muleContext from ResourceAdaptor somehow 
118         // (MULE-2916 MuleContext should not be a static singleton instance)
119         MuleConnection connection = new DefaultMuleConnection(this, null, creds);
120         addConnection(connection);
121         return connection;
122     }
123 
124     /**
125      * Destroys the physical connection.
126      * 
127      * @throws ResourceException if the method fails to destroy the connection
128      */
129 
130     public void destroy() throws ResourceException
131     {
132         if (destroyed)
133         {
134             return;
135         }
136         destroyed = true;
137 
138         invalidateConnections();
139     }
140 
141     /**
142      * Initiates a cleanup of the client-specific state maintained by a
143      * ManagedConnection instance. The cleanup should invalidate all connection
144      * handles created using this ManagedConnection instance.
145      * 
146      * @throws ResourceException if the cleanup fails
147      */
148 
149     public void cleanup() throws ResourceException
150     {
151         checkIfDestroyed();
152 
153         invalidateConnections();
154     }
155 
156     private void invalidateConnections()
157     {
158         Iterator it = connectionSet.iterator();
159         while (it.hasNext())
160         {
161             DefaultMuleConnection connection = (DefaultMuleConnection)it.next();
162             connection.invalidate();
163         }
164         connectionSet.clear();
165     }
166 
167     /**
168      * Used by the container to change the association of an application-level
169      * connection handle with a ManagedConnection instance. The container should find
170      * the right ManagedConnection instance and call the associateConnection method.
171      * 
172      * @param connection application-level connection handle
173      * @throws ResourceException if the attempt to change the association fails
174      */
175 
176     public void associateConnection(Object connection) throws ResourceException
177     {
178         checkIfDestroyed();
179 
180         if (connection instanceof MuleConnection)
181         {
182             MuleConnection cnn = (MuleConnection)connection;
183             cnn.associateConnection(this);
184         }
185         else
186         {
187             throw new IllegalStateException(
188                 JcaMessages.objectMarkedInvalid(DefaultMuleConnection.class.getName() + ": "
189                                 + (connection == null ? "null" : connection.getClass().getName())).toString());
190         }
191     }
192 
193     /**
194      * Adds a connection event listener to the ManagedConnection instance. The
195      * registered ConnectionEventListener instances are notified of connection close
196      * and error events as well as local-transaction-related events on the Managed
197      * Connection.
198      * 
199      * @param listener a new ConnectionEventListener to be registered
200      */
201 
202     public void addConnectionEventListener(ConnectionEventListener listener)
203     {
204         listeners.add(listener);
205     }
206 
207     /**
208      * Removes an already registered connection event listener from the
209      * ManagedConnection instance.
210      * 
211      * @param listener already registered connection event listener to be removed
212      */
213 
214     public void removeConnectionEventListener(ConnectionEventListener listener)
215     {
216         listeners.remove(listener);
217     }
218 
219     /**
220      * Returns a javax.transaction.xa.XAresource instance. An application server
221      * enlists this XAResource instance with the Transaction Manager if the
222      * ManagedConnection instance is being used in a JTA transaction that is being
223      * coordinated by the Transaction Manager. <p/> Because this implementation does
224      * not support transactions, the method throws an exception.
225      * 
226      * @return the XAResource instance
227      * @throws ResourceException if transactions are not supported
228      */
229     // TODO
230     public XAResource getXAResource() throws ResourceException
231     {
232         throw new NotSupportedException("getXAResource");
233     }
234 
235     /**
236      * Returns a javax.resource.spi.LocalTransaction instance. The LocalTransaction
237      * interface is used by the container to manage local transactions for a RM
238      * instance. <p/> Because this implementation does not support transactions, the
239      * method throws an exception.
240      * 
241      * @return javax.resource.spi.LocalTransaction instance
242      * @throws ResourceException if transactions are not supported
243      */
244 
245     public javax.resource.spi.LocalTransaction getLocalTransaction() throws ResourceException
246     {
247         throw new NotSupportedException("getLocalTransaction");
248     }
249 
250     /**
251      * Gets the metadata information for this connection's underlying EIS resource
252      * manager instance. The ManagedConnectionMetaData interface provides information
253      * about the underlying EIS instance associated with the ManagedConnection
254      * instance.
255      * 
256      * @return ManagedConnectionMetaData ManagedConnectionMetaData instance
257      * @throws ResourceException if the metadata cannot be retrieved
258      */
259 
260     public ManagedConnectionMetaData getMetaData() throws ResourceException
261     {
262         checkIfDestroyed();
263         return new MuleManagedConnectionMetaData(this);
264     }
265 
266     /**
267      * Sets the log writer for this ManagedConnection instance. The log writer is a
268      * character output stream to which all logging and tracing messages for this
269      * ManagedConnection instance will be printed.
270      * 
271      * @param out character output stream to be associated
272      * @throws ResourceException if the method fails
273      */
274 
275     public void setLogWriter(PrintWriter out) throws ResourceException
276     {
277         this.logWriter = out;
278     }
279 
280     /**
281      * Gets the log writer for this ManagedConnection instance.
282      * 
283      * @return the character output stream associated with this ManagedConnection
284      *         instance
285      * @throws ResourceException if the method fails
286      */
287 
288     public PrintWriter getLogWriter() throws ResourceException
289     {
290         return logWriter;
291     }
292 
293     /**
294      * Gets the user name of the user associated with the ManagedConnection instance.
295      * 
296      * @return the username for this connection
297      */
298 
299     public String getUsername()
300     {
301         if (passCred != null)
302         {
303             return passCred.getUserName();
304         }
305         else
306         {
307             return null;
308         }
309     }
310 
311     /**
312      * Gets the password for the user associated with the ManagedConnection instance.
313      * 
314      * @return the password for this connection
315      */
316 
317     public PasswordCredential getPasswordCredential()
318     {
319         return passCred;
320     }
321 
322     /**
323      * Associate connection handle with the physical connection.
324      * 
325      * @param connection connection handle
326      */
327 
328     public void addConnection(MuleConnection connection)
329     {
330         connectionSet.add(connection);
331     }
332 
333     /**
334      * Check validation of the physical connection.
335      * 
336      * @throws ResourceException if the connection has been destroyed
337      */
338 
339     private void checkIfDestroyed() throws ResourceException
340     {
341         if (destroyed)
342         {
343             throw new ResourceException(
344                 JcaMessages.objectIsDisposed("MuleManagedConnection").toString());
345         }
346     }
347 
348     /**
349      * Removes the associated connection handle from the connections set to the
350      * physical connection.
351      * 
352      * @param connection the connection handle
353      */
354 
355     public void removeConnection(MuleConnection connection)
356     {
357         connectionSet.remove(connection);
358     }
359 
360     /**
361      * Checks validation of the physical connection.
362      * 
363      * @return true if the connection has been destroyed; false otherwise
364      */
365 
366     boolean isDestroyed()
367     {
368         return destroyed;
369     }
370 
371     /**
372      * Returns the ManagedConnectionFactory that created this instance of
373      * ManagedConnection.
374      * 
375      * @return the ManagedConnectionFactory for this connection
376      */
377 
378     public MuleManagedConnectionFactory getManagedConnectionFactory()
379     {
380         return this.mcf;
381     }
382 
383     void fireBeginEvent()
384     {
385         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
386             ConnectionEvent.LOCAL_TRANSACTION_STARTED);
387         Iterator iterator = listeners.iterator();
388         while (iterator.hasNext())
389         {
390             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
391             l.localTransactionStarted(event);
392         }
393     }
394 
395     void fireCommitEvent()
396     {
397         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
398             ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
399         Iterator iterator = listeners.iterator();
400         while (iterator.hasNext())
401         {
402             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
403             l.localTransactionCommitted(event);
404         }
405     }
406 
407     void fireRollbackEvent()
408     {
409         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
410             ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK);
411         Iterator iterator = listeners.iterator();
412         while (iterator.hasNext())
413         {
414             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
415             l.localTransactionRolledback(event);
416         }
417     }
418 
419     void fireCloseEvent(MuleConnection connection)
420     {
421         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
422             ConnectionEvent.CONNECTION_CLOSED);
423         event.setConnectionHandle(connection);
424 
425         Iterator iterator = listeners.iterator();
426         while (iterator.hasNext())
427         {
428             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
429             l.connectionClosed(event);
430         }
431     }
432 
433     void fireErrorOccurredEvent(Exception error)
434     {
435         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
436             ConnectionEvent.CONNECTION_ERROR_OCCURRED, error);
437         Iterator iterator = listeners.iterator();
438         while (iterator.hasNext())
439         {
440             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
441             l.connectionErrorOccurred(event);
442         }
443     }
444 
445 }