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     */
017    package org.apache.activemq.ra;
018    
019    import java.io.IOException;
020    import java.io.ObjectInputStream;
021    import java.io.ObjectOutputStream;
022    import java.io.PrintWriter;
023    import java.io.Serializable;
024    import java.util.Iterator;
025    import java.util.Set;
026    
027    import javax.jms.JMSException;
028    import javax.resource.ResourceException;
029    import javax.resource.spi.ConnectionManager;
030    import javax.resource.spi.ConnectionRequestInfo;
031    import javax.resource.spi.ManagedConnection;
032    import javax.resource.spi.ManagedConnectionFactory;
033    import javax.resource.spi.ResourceAdapter;
034    import javax.resource.spi.ResourceAdapterAssociation;
035    import javax.security.auth.Subject;
036    import org.slf4j.LoggerFactory;
037    
038    /**
039     * @version $Revisio n$ TODO: Must override equals and hashCode (JCA spec 16.4)
040     * @org.apache.xbean.XBean element="managedConnectionFactory"
041     */
042    public class ActiveMQManagedConnectionFactory extends ActiveMQConnectionSupport
043            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        public void setResourceAdapter(ResourceAdapter adapter) throws ResourceException {
052            if (!(adapter instanceof MessageResourceAdapter)) {
053                throw new ResourceException("ResourceAdapter is not of type: " + MessageResourceAdapter.class.getName());
054            }
055            else
056            {
057                if ( log.isDebugEnabled() ) {
058                    log.debug("copying standard ResourceAdapter configuration properties");
059                }
060    
061                ActiveMQConnectionRequestInfo baseInfo = ((MessageResourceAdapter) adapter).getInfo().copy();
062                if (getClientid() == null) {
063                    setClientid(baseInfo.getClientid());
064                }
065                if (getPassword() == null) {
066                    setPassword(baseInfo.getPassword());
067                }
068                if (getServerUrl() == null) {
069                    setServerUrl(baseInfo.getServerUrl());
070                }
071                if (getUseInboundSession() == null) {
072                    setUseInboundSession(baseInfo.getUseInboundSession());
073                }
074                if (getUserName() == null) {
075                    setUserName(baseInfo.getUserName());
076                }
077                if (getDurableTopicPrefetch() != null) {
078                    setDurableTopicPrefetch(baseInfo.getDurableTopicPrefetch());
079                }
080                if (getOptimizeDurableTopicPrefetch() != null) {
081                    setOptimizeDurableTopicPrefetch(baseInfo.getOptimizeDurableTopicPrefetch());
082                }
083                if (getQueuePrefetch() != null) {
084                    setQueuePrefetch(baseInfo.getQueuePrefetch());
085                }
086                if (getQueueBrowserPrefetch() != null) {
087                    setQueueBrowserPrefetch(baseInfo.getQueueBrowserPrefetch());
088                }
089                if (getTopicPrefetch() != null) {
090                    setTopicPrefetch(baseInfo.getTopicPrefetch());
091                }
092                if (getInputStreamPrefetch() != null) {
093                    setInputStreamPrefetch(baseInfo.getInputStreamPrefetch());
094                }
095            }
096        }
097    
098        /**
099         * @see javax.resource.spi.ResourceAdapterAssociation#getResourceAdapter()
100         */
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' <i>info</i> property.
126         * This needs to be done manually since the superclass is not serializable itself.
127         * 
128         * @param out the stream to write object state to
129         * @throws java.io.IOException if the object cannot be serialized
130         */
131        private void writeObject(ObjectOutputStream out) throws IOException {
132            if ( logWriter != null && !(logWriter instanceof Serializable) ) {
133                // if the PrintWriter injected by the application server is not
134                // serializable we just drop the reference and let the application
135                // server re-inject a PrintWriter later (after this factory has been
136                // deserialized again) using the standard setLogWriter() method
137                logWriter = null;
138        }
139            out.defaultWriteObject();
140            out.writeObject(getInfo());
141        }
142    
143        /**
144         * Restores this factory along with the superclass' <i>info</i> property.
145         * This needs to be done manually since the superclass is not serializable itself.
146         * 
147         * @param in the stream to read object state from
148         * @throws java.io.IOException if the object state could not be restored
149         * @throws java.lang.ClassNotFoundException if the object state could not be restored
150         */
151        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
152            in.defaultReadObject();
153            setInfo((ActiveMQConnectionRequestInfo) in.readObject());
154            log = LoggerFactory.getLogger(getClass());
155        }
156        
157        /**
158         * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager)
159         */
160        public Object createConnectionFactory(ConnectionManager manager) throws ResourceException {
161            return new ActiveMQConnectionFactory(this, manager, getInfo());
162        }
163    
164        /**
165         * This is used when not running in an app server. For now we are creating a
166         * ConnectionFactory that has our SimpleConnectionManager implementation but
167         * it may be a better idea to not support this. The JMS api will have many
168         * quirks the user may not expect when running through the resource adapter.
169         * 
170         * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory()
171         */
172        public Object createConnectionFactory() throws ResourceException {
173            return new ActiveMQConnectionFactory(this, new SimpleConnectionManager(), getInfo());
174        }
175    
176        /**
177         * @see javax.resource.spi.ManagedConnectionFactory#createManagedConnection(javax.security.auth.Subject,
178         *      javax.resource.spi.ConnectionRequestInfo)
179         */
180        public ManagedConnection createManagedConnection(
181                Subject subject, 
182                ConnectionRequestInfo connectionRequestInfo) throws ResourceException {
183            ActiveMQConnectionRequestInfo amqInfo = getInfo();
184            if ( connectionRequestInfo instanceof ActiveMQConnectionRequestInfo ) {
185                amqInfo = (ActiveMQConnectionRequestInfo) connectionRequestInfo;
186                }
187            try {
188                return new ActiveMQManagedConnection(subject, makeConnection(amqInfo), amqInfo);
189            } catch (JMSException e) {
190                throw new ResourceException("Could not create connection.", e);
191            }
192        }
193    
194        /**
195         * @see javax.resource.spi.ManagedConnectionFactory#matchManagedConnections(java.util.Set,
196         *      javax.security.auth.Subject,
197         *      javax.resource.spi.ConnectionRequestInfo)
198         */
199        public ManagedConnection matchManagedConnections(
200                Set connections, 
201                Subject subject, 
202                ConnectionRequestInfo connectionRequestInfo) throws ResourceException {
203            Iterator iterator = connections.iterator();
204            while (iterator.hasNext()) {
205                ActiveMQManagedConnection c = (ActiveMQManagedConnection)iterator.next();
206                if (c.matches(subject, connectionRequestInfo)) {
207                    try {
208                        c.associate(subject, (ActiveMQConnectionRequestInfo) connectionRequestInfo);
209                        return c;
210                    } catch (JMSException e) {
211                        throw new ResourceException(e);
212                    }
213                }
214            }
215            return null;
216        }
217    
218        /**
219         * @see javax.resource.spi.ManagedConnectionFactory#setLogWriter(java.io.PrintWriter)
220         */
221        public void setLogWriter(PrintWriter aLogWriter) throws ResourceException {
222            if ( log.isTraceEnabled() ) {
223                log.trace("setting log writer [" + aLogWriter + "]");
224        }
225            this.logWriter = aLogWriter;
226        }
227    
228        /**
229         * @see javax.resource.spi.ManagedConnectionFactory#getLogWriter()
230         */
231        public PrintWriter getLogWriter() throws ResourceException {
232            if ( log.isTraceEnabled() ) {
233                log.trace("getting log writer [" + logWriter + "]");
234            }
235            return logWriter;
236        }
237    
238        }