--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.databoard.method;
+
+import java.io.IOException;\r
+import java.net.ServerSocket;\r
+import java.net.Socket;\r
+import java.util.List;\r
+import java.util.concurrent.CopyOnWriteArrayList;\r
+import java.util.logging.Level;\r
+import java.util.logging.Logger;\r
+\r
+import org.simantics.databoard.method.TcpConnection.ConnectionListener;\r
+
+/**
+ * Server opens a server socket and accepts incoming connections.
+ * <p>
+ * Methods are invoked in read thread. Therefore method invocation blocks
+ * the whole socket.
+ * It is highly recommended that that MethodInterface implementation is
+ * non-blocking.
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class Server {
+
+ static Logger LOGGER = Logger.getLogger(Server.class.getName());
+
+ ServerSocket socket;
+ Thread acceptThread;
+ MethodInterface handler;
+ List<TcpConnection> connections = new CopyOnWriteArrayList<TcpConnection>();
+
+ /**
+ * Create new method interface server.
+ *
+ * @param port
+ * @param handler method handler of local methods or
+ * @throws IOException
+ */
+ public Server(int port, MethodInterface handler)
+ throws IOException
+ {
+ this.handler = handler;
+
+ socket = new ServerSocket(port);
+ acceptThread = new Thread() {
+ @Override
+ public void run() {
+ while(true) {
+ Socket s;
+ try {
+ s = socket.accept();
+ } catch (IOException e) {
+ return;
+ }
+
+ try {
+ Handshake local = new Handshake();
+ local.methods = Server.this.handler.getInterface().getMethodDefinitions();
+ Handshake remote = TcpConnection.handshake(s, local);
+ final TcpConnection c = new TcpConnection(s, Server.this.handler, local, remote);
+ c.addConnectionListener(new ConnectionListener() {
+ @Override
+ public void onClosed() {
+ connections.remove(c);
+ }
+ @Override
+ public void onError(Exception error) {
+ connections.remove(c);
+ }
+ });
+
+ connections.add( c ); \r
+ if (c.getSocket().isClosed()) connections.remove(c);
+ } catch (IOException e) {
+ LOGGER.log(Level.FINER, "Connection Closed");
+ try {
+ s.close();
+ } catch (IOException e1) {
+ }
+ }
+ }
+ }
+ };\r
+ acceptThread.setDaemon(true);
+ acceptThread.start();
+ }
+
+ /**
+ * Stop listening for new connections and shutdown existing connections.
+ */
+ public void close() {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ }
+ for (TcpConnection c : connections) {
+ c.close();
+ try {
+ c.getSocket().close();
+ } catch (IOException e) {
+ }
+ }
+ }\r
+ \r
+ /** \r
+ * @return The port the server is listening.\r
+ */\r
+ public int getPort() {\r
+ return socket.getLocalPort(); \r
+ }
+
+}
+