001package ca.uhn.hl7v2.hoh.relay.listener; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.concurrent.Executors; 006import java.util.concurrent.ThreadFactory; 007import java.util.concurrent.atomic.AtomicInteger; 008 009import org.springframework.beans.factory.BeanNameAware; 010import org.springframework.beans.factory.DisposableBean; 011import org.springframework.beans.factory.InitializingBean; 012 013import ca.uhn.hl7v2.DefaultHapiContext; 014import ca.uhn.hl7v2.app.SimpleServer; 015import ca.uhn.hl7v2.hoh.util.Validate; 016import ca.uhn.hl7v2.llp.MinLowerLayerProtocol; 017import ca.uhn.hl7v2.parser.GenericModelClassFactory; 018import ca.uhn.hl7v2.protocol.ApplicationRouter.AppRoutingData; 019import ca.uhn.hl7v2.protocol.ReceivingApplication; 020import ca.uhn.hl7v2.util.StandardSocketFactory; 021 022public class RelayMllpListener implements InitializingBean, DisposableBean, IRelayListener, BeanNameAware { 023 024 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RelayMllpListener.class); 025 private List<ReceivingApplication> myApplications = new ArrayList<ReceivingApplication>(); 026 private List<AppRoutingData> myAppRoutingData = new ArrayList<AppRoutingData>(); 027 private String myBeanName; 028 private int myPort; 029 private SimpleServer myServer; 030 private AtomicInteger threadNum = new AtomicInteger(1); 031 private DefaultHapiContext myContext; 032 033 /** 034 * Fired automatically by the container when 035 * the bean is ready to start 036 */ 037 public void afterPropertiesSet() throws Exception { 038 if (myPort <= 0) { 039 throw new IllegalStateException("Port not set"); 040 } 041 042 myContext = new DefaultHapiContext(); 043 StandardSocketFactory socketFactory = new StandardSocketFactory(); 044 socketFactory.setAcceptedSocketTimeout(2000); 045 myContext.setSocketFactory(socketFactory); 046 myContext.setExecutorService(Executors.newCachedThreadPool(new MyThreadFactory())); 047 myContext.setLowerLayerProtocol(new MinLowerLayerProtocol(true)); 048 myContext.setModelClassFactory(new GenericModelClassFactory()); 049 myServer = myContext.newServer(myPort, false); 050 051 for (int i = 0; i < myAppRoutingData.size(); i++) { 052 myServer.registerApplication(myAppRoutingData.get(i), myApplications.get(i)); 053 } 054 055 ourLog.info("Starting listener on port {}", myPort); 056 myServer.startAndWait(); 057 ourLog.info("Listener on port {} has started, and is ready for processing", myPort); 058 059 if (myServer.getServiceExitedWithException() != null) { 060 Throwable ex = myServer.getServiceExitedWithException(); 061 ourLog.error("Server failed to start", ex); 062 if (ex instanceof Exception) { 063 throw (Exception) ex; 064 } else { 065 throw new Error(ex); 066 } 067 } 068 069 } 070 071 072 /** 073 * Fired automatically by the container when 074 * the bean is shutting down 075 */ 076 public void destroy() throws Exception { 077 ourLog.info("Stopping listener on port {}", myPort); 078 myServer.stopAndWait(); 079 ourLog.info("Listener on port {} has stopped", myPort); 080 081 ourLog.info("Closing HAPI Context Object"); 082 myContext.close(); 083 ourLog.info("Done closing HAPI Context object"); 084 } 085 086 public String getBeanName() { 087 return myBeanName; 088 } 089 090 091 public void registerApplication(AppRoutingData theAppRouting, ReceivingApplication theReceivingApplication) { 092 Validate.notNull(theAppRouting, "appRouting"); 093 Validate.notNull(theReceivingApplication, "receivingApplication"); 094 095 if (myServer != null) { 096 myServer.registerApplication(theAppRouting, theReceivingApplication); 097 } else { 098 myAppRoutingData.add(theAppRouting); 099 myApplications.add(theReceivingApplication); 100 } 101 } 102 103 104 public void setBeanName(String theBeanName) { 105 myBeanName = theBeanName; 106 } 107 108 public void setPort(int thePort) { 109 myPort = thePort; 110 } 111 112 private class MyThreadFactory implements ThreadFactory { 113 114 private ThreadGroup group; 115 116 private MyThreadFactory() { 117 group = Thread.currentThread().getThreadGroup(); 118 } 119 120 public Thread newThread(Runnable theR) { 121 String name = "hoh-port-" + myPort + "-worker-" + threadNum.getAndIncrement(); 122 Thread t = new Thread(group, theR, name, 0); 123 if (t.isDaemon()) { 124 t.setDaemon(false); 125 } 126 if (t.getPriority() != Thread.NORM_PRIORITY) { 127 t.setPriority(Thread.NORM_PRIORITY); 128 } 129 return t; 130 } 131 132 } 133 134 135}