summaryrefslogtreecommitdiff
path: root/src/main/java/com/c2kernel/utils/server
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@cern.ch>2012-05-30 08:37:45 +0200
committerAndrew Branson <andrew.branson@cern.ch>2012-05-30 08:37:45 +0200
commitb086f57f56bf0eb9dab9cf321a0f69aaaae84347 (patch)
tree8e6e26e8b7eed6abad7a17b093bdbb55c5e6b1ba /src/main/java/com/c2kernel/utils/server
parent22088ae8d2d5ff390518dbe1c4372325ffb3a647 (diff)
Initial Maven Conversion
Diffstat (limited to 'src/main/java/com/c2kernel/utils/server')
-rw-r--r--src/main/java/com/c2kernel/utils/server/HTTPRequestHandler.java160
-rw-r--r--src/main/java/com/c2kernel/utils/server/SimpleTCPIPServer.java109
-rw-r--r--src/main/java/com/c2kernel/utils/server/SocketHandler.java15
-rw-r--r--src/main/java/com/c2kernel/utils/server/UDPListener.java54
4 files changed, 338 insertions, 0 deletions
diff --git a/src/main/java/com/c2kernel/utils/server/HTTPRequestHandler.java b/src/main/java/com/c2kernel/utils/server/HTTPRequestHandler.java
new file mode 100644
index 0000000..886ae9f
--- /dev/null
+++ b/src/main/java/com/c2kernel/utils/server/HTTPRequestHandler.java
@@ -0,0 +1,160 @@
+package com.c2kernel.utils.server;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+import com.c2kernel.utils.Logger;
+
+public class HTTPRequestHandler implements SocketHandler {
+
+ protected HashMap<String, String> headers = new HashMap<String, String>();
+ protected String method;
+ protected String resource;
+ protected String version;
+ protected String returnMIME;
+ protected String statusCode;
+ protected String postData;
+ protected final static String CRLF = "\r\n";
+ protected BufferedReader request;
+ protected Socket currentSocket = null;
+
+ public HTTPRequestHandler() { }
+
+ @Override
+ public String getName() {
+ return "HTTP Server";
+ }
+
+ @Override
+ public boolean isBusy() {
+ return (currentSocket!=null);
+ }
+
+ @Override
+ public void setSocket(Socket newSocket) {
+ currentSocket = newSocket;
+ }
+
+ @Override
+ public void shutdown() {
+ try {
+ if (currentSocket != null) currentSocket.close();
+ } catch (IOException e) {
+ Logger.error("Error shutting down HTTP connection");
+ }
+ currentSocket = null;
+ }
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("HTTP Request Handler");
+ try {
+ request = new BufferedReader(new InputStreamReader(currentSocket.getInputStream()));
+ // parse the request
+ boolean firstLine = true;
+ String headerLine;
+ do {
+ headerLine = request.readLine();
+ if (headerLine == null)
+ throw new IOException("Disconnected");
+ if (firstLine) { // request line
+ StringTokenizer params = new StringTokenizer(headerLine);
+ try {
+ method = params.nextToken();
+ resource = params.nextToken();
+ version = params.nextToken();
+ } catch (NoSuchElementException ex1) { } // incomplete request line - doesn't matter
+ firstLine = false;
+ }
+ else { // headers
+ int split = headerLine.indexOf(": ");
+ if (split >= 0)
+ headers.put(
+ headerLine.substring(0, split),
+ headerLine.substring(split+2)
+ );
+ }
+ } while (!headerLine.equals(CRLF) && !headerLine.equals(""));
+
+ String response = null;
+
+ try {
+
+ if (headers.containsKey("Content-length")) { // read POST data
+ StringBuffer postBuffer = new StringBuffer();
+ int received = 0; int length = Integer.parseInt(headers.get("Content-length"));
+ try {
+ while (received < length) {
+ String postLine = request.readLine();
+ postBuffer.append(postLine);
+ received+=postLine.length();
+ }
+ } catch (IOException ex) {
+ Logger.error("Error reading post data. "+received+" bytes of "+length+" received. ("+(received*100.0/length)+"%");
+ Logger.error(ex);
+ throw ex;
+ }
+ }
+ // Got the params, generate response
+
+ returnMIME = "text/xml";
+ statusCode = "200 OK";
+
+ response = processRequest();
+ } catch (Exception ex3) {
+ response = error("500 Server Error", ex3.getClass().getName()+"<br>"+ex3.getMessage());
+ }
+ System.out.println(new Date().toString()+" "+currentSocket.getInetAddress()+" "+method+" "+resource+" "+statusCode);
+
+ OutputStream output = currentSocket.getOutputStream();
+
+ statusCode = "HTTP/1.0 "+statusCode+CRLF;
+ output.write(statusCode.getBytes());
+
+ returnMIME = "Content-type: "+returnMIME+CRLF;
+ output.write(returnMIME.getBytes());
+
+ String contentLength = "Content-Length: "+response.length()+CRLF;
+ output.write(contentLength.getBytes());
+
+ // Possible: last mod?
+ // end of headers
+ output.write(CRLF.getBytes());
+
+ // write the content
+ output.write(response.getBytes());
+ request.close();
+ output.close();
+ currentSocket.close();
+ } catch (IOException ex2) {
+ Logger.error(ex2);
+ } // aborted connection probably
+ currentSocket = null;
+ }
+
+ /* This is a dummy method that doesn't support anything.
+ * Override it.
+ */
+
+ public String processRequest() {
+ return error("501 Not Implemented", "The method "+method+" you have requested is not supported by this server.");
+ }
+
+ public String error(String code, String desc) {
+ statusCode = code;
+ returnMIME = "text/html";
+ return ("<HTML>" +
+ "<HEAD><TITLE>"+code+"</TITLE></HEAD>" +
+ "<BODY><h1>"+code+"</h1>" +
+ "<p>"+desc+
+ "<hr><p><small>Cristal Item HTTP server</small></BODY></HTML>");
+ }
+}
+
diff --git a/src/main/java/com/c2kernel/utils/server/SimpleTCPIPServer.java b/src/main/java/com/c2kernel/utils/server/SimpleTCPIPServer.java
new file mode 100644
index 0000000..930fcee
--- /dev/null
+++ b/src/main/java/com/c2kernel/utils/server/SimpleTCPIPServer.java
@@ -0,0 +1,109 @@
+package com.c2kernel.utils.server;
+
+import java.io.InterruptedIOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import com.c2kernel.utils.Logger;
+
+
+public class SimpleTCPIPServer implements Runnable
+{
+ int port = 0;
+ int maxConn = 10;
+ Thread listener = null;
+ Class<?> handlerClass = null;
+ ServerSocket serverSocket = null;
+ boolean keepListening = true;
+ ArrayList<SocketHandler> currentHandlers = new ArrayList<SocketHandler>();
+ static short noServers = 0;
+
+ public SimpleTCPIPServer(int port, Class<?> handlerClass, int maxConnections)
+ {
+ this.port = port;
+ this.handlerClass = handlerClass;
+ this.maxConn = maxConnections;
+ noServers++;
+ }
+
+ public void startListening()
+ {
+ if(listener != null) return;
+ keepListening = true;
+
+ listener = new Thread(this);
+ listener.start();
+ }
+
+ public void stopListening()
+ {
+ Logger.msg("SimpleTCPIPServer: Closing server for " + handlerClass.getName() +" on port "+ port);
+ keepListening = false;
+ for (SocketHandler thisHandler : currentHandlers) {
+ thisHandler.shutdown();
+ }
+ }
+
+ @Override
+ public void run()
+ {
+ Thread.currentThread().setName("TCP/IP Server for "+handlerClass.getName());
+ Socket connectionSocket = null;
+
+ try {
+ serverSocket = new ServerSocket(port);
+ if (port == 0)
+ port = serverSocket.getLocalPort();
+ Logger.msg("SimpleTCPIPServer: Created server for " + handlerClass.getName()+" on port "+port);
+ serverSocket.setSoTimeout(500);
+ SocketHandler freeHandler = null;
+ while(keepListening) {
+ if (freeHandler == null || freeHandler.isBusy()) {
+ ListIterator<SocketHandler> i = currentHandlers.listIterator();
+ try {
+ do {
+ freeHandler = i.next();
+ } while (freeHandler.isBusy());
+ } catch (NoSuchElementException e) {
+ // create new one
+ if (currentHandlers.size() < maxConn) {
+ freeHandler = (SocketHandler)handlerClass.newInstance();
+ currentHandlers.add(freeHandler);
+ }
+ else { // max handlers are created. wait for a while, then look again
+ Logger.warning("No free handlers left for "+handlerClass.getName()+" on port "+ port + "!");
+ Thread.sleep(2000);
+ continue;
+ }
+ }
+ }
+ try {
+ connectionSocket = serverSocket.accept();
+ if (keepListening) {
+ Logger.msg("SimpleTCPIPServer: Connection to "+freeHandler.getName()+" from "+
+ connectionSocket.getInetAddress());
+ freeHandler.setSocket(connectionSocket);
+ new Thread(freeHandler).start();
+ }
+ } catch (InterruptedIOException ex1) { }// timeout just to check if we've been told to die
+
+ }
+ serverSocket.close();
+ Logger.msg("SimpleTCPIPServer: Server closed for " + handlerClass.getName() +" on port "+ port);
+ } catch(Exception ex) {
+ Logger.error(ex);
+ Logger.error("SimpleTCPIPServer.run(): Fatal Error. Listener for '"+handlerClass.getName()+"' will stop.");
+ listener = null; --noServers;
+ return;
+ }
+ listener = null;
+ Logger.msg("SimpleTCPIPServer - Servers still running: "+--noServers);
+ }
+
+ public int getPort() {
+ return port;
+ }
+}
diff --git a/src/main/java/com/c2kernel/utils/server/SocketHandler.java b/src/main/java/com/c2kernel/utils/server/SocketHandler.java
new file mode 100644
index 0000000..8d37714
--- /dev/null
+++ b/src/main/java/com/c2kernel/utils/server/SocketHandler.java
@@ -0,0 +1,15 @@
+package com.c2kernel.utils.server;
+
+import java.net.Socket;
+
+public interface SocketHandler extends Runnable {
+
+ public String getName();
+
+ public boolean isBusy();
+
+ public void setSocket(Socket newSocket);
+
+ public void shutdown();
+}
+
diff --git a/src/main/java/com/c2kernel/utils/server/UDPListener.java b/src/main/java/com/c2kernel/utils/server/UDPListener.java
new file mode 100644
index 0000000..3b1fc9d
--- /dev/null
+++ b/src/main/java/com/c2kernel/utils/server/UDPListener.java
@@ -0,0 +1,54 @@
+package com.c2kernel.utils.server;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2004/02/06 14:50:43 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public abstract class UDPListener extends Thread {
+
+ private boolean active = true;
+ protected DatagramSocket socket;
+
+ public UDPListener() {
+ super();
+ }
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("UDP Server");
+ byte[] buffer = new byte[255];
+ DatagramPacket newPacket = new DatagramPacket(buffer, buffer.length);
+ while (active) {
+ try {
+ socket.receive(newPacket);
+ processPacket(newPacket);
+ } catch (InterruptedIOException e) { // ignore timeout
+ } catch (IOException e) {
+ Logger.error("Error receiving proxy packet:");
+ Logger.error(e);
+ } catch (InvalidDataException e) {
+ Logger.error(e);
+ }
+ }
+ socket.close();
+ }
+
+ protected abstract void processPacket(DatagramPacket packet) throws InvalidDataException;
+
+ public void shutdown() {
+ active = false;
+ }
+}