View Javadoc

1   /*
2    * $Id: MuleManagedConnection.java 7963 2007-08-21 08:53:15Z 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.ra;
12  
13  import org.mule.impl.security.MuleCredentials;
14  import org.mule.ra.i18n.JcaMessages;
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         MuleConnection connection = new DefaultMuleConnection(this, info.getManager(), creds);
118         addConnection(connection);
119         return connection;
120     }
121 
122     /**
123      * Destroys the physical connection.
124      * 
125      * @throws ResourceException if the method fails to destroy the connection
126      */
127 
128     public void destroy() throws ResourceException
129     {
130         if (destroyed)
131         {
132             return;
133         }
134         destroyed = true;
135 
136         invalidateConnections();
137     }
138 
139     /**
140      * Initiates a cleanup of the client-specific state maintained by a
141      * ManagedConnection instance. The cleanup should invalidate all connection
142      * handles created using this ManagedConnection instance.
143      * 
144      * @throws ResourceException if the cleanup fails
145      */
146 
147     public void cleanup() throws ResourceException
148     {
149         checkIfDestroyed();
150 
151         invalidateConnections();
152     }
153 
154     private void invalidateConnections()
155     {
156         Iterator it = connectionSet.iterator();
157         while (it.hasNext())
158         {
159             DefaultMuleConnection connection = (DefaultMuleConnection)it.next();
160             connection.invalidate();
161         }
162         connectionSet.clear();
163     }
164 
165     /**
166      * Used by the container to change the association of an application-level
167      * connection handle with a ManagedConnection instance. The container should find
168      * the right ManagedConnection instance and call the associateConnection method.
169      * 
170      * @param connection application-level connection handle
171      * @throws ResourceException if the attempt to change the association fails
172      */
173 
174     public void associateConnection(Object connection) throws ResourceException
175     {
176         checkIfDestroyed();
177 
178         if (connection instanceof MuleConnection)
179         {
180             MuleConnection cnn = (MuleConnection)connection;
181             cnn.associateConnection(this);
182         }
183         else
184         {
185             throw new IllegalStateException(
186                 JcaMessages.objectMarkedInvalid(DefaultMuleConnection.class.getName() + ": "
187                                 + (connection == null ? "null" : connection.getClass().getName())).toString());
188         }
189     }
190 
191     /**
192      * Adds a connection event listener to the ManagedConnection instance. The
193      * registered ConnectionEventListener instances are notified of connection close
194      * and error events as well as local-transaction-related events on the Managed
195      * Connection.
196      * 
197      * @param listener a new ConnectionEventListener to be registered
198      */
199 
200     public void addConnectionEventListener(ConnectionEventListener listener)
201     {
202         listeners.add(listener);
203     }
204 
205     /**
206      * Removes an already registered connection event listener from the
207      * ManagedConnection instance.
208      * 
209      * @param listener already registered connection event listener to be removed
210      */
211 
212     public void removeConnectionEventListener(ConnectionEventListener listener)
213     {
214         listeners.remove(listener);
215     }
216 
217     /**
218      * Returns a javax.transaction.xa.XAresource instance. An application server
219      * enlists this XAResource instance with the Transaction Manager if the
220      * ManagedConnection instance is being used in a JTA transaction that is being
221      * coordinated by the Transaction Manager. <p/> Because this implementation does
222      * not support transactions, the method throws an exception.
223      * 
224      * @return the XAResource instance
225      * @throws ResourceException if transactions are not supported
226      */
227     // TODO
228     public XAResource getXAResource() throws ResourceException
229     {
230         throw new NotSupportedException("getXAResource");
231     }
232 
233     /**
234      * Returns a javax.resource.spi.LocalTransaction instance. The LocalTransaction
235      * interface is used by the container to manage local transactions for a RM
236      * instance. <p/> Because this implementation does not support transactions, the
237      * method throws an exception.
238      * 
239      * @return javax.resource.spi.LocalTransaction instance
240      * @throws ResourceException if transactions are not supported
241      */
242 
243     public javax.resource.spi.LocalTransaction getLocalTransaction() throws ResourceException
244     {
245         throw new NotSupportedException("getLocalTransaction");
246     }
247 
248     /**
249      * Gets the metadata information for this connection's underlying EIS resource
250      * manager instance. The ManagedConnectionMetaData interface provides information
251      * about the underlying EIS instance associated with the ManagedConnection
252      * instance.
253      * 
254      * @return ManagedConnectionMetaData ManagedConnectionMetaData instance
255      * @throws ResourceException if the metadata cannot be retrieved
256      */
257 
258     public ManagedConnectionMetaData getMetaData() throws ResourceException
259     {
260         checkIfDestroyed();
261         return new MuleManagedConnectionMetaData(this);
262     }
263 
264     /**
265      * Sets the log writer for this ManagedConnection instance. The log writer is a
266      * character output stream to which all logging and tracing messages for this
267      * ManagedConnection instance will be printed.
268      * 
269      * @param out character output stream to be associated
270      * @throws ResourceException if the method fails
271      */
272 
273     public void setLogWriter(PrintWriter out) throws ResourceException
274     {
275         this.logWriter = out;
276     }
277 
278     /**
279      * Gets the log writer for this ManagedConnection instance.
280      * 
281      * @return the character output stream associated with this ManagedConnection
282      *         instance
283      * @throws ResourceException if the method fails
284      */
285 
286     public PrintWriter getLogWriter() throws ResourceException
287     {
288         return logWriter;
289     }
290 
291     /**
292      * Gets the user name of the user associated with the ManagedConnection instance.
293      * 
294      * @return the username for this connection
295      */
296 
297     public String getUsername()
298     {
299         if (passCred != null)
300         {
301             return passCred.getUserName();
302         }
303         else
304         {
305             return null;
306         }
307     }
308 
309     /**
310      * Gets the password for the user associated with the ManagedConnection instance.
311      * 
312      * @return the password for this connection
313      */
314 
315     public PasswordCredential getPasswordCredential()
316     {
317         return passCred;
318     }
319 
320     /**
321      * Associate connection handle with the physical connection.
322      * 
323      * @param connection connection handle
324      */
325 
326     public void addConnection(MuleConnection connection)
327     {
328         connectionSet.add(connection);
329     }
330 
331     /**
332      * Check validation of the physical connection.
333      * 
334      * @throws ResourceException if the connection has been destroyed
335      */
336 
337     private void checkIfDestroyed() throws ResourceException
338     {
339         if (destroyed)
340         {
341             throw new ResourceException(
342                 JcaMessages.objectIsDisposed("MuleManagedConnection").toString());
343         }
344     }
345 
346     /**
347      * Removes the associated connection handle from the connections set to the
348      * physical connection.
349      * 
350      * @param connection the connection handle
351      */
352 
353     public void removeConnection(MuleConnection connection)
354     {
355         connectionSet.remove(connection);
356     }
357 
358     /**
359      * Checks validation of the physical connection.
360      * 
361      * @return true if the connection has been destroyed; false otherwise
362      */
363 
364     boolean isDestroyed()
365     {
366         return destroyed;
367     }
368 
369     /**
370      * Returns the ManagedConnectionFactory that created this instance of
371      * ManagedConnection.
372      * 
373      * @return the ManagedConnectionFactory for this connection
374      */
375 
376     public MuleManagedConnectionFactory getManagedConnectionFactory()
377     {
378         return this.mcf;
379     }
380 
381     void fireBeginEvent()
382     {
383         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
384             ConnectionEvent.LOCAL_TRANSACTION_STARTED);
385         Iterator iterator = listeners.iterator();
386         while (iterator.hasNext())
387         {
388             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
389             l.localTransactionStarted(event);
390         }
391     }
392 
393     void fireCommitEvent()
394     {
395         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
396             ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
397         Iterator iterator = listeners.iterator();
398         while (iterator.hasNext())
399         {
400             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
401             l.localTransactionCommitted(event);
402         }
403     }
404 
405     void fireRollbackEvent()
406     {
407         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
408             ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK);
409         Iterator iterator = listeners.iterator();
410         while (iterator.hasNext())
411         {
412             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
413             l.localTransactionRolledback(event);
414         }
415     }
416 
417     void fireCloseEvent(MuleConnection connection)
418     {
419         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
420             ConnectionEvent.CONNECTION_CLOSED);
421         event.setConnectionHandle(connection);
422 
423         Iterator iterator = listeners.iterator();
424         while (iterator.hasNext())
425         {
426             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
427             l.connectionClosed(event);
428         }
429     }
430 
431     void fireErrorOccurredEvent(Exception error)
432     {
433         ConnectionEvent event = new ConnectionEvent(MuleManagedConnection.this,
434             ConnectionEvent.CONNECTION_ERROR_OCCURRED, error);
435         Iterator iterator = listeners.iterator();
436         while (iterator.hasNext())
437         {
438             ConnectionEventListener l = (ConnectionEventListener)iterator.next();
439             l.connectionErrorOccurred(event);
440         }
441     }
442 
443 }