package open.dolphin.impl.server;
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DateFormat;
import java.util.Date;
import java.util.logging.Level;
import open.dolphin.client.MainWindow;
import open.dolphin.infomodel.UserModel;
/**
* PVT socket server<br>
* <br>
* PVTServer() listen to ORCA for MML file through socket<br>
* <br>
* Creates 'Connection' thread on getting MML file from ORCA<br>
*
* @author Kazushi Minagawa, Digital Globe, Inc.
*
* Modified by Mirror-i corp for writing into postgreSQL
*
*/
public final class PVTClientServer implements Runnable,open.dolphin.server.PVTServer {
public static final int EOT = 0x04;
public static final int ACK = 0x06;
public static final int NAK = 0x15;
public static final String UTF8 = "UTF8";
public static final String SJIS = "SHIFT_JIS";
public static final String EUC = "EUC_JIS";
private static final int DEFAULT_PORT = 5002;
private UserModel user;
private int port = DEFAULT_PORT;
private String bindAddress;
private ServerSocket listenSocket;
private String encoding = UTF8;
private Thread serverThread;
private PVTSender sender;
private MainWindow context;
private String name;
/** Creates new ClaimServer */
public PVTClientServer() {
}
@Override
public String getBindAddress() {
return bindAddress;
}
@Override
public void setBindAddress(String bindAddress) {
this.bindAddress = bindAddress;
}
public UserModel getUser() {
return user;
}
public void setUser(UserModel user) {
this.user = user;
}
@Override
public int getPort() {
return port;
}
@Override
public void setPort(int port) {
this.port = port;
}
@Override
public String getEncoding() {
return encoding;
}
@Override
public void setEncoding(String enc) {
encoding = enc;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public MainWindow getContext() {
return context;
}
@Override
public void setContext(MainWindow context) {
this.context = context;
}
@Override
public void start() {
startService();
}
@Override
public void stop() {
stopService();
}
/**
* 受付受信サーバを開始する。
*/
public void startService() {
try {
sender = new PVTSender();
sender.startService();
InetSocketAddress address = null;
String test = getBindAddress();
if (test !=null && (!test.equals("")) ) {
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.FINE, "PVT ServerSocket bind address = {0}", getBindAddress());
try {
InetAddress addr = InetAddress.getByName(test);
address = new InetSocketAddress(addr, port);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
if (address == null) {
address = new InetSocketAddress(InetAddress.getLocalHost(), port);
}
listenSocket = new ServerSocket();
listenSocket.bind(address);
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.INFO, "PVT Server is binded {0} with encoding: {1}", new Object[]{address, encoding});
serverThread = new Thread(this);
serverThread.setPriority(Thread.NORM_PRIORITY);
serverThread.start();
} catch (IOException e) {
e.printStackTrace(System.err);
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "IOException while creating the ServerSocket: {0}", e.toString());
}
}
/**
* 受付受信サーバをストップする。
*/
public void stopService() {
if (serverThread != null) {
serverThread = null;
}
if (listenSocket != null) {
try {
listenSocket.close();
listenSocket = null;
} catch (IOException e) {
e.printStackTrace(System.err);
java.util.logging.Logger.getLogger(this.getClass().getName()).warning(e.getMessage());
}
}
if (sender != null) {
sender.stopService();
}
}
/**
*
* run(), This method is called from startServer()<br>
* Listens to ORCA server for MML file and creats new 'Connection' thread
* <br>
*
*/
@Override
public void run() {
Thread thisThread = Thread.currentThread();
while (thisThread==serverThread) {
try {
Socket clientSocket = listenSocket.accept();
Connection con = new Connection(clientSocket);
Thread t = new Thread(con);
t.setPriority(Thread.NORM_PRIORITY);
t.start();
} catch (IOException e) {
if (thisThread!=serverThread) {
java.util.logging.Logger.getLogger(this.getClass().getName()).warning("PVTServer stopped");
} else {
e.printStackTrace(System.err);
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Exception while listening for connections:{0}", e);
}
}
}
}
/**
* 'Connection' thread<br>
*
* 'Connection' thread created from 'PVTServer' thread<br>
* Converts the socket stream in to string and creates 'PatientRegister'
* object<br>
* Calls 'regist' method of 'PatientRegister' with received MML info<br>
* Receives 'PVTPostgres' object by calling 'getPVT' method of
* 'PatientRegister' object<br>
* Creates new 'PVTPostgresConnection' object to get Postgres conenction<br>
* Calls 'addWork' method of 'PVTPostgresConnection' to add/update patient
* various info in Postgres database<br>
* Overall transaction result sent to ORCA (ACK/NAK)<br>
*
*/
protected final class Connection implements Runnable {
private Socket client;
public Connection(Socket clientSocket) {
this.client = clientSocket;
}
private void printInfo() {
String addr = this.client.getInetAddress().getHostAddress();
String time = DateFormat.getDateTimeInstance().format(new Date());
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Connected from {0} at {1}", new Object[]{addr, time});
}
@Override
public void run() {
BufferedInputStream reader;
BufferedOutputStream writer;
try {
printInfo();
reader = new BufferedInputStream(new DataInputStream(this.client.getInputStream()));
writer = new BufferedOutputStream(new DataOutputStream(this.client.getOutputStream()));
ByteArrayOutputStream bo = new ByteArrayOutputStream();
BufferedOutputStream buf = new BufferedOutputStream(bo);
String recieved;
byte[] buffer = new byte[16384];
int readLen;
while (true) {
readLen = reader.read(buffer);
if (readLen == -1) {
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("EOF");
break;
}
if (buffer[readLen-1] == EOT) {
buf.write(buffer, 0, readLen-1);
buf.flush();
recieved = bo.toString(encoding);
int len = recieved.length();
bo.close();
buf.close();
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Recieved EOT length = {0} bytes", len);
java.util.logging.Logger.getLogger(this.getClass().getName()).info(recieved);
// add queue
sender.processPvt(recieved);
// Reply ACK
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("return ACK");
writer.write(ACK);
writer.flush();
} else {
buf.write(buffer, 0, readLen);
}
}
reader.close();
writer.close();
client.close();
client = null;
} catch (IOException e) {
java.util.logging.Logger.getLogger(this.getClass().getName()).warning("IOException while reading streams");
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Exception details:{0}", e);
} finally {
if (client != null) {
try {
client.close();
client = null;
} catch (IOException e2) {
java.util.logging.Logger.getLogger(this.getClass().getName()).warning("Exception while closing socket conenction after reading streams");
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Exception details:{0}", e2);
}
}
}
}
}
}