001: /*
002: * $Id: MuleManagedConnection.java 10789 2008-02-12 20:04:43Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.module.jca;
012:
013: import org.mule.module.jca.i18n.JcaMessages;
014: import org.mule.security.MuleCredentials;
015:
016: import java.io.PrintWriter;
017: import java.util.ArrayList;
018: import java.util.HashSet;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Set;
022:
023: import javax.resource.NotSupportedException;
024: import javax.resource.ResourceException;
025: import javax.resource.spi.ConnectionEvent;
026: import javax.resource.spi.ConnectionEventListener;
027: import javax.resource.spi.ConnectionRequestInfo;
028: import javax.resource.spi.ManagedConnection;
029: import javax.resource.spi.ManagedConnectionMetaData;
030: import javax.resource.spi.security.PasswordCredential;
031: import javax.security.auth.Subject;
032: import javax.transaction.xa.XAResource;
033:
034: /**
035: * <code>MuleManagedConnection</code> TODO
036: */
037: public class MuleManagedConnection implements ManagedConnection {
038: private MuleManagedConnectionFactory mcf;
039: private List listeners = new ArrayList();
040: private Set connectionSet;
041: private PrintWriter logWriter;
042: private boolean destroyed;
043:
044: private PasswordCredential passCred;
045:
046: /**
047: * Constructor.
048: *
049: * @param mcf the ManagedConnectionFactory that created this instance
050: * @param subject security context as JAAS subject
051: * @param cxRequestInfo ConnectionRequestInfo instance
052: * @throws javax.resource.ResourceException in case of any error
053: */
054:
055: MuleManagedConnection(MuleManagedConnectionFactory mcf,
056: Subject subject, ConnectionRequestInfo cxRequestInfo)
057: throws ResourceException {
058: this .mcf = mcf;
059:
060: // Note: this will select the credential that matches this MC's MCF.
061: // The credential's MCF is set by the application server.
062: this .passCred = RaHelper.getPasswordCredential(mcf, subject,
063: cxRequestInfo);
064:
065: connectionSet = new HashSet();
066: }
067:
068: /**
069: * Creates a new connection handle to the Mail Server represented by the
070: * ManagedConnection instance. This connection handle is used by the application
071: * code to refer to the underlying physical connection.
072: *
073: * @param subject security context as JAAS subject
074: * @param connectionRequestInfo ConnectionRequestInfo instance
075: * @return Connection instance representing the connection handle
076: * @throws ResourceException if the method fails to get a connection
077: */
078:
079: public Object getConnection(Subject subject,
080: ConnectionRequestInfo connectionRequestInfo)
081: throws ResourceException {
082:
083: checkIfDestroyed();
084:
085: PasswordCredential pc = RaHelper.getPasswordCredential(mcf,
086: subject, connectionRequestInfo);
087:
088: if (!passCred.equals(pc)) {
089: // TODO change the message, we are not dealing with an endpoint here
090: throw new javax.resource.spi.SecurityException(JcaMessages
091: .authDeniedOnEndpoint(this ).getMessage());
092: }
093:
094: String user;
095: String password;
096: MuleConnectionRequestInfo info = (MuleConnectionRequestInfo) connectionRequestInfo;
097:
098: user = info.getUserName();
099: password = info.getPassword();
100: if (user == null) {
101: // Use default values
102: user = mcf.getUsername();
103: password = mcf.getPassword();
104: }
105: MuleCredentials creds = null;
106: if (user != null) {
107: if (password == null) {
108: password = "";
109: }
110: creds = new MuleCredentials(user, password.toCharArray());
111: }
112:
113: MuleConnection connection = new DefaultMuleConnection(this ,
114: info.getMuleContext(), creds);
115: addConnection(connection);
116: return connection;
117: }
118:
119: /**
120: * Destroys the physical connection.
121: *
122: * @throws ResourceException if the method fails to destroy the connection
123: */
124:
125: public void destroy() throws ResourceException {
126: if (destroyed) {
127: return;
128: }
129: destroyed = true;
130:
131: invalidateConnections();
132: }
133:
134: /**
135: * Initiates a cleanup of the client-specific state maintained by a
136: * ManagedConnection instance. The cleanup should invalidate all connection
137: * handles created using this ManagedConnection instance.
138: *
139: * @throws ResourceException if the cleanup fails
140: */
141:
142: public void cleanup() throws ResourceException {
143: checkIfDestroyed();
144:
145: invalidateConnections();
146: }
147:
148: private void invalidateConnections() {
149: Iterator it = connectionSet.iterator();
150: while (it.hasNext()) {
151: DefaultMuleConnection connection = (DefaultMuleConnection) it
152: .next();
153: connection.invalidate();
154: }
155: connectionSet.clear();
156: }
157:
158: /**
159: * Used by the container to change the association of an application-level
160: * connection handle with a ManagedConnection instance. The container should find
161: * the right ManagedConnection instance and call the associateConnection method.
162: *
163: * @param connection application-level connection handle
164: * @throws ResourceException if the attempt to change the association fails
165: */
166:
167: public void associateConnection(Object connection)
168: throws ResourceException {
169: checkIfDestroyed();
170:
171: if (connection instanceof MuleConnection) {
172: MuleConnection cnn = (MuleConnection) connection;
173: cnn.associateConnection(this );
174: } else {
175: throw new IllegalStateException(JcaMessages
176: .objectMarkedInvalid(
177: DefaultMuleConnection.class.getName()
178: + ": "
179: + (connection == null ? "null"
180: : connection.getClass()
181: .getName()))
182: .toString());
183: }
184: }
185:
186: /**
187: * Adds a connection event listener to the ManagedConnection instance. The
188: * registered ConnectionEventListener instances are notified of connection close
189: * and error events as well as local-transaction-related events on the Managed
190: * Connection.
191: *
192: * @param listener a new ConnectionEventListener to be registered
193: */
194:
195: public void addConnectionEventListener(
196: ConnectionEventListener listener) {
197: listeners.add(listener);
198: }
199:
200: /**
201: * Removes an already registered connection event listener from the
202: * ManagedConnection instance.
203: *
204: * @param listener already registered connection event listener to be removed
205: */
206:
207: public void removeConnectionEventListener(
208: ConnectionEventListener listener) {
209: listeners.remove(listener);
210: }
211:
212: /**
213: * Returns a javax.transaction.xa.XAresource instance. An application server
214: * enlists this XAResource instance with the Transaction Manager if the
215: * ManagedConnection instance is being used in a JTA transaction that is being
216: * coordinated by the Transaction Manager. <p/> Because this implementation does
217: * not support transactions, the method throws an exception.
218: *
219: * @return the XAResource instance
220: * @throws ResourceException if transactions are not supported
221: */
222: // TODO
223: public XAResource getXAResource() throws ResourceException {
224: throw new NotSupportedException("getXAResource");
225: }
226:
227: /**
228: * Returns a javax.resource.spi.LocalTransaction instance. The LocalTransaction
229: * interface is used by the container to manage local transactions for a RM
230: * instance. <p/> Because this implementation does not support transactions, the
231: * method throws an exception.
232: *
233: * @return javax.resource.spi.LocalTransaction instance
234: * @throws ResourceException if transactions are not supported
235: */
236:
237: public javax.resource.spi.LocalTransaction getLocalTransaction()
238: throws ResourceException {
239: throw new NotSupportedException("getLocalTransaction");
240: }
241:
242: /**
243: * Gets the metadata information for this connection's underlying EIS resource
244: * manager instance. The ManagedConnectionMetaData interface provides information
245: * about the underlying EIS instance associated with the ManagedConnection
246: * instance.
247: *
248: * @return ManagedConnectionMetaData ManagedConnectionMetaData instance
249: * @throws ResourceException if the metadata cannot be retrieved
250: */
251:
252: public ManagedConnectionMetaData getMetaData()
253: throws ResourceException {
254: checkIfDestroyed();
255: return new MuleManagedConnectionMetaData(this );
256: }
257:
258: /**
259: * Sets the log writer for this ManagedConnection instance. The log writer is a
260: * character output stream to which all logging and tracing messages for this
261: * ManagedConnection instance will be printed.
262: *
263: * @param out character output stream to be associated
264: * @throws ResourceException if the method fails
265: */
266:
267: public void setLogWriter(PrintWriter out) throws ResourceException {
268: this .logWriter = out;
269: }
270:
271: /**
272: * Gets the log writer for this ManagedConnection instance.
273: *
274: * @return the character output stream associated with this ManagedConnection
275: * instance
276: * @throws ResourceException if the method fails
277: */
278:
279: public PrintWriter getLogWriter() throws ResourceException {
280: return logWriter;
281: }
282:
283: /**
284: * Gets the user name of the user associated with the ManagedConnection instance.
285: *
286: * @return the username for this connection
287: */
288:
289: public String getUsername() {
290: if (passCred != null) {
291: return passCred.getUserName();
292: } else {
293: return null;
294: }
295: }
296:
297: /**
298: * Gets the password for the user associated with the ManagedConnection instance.
299: *
300: * @return the password for this connection
301: */
302:
303: public PasswordCredential getPasswordCredential() {
304: return passCred;
305: }
306:
307: /**
308: * Associate connection handle with the physical connection.
309: *
310: * @param connection connection handle
311: */
312:
313: public void addConnection(MuleConnection connection) {
314: connectionSet.add(connection);
315: }
316:
317: /**
318: * Check validation of the physical connection.
319: *
320: * @throws ResourceException if the connection has been destroyed
321: */
322:
323: private void checkIfDestroyed() throws ResourceException {
324: if (destroyed) {
325: throw new ResourceException(JcaMessages.objectIsDisposed(
326: "MuleManagedConnection").toString());
327: }
328: }
329:
330: /**
331: * Removes the associated connection handle from the connections set to the
332: * physical connection.
333: *
334: * @param connection the connection handle
335: */
336:
337: public void removeConnection(MuleConnection connection) {
338: connectionSet.remove(connection);
339: }
340:
341: /**
342: * Checks validation of the physical connection.
343: *
344: * @return true if the connection has been destroyed; false otherwise
345: */
346:
347: boolean isDestroyed() {
348: return destroyed;
349: }
350:
351: /**
352: * Returns the ManagedConnectionFactory that created this instance of
353: * ManagedConnection.
354: *
355: * @return the ManagedConnectionFactory for this connection
356: */
357:
358: public MuleManagedConnectionFactory getManagedConnectionFactory() {
359: return this .mcf;
360: }
361:
362: void fireBeginEvent() {
363: ConnectionEvent event = new ConnectionEvent(
364: MuleManagedConnection.this ,
365: ConnectionEvent.LOCAL_TRANSACTION_STARTED);
366: Iterator iterator = listeners.iterator();
367: while (iterator.hasNext()) {
368: ConnectionEventListener l = (ConnectionEventListener) iterator
369: .next();
370: l.localTransactionStarted(event);
371: }
372: }
373:
374: void fireCommitEvent() {
375: ConnectionEvent event = new ConnectionEvent(
376: MuleManagedConnection.this ,
377: ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
378: Iterator iterator = listeners.iterator();
379: while (iterator.hasNext()) {
380: ConnectionEventListener l = (ConnectionEventListener) iterator
381: .next();
382: l.localTransactionCommitted(event);
383: }
384: }
385:
386: void fireRollbackEvent() {
387: ConnectionEvent event = new ConnectionEvent(
388: MuleManagedConnection.this ,
389: ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK);
390: Iterator iterator = listeners.iterator();
391: while (iterator.hasNext()) {
392: ConnectionEventListener l = (ConnectionEventListener) iterator
393: .next();
394: l.localTransactionRolledback(event);
395: }
396: }
397:
398: void fireCloseEvent(MuleConnection connection) {
399: ConnectionEvent event = new ConnectionEvent(
400: MuleManagedConnection.this ,
401: ConnectionEvent.CONNECTION_CLOSED);
402: event.setConnectionHandle(connection);
403:
404: Iterator iterator = listeners.iterator();
405: while (iterator.hasNext()) {
406: ConnectionEventListener l = (ConnectionEventListener) iterator
407: .next();
408: l.connectionClosed(event);
409: }
410: }
411:
412: void fireErrorOccurredEvent(Exception error) {
413: ConnectionEvent event = new ConnectionEvent(
414: MuleManagedConnection.this ,
415: ConnectionEvent.CONNECTION_ERROR_OCCURRED, error);
416: Iterator iterator = listeners.iterator();
417: while (iterator.hasNext()) {
418: ConnectionEventListener l = (ConnectionEventListener) iterator
419: .next();
420: l.connectionErrorOccurred(event);
421: }
422: }
423:
424: }
|