You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by cw...@apache.org on 2019/05/22 15:22:11 UTC

svn commit: r1859731 - in /uima/uima-ducc/trunk: uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/ uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/utils/ uima-ducc-pullservice/src/mai...

Author: cwiklik
Date: Wed May 22 15:22:10 2019
New Revision: 1859731

URL: http://svn.apache.org/viewvc?rev=1859731&view=rev
Log:
UIMA-6040 modified uima JP to use classpath separation. User code runs in System classloader whereas ducc runs fenced in a custom classloader

Modified:
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/AbstractServiceProcessor.java
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/UimaServiceProcessor.java
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/utils/UimaMetricsGenerator.java
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/protocol/builtin/DefaultServiceProtocolHandler.java
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitErrorHandlingTestSuite.java
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitPullServiceTestCase.java
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/wrapper/JUnitServiceWrapperTestCase.java
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitProtocolHandlerTestCase.java
    uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitTransportTestCase.java
    uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/DuccJobService.java
    uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/PullServiceWrapper.java

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/AbstractServiceProcessor.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/AbstractServiceProcessor.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/AbstractServiceProcessor.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/AbstractServiceProcessor.java Wed May 22 15:22:10 2019
@@ -29,6 +29,9 @@ import org.apache.uima.util.Level;
 import org.apache.uima.util.Logger;
 
 public class AbstractServiceProcessor {
+	
+	public static final String CLASSPATH_SWITCH_PROP = "ClasspathSwitch";
+
 	// Map to store DuccUimaSerializer instances. Each has affinity to a thread
 	protected Map<Long, UimaSerializer> serializerMap = new HashMap<>();
 	protected AtomicLong errorCount = new AtomicLong();

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/UimaServiceProcessor.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/UimaServiceProcessor.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/UimaServiceProcessor.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/UimaServiceProcessor.java Wed May 22 15:22:10 2019
@@ -19,77 +19,65 @@
 package org.apache.uima.ducc.ps.service.processor.uima;
 
 import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Objects;
 import java.util.Properties;
-//import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.uima.UIMAFramework;
 import org.apache.uima.analysis_engine.AnalysisEngine;
-import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData;
-import org.apache.uima.cas.CAS;
 import org.apache.uima.ducc.ps.service.IServiceState;
 import org.apache.uima.ducc.ps.service.ServiceConfiguration;
-//import org.apache.uima.ducc.ps.service.dgen.DeployableGeneration;
 import org.apache.uima.ducc.ps.service.errors.IServiceErrorHandler;
 import org.apache.uima.ducc.ps.service.errors.IServiceErrorHandler.Action;
 import org.apache.uima.ducc.ps.service.metrics.IWindowStats;
 import org.apache.uima.ducc.ps.service.metrics.builtin.ProcessWindowStats;
-//import org.apache.uima.ducc.ps.service.jmx.JmxAEProcessInitMonitor;
 import org.apache.uima.ducc.ps.service.monitor.IServiceMonitor;
 import org.apache.uima.ducc.ps.service.monitor.builtin.RemoteStateObserver;
 import org.apache.uima.ducc.ps.service.processor.IProcessResult;
 import org.apache.uima.ducc.ps.service.processor.IServiceProcessor;
 import org.apache.uima.ducc.ps.service.processor.IServiceResultSerializer;
 import org.apache.uima.ducc.ps.service.processor.uima.utils.PerformanceMetrics;
-import org.apache.uima.ducc.ps.service.processor.uima.utils.UimaMetricsGenerator;
 import org.apache.uima.ducc.ps.service.processor.uima.utils.UimaResultDefaultSerializer;
 import org.apache.uima.ducc.ps.service.utils.UimaSerializer;
 import org.apache.uima.ducc.ps.service.utils.UimaUtils;
-import org.apache.uima.resource.Resource;
-import org.apache.uima.resource.ResourceInitializationException;
-import org.apache.uima.resource.ResourceManager;
 import org.apache.uima.resource.ResourceSpecifier;
-import org.apache.uima.util.CasPool;
 import org.apache.uima.util.Level;
 import org.apache.uima.util.Logger;
 import org.apache.uima.util.XMLInputSource;
 
 public class UimaServiceProcessor extends AbstractServiceProcessor implements IServiceProcessor {
+	public static final String AE_NAME = "AeName";
+	public static final String AE_CONTEXT = "AeContext";
+	public static final String AE_ANALYSIS_TIME = "AeAnalysisTime";
+	public static final String AE_CAS_PROCESSED = "AeProcessedCasCount";
+
 	public static final String IMPORT_BY_NAME_PREFIX = "*importByName:";
+	private static String M_PROCESS="process";
+	private static String M_STOP="stop";
+	private static String M_INITIALIZE="initialize";
+
 	Logger logger = UIMAFramework.getLogger(UimaServiceProcessor.class);
-   // Map to store DuccUimaSerializer instances. Each has affinity to a thread
 	private IServiceResultSerializer resultSerializer;
 	// stores AE instance pinned to a thread
-	private ThreadLocal<AnalysisEngine> threadLocal = 
-			new ThreadLocal<> ();
+	private ThreadLocal<AnalysisEngine> threadLocal = new ThreadLocal<> ();
     private ReentrantLock initStateLock = new ReentrantLock();
     private boolean sendInitializingState = true;
-	private ResourceManager rm = 
-			UIMAFramework.newDefaultResourceManager();;
-    private CasPool casPool = null;
 	private int scaleout=1;
     private String analysisEngineDescriptor;
-    private AnalysisEngineMetaData analysisEngineMetadata;
-	// Platform MBean server if one is available (Java 1.5 only)
-	private static Object platformMBeanServer;
-	private ServiceConfiguration serviceConfiguration;
+ 	private ServiceConfiguration serviceConfiguration;
 	private IServiceMonitor monitor;
 	private AtomicInteger numberOfInitializedThreads = new AtomicInteger();
 	private IServiceErrorHandler errorHandler;
-	
-	static {
-		// try to get platform MBean Server (Java 1.5 only)
-		try {
-			Class<?> managementFactory = Class.forName("java.lang.management.ManagementFactory");
-			Method getPlatformMBeanServer = managementFactory.getMethod("getPlatformMBeanServer", new Class[0]);
-			platformMBeanServer = getPlatformMBeanServer.invoke(null, (Object[]) null);
-		} catch (Exception e) {
-			platformMBeanServer = null;
-		}
-	}	
+	private Method processMethod;
+	private Method stopMethod;
+	private Object processorInstance;
+	private UimaDelegator uimaDelegator=null;
 	
 	public UimaServiceProcessor(String analysisEngineDescriptor) {
 		this(analysisEngineDescriptor,  new UimaResultDefaultSerializer(), new ServiceConfiguration());
@@ -135,6 +123,17 @@ public class UimaServiceProcessor extend
 	public int getScaleout() {
 		return scaleout;
 	}
+	public void dump(ClassLoader cl, int numLevels) {
+		int n = 0;
+		for (URLClassLoader ucl = (URLClassLoader) cl; ucl != null
+				&& ++n <= numLevels; ucl = (URLClassLoader) ucl.getParent()) {
+			System.out.println("Class-loader " + n + " has "
+					+ ucl.getURLs().length + " urls:");
+			for (URL u : ucl.getURLs()) {
+				System.out.println("  " + u);
+			}
+		}
+	}
 
 	@Override
 	public void initialize() {
@@ -157,41 +156,72 @@ public class UimaServiceProcessor extend
 		} finally {
 			initStateLock.unlock();
 		}
+		// every process thread has its own uima deserializer
+		if (serviceConfiguration.getJpType() != null) {
+		  serializerMap.put(Thread.currentThread().getId(), new UimaSerializer());
+		}
+        // *****************************************
+		// SWITCHING CLASSLOADER
+        // *****************************************
+        // Ducc code is loaded from jars identified by -Dducc.deploy.DuccClasspath. The jars
+		// are loaded into a custom classloader.
+		
+		// User code is loaded from jars in the System Classloader. We must switch classloaders
+		// if we want to access user code. When user code is done, we restore Ducc classloader to be able
+		// to access Ducc classes.
+		
+	   	// Save current context cl and inject System classloader as
+		// a context cl before calling user code. 
+		ClassLoader savedCL = Thread.currentThread().getContextClassLoader();
+		boolean failed = false;
+		try {
+			
+			// For junit testing dont use classpath switching. 
+			if ( Objects.isNull(System.getProperty(CLASSPATH_SWITCH_PROP)) ) {
+				// Running with classpath switching 
+				Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
+				if ( logger.isLoggable(Level.FINE)) {
+					logger.log(Level.FINE,"",">>>> initialize():::Context Classloader Switch - Executing code from System Classloader");
+				}
+				// load proxy class from uima-ducc-user.jar to access uima classes. The UimaWrapper is a convenience/wrapper
+				// class so that we dont have to use reflection on Uima classes.
+				Class<?> classToLaunch = 
+						ClassLoader.getSystemClassLoader().loadClass("org.apache.uima.ducc.user.common.main.UimaWrapper");
+	
+				processorInstance = classToLaunch.newInstance();
 
+				Method initMethod = processorInstance.getClass().getMethod(M_INITIALIZE, String.class, int.class, boolean.class, ThreadLocal.class);
 
-	    HashMap<String,Object> paramsMap = new HashMap<>();
-        paramsMap.put(Resource.PARAM_RESOURCE_MANAGER, rm);
-	    paramsMap.put(AnalysisEngine.PARAM_MBEAN_SERVER, platformMBeanServer);
-	    
-		try {
-		
-			XMLInputSource is =
-					UimaUtils.getXMLInputSource(analysisEngineDescriptor);
-			String aed = is.getURL().toString();
-			ResourceSpecifier rSpecifier =
-			    UimaUtils.getResourceSpecifier(aed);
-
-			AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(rSpecifier,
-					paramsMap);
-			// pin AE instance to this thread
-			threadLocal.set(ae);
-
-			synchronized(UimaServiceProcessor.class) {
-		    	if ( casPool == null ) {
-		    		initializeCasPool(ae.getAnalysisEngineMetaData());
-		    	}
-			}
-			// every process thread has its own uima deserializer
-			if (serviceConfiguration.getJpType() != null) {
-			  serializerMap.put(Thread.currentThread().getId(), new UimaSerializer());
+				processMethod = processorInstance.getClass().getMethod(M_PROCESS, new Class[] {String.class, ThreadLocal.class});
+				
+				stopMethod = processorInstance.getClass().getMethod(M_STOP, ThreadLocal.class);
+ 
+				// initialize AE via UimaWrapper
+				initMethod.invoke(processorInstance, analysisEngineDescriptor, scaleout, (serviceConfiguration.getJpType() != null), threadLocal);
+				
+			} else {
+				// no classloader switching for junit tests
+				ResourceSpecifier rSpecifier = getResourceSpecifier(analysisEngineDescriptor);
+				// The UimaDelegator is a convenience class which wraps Uima classes
+				uimaDelegator = new UimaDelegator();
+				uimaDelegator.initialize(rSpecifier, scaleout, (serviceConfiguration.getJpType() != null), threadLocal);
 			}
+			
 
 		} catch (Exception e) {
 			logger.log(Level.WARNING, null, e);
-			monitor.onStateChange(IServiceState.State.FailedInitialization.toString(), new Properties());
+			failed = true;
 			throw new RuntimeException(e);
 
-		} 
+		}  finally {
+			Thread.currentThread().setContextClassLoader(savedCL);
+			if ( logger.isLoggable(Level.FINE)) {
+				logger.log(Level.FINE,"",">>>> initialize():::Context Classloader Switch - Restored Ducc Classloader");
+			}
+			if ( failed ) {
+				monitor.onStateChange(IServiceState.State.FailedInitialization.toString(), new Properties());
+			}
+		}
 		if ( logger.isLoggable(Level.INFO)) {
 			logger.log(Level.INFO, "Process Thread:"+ Thread.currentThread().getName()+" Done Initializing AE");
 			
@@ -201,52 +231,60 @@ public class UimaServiceProcessor extend
 			monitor.onStateChange(IServiceState.State.Running.toString(), new Properties());
 		}
 	}
+	private ResourceSpecifier getResourceSpecifier(String analysisEngineDescriptor) throws Exception {
+		XMLInputSource is =
+				UimaUtils.getXMLInputSource(analysisEngineDescriptor);
+		String aed = is.getURL().toString();
+		return  UimaUtils.getResourceSpecifier(aed);
 
-	private void initializeCasPool(AnalysisEngineMetaData aeMeta) throws ResourceInitializationException {
-		Properties props = new Properties();
-		props.setProperty(UIMAFramework.CAS_INITIAL_HEAP_SIZE, "1000");
-
-		analysisEngineMetadata = aeMeta;
-		casPool = new CasPool(scaleout, analysisEngineMetadata, rm);
 	}
-
+	@SuppressWarnings("unchecked")
 	@Override
 	public IProcessResult process(String serializedTask) {
-		AnalysisEngine ae = null;
+	   	// save current context cl and inject System classloader as
+		// a context cl before calling user code. 
+		ClassLoader savedCL = Thread.currentThread().getContextClassLoader();
+		Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
+		if ( logger.isLoggable(Level.FINE)) {
+			logger.log(Level.FINE,"",">>>> process():::Context Classloader Switch - Executing code from System Classloader");
+		}
 
-		CAS cas = casPool.getCas();
 		IProcessResult result;
 		
 		try {
-		  // DUCC JP  services are given a serialized CAS ... others just the doc-text for a CAS
-			if (serviceConfiguration.getJpType() != null) {
-			  getUimaSerializer().deserializeCasFromXmi(serializedTask, cas);
+			
+			// The clients expect metrics in PeformanceMetrics class
+			List<PerformanceMetrics> casMetrics;
+
+			// JUnit tests currently dont support CL switching so don't use
+			// reflection 
+			if ( Objects.isNull(System.getProperty(CLASSPATH_SWITCH_PROP)) ) {
+				casMetrics = new ArrayList<>();
+				// Use basic data structures for returning performance metrics from 
+				// a processor process(). The PerformanceMetrics class is not 
+				// visible in the code packaged in uima-ducc-user.jar so return
+				// metrics in Properties object for each AE.
+				List<Properties> metrics;
+
+				// *****************************************************
+				// PROCESS
+				// *****************************************************
+				metrics = (List<Properties>) processMethod.invoke(processorInstance, serializedTask, threadLocal);
+				for( Properties p : metrics ) {
+					// there is Properties object for each AE, so create an
+					// instance of PerformanceMetrics and initialize it
+					PerformanceMetrics pm = 
+							new PerformanceMetrics(p.getProperty(AE_NAME), 
+									p.getProperty(AE_CONTEXT),
+									Long.valueOf(p.getProperty(AE_ANALYSIS_TIME)), 
+									Long.valueOf(p.getProperty(AE_CAS_PROCESSED)));
+					casMetrics.add(pm);
+				}
 			} else {
-			  cas.setDocumentText(serializedTask);
-			  cas.setDocumentLanguage("en");
+				// for JUnit tests call delegator which does not use reflection
+				casMetrics = uimaDelegator.process(serializedTask, threadLocal);
 			}
-			// check out AE instance pinned to this thread
-			ae = threadLocal.get();
-			// get AE metrics before calling process(). Needed for
-			// computing a delta
-			List<PerformanceMetrics> beforeAnalysis = 
-					UimaMetricsGenerator.get(ae);
-			
-			// *****************************************************
-			// PROCESS
-			// *****************************************************
-			ae.process(cas);
-			
-			// *****************************************************
-			// No exception in process() , fetch metrics 
-			// *****************************************************
-			List<PerformanceMetrics> afterAnalysis = 
-					UimaMetricsGenerator.get(ae);
-
-			// get the delta
-			List<PerformanceMetrics> casMetrics = 
-					UimaMetricsGenerator.getDelta( afterAnalysis, beforeAnalysis);
-			
+
 			successCount.incrementAndGet();
 			errorCountSinceLastSuccess.set(0);
 			return new UimaProcessResult(resultSerializer.serialize(casMetrics));
@@ -262,9 +300,9 @@ public class UimaServiceProcessor extend
 			result = new UimaProcessResult(e, action);
 			return result;
  		} finally {
-			
-			if (cas != null) {
-				casPool.releaseCas(cas);
+			Thread.currentThread().setContextClassLoader(savedCL);
+			if ( logger.isLoggable(Level.FINE)) {
+				logger.log(Level.FINE,"",">>>> process():::Context Classloader Switch - Restored Ducc Classloader");
 			}
 		}
 	}
@@ -277,40 +315,31 @@ public class UimaServiceProcessor extend
 	@Override
 	public void stop() {
 		logger.log(Level.INFO,this.getClass().getName()+" stop() called");
+	   	// save current context cl and inject System classloader as
+		// a context cl before calling user code. This is done in 
+		// user code needs to load resources 
+		ClassLoader savedCL = Thread.currentThread().getContextClassLoader();
+		Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
+		if ( logger.isLoggable(Level.FINE)) {
+			logger.log(Level.FINE,"",">>>> stop():::Context Classloader Switch - Executing code from System Classloader");
+		}
 		try {
-			AnalysisEngine ae = threadLocal.get();
-			if ( ae != null ) {
-				ae.destroy();
+			if ( Objects.isNull(System.getProperty(CLASSPATH_SWITCH_PROP)) ) {
+				stopMethod.invoke(processorInstance, threadLocal);
+			} else {
+				uimaDelegator.stop(threadLocal);
 			}
 			super.stop();
 
 		} catch( Exception e) {
 			logger.log(Level.WARNING, "stop", e);
-		} 
+		} finally {
+			Thread.currentThread().setContextClassLoader(savedCL);
+			if ( logger.isLoggable(Level.FINE)) {
+				logger.log(Level.FINE,"",">>>> stop():::Context Classloader Switch - Restored Ducc Classloader");
+			}
+		}
 	}
-	/*
-	  // Build just an AE from parts and return the filename
-	  // (DD's are converted in UimaAsProcessContainer.parseDD)
-	  protected String buildDeployable(ServiceConfiguration serviceConfiguration) {
-		  try {
-			  String jpType = serviceConfiguration.getJpType();//getPropertyString("ducc.deploy.JpType");
-			  if(jpType == null) {
-				  jpType = "uima";
-			  }
-			  if(jpType.equalsIgnoreCase("uima-as")) {
-				  logger.log(Level.WARNING,"ERROR - should not be called for type="+jpType);
-			  }
-			  else {
-				  DeployableGeneration dg = new DeployableGeneration(serviceConfiguration);
-				  return dg.generate(true);
-			  }
-		  }
-		  catch(Exception e) {
-			  e.printStackTrace();
-			  logger.log(Level.WARNING,"buildDeployable",e);
-		  }
-		  return null;
-	  }
-*/
+
 }
 

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/utils/UimaMetricsGenerator.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/utils/UimaMetricsGenerator.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/utils/UimaMetricsGenerator.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/processor/uima/utils/UimaMetricsGenerator.java Wed May 22 15:22:10 2019
@@ -66,7 +66,37 @@ public class UimaMetricsGenerator {
 		}
 		return analysisManagementObjects;
 	}
-		
+	   public static List<PerformanceMetrics> get(AnalysisEngineManagement aem)
+			throws Exception {
+		List<PerformanceMetrics> analysisManagementObjects = new ArrayList<PerformanceMetrics>();
+		synchronized(UimaMetricsGenerator.class) {
+			// Fetch AE's management information that includes per component
+			// performance stats
+			// These stats are internally maintained in a Map. If the AE is an
+			// aggregate
+			// the Map will contain AnalysisEngineManagement instance for each AE.
+			//AnalysisEngineManagement aem = ae.getManagementInterface();
+			if (aem.getComponents().size() > 0) {
+				// Flatten the hierarchy by recursively (if this AE is an aggregate)
+				// extracting
+				// primitive AE's AnalysisEngineManagement instance and placing it
+				// in
+				// afterAnalysisManagementObjects List.
+				getLeafManagementObjects(aem, analysisManagementObjects);
+				// System.out.println("-----------------Unique1:"+aem.getUniqueMBeanName());
+				// System.out.println("-----------------Simple1:"+aem.getName());
+			} else {
+				String path = produceUniqueName(aem);
+//				 System.out.println(Thread.currentThread().getId()+" -----------------Unique2:"+aem.getUniqueMBeanName());
+//				 System.out.println(Thread.currentThread().getId()+" -----------------Simple2:"+aem.getName());
+//				 System.out.println(Thread.currentThread().getId()+" -----------------Path:"+path);
+				analysisManagementObjects.add(deepCopyMetrics(aem, path));
+
+			}
+			
+		}
+		return analysisManagementObjects;
+	}	
 	/**
 	 * Recursively
 	 * 

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/protocol/builtin/DefaultServiceProtocolHandler.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/protocol/builtin/DefaultServiceProtocolHandler.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/protocol/builtin/DefaultServiceProtocolHandler.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/main/java/org/apache/uima/ducc/ps/service/protocol/builtin/DefaultServiceProtocolHandler.java Wed May 22 15:22:10 2019
@@ -214,53 +214,48 @@ public class DefaultServiceProtocolHandl
    * @throws Exception
    */
   private IMetaTaskTransaction callGet(IMetaTaskTransaction transaction) throws Exception {
-    transaction.setType(Type.Get);
-    if (logger.isLoggable(Level.FINE)) {
-      logger.log(Level.FINE, "ProtocolHandler calling GET");
-    }
-    IMetaTaskTransaction metaTransaction = null;
+	  transaction.setType(Type.Get);
+	  if (logger.isLoggable(Level.FINE)) {
+		  logger.log(Level.FINE, "ProtocolHandler calling GET");
+	  }
+	  IMetaTaskTransaction metaTransaction = null;
 
-    try {
-        while (running) {
-            metaTransaction = sendAndReceive(transaction);
-            if (metaTransaction.getMetaTask() != null
-                    && metaTransaction.getMetaTask().getUserSpaceTask() != null) {
-              return metaTransaction;
-            }
+	  while (running) {
+		  metaTransaction = sendAndReceive(transaction);
+		  if (metaTransaction.getMetaTask() != null
+				  && metaTransaction.getMetaTask().getUserSpaceTask() != null) {
+			  return metaTransaction;
+		  }
 
-            // If the first thread to get the lock poll for work and unlock when work found
-            // If don't immediately get the lock then wait for the lock to be released when
-            // work becomes available,
-            // and immediately release the lock and loop back to retry
-            boolean firstLocker = noWorkLock.tryLock();
-            if (!firstLocker) {
-              noWorkLock.lock();
-              noWorkLock.unlock();
-              continue;
-            }
+		  // If the first thread to get the lock poll for work and unlock when work found
+		  // If don't immediately get the lock then wait for the lock to be released when
+		  // work becomes available,
+		  // and immediately release the lock and loop back to retry
+		  boolean firstLocker = noWorkLock.tryLock();
+		  if (!firstLocker) {
+			  noWorkLock.lock();
+			  noWorkLock.unlock();
+			  continue;
+		  }
 
-            // If the first one here hold the lock and sleep before retrying
-            if (logger.isLoggable(Level.INFO)) {
-              logger.log(Level.INFO, "Driver is out of tasks - waiting for "
-                      + noTaskStrategy.getWaitTimeInMillis() + "ms before trying again ");
-            }
-            while (running) {
-              noTaskStrategy.handleNoTaskSupplied();
-              metaTransaction = sendAndReceive(transaction);
-              if (metaTransaction.getMetaTask() != null
-                      && metaTransaction.getMetaTask().getUserSpaceTask() != null) {
-                noWorkLock.unlock();
-                return metaTransaction;
-              }
-            }
-          } 
-    } finally {
-    	if ( noWorkLock.isHeldByCurrentThread() ) {
-    		noWorkLock.unlock();
-    	}
-    }
+		  // If the first one here hold the lock and sleep before retrying
+		  if (logger.isLoggable(Level.INFO)) {
+			  logger.log(Level.INFO, "Driver is out of tasks - waiting for "
+					  + noTaskStrategy.getWaitTimeInMillis() + "ms before trying again ");
+		  }
+		  while (running) {
+			  noTaskStrategy.handleNoTaskSupplied();
+			  metaTransaction = sendAndReceive(transaction);
+			  if (metaTransaction.getMetaTask() != null
+					  && metaTransaction.getMetaTask().getUserSpaceTask() != null) {
+				  noWorkLock.unlock();
+				  return metaTransaction;
+			  }
+		  }
+	  } 
+	  noWorkLock.unlock();
 
-    return metaTransaction; // When shutting down
+	  return metaTransaction; // When shutting down
   }
 
   /**

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitErrorHandlingTestSuite.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitErrorHandlingTestSuite.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitErrorHandlingTestSuite.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitErrorHandlingTestSuite.java Wed May 22 15:22:10 2019
@@ -1,6 +1,9 @@
 package org.apache.uima.ducc.ps.service;
 
 import org.apache.uima.ducc.ps.service.errors.builtin.WindowBasedErrorHandler;
+import org.apache.uima.ducc.ps.service.processor.uima.AbstractServiceProcessor;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 import junit.framework.Assert;
@@ -30,7 +33,14 @@ public class JunitErrorHandlingTestSuite
 		
 		
 	}
-
+	  @Before
+	  public void setUp() throws Exception {
+		  System.setProperty(AbstractServiceProcessor.CLASSPATH_SWITCH_PROP,"true");
+	  }
+	  @After
+	  public void tearDown() throws Exception {
+		  
+	  }
 	@Test
 	public void testNoWindow() throws Exception {
 		// fails on 3rd error 

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitPullServiceTestCase.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitPullServiceTestCase.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitPullServiceTestCase.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/JunitPullServiceTestCase.java Wed May 22 15:22:10 2019
@@ -27,7 +27,10 @@ import org.apache.uima.ducc.ps.Client;
 import org.apache.uima.ducc.ps.service.builders.PullServiceStepBuilder;
 import org.apache.uima.ducc.ps.service.errors.ServiceInitializationException;
 import org.apache.uima.ducc.ps.service.processor.IServiceProcessor;
+import org.apache.uima.ducc.ps.service.processor.uima.AbstractServiceProcessor;
 import org.apache.uima.ducc.ps.service.processor.uima.UimaServiceProcessor;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 public class JunitPullServiceTestCase extends Client {
@@ -42,6 +45,14 @@ public class JunitPullServiceTestCase ex
     System.setProperty("ducc.service.init.delay", "3000");
   }
 
+  @Before
+  public void setUp() throws Exception {
+	  System.setProperty(AbstractServiceProcessor.CLASSPATH_SWITCH_PROP,"true");
+  }
+  @After
+  public void tearDown() throws Exception {
+	  
+  }
   @Test
   public void testPullService() throws Exception {
     System.out.println("----------------- testPullService -------------------");
@@ -292,3 +303,4 @@ public class JunitPullServiceTestCase ex
   }
 
 }
+

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/wrapper/JUnitServiceWrapperTestCase.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/wrapper/JUnitServiceWrapperTestCase.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/wrapper/JUnitServiceWrapperTestCase.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/service/wrapper/JUnitServiceWrapperTestCase.java Wed May 22 15:22:10 2019
@@ -26,6 +26,9 @@ import org.apache.uima.ducc.ps.Client;
 import org.apache.uima.ducc.ps.StateMonitor;
 import org.apache.uima.ducc.ps.service.errors.ServiceInitializationException;
 import org.apache.uima.ducc.ps.service.main.ServiceWrapper;
+import org.apache.uima.ducc.ps.service.processor.uima.AbstractServiceProcessor;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 public class JUnitServiceWrapperTestCase extends Client {
@@ -35,7 +38,14 @@ public class JUnitServiceWrapperTestCase
     // sending READY to a monitor
     System.setProperty("ducc.service.init.delay", "3000");
   }
-
+  @Before
+  public void setUp() throws Exception {
+	 System.setProperty(AbstractServiceProcessor.CLASSPATH_SWITCH_PROP,"true");
+  }
+  @After
+  public void tearDown() throws Exception {
+	  
+  }
   @Test
   public void testPullServiceWrapperNoTask() throws Exception {
     // make client return null task in response to GET

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitProtocolHandlerTestCase.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitProtocolHandlerTestCase.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitProtocolHandlerTestCase.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitProtocolHandlerTestCase.java Wed May 22 15:22:10 2019
@@ -30,6 +30,7 @@ import org.apache.uima.ducc.ps.service.I
 import org.apache.uima.ducc.ps.service.errors.ServiceException;
 import org.apache.uima.ducc.ps.service.errors.ServiceInitializationException;
 import org.apache.uima.ducc.ps.service.processor.IServiceProcessor;
+import org.apache.uima.ducc.ps.service.processor.uima.AbstractServiceProcessor;
 import org.apache.uima.ducc.ps.service.processor.uima.UimaServiceProcessor;
 import org.apache.uima.ducc.ps.service.protocol.INoTaskAvailableStrategy;
 import org.apache.uima.ducc.ps.service.protocol.IServiceProtocolHandler;
@@ -41,12 +42,21 @@ import org.apache.uima.ducc.ps.service.t
 import org.apache.uima.ducc.ps.service.transport.http.HttpServiceTransport;
 import org.apache.uima.ducc.ps.service.transport.target.HttpTargetURI;
 //import org.junit.Test;
+import org.junit.After;
+import org.junit.Before;
 
 public class JunitProtocolHandlerTestCase extends Client {
 
 	CountDownLatch threadsReady;
 	CountDownLatch stopLatch;
-	
+	  @Before
+	  public void setUp() throws Exception {
+		  System.setProperty(AbstractServiceProcessor.CLASSPATH_SWITCH_PROP,"true");
+	  }
+	  @After
+	  public void tearDown() throws Exception {
+		  
+	  }
 	private IServiceTransport initializeTransport() throws Exception {
 		int scaleout = 1;
     	ITargetURI targetUrl = new HttpTargetURI("http://localhost:"+super.getPort()+"/"+super.getApp());

Modified: uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitTransportTestCase.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitTransportTestCase.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitTransportTestCase.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-pullservice/src/test/java/org/apache/uima/ducc/ps/transport/JunitTransportTestCase.java Wed May 22 15:22:10 2019
@@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletRes
 import org.apache.uima.ducc.ps.net.iface.IMetaTaskTransaction;
 import org.apache.uima.ducc.ps.net.impl.MetaTask;
 import org.apache.uima.ducc.ps.net.impl.MetaTaskTransaction;
+import org.apache.uima.ducc.ps.service.processor.uima.AbstractServiceProcessor;
 import org.apache.uima.ducc.ps.service.registry.DefaultRegistryClient;
 import org.apache.uima.ducc.ps.service.transport.ITargetURI;
 import org.apache.uima.ducc.ps.service.transport.XStreamUtils;
@@ -65,7 +66,14 @@ public class JunitTransportTestCase {
       return new HashMap<Long, XStream>();
     }
   };
-
+  @Before
+  public void setUp() throws Exception {
+	  System.setProperty(AbstractServiceProcessor.CLASSPATH_SWITCH_PROP,"true");
+  }
+  @After
+  public void tearDown() throws Exception {
+	  
+  }
   private int getJettyPort() {
     while (true) {
       ServerSocket socket = null;

Modified: uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/DuccJobService.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/DuccJobService.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/DuccJobService.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/DuccJobService.java Wed May 22 15:22:10 2019
@@ -19,8 +19,6 @@
 package org.apache.uima.ducc.user.common.main;
 
 import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -40,7 +38,7 @@ public class DuccJobService {
 	private Investment investment = null;
 	private Logger logger = Logger.getLogger(DuccJobService.class.getName());
 	private IServiceWrapper service = null;
-	 
+
 	public static URLClassLoader create(String classPath)
 			throws MalformedURLException {
 		return create(classPath.split(":"));
@@ -87,71 +85,15 @@ public class DuccJobService {
 			}
 		}
 	}
-	private void addUrlsToSystemLoader(URL[] urls) throws IOException {
-		URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader
-				.getSystemClassLoader();
-		try {
-			Method method = URLClassLoader.class.getDeclaredMethod("addURL",
-					new Class[] { URL.class });
-			method.setAccessible(true); // is normally "protected"
-			for (URL url : urls) {
-				method.invoke(systemClassLoader, new Object[] { url });
-			}
-		} catch (Throwable t) {
-			t.printStackTrace();
-			throw new IOException(
-					"Error, could not add URL to system classloader");
-		}
-	}
-	private URL[] getUrlsFromDuccClasspath(String[] duccClassPath)
-			throws MalformedURLException {
-		ArrayList<URL> urlList = new ArrayList<URL>(duccClassPath.length);
-		for (String element : duccClassPath) {
-			if (element.endsWith("*")) {
-				File dir = new File(element.substring(0, element.length() - 1));
-				File[] files = dir.listFiles(); // Will be null if missing or
-												// not a dir
-				if (files != null) {
-					for (File f : files) {
-						if (f.getName().endsWith(".jar")) {
-							urlList.add(f.toURI().toURL());
-						}
-					}
-				}
-			} else {
-				File f = new File(element);
-				if (f.exists()) {
-					urlList.add(f.toURI().toURL());
-				}
-			}
-		}
-		URL[] urls = new URL[urlList.size()];
-		return urlList.toArray(urls);
-	}
+
+
 	public void start(String[] args) throws Exception {
 		try {
 	        investment = new Investment();
 
-			// Fetch a classpath for the fenced Ducc container
-			String duccContainerClasspath = System.getProperty("ducc.deploy.DuccClasspath");
-			if ( duccContainerClasspath != null ) {
-				URL[] urls = getUrlsFromDuccClasspath(duccContainerClasspath.split(":"));
-				addUrlsToSystemLoader(urls);
-			}
-			if (System.getProperty("ducc.debug") != null) {
-				DEBUG = true;
-			}
-			if (DEBUG) {
-				dump((URLClassLoader) ClassLoader
-						.getSystemClassLoader(), 4);
-			}
 	        service = ServiceFactory.newService();
 	        service.initialize(args);
 	        service.start();
-	        
-//			HashMap<String, String> savedPropsMap = hideLoggingProperties();  // Ensure DUCC doesn't try to use the user's logging setup
-//			restoreLoggingProperties(savedPropsMap);  // May not be necessary as user's logger has been established
-
 			logger.log(Level.INFO, "<<<<<<<< Ducc Container ended");
 			
 		} catch( Throwable t) {
@@ -183,7 +125,6 @@ public class DuccJobService {
 			if (val != null) {
 				savedPropsMap.put(prop,  val);
 				System.getProperties().remove(prop);
-				//System.out.println("!!!! Saved prop " + prop + " = " + val);
 			}
 		}
 		return savedPropsMap;
@@ -192,7 +133,6 @@ public class DuccJobService {
 	public static void restoreLoggingProperties(HashMap<String,String> savedPropsMap) {
 		for (String prop : savedPropsMap.keySet()) {
 			System.setProperty(prop, savedPropsMap.get(prop));
-			//System.out.println("!!!! Restored prop " + prop + " = " + System.getProperty(prop));
 		}
 	}
 	

Modified: uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/PullServiceWrapper.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/PullServiceWrapper.java?rev=1859731&r1=1859730&r2=1859731&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/PullServiceWrapper.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-user/src/main/java/org/apache/uima/ducc/user/common/main/PullServiceWrapper.java Wed May 22 15:22:10 2019
@@ -19,6 +19,7 @@
 package org.apache.uima.ducc.user.common.main;
 
 import java.lang.reflect.Method;
+import java.net.URLClassLoader;
 
 /*
  * Implements dynamic loading of a service class, initializes its instance
@@ -29,10 +30,22 @@ public class PullServiceWrapper implemen
 
 	private Object instance = null;
 	private Class<?> duccServiceClass =  null;
+	private boolean DEBUG;
 	
 	public void initialize(String[] args) throws Exception{
-		duccServiceClass = 
-				ClassLoader.getSystemClassLoader().loadClass("org.apache.uima.ducc.ps.service.main.ServiceWrapper");
+		
+		// Fetch a classpath for the fenced Ducc container
+		String duccContainerClasspath = System.getProperty("ducc.deploy.DuccClasspath");
+		URLClassLoader ucl = DuccJobService.create(duccContainerClasspath);
+		if (System.getProperty("ducc.debug") != null) {
+			DEBUG = true;
+		}
+		if (DEBUG) {
+			DuccJobService.dump(ucl, 4);
+		}
+
+		// Load the DuccService class and find its methods of interest
+		duccServiceClass = ucl.loadClass("org.apache.uima.ducc.ps.service.main.ServiceWrapper");
 		instance = duccServiceClass.newInstance();
 		Method initMethod = duccServiceClass.getMethod("initialize", String[].class);
 		initMethod.invoke(instance, (Object) args);