001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.ra; 018 019import java.io.IOException; 020import java.io.ObjectInputStream; 021import java.io.ObjectOutputStream; 022import java.io.PrintWriter; 023import java.io.Serializable; 024import java.util.Iterator; 025import java.util.Set; 026 027import javax.jms.JMSException; 028import javax.resource.ResourceException; 029import javax.resource.spi.ConnectionManager; 030import javax.resource.spi.ConnectionRequestInfo; 031import javax.resource.spi.ManagedConnection; 032import javax.resource.spi.ManagedConnectionFactory; 033import javax.resource.spi.ResourceAdapter; 034import javax.resource.spi.ResourceAdapterAssociation; 035import javax.security.auth.Subject; 036 037import org.slf4j.LoggerFactory; 038 039/** 040 * @version $Revisio n$ TODO: Must override equals and hashCode (JCA spec 16.4) 041 * @org.apache.xbean.XBean element="managedConnectionFactory" 042 */ 043public class ActiveMQManagedConnectionFactory extends ActiveMQConnectionSupport implements ManagedConnectionFactory, ResourceAdapterAssociation { 044 045 private static final long serialVersionUID = 6196921962230582875L; 046 private PrintWriter logWriter; 047 048 /** 049 * @see javax.resource.spi.ResourceAdapterAssociation#setResourceAdapter(javax.resource.spi.ResourceAdapter) 050 */ 051 @Override 052 public void setResourceAdapter(ResourceAdapter adapter) throws ResourceException { 053 if (!(adapter instanceof MessageResourceAdapter)) { 054 throw new ResourceException("ResourceAdapter is not of type: " + MessageResourceAdapter.class.getName()); 055 } else { 056 if (log.isDebugEnabled()) { 057 log.debug(this + ", copying standard ResourceAdapter configuration properties"); 058 } 059 060 ActiveMQConnectionRequestInfo baseInfo = ((MessageResourceAdapter) adapter).getInfo().copy(); 061 if (getClientid() == null) { 062 setClientid(baseInfo.getClientid()); 063 } 064 if (getPassword() == null) { 065 setPassword(baseInfo.getPassword()); 066 } 067 if (getServerUrl() == null) { 068 setServerUrl(baseInfo.getServerUrl()); 069 } 070 if (getUseInboundSession() == null) { 071 setUseInboundSession(baseInfo.getUseInboundSession()); 072 } 073 if (getUseSessionArgs() == null) { 074 setUseSessionArgs(baseInfo.isUseSessionArgs()); 075 } 076 if (getUserName() == null) { 077 setUserName(baseInfo.getUserName()); 078 } 079 if (getDurableTopicPrefetch() != null) { 080 setDurableTopicPrefetch(baseInfo.getDurableTopicPrefetch()); 081 } 082 if (getOptimizeDurableTopicPrefetch() != null) { 083 setOptimizeDurableTopicPrefetch(baseInfo.getOptimizeDurableTopicPrefetch()); 084 } 085 if (getQueuePrefetch() != null) { 086 setQueuePrefetch(baseInfo.getQueuePrefetch()); 087 } 088 if (getQueueBrowserPrefetch() != null) { 089 setQueueBrowserPrefetch(baseInfo.getQueueBrowserPrefetch()); 090 } 091 if (getTopicPrefetch() != null) { 092 setTopicPrefetch(baseInfo.getTopicPrefetch()); 093 } 094 } 095 } 096 097 /** 098 * @see javax.resource.spi.ResourceAdapterAssociation#getResourceAdapter() 099 */ 100 @Override 101 public ResourceAdapter getResourceAdapter() { 102 return null; 103 } 104 105 /** 106 * @see java.lang.Object#equals(java.lang.Object) 107 */ 108 @Override 109 public boolean equals(Object object) { 110 if (object == null || object.getClass() != ActiveMQManagedConnectionFactory.class) { 111 return false; 112 } 113 return ((ActiveMQManagedConnectionFactory) object).getInfo().equals(getInfo()); 114 } 115 116 /** 117 * @see java.lang.Object#hashCode() 118 */ 119 @Override 120 public int hashCode() { 121 return getInfo().hashCode(); 122 } 123 124 /** 125 * Writes this factory during serialization along with the superclass' 126 * <i>info</i> property. This needs to be done manually since the superclass 127 * is not serializable itself. 128 * 129 * @param out 130 * the stream to write object state to 131 * @throws java.io.IOException 132 * if the object cannot be serialized 133 */ 134 private void writeObject(ObjectOutputStream out) throws IOException { 135 if (logWriter != null && !(logWriter instanceof Serializable)) { 136 // if the PrintWriter injected by the application server is not 137 // serializable we just drop the reference and let the application 138 // server re-inject a PrintWriter later (after this factory has been 139 // deserialized again) using the standard setLogWriter() method 140 logWriter = null; 141 } 142 out.defaultWriteObject(); 143 out.writeObject(getInfo()); 144 } 145 146 /** 147 * Restores this factory along with the superclass' <i>info</i> property. 148 * This needs to be done manually since the superclass is not serializable 149 * itself. 150 * 151 * @param in 152 * the stream to read object state from 153 * @throws java.io.IOException 154 * if the object state could not be restored 155 * @throws java.lang.ClassNotFoundException 156 * if the object state could not be restored 157 */ 158 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 159 in.defaultReadObject(); 160 setInfo((ActiveMQConnectionRequestInfo) in.readObject()); 161 log = LoggerFactory.getLogger(getClass()); 162 } 163 164 /** 165 * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager) 166 */ 167 @Override 168 public Object createConnectionFactory(ConnectionManager manager) throws ResourceException { 169 return new ActiveMQConnectionFactory(this, manager, getInfo()); 170 } 171 172 /** 173 * This is used when not running in an app server. For now we are creating a 174 * ConnectionFactory that has our SimpleConnectionManager implementation but 175 * it may be a better idea to not support this. The JMS api will have many 176 * quirks the user may not expect when running through the resource adapter. 177 * 178 * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory() 179 */ 180 @Override 181 public Object createConnectionFactory() throws ResourceException { 182 return new ActiveMQConnectionFactory(this, new SimpleConnectionManager(), getInfo()); 183 } 184 185 /** 186 * @see javax.resource.spi.ManagedConnectionFactory#createManagedConnection(javax.security.auth.Subject, 187 * javax.resource.spi.ConnectionRequestInfo) 188 */ 189 @Override 190 public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException { 191 ActiveMQConnectionRequestInfo amqInfo = getInfo(); 192 if (connectionRequestInfo instanceof ActiveMQConnectionRequestInfo) { 193 amqInfo = (ActiveMQConnectionRequestInfo) connectionRequestInfo; 194 } 195 try { 196 return new ActiveMQManagedConnection(subject, makeConnection(amqInfo), amqInfo); 197 } catch (JMSException e) { 198 throw new ResourceException("Could not create connection.", e); 199 } 200 } 201 202 /** 203 * @see javax.resource.spi.ManagedConnectionFactory#matchManagedConnections(java.util.Set, 204 * javax.security.auth.Subject, 205 * javax.resource.spi.ConnectionRequestInfo) 206 */ 207 @Override 208 public ManagedConnection matchManagedConnections(Set connections, Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException { 209 Iterator iterator = connections.iterator(); 210 while (iterator.hasNext()) { 211 ActiveMQManagedConnection c = (ActiveMQManagedConnection) iterator.next(); 212 if (c.matches(subject, connectionRequestInfo)) { 213 try { 214 c.associate(subject, (ActiveMQConnectionRequestInfo) connectionRequestInfo); 215 return c; 216 } catch (JMSException e) { 217 throw new ResourceException(e); 218 } 219 } 220 } 221 return null; 222 } 223 224 /** 225 * @see javax.resource.spi.ManagedConnectionFactory#setLogWriter(java.io.PrintWriter) 226 */ 227 @Override 228 public void setLogWriter(PrintWriter aLogWriter) throws ResourceException { 229 if (log.isTraceEnabled()) { 230 log.trace("setting log writer [" + aLogWriter + "]"); 231 } 232 this.logWriter = aLogWriter; 233 } 234 235 /** 236 * @see javax.resource.spi.ManagedConnectionFactory#getLogWriter() 237 */ 238 @Override 239 public PrintWriter getLogWriter() throws ResourceException { 240 if (log.isTraceEnabled()) { 241 log.trace("getting log writer [" + logWriter + "]"); 242 } 243 return logWriter; 244 } 245}