/*
 * 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.uima.adapter.jms.client;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Collections;
import java.util.Comparator;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.DestinationDoesNotExistException;
import org.apache.activemq.transport.TransportListener;
import org.apache.uima.UIMAFramework;
import org.apache.uima.UIMARuntimeException;
import org.apache.uima.UIMA_IllegalStateException;
import org.apache.uima.aae.AsynchAECasManager;
import org.apache.uima.aae.UIDGenerator;
import org.apache.uima.aae.UIMAEE_Constants;
import org.apache.uima.aae.UimaSerializer;
import org.apache.uima.aae.client.UimaASProcessStatus;
import org.apache.uima.aae.client.UimaASProcessStatusImpl;
import org.apache.uima.aae.client.UimaASStatusCallbackListener;
import org.apache.uima.aae.client.UimaAsBaseCallbackListener;
import org.apache.uima.aae.client.UimaAsynchronousEngine;
import org.apache.uima.aae.controller.AggregateAnalysisEngineController_impl;
import org.apache.uima.aae.delegate.Delegate;
import org.apache.uima.aae.delegate.Delegate.DelegateEntry;
import org.apache.uima.aae.error.AsynchAEException;
import org.apache.uima.aae.error.InvalidMessageException;
import org.apache.uima.aae.error.MessageTimeoutException;
import org.apache.uima.aae.error.ServiceShutdownException;
import org.apache.uima.aae.error.UimaASCollectionProcessCompleteTimeout;
import org.apache.uima.aae.error.UimaASMetaRequestTimeout;
import org.apache.uima.aae.error.UimaASPingTimeout;
import org.apache.uima.aae.error.UimaASProcessCasTimeout;
import org.apache.uima.aae.error.UimaEEServiceException;
import org.apache.uima.aae.jmx.UimaASClientInfo;
import org.apache.uima.aae.jmx.UimaASClientInfoMBean;
import org.apache.uima.aae.message.AsynchAEMessage;
import org.apache.uima.aae.monitor.statistics.AnalysisEnginePerformanceMetrics;
import org.apache.uima.adapter.jms.ConnectionValidator;
import org.apache.uima.adapter.jms.JmsConstants;
import org.apache.uima.adapter.jms.message.PendingMessage;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.SerialFormat;
import org.apache.uima.cas.impl.AllowPreexistingFS;
import org.apache.uima.cas.impl.BinaryCasSerDes6;
import org.apache.uima.cas.impl.BinaryCasSerDes6.ReuseInfo;
import org.apache.uima.cas.impl.CASImpl;
import org.apache.uima.cas.impl.Serialization;
import org.apache.uima.cas.impl.TypeSystemImpl;
import org.apache.uima.cas.impl.XmiSerializationSharedData;
import org.apache.uima.collection.CollectionReader;
import org.apache.uima.collection.EntityProcessStatus;
import org.apache.uima.jms.error.handler.BrokerConnectionException;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceProcessException;
import org.apache.uima.resource.metadata.ProcessingResourceMetaData;
import org.apache.uima.util.Level;
import org.apache.uima.util.ProcessTrace;
import org.apache.uima.util.XMLInputSource;
import org.apache.uima.util.impl.ProcessTrace_impl;

public abstract class BaseUIMAAsynchronousEngineCommon_impl implements UimaAsynchronousEngine,
        MessageListener {
  private static final Class<BaseUIMAAsynchronousEngineCommon_impl> CLASS_NAME = 
		  BaseUIMAAsynchronousEngineCommon_impl.class;

  public enum ClientState {INITIALIZING, RUNNING, FAILED, RECONNECTING, STOPPING, STOPPED};
  
  protected ClientState state = ClientState.INITIALIZING;

  protected String brokerURI = null;

  protected static final String SHADOW_CAS_POOL = "ShadowCasPool";

  protected static final int MetadataTimeout = 1;

  protected static final int CpCTimeout = 2;

  protected static final int ProcessTimeout = 3;

  protected static final int PingTimeout = 4;

  protected volatile boolean initialized;

  protected List listeners = new ArrayList();

  protected AsynchAECasManager asynchManager;

  protected boolean remoteService = false;

  protected CollectionReader collectionReader = null;

  protected volatile boolean running = false;

  protected ProcessingResourceMetaData resourceMetadata;
  
  protected CAS sendAndReceiveCAS = null;

  protected UIDGenerator idGenerator = new UIDGenerator();

  protected ConcurrentHashMap<String, ClientRequest> clientCache = new ConcurrentHashMap<String, ClientRequest>();

  protected ConcurrentHashMap<Long, ThreadMonitor> threadMonitorMap = new ConcurrentHashMap<Long, ThreadMonitor>();

  // Default timeout for ProcessCas requests
  protected int processTimeout = 0;

  // Default timeout for GetMeta requests
  protected int metadataTimeout = 60000;

  // Default timeout for CpC requests is no timeout
  protected int cpcTimeout = 0;

  protected volatile boolean abort = false;

  protected static final String uniqueIdentifier = String.valueOf(System.nanoTime());

  protected Exception exc;

  // Counter maintaining a number of CASes sent to a service. The counter
  // is incremented every time a CAS is sent and decremented when the CAS
  // reply is received. It is also adjusted down in case of a timeout or
  // error.
  protected AtomicLong outstandingCasRequests = new AtomicLong();

  protected AtomicLong totalCasRequestsSentBetweenCpCs = new AtomicLong();

  protected ConcurrentHashMap springContainerRegistry = new ConcurrentHashMap();

  protected MessageConsumer consumer = null;

  protected SerialFormat serialFormat = SerialFormat.XMI;
  
  protected TypeSystemImpl remoteTypeSystem; // of the remote service, for filtered binary compression

  protected UimaASClientInfoMBean clientSideJmxStats = new UimaASClientInfo();

  private UimaSerializer uimaSerializer = new UimaSerializer();

  protected ClientServiceDelegate serviceDelegate = null;

  private Object stopMux = new Object();

  private Object sendMux = new Object();

  private BlockingQueue<CasQueueEntry> threadQueue = new LinkedBlockingQueue<CasQueueEntry>();

  private ConcurrentHashMap<Long, CasQueueEntry> threadRegistrar = new ConcurrentHashMap<Long, CasQueueEntry>();

  private volatile boolean casQueueProducerReady;

  private Object casProducerMux = new Object();

  protected BlockingQueue<PendingMessage> pendingMessageQueue = new LinkedBlockingQueue<PendingMessage>();

  // Create Semaphore that will signal when the producer object is initialized
  protected Semaphore producerSemaphore = new Semaphore(1);

  // Create Semaphore that will signal when CPC reply has been received
  protected Semaphore cpcSemaphore = new Semaphore(1);

  // Create Semaphore that will signal when GetMeta reply has been received
  protected Semaphore getMetaSemaphore = new Semaphore(0, true);

  // Signals when the client is ready to send CPC request
  protected Semaphore cpcReadySemaphore = new Semaphore(1);

  // Signals receipt of a CPC reply
  protected Semaphore cpcReplySemaphore = new Semaphore(1);

  protected volatile boolean producerInitialized;

  protected static ConcurrentHashMap<String, SharedConnection> sharedConnections =
		  new ConcurrentHashMap<String, SharedConnection>();
  
  //protected static SharedConnection sharedConnection = null;

  protected Thread shutdownHookThread = null;

  private ExecutorService exec = Executors.newFixedThreadPool(1);
  
  private volatile boolean casMultiplierDelegate;
  
  abstract public String getEndPointName() throws Exception;

  abstract protected TextMessage createTextMessage() throws Exception;

  abstract protected BytesMessage createBytesMessage() throws Exception;

  abstract protected void setMetaRequestMessage(Message msg) throws Exception;

  abstract protected void setCASMessage(String casReferenceId, CAS aCAS, Message msg)
          throws Exception;

  abstract protected void setCASMessage(String casReferenceId, String aSerializedCAS, Message msg)
          throws Exception;

  abstract protected void setCASMessage(String casReferenceId, byte[] aSerializedCAS, Message msg)
          throws Exception;
  
  abstract protected void setFreeCasMessage(Message msg, String aCasReferenceId, String selector) throws Exception;

  abstract protected void setStopMessage(Message msg, String aCasReferenceId) throws Exception;

  abstract protected void setCPCMessage(Message msg) throws Exception;

  abstract public void initialize(Map anApplicationContext) throws ResourceInitializationException;

  abstract protected void cleanup() throws Exception;

  abstract public String deploy(String[] aDeploymentDescriptorList, Map anApplicationContext)
          throws Exception;

  abstract protected String deploySpringContainer(String[] springContextFiles)
          throws ResourceInitializationException;

  abstract protected MessageSender getDispatcher();
  
  abstract protected void initializeConsumer(String aBrokerURI, Connection connection) throws Exception;

  abstract protected SharedConnection validateConnection(String aBrokerURI) throws Exception;
  
  abstract protected void dispatchFreeCasRequest(String casReferenceId, Message message) throws Exception;

  // enables/disable timer per CAS. Defaul is to use single timer for
  // all outstanding CASes
  protected volatile boolean timerPerCAS=false;
  
  //abstract protected  String getBrokerURI();

  protected void setBrokeryURI(String brokerURI ) {
	  this.brokerURI = brokerURI;
  }
  protected String getBrokerURI() {
	  return brokerURI;
  }
  
  public void addStatusCallbackListener(UimaAsBaseCallbackListener aListener) {
    if (running) {
	   throw new UIMA_IllegalStateException(JmsConstants.JMS_LOG_RESOURCE_BUNDLE,"UIMAJMS_listener_added_after_initialize__WARNING", new Object[]{});
	}
    listeners.add(aListener);
  }

  public SerialFormat getSerialFormat() {
    return serialFormat;
  }

  protected void setSerialFormat(SerialFormat aSerialFormat) {
    serialFormat = aSerialFormat;
  }
  
  public TypeSystemImpl getRemoteTypeSystem() {
    return remoteTypeSystem;
  }

  protected void setRemoteTypeSystem(TypeSystemImpl remoteTypeSystem) {
    this.remoteTypeSystem = remoteTypeSystem;
  }
  
  /**
   * Serializes a given CAS.
   * 
   * @param aCAS
   *          - CAS to serialize
   * @return - serialized CAS
   * 
   * @throws Exception
   */
  protected String serializeCAS(CAS aCAS, XmiSerializationSharedData serSharedData)
          throws Exception {
    return uimaSerializer.serializeCasToXmi(aCAS, serSharedData);
  }

  protected String serializeCAS(CAS aCAS) throws Exception {
    XmiSerializationSharedData serSharedData = new XmiSerializationSharedData();
    return uimaSerializer.serializeCasToXmi(aCAS, serSharedData);
  }

  public void removeStatusCallbackListener(UimaAsBaseCallbackListener aListener) {
    listeners.remove(aListener);
  }

  public void onBeforeMessageSend(UimaASProcessStatus status) {
      try {
   	    for (int i = 0; listeners != null && i < listeners.size(); i++) {
   	        UimaAsBaseCallbackListener statCL = (UimaAsBaseCallbackListener) listeners.get(i);
   	        statCL.onBeforeMessageSend(status);
   	    }
      } catch( Throwable t) {
			UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                    "onBeforeMessageSend", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAEE_exception__WARNING", t);
      }	  
  }

  public void onBeforeProcessCAS(UimaASProcessStatus status, String nodeIP, String pid) {
    for (int i = 0; listeners != null && i < listeners.size(); i++) {
      UimaAsBaseCallbackListener statCL = (UimaAsBaseCallbackListener) listeners.get(i);
      try {
          statCL.onBeforeProcessCAS(status, nodeIP, pid);
    	  
      } catch( Throwable t) {
			UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                    "onBeforeProcessCAS", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAEE_exception__WARNING", t);
      }
    }
  }

  public void onBeforeProcessMeta(String nodeIP, String pid) {
	  for (int i = 0; listeners != null && i < listeners.size(); i++) {
		  UimaAsBaseCallbackListener statCL = (UimaAsBaseCallbackListener) listeners
				  .get(i);
		  try {
			  statCL.onBeforeProcessMeta(nodeIP, pid);
		  } catch (Throwable t) {
			  UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING,
					  getClass().getName(), "onBeforeProcessMeta",
					  UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
					  "UIMAEE_exception__WARNING", t);
		  }
	  }
  }
  public synchronized void setCollectionReader(CollectionReader aCollectionReader)
          throws ResourceInitializationException {
    if (initialized) {
      // Uima ee client has already been initialized. CR should be
      // set before calling initialize()
      throw new ResourceInitializationException();
    }
    collectionReader = aCollectionReader;
  }

  private void addMessage(PendingMessage msg) {
    pendingMessageQueue.add(msg);
  }

  protected void acquireCpcReadySemaphore() {
    try {
      // Acquire cpcReady semaphore to block sending CPC request until
      // ALL outstanding CASes are received.
      cpcReadySemaphore.acquire();
    } catch (InterruptedException e) {
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                    "collectionProcessingComplete", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAJMS_client_interrupted_while_acquiring_cpcReadySemaphore__WARNING", new Object[] {});
          }
    }
  }

  public synchronized void collectionProcessingComplete() throws ResourceProcessException {
    try {
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(),
                "collectionProcessingComplete", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_app_cpc_request_FINEST", new Object[] {});
      }
      if (outstandingCasRequests.get() > 0) {
        UIMAFramework.getLogger(CLASS_NAME)
                .logrb(
                        Level.INFO,
                        CLASS_NAME.getName(),
                        "collectionProcessingComplete",
                        JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                        "UIMAJMS_in_cpc_INFO",
                        new Object[] { outstandingCasRequests.get(),
                            totalCasRequestsSentBetweenCpCs.get() });
      }
      // If the client was initialized but never sent any CASes its cpcReadySemaphore
      // must be first explicitly released to enable the code to send CPC to a service.
      // The semaphore is initially acquired in the initialize(Map) method and typically
      // released when the number of CASes sent equals the number of CASes received. Since
      // no CASes were sent we must do the release here to be able to continue.
      if (totalCasRequestsSentBetweenCpCs.get() == 0 && !serviceDelegate.isAwaitingPingReply()) {
        cpcReadySemaphore.release();
      }
      // The cpcReadySemaphore was initially acquired in the initialize() method
      // so below we wait until ALL CASes are processed. Once all
      // CASes are received the semaphore will be released
      acquireCpcReadySemaphore();
      serviceDelegate.cancelDelegateTimer();
      if (!running) {
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
                  "collectionProcessingComplete", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_cpc_request_not_done_INFO", new Object[] {});
        }
        return;
      }

      ClientRequest requestToCache = new ClientRequest(uniqueIdentifier, this); // , timeout);
      requestToCache.setIsRemote(remoteService);
      requestToCache.setCPCRequest(true);
      requestToCache.setCpcTimeout(cpcTimeout);
      requestToCache.setEndpoint(getEndPointName());

      clientCache.put(uniqueIdentifier, requestToCache);

      PendingMessage msg = new PendingMessage(AsynchAEMessage.CollectionProcessComplete);
      if (cpcTimeout > 0) {
        requestToCache.startTimer();
        msg.put(UimaAsynchronousEngine.CpcTimeout, String.valueOf(cpcTimeout));
      }
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(),
                "collectionProcessingComplete", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_started_cpc_request_timer_FINEST", new Object[] {});
      }
      // Add CPC message to the pending queue
      addMessage(msg);
      // Acquire cpc semaphore. When a CPC reply comes or there is a timeout or the client
      // is stopped, the semaphore will be released.
      try {
        cpcReplySemaphore.acquire();
      } catch (InterruptedException ex) {
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                    "collectionProcessingComplete", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAJMS_client_interrupted_while_acquiring_cpcReplySemaphore__WARNING", new Object[] {});
          }
      }
      // Wait for CPC Reply. This blocks on the cpcReplySemaphore
      waitForCpcReply();
      totalCasRequestsSentBetweenCpCs.set(0); // reset number of CASes sent to a service
      cancelTimer(uniqueIdentifier);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(),
                "collectionProcessingComplete", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_cancelled_cpc_request_timer_FINEST", new Object[] {});
      }
      if (running) {
        for (int i = 0; listeners != null && i < listeners.size(); i++) {
          ((UimaASStatusCallbackListener) listeners.get(i)).collectionProcessComplete(null);
        }
      }
    } catch (Exception e) {
      throw new ResourceProcessException(e);
    }
  }

  private void releaseCacheEntries() {
    Iterator it = clientCache.keySet().iterator();
    while (it.hasNext()) {
      ClientRequest entry = clientCache.get((String) it.next());
      if (entry != null && entry.getCAS() != null) {
        entry.getCAS().release();
      }
    }
  }

  private void clearThreadRegistrar() {
    Iterator it = threadRegistrar.keySet().iterator();
    while (it.hasNext()) {
      Long key = (Long) it.next();
      CasQueueEntry entry = threadRegistrar.get(key);
      if (entry != null) {
        entry.clear();
      }
    }
  }

  public void doStop() {
    synchronized (stopMux) {
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "stop",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_stopping_as_client_INFO",
                new Object[] {});
      }
      if (!running) {
        return;
      }

      exec.shutdownNow();
      
      casQueueProducerReady = false;
      if (serviceDelegate != null) {
        serviceDelegate.cancelDelegateTimer();
        serviceDelegate.cancelDelegateGetMetaTimer();
      }
      try {
        try {
          clearThreadRegistrar();
          releaseCacheEntries();
        } catch (Exception ex) {
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                    "stop", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAEE_exception__WARNING", ex);
          }
        }

        // Unblock threads
        if (threadMonitorMap.size() > 0) {
          Iterator<?> it = threadMonitorMap.keySet().iterator();
          while (it.hasNext()) {
            long key = ((Long) it.next()).longValue();
            ThreadMonitor threadMonitor = (ThreadMonitor) threadMonitorMap.get(key);
            if (threadMonitor == null || threadMonitor.getMonitor() == null) {
              continue;
            }
            // convey that the semaphore was released from stop(). 
            // Any thread waiting in sendAndReceive() will check for this
            // and throw an exception back to the client. This would have 
            // a similar effect to an Interrupt. A thread in blocked in 
            // sendAndReceive() until a reply comes or stop() clears the
            // threadMonitor semaphore.
            threadMonitor.calledFromStopMethod();
            threadMonitor.getMonitor().release();
          }
        }
        cpcReadySemaphore.release();
        outstandingCasRequests.set(0); // reset global counter of outstanding requests

        cpcReplySemaphore.release();
        getMetaSemaphore.release();

        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "stop",
                  JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_stopped_as_client_INFO",
                  new Object[] {});
        }
        for (Iterator i = springContainerRegistry.entrySet().iterator(); i.hasNext();) {
          Map.Entry entry = (Map.Entry) i.next();
          Object key = entry.getKey();
          undeploy((String) key);
        }
        asynchManager = null;
        springContainerRegistry.clear();
        listeners.clear();
        clientCache.clear();
        threadQueue.clear();
        // Add empty CasQueueEntry object to the queue so that we wake up a reader thread which
        // may be sitting in the threadQueue.take() method. The reader will
        // first check the state of the 'running' flag and find it false which
        // will cause the reader to exit run() method
        threadQueue.add(new CasQueueEntry());
        threadRegistrar.clear();
      } catch (Exception e) {
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                  "stop", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAEE_exception__WARNING", e);
        }
      } finally {
        //  Shutdown hook has been previously added in case an application 'forgets'
        //  to call stop. Since we are in the stop() method, the hook is no longer 
        //  needed. Catch IllegalStateException which is thrown by JVM if it is already 
        //  in the process of shutting down
        if ( shutdownHookThread != null ) {
          try {
            Runtime.getRuntime().removeShutdownHook(shutdownHookThread);
          } catch( IllegalStateException e) {}
        }
      }
    }
  }

  /**
   * This method spins a thread where CASes are distributed to requesting threads in an orderly
   * fashion. CASes are distributed among the threads based on FIFO. Oldest waiting thread receive
   * the CAS first.
   * 
   */
  private void serveCASes() {
    synchronized (casProducerMux) {
      if (casQueueProducerReady) {
        return; // Only one CAS producer thread is needed/allowed
      }
      casQueueProducerReady = true;
    }
    // Spin a CAS producer thread
    new Thread() {
      public void run() {
        // terminate when the client API is stopped
        while (running) {
          try {
            // Remove the oldest CAS request from the queue.
            // Every thread requesting a CAS adds an entry to this
            // queue.
            CasQueueEntry entry = threadQueue.take();
            CAS cas = null;
            long startTime = System.nanoTime();
            // Wait for a free CAS instance
            if (!running || asynchManager == null) {
              return; // client API has been stopped
            }
            if (remoteService) {
              cas = asynchManager.getNewCas("ApplicationCasPoolContext");
            } else {
              cas = asynchManager.getNewCas();
            }
            long waitingTime = System.nanoTime() - startTime;
            clientSideJmxStats.incrementTotalTimeWaitingForCas(waitingTime);
            if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
              UIMAFramework.getLogger(CLASS_NAME).logrb(
                      Level.FINEST,
                      CLASS_NAME.getName(),
                      "serveCASes.run()",
                      JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                      "UIMAJMS_new_cas_FINEST",
                      new Object[] { "Time Waiting for CAS",
                          (double) waitingTime / (double) 1000000 });
            }
            if (running) { // only if the client is still running handle the new cas
							//	Assigns a CAS and releases a semaphore
	            entry.setCas(cas);
            } else {
              return; // Client is terminating
            }
          } catch (Exception e) {
            if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                      "serveCASes.run()", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                      "UIMAEE_exception__WARNING", e);
            }
          }
        }
      }
    }.start();
  }

  /**
   * Returns a CAS. If multiple threads call this method, the order of each request is preserved.
   * The oldest waiting thread receives the CAS. Each request for a CAS is queued, and when the CAS
   * becomes available the oldest waiting thread will receive it for processing.
   */
  public CAS getCAS() throws Exception {
    if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
      UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(), "getCAS",
              JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_request_for_cas_FINEST",
              new Object[] {});
    }
    if (!running) {
      throw new RuntimeException("Uima AS Client Is Stopping");
    }
    if (!initialized) {
      throw new ResourceInitializationException();
    }
    // Spin a thread that fetches CASes from the CAS Pool
    if (!casQueueProducerReady) {
      serveCASes(); // start CAS producer thread
    }
    // Each thread has an entry in the map. The entry is created in the
    // map once and cached.
    CasQueueEntry entry = getQueueEntry(Thread.currentThread().getId());
    // Add this thread entry to the queue of threads waiting for a CAS
    threadQueue.add(entry);
    if (entry != null) {
      while (running) {
        CAS cas = null;
        //  getCas() blocks until a CAS is set in the CAS producer thread
        //  ( see serveCASes() above).
        //  If the client is stopped, the cleanup code will force getCas()
        //  to release a semaphore to prevent a hang.
        if ( (cas = entry.getCas()) == null) {
          break;
        } else {
          //  We may have been waiting in entry.getCas() for awhile 
          //  so first check the status of the client. If is not running
          //  the semaphore in getCas() was forcefully released to prevent
          //  a hang. If we are stopping just return null.
          if ( !running ) {
            break;
          }
          return cas;
        }
      } // while
    }
    return null; // client has terminated
  }

  private CasQueueEntry getQueueEntry(long aThreadId) {
    CasQueueEntry entry = null;
    if (threadRegistrar.containsKey(aThreadId)) {
      entry = threadRegistrar.get(aThreadId);
    } else {
    	//	Creates a new instance and acquires a semaphore. The semaphore
    	//	is released in the CasQueueEntry.setCAS()
      entry = new CasQueueEntry();
      threadRegistrar.put(aThreadId, entry);
    }
    return entry;
  }

  protected void reset() {
  }

  /**
   * This class manages access to a CAS. A CAS is assigned
   * to an instance of this class in the CAS producer thread and
   * it is consumed in the getCAS() method. Access to a CAS
   * is protected by a semaphore.
   *
   */
  private static class CasQueueEntry {
    private CAS cas;

    private Semaphore semaphore = null;

    public CasQueueEntry() {
      semaphore = new Semaphore(1);
      //  Acquire the semaphore to force getCAS() to block
      //  until setCAS() or clear() is called
      semaphore.acquireUninterruptibly();
    }
    public CAS getCas() {
    	//	Wait until setCAS() is called
      semaphore.acquireUninterruptibly();
      return cas;
    }
    public void setCas(CAS cas) {
      this.cas = cas;
      //	Release semaphore so that getCAS() can return a CAS instance
      semaphore.release();
    }
    //	Called when the client is stopping to
    //	release a semaphore
    public void clear() {
      cas = null;
      semaphore.release();
    }

  }

  protected void sendMetaRequest() throws Exception {
    PendingMessage msg = new PendingMessage(AsynchAEMessage.GetMeta);
    ClientRequest requestToCache = new ClientRequest(uniqueIdentifier, this); // , metadataTimeout);
    requestToCache.setIsRemote(remoteService);
    requestToCache.setMetaRequest(true);
    requestToCache.setMetadataTimeout(metadataTimeout);

    requestToCache.setEndpoint(getEndPointName());

    clientCache.put(uniqueIdentifier, requestToCache);
    
    // Add message to the pending queue
    addMessage(msg);
  }

  protected void waitForCpcReply() {
    try {
      // wait for CPC reply
      cpcReplySemaphore.acquire();
    } catch (InterruptedException e) {

    } finally {
      cpcReplySemaphore.release();
    }
  }

  /**
   * Blocks while trying to acquire a semaphore awaiting receipt of GetMeta Reply. When the GetMeta
   * is received, or there is a timeout, or the client stops the semaphore will be released.
   */
  protected void waitForMetadataReply() {
    try {
      getMetaSemaphore.acquire();
    } catch (InterruptedException e) {
    	e.printStackTrace();
    } 
  }

  public String getPerformanceReport() {
    return null;
  }

  public synchronized void process() throws ResourceProcessException {
    if (!initialized) {
      throw new ResourceProcessException();
    }
    if (collectionReader == null) {
      throw new ResourceProcessException();
    }
    if (!casQueueProducerReady) {
      serveCASes(); // start CAS producer thread
    }
    CAS cas = null;
    boolean hasNext = true;
    while (initialized && running ) {
      try {
         if ( (hasNext = collectionReader.hasNext()) == true) {
             cas = getCAS();
             collectionReader.getNext(cas);
             String targetStringSelector = 
            		 System.getProperty(UimaAsynchronousEngine.TargetSelectorProperty);
             if (targetStringSelector != null && targetStringSelector.trim().length() > 0 ) {
            	 sendCAS(cas, targetStringSelector );
             } else {
            	 sendCAS(cas);
             }
             
         } else {
           break;
         }
      } catch (Exception e) {
        e.printStackTrace();
		throw new ResourceProcessException(e);
      }
    }
    //	If the CR is done, enter a polling loop waiting for outstanding CASes to return
    //  from a service
    if (hasNext == false ) {
    	Object mObject = new Object();
    	//	if client is running and there are outstanding CASe go sleep for awhile and
    	//  try again, until all CASes come back from a service
    	while ( running && serviceDelegate.getCasPendingReplyListSize() > 0 ) {
    		synchronized(mObject) {
    			try {
        			mObject.wait(100);
    			} catch( Exception e) {
    		        e.printStackTrace();
    				throw new ResourceProcessException(e);
    			}
    		}
    	}
    	collectionProcessingComplete();
    }
  }

  protected ConcurrentHashMap<String, ClientRequest> getCache() {
    return clientCache;
  }

  /**
   * Sends a given CAS for analysis to the UIMA EE Service.
   * 
   */
  private String sendCAS(CAS aCAS, ClientRequest requestToCache, String targetServiceId) throws ResourceProcessException {
    synchronized (sendMux) {
      if ( requestToCache == null ) {
        throw new ResourceProcessException(new Exception("Invalid Process Request. Cache Entry is Null"));
      }
      String casReferenceId = requestToCache.getCasReferenceId();
      // check if application wants to target a specific service instance to process the CAS
      if ( targetServiceId != null) {
    	  // the dispatcher will fetch the service target id before sending the msg
    	  requestToCache.setTargetServiceId(targetServiceId);
      }
      try {
        if (!running) {
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "sendCAS",
                    JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_not_sending_cas_INFO",
                    new Object[] { "Asynchronous Client is Stopping" });
          }
          return null;
        }

        clientCache.put(casReferenceId, requestToCache);
        PendingMessage msg = new PendingMessage(AsynchAEMessage.Process);
        long t1 = System.nanoTime();
        switch (serialFormat) {
        case XMI:
          XmiSerializationSharedData serSharedData = new XmiSerializationSharedData();
          String serializedCAS = serializeCAS(aCAS, serSharedData);
          msg.put(AsynchAEMessage.CAS, serializedCAS);
          if (remoteService) {  // always true 5/2013
            // Store the serialized CAS in case the timeout occurs and need to send the
            // the offending CAS to listeners for reporting
            requestToCache.setCAS(serializedCAS);
            requestToCache.setXmiSerializationSharedData(serSharedData);
          }
          break;
        case BINARY:
          byte[] serializedBinaryCAS = uimaSerializer.serializeCasToBinary(aCAS);
          msg.put(AsynchAEMessage.CAS, serializedBinaryCAS);
          break;
        case COMPRESSED_FILTERED:
          // can't use uimaserializer directly - project doesn't have ref to this one
          // for storing the reuse info
          BinaryCasSerDes6 bcs = new BinaryCasSerDes6(aCAS, this.getRemoteTypeSystem());
          ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
          bcs.serialize(baos);
          requestToCache.setCompress6ReuseInfo(bcs.getReuseInfo());           
          msg.put(AsynchAEMessage.CAS, baos.toByteArray());
          break;
        default:
          throw new UIMARuntimeException(new Exception("Internal Error"));    
        }
        
        requestToCache.setCAS(aCAS);

        requestToCache.setSerializationTime(System.nanoTime() - t1);
        msg.put(AsynchAEMessage.CasReference, casReferenceId);
        requestToCache.setIsRemote(remoteService);
        requestToCache.setEndpoint(getEndPointName());
        requestToCache.setProcessTimeout(processTimeout);
        requestToCache.clearTimeoutException();

        // The sendCAS() method is synchronized no need to synchronize the code below
        if (serviceDelegate.getState() == Delegate.TIMEOUT_STATE ) {
          SharedConnection sharedConnection = lookupConnection(getBrokerURI());
          
          //  Send Ping to service as getMeta request
          if ( sharedConnection != null && !serviceDelegate.isAwaitingPingReply() && sharedConnection.isOpen() ) {
            serviceDelegate.setAwaitingPingReply();
            // Add the cas to a list of CASes pending reply. Also start the timer if necessary
			// serviceDelegate.addCasToOutstandingList(requestToCache.getCasReferenceId());
        	  
        	  // since the service is in time out state, we dont send CASes to it just yet. Instead, place
        	  // a CAS in a pending dispatch list. CASes from this list will be sent once a response to PING
        	  // arrives.
            serviceDelegate.addCasToPendingDispatchList(requestToCache.getCasReferenceId(), aCAS.hashCode(), timerPerCAS); 
            if ( cpcReadySemaphore.availablePermits() > 0 ) {
              acquireCpcReadySemaphore();
            }

            // Send PING Request to check delegate's availability
            sendMetaRequest();
            // @@@@@@@@@@@@@@@ Changed on 4/20 serviceDelegate.cancelDelegateTimer();
            // Start a timer for GetMeta ping and associate a cas id
            // with this timer. The delegate is currently in a timed out
            // state due to a timeout on a CAS with a given casReferenceId.
            //  
            serviceDelegate.startGetMetaRequestTimer(casReferenceId);
            
            if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "sendCAS",
                      JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_client_sending_ping__FINE",
                      new Object[] { serviceDelegate.getKey() });
            }
            return casReferenceId;
          } else {
            if ( !requestToCache.isSynchronousInvocation() && !sharedConnection.isOpen() ) {
              Exception exception = new BrokerConnectionException("Unable To Deliver CAS:"+requestToCache.getCasReferenceId()+" To Destination. Connection To Broker "+getBrokerURI()+" Has Been Lost");
              handleException(exception, requestToCache.getCasReferenceId(), null, requestToCache, true);
              return casReferenceId;
            } else {
              //  Add to the outstanding list.  
			  //  serviceDelegate.addCasToOutstandingList(requestToCache.getCasReferenceId());
        	  // since the service is in time out state, we dont send CASes to it just yet. Instead, place
        	  // a CAS in a pending dispatch list. CASes from this list will be sent once a response to PING
        	  // arrives.
              serviceDelegate.addCasToPendingDispatchList(requestToCache.getCasReferenceId(), aCAS.hashCode(), timerPerCAS);
              return casReferenceId;
            }
          }
        }
        SharedConnection sharedConnection = lookupConnection(getBrokerURI());
        if ( sharedConnection != null &&  !sharedConnection.isOpen() ) {
          if (requestToCache != null && !requestToCache.isSynchronousInvocation() && aCAS != null ) {
            aCAS.release();
          }
          throw new ResourceProcessException(new BrokerConnectionException("Unable To Deliver Message To Destination. Connection To Broker "+sharedConnection.getBroker()+" Has Been Lost")); 
        }    
        // Incremented number of outstanding CASes sent to a service. When a reply comes
        // this counter is decremented
        outstandingCasRequests.incrementAndGet();
        // Increment total number of CASes sent to a service. This is reset
        // on CPC
        totalCasRequestsSentBetweenCpCs.incrementAndGet();
        // Add message to the pending queue
        addMessage(msg);
      } catch (ResourceProcessException e) {
        clientCache.remove(casReferenceId);
        throw e;
      } catch (Exception e) {
        clientCache.remove(casReferenceId);
        throw new ResourceProcessException(e);
      }
      return casReferenceId;
    }
  }

  /**
   * Checks the state of a delegate to see if it is in TIMEOUT State. If it is, push the CAS id onto
   * a list of CASes pending dispatch. The delegate is in a questionable state and the aggregate
   * sends a ping message to check delegate's availability. If the delegate responds to the ping,
   * all CASes in the pending dispatch list will be immediately dispatched.
   **/
  public boolean delayCasIfDelegateInTimedOutState(String aCasReferenceId, long casHashcode) throws AsynchAEException {
    if (serviceDelegate != null && serviceDelegate.getState() == Delegate.TIMEOUT_STATE) {
      // Add CAS id to the list of delayed CASes.
      serviceDelegate.addCasToPendingDispatchList(aCasReferenceId, casHashcode, timerPerCAS); 
      return true;
    }
    return false; // Cas Not Delayed
  }

  private ClientRequest produceNewClientRequestObject() {
    String casReferenceId = idGenerator.nextId();
    return new ClientRequest(casReferenceId, this);
  }

  /**
   * Sends a given CAS for analysis to the UIMA EE Service.
   * 
   */
  public synchronized String sendCAS(CAS aCAS) throws ResourceProcessException {
    if ( !running ) {
    	throw new ResourceProcessException(new UimaEEServiceException("Uima AS Client Has Been Stopped. Rejecting Request to Process CAS"));
    }
	  return this.sendCAS(aCAS, produceNewClientRequestObject(), null);
  }
  public synchronized String sendCAS(CAS aCAS, String targetServiceId) throws ResourceProcessException {
	    if ( !running ) {
	    	throw new ResourceProcessException(new UimaEEServiceException("Uima AS Client Has Been Stopped. Rejecting Request to Process CAS"));
	    }
		  return this.sendCAS(aCAS, produceNewClientRequestObject(),targetServiceId);
	  }

  /**
   * Handles response to CollectionProcessComplete request.
   * 
   * @throws Exception
   */
  protected void handleCollectionProcessCompleteReply(Message message) throws Exception {
    int payload = ((Integer) message.getIntProperty(AsynchAEMessage.Payload)).intValue();
    try {
      if (AsynchAEMessage.Exception == payload) {
        ProcessTrace pt = new ProcessTrace_impl();
        UimaASProcessStatusImpl status = new UimaASProcessStatusImpl(pt);
        Exception exception = retrieveExceptionFromMessage(message);

        status.addEventStatus("CpC", "Failed", exception);
        notifyListeners(null, status, AsynchAEMessage.CollectionProcessComplete);
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(
                  Level.INFO,
                  CLASS_NAME.getName(),
                  "handleCollectionProcessCompleteReply",
                  JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_received_exception_msg_INFO",
                  new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    getBrokerURI(),  
                    message.getStringProperty(AsynchAEMessage.CasReference), exception });
        }
      } else {
        // After receiving CPC reply there may be cleanup to do. Delegate this
        // to platform specific implementation (ActiveMQ or WAS)
        cleanup();
      }
    } catch (Exception e) {
      throw e;
    } finally {
      // Release the semaphore acquired in collectionProcessingComplete()
      cpcReplySemaphore.release();
    }
  }

  /**
   * Handles response to GetMeta Request. Deserializes ResourceMetaData and initializes CasManager.
   * 
   * @param message
   *          - jms message containing serialized ResourceMetaData
   * 
   * @throws Exception
   */
  protected void handleMetadataReply(Message message) throws Exception {

    serviceDelegate.cancelDelegateGetMetaTimer();
    serviceDelegate.setState(Delegate.OK_STATE);
    // check if the reply msg contains replyTo destination. It will be
    // added by the Cas Multiplier to the getMeta reply
    if (message.getJMSReplyTo() != null) {
      serviceDelegate.setFreeCasDestination(message.getJMSReplyTo());
    }
    // Check if this is a reply for a Ping sent in response to a timeout
    if (serviceDelegate.isAwaitingPingReply()) {
     System.out.println("------------------------ Client Received GetMeta Ping Reply");
    	if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.INFO,
                CLASS_NAME.getName(),
                "handleMetadataReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_rcvd_ping_reply__INFO",
                new Object[] { 
                  message.getStringProperty(AsynchAEMessage.MessageFrom),
                  message.getStringProperty(AsynchAEMessage.ServerIP)});
      }
      //  reset the state of the service. The client received its ping reply  
      serviceDelegate.resetAwaitingPingReply();
      String casReferenceId = null;
      if (serviceDelegate.getCasPendingReplyListSize() > 0 || serviceDelegate.getCasPendingDispatchListSize() > 0) {
    	  serviceDelegate.restartTimerForOldestCasInOutstandingList();
          //	We got a reply to GetMeta ping. Send all CASes that have been
          //    placed on the pending dispatch queue to a service.
    	  while( serviceDelegate.getState()==Delegate.OK_STATE && (casReferenceId = serviceDelegate.removeOldestFromPendingDispatchList()) != null ) {
    	        ClientRequest cachedRequest = (ClientRequest) clientCache.get(casReferenceId);
    	        if (cachedRequest != null) {
    	          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
    	            UIMAFramework.getLogger(CLASS_NAME).logrb(
    	                    Level.INFO,
    	                    CLASS_NAME.getName(),
    	                    "handleMetadataReply",
    	                    JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
    	                    "UIMAJMS_dispatch_delayed_cas__INFO",
    	                    new Object[] { casReferenceId, String.valueOf(cachedRequest.cas.hashCode())});
    	          }
    	          sendCAS(cachedRequest.getCAS(), cachedRequest,null);
    	        }
    	  }
      } else {
        ProcessTrace pt = new ProcessTrace_impl();
        UimaASProcessStatusImpl status = new UimaASProcessStatusImpl(pt);
        notifyListeners(null, status, AsynchAEMessage.GetMeta);
      }
      // Handled Ping reply
      return;
    }
    int payload = ((Integer) message.getIntProperty(AsynchAEMessage.Payload)).intValue();
    removeFromCache(uniqueIdentifier);

    try {
      if (AsynchAEMessage.Exception == payload) {
        ProcessTrace pt = new ProcessTrace_impl();
        UimaASProcessStatusImpl status = new UimaASProcessStatusImpl(pt);
        Exception exception = retrieveExceptionFromMessage(message);
        clientSideJmxStats.incrementMetaErrorCount();
        status.addEventStatus("GetMeta", "Failed", exception);
        notifyListeners(null, status, AsynchAEMessage.GetMeta);
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(
                  Level.INFO,
                  CLASS_NAME.getName(),
                  "handleMetadataReply",
                  JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_received_exception_msg_INFO",
                  new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                      getBrokerURI(),
                      message.getStringProperty(AsynchAEMessage.CasReference), exception });
        }
        abort = true;
        initialized = false;
      } else {
        // Check serialization supported by the service against client configuration.
        // If the client is configured to use Binary serialization *but* the service
        // doesnt support it, change the client serialization to xmi. Old services will
        // not return in a reply the type of serialization supported which implies "xmi".
        // New services *always* return "binary" or "compressedBinaryXXX" 
        // as a default serialization. The client
        // however may still want to serialize messages using xmi though.
        if (!message.propertyExists(AsynchAEMessage.SERIALIZATION)) {
          // Dealing with an old service here, check if there is a mismatch with the
          // client configuration. If the client is configured with binary serialization
          // override this and change serialization to "xmi".
          if (getSerialFormat() != SerialFormat.XMI) {
            // Override configured serialization
            setSerialFormat(SerialFormat.XMI);
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                    "handleMetadataReply", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAJMS_client_serialization_ovveride__WARNING", new Object[] {});
          }
        } else {
          final int c = message.getIntProperty(AsynchAEMessage.SERIALIZATION);
          if (getSerialFormat() != SerialFormat.XMI) {
            // don't override if XMI - because the remote may have different type system
              setSerialFormat((c == AsynchAEMessage.XMI_SERIALIZATION)    ? SerialFormat.XMI :
                              (c == AsynchAEMessage.BINARY_SERIALIZATION) ? SerialFormat.BINARY :
                                                                            SerialFormat.COMPRESSED_FILTERED);
          }
        }
        String meta = ((TextMessage) message).getText();
        ByteArrayInputStream bis = new ByteArrayInputStream(meta.getBytes());
        XMLInputSource in1 = new XMLInputSource(bis, null);
        // Adam - store ResouceMetaData in field so we can return it from getMetaData().
        resourceMetadata = (ProcessingResourceMetaData) UIMAFramework.getXMLParser()
                .parseResourceMetaData(in1);
        // if remote delegate, save type system 
        if (!brokerURI.startsWith("vm:")) { // test if remote
          setRemoteTypeSystem(AggregateAnalysisEngineController_impl.getTypeSystemImpl(resourceMetadata));
        }
        casMultiplierDelegate = resourceMetadata.getOperationalProperties().getOutputsNewCASes();
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(),
                  "handleMetadataReply", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_handling_meta_reply_FINEST",
                  new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom), meta });
        }
        //  check the state of the client 
        if ( running && asynchManager != null ) {
          //  Merge the metadata only if the client is still running
          asynchManager.addMetadata(resourceMetadata);
        }
      }

    } catch (Exception e) {
      throw e;
    } finally {
      getMetaSemaphore.release();
    }
  }
  @SuppressWarnings("unchecked")
      protected void notifyListeners(CAS aCAS, EntityProcessStatus aStatus, int aCommand, List<AnalysisEnginePerformanceMetrics> ml ) { //String serializedComponentStats) {
    if ( aCommand == AsynchAEMessage.Process) {
      ((UimaASProcessStatusImpl)aStatus).
	  setPerformanceMetrics(ml); //UimaSerializer.deserializePerformanceMetrics(serializedComponentStats));
      for (int i = 0; listeners != null && i < listeners.size(); i++) {
        UimaAsBaseCallbackListener statCL = (UimaAsBaseCallbackListener) listeners.get(i);
        statCL.entityProcessComplete(aCAS, aStatus);
      }
    }
  }
  protected void notifyListeners(CAS aCAS, EntityProcessStatus aStatus, int aCommand) {
    for (int i = 0; listeners != null && i < listeners.size(); i++) {
      UimaAsBaseCallbackListener statCL = (UimaAsBaseCallbackListener) listeners.get(i);
      switch (aCommand) {
        case AsynchAEMessage.GetMeta:
          statCL.initializationComplete(aStatus);
          break;

        case AsynchAEMessage.CollectionProcessComplete:
          statCL.collectionProcessComplete(aStatus);
          break;

        case AsynchAEMessage.Process:
        case AsynchAEMessage.Ping:
          statCL.entityProcessComplete(aCAS, aStatus);
          break;

      }

    }
  }

  protected void cancelTimer(String identifier) {
    ClientRequest request = null;
    if (clientCache.containsKey(identifier)) {
      request = (ClientRequest) clientCache.get(identifier);
      if (request != null) {
        request.cancelTimer();
      }
    }
  }

  private boolean isException(Message message) throws Exception {
    int payload;
    if (message.propertyExists(AsynchAEMessage.Payload)) {
      payload = ((Integer) message.getIntProperty(AsynchAEMessage.Payload)).intValue();
    } else {
      throw new InvalidMessageException("Message Does not Contain Payload property");
    }

    return (AsynchAEMessage.Exception == payload ? true : false);
  }

  private Exception retrieveExceptionFromMessage(Message message) throws Exception {
    Exception exception = null;
    try {
      if (message instanceof ObjectMessage
              && ((ObjectMessage) message).getObject() instanceof Exception) {
        exception = (Exception) ((ObjectMessage) message).getObject();
      } else if (message instanceof TextMessage) {
        exception = new UimaEEServiceException(((TextMessage) message).getText());
      }
    } catch( Exception e) {
      UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
              "retrieveExceptionFromMessage", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
              "UIMAEE_exception__WARNING", e);   
      exception = new UimaEEServiceException("UIMA AS client is unable to de-serialize Exception from a remote service",e);
    }
    return exception;
  }

  private void handleProcessReplyFromSynchronousCall(ClientRequest cachedRequest, Message message)
          throws Exception {
    // Save reply message in the cache
    cachedRequest.setMessage(message);
    wakeUpSendThread(cachedRequest);
  }

  protected void wakeUpSendThread(ClientRequest cachedRequest) throws Exception {
    if (threadMonitorMap.containsKey(cachedRequest.getThreadId())) {
      ThreadMonitor threadMonitor = (ThreadMonitor) threadMonitorMap.get(cachedRequest
              .getThreadId());
      // Unblock the sending thread so that it can complete processing
      // of the reply. The message has been stored in the cache and
      // when the thread wakes up due to notification below, it will
      // retrieve the reply and process it.
      if (threadMonitor != null) {
        cachedRequest.setReceivedProcessCasReply();
        threadMonitor.getMonitor().release();
      }
    } 

  }

  /**
   * Handles a ServiceInfo message returned from the Cas Multiplier. The primary purpose of this
   * message is to provide the client with a dedicated queue object where the client may send
   * messages to the specific CM service instance. An example of this would be a stop request that
   * client needs to send to the specific Cas Multiplier.
   * 
   * @param message
   *          - message received from a service
   * @throws Exception
   */
  protected void handleServiceInfo(Message message) throws Exception {
    String casReferenceId = message.getStringProperty(AsynchAEMessage.CasReference);
    ClientRequest casCachedRequest = null;
    if ( casReferenceId != null ) {
    	casCachedRequest = (ClientRequest) clientCache.get(casReferenceId);
    }
    try {
    	if ( casCachedRequest != null ) {
    	  // invoke 2nd callback to the application if necessary. Makes  sure the callback is done once
	  	  notifyApplication(casCachedRequest, 
            	  new ProcessTrace_impl(), 
          		  casReferenceId, 
       		      message.getStringProperty(AsynchAEMessage.InputCasReference),
   		          message.getStringProperty(AsynchAEMessage.ServerIP), 
   		          message.getStringProperty(AsynchAEMessage.UimaASProcessPID));
   	      
	  	  if (message.getJMSReplyTo() != null && serviceDelegate.isCasOutstanding(casReferenceId)) {
   	          casCachedRequest.setFreeCasNotificationQueue(message.getJMSReplyTo());
   	      }
    	} else {
    		ClientRequest requestToCache = (ClientRequest) clientCache.get(uniqueIdentifier);
    		if ( requestToCache != null && requestToCache.isMetaRequest()) {
        	  String nodeIP = message.getStringProperty(AsynchAEMessage.ServerIP);
      	      String pid = message.getStringProperty(AsynchAEMessage.UimaASProcessPID);
      	      if ( pid != null && nodeIP != null ) {
          	      // notify client that the last request (GetMeta ) has been received by a service.
          	     onBeforeProcessMeta(nodeIP, pid);
      	      }
    			
    		}
    		
    	}

    } catch( Exception e) {
      UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
              "handleServiceInfo", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
              "UIMAEE_exception__WARNING", e);
    }
  }
  protected void decrementOutstandingCasCounter() {
    // Received a reply, decrement number of outstanding CASes
    long outstandingCasCount = outstandingCasRequests.decrementAndGet();
    if (outstandingCasCount == 0) {
      cpcReadySemaphore.release();
    }
  }
  private void  notifyApplication(ClientRequest cachedRequest, ProcessTrace pt, String casReferenceId, String parentCasReferenceId, String hostIP, String processPID) {
	    // synchronize handling of the ACK to avoid race condition where the ACK process thread
	    // comes after the reply thread. We want to avoid calling onBeforeProcessCAS() twice.
	  synchronized( cachedRequest) {
		    	if ( !cachedRequest.receivedServiceACK ) {
				       cachedRequest.setReceivedServiceACK(true);
				     
		    	    	cachedRequest.setHostIpProcessingCAS(hostIP);
		    	    	cachedRequest.setServicePID(processPID);
		                UimaASProcessStatusImpl status;
		                
		                if (parentCasReferenceId != null  && parentCasReferenceId.equals(cachedRequest.getCasReferenceId())) {
		                    status = new UimaASProcessStatusImpl(pt, cachedRequest.getCAS(),casReferenceId, parentCasReferenceId);
		                } else {
		                    status = new UimaASProcessStatusImpl(pt, cachedRequest.getCAS(), casReferenceId);
		                }
		                try {
		        	    	// Notify the application with an ACK as if the ACK came from the remote service. Some
		            		// applications may depend on receiving the ACK.
		            		onBeforeProcessCAS(status, cachedRequest.getHostIpProcessingCAS(), cachedRequest.getServicePID());
		                } catch( Exception uex) {  
		                	UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
		                            "notifyApplication", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
		                            "UIMAEE_exception__WARNING", uex);  
		                }				     
		    	}
		    }

  }

  /**
   * Handles response to Process CAS request. If the message originated in a service that is running
   * in a separate jvm (remote), deserialize the CAS and notify the application of the completed
   * analysis via application listener.
   * 
   * @param message
   *          - jms message containing serialized CAS
   * 
   * @throws Exception
   */
  protected void handleProcessReply(Message message, boolean doNotify, ProcessTrace pt)
          throws Exception {
    if (!running) {
      return;
    }
    int payload = -1;
    String casReferenceId = message.getStringProperty(AsynchAEMessage.CasReference);
    // Determine the type of payload in the message (XMI,Cas Reference,Exception,etc)
    if (message.propertyExists(AsynchAEMessage.Payload)) {
      payload = ((Integer) message.getIntProperty(AsynchAEMessage.Payload)).intValue();
    }
    // Fetch entry from the client cache for a cas id returned from the service
    // The client cache maintains an entry for every outstanding CAS sent to the
    // service.
    ClientRequest cachedRequest = null;

    if (casReferenceId != null) {
      cachedRequest = (ClientRequest) clientCache.get(casReferenceId);
      if (cachedRequest != null && casReferenceId.equals(cachedRequest.getCasReferenceId())) {
    	  // invoke 2nd callback to the application if necessary. Makes  sure the callback is done once
          notifyApplication(cachedRequest, 
        		  pt, 
        		  casReferenceId, 
        		  message.getStringProperty(AsynchAEMessage.InputCasReference),
        		  message.getStringProperty(AsynchAEMessage.ServerIP), 
        		  message.getStringProperty(AsynchAEMessage.UimaASProcessPID));

    	  // Received a reply, decrement number of outstanding CASes
        decrementOutstandingCasCounter();
        }
      serviceDelegate.removeCasFromOutstandingList(casReferenceId);
    }
    if (AsynchAEMessage.Exception == payload) {
      handleException(message, cachedRequest, true);
      return;
    }
    // cachedRequest is only null if we are receiving child CASes from a 
    // Cas Multiplier. Otherwise, we drop the message as it is out of band
    if ( cachedRequest == null && !casMultiplierDelegate ) {
    	// most likely a reply came in after the thread was interrupted
    	return;
    }
    
    
    // If the Cas Reference id not in the message check if the message contains an
    // exception and if so, handle the exception and return.
    if (casReferenceId == null) {
      return;
    }

    if (message instanceof TextMessage
            && UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
      UIMAFramework.getLogger(CLASS_NAME).logrb(
              Level.FINEST,
              CLASS_NAME.getName(),
              "handleProcessReply",
              JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
              "UIMAJMS_handling_process_reply_FINEST",
              new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                  message.getStringProperty(AsynchAEMessage.CasReference),
                  message.toString() + ((TextMessage) message).getText() });
    }

    if (cachedRequest != null) {
      // Store the total latency for this CAS. The departure time is set right before the CAS
      // is sent to a service.
      cachedRequest.setTimeWaitingForReply(System.nanoTime() - cachedRequest.getCASDepartureTime());
  	  if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(),
                "handleProcessReply", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_cas_reply_rcvd_FINE", new Object[] { casReferenceId, String.valueOf(cachedRequest.getCAS().hashCode())});
      }

      // If the CAS was sent from a synchronous API sendAndReceive(), wake up the thread that
      // sent the CAS and process the reply
      if (cachedRequest.isSynchronousInvocation()) {
        handleProcessReplyFromSynchronousCall(cachedRequest, message);
      } else {
        deserializeAndCompleteProcessingReply(casReferenceId, message, cachedRequest, pt, doNotify);
      }
    } else if (message.propertyExists(AsynchAEMessage.InputCasReference)) {
    	int command = message.getIntProperty(AsynchAEMessage.Command);
    	if (AsynchAEMessage.ServiceInfo != command) {
    	      handleProcessReplyFromCasMultiplier(message, casReferenceId, payload);
    	}
    } else {
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
        // Most likely expired message. Already handled as timeout. Discard the message and move on
        // to the next
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.INFO,
                CLASS_NAME.getName(),
                "handleProcessReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_received_expired_msg_INFO",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    message.getStringProperty(AsynchAEMessage.CasReference) });
      }
    }
  }

  private void handleProcessReplyFromCasMultiplier(Message message, String casReferenceId,
          int payload /* , ClientRequest inputCasCachedRequest */) throws Exception {
    // Check if the message contains a CAS that was generated by a Cas Multiplier. If so,
    // verify that the message also includes an input CAS id and that such input CAS id
    // exists in the client's cache.
    // Fetch the input CAS Reference Id from which the CAS being processed was generated from
    String inputCasReferenceId = message.getStringProperty(AsynchAEMessage.InputCasReference);
    try {
  	  String nodeIP = message.getStringProperty(AsynchAEMessage.ServerIP);
	      String pid = message.getStringProperty(AsynchAEMessage.UimaASProcessPID);
	       if ( message.getStringProperty(AsynchAEMessage.TargetingSelector) != null) {
	        	  serviceDelegate.setFreeCasSelector(message.getStringProperty(AsynchAEMessage.TargetingSelector));
	        	  System.out.println("+++++++++++++++++ Client Received Service Targeting Selector:"+
	        			  message.getStringProperty(AsynchAEMessage.TargetingSelector));
	          }
//	      System.out.println("%%%%%%%%%%%%% CasMultiplier Sent IP:"+nodeIP+" PID:"+pid);
    	// Free a given CAS in the remote CM
        dispatchFreeCasRequest(casReferenceId, message);

    } catch (Exception e) {
    	e.printStackTrace();
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                    "handleProcessReplyFromCasMultiplier", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAJMS_error_while_sending_msg__WARNING",
                    new Object[] { "Free Cas Temp Destination", e });
          }
        }
     
    /*
     *     Destination freeCASNotificationDestination = message.getJMSReplyTo();

    if (freeCASNotificationDestination != null) {
      TextMessage msg = createTextMessage();
      msg.setText("");
     dsa
      setReleaseCASMessage(msg, casReferenceId);
  	MessageProducer msgProducer = null;
  	try {
        // Create Message Producer for the Destination
        msgProducer = getMessageProducer(freeCASNotificationDestination);
  		
  	} catch( DestinationDoesNotExistException ee) {
  		
  	}

      if (msgProducer != null) {
        try {
          // Send FreeCAS message to a Cas Multiplier
          msgProducer.send(msg);
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(
                    Level.FINEST,
                    CLASS_NAME.getName(),
                    "handleProcessReplyFromCasMultiplier",
                    JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAJMS_client_sending_release_cas_FINEST",
                    new Object[] { freeCASNotificationDestination,
                        message.getStringProperty(AsynchAEMessage.CasReference) });
          }
        } catch (Exception e) {
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                    "handleProcessReplyFromCasMultiplier", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAJMS_error_while_sending_msg__WARNING",
                    new Object[] { "Free Cas Temp Destination", e });
          }
        }
      }
    }
    */
    // Fetch an entry from the client cache for a given input CAS id. This would be an id
    // of the CAS that the client sent out to the service.
    ClientRequest inputCasCachedRequest = (ClientRequest) clientCache.get(inputCasReferenceId);
    if (inputCasCachedRequest == null) {
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
        // Most likely expired message. Already handled as timeout. Discard the message and move on
        // to the next
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.INFO,
                CLASS_NAME.getName(),
                "handleProcessReplyFromCasMultiplier",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_received_expired_msg_INFO",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    message.getStringProperty(AsynchAEMessage.CasReference) });
      }
      return;
    }
    if (inputCasCachedRequest.isSynchronousInvocation()) {
    	// with synchronous invocation, child CASes are thrown away. With sync API, the UIMA-AS client
    	// is not using callbacks. 
    	if ( casReferenceId.equals(inputCasCachedRequest.getCasReferenceId())) {
    	      handleProcessReplyFromSynchronousCall(inputCasCachedRequest, message);
    	} else {
    		return;
    	}
    }
    CAS cas = null;
    if (message instanceof TextMessage) {
      cas = deserializeCAS(((TextMessage) message).getText(), SHADOW_CAS_POOL);
    } else {
      long bodyLength = ((BytesMessage) message).getBodyLength();
      byte[] serializedCas = new byte[(int) bodyLength];
      ((BytesMessage) message).readBytes(serializedCas);
      cas = deserializeCAS(serializedCas, SHADOW_CAS_POOL);

    }
    completeProcessingReply(cas, casReferenceId, payload, true, message, inputCasCachedRequest,
            null);
  }

  private boolean isShutdownException(Exception exception) throws Exception {
    if (exception != null) {
      if (exception instanceof ServiceShutdownException || exception.getCause() != null
              && exception.getCause() instanceof ServiceShutdownException) {
        return true;
      }
    }
    return false;
  }
  protected void handleNonProcessException(Exception exception ) 
  throws Exception {
    ProcessTrace pt = new ProcessTrace_impl();
    UimaASProcessStatusImpl status = new UimaASProcessStatusImpl(pt);
    clientSideJmxStats.incrementMetaErrorCount();
    status.addEventStatus("GetMeta", "Failed", exception);
    notifyListeners(null, status, AsynchAEMessage.GetMeta);
  }
  protected void handleException(Exception exception, String casReferenceId, String inputCasReferenceId, ClientRequest cachedRequest, boolean doNotify)
  throws Exception {
    handleException(exception, casReferenceId, inputCasReferenceId, cachedRequest, doNotify, true);
  }
  protected void handleException(Exception exception, String casReferenceId, String inputCasReferenceId, ClientRequest cachedRequest, boolean doNotify, boolean rethrow)
          throws Exception {
    if (!isShutdownException(exception)) {
      clientSideJmxStats.incrementProcessErrorCount();
    }
    if (exception != null && cachedRequest != null) {
      cachedRequest.setException(exception);
      cachedRequest.setProcessException();
    }
    cpcReadySemaphore.release();
    if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
      UIMAFramework.getLogger(CLASS_NAME).logrb(
              Level.INFO,
              CLASS_NAME.getName(),
              "handleException",
              JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
              "UIMAJMS_received_exception_msg_INFO",
              new Object[] { serviceDelegate.getComponentName(),
                getBrokerURI(),
                casReferenceId, exception });
    }
    try {
      if (doNotify) {
        ProcessTrace pt = new ProcessTrace_impl();

        // HACK! Service should only send exceptions for CASes that we sent.
        // Check if this or its input parent is known.
        if (inputCasReferenceId != null) {
          serviceDelegate.removeCasFromOutstandingList(inputCasReferenceId);
        } else if (casReferenceId != null ) {
          serviceDelegate.removeCasFromOutstandingList(casReferenceId);
        }
        UimaASProcessStatusImpl status;
        
        if (cachedRequest != null ) {
            // Add Cas referenceId(s) to enable matching replies with requests (ids may be null)
            status = new UimaASProcessStatusImpl(pt, cachedRequest.getCAS(), casReferenceId,
                    inputCasReferenceId);
        } else {
            status = new UimaASProcessStatusImpl(pt, null, casReferenceId,
                    inputCasReferenceId);
        }
        status.addEventStatus("Process", "Failed", exception);
        if (cachedRequest != null && !cachedRequest.isSynchronousInvocation()
                && cachedRequest.getCAS() != null) {
          notifyListeners(cachedRequest.getCAS(), status, AsynchAEMessage.Process);
        } else {
        	notifyListeners(null, status, AsynchAEMessage.Process);
        }
        // Done here
        return;
      } else {
        if ( rethrow ) {
          throw new ResourceProcessException(exception);
        }
      }
    } catch (Exception e) {
      throw e;
    } finally {
      if (cachedRequest != null) {
        if (cachedRequest.isSynchronousInvocation() && cachedRequest.isProcessException()) {
          // Wake up the send thread that is blocking waiting for a reply. When the thread
          // receives the signal, it checks if the reply contains an exception and will
          // not return control back to the client
          wakeUpSendThread(cachedRequest);
        }
        // Dont release the CAS if the application uses synchronous API
        if (!cachedRequest.isSynchronousInvocation() && cachedRequest.getCAS() != null) {
          cachedRequest.getCAS().release();
        }
      }
      removeFromCache(casReferenceId);
      serviceDelegate.removeCasFromOutstandingList(casReferenceId);
      decrementOutstandingCasCounter();
    }
  }
  
  protected void handleException(Message message, ClientRequest cachedRequest, boolean doNotify)
          throws Exception {
    
    Exception exception = retrieveExceptionFromMessage(message);
    String casReferenceId = message.getStringProperty(AsynchAEMessage.CasReference);
    String inputCasReferenceId = message.getStringProperty(AsynchAEMessage.InputCasReference);
    handleException(exception, casReferenceId, inputCasReferenceId, cachedRequest, doNotify);
  }

    private void dumpMetrics(List<AnalysisEnginePerformanceMetrics> ml, String casReferenceId ) {
	StringBuffer sb = new StringBuffer();
	sb.append(">>>> Client performance metrics Deserialized by XStream CAS ID:").append(casReferenceId).append("\n\t");
	for(AnalysisEnginePerformanceMetrics met: ml ) {
	    sb.append("AE:").append(met.getUniqueName()).append(" AnalysisTime:").append(met.getAnalysisTime()).append("\n\t");
	}
	System.out.println(sb.toString());
	  
    }
    private List<AnalysisEnginePerformanceMetrics> getMetrics(String metrics, String casReferenceId, boolean dump) {
	if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
	    UIMAFramework.getLogger(CLASS_NAME).logrb(
						      Level.FINEST,
						      CLASS_NAME.getName(),
						      "getMetrics",
						      JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
						      "UIMAJMS_dump_metrics__FINEST",
						      new Object[] { casReferenceId, metrics });
	}
	//System.out.println("Client performance metrics (before XStream)\n"+metrics);
    List<AnalysisEnginePerformanceMetrics> ml = 
	UimaSerializer.deserializePerformanceMetrics(metrics);
    if ( dump ) {
	dumpMetrics(ml, casReferenceId);
    }
    return ml;
    }
  private void completeProcessingReply(CAS cas, String casReferenceId, int payload,
          boolean doNotify, Message message, ClientRequest cachedRequest, ProcessTrace pt)
          throws Exception {
    if (AsynchAEMessage.XMIPayload == payload || AsynchAEMessage.BinaryPayload == payload
            || AsynchAEMessage.CASRefID == payload) {
      if (pt == null) {
        pt = new ProcessTrace_impl();
      }
      try {
        // Log stats and populate ProcessTrace object
        logTimingInfo(message, pt, cachedRequest);
        if (doNotify) {
          UimaASProcessStatusImpl status;
          String inputCasReferenceId = message.getStringProperty(AsynchAEMessage.InputCasReference);
          if (inputCasReferenceId != null
                  && inputCasReferenceId.equals(cachedRequest.getCasReferenceId())) {
            status = new UimaASProcessStatusImpl(pt, cas,casReferenceId, inputCasReferenceId);
          } else {
            status = new UimaASProcessStatusImpl(pt, cas, casReferenceId);
          }
          if ( cachedRequest.getTargetServiceId() != null ) {
        	  status.setServiceTargetID(cachedRequest.getTargetServiceId());
          }
          
          if ( message.propertyExists(AsynchAEMessage.CASPerComponentMetrics)) {
 
	      List<AnalysisEnginePerformanceMetrics> ml = 
		  getMetrics(message.getStringProperty(AsynchAEMessage.CASPerComponentMetrics), casReferenceId, UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST));


           // Add CAS identifier to enable matching replies with requests
	      notifyListeners(cas, status, AsynchAEMessage.Process, ml); //message.getStringProperty(AsynchAEMessage.CASPerComponentMetrics));
          } else {
            // Add CAS identifier to enable matching replies with requests
            notifyListeners(cas, status, AsynchAEMessage.Process);
          }
        } else {  // synchronous sendAndReceive() was used
            if (casReferenceId != null && message.propertyExists(AsynchAEMessage.CASPerComponentMetrics) ) {

                cachedRequest = (ClientRequest) clientCache.get(casReferenceId);
                if ( cachedRequest != null && cachedRequest.getComponentMetricsList() != null ) {

		    List<AnalysisEnginePerformanceMetrics> ml = 
			getMetrics(message.getStringProperty(AsynchAEMessage.CASPerComponentMetrics), casReferenceId, false);
		    cachedRequest.getComponentMetricsList().clear();
		    cachedRequest.getComponentMetricsList().addAll(ml);
		    if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
			   dumpMetrics(cachedRequest.getComponentMetricsList(), casReferenceId);
		    }


		    //                	cachedRequest.getComponentMetricsList().
		    //		addAll(UimaSerializer.deserializePerformanceMetrics(message.getStringProperty(AsynchAEMessage.CASPerComponentMetrics)));
                }
            }
        }
      } finally {
        // Dont release the CAS if the application uses synchronous API
        if (remoteService && !cachedRequest.isSynchronousInvocation()) {
          if (cas != null) {
            cas.release();
          }
        }
        
        removeFromCache(casReferenceId);
      }
    }
  }

  private void logTimingInfo(Message message, ProcessTrace pt, ClientRequest cachedRequest)
          throws Exception {
    clientSideJmxStats.incrementTotalNumberOfCasesProcessed();

    if (message.getStringProperty(AsynchAEMessage.CasReference) != null) {
      String casReferenceId = message.getStringProperty(AsynchAEMessage.CasReference);
      if (clientCache.containsKey(casReferenceId)) {
        ClientRequest cacheEntry = (ClientRequest) clientCache.get(casReferenceId);
        if (cacheEntry == null) {
          return;
        }
        // Add time waiting for reply to the client JMX stats
        long timeWaitingForReply = cacheEntry.getTimeWaitingForReply();
        clientSideJmxStats.incrementTotalTimeWaitingForReply(timeWaitingForReply);
        // Add CAS response latency time to the client JMX stats
        long responseLatencyTime = cacheEntry.getSerializationTime() + timeWaitingForReply
                + cacheEntry.getDeserializationTime();
        clientSideJmxStats.incrementTotalResponseLatencyTime(responseLatencyTime);
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
          UIMAFramework.getLogger(CLASS_NAME)
                  .logrb(
                          Level.FINEST,
                          CLASS_NAME.getName(),
                          "handleProcessReply",
                          JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                          "UIMAJMS_timer_detail_FINEST",
                          new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                              "Total Time Waiting For Reply",
                              (float) timeWaitingForReply / (float) 1000000 });
        }
        pt.addEvent("UimaEE", "process", "Total Time Waiting For Reply",
                (int) (timeWaitingForReply / 1000000), "");
      }
    }
    if (message.propertyExists(AsynchAEMessage.TimeToSerializeCAS)) {
      long timeToSerializeCAS = message.getLongProperty(AsynchAEMessage.TimeToSerializeCAS);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.FINEST,
                CLASS_NAME.getName(),
                "handleProcessReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_timer_detail_FINEST",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    "Time To Serialize Cas", (float) timeToSerializeCAS / (float) 1000000 });
      }
      pt.addEvent("UimaEE", "process", "Time To Serialize Cas",
              (int) (timeToSerializeCAS / 1000000), "");
      // Add the client serialization overhead to the value returned from a service
      timeToSerializeCAS += cachedRequest.getSerializationTime();
      clientSideJmxStats.incrementTotalSerializationTime(timeToSerializeCAS);
    }
    if (message.propertyExists(AsynchAEMessage.TimeToDeserializeCAS)) {
      long timeToDeserializeCAS = message.getLongProperty(AsynchAEMessage.TimeToDeserializeCAS);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.FINEST,
                CLASS_NAME.getName(),
                "handleProcessReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_timer_detail_FINEST",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    "Time To Deserialize Cas", (float) timeToDeserializeCAS / (float) 1000000 });
      }
      pt.addEvent("UimaEE", "process", "Time To Deserialize Cas",
              (int) (timeToDeserializeCAS / 1000000), "");
      // Add the client deserialization overhead to the value returned from a service
      timeToDeserializeCAS += cachedRequest.getDeserializationTime();
      clientSideJmxStats.incrementTotalDeserializationTime(timeToDeserializeCAS);
    }
    if (message.propertyExists(AsynchAEMessage.TimeWaitingForCAS)) {
      long timeWaitingForCAS = message.getLongProperty(AsynchAEMessage.TimeWaitingForCAS);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.FINEST,
                CLASS_NAME.getName(),
                "handleProcessReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_timer_detail_FINEST",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    "Time to Wait for CAS", (float) timeWaitingForCAS / (float) 1000000 });
      }
      pt.addEvent("UimaEE", "process", "Time to Wait for CAS", (int) (timeWaitingForCAS / 1000000),
              "");
    }
    if (message.propertyExists(AsynchAEMessage.TimeInService)) {
      long ttimeInService = message.getLongProperty(AsynchAEMessage.TimeInService);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.FINEST,
                CLASS_NAME.getName(),
                "handleProcessReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_timer_detail_FINEST",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    "Time In Service", (float) ttimeInService / (float) 1000000 });
      }
      pt.addEvent("UimaEE", "process", "Time In Service", (int) (ttimeInService / 1000000), "");

    }
    if (message.propertyExists(AsynchAEMessage.TotalTimeSpentInAnalytic)) {
      long totaltimeInService = message.getLongProperty(AsynchAEMessage.TotalTimeSpentInAnalytic);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.FINEST,
                CLASS_NAME.getName(),
                "handleProcessReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_timer_detail_FINEST",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    "Total Time In Service", (float) totaltimeInService / (float) 1000000 });
      }
      pt.addEvent("UimaEE", "process", "Total Time In Service",
              (int) (totaltimeInService / 1000000), "");
    }
    if (message.propertyExists(AsynchAEMessage.TimeInProcessCAS)) {
      long totaltimeInProcessCAS = message.getLongProperty(AsynchAEMessage.TimeInProcessCAS);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.FINEST,
                CLASS_NAME.getName(),
                "handleProcessReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_timer_detail_FINEST",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    "Total Time In Process CAS", (float) totaltimeInProcessCAS / (float) 1000000 });
      }
      float timeInMillis = (float) totaltimeInProcessCAS / (float) 1000000;
      pt.addEvent("UimaEE", "process", "Total Time In Process CAS", (int) timeInMillis, "");
      clientSideJmxStats.incrementTotalTimeToProcess(totaltimeInProcessCAS);
    }
    if (message.propertyExists(AsynchAEMessage.IdleTime)) {
      long totalIdletime = message.getLongProperty(AsynchAEMessage.IdleTime);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(
                Level.FINEST,
                CLASS_NAME.getName(),
                "handleProcessReply",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_timer_detail_FINEST",
                new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom),
                    "Idle Time Waiting For CAS", (float) totalIdletime / (float) 1000000 });
      }
      pt.addEvent("UimaEE", "process", "Idle Time Waiting For CAS",
              (int) (totalIdletime / 1000000), "");
      clientSideJmxStats.incrementTotalIdleTime(totalIdletime);
    }
    if (message.propertyExists(AsynchAEMessage.ServerIP)) {
      pt.addEvent("UimaEE", "process", "Service IP", 0, message
              .getStringProperty(AsynchAEMessage.ServerIP));
    }

  }

  protected void removeFromCache(String aCasReferenceId) {
	  if ( aCasReferenceId == null ) {
		  return;
	  }
      clientCache.remove(aCasReferenceId);
  }

  protected CAS deserialize(String aSerializedCAS, CAS aCAS) throws Exception {
    XmiSerializationSharedData deserSharedData = new XmiSerializationSharedData();
    uimaSerializer.deserializeCasFromXmi(aSerializedCAS, aCAS, deserSharedData, true, -1);
    return aCAS;
  }

  protected CAS deserialize(String aSerializedCAS, CAS aCAS,
          XmiSerializationSharedData deserSharedData, boolean deltaCas) throws Exception {
    if (deltaCas) {
      uimaSerializer.deserializeCasFromXmi(aSerializedCAS, aCAS, deserSharedData, true,
              deserSharedData.getMaxXmiId(), AllowPreexistingFS.allow);
    } else {
      uimaSerializer.deserializeCasFromXmi(aSerializedCAS, aCAS, deserSharedData, true, -1);
    }
    return aCAS;
  }

  protected CAS deserialize(byte[] binaryData, ClientRequest cachedRequest) throws Exception {
    CAS cas = cachedRequest.getCAS();
    uimaSerializer.deserializeCasFromBinary(binaryData, cas);
    return cas;
  }

  protected CAS deserializeCAS(String aSerializedCAS, ClientRequest cachedRequest) throws Exception {
    CAS cas = cachedRequest.getCAS();
    return deserialize(aSerializedCAS, cas);
  }

  /**
   * handle both ordinary binary and compressed6 binary
   * @param aSerializedCAS
   * @param cachedRequest
   * @return
   * @throws Exception
   */
  protected CAS deserializeCAS(byte[] aSerializedCAS, ClientRequest cachedRequest) throws Exception {
    CAS cas = cachedRequest.getCAS();
    ReuseInfo reuseInfo = cachedRequest.getCompress6ReuseInfo();
    ByteArrayInputStream bais = new ByteArrayInputStream(aSerializedCAS);
    if (reuseInfo != null) {
      Serialization.deserializeCAS(cas, bais, null, reuseInfo);
    } else {
      ((CASImpl)cas).reinit(bais);
    }
//    uimaSerializer.deserializeCasFromBinary(aSerializedCAS, cas);
    return cas;
  }

  // never called 5/2013 ??
  protected CAS deserializeCAS(byte[] aSerializedCAS, CAS aCas) throws Exception {
    uimaSerializer.deserializeCasFromBinary(aSerializedCAS, aCas);
    return aCas;
  }

  protected CAS deserializeCAS(String aSerializedCAS, ClientRequest cachedRequest, boolean deltaCas)
          throws Exception {
    CAS cas = cachedRequest.getCAS();
    return deserialize(aSerializedCAS, cas, cachedRequest.getXmiSerializationSharedData(), deltaCas);
  }

  protected CAS deserializeCAS(String aSerializedCAS, String aCasPoolName) throws Exception {
    CAS cas = asynchManager.getNewCas(aCasPoolName);
    return deserialize(aSerializedCAS, cas);
  }

  protected CAS deserializeCAS(byte[] aSerializedCAS, String aCasPoolName) throws Exception {
    CAS cas = asynchManager.getNewCas(aCasPoolName);
    uimaSerializer.deserializeCasFromBinary(aSerializedCAS, cas);
    return cas;
  }

  /**
   * Listener method receiving JMS Messages from the response queue.
   * 
   */
  public void onMessage(final Message message) {
	  if ( !this.running) {
		  return;    // ignore the message if the client is stopping
	  }
    // Process message in a separate thread. Previously the message was processed in ActiveMQ dispatch thread.
    // This onMessage() method is called by ActiveMQ code from a critical region protected with a lock. The lock 
    // is only released if this method returns. Running in a dispatch thread caused a hang when an application
    // decided to call System.exit() in any of its callback listener methods. The UIMA AS client adds a 
    // ShutdownHoook to the JVM to enable orderly shutdown which includes stopping JMS Consumer, JMS Producer
    // and finally stopping JMS Connection. The ShutdownHook support was added to the client in case the 
    // application doesnt call client's stop() method. Now, the hang was caused by the fact that the dispatch
    // thread was used to call System.exit() which in turn executed client's ShutdownHook code. The ShutdownHook
    // code runs in a separate thread, but the the JVM blocks the dispatch thread until the ShutdownHook 
    // finishes. It never will though, since the ShutdownHook is calling ActiveMQSession.close() which tries to enter
    // the same critical region that the dispatch thread is still stuck into. DEADLOCK.
    // The code below uses a simple FixedThreadPool Executor with a single thread. This thread is reused instead
    // creating one on the fly.
    exec.execute( new Runnable() {
      
      public void run() {
        try {

          
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(), "onMessage",
                    JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_received_msg_FINEST",
                    new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom) });
          }
          if (!message.propertyExists(AsynchAEMessage.Command)) {
            return;
          }

          int command = message.getIntProperty(AsynchAEMessage.Command);
          if (AsynchAEMessage.CollectionProcessComplete == command) {
            if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(), "onMessage",
                      JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_received_cpc_reply_FINE",
                      new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom) });
            }
            handleCollectionProcessCompleteReply(message);
          } else if (AsynchAEMessage.GetMeta == command) {
            if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(), "onMessage",
                      JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_received_meta_reply_FINE",
                      new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom) });
            }
            handleMetadataReply(message);
          } else if (AsynchAEMessage.Process == command) {
            if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(), "onMessage",
                      JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_received_process_reply_FINE",
                      new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom) });
            }
            handleProcessReply(message, true, null);
          } else if (AsynchAEMessage.ServiceInfo == command) {
            if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(),
                      "onMessage", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                      "UIMAJMS_received_service_info_FINEST",
                      new Object[] { message.getStringProperty(AsynchAEMessage.MessageFrom) });
            }
            handleServiceInfo(message);
          }
        } catch (Exception e) {
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                    "onMessage", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAEE_exception__WARNING", e);
          }

        }
        
      }
    });

  }

  /**
   * Gets the ProcessingResourceMetadata for the asynchronous AnalysisEngine.
   */
  public ProcessingResourceMetaData getMetaData() throws ResourceInitializationException {
    return resourceMetadata;
  }
  public String sendAndReceiveCAS(CAS aCAS) throws ResourceProcessException {
    return sendAndReceiveCAS(aCAS, null, null);
  }
  /**
   * This method is not part of a public interface and should not be used by an application
   * directly. It is used by a test code internally. 
   * 
   * @param aCAS - CAS to process
   * @param pt - ProcessTrace to aggregate stats
   * @return - Spring container ID
   * @throws ResourceProcessException on error
   */
  public String sendAndReceiveCAS(CAS aCAS, ProcessTrace pt) throws ResourceProcessException {
    return sendAndReceiveCAS(aCAS, pt, null, null);
  }
  public String sendAndReceiveCAS(CAS aCAS, List<AnalysisEnginePerformanceMetrics> componentMetricsList) throws ResourceProcessException {
    return sendAndReceiveCAS(aCAS, null, componentMetricsList, null);
  }
  public String sendAndReceiveCAS(CAS aCAS, List<AnalysisEnginePerformanceMetrics> componentMetricsList, String targetServiceId) throws ResourceProcessException {
	    return sendAndReceiveCAS(aCAS, null, componentMetricsList, targetServiceId);
	  }
  /**
   * This is a synchronous method which sends a message to a destination and blocks waiting for a
   * reply.
   */
  public String sendAndReceiveCAS(CAS aCAS, ProcessTrace pt, List<AnalysisEnginePerformanceMetrics> componentMetricsList, String targetServiceId) throws ResourceProcessException {
    if (!running) {
      throw new ResourceProcessException(new Exception("Uima EE Client Not In Running State"));
    }
    if (!serviceDelegate.isSynchronousAPI()) {
      // Change the flag to indicate synchronous invocation.
      // This info will be needed to handle Ping replies.
      // Different code is used for handling PING replies for
      // sync and async API.
      serviceDelegate.setSynchronousAPI();
    }
    String casReferenceId = null;
    // keep handle to CAS, we'll deserialize into this same CAS later
    sendAndReceiveCAS = aCAS;

    ThreadMonitor threadMonitor = null;

    if (threadMonitorMap.containsKey(Thread.currentThread().getId())) {
      threadMonitor = (ThreadMonitor) threadMonitorMap.get(Thread.currentThread().getId());
    } else {
      threadMonitor = new ThreadMonitor(Thread.currentThread().getId());
      threadMonitorMap.put(Thread.currentThread().getId(), threadMonitor);
    }

    ClientRequest cachedRequest = produceNewClientRequestObject();
    cachedRequest.setSynchronousInvocation();
//    cachedRequest.setTargetServiceId(targetServiceId);
    //	save application provided List where the performance stats will be copied
    //  when reply comes back
    cachedRequest.setComponentMetricsList(componentMetricsList);
    
    // This is synchronous call, acquire and hold the semaphore before
    // dispatching a CAS to a service. The semaphore will be released
    // iff:
    // a) reply is received (success or failure with exception)
    // b) timeout occurs
    // c) client is stopped
    // Once the semaphore is acquired and the CAS is dispatched
    // the thread will block in trying to acquire the semaphore again
    // below.
    if (threadMonitor != null && threadMonitor.getMonitor() != null) {
      try {
        threadMonitor.getMonitor().acquire();
      } catch (InterruptedException e) {
      	if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
                    "sendAndReceiveCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAJMS_client_interrupted_INFO", new Object[] { casReferenceId, String.valueOf(aCAS.hashCode())});
        }
    	// cancel the timer if it is associated with a CAS this thread is waiting for. This would be
    	// the oldest CAS submitted to a queue for processing. The timer will be canceled and restarted
    	// for the second oldest CAS in the outstanding list.
    	serviceDelegate.cancelTimerForCasOrPurge(casReferenceId);
    	throw new ResourceProcessException(e);
      } 
    }
    try {
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
                "sendAndReceiveCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_cas_submitting_FINE", new Object[] { casReferenceId, String.valueOf(aCAS.hashCode()), Thread.currentThread().getId()});
      }
      // send CAS. This call does not block. Instead we will block the sending thread below.
      casReferenceId = sendCAS(aCAS, cachedRequest, targetServiceId);

    } catch( ResourceProcessException e) {
      
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                "sendAndReceiveCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                "UIMAJMS_exception__WARNING", new Object[] { e });
      }
      threadMonitor.getMonitor().release();
      removeFromCache(casReferenceId);
      throw e;
    }
    if (threadMonitor != null && threadMonitor.getMonitor() != null) {
      while (running) {
        try {
          // Block sending thread until a reply is received. The thread
          // will be signaled either when a reply to the request just
          // sent is received OR a Ping reply was received. The latter
          // is necessary to allow handling of CASes delayed due to
          // a timeout. A previous request timed out and the service
          // state was changed to TIMEDOUT. While the service is in this
          // state all sending threads add outstanding CASes to the list
          // of CASes pending dispatch and each waits until the state
          // of the service changes to OK. The state is changed to OK
          // when the client receives a reply to a PING request. When
          // the Ping reply comes, the client will signal this thread.
          // The thread checks the list of CASes pending dispatch trying
          // to find an entry that matches ID of the CAS previously
          // delayed. If the CAS is found in the delayed list, it will
          // be removed from the list and send to the service for
          // processing. The 'wasSignaled' flag is only set when the
          // CAS reply is received. Ping reply logic does not change
          // this flag.
          threadMonitor.getMonitor().acquire();
          // if the semaphore was cleared in the stop() method, the client
          // must be in a shutdown mode. Throw an exception back to the
          // caller. The CAS reply has not come back yet.
          if ( threadMonitor.wasCalledFromStopMethod()) {
        	  throw new ResourceProcessException(new UimaAsClientStoppingException("Client is stopping - sendAndReceive() has been interrupted"));
          }
          // Send thread was awoken by either process reply or ping reply
          // If the service is in the ok state and the CAS is in the
          // list of CASes pending dispatch, remove the CAS from the list
          // and send it to the service.
          if (cachedRequest.isTimeoutException() || cachedRequest.isProcessException()) {
            if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
                      "sendAndReceiveCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                      "UIMAJMS_process_exception_handler5__WARNING", new Object[] { String.valueOf(aCAS.hashCode()), Thread.currentThread().getId()});
            }
            // Handled outside of the while-loop below
            break;
          }
          if (running && serviceDelegate.getState() == Delegate.OK_STATE
                  && serviceDelegate.removeCasFromPendingDispatchList(casReferenceId)) {
            sendCAS(aCAS, cachedRequest, targetServiceId);
          } else {
            break; // done here, received a reply or the client is not running
          }
        } catch (InterruptedException e) {
        	if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
                UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
                        "sendAndReceiveCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                        "UIMAJMS_client_interrupted_INFO", new Object[] { Thread.currentThread().getId(), casReferenceId, String.valueOf(aCAS.hashCode())});
          }
        	// try to remove from pending dispatch list. If not there, remove from pending reply list
        	if ( !serviceDelegate.removeCasFromPendingDispatchList(casReferenceId)) {
            serviceDelegate.removeCasFromOutstandingList(casReferenceId);
        	}
        	// cancel the timer if it is associated with a CAS this thread is waiting for. This would be
        	// the oldest CAS submitted to a queue for processing. The timer will be canceled and restarted
        	// for the second oldest CAS in the outstanding list.
        	serviceDelegate.cancelTimerForCasOrPurge(casReferenceId);
        	if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
                UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
                        "sendAndReceiveCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                        "UIMAJMS_client_canceled_timer_INFO", new Object[] { Thread.currentThread().getId(), casReferenceId, String.valueOf(aCAS.hashCode())});
            }
            removeFromCache(casReferenceId);
        	throw new ResourceProcessException(e);
        } finally {
          threadMonitor.getMonitor().release();
        }
      }
    } // if

    if (abort) {
      throw new ResourceProcessException(new RuntimeException("Uima AS Client API Stopping"));
    }
    // check if timeout exception
    if (cachedRequest.isTimeoutException()) {
      String qName="";
      try {
        qName = getEndPointName();
      } catch( Exception e) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                  "sendAndReceiveCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_exception__WARNING", e);
      }
     // Request To Process Cas Has Timed-out.  
      throw new ResourceProcessException(JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "" +
      		"UIMAJMS_process_timeout_WARNING", 
      		new Object[]{qName, getBrokerURI(), cachedRequest.getHostIpProcessingCAS()},
      		new UimaASProcessCasTimeout("UIMA AS Client Timed Out Waiting for Reply From Service:"+qName+" Broker:"+getBrokerURI()));
    }
    // If a reply contains process exception, throw an exception and let the
    // listener decide what happens next
    if (cachedRequest.isProcessException()) {
      String qName="";
      try {
        qName = getEndPointName();
      } catch( Exception e) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                  "sendAndReceiveCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_exception__WARNING", e);
      }
      throw new ResourceProcessException(
              JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "" +
              "UIMAJMS_received_exception_msg_INFO",
              new Object[]{qName, getBrokerURI(), casReferenceId},
              cachedRequest.getException());
    }
    try {
      // Process reply in the send thread
      Message message = cachedRequest.getMessage();
      if (message != null) {
        deserializeAndCompleteProcessingReply(casReferenceId, message, cachedRequest, pt, false);
      }
    } catch (ResourceProcessException rpe) {
      throw rpe;
    } catch (Exception e) {
      throw new ResourceProcessException(e);
    }
    return casReferenceId;
  }

  private void deserializeAndCompleteProcessingReply(String casReferenceId, Message message,
          ClientRequest cachedRequest, ProcessTrace pt, boolean doNotify) throws Exception {
    if (!running) {
      return;
    }
    int payload = ((Integer) message.getIntProperty(AsynchAEMessage.Payload)).intValue();
    if (message.propertyExists(AsynchAEMessage.CasSequence)) {
      handleProcessReplyFromCasMultiplier(message, casReferenceId, payload);// , cachedRequest);
    } else {
      long t1 = System.nanoTime();
      boolean deltaCas = false;
      if (message.propertyExists(AsynchAEMessage.SentDeltaCas)) {
        deltaCas = message.getBooleanProperty(AsynchAEMessage.SentDeltaCas);
      }
      CAS cas = null;
      if (message instanceof TextMessage) {
        cas = deserializeCAS(((TextMessage) message).getText(), cachedRequest, deltaCas);
      } else {
        long bodyLength = ((BytesMessage) message).getBodyLength();
        byte[] serializedCas = new byte[(int) bodyLength];
        ((BytesMessage) message).readBytes(serializedCas);
        cas = deserializeCAS(serializedCas, cachedRequest);
      }
      cachedRequest.setDeserializationTime(System.nanoTime() - t1);
      completeProcessingReply(cas, casReferenceId, payload, doNotify, message, cachedRequest, pt);
    }
  }

  protected void notifyOnTimout(CAS aCAS, String anEndpoint, int aTimeoutKind, String casReferenceId) {

    ProcessTrace pt = new ProcessTrace_impl();
    UimaASProcessStatusImpl status = new UimaASProcessStatusImpl(pt, aCAS, casReferenceId);

    switch (aTimeoutKind) {
      case (MetadataTimeout):
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                  "notifyOnTimout", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_meta_timeout_WARNING", new Object[] { anEndpoint });
        }
        status.addEventStatus("GetMeta", "Failed", new UimaASMetaRequestTimeout("UIMA AS Client Timed Out Waiting For GetMeta Reply From a Service On Queue:"+anEndpoint));
        notifyListeners(null, status, AsynchAEMessage.GetMeta);
        abort = true;
        getMetaSemaphore.release();
        break;
      case (PingTimeout):
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
                  "notifyOnTimout", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_meta_timeout_WARNING", new Object[] { anEndpoint });
        }
        status.addEventStatus("Ping", "Failed", new UimaASPingTimeout("UIMA AS Client Timed Out Waiting For Ping Reply From a Service On Queue:"+anEndpoint));
        notifyListeners(null, status, AsynchAEMessage.Ping);
        // The main thread could be stuck waiting for a CAS. Grab any CAS in the
        // client cache and release it so that we can shutdown.
        if (!clientCache.isEmpty()) {
          ClientRequest anyCasRequest = clientCache.elements().nextElement();
          if (anyCasRequest.getCAS() != null) {
            anyCasRequest.getCAS().release();
          }
        }
        abort = true;
        break;
      case (CpCTimeout):
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
                  "notifyOnTimout", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                  "UIMAJMS_cpc_timeout_INFO", new Object[] { anEndpoint });
        }
        status.addEventStatus("CpC", "Failed", 
                new UimaASCollectionProcessCompleteTimeout("UIMA AS Client Timed Out Waiting For CPC Reply From a Service On Queue:"+anEndpoint));
        // release the semaphore acquired in collectionProcessingComplete()
        cpcReplySemaphore.release();
        notifyListeners(null, status, AsynchAEMessage.CollectionProcessComplete);
        break;

      case (ProcessTimeout):
    	  if ( casReferenceId != null ) {
    	        ClientRequest cachedRequest = (ClientRequest) clientCache.get(casReferenceId);
    	        if (cachedRequest != null) {
    	          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
    	            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(),
    	                  "notifyOnTimout", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
    	                  "UIMAJMS_process_timeout_WARNING", new Object[] { anEndpoint, getBrokerURI(), cachedRequest.getHostIpProcessingCAS() });
    	          }
    	        } else {
    	          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
    	            // if missing for any reason ...
    	            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
    	                    "notifyOnTimout", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
    	                    "UIMAJMS_received_expired_msg_INFO",
    	                    new Object[] { anEndpoint, casReferenceId });
    	          }
    	          return;
    	        }
    	        // Store the total latency for this CAS. The departure time is set right before the CAS
    	        // is sent to a service.
    	        cachedRequest.setTimeWaitingForReply(System.nanoTime()
    	                - cachedRequest.getCASDepartureTime());

    	        // mark timeout exception
    	        cachedRequest.setTimeoutException();

    	        if (cachedRequest.isSynchronousInvocation()) {
    	          // Signal a thread that we received a reply, if in the map
    	          if (threadMonitorMap.containsKey(cachedRequest.getThreadId())) {
    	            ThreadMonitor threadMonitor = (ThreadMonitor) threadMonitorMap.get(cachedRequest
    	                    .getThreadId());
    	            // Unblock the sending thread so that it can complete processing with an error
    	            if (threadMonitor != null) {
    	              threadMonitor.getMonitor().release();
    	              cachedRequest.setReceivedProcessCasReply(); // should not be needed
    	            }
    	          } 
    	        } else {
    	          // notify the application listener with the error
    	          if ( serviceDelegate.isPingTimeout()) {
    	            exc = new UimaASProcessCasTimeout(new UimaASPingTimeout("UIMA AS Client Ping Time While Waiting For Reply From a Service On Queue:"+anEndpoint));
    	            serviceDelegate.resetPingTimeout();
    	          } else {
    	            exc = new UimaASProcessCasTimeout("UIMA AS Client Timed Out Waiting For CAS:"+casReferenceId+ " Reply From a Service On Queue:"+anEndpoint);
    	          }
    	          status.addEventStatus("Process", "Failed", exc);
    	          notifyListeners(aCAS, status, AsynchAEMessage.Process);
    	        }
    	        boolean isSynchronousCall = cachedRequest.isSynchronousInvocation();
    	        
    	        cachedRequest.removeEntry(casReferenceId);
    	        serviceDelegate.removeCasFromOutstandingList(casReferenceId);
    	        // Check if all replies have been received
    	        long outstandingCasCount = outstandingCasRequests.decrementAndGet();

    	        if (outstandingCasCount <= 0) {
    	          cpcReadySemaphore.release();
    	        }
    	        //	
    	        System.out.println("isSynchronousCall="+isSynchronousCall+" serviceDelegate.getCasPendingReplyListSize()="+serviceDelegate.getCasPendingReplyListSize());
    	        if ( !isSynchronousCall && serviceDelegate.getCasPendingReplyListSize() > 0) {
    	            String nextOutstandingCasReferenceId = 
    	            		serviceDelegate.getOldestCasIdFromOutstandingList();
    	        	if ( nextOutstandingCasReferenceId != null ) {
    	        		cachedRequest = (ClientRequest) clientCache.get(nextOutstandingCasReferenceId);
    	        		if ( cachedRequest != null && cachedRequest.getCAS() != null ) {
        	        		try {
        	        			System.out.println("Sending CAS Again");
        	            		sendCAS(cachedRequest.getCAS());
        	        		} catch( Exception e) {
        	        			UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
        	                            "notifyOnTimout", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
        	                            "UIMAEE_exception__WARNING", e);
        	        		}
    	        		}
    	        	}
    	        }
    	  }
        break;
    } // case
  }

  /**
   * @override
   */
  protected MessageProducer getMessageProducer(Destination destination) throws Exception {
    return null;
  }

  /**
   * has some cache values for CAS, similar to class CacheEntry 
   *
   */
  public class ClientRequest {
    private Timer timer = null;

    private long processTimeout = 0L;

    private long metadataTimeout = 0L;

    private long cpcTimeout = 0L;

    private String casReferenceId = null;

    private BaseUIMAAsynchronousEngineCommon_impl uimaEEEngine = null;

    private volatile boolean isSerializedCAS;

    private String serializedCAS;

    private CAS cas;

    private volatile boolean isMetaRequest = false;

    private volatile boolean isCPCRequest = false;

    private volatile boolean isRemote = true;

    private String endpoint;

    private long threadId = Thread.currentThread().getId();
    private Message message;

    private volatile boolean synchronousInvocation;

    private volatile boolean timeoutException;

    private long casDepartureTime;

    private long timeWaitingForReply;

    private long serializationTime;

    private long deserializationTime;

    private long metaTimeoutErrorCount;

    private long processTimeoutErrorCount;

    private long processErrorCount;

    private XmiSerializationSharedData sharedData;
    
    private ReuseInfo compress6ReuseInfo;

    private byte[] binaryCas = null;

    private volatile boolean isBinaryCas = false;

    private Exception exception;

    private volatile boolean processException;

    private Destination freeCasNotificationQueue = null;

    private String hostIpProcessingCAS;

	private String servicePID;
    
    List<AnalysisEnginePerformanceMetrics> componentMetricsList;
    
    // flag to indicate if the remote service acknowledged receiving a CAS for processing
    private volatile boolean receivedServiceACK=false;
    
    private String targetServiceId;
    
    public String getTargetServiceId() {
		return targetServiceId;
	}

	public void setTargetServiceId(String serviceTargetId) {
		this.targetServiceId = serviceTargetId;
	}

	public boolean receivedServiceACK() {
		return receivedServiceACK;
	}

	public void setReceivedServiceACK(boolean receivedServiceACK) {
		this.receivedServiceACK = receivedServiceACK;
	}

	public String getServicePID() {
		return servicePID;
	}

	public void setServicePID(String servicePID) {
		this.servicePID = servicePID;
	}
	
    public List<AnalysisEnginePerformanceMetrics> getComponentMetricsList() {
		return componentMetricsList;
	}

	public void setComponentMetricsList(
			List<AnalysisEnginePerformanceMetrics> componentMetricsList) {
		this.componentMetricsList = componentMetricsList;
	}

	public String getHostIpProcessingCAS() {
      return hostIpProcessingCAS;
    }

    public void setHostIpProcessingCAS(String hostIpProcessingCAS) {
      this.hostIpProcessingCAS = hostIpProcessingCAS;
    }

    public Destination getFreeCasNotificationQueue() {
      return freeCasNotificationQueue;
    }

    public void setFreeCasNotificationQueue(Destination freeCasNotificationQueue) {
      this.freeCasNotificationQueue = freeCasNotificationQueue;
    }

    public boolean isProcessException() {
      return processException;
    }

    public void setProcessException() {
      this.processException = true;
    }
    

    public Exception getException() {
      return exception;
    }

    public void setException(Exception exception) {
      this.exception = exception;
    }

    public long getMetaTimeoutErrorCount() {
      return metaTimeoutErrorCount;
    }

    public void setMetaTimeoutErrorCount(long timeoutErrorCount) {
      metaTimeoutErrorCount = timeoutErrorCount;
    }

    public long getProcessTimeoutErrorCount() {
      return processTimeoutErrorCount;
    }

    public void setProcessTimeoutErrorCount(long timeoutErrorCount) {
      processTimeoutErrorCount = timeoutErrorCount;
    }

    public long getProcessErrorCount() {
      return processErrorCount;
    }

    public void setProcessErrorCount(long processErrorCount) {
      this.processErrorCount = processErrorCount;
    }

    public long getSerializationTime() {
      return serializationTime;
    }

    public void setSerializationTime(long serializationTime) {
      this.serializationTime = serializationTime;
    }

    public long getDeserializationTime() {
      return deserializationTime;
    }

    public void setDeserializationTime(long deserializationTime) {
      this.deserializationTime = deserializationTime;
    }

    public boolean isSynchronousInvocation() {
      return synchronousInvocation;
    }

    public void setSynchronousInvocation() {
      synchronousInvocation = true;
    }

    public boolean isTimeoutException() {
      return timeoutException;
    }

    public void setTimeoutException() {
      timeoutException = true;
    }

    public void clearTimeoutException() {
      timeoutException = false;
    }

    public Message getMessage() {
      return message;
    }

    public void setMessage(Message message) {
      this.message = message;
    }

    public ClientRequest(String aCasReferenceId, BaseUIMAAsynchronousEngineCommon_impl aUimaEEEngine) // ,
                                                                                                      // long
                                                                                                      // aTimeout)
    {
      uimaEEEngine = aUimaEEEngine;
      casReferenceId = aCasReferenceId;
      sharedData = null;
    }

    public String getCasReferenceId() {
      return casReferenceId;
    }

    public void setThreadId(long aThreadId) {
      threadId = aThreadId;
    }

    public long getThreadId() {
      return threadId;
    }

    public void setReceivedProcessCasReply() {
    }

    public void setMetadataTimeout(int aTimeout) {
      metadataTimeout = aTimeout;
    }

    public void setProcessTimeout(int aTimeout) {
      processTimeout = aTimeout;
    }

    public long getProcessTimeout() {
      return processTimeout;
    }

    public void setCpcTimeout(int aTimeout) {
      cpcTimeout = aTimeout;
    }

    public void setEndpoint(String anEndpoint) {
      endpoint = anEndpoint;
    }

    public void setIsRemote(boolean aRemote) {
      isRemote = aRemote;
    }

    public boolean isRemote() {
      return isRemote;
    }

    public void setCAS(CAS aCAS) {
      cas = aCAS;
    }

    public CAS getCAS() {
      return cas;
    }

    public void setCAS(String aSerializedCAS) {
      serializedCAS = aSerializedCAS;
      isSerializedCAS = true;
    }

    public void setBinaryCAS(byte[] aBinaryCas) {
      binaryCas = aBinaryCas;
      isBinaryCas = true;
    }

    public boolean isBinaryCAS() {
      return isBinaryCas;
    }

    public byte[] getBinaryCAS() {
      return binaryCas;
    }

    public String getXmiCAS() {
      return serializedCAS;
    }

    public void startTimer() {
      Date timeToRun = null;
      final ClientRequest _clientReqRef = this;
      if (isMetaRequest()) {
        timeToRun = new Date(System.currentTimeMillis() + metadataTimeout);
      } else if (isCPCRequest()) {
        timeToRun = new Date(System.currentTimeMillis() + cpcTimeout);
      } else {
        timeToRun = new Date(System.currentTimeMillis() + processTimeout);
      }

      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINEST)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(), "startTimer",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_starting_timer_FINEST",
                new Object[] { endpoint });
      }
      timer = new Timer();
      timer.schedule(new TimerTask() {
        public void run() {
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "run",
                    JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_timer_expired_INFO",
                    new Object[] { endpoint, casReferenceId });
          }
          CAS cas = null;
          if (isSerializedCAS) {
            try {
              if (isRemote) {
                if (isBinaryCas) {
                  cas = deserialize(binaryCas, _clientReqRef);
                } else {
                  cas = deserializeCAS(serializedCAS, _clientReqRef);
                }
              } else {
                cas = null; // not supported for collocated
              }
            } catch (Exception e) {
              if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
                UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                        "startTimer.run()", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                        "UIMAEE_exception__WARNING", e);
              }
            }
          }

          int timeOutKind;
          if (isMetaRequest()) {
            timeOutKind = MetadataTimeout;
            initialized = false;
            abort = true;
            metaTimeoutErrorCount++;
            clientSideJmxStats.incrementMetaTimeoutErrorCount();
            getMetaSemaphore.release();
          } else if (isCPCRequest()) {
            try {
                if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
                    UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                            "startTimer.run()", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
                            "UIMAJMS_client_timedout_waiting_for_CPC__WARNING", getEndPointName());
                  }
            } catch (Exception e) {

            }
            timeOutKind = CpCTimeout;
            cpcReadySemaphore.release();
          } else {
            timeOutKind = ProcessTimeout;
            processTimeoutErrorCount++;
            clientSideJmxStats.incrementProcessTimeoutErrorCount();
          }
          System.out.println("calling notifyOnTimeout() - Got Process Timeout ");
          uimaEEEngine.notifyOnTimout(cas, endpoint, timeOutKind, getCasReferenceId());
          timer.cancel();
          if (cas != null) {
            cas.release();
          }
          return;
        }
      }, timeToRun);

    }

    public void removeEntry(String aCasReferenceId) {
      if (uimaEEEngine.clientCache.containsKey(casReferenceId)) {
        uimaEEEngine.clientCache.remove(casReferenceId);
      }

    }

    public void cancelTimer() {
      if (timer != null) {
        timer.cancel();
      }
    }

    public boolean isCPCRequest() {
      return isCPCRequest;
    }

    public void setCPCRequest(boolean isCPCRequest) {
      this.isCPCRequest = isCPCRequest;
    }

    public boolean isMetaRequest() {
      return isMetaRequest;
    }

    public void setMetaRequest(boolean isMetaRequest) {
      this.isMetaRequest = isMetaRequest;
    }

    public void setCASDepartureTime(long aDepartureTime) {
      casDepartureTime = aDepartureTime;
    }

    public long getCASDepartureTime() {
      return casDepartureTime;
    }

    public void setTimeWaitingForReply(long aTimeWaitingForReply) {
      timeWaitingForReply = aTimeWaitingForReply;
    }

    public long getTimeWaitingForReply() {
      return timeWaitingForReply;
    }

    public XmiSerializationSharedData getXmiSerializationSharedData() {
      return sharedData;
    }

    public void setXmiSerializationSharedData(XmiSerializationSharedData data) {
      this.sharedData = data;
    }
    
    public ReuseInfo getCompress6ReuseInfo() {
      return compress6ReuseInfo;
    }
    
    public void setCompress6ReuseInfo(ReuseInfo compress6ReuseInfo) {
      this.compress6ReuseInfo = compress6ReuseInfo;
    }
  }

  protected static class ThreadMonitor {
    private long threadId;
    private volatile boolean calledFromStop = false;
    
    private Semaphore monitor = new Semaphore(1);

    public ThreadMonitor(long aThreadId) {
      threadId = aThreadId;
    }

    public void calledFromStopMethod() {
    	calledFromStop = true;
    }
    public boolean wasCalledFromStopMethod() {
    	return calledFromStop;
    }
    public long getThreadId() {
      return threadId;
    }

    public Semaphore getMonitor() {
      return monitor;
    }
  }

  /**
   * Called when the producer thread is fully initialized
   */
  protected void onProducerInitialized() {
    producerInitialized = true;
  }

  public boolean connectionOpen() {
	SharedConnection sharedConnection;
    if ( (sharedConnection = lookupConnection(getBrokerURI())) != null ) {
      return sharedConnection.isConnectionValid();
    }
    return false;
  }
  /**
   * Continuously tries to recover connection a broker. it gives up
   * when the client is stopped or the connection is recovered.
   */
  public boolean recoverSharedConnectionIfClosed() {
	SharedConnection sharedConnection;
    //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.recoverSharedConnectionIfClosed() ");

    if ( !connectionOpen() ) {
        //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.recoverSharedConnectionIfClosed() connection Not Open");
      sharedConnection = lookupConnection(getBrokerURI());
      while ( sharedConnection != null && running ) {
        //  blocks until connection is refreshed 
          //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.recoverSharedConnectionIfClosed() got SharedConnection");
        try {
            //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.recoverSharedConnectionIfClosed() Retrying until success");
          sharedConnection.retryConnectionUntilSuccessfull();
          break;
        } catch( Exception e) {
          //  will retry until successful or the client is not running
        }
      }
       
      //  if still running inject new connection
      if ( running && sharedConnection.getClientCount() > 0) {
        //  Inject a new Connection object into an object that sends 
        //  messages to a service. This call invalidates all Session
        //  and Producer objects.
        //  System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.recoverSharedConnectionIfClosed() Got new connection");
        getDispatcher().setConnection(sharedConnection.getConnection());
        
        //System.out.println("Uima-AS Client Recovered Broker Connection - Sending GetMeta Ping");
        serviceDelegate.setAwaitingPingReply();

        try {
            sendMetaRequest();
            // @@@@@@@@@@@@@@@ Changed on 4/20 serviceDelegate.cancelDelegateTimer();
            // Start a timer for GetMeta ping and associate a cas id
            // with this timer. The delegate is currently in a timed out
            // state due to a timeout on a CAS with a given casReferenceId.
            //  
            String cid = serviceDelegate.getOldestCasIdFromOutstandingList();
            if ( cid != null ) {
                serviceDelegate.startGetMetaRequestTimer(cid);
            } else {
                serviceDelegate.startGetMetaRequestTimer();
            }
        } catch( Exception e) {
        	
        }
      }
      return true;
    }
    return false;
  }
  public void onException(Exception aFailure, String aDestination) {
    if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
      UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(), "onException",
              JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_error_while_sending_msg__WARNING",
              new Object[] { aDestination, aFailure });
    }
    try {
      stop();
    } catch( Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * @override
   */
  protected void setReleaseCASMessage(TextMessage msg, String aCasReferenceId) throws Exception {
  }

  
  protected SharedConnection lookupConnection(String brokerUrl) {
    SharedConnection sharedConnection = null;
    try {
      if ( sharedConnections.containsKey(brokerUrl) ) {
        return sharedConnections.get(brokerUrl);
      } else {
        boolean first = true;
        while( running ) {

          try {
            producerInitialized = false;
            sharedConnection = validateConnection(brokerUrl);
            sharedConnection.retryConnectionUntilSuccessfull();
            break;
          } catch( Exception e) {
            Object monitor = new Object();
            try {
              synchronized(monitor) {
                if ( first ) {
                  first = false;
                  if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
                    UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(), "onException",
                            JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_retrying_jms_connection__WARNING",
                            new Object[] { brokerUrl });
                  }
                }
                monitor.wait(5000);  // retry connection every 5 secs
              }
            } catch( Exception ex) {
            }
          }
        } // while
      }
    } catch( Exception exx ) {

      if ( brokerUrl == null ) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(), "onException",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_invalid_broker_url__WARNING",
                new Object[] { });
        Thread.dumpStack();
      }
      StringBuffer sb = new StringBuffer();
      for( Entry<String, SharedConnection> conn : sharedConnections.entrySet()) {
        sb.append("-- Shared Connection broker:"+conn.getKey()+" State:"+conn.getValue().getState()+"\n");
      }
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(), "onException",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_shared_connections__INFO",
                new Object[] { sb.toString()});
      }
      throw new RuntimeException("Invalid State");
    }

    return sharedConnection;
      
  }
  
  // This class is used to share JMS Connection by all instances of UIMA AS
  // client deployed in the same JVM.
  public static class SharedConnection {
    
    private static final Class<SharedConnection> CLASS_NAME = SharedConnection.class;
    
    public enum ConnectionState { CLOSED, FAILED, WAITING_FOR_BROKER, OPEN };
    
    private volatile Connection connection;
    private volatile boolean stop = false;
    
    private ConnectionState state = ConnectionState.CLOSED;
    private Object stateMonitor = new Object();
    private Object mux = new Object();
    private String brokerURL;
    private ConnectionValidator connectionValidator;
  //  private Object destroyMux = new Object();
    private ConnectionFactory connectionFactory = null;
    private Semaphore semaphore;
    
    public void setConnectionFactory(ConnectionFactory cf ) {
    	this.connectionFactory = cf;
    }
	public Semaphore getSemaphore() {
		return semaphore;
	}
	public void setSemaphore(Semaphore semaphore) {
		this.semaphore = semaphore;
	}

	private List<BaseUIMAAsynchronousEngineCommon_impl> clientList = 
      new ArrayList<BaseUIMAAsynchronousEngineCommon_impl>();
      
    public SharedConnection( ConnectionFactory connectionFactory , String brokerURL ) {
      this.connectionFactory = connectionFactory;
      this.brokerURL = brokerURL;
    }
    public String getBroker() {
      return brokerURL;
    }
    public void setConnectionValidator( ConnectionValidator validator ) {
      connectionValidator = validator;
    }
    public boolean isOpen() {
      return state == ConnectionState.OPEN;
    }
    public  boolean isConnectionValid() {
      if ( connectionValidator == null ) {
        return false;
      }
      if ( connectionValidator.connectionClosedOrInvalid(connection) == false ) {
        return true;
      } 
      return false;
    }
    /**
     * Using jndi context look the connection factory and 
     * attempt to create broker connection. Throws exception
     * if not successfull. 
     */ 
    public void create() throws Exception {
      if ( connectionFactory == null ) {
          //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.create() - ConnectionFactory is null");
        throw new InstantiationException("UIMA AS Client Unable to Initialize SharedConnection Object. ConnectionFactory Has Not Been Provided");
      }
      if ( connection != null ) {
    	  try {
    		  connection.close();
    	  } catch( Exception eee) {
    		  
    	  }
      }
      //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.create() - Creating new Connection");
      //  Create shared jms connection to a broker
      connection = connectionFactory.createConnection();
      connection.setClientID("ClientListener");
      state = ConnectionState.OPEN;
      stop = false;      
    }
    private void reinitializeClientListeners() {
      for( BaseUIMAAsynchronousEngineCommon_impl client : clientList ) {
        try {
          client.initializeConsumer(brokerURL, connection);
        } catch( Exception e) {
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                    "reinitializeClientListeners", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                    "UIMAEE_exception__WARNING", e);
          }
        }
      }
    }
   private void forceTimeout(List<DelegateEntry> casList, BaseUIMAAsynchronousEngineCommon_impl client) throws Exception {
     //  Force timeout on all pending CASes. Replies will never come, we've lost broker
     //  connection.
     Exception forcedTimeoutException = new MessageTimeoutException("Client Lost Connection To Broker. Forcing Timeout Exception");
     ArrayList<DelegateEntry> copyOfPendingCasList = new ArrayList<DelegateEntry>(casList);
     for( DelegateEntry entry : copyOfPendingCasList ) {
       try {
         ClientRequest cachedRequest = (ClientRequest) client.clientCache.get(entry.getCasReferenceId());
         //  Handle forced timeout. This method removes CAS from the list of CASes pending reply
         client.handleException(forcedTimeoutException, entry.getCasReferenceId(), entry.getCasReferenceId(), cachedRequest, true);
       } catch( Exception e) {
         if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
           UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, getClass().getName(),
                   "forceTimeout", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
                   "UIMAEE_exception__WARNING", e);
         }
       }
     }
     
   }
    public synchronized void retryConnectionUntilSuccessfull() {
      //  Check if the connection has been restored to the broker. Another thread
      //  may have previously recovered the connection here while we were blocked
      //  on entry to this method ( it is synchronized)
      if ( isConnectionValid() ) {
          //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.retryConnectionUntilSuccessfull() connection is valid");

        return;
      }
      //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.retryConnectionUntilSuccessfull() connection Not valid");
      //  Change state of each client in this JVM that uses this shared connection.
      for(BaseUIMAAsynchronousEngineCommon_impl client: clientList) {
        client.state = ClientState.RECONNECTING;
        client.producerInitialized = false;
      }
      //System.out.println("------------------------ stop1? "+stop);
      if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
        UIMAFramework.getLogger(CLASS_NAME).logrb(Level.WARNING, CLASS_NAME.getName(), "retryConnectionUntilSuccessfull",
              JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_client_lost_connection_to_broker__WARNING",
              new Object[] { brokerURL, (stop==true) });
      }
//      stop = false;
      //System.out.println("------------------------ stop2? "+stop);
      //  This loop attempts to recover broker connection every 5 seconds and ends when all clients 
      //  using this shared object terminate or a connection is recovered
      boolean log = true;
      while( !stop ) {
    	  
    	  BaseUIMAAsynchronousEngineCommon_impl c = null;
        if ( clientList.size() == 0 ) {
          break; // no more active clients - break out of connection recovery
        } else {
        	
        	c = clientList.get(0);
        	if ( !c.running) {
        		break;
        	} 
        }
        try {
        	
          //  Attempt a new connection to a broker
          create();
          if ( c != null && !c.running) {
        	  break;
          }
          //  Got it, start the connection
          start();
          if ( c != null && !c.running) {
        	  break;
          }
          //  Forces clients to drop old Session, Temp Queue, and Consumer objects and create 
          //  new ones. This is needs to be done after a new Connection is created.
          reinitializeClientListeners();
          synchronized( stateMonitor) {
            state = ConnectionState.OPEN;
          }
          break;
        } catch( Exception e) {
        	
    		if ( log ) {
                if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
                    UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "retryConnectionUntilSuccessfull",
                          JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_client_connection_retry__INFO",
                          new Object[] { brokerURL });
                }
        		if ( e instanceof JMSException && e.getMessage().indexOf("Connection refused") > 0) {
        			log = false;
            		System.out.println("Uima AS Client:"+e.getMessage()+" Retrying every 5 seconds until successfull");
                    
        	    } else {
            	    e.printStackTrace();
        	    }
    		}
           synchronized( stateMonitor ) {
            try {
              stateMonitor.wait(5000); // retry every 5 secs
            } catch( InterruptedException ie) {}
          }
        }
      }
      
      
      if ( !stop ) {
        if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "retryConnectionUntilSuccessfull",
                JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_client_recovered_connection__INFO",
                new Object[] { brokerURL });
        }
      }
      for(BaseUIMAAsynchronousEngineCommon_impl client: clientList) {
        client.state = ClientState.RUNNING;
      }
    }
    public void stop() {
    	stop = true;
    }
    public void start() throws Exception {
      if ( connectionValidator != null && connectionValidator.connectionClosedOrInvalid(connection) ) {
        throw new ResourceInitializationException(new Exception("Unable to start JMS connection that is not open."));
      }
      connection.start();
    }
    public ConnectionState getState() {
      synchronized( stateMonitor) {
        return this.state;
      }
    }
    

    public synchronized Connection getConnection() {
      return connection;
    }

    public synchronized void setConnection(Connection connection) {
      this.connection = connection;
    }

    public void registerClient(BaseUIMAAsynchronousEngineCommon_impl client) {
      synchronized(mux) {
        clientList.add(client);
      }
    }
    public void unregisterClient(BaseUIMAAsynchronousEngineCommon_impl client) {
      synchronized(mux) {
        clientList.remove(client);
      }
      
    }
    public int getClientCount() {
      synchronized (mux) {
        return clientList.size();
      }
    }
    /**
     * This method is called from stop(). It will stop the shared connection if all of the clients
     * have already terminated
     * @return
     */
    public boolean destroy() {
    	return destroy(false);
    }
    
    public boolean destroy(boolean doShutdown) {
        //  Check if all clients have terminated and only than stop the shared connection
        if (getClientCount() == 0 && connection != null
                && !((ActiveMQConnection) connection).isClosed() 
                && !((ActiveMQConnection) connection).isClosing()) {
          try {
            stop = true;
            connection.stop();
            connection.close();
            Object closeMux = new Object();
            // wait until the connection is closed. Sleep for awhile between
            // checks
            while( !((ActiveMQConnection) connection).isClosed() ) {
              try {
                  synchronized(closeMux) {
                	  closeMux.wait(100);
                  }
              } catch( InterruptedException exx) {}
            }
            // remove this shared connection from global connections map
            sharedConnections.remove(brokerURL);
          } catch (Exception e) {
            /* ignore */
          }
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "destroy",
                  JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_client_connection_closed__INFO",
                  new Object[] {  });
          }
          return true;

        } else {
          if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
            UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(), "destroy",
                  JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_client_shared_connection_not_closed__INFO",
                  new Object[] { getClientCount() });
          }

        }
        return false;
      }
  }
  public static class UimaAsTransportListener implements TransportListener {

	@Override
	public void onCommand(Object arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onException(IOException arg0) {
		System.out.println("!!!!!!!!!!!!!!!!!! UimaAsTransportListener.onException() - lost connectipon to broker");
		
	}

	@Override
	public void transportInterupted() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void transportResumed() {
		// TODO Auto-generated method stub
		
	}
	  
  }
  public static class UimaASShutdownHook implements Runnable {
    UimaAsynchronousEngine asEngine=null;
    public UimaASShutdownHook( UimaAsynchronousEngine asEngine) {
      this.asEngine = asEngine;
    }
    public void run() {
      try {
        if ( asEngine != null ) {
          asEngine.stop();
        } 
      } catch( Exception ex) {
        ex.printStackTrace();
      }
    }
    
  }
}
