You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2018/12/20 14:51:16 UTC

svn commit: r1849402 - in /uima/uv3/uima-as-v3/trunk/uimaj-as-jms: ./ src/main/java/org/apache/uima/adapter/jms/client/ src/main/java/org/apache/uima/adapter/jms/message/ src/main/java/org/apache/uima/adapter/jms/service/ src/main/resources/

Author: schor
Date: Thu Dec 20 14:51:16 2018
New Revision: 1849402

URL: http://svn.apache.org/viewvc?rev=1849402&view=rev
Log:
[UIMA-5937] update pom version and scm, merge v2 updates, record merge

Added:
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/UimaAsClientStoppingException.java
      - copied unchanged from r1846915, uima/uima-as/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/UimaAsClientStoppingException.java
Modified:
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/   (props changed)
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/pom.xml
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseMessageSender.java
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngineCommon_impl.java
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/ClientServiceDelegate.java
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/message/PendingMessage.java
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/service/Dd2spring.java
    uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/resources/jms_adapter_messages.properties

Propchange: uima/uv3/uima-as-v3/trunk/uimaj-as-jms/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Dec 20 14:51:16 2018
@@ -1,2 +1,3 @@
 /uima/uima-as/branches/depend-on-parent-pom-4/uimaj-as-jms:961335-961760
 /uima/uima-as/branches/mavenAlign/uimaj-as-jms:941450-944450
+/uima/uima-as/trunk/uimaj-as-jms:1786000-1846915

Modified: uima/uv3/uima-as-v3/trunk/uimaj-as-jms/pom.xml
URL: http://svn.apache.org/viewvc/uima/uv3/uima-as-v3/trunk/uimaj-as-jms/pom.xml?rev=1849402&r1=1849401&r2=1849402&view=diff
==============================================================================
--- uima/uv3/uima-as-v3/trunk/uimaj-as-jms/pom.xml (original)
+++ uima/uv3/uima-as-v3/trunk/uimaj-as-jms/pom.xml Thu Dec 20 14:51:16 2018
@@ -15,7 +15,7 @@
 	<parent>
 		<groupId>org.apache.uima</groupId>
 		<artifactId>uima-as-parent</artifactId>
-		<version>3.0.0-SNAPSHOT</version>
+		<version>3.0.1-SNAPSHOT</version>
 		<relativePath>../uima-as-parent/pom.xml</relativePath>
 	</parent>
 
@@ -30,13 +30,13 @@
 		cutting/pasting the <scm> element, and just changing the following two properties -->
 	<scm>
 		<connection>
-      scm:svn:http://svn.apache.org/repos/asf/uima/uima-as/trunk/uimaj-as-jms
+      scm:svn:http://svn.apache.org/repos/asf/uima/uv3/uima-as-v3/trunk/uimaj-as-jms
     </connection>
 		<developerConnection>
-      scm:svn:https://svn.apache.org/repos/asf/uima/uima-as/trunk/uimaj-as-jms
+      scm:svn:https://svn.apache.org/repos/asf/uima/uv3/uima-as-v3/trunk/uimaj-as-jms
     </developerConnection>
 		<url>
-      http://svn.apache.org/viewvc/uima/uima-as/trunk/uimaj-as-jms
+      http://svn.apache.org/viewvc/uima/uv3/uima-as-v3/trunk/uimaj-as-jms
     </url>
 	</scm>
 

Modified: uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseMessageSender.java
URL: http://svn.apache.org/viewvc/uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseMessageSender.java?rev=1849402&r1=1849401&r2=1849402&view=diff
==============================================================================
--- uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseMessageSender.java (original)
+++ uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseMessageSender.java Thu Dec 20 14:51:16 2018
@@ -20,6 +20,7 @@
 package org.apache.uima.adapter.jms.client;
 
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 
 import javax.jms.Connection;
@@ -85,7 +86,9 @@ public abstract class BaseMessageSender
 
   // Releases resources
   protected abstract void cleanup() throws Exception;
-
+  
+  protected abstract void dispatchMessage(PendingMessage pm, BaseUIMAAsynchronousEngineCommon_impl engine, boolean casProcessRequest ) throws Exception;
+	  
   // Returns the name of the destination
   protected abstract String getDestinationEndpoint() throws Exception;
 
@@ -93,6 +96,7 @@ public abstract class BaseMessageSender
   
   private MessageProducer producer = null;
   
+  private CountDownLatch stopLatch = new CountDownLatch(1);
 
   public BaseMessageSender(BaseUIMAAsynchronousEngineCommon_impl anEngine) {
     messageQueue = anEngine.pendingMessageQueue;
@@ -110,9 +114,32 @@ public abstract class BaseMessageSender
    */
   public void doStop() {
     done = true;
+    
     // Create an empty message to deliver to the queue that is blocking
     PendingMessage emptyMessage = new PendingMessage(0);
+    
+    messageQueue.add(emptyMessage);
+    synchronized(emptyMessage) {
+    	try {
+    		emptyMessage.wait(200);
+    	} catch( Exception ee) {
+    		
+    	}
+    	
+    }
     messageQueue.add(emptyMessage);
+    if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(
+			Level.INFO)) {
+     UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO,
+				CLASS_NAME.getName(), "doStop",
+				JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
+				"UIMAJMS_STOP_DISPATCH_THREAD_INFO");
+  }
+    try {
+        stopLatch.await();
+    } catch( InterruptedException e) {
+    	
+    }
   }
 
   /**
@@ -216,6 +243,11 @@ public abstract class BaseMessageSender
    */
   public void run() {
     String destination = null;
+    if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
+          UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, getClass().getName(),
+                  "run", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
+                  "UIMAJMS_START_DISPATCH_THREAD_INFO");
+    }
     //  by default, add time to live to each message
     boolean addTimeToLive = true;
     // Check the environment for existence of NoTTL tag. If present,
@@ -261,7 +293,13 @@ public abstract class BaseMessageSender
       } catch (InterruptedException e) {
       }
       if (done) {
-        break; // done in this loop
+    	  if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
+              UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, getClass().getName(),
+                      "run", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
+                      "UIMAJMS_EXIT_DISPATCH_THREAD_INFO");
+            }
+    	  stopLatch.countDown();
+    	  break; // done in this loop
       }
       //  Check if the request should be rejected. If the connection to the broker is invalid and the request
       //  is not GetMeta Ping, reject the request after the connection is made. The reject() method created
@@ -283,7 +321,7 @@ public abstract class BaseMessageSender
       }
      
       //  get the producer initialized from a valid connection
-      producer = getMessageProducer();
+//      producer = getMessageProducer();
       //  Check if the request should be rejected. It would be the case if the connection was invalid and
       //  subsequently recovered. If it was invalid, we went through error handling and the request is stale.
       if ( !rejectRequest && engine.running) {
@@ -295,6 +333,24 @@ public abstract class BaseMessageSender
                       "UIMAJMS_client_dispatching_getmeta_ping__INFO", new Object[] { });
             }
            }
+          
+          // NEW CODE 07/12/2017
+          while( engine.running ) {
+        	  try {
+        	      //  blocks until the connection is re-established with a broker
+        	      engine.recoverSharedConnectionIfClosed();
+        	      SharedConnection sc = 
+        	    		  engine.lookupConnection(engine.getBrokerURI());
+        	      dispatchMessage(pm,engine,isProcessRequest(pm));
+        	
+        		  break;
+        	  } catch( Exception exx) {
+        		  
+        	  }
+          }
+          
+          
+        /*  
            try {
              // Request JMS Message from the concrete implementation
              Message message = null;
@@ -306,7 +362,9 @@ public abstract class BaseMessageSender
              } else {
                message = createTextMessage();
              }
-
+             //  get the producer initialized from a valid connection
+             producer = getMessageProducer();
+            
              initializeMessage(pm, message);
              if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
                UIMAFramework.getLogger(CLASS_NAME).logrb(
@@ -425,17 +483,21 @@ public abstract class BaseMessageSender
              }
              reject(pm,e);
            }
-
+*/
       }
     }
     try {
       cleanup();
+      if ( stopLatch.getCount() > 0) {
+    	  stopLatch.countDown();
+      }
+      stopLatch.countDown();
     } catch (Exception e) {
       handleException(e, destination);
     }
   }
 
-  private void initializeMessage(PendingMessage aPm, Message anOutgoingMessage) throws Exception {
+  protected void initializeMessage(PendingMessage aPm, Message anOutgoingMessage) throws Exception {
     // Populate message properties based on outgoing message type
     switch (aPm.getMessageType()) {
       case AsynchAEMessage.GetMeta:
@@ -459,6 +521,19 @@ public abstract class BaseMessageSender
       case AsynchAEMessage.CollectionProcessComplete:
         engine.setCPCMessage(anOutgoingMessage);
         break;
+        
+      case AsynchAEMessage.ReleaseCAS:
+          String casRefId = (String) aPm.get(AsynchAEMessage.CasReference);
+          String selector = 
+        			 (String) aPm.get(AsynchAEMessage.TargetingSelector) ;
+
+          engine.setFreeCasMessage(anOutgoingMessage, casRefId, selector);
+          break;
+          
+      case AsynchAEMessage.Stop:
+          String casRefId2 = (String) aPm.get(AsynchAEMessage.CasReference);
+          engine.setStopMessage(anOutgoingMessage, casRefId2);
+    	  break;
     }
   }
 

Modified: uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngineCommon_impl.java
URL: http://svn.apache.org/viewvc/uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngineCommon_impl.java?rev=1849402&r1=1849401&r2=1849402&view=diff
==============================================================================
--- uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngineCommon_impl.java (original)
+++ uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/BaseUIMAAsynchronousEngineCommon_impl.java Thu Dec 20 14:51:16 2018
@@ -31,6 +31,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.UUID;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
@@ -38,7 +39,6 @@ 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;
 
@@ -246,8 +246,12 @@ public abstract class BaseUIMAAsynchrono
 
   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 public void setCPCMessage(Message msg) throws Exception;
+  abstract protected void setCPCMessage(Message msg) throws Exception;
 
   abstract public void initialize(Map anApplicationContext) throws ResourceInitializationException;
 
@@ -264,6 +268,8 @@ public abstract class BaseUIMAAsynchrono
   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
@@ -536,13 +542,20 @@ public abstract class BaseUIMAAsynchrono
 
         // Unblock threads
         if (threadMonitorMap.size() > 0) {
-          Iterator it = threadMonitorMap.keySet().iterator();
+          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();
           }
         }
@@ -819,7 +832,14 @@ public abstract class BaseUIMAAsynchrono
          if ( (hasNext = collectionReader.hasNext()) == true) {
              cas = getCAS();
              collectionReader.getNext(cas);
-             sendCAS(cas);
+             String targetStringSelector = 
+            		 System.getProperty(UimaAsynchronousEngine.TargetSelectorProperty);
+             if (targetStringSelector != null && targetStringSelector.trim().length() > 0 ) {
+            	 sendCAS(cas, targetStringSelector );
+             } else {
+            	 sendCAS(cas);
+             }
+             
          } else {
            break;
          }
@@ -856,12 +876,17 @@ public abstract class BaseUIMAAsynchrono
    * Sends a given CAS for analysis to the UIMA EE Service.
    * 
    */
-  private String sendCAS(CAS aCAS, ClientRequest requestToCache) throws ResourceProcessException {
+  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)) {
@@ -1016,8 +1041,14 @@ public abstract class BaseUIMAAsynchrono
     if ( !running ) {
     	throw new ResourceProcessException(new UimaEEServiceException("Uima AS Client Has Been Stopped. Rejecting Request to Process CAS"));
     }
-	  return this.sendCAS(aCAS, produceNewClientRequestObject());
+	  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.
@@ -1108,7 +1139,7 @@ public abstract class BaseUIMAAsynchrono
     	                    "UIMAJMS_dispatch_delayed_cas__INFO",
     	                    new Object[] { casReferenceId, String.valueOf(cachedRequest.cas.hashCode())});
     	          }
-    	          sendCAS(cachedRequest.getCAS(), cachedRequest);
+    	          sendCAS(cachedRequest.getCAS(), cachedRequest,null);
     	        }
     	  }
       } else {
@@ -1500,11 +1531,35 @@ public abstract class BaseUIMAAsynchrono
     // 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);
-    // Fetch the destination for Free CAS notification
-    Destination freeCASNotificationDestination = message.getJMSReplyTo();
+    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 {
@@ -1539,7 +1594,7 @@ public abstract class BaseUIMAAsynchrono
         }
       }
     }
-    
+    */
     // 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);
@@ -1735,6 +1790,10 @@ public abstract class BaseUIMAAsynchrono
           } else {
             status = new UimaASProcessStatusImpl(pt, cas, casReferenceId);
           }
+          if ( cachedRequest.getTargetServiceId() != null ) {
+        	  status.setServiceTargetID(cachedRequest.getTargetServiceId());
+          }
+          
           if ( message.propertyExists(AsynchAEMessage.CASPerComponentMetrics)) {
  
 	      List<AnalysisEnginePerformanceMetrics> ml = 
@@ -2102,18 +2161,29 @@ public abstract class BaseUIMAAsynchrono
   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);
+    return sendAndReceiveCAS(aCAS, pt, null, null);
   }
   public String sendAndReceiveCAS(CAS aCAS, List<AnalysisEnginePerformanceMetrics> componentMetricsList) throws ResourceProcessException {
-    return sendAndReceiveCAS(aCAS, null, componentMetricsList);
+    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) throws ResourceProcessException {
+  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"));
     }
@@ -2139,7 +2209,7 @@ public abstract class BaseUIMAAsynchrono
 
     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);
@@ -2176,7 +2246,7 @@ public abstract class BaseUIMAAsynchrono
                 "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);
+      casReferenceId = sendCAS(aCAS, cachedRequest, targetServiceId);
 
     } catch( ResourceProcessException e) {
       
@@ -2211,6 +2281,12 @@ public abstract class BaseUIMAAsynchrono
           // 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
@@ -2226,7 +2302,7 @@ public abstract class BaseUIMAAsynchrono
           }
           if (running && serviceDelegate.getState() == Delegate.OK_STATE
                   && serviceDelegate.removeCasFromPendingDispatchList(casReferenceId)) {
-            sendCAS(aCAS, cachedRequest);
+            sendCAS(aCAS, cachedRequest, targetServiceId);
           } else {
             break; // done here, received a reply or the client is not running
           }
@@ -2548,7 +2624,17 @@ public abstract class BaseUIMAAsynchrono
     // flag to indicate if the remote service acknowledged receiving a CAS for processing
     private volatile boolean receivedServiceACK=false;
     
-    public boolean receivedServiceACK() {
+    private String targetServiceId;
+    
+    public String getTargetServiceId() {
+		return targetServiceId;
+	}
+
+	public void setTargetServiceId(String serviceTargetId) {
+		this.targetServiceId = serviceTargetId;
+	}
+
+	public boolean receivedServiceACK() {
 		return receivedServiceACK;
 	}
 
@@ -2902,13 +2988,20 @@ public abstract class BaseUIMAAsynchrono
 
   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;
     }
@@ -2963,7 +3056,7 @@ public abstract class BaseUIMAAsynchrono
         //  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");
+        //System.out.println("Uima-AS Client Recovered Broker Connection - Sending GetMeta Ping");
         serviceDelegate.setAwaitingPingReply();
 
         try {
@@ -3129,12 +3222,19 @@ public abstract class BaseUIMAAsynchrono
           //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-"+UIDGenerator.getGUID());
       state = ConnectionState.OPEN;
       stop = false;      
-      //System.out.println("------------- BaseUIMAAsynchronousEngineCommon_impl.create() - Created New Connection");
     }
     private void reinitializeClientListeners() {
       for( BaseUIMAAsynchronousEngineCommon_impl client : clientList ) {
@@ -3196,17 +3296,29 @@ public abstract class BaseUIMAAsynchrono
       //  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 {
-        	BaseUIMAAsynchronousEngineCommon_impl c =
-        			clientList.get(0);
+        	
+        	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();
@@ -3222,7 +3334,7 @@ public abstract class BaseUIMAAsynchrono
                           JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMAJMS_client_connection_retry__INFO",
                           new Object[] { brokerURL });
                 }
-        		if ( e instanceof JMSException && e.getMessage().endsWith("Connection refused") ) {
+        		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");
                     

Modified: uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/ClientServiceDelegate.java
URL: http://svn.apache.org/viewvc/uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/ClientServiceDelegate.java?rev=1849402&r1=1849401&r2=1849402&view=diff
==============================================================================
--- uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/ClientServiceDelegate.java (original)
+++ uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/client/ClientServiceDelegate.java Thu Dec 20 14:51:16 2018
@@ -55,7 +55,10 @@ public class ClientServiceDelegate exten
 
   private volatile boolean pingTimeout = false;
   
-  public ClientServiceDelegate(String serviceName, String anApplicationName,
+  private String freeCasSelector = "";
+  
+ 
+public ClientServiceDelegate(String serviceName, String anApplicationName,
           BaseUIMAAsynchronousEngineCommon_impl engine) {
     super.delegateKey = serviceName;
     clientUimaAsEngine = engine;
@@ -63,6 +66,13 @@ public class ClientServiceDelegate exten
       applicationName = anApplicationName;
     }
   }
+public String getFreeCasSelector() {
+	return freeCasSelector;
+}
+
+public void setFreeCasSelector(String freeCasSelector) {
+	this.freeCasSelector = freeCasSelector;
+}
 
   public boolean isSynchronousAPI() {
     return usesSynchronousAPI;

Modified: uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/message/PendingMessage.java
URL: http://svn.apache.org/viewvc/uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/message/PendingMessage.java?rev=1849402&r1=1849401&r2=1849402&view=diff
==============================================================================
--- uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/message/PendingMessage.java (original)
+++ uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/message/PendingMessage.java Thu Dec 20 14:51:16 2018
@@ -20,8 +20,10 @@ package org.apache.uima.adapter.jms.mess
 
 import java.util.HashMap;
 
-public class PendingMessage extends HashMap {
-  private int messageType;
+public class PendingMessage extends HashMap<Object, Object> {
+ 
+private static final long serialVersionUID = 3512718154731557413L;
+private int messageType;
 
   public PendingMessage(int aMessageType) {
     messageType = aMessageType;

Modified: uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/service/Dd2spring.java
URL: http://svn.apache.org/viewvc/uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/service/Dd2spring.java?rev=1849402&r1=1849401&r2=1849402&view=diff
==============================================================================
--- uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/service/Dd2spring.java (original)
+++ uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/java/org/apache/uima/adapter/jms/service/Dd2spring.java Thu Dec 20 14:51:16 2018
@@ -19,8 +19,11 @@
 
 package org.apache.uima.adapter.jms.service;
 
+import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileWriter;
 import java.io.IOException;
+import java.io.StringWriter;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -28,172 +31,469 @@ import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
 import org.apache.uima.UIMAFramework;
 import org.apache.uima.aae.UIMAEE_Constants;
 import org.apache.uima.adapter.jms.JmsConstants;
+import org.apache.uima.internal.util.XMLUtils;
 import org.apache.uima.util.Level;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
 
 public class Dd2spring {
 
-  private static final Class<Dd2spring> THIS_CLASS = Dd2spring.class;
+	private static final Class<Dd2spring> THIS_CLASS = Dd2spring.class;
+
+	private ClassLoader saxonClassLoader;
 
-  private ClassLoader saxonClassLoader;
-  
-  /**
-   * Test driver arg = path_to_source, path_to_xslt, path_to_saxon_jar, uima-as-debug flag
-   * 
-   * @param args
-   */
-  public static void main(String[] args) {
-	  try {
-		    new Dd2spring().convertDd2Spring(args[0], args[1], args[2], args[3]);
+	/**
+	 * Test driver arg = path_to_source, path_to_xslt, path_to_saxon_jar,
+	 * uima-as-debug flag
+	 * 
+	 * @param args
+	 */
+	public static void main(String[] args) {
+		try {
+			new Dd2spring()
+					.convertDd2Spring(args[0], args[1], args[2], args[3]);
+
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	public File convertDd2Spring(String ddFilePath,
+			String dd2SpringXsltFilePath, String saxonClasspath,
+			String uimaAsDebug) throws Exception {
+
+		URL urlForSaxonClassPath;
+		try {
+			urlForSaxonClassPath = new URL(saxonClasspath);
+		} catch (MalformedURLException e) {
+			e.printStackTrace();
+			UIMAFramework
+					.getLogger(THIS_CLASS)
+					.logrb(Level.CONFIG,
+							THIS_CLASS.getName(),
+							"convertDD2Spring",
+							JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
+							"UIMA_dd2spring_Cannot_convert_saxon_classpath_to_a_URL_SEVERE",
+							new Object[] { saxonClasspath });
+			return null;
+		}
+
+		File tempFile;
+		try {
+			tempFile = File.createTempFile("UIMAdd2springOutput", ".xml");
+		} catch (IOException e) {
+			e.printStackTrace();
+			UIMAFramework.getLogger(THIS_CLASS).logrb(Level.CONFIG,
+					THIS_CLASS.getName(), "convertDD2Spring",
+					JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
+					"UIMA_dd2spring_cant_create_temp_output_file_SEVERE");
+			return null;
+		}
+
+		// UIMA-5022 No longer capture output and scan for "ERROR: " as that hid
+		// errors that Saxon followed by calling exit!
+		// Processing now terminates on the first error.
+		convertDd2Spring(tempFile, ddFilePath, dd2SpringXsltFilePath,
+				urlForSaxonClassPath);
+
+		// delete the file when terminating if
+		// a) uimaAsDebug is not specified (is null) or
+		// b) uimaAsDebug is specified, but is ""
+		if (null == uimaAsDebug || uimaAsDebug.equals("")) {
+			tempFile.deleteOnExit();
+		}
+
+		return tempFile;
+	}
+
+	private void testForSaxon9InClasspath() throws Exception {
+		// UIMA-5117 Check for saxon9. If it is in the users's classpath an NPE
+		// is thrown in
+		// net.sf.saxon.event.ReceivingContentHandler.getNodeName while handling
+		// a getMeta request.
+		try {
+			Class<?> saxonVersionClass = Class.forName("net.sf.saxon.Version");
+			Method versionMethod = saxonVersionClass
+					.getMethod("getProductVersion");
+			String version = (String) versionMethod.invoke(null);
+			if (version.startsWith("9")) {
+				UIMAFramework.getLogger(THIS_CLASS).logrb(Level.SEVERE,
+						THIS_CLASS.getName(), "convertDD2Spring",
+						UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE,
+						"UIMAEE_exception__SEVERE",
+						new Object[] { "saxon9 must not be in classpath" });
+				throw new Dd2springException(
+						"saxon9 found in classpath - dd2spring transformation and UIMA-AS do not support saxon9");
+			}
+		} catch (ClassNotFoundException e) {
+			// OK - saxon not in classpath
+		}
+	}
+
+	/**
+	 * 
+	 * @param tempFile
+	 *            file to hold generated Spring from dd2spring transform
+	 * @param ddFilePath
+	 *            file path to UIMA Deployment Descriptor - passed to saxon
+	 * @param dd2SpringXsltFilePath
+	 *            file path to dd2spring.xslt transformation file - passed to
+	 *            saxon
+	 * @param saxonClasspathURL
+	 *            classpath for saxon8.jar
+	 */
+	public void convertDd2Spring(File tempFile, String ddFilePath,
+			String dd2SpringXsltFilePath, URL saxonClasspathURL)
+			throws Exception {
+
+		testForSaxon9InClasspath();
+
+		// UIMA-5117 - Add shutdown hook so can log when saxon gives up and
+		// calls exit :(
+		ShutdownHook shutdownHook = new ShutdownHook();
+		Runtime.getRuntime().addShutdownHook(shutdownHook);
+
+		// Create a classloader with saxon8 that delegates to the user's
+		// classloader and includes the classes defining xslt helper java methods
+		//   org.apache.uima.aae.deploymentDescriptor.XsltGUIDgenerator and
+		//   org.apache.uima.aae.deploymentDescriptor.XsltImportByName
+		// We do this by creating a custom class loader, which delegates
+		//   first to the threadlocal class loader, and then to 
+		//   the class loader that loaded this class.
+		//   See https://issues.apache.org/jira/browse/UIMA-5907
+		final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+		ClassLoader tccl_plus_this = new ClassLoader(this.getClass().getClassLoader()) {
+		  @Override
+		  protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+		    synchronized(Dd2spring.class) {
+  		    Class<?> c = null;
+  		    try {
+    		    c = tccl.loadClass(name);
+  		    } catch (ClassNotFoundException e) {
+  		      c = getParent().loadClass(name);
+  		    }
+  		    if (c != null && resolve) {
+  		      resolveClass(c);
+  		    }
+          return c;
+  		  }
+		  }
+		  
+		  @Override
+		  public URL getResource(String name) {
+		    synchronized(Dd2spring.class) {
+		      URL url = tccl.getResource(name);
+		      if (null == url) {
+		        url = getParent().getResource(name);  
+		      }
+	        return url;
+		    }
+		  }
 		  
-	  } catch ( Exception e) {
-		  e.printStackTrace();
-	  }
-  }
-
-  public File convertDd2Spring(String ddFilePath, String dd2SpringXsltFilePath,
-          String saxonClasspath, String uimaAsDebug) throws Exception {
-
-    URL urlForSaxonClassPath;
-    try {
-      urlForSaxonClassPath = new URL(saxonClasspath);
-    } catch (MalformedURLException e) {
-      e.printStackTrace();
-      UIMAFramework.getLogger(THIS_CLASS).logrb(Level.CONFIG, THIS_CLASS.getName(),
-              "convertDD2Spring", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
-              "UIMA_dd2spring_Cannot_convert_saxon_classpath_to_a_URL_SEVERE",
-              new Object[] { saxonClasspath });
-      return null;
-    }
-
-    File tempFile;
-    try {
-      tempFile = File.createTempFile("UIMAdd2springOutput", ".xml");
-    } catch (IOException e) {
-      e.printStackTrace();
-      UIMAFramework.getLogger(THIS_CLASS).logrb(Level.CONFIG, THIS_CLASS.getName(),
-              "convertDD2Spring", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
-              "UIMA_dd2spring_cant_create_temp_output_file_SEVERE");
-      return null;
-    }
-
-    // UIMA-5022 No longer capture output and scan for "ERROR: " as that hid
-    // errors that Saxon followed by calling exit!
-    // Processing now terminates on the first error.
-    convertDd2Spring(tempFile, ddFilePath, dd2SpringXsltFilePath, urlForSaxonClassPath);
-
-    // delete the file when terminating if
-    // a) uimaAsDebug is not specified (is null) or
-    // b) uimaAsDebug is specified, but is ""
-    if (null == uimaAsDebug || uimaAsDebug.equals("")) {
-      tempFile.deleteOnExit();
-    }
-
-    return tempFile;
-  }
-
-  /**
-   *
-   * @param tempFile
-   *          file to hold generated Spring from dd2spring transform
-   * @param ddFilePath
-   *          file path to UIMA Deployment Descriptor - passed to saxon
-   * @param dd2SpringXsltFilePath
-   *          file path to dd2spring.xslt transformation file - passed to saxon
-   * @param saxonClasspathURL
-   *          classpath for saxon8.jar
-   */
-  public void convertDd2Spring(File tempFile, String ddFilePath, String dd2SpringXsltFilePath,
-          URL saxonClasspathURL) throws Exception {
-
-    // UIMA-5117 Check for saxon9.  If it is in the users's classpath an NPE is thrown in 
-    // net.sf.saxon.event.ReceivingContentHandler.getNodeName while handling a getMeta request.
-    try {
-      Class<?> saxonVersionClass = Class.forName("net.sf.saxon.Version");
-      Method versionMethod = saxonVersionClass.getMethod("getProductVersion");
-      String version = (String) versionMethod.invoke(null);
-      if (version.startsWith("9")) {
-        UIMAFramework.getLogger(THIS_CLASS).logrb(Level.SEVERE, THIS_CLASS.getName(), "convertDD2Spring", 
-                UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_exception__SEVERE",
-                new Object[] { "saxon9 must not be in classpath" });
-        throw new Dd2springException("saxon9 found in classpath - dd2spring transformation and UIMA-AS do not support saxon9");
-      }
-    } catch (ClassNotFoundException e) {
-      // OK - saxon not in classpath
-    }
-    
-    // UIMA-5117 - Add shutdown hook so can log when saxon gives up and calls exit :(
-    ShutdownHook shutdownHook = new ShutdownHook();
-    Runtime.getRuntime().addShutdownHook(shutdownHook);
-    
-    // Create a classloader with saxon8 that delegates to the user's classloader
-    ClassLoader currentClassloader = Thread.currentThread().getContextClassLoader();
-    if (null == saxonClassLoader) {
-      URL[] classLoaderUrls = new URL[] { saxonClasspathURL };
-      saxonClassLoader = new URLClassLoader(classLoaderUrls, currentClassloader);
-    }
-      
-    // args for saxon
-    // -l -s deployment_descriptor} -o output_file_path dd2spring.xsl_file_path <-x sax_parser_class>
-    // If a custom framework includes a custom XML parser we may also need a custom parser for Saxon,
-    // so check for the existence of a class with "_SAXParser" appended to the framework name.
-
-    List<String> argsForSaxon = new ArrayList<String>();
-    String uimaFrameworkClass = System.getProperty("uima.framework_impl");
-    if (uimaFrameworkClass != null) {
-      String saxonParserClass = uimaFrameworkClass + "_SAXParser";
-      try {
-        saxonClassLoader.loadClass(saxonParserClass);
-        argsForSaxon.add("-x");
-        argsForSaxon.add(saxonParserClass);
-      } catch (ClassNotFoundException e) {
-        // No parser class defined
-      }
-    }
-    argsForSaxon.add("-l"); // turn on line numbers
-    argsForSaxon.add("-s"); // source file
-    argsForSaxon.add(ddFilePath); // source file
-    argsForSaxon.add("-o"); // output file
-    argsForSaxon.add(tempFile.getAbsolutePath()); // output file
-    argsForSaxon.add(dd2SpringXsltFilePath); // xslt transform to apply
-
-    UIMAFramework.getLogger(THIS_CLASS).log(Level.INFO, "Saxon args: " + argsForSaxon);
-
-    // Set the thread classloader so that all classes are loaded from this
-    Thread.currentThread().setContextClassLoader(saxonClassLoader);
-    Class<?> mainStartClass = null;
-    try {
-      mainStartClass = Class.forName("net.sf.saxon.Transform", true, saxonClassLoader);
-      Method mainMethod = mainStartClass.getMethod("main", String[].class);
-      mainMethod.invoke(null, new Object[] { argsForSaxon.toArray(new String[argsForSaxon.size()]) });
-    } catch (ClassNotFoundException e) {
-      System.err.println("Error - can't load Saxon jar from " + saxonClasspathURL + " for dd2spring transformation.");
-      e.printStackTrace();
-      UIMAFramework.getLogger(THIS_CLASS).logrb(Level.SEVERE, THIS_CLASS.getName(), "convertDD2Spring", 
-              JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMA_dd2spring_saxon_missing_SEVERE");
-      throw e;
-    } catch (Exception e) {
-      System.err.println("Error - dd2spring transformation failed:");
-      e.printStackTrace();
-      UIMAFramework.getLogger(THIS_CLASS).logrb(Level.SEVERE, THIS_CLASS.getName(), "convertDD2Spring", 
-              JmsConstants.JMS_LOG_RESOURCE_BUNDLE, "UIMA_dd2spring_internal_error_calling_saxon");
-      throw e;
-    } finally {
-      // Restore original classloader and remove used shutdown hook
-      Thread.currentThread().setContextClassLoader(currentClassloader);
-      Runtime.getRuntime().removeShutdownHook(shutdownHook);
-    }
-    return;
-  }
-
-  // Shutdown hook that reports when Saxon calls exit!
-  private class ShutdownHook extends Thread {
-    public void run() {
-      System.err.println("ERROR in dd2spring Saxon transformation ... System.exit called");
-      System.err.flush();
-    }
-  }
+    };
+		
+		if (null == saxonClassLoader) {
+			URL[] classLoaderUrls = new URL[] { saxonClasspathURL };
+			saxonClassLoader = new URLClassLoader(classLoaderUrls,
+					tccl_plus_this);
+		}
+		// configure Saxon with these settings
+		SaxonInputs saxonConfig = new SaxonInputs(ddFilePath, tempFile,
+				dd2SpringXsltFilePath, saxonClassLoader, tccl_plus_this);
+		
+		// creates either command line or java based interface to Saxon
+		SaxonInterface saxon = SaxonInterfaceFactory.newSaxonInterface(
+				saxonConfig);
+
+		try {
+
+			saxon.convertDD2Spring();
+
+		} catch (ClassNotFoundException e) {
+			System.err.println("Error - can't load Saxon jar from "
+					+ saxonClasspathURL + " for dd2spring transformation.");
+			e.printStackTrace();
+			UIMAFramework.getLogger(THIS_CLASS).logrb(Level.SEVERE,
+					THIS_CLASS.getName(), "convertDD2Spring",
+					JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
+					"UIMA_dd2spring_saxon_missing_SEVERE");
+			throw e;
+		} catch (Exception e) {
+			System.err.println("Error - dd2spring transformation failed:");
+			e.printStackTrace();
+			UIMAFramework.getLogger(THIS_CLASS).logrb(Level.SEVERE,
+					THIS_CLASS.getName(), "convertDD2Spring",
+					JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
+					"UIMA_dd2spring_internal_error_calling_saxon");
+			throw e;
+		} finally {
+			Runtime.getRuntime().removeShutdownHook(shutdownHook);
+		}
+		return;
+	}
+
+	// Shutdown hook that reports when Saxon calls exit!
+	private class ShutdownHook extends Thread {
+		public void run() {
+			System.err
+					.println("ERROR in dd2spring Saxon transformation ... System.exit called");
+			System.err.flush();
+		}
+	}
+
+	/**
+	 * The SaxonInputs class is used to configure Saxon
+	 *
+	 */
+	private class SaxonInputs {
+		String ddFilePath;
+		File springFilePath;
+		String xsltPath;
+		ClassLoader currentClassLoader;
+		ClassLoader saxonClassLoader;
+		public SaxonInputs(String ddFilePath, File springFilePath,
+				String xsltPath, ClassLoader saxonClassloader,
+				ClassLoader currentClassloader) {
+			super();
+			this.ddFilePath = ddFilePath;
+			this.springFilePath = springFilePath;
+			this.xsltPath = xsltPath;
+			this.currentClassLoader = currentClassloader;
+			this.saxonClassLoader = saxonClassloader;
+		}
+
+		public ClassLoader getCurrentClassLoader() {
+			return currentClassLoader;
+		}
+		public ClassLoader getSaxonClassLoader() {
+			return saxonClassLoader;
+		}
+
+		public String getDDFilePath() {
+			return ddFilePath;
+		}
+
+		public File getSpringFilePath() {
+			return springFilePath;
+		}
+
+		public String getXSLTPath() {
+			return xsltPath;
+		}
+	}
+	// Factory to produce desired Saxon interface. Currently two
+	// are supported: command line based and java API based. The
+	// default is java API interface. The command line is used
+	// to provide Saxon a custom parser.
+	private static class SaxonInterfaceFactory {
+		public static SaxonInterface newSaxonInterface(	SaxonInputs saxonConfig) {
+			SaxonInterface saxon;
+			if (System.getProperty("uima.framework_impl") != null) {
+				UIMAFramework.getLogger(THIS_CLASS).log(Level.INFO,
+					     "Using Saxon command line interface - Java Vendor:"+System.getProperty("java.vendor"));
+				// The command line based Saxon interface is used to plug-in
+				// custom parser into Saxon
+				saxon = new SaxonCommandLineInterface(saxonConfig);
+			} else {
+				UIMAFramework.getLogger(THIS_CLASS).log(Level.INFO,
+				     "Using Saxon Java API - Java Vendor:"+System.getProperty("java.vendor"));
+				// Default, use java API based Saxon interface
+				saxon = new SaxonJavaInterface(saxonConfig);
+			}
+			return saxon;
+		}
+	}
+
+	private interface SaxonInterface {
+		public void convertDD2Spring() throws Exception;
+	}
+
+	private static class SaxonCommandLineInterface implements SaxonInterface {
+		private List<String> argsForSaxon = new ArrayList<String>();
+		private SaxonInputs saxonConfig;
+		
+		SaxonCommandLineInterface(SaxonInputs saxonConfig) {
+			// args for saxon
+			// -l -s deployment_descriptor} -o output_file_path
+			// dd2spring.xsl_file_path <-x sax_parser_class>
+			// If a custom framework includes a custom XML parser we may also
+			// need a custom parser for Saxon,
+			// so check for the existence of a class with "_SAXParser" appended
+			// to the framework name.
+			this.saxonConfig = saxonConfig;
+			argsForSaxon.add("-l"); // turn on line numbers
+			argsForSaxon.add("-s"); // source file
+			argsForSaxon.add(saxonConfig.getDDFilePath()); // source file
+			argsForSaxon.add("-o"); // output file
+			argsForSaxon.add(saxonConfig.getSpringFilePath().getAbsolutePath()); // output
+																					// file
+			argsForSaxon.add(saxonConfig.getXSLTPath()); // xslt transform to
+															// apply
+			// test if there is a custom parser defined
+			String uimaFrameworkClass = System
+					.getProperty("uima.framework_impl");
+
+			if (uimaFrameworkClass != null) {
+				String saxonParserClass = uimaFrameworkClass + "_SAXParser";
+				try {
+					saxonConfig.getSaxonClassLoader().loadClass(saxonParserClass);
+					argsForSaxon.add("-x");
+					argsForSaxon.add(saxonParserClass);
+				} catch (ClassNotFoundException e) {
+					// No parser class defined
+				}
+			}
+			UIMAFramework.getLogger(THIS_CLASS).log(Level.INFO,
+					"Saxon args: " + argsForSaxon);
+
+		}
+
+		public void convertDD2Spring() throws Exception {
+			try {
+				// Set the thread classloader so that all classes are loaded from this
+				Thread.currentThread().setContextClassLoader(saxonConfig.getSaxonClassLoader());
+				Class<?> mainStartClass = null;
+				mainStartClass = Class.forName("net.sf.saxon.Transform", true,
+						saxonConfig.getSaxonClassLoader());
+				Method mainMethod = mainStartClass
+						.getMethod("main", String[].class);
+				mainMethod.invoke(null, new Object[] { argsForSaxon
+						.toArray(new String[argsForSaxon.size()]) });
+
+			} finally {
+				// Restore original classloader and remove used shutdown hook
+				Thread.currentThread().setContextClassLoader(saxonConfig.getCurrentClassLoader());
+
+			}
+		}
+
+	}
+
+	private static class SaxonJavaInterface implements SaxonInterface {
+		private SaxonInputs saxonConfig;
+
+		SaxonJavaInterface(SaxonInputs saxonConfig) {
+			this.saxonConfig = saxonConfig;
+		}
+		private void setFeature(Method setFeatureMethod, Object xmlReaderObject, String feature, boolean flag) {
+			try{
+				setFeatureMethod.invoke(xmlReaderObject, feature, flag );
+			} catch( Exception e) {
+				UIMAFramework.getLogger(THIS_CLASS).log(Level.WARNING,"XMLReader didn't recognize feature "+feature);
+			}
+		}
+		private void configure(Object xmlReaderObject) throws Exception {
+			Class<?> xmlReaderClass = Class.forName("org.xml.sax.XMLReader",
+					true, saxonConfig.getSaxonClassLoader());
+			Method setFeatureMethod = xmlReaderClass.getMethod("setFeature",
+					new Class[] { String.class, boolean.class });
+			setFeature(setFeatureMethod,xmlReaderObject,"http://xml.org/sax/features/external-general-entities", false);
+			setFeature(setFeatureMethod,xmlReaderObject,"http://xml.org/sax/features/external-parameter-entities", false);
+			setFeature(setFeatureMethod,xmlReaderObject,"http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+			setFeature(setFeatureMethod,xmlReaderObject,"http://apache.org/xml/features/disallow-doctype-decl", true);
+		}
+
+		private void beforeProcess() {
+			/* *********************************************************************************** */
+			/*
+			 * The following properties are required by Saxon. Dont remove these
+			 * settings
+			 */
+			/* *********************************************************************************** */
+
+			System.setProperty("javax.xml.transform.TransformerFactory",
+					"net.sf.saxon.TransformerFactoryImpl");
+
+		}
+
+		private void afterProcess() {
+			/* *********************************************************************************** */
+			/*
+			 * Don't remove both clearProperty() calls below. Downstream parsers
+			 * may get confused.
+			 */
+			/* *********************************************************************************** */
+			System.clearProperty("javax.xml.parsers.SAXParserFactory");
+			System.clearProperty("javax.xml.transform.TransformerFactory");
+			/* *********************************************************************************** */
+
+		}
+
+		public void convertDD2Spring() throws Exception {
+			beforeProcess();
+			BufferedWriter writer = null;
+			try {
+				// Set the thread classloader so that all classes are loaded from this
+				Thread.currentThread().setContextClassLoader(saxonConfig.getSaxonClassLoader());
+
+				Class<?> configClass = Class.forName(
+						"net.sf.saxon.Configuration", true, saxonConfig.getSaxonClassLoader());
+				Object oc = configClass.newInstance();
+				Method getXMLReaderMethod = configClass
+						.getMethod("getStyleParser");
+
+				// get Saxon xml parser
+				Object xmlReaderObject = getXMLReaderMethod.invoke(oc);
+				configure(xmlReaderObject);
+				StringWriter out = new StringWriter();
+
+				//TransformerFactory tFactory = TransformerFactory.newInstance();
+				TransformerFactory tFactory = 
+					XMLUtils.createSaxTransformerFactory();
+				StreamSource xslSource = new StreamSource(new File(
+						saxonConfig.getXSLTPath()));
+				StreamResult xmlResult = new StreamResult(out);
+				Transformer transformer = tFactory.newTransformer(xslSource);
+				// Need an absolute file path for the dd. This is fed to
+				// InputSource below
+				File ddAbsFilePath = new File(saxonConfig.getDDFilePath());
+				// System.out.println("DD:"+ddAbsFilePath.getAbsolutePath());
+				// Must be URI otherwise the transform fails on windows with
+				// DynamicError. 
+				SAXSource source = new SAXSource(new InputSource(
+						ddAbsFilePath.toURI().toString())); 
+
+				source.setXMLReader((XMLReader) xmlReaderObject);
+
+				transformer.transform(source, xmlResult);
+				// Save transformed DD for loading into Spring Framework
+				writer = new BufferedWriter(new FileWriter(
+						saxonConfig.getSpringFilePath()));
+				writer.write(out.toString());
+				
+				if ( UIMAFramework
+					.getLogger(THIS_CLASS)
+					.isLoggable(Level.FINEST) ) {
+					System.out.println("Finished Writing to temp file:"
+							+ saxonConfig.getSpringFilePath().getAbsolutePath());
+					String result = out.toString();
+					System.out.println(result);
+
+				}
+
+			} finally {
+				if ( writer != null ) {
+					try {
+						writer.close();
+					} catch(Exception e){}
+				}
+
+				afterProcess();
+				// Restore original classloader and remove used shutdown hook
+				Thread.currentThread().setContextClassLoader(saxonConfig.getCurrentClassLoader());
+
+			}
+
+		}
 
+	}
 }

Modified: uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/resources/jms_adapter_messages.properties
URL: http://svn.apache.org/viewvc/uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/resources/jms_adapter_messages.properties?rev=1849402&r1=1849401&r2=1849402&view=diff
==============================================================================
--- uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/resources/jms_adapter_messages.properties (original)
+++ uima/uv3/uima-as-v3/trunk/uimaj-as-jms/src/main/resources/jms_adapter_messages.properties Thu Dec 20 14:51:16 2018
@@ -247,4 +247,10 @@ UIMAJMS_received_service_info_FINEST = R
 UIMAJMS_debug_msg__FINEST={0}
 UIMAJMS_temp_destination_not_available_retrying__INFO=Service:{0} Unable to refresh temp destination - retrying in {1} seconds until success ...
 UIMAJMS_temp_destination_available__INFO=Service:{0} succesfully refreshed temp destination:{1} - FreeCas Queue:{2}
-UIMAJMS_client_connection_retry__INFO=UIMA-AS Client Unable to Connect to Broker:{0} - Retrying Until Success ...
\ No newline at end of file
+UIMAJMS_client_connection_retry__INFO=UIMA-AS Client Unable to Connect to Broker:{0} - Retrying Until Success ...
+UIMAJMS_TARGET_LISTENER__INFO=Target Listener with Selector {0} has been Started - Controller: {1}
+UIMAJMS_MSG_INTERCEPTOR__FINEST=Service: {0} Listener  recv'd msg - Priority: {1} Selector: {2}
+UIMAJMS_STOP_DISPATCH_THREAD_INFO=Stopping Dispatch Thread
+UIMAJMS_START_DISPATCH_THREAD_INFO=Starting Dispatch Thread
+UIMAJMS_EXIT_DISPATCH_THREAD_INFO=Exiting Dispatch Thread
+