diff --git a/org.eclipse.scanning.example/src/org/eclipse/scanning/example/malcolm/AbstractEPICSv4Device.java b/org.eclipse.scanning.example/src/org/eclipse/scanning/example/malcolm/AbstractEPICSv4Device.java index 8f2f37437a..d020515d43 100644 --- a/org.eclipse.scanning.example/src/org/eclipse/scanning/example/malcolm/AbstractEPICSv4Device.java +++ b/org.eclipse.scanning.example/src/org/eclipse/scanning/example/malcolm/AbstractEPICSv4Device.java @@ -1,13 +1,18 @@ package org.eclipse.scanning.example.malcolm; +import java.io.PrintStream; +import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.CountDownLatch; import org.epics.pvaccess.server.ServerContext; -import org.epics.pvaccess.server.impl.remote.ServerContextImpl; import org.epics.pvdata.pv.PVStructure; import org.epics.pvdatabase.PVDatabase; import org.epics.pvdatabase.PVDatabaseFactory; +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This class creates an Epics V4 service, that listens for connections and handles RPC, GET, PUT etc. The modelled @@ -23,6 +28,7 @@ public abstract class AbstractEPICSv4Device implements IEPICSv4Device { protected static int traceLevel = 0; protected final CountDownLatch latch = new CountDownLatch(1); protected DummyMalcolmRecord pvRecord = null; + private static final Logger logger = LoggerFactory.getLogger(AbstractEPICSv4Device.class); public AbstractEPICSv4Device(String deviceName) { recordName = deviceName; @@ -49,8 +55,8 @@ public void start() throws Exception { pvRecord = DummyMalcolmRecord.create(recordName); pvRecord.setTraceLevel(traceLevel); master.addRecord(pvRecord); - ServerContext context = ServerContextImpl.startPVAServer(getPvaProviderName(), 0, true, - System.out); + ServerContext context = startPvaServerWithReflection(getPvaProviderName(), 0, true, System.out); + logger.info("PVA Server Started"); latch.await(); master.removeRecord(pvRecord); context.destroy(); @@ -58,4 +64,36 @@ public void start() throws Exception { protected abstract String getPvaProviderName(); + + // TODO replace this once there is a solution to https://github.com/epics-base/epicsCoreJava/issues/100 + /** + * Since Tycho runs in OSGi it cannot see internal class from EpicsV4: + * {@code org.epics.pvaccess.server.impl.remote.ServerContextImpl} + *

+ * The Epics library currently provides no other exported API mechanism to + * start a PVA server apart from ServerFactory.create() but this is not good + * for tests as there is no way to stop the created server. + *

+ * This workaround uses reflection to call the method and return the result as a + * ServerContext interface object which is from an exported package. + *

+ * Keep checking the issue + * for solution so this can be removed. + */ + private ServerContext startPvaServerWithReflection(String providerNames, int timeToRun, + boolean runInSeparateThread, PrintStream printInfoStream) throws Exception { + String implClassName = "org.epics.pvaccess.server.impl.remote.ServerContextImpl"; + Class implClass; + Bundle bundle = FrameworkUtil.getBundle(ServerContext.class); + if (bundle != null) { + implClass = bundle.loadClass(implClassName); + } else { + implClass = Class.forName(implClassName); + } + Method startPvaMethod = implClass.getMethod("startPVAServer", String.class, int.class, boolean.class, + PrintStream.class); + return (ServerContext) startPvaMethod.invoke(null, providerNames, timeToRun, runInSeparateThread, + printInfoStream); + } + } diff --git a/org.eclipse.scanning.test/pom.xml b/org.eclipse.scanning.test/pom.xml index ed0ce43531..74c6f32b34 100644 --- a/org.eclipse.scanning.test/pom.xml +++ b/org.eclipse.scanning.test/pom.xml @@ -40,9 +40,6 @@ ${tycho.version} - - ExampleMalcolmDeviceTest - MalcolmEpicsV4ConnectorTest PseudoSpringParserTest