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 if (getKeyStore() == null) { 095 setKeyStore(baseInfo.getKeyStore()); 096 } 097 if (getKeyStorePassword() == null) { 098 setKeyStorePassword(baseInfo.getKeyStorePassword()); 099 } 100 if (getTrustStore() == null) { 101 setTrustStore(baseInfo.getTrustStore()); 102 } 103 if (getTrustStorePassword() == null) { 104 setTrustStorePassword(baseInfo.getTrustStorePassword()); 105 } 106 } 107 } 108 109 /** 110 * @see javax.resource.spi.ResourceAdapterAssociation#getResourceAdapter() 111 */ 112 @Override 113 public ResourceAdapter getResourceAdapter() { 114 return null; 115 } 116 117 /** 118 * @see java.lang.Object#equals(java.lang.Object) 119 */ 120 @Override 121 public boolean equals(Object object) { 122 if (object == null || object.getClass() != ActiveMQManagedConnectionFactory.class) { 123 return false; 124 } 125 return ((ActiveMQManagedConnectionFactory) object).getInfo().equals(getInfo()); 126 } 127 128 /** 129 * @see java.lang.Object#hashCode() 130 */ 131 @Override 132 public int hashCode() { 133 return getInfo().hashCode(); 134 } 135 136 /** 137 * Writes this factory during serialization along with the superclass' 138 * <i>info</i> property. This needs to be done manually since the superclass 139 * is not serializable itself. 140 * 141 * @param out 142 * the stream to write object state to 143 * @throws java.io.IOException 144 * if the object cannot be serialized 145 */ 146 private void writeObject(ObjectOutputStream out) throws IOException { 147 if (logWriter != null && !(logWriter instanceof Serializable)) { 148 // if the PrintWriter injected by the application server is not 149 // serializable we just drop the reference and let the application 150 // server re-inject a PrintWriter later (after this factory has been 151 // deserialized again) using the standard setLogWriter() method 152 logWriter = null; 153 } 154 out.defaultWriteObject(); 155 out.writeObject(getInfo()); 156 } 157 158 /** 159 * Restores this factory along with the superclass' <i>info</i> property. 160 * This needs to be done manually since the superclass is not serializable 161 * itself. 162 * 163 * @param in 164 * the stream to read object state from 165 * @throws java.io.IOException 166 * if the object state could not be restored 167 * @throws java.lang.ClassNotFoundException 168 * if the object state could not be restored 169 */ 170 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 171 in.defaultReadObject(); 172 setInfo((ActiveMQConnectionRequestInfo) in.readObject()); 173 log = LoggerFactory.getLogger(getClass()); 174 } 175 176 /** 177 * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager) 178 */ 179 @Override 180 public Object createConnectionFactory(ConnectionManager manager) throws ResourceException { 181 return new ActiveMQConnectionFactory(this, manager, getInfo()); 182 } 183 184 /** 185 * This is used when not running in an app server. For now we are creating a 186 * ConnectionFactory that has our SimpleConnectionManager implementation but 187 * it may be a better idea to not support this. The JMS api will have many 188 * quirks the user may not expect when running through the resource adapter. 189 * 190 * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory() 191 */ 192 @Override 193 public Object createConnectionFactory() throws ResourceException { 194 return new ActiveMQConnectionFactory(this, new SimpleConnectionManager(), getInfo()); 195 } 196 197 /** 198 * @see javax.resource.spi.ManagedConnectionFactory#createManagedConnection(javax.security.auth.Subject, 199 * javax.resource.spi.ConnectionRequestInfo) 200 */ 201 @Override 202 public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException { 203 ActiveMQConnectionRequestInfo amqInfo = getInfo(); 204 if (connectionRequestInfo instanceof ActiveMQConnectionRequestInfo) { 205 amqInfo = (ActiveMQConnectionRequestInfo) connectionRequestInfo; 206 } 207 try { 208 return new ActiveMQManagedConnection(subject, makeConnection(amqInfo), amqInfo); 209 } catch (JMSException e) { 210 throw new ResourceException("Could not create connection.", e); 211 } 212 } 213 214 /** 215 * @see javax.resource.spi.ManagedConnectionFactory#matchManagedConnections(java.util.Set, 216 * javax.security.auth.Subject, 217 * javax.resource.spi.ConnectionRequestInfo) 218 */ 219 @Override 220 public ManagedConnection matchManagedConnections(Set connections, Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException { 221 Iterator iterator = connections.iterator(); 222 while (iterator.hasNext()) { 223 ActiveMQManagedConnection c = (ActiveMQManagedConnection) iterator.next(); 224 if (c.matches(subject, connectionRequestInfo)) { 225 try { 226 c.associate(subject, (ActiveMQConnectionRequestInfo) connectionRequestInfo); 227 return c; 228 } catch (JMSException e) { 229 throw new ResourceException(e); 230 } 231 } 232 } 233 return null; 234 } 235 236 /** 237 * @see javax.resource.spi.ManagedConnectionFactory#setLogWriter(java.io.PrintWriter) 238 */ 239 @Override 240 public void setLogWriter(PrintWriter aLogWriter) throws ResourceException { 241 if (log.isTraceEnabled()) { 242 log.trace("setting log writer [" + aLogWriter + "]"); 243 } 244 this.logWriter = aLogWriter; 245 } 246 247 /** 248 * @see javax.resource.spi.ManagedConnectionFactory#getLogWriter() 249 */ 250 @Override 251 public PrintWriter getLogWriter() throws ResourceException { 252 if (log.isTraceEnabled()) { 253 log.trace("getting log writer [" + logWriter + "]"); 254 } 255 return logWriter; 256 } 257}