New Server class to send/rec objects via network
[nikiroo-utils.git] / src / be / nikiroo / utils / serial / ConnectAction.java
1 package be.nikiroo.utils.serial;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
6 import java.io.OutputStreamWriter;
7 import java.net.Socket;
8
9 import be.nikiroo.utils.Version;
10
11 abstract class ConnectAction {
12 private Socket s;
13 private boolean server;
14 private Version version;
15
16 private Object lock = new Object();
17 private BufferedReader in;
18 private OutputStreamWriter out;
19 private boolean contentToSend;
20
21 // serverVersion = null on server (or bad clients)
22 abstract public void action(Version serverVersion) throws Exception;
23
24 // server = version NULL
25 protected ConnectAction(Socket s, boolean server, Version version) {
26 this.s = s;
27 this.server = server;
28
29 if (version == null) {
30 this.version = new Version();
31 } else {
32 this.version = version;
33 }
34 }
35
36 public void connectAsync() {
37 new Thread(new Runnable() {
38 public void run() {
39 connect();
40 }
41 }).start();
42 }
43
44 public void connect() {
45 try {
46 in = new BufferedReader(new InputStreamReader(s.getInputStream(),
47 "UTF-8"));
48 try {
49 out = new OutputStreamWriter(s.getOutputStream(), "UTF-8");
50 try {
51 if (server) {
52 action(version);
53 } else {
54 String v = sendString("VERSION " + version.toString());
55 if (v != null && v.startsWith("VERSION ")) {
56 v = v.substring("VERSION ".length());
57 }
58
59 action(new Version(v));
60 }
61 } finally {
62 out.close();
63 }
64 } finally {
65 in.close();
66 }
67 } catch (Exception e) {
68 onError(e);
69 } finally {
70 try {
71 s.close();
72 } catch (Exception e) {
73 onError(e);
74 }
75 }
76 }
77
78 // (also, server never get anything)
79 public Object send(Object data) throws IOException, NoSuchFieldException,
80 NoSuchMethodException, ClassNotFoundException {
81 synchronized (lock) {
82 String rep = sendString(new Exporter().append(data).toString(true));
83 return new Importer().read(rep).getValue();
84 }
85 }
86
87 public Object flush() throws NoSuchFieldException, NoSuchMethodException,
88 ClassNotFoundException, IOException, java.lang.NullPointerException {
89 String str = flushString();
90 if (str == null) {
91 throw new NullPointerException("No more data from client");
92 }
93
94 return new Importer().read(str).getValue();
95 }
96
97 protected void onClientVersionReceived(Version clientVersion) {
98
99 }
100
101 protected void onError(Exception e) {
102
103 }
104
105 // \n included in line, but not in rep (also, server never get anything)
106 private String sendString(String line) throws IOException {
107 synchronized (lock) {
108 out.write(line);
109 out.write("\n");
110
111 if (server) {
112 out.flush();
113 return null;
114 } else {
115 contentToSend = true;
116 return flushString();
117 }
118 }
119 }
120
121 // server can receive something even without pending content
122 private String flushString() throws IOException {
123 synchronized (lock) {
124 if (server || contentToSend) {
125 if (contentToSend) {
126 out.flush();
127 contentToSend = false;
128 }
129
130 String line = in.readLine();
131 if (server && line != null && line.startsWith("VERSION ")) {
132 // "VERSION client-version" (VERSION 1.0.0)
133 Version clientVersion = new Version(
134 line.substring("VERSION ".length()));
135 onClientVersionReceived(clientVersion);
136 sendString("VERSION " + version.toString());
137
138 line = in.readLine();
139 }
140
141 return line;
142 } else {
143 return null;
144 }
145 }
146 }
147 }