content: /**
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.activemq.ra;
  
  import java.io.IOException;
  import java.io.ObjectInputStream;
  import java.io.ObjectOutputStream;
  import java.io.PrintWriter;
  import java.io.Serializable;
  import java.util.Iterator;
  import java.util.Set;
  
  import jakarta.jms.JMSException;
  import jakarta.resource.ResourceException;
  import jakarta.resource.spi.ConnectionManager;
  import jakarta.resource.spi.ConnectionRequestInfo;
  import jakarta.resource.spi.ManagedConnection;
  import jakarta.resource.spi.ManagedConnectionFactory;
  import jakarta.resource.spi.ResourceAdapter;
  import jakarta.resource.spi.ResourceAdapterAssociation;
  import javax.security.auth.Subject;
  
  import org.slf4j.LoggerFactory;
  
  /**
   * @version $Revisio n$ TODO: Must override equals and hashCode (JCA spec 16.4)
   * @org.apache.xbean.XBean element="managedConnectionFactory"
   */
  public class ActiveMQManagedConnectionFactory extends ActiveMQConnectionSupport implements ManagedConnectionFactory, ResourceAdapterAssociation {
  
      private static final long serialVersionUID = 6196921962230582875L;
      private PrintWriter logWriter;
  
      /**
       * @see javax.resource.spi.ResourceAdapterAssociation#setResourceAdapter(javax.resource.spi.ResourceAdapter)
       */
      @Override
      public void setResourceAdapter(ResourceAdapter adapter) throws ResourceException {
          if (!(adapter instanceof MessageResourceAdapter)) {
              throw new ResourceException("ResourceAdapter is not of type: " + MessageResourceAdapter.class.getName());
          } else {
              if (log.isDebugEnabled()) {
                  log.debug(this + ", copying standard ResourceAdapter configuration properties");
              }
  
              ActiveMQConnectionRequestInfo baseInfo = ((MessageResourceAdapter) adapter).getInfo().copy();
              if (getClientid() == null) {
                  setClientid(baseInfo.getClientid());
              }
              if (getPassword() == null) {
                  setPassword(baseInfo.getPassword());
              }
              if (getServerUrl() == null) {
                  setServerUrl(baseInfo.getServerUrl());
              }
              if (getUseInboundSession() == null) {
                  setUseInboundSession(baseInfo.getUseInboundSession());
              }
              if (getUseSessionArgs() == null) {
                  setUseSessionArgs(baseInfo.isUseSessionArgs());
              }
              if (getUserName() == null) {
                  setUserName(baseInfo.getUserName());
              }
              if (getDurableTopicPrefetch() == null) {
                  setDurableTopicPrefetch(baseInfo.getDurableTopicPrefetch());
              }
              if (getOptimizeDurableTopicPrefetch() == null) {
                  setOptimizeDurableTopicPrefetch(baseInfo.getOptimizeDurableTopicPrefetch());
              }
              if (getQueuePrefetch() == null) {
                  setQueuePrefetch(baseInfo.getQueuePrefetch());
              }
              if (getQueueBrowserPrefetch() == null) {
                  setQueueBrowserPrefetch(baseInfo.getQueueBrowserPrefetch());
              }
              if (getTopicPrefetch() == null) {
                  setTopicPrefetch(baseInfo.getTopicPrefetch());
              }
              if (getKeyStore() == null) {
                  setKeyStore(baseInfo.getKeyStore());
              }
              if (getKeyStorePassword() == null) {
                  setKeyStorePassword(baseInfo.getKeyStorePassword());
              }
              if (getTrustStore() == null) {
                  setTrustStore(baseInfo.getTrustStore());
              }
              if (getTrustStorePassword() == null) {
                  setTrustStorePassword(baseInfo.getTrustStorePassword());
              }
          }
      }
  
      /**
       * @see javax.resource.spi.ResourceAdapterAssociation#getResourceAdapter()
       */
      @Override
      public ResourceAdapter getResourceAdapter() {
          return null;
      }
  
      /**
       * @see java.lang.Object#equals(java.lang.Object)
       */
      @Override
      public boolean equals(Object object) {
          if (object == null || object.getClass() != ActiveMQManagedConnectionFactory.class) {
              return false;
          }
          return ((ActiveMQManagedConnectionFactory) object).getInfo().equals(getInfo());
      }
  
      /**
       * @see java.lang.Object#hashCode()
       */
      @Override
      public int hashCode() {
          return getInfo().hashCode();
      }
  
      /**
       * Writes this factory during serialization along with the superclass'
       * <i>info</i> property. This needs to be done manually since the superclass
       * is not serializable itself.
       *
       * @param out
       *        the stream to write object state to
       * @throws java.io.IOException
       *         if the object cannot be serialized
       */
      private void writeObject(ObjectOutputStream out) throws IOException {
          if (logWriter != null && !(logWriter instanceof Serializable)) {
              // if the PrintWriter injected by the application server is not
              // serializable we just drop the reference and let the application
              // server re-inject a PrintWriter later (after this factory has been
              // deserialized again) using the standard setLogWriter() method
              logWriter = null;
          }
          out.defaultWriteObject();
          out.writeObject(getInfo());
      }
  
      /**
       * Restores this factory along with the superclass' <i>info</i> property.
       * This needs to be done manually since the superclass is not serializable
       * itself.
       *
       * @param in
       *        the stream to read object state from
       * @throws java.io.IOException
       *         if the object state could not be restored
       * @throws java.lang.ClassNotFoundException
       *         if the object state could not be restored
       */
      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
          in.defaultReadObject();
          setInfo((ActiveMQConnectionRequestInfo) in.readObject());
          log = LoggerFactory.getLogger(getClass());
      }
  
      /**
       * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager)
       */
      @Override
      public Object createConnectionFactory(ConnectionManager manager) throws ResourceException {
          return new ActiveMQConnectionFactory(this, manager, getInfo());
      }
  
      /**
       * This is used when not running in an app server. For now we are creating a
       * ConnectionFactory that has our SimpleConnectionManager implementation but
       * it may be a better idea to not support this. The JMS api will have many
       * quirks the user may not expect when running through the resource adapter.
       *
       * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory()
       */
      @Override
      public Object createConnectionFactory() throws ResourceException {
          return new ActiveMQConnectionFactory(this, new SimpleConnectionManager(), getInfo());
      }
  
      /**
       * @see javax.resource.spi.ManagedConnectionFactory#createManagedConnection(javax.security.auth.Subject,
       *      javax.resource.spi.ConnectionRequestInfo)
       */
      @Override
      public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException {
          ActiveMQConnectionRequestInfo amqInfo = getInfo();
          if (connectionRequestInfo instanceof ActiveMQConnectionRequestInfo) {
              amqInfo = (ActiveMQConnectionRequestInfo) connectionRequestInfo;
          }
          try {
              return new ActiveMQManagedConnection(subject, makeConnection(amqInfo), amqInfo);
          } catch (JMSException e) {
              throw new ResourceException("Could not create connection.", e);
          }
      }
  
      /**
       * @see javax.resource.spi.ManagedConnectionFactory#matchManagedConnections(java.util.Set,
       *      javax.security.auth.Subject,
       *      javax.resource.spi.ConnectionRequestInfo)
       */
      @Override
      public ManagedConnection matchManagedConnections(Set connections, Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException {
          Iterator iterator = connections.iterator();
          while (iterator.hasNext()) {
              ActiveMQManagedConnection c = (ActiveMQManagedConnection) iterator.next();
              if (c.matches(subject, connectionRequestInfo)) {
                  try {
                      c.associate(subject, (ActiveMQConnectionRequestInfo) connectionRequestInfo);
                      return c;
                  } catch (JMSException e) {
                      throw new ResourceException(e);
                  }
              }
          }
          return null;
      }
  
      /**
       * @see javax.resource.spi.ManagedConnectionFactory#setLogWriter(java.io.PrintWriter)
       */
      @Override
      public void setLogWriter(PrintWriter aLogWriter) throws ResourceException {
          if (log.isTraceEnabled()) {
              log.trace("setting log writer [" + aLogWriter + "]");
          }
          this.logWriter = aLogWriter;
      }
  
      /**
       * @see javax.resource.spi.ManagedConnectionFactory#getLogWriter()
       */
      @Override
      public PrintWriter getLogWriter() throws ResourceException {
          if (log.isTraceEnabled()) {
              log.trace("getting log writer [" + logWriter + "]");
          }
          return logWriter;
      }
  }
  