]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/method/Server.java
Improve Databoard's dynamically typed data capabilities.
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / method / Server.java
1 /*******************************************************************************\r
2  *  Copyright (c) 2010 Association for Decentralized Information Management in\r
3  *  Industry THTH ry.\r
4  *  All rights reserved. This program and the accompanying materials\r
5  *  are made available under the terms of the Eclipse Public License v1.0\r
6  *  which accompanies this distribution, and is available at\r
7  *  http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  *  Contributors:\r
10  *      VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.method;
13
14 import java.io.IOException;\r
15 import java.net.ServerSocket;\r
16 import java.net.Socket;\r
17 import java.util.List;\r
18 import java.util.concurrent.CopyOnWriteArrayList;\r
19 import java.util.logging.Level;\r
20 import java.util.logging.Logger;\r
21 \r
22 import org.simantics.databoard.method.TcpConnection.ConnectionListener;\r
23
24 /**
25  * Server opens a server socket and accepts incoming connections. 
26  * <p>
27  * Methods are invoked in read thread. Therefore method invocation blocks 
28  * the whole socket. 
29  * It is highly recommended that that MethodInterface implementation is 
30  * non-blocking.
31  *
32  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
33  */
34 public class Server {
35         
36         static Logger LOGGER = Logger.getLogger(Server.class.getName());
37
38         ServerSocket socket;
39         Thread acceptThread;
40         MethodInterface handler;
41         List<TcpConnection> connections = new CopyOnWriteArrayList<TcpConnection>();
42         
43         /**
44          * Create new method interface server. 
45          * 
46          * @param port
47          * @param handler method handler of local methods or 
48          * @throws IOException
49          */
50         public Server(int port, MethodInterface handler) 
51         throws IOException
52         {
53                 this.handler = handler;
54                 
55                 socket = new ServerSocket(port);
56                 acceptThread = new Thread() {
57                         @Override
58                         public void run() {
59                                 while(true) {
60                                         Socket s;
61                                         try {
62                                                 s = socket.accept();
63                                         } catch (IOException e) {
64                                                 return;
65                                         }
66                                         
67                                         try {
68                                                 Handshake local = new Handshake();
69                                                 local.methods = Server.this.handler.getInterface().getMethodDefinitions();
70                                                 Handshake remote = TcpConnection.handshake(s, local);
71                                                 final TcpConnection c = new TcpConnection(s, Server.this.handler, local, remote);                                               
72                                                 c.addConnectionListener(new ConnectionListener() {
73                                                         @Override
74                                                         public void onClosed() {
75                                                                 connections.remove(c);
76                                                         }
77                                                         @Override
78                                                         public void onError(Exception error) {
79                                                                 connections.remove(c);
80                                                         }
81                                                 });
82                                                 
83                                                 connections.add( c );                                           \r
84                                                 if (c.getSocket().isClosed()) connections.remove(c);
85                                         } catch (IOException e) {
86                                                 LOGGER.log(Level.FINER, "Connection Closed");
87                                                 try {
88                                                         s.close();
89                                                 } catch (IOException e1) {
90                                                 }
91                                         }
92                                 }                               
93                         }
94                 };\r
95                 acceptThread.setDaemon(true);
96                 acceptThread.start();
97         }
98         
99         /**
100          * Stop listening for new connections and shutdown existing connections. 
101          */
102         public void close() {
103                 try {
104                         socket.close();
105                 } catch (IOException e) {
106                 }
107                 for (TcpConnection c : connections) {
108                         c.close();
109                         try {
110                                 c.getSocket().close();
111                         } catch (IOException e) {
112                         }
113                 }
114         }\r
115         \r
116         /** \r
117          * @return The port the server is listening.\r
118          */\r
119         public int getPort() {\r
120                 return socket.getLocalPort(); \r
121         }
122         
123 }
124