Source code: reeb/lazysync/LazySyncServer.java
1 // LazySyncServer.java
2 package reeb.lazysync;
3
4 import java.net.*;
5 import java.io.*;
6 import java.util.*;
7
8 /** LazySync server for desktop running */
9 public class LazySyncServer
10 {
11 /** The version number */
12 private static final String VERSION="0.1";
13
14 /** The port number to listen on */
15 private static final int DEFAULT_PORT=6666;
16
17 /** Main entry point */
18 public static void main(String args[]) throws Exception
19 {
20 ServerSocket serverSocket;
21 Socket socket;
22 BufferedReader reader;
23 PrintWriter writer;
24 File syncDir, clientSyncDir;
25 String input, clientDir, serverDir;
26 int listenPort=DEFAULT_PORT;
27
28 // Check args
29 if (args.length<1)
30 {
31 // Show usage
32 System.out.println("Usage: LazySyncServer <sync dir> [port]");
33 System.exit(0);
34 }
35
36 // Get dir
37 syncDir=new File(args[0]);
38
39 // Check port
40 if (args.length>1)
41 // Get listen port
42 listenPort=Integer.parseInt(args[1]);
43
44 // Create the server socket
45 serverSocket=new ServerSocket(listenPort);
46
47 // Show startup message
48 System.out.println("LazySyncServer "+VERSION+" started on "+InetAddress.getLocalHost()+":"+listenPort);
49
50 // Wait for connection
51 while (true)
52 {
53 // Wait
54 socket=serverSocket.accept();
55
56 System.out.println("Got client connection: "+socket);
57
58 // Get reader and writers for socket
59 reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
60 writer=new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
61
62 // Send back the version number
63 writer.println(VERSION);
64 writer.flush();
65
66 // Get the client sync dir
67 clientDir=reader.readLine();
68
69 System.out.println("Client syncdir: "+clientDir);
70
71 // Write back OK
72 writer.println("OK");
73 writer.flush();
74
75 // Mangle to get server dir
76 serverDir=mangleClientSyncDir(clientDir);
77
78 // Get absolute file object
79 clientSyncDir=new File(syncDir,serverDir);
80
81 // Does it exist
82 if (!clientSyncDir.exists())
83 // Create it
84 clientSyncDir.mkdir();
85
86 // Set to run
87 input="";
88
89 // Get further commands
90 while (!input.equals("bye"))
91 {
92 // Get input
93 input=reader.readLine();
94
95 System.out.println("Got request: "+input);
96
97 // Check input
98 if (input.equals("getDirList"))
99 // Return the file list
100 getDirList(reader,writer,clientSyncDir);
101 else if (input.equals("getFileInfo"))
102 // Return a files info
103 getFileInfo(reader,writer,clientSyncDir);
104 else if (input.equals("getFileData"))
105 // Return a files data
106 getFileData(socket,reader,writer,clientSyncDir,listenPort);
107 else if (input.equals("putFileData"))
108 // Accepts a files data
109 putFileData(socket,reader,writer,clientSyncDir,listenPort);
110 else if (input.equals("deleteFile"))
111 // Removes a local file or dir
112 deleteFile(reader,writer,clientSyncDir);
113 else if (input.equals("createDir"))
114 // Creates a local directory
115 createDir(reader,writer,clientSyncDir);
116 else if (input.equals("getLastSyncData"))
117 // Returns the last sync data if available
118 getLastSyncData(reader,writer,clientSyncDir);
119 else if (input.equals("setLastSyncData"))
120 // Sets the last sync data
121 setLastSyncData(reader,writer,clientSyncDir);
122 }
123 }
124 }
125
126 /** Sets the last sync data */
127 private static void setLastSyncData(BufferedReader reader, PrintWriter writer, File syncDir) throws Exception
128 {
129 File lastSyncFile;
130 ObjectOutputStream oos;
131 Vector dirList, fileList;
132 int i, numItems;
133
134 // Create the vectors
135 dirList=new Vector();
136 fileList=new Vector();
137
138 // Create the file object
139 lastSyncFile=new File(syncDir.getParent(),syncDir.getName()+".lastsync");
140
141 // Get the object output stream
142 oos=new ObjectOutputStream(new FileOutputStream(lastSyncFile));
143
144 // Get the number of dirs to follow
145 numItems=Integer.parseInt(reader.readLine());
146
147 // Go through
148 for (i=0;i<numItems;i++)
149 // Read in the item
150 dirList.addElement(reader.readLine());
151
152 // Get the number of files to follow
153 numItems=Integer.parseInt(reader.readLine());
154
155 // Go through
156 for (i=0;i<numItems;i++)
157 // Read in the item
158 fileList.addElement(reader.readLine());
159
160 // Write out to object output stream
161 oos.writeObject(dirList);
162 oos.writeObject(fileList);
163
164 // Close stream
165 oos.close();
166 }
167
168 /** Returns the last sync data if available */
169 private static void getLastSyncData(BufferedReader reader, PrintWriter writer, File syncDir) throws Exception
170 {
171 File lastSyncFile;
172 ObjectInputStream ois;
173 Vector dirList, fileList;
174 int i;
175
176 // Create the file object
177 lastSyncFile=new File(syncDir.getParent(),syncDir.getName()+".lastsync");
178
179 // If exists
180 if (lastSyncFile.exists())
181 {
182 // Get the object input stream
183 ois=new ObjectInputStream(new FileInputStream(lastSyncFile));
184
185 // Read in the directory vector
186 dirList=(Vector)ois.readObject();
187
188 // Read in the file vector
189 fileList=(Vector)ois.readObject();
190
191 // Close the stream
192 ois.close();
193 }
194 else
195 {
196 // Empty vectors
197 dirList=new Vector();
198 fileList=new Vector();
199 }
200
201 // Write out the number of dirs to follow
202 writer.println(dirList.size());
203 writer.flush();
204
205 // Write them out
206 for (i=0;i<dirList.size();i++)
207 // Write them out
208 writer.println(dirList.elementAt(i));
209
210 // Flush
211 writer.flush();
212
213 // Write out the number of files to follow
214 writer.println(fileList.size());
215 writer.flush();
216
217 // Write them out
218 for (i=0;i<fileList.size();i++)
219 // Write them out
220 writer.println(fileList.elementAt(i));
221
222 // Flush
223 writer.flush();
224 }
225
226 /** Mangles a passed client sync dir to create the server sync dir */
227 private static String mangleClientSyncDir(String clientSyncDir) throws Exception
228 {
229 String serverDir;
230
231 // Replace forward slashes with underscores
232 serverDir=clientSyncDir.replace('/','_');
233
234 // Replace back slashes with underscores
235 serverDir=serverDir.replace('\\','_');
236
237 // Replace colons with underscores
238 serverDir=serverDir.replace(':','_');
239
240 // Return the new string
241 return serverDir;
242 }
243
244 /** Creates the specified directory */
245 private static void createDir(BufferedReader reader, PrintWriter writer, File syncDir) throws Exception
246 {
247 String file;
248 File localFile;
249
250 // Get the file to get info about
251 file=reader.readLine();
252
253 // Get the local file
254 localFile=getAbsoluteFile(syncDir,file);
255
256 // Create the dir
257 localFile.mkdir();
258 }
259
260 /** Deletes the specified file */
261 private static void deleteFile(BufferedReader reader, PrintWriter writer, File syncDir) throws Exception
262 {
263 String file;
264 File localFile;
265
266 // Get the file to get info about
267 file=reader.readLine();
268
269 // Get the local file
270 localFile=getAbsoluteFile(syncDir,file);
271
272 // Delete the file
273 localFile.delete();
274 }
275
276 /** Writes file data */
277 private static void putFileData(Socket socket, BufferedReader reader, PrintWriter writer, File syncDir, int portNum) throws Exception
278 {
279 String file;
280 File localFile;
281 ServerSocket serverSocket;
282 Socket ftpSocket;
283 long fileSize, timeStamp;
284
285 // Get the file to write out
286 file=reader.readLine();
287
288 // Get the local location
289 localFile=getAbsoluteFile(syncDir,file);
290
291 // Get file size
292 fileSize=Long.parseLong(reader.readLine());
293
294 // Get time stamp
295 timeStamp=Long.parseLong(reader.readLine());
296
297 // Create ftp connection
298 serverSocket=new ServerSocket(portNum+1);
299
300 // Wait for cliemt
301 ftpSocket=serverSocket.accept();
302
303 // Receive the file
304 FileTransfer.receiveFile(ftpSocket,localFile,fileSize,timeStamp);
305
306 // Close the server socket
307 serverSocket.close();
308
309 // Send complete
310 writer.println("Done");
311 writer.flush();
312 }
313
314 /** Returns file data as a binary stream to client */
315 private static void getFileData(Socket socket, BufferedReader reader, PrintWriter writer, File syncDir, int portNum) throws Exception
316 {
317 String file;
318 ServerSocket serverSocket;
319 Socket ftpSocket;
320 File localFile;
321
322 // Get the file to get info about
323 file=reader.readLine();
324
325 // Get the local file
326 localFile=getAbsoluteFile(syncDir,file);
327
328 // Create ftp connection
329 serverSocket=new ServerSocket(portNum+1);
330
331 // Wait for client to connect
332 ftpSocket=serverSocket.accept();
333
334 // Send file
335 FileTransfer.sendFile(ftpSocket,localFile);
336
337 // Close the socket
338 serverSocket.close();
339
340 // Send complete
341 writer.println("Done");
342 writer.flush();
343 }
344
345 /** Returns file type (dir/file), file size and last modified date (as long) */
346 private static void getFileInfo(BufferedReader reader, PrintWriter writer, File syncDir) throws Exception
347 {
348 String file;
349 File localFile;
350
351 // Get the file to get info about
352 file=reader.readLine();
353
354 // Get the local file
355 localFile=getAbsoluteFile(syncDir,file);
356
357 // Write out the type
358 if (localFile.isDirectory())
359 // Write out dir
360 writer.println("dir");
361 else
362 // Write out file
363 writer.println("file");
364
365 // Write out the size
366 writer.println(localFile.length());
367
368 // Write out the last modified date
369 writer.println(localFile.lastModified());
370
371 // Flush out
372 writer.flush();
373 }
374
375 /** Returns the file list */
376 private static void getDirList(BufferedReader reader, PrintWriter writer, File syncDir) throws Exception
377 {
378 String relDir;
379 File dir;
380 String[] files;
381 int i;
382
383 // Get the relative directory location
384 relDir=reader.readLine();
385
386 // Get the file object representing the dir
387 dir=getAbsoluteFile(syncDir,relDir);
388
389 // Get list of files
390 files=dir.list();
391
392 // Check files
393 if (files==null)
394 // Set empty array
395 files=new String[0];
396
397 // Output number of files to follow
398 writer.println(files.length);
399 writer.flush();
400
401 // Go through writing
402 for (i=0;i<files.length;i++)
403 // Write
404 writer.println(files[i]);
405
406 // Flush
407 writer.flush();
408 }
409
410 /** Returns the path for a file based upon absolute root and relative path */
411 private static File getAbsoluteFile(File root, String relPath) throws Exception
412 {
413 // Check platform
414 if (File.separatorChar=='\\')
415 // Convert slashes
416 relPath=relPath.replace('/','\\');
417
418 // Check root
419 if (relPath.equals(""))
420 // Return root
421 return root;
422 else
423 // Return file
424 return new File(root,relPath);
425 }
426 }