001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.jms.connection;
018:
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.LinkedList;
022: import java.util.List;
023: import java.util.Map;
024:
025: import javax.jms.Connection;
026: import javax.jms.ConnectionFactory;
027: import javax.jms.JMSException;
028: import javax.jms.Session;
029: import javax.jms.TransactionInProgressException;
030:
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033:
034: import org.springframework.transaction.support.ResourceHolderSupport;
035: import org.springframework.util.Assert;
036: import org.springframework.util.CollectionUtils;
037:
038: /**
039: * Connection holder, wrapping a JMS Connection and a JMS Session.
040: * JmsTransactionManager binds instances of this class to the thread,
041: * for a given JMS ConnectionFactory.
042: *
043: * <p>Note: This is an SPI class, not intended to be used by applications.
044: *
045: * @author Juergen Hoeller
046: * @since 1.1
047: * @see JmsTransactionManager
048: * @see org.springframework.jms.core.JmsTemplate
049: */
050: public class JmsResourceHolder extends ResourceHolderSupport {
051:
052: private static final Log logger = LogFactory
053: .getLog(JmsResourceHolder.class);
054:
055: private boolean frozen;
056:
057: private final ConnectionFactory connectionFactory;
058:
059: private final List connections = new LinkedList();
060:
061: private final List sessions = new LinkedList();
062:
063: private final Map sessionsPerConnection = new HashMap();
064:
065: /**
066: * Create a new JmsResourceHolder that is open for resources to be added.
067: * @see #addConnection
068: * @see #addSession
069: */
070: public JmsResourceHolder() {
071: this (null);
072: }
073:
074: /**
075: * Create a new JmsResourceHolder that is open for resources to be added.
076: * @param connectionFactory the JMS ConnectionFactory that this
077: * resource holder is associated with (may be <code>null</code>)
078: */
079: public JmsResourceHolder(ConnectionFactory connectionFactory) {
080: this .connectionFactory = connectionFactory;
081: this .frozen = false;
082: }
083:
084: /**
085: * Create a new JmsResourceHolder for the given JMS resources.
086: * @param connection the JMS Connection
087: * @param session the JMS Session
088: */
089: public JmsResourceHolder(Connection connection, Session session) {
090: this (null, connection, session);
091: }
092:
093: /**
094: * Create a new JmsResourceHolder for the given JMS resources.
095: * @param connectionFactory the JMS ConnectionFactory that this
096: * resource holder is associated with (may be <code>null</code>)
097: * @param connection the JMS Connection
098: * @param session the JMS Session
099: */
100: public JmsResourceHolder(ConnectionFactory connectionFactory,
101: Connection connection, Session session) {
102: this .connectionFactory = connectionFactory;
103: addConnection(connection);
104: addSession(session, connection);
105: this .frozen = true;
106: }
107:
108: public final boolean isFrozen() {
109: return this .frozen;
110: }
111:
112: public final void addConnection(Connection connection) {
113: Assert
114: .isTrue(!this .frozen,
115: "Cannot add Connection because JmsResourceHolder is frozen");
116: Assert.notNull(connection, "Connection must not be null");
117: if (!this .connections.contains(connection)) {
118: this .connections.add(connection);
119: }
120: }
121:
122: public final void addSession(Session session) {
123: addSession(session, null);
124: }
125:
126: public final void addSession(Session session, Connection connection) {
127: Assert
128: .isTrue(!this .frozen,
129: "Cannot add Session because JmsResourceHolder is frozen");
130: Assert.notNull(session, "Session must not be null");
131: if (!this .sessions.contains(session)) {
132: this .sessions.add(session);
133: if (connection != null) {
134: List sessions = (List) this .sessionsPerConnection
135: .get(connection);
136: if (sessions == null) {
137: sessions = new LinkedList();
138: this .sessionsPerConnection
139: .put(connection, sessions);
140: }
141: sessions.add(session);
142: }
143: }
144: }
145:
146: public boolean containsSession(Session session) {
147: return this .sessions.contains(session);
148: }
149:
150: public Connection getConnection() {
151: return (!this .connections.isEmpty() ? (Connection) this .connections
152: .get(0)
153: : null);
154: }
155:
156: public Connection getConnection(Class connectionType) {
157: return (Connection) CollectionUtils.findValueOfType(
158: this .connections, connectionType);
159: }
160:
161: public Session getSession() {
162: return (!this .sessions.isEmpty() ? (Session) this .sessions
163: .get(0) : null);
164: }
165:
166: public Session getSession(Class sessionType) {
167: return getSession(sessionType, null);
168: }
169:
170: public Session getSession(Class sessionType, Connection connection) {
171: List sessions = this .sessions;
172: if (connection != null) {
173: sessions = (List) this .sessionsPerConnection
174: .get(connection);
175: }
176: return (Session) CollectionUtils.findValueOfType(sessions,
177: sessionType);
178: }
179:
180: public void commitAll() throws JMSException {
181: for (Iterator it = this .sessions.iterator(); it.hasNext();) {
182: try {
183: ((Session) it.next()).commit();
184: } catch (TransactionInProgressException ex) {
185: // Ignore -> can only happen in case of a JTA transaction.
186: } catch (javax.jms.IllegalStateException ex) {
187: // Ignore -> can only happen in case of a JTA transaction.
188: }
189: }
190: }
191:
192: public void closeAll() {
193: for (Iterator it = this .sessions.iterator(); it.hasNext();) {
194: try {
195: ((Session) it.next()).close();
196: } catch (Throwable ex) {
197: logger
198: .debug(
199: "Could not close synchronized JMS Session after transaction",
200: ex);
201: }
202: }
203: for (Iterator it = this .connections.iterator(); it.hasNext();) {
204: Connection con = (Connection) it.next();
205: ConnectionFactoryUtils.releaseConnection(con,
206: this .connectionFactory, true);
207: }
208: }
209:
210: }
|