KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > server > ftp > FtpServer


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.server.ftp;
6
7 import java.io.ByteArrayInputStream JavaDoc;
8 import java.io.ByteArrayOutputStream JavaDoc;
9 import java.io.File JavaDoc;
10 import java.io.FileOutputStream JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.io.InputStream JavaDoc;
13 import java.io.OutputStream JavaDoc;
14 import java.net.ServerSocket JavaDoc;
15 import java.net.Socket JavaDoc;
16 import java.sql.Connection JavaDoc;
17 import java.sql.DriverManager JavaDoc;
18 import java.sql.SQLException JavaDoc;
19 import java.text.SimpleDateFormat JavaDoc;
20 import java.util.Date JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Locale JavaDoc;
23 import java.util.Properties JavaDoc;
24
25 import org.h2.engine.Constants;
26 import org.h2.server.Service;
27 import org.h2.util.IOUtils;
28 import org.h2.util.MathUtils;
29 import org.h2.util.NetUtils;
30
31 /**
32  * Small FTP Server. Intended for ad-hoc networks in a secure environment.
33  * See also http://cr.yp.to/ftp.html http://www.ftpguide.com/
34  */

35 public class FtpServer implements Service {
36     
37     public static final String JavaDoc DEFAULT_ROOT = "ftp";
38     public static final String JavaDoc DEFAULT_READ = "guest";
39     public static final String JavaDoc DEFAULT_WRITE = "sa";
40     public static final String JavaDoc DEFAULT_WRITE_PASSWORD = "sa";
41     
42     private ServerSocket JavaDoc serverSocket;
43     private int port = Constants.DEFAULT_FTP_PORT;
44     private int openConnectionCount;
45     private int maxConnectionCount = 100;
46     
47     private SimpleDateFormat JavaDoc dateFormatNew = new SimpleDateFormat JavaDoc("MMM dd HH:mm", Locale.ENGLISH);
48     private SimpleDateFormat JavaDoc dateFormatOld = new SimpleDateFormat JavaDoc("MMM dd yyyy", Locale.ENGLISH);
49     private SimpleDateFormat JavaDoc dateFormat = new SimpleDateFormat JavaDoc("yyyyMMddHHmmss");
50     
51     private String JavaDoc root = DEFAULT_ROOT;
52     private String JavaDoc writeUserName = DEFAULT_WRITE, writePassword = DEFAULT_WRITE_PASSWORD;
53     private String JavaDoc readUserName = DEFAULT_READ;
54     private HashMap JavaDoc tasks = new HashMap JavaDoc();
55     
56     private FileSystemDatabase db;
57     private boolean log;
58     private boolean allowTask;
59     static final String JavaDoc TASK_SUFFIX = ".task";
60
61     public void listen() {
62         try {
63             while (serverSocket != null) {
64                 Socket JavaDoc s = serverSocket.accept();
65                 boolean stop;
66                 synchronized(this) {
67                     openConnectionCount++;
68                     stop = openConnectionCount > maxConnectionCount;
69                 }
70                 FtpControl c = new FtpControl(s, this, stop);
71                 c.start();
72             }
73         } catch (Exception JavaDoc e) {
74             logError(e);
75         }
76     }
77     
78     void closeConnection() {
79         synchronized(this) {
80             openConnectionCount--;
81         }
82     }
83
84     public ServerSocket JavaDoc createDataSocket() throws IOException JavaDoc {
85         ServerSocket JavaDoc dataSocket = new ServerSocket JavaDoc(0);
86         return dataSocket;
87     }
88     
89     void appendFile(StringBuffer JavaDoc buff, FileObject f) {
90         buff.append(f.isDirectory() ? 'd' : '-');
91         buff.append(f.canRead() ? 'r' : '-');
92         buff.append(f.canWrite() ? 'w' : '-');
93         buff.append("------- 1 owner group ");
94         String JavaDoc size = String.valueOf(f.length());
95         for(int i = size.length(); i < 15; i++) {
96             buff.append(' ');
97         }
98         buff.append(size);
99         buff.append(' ');
100         Date JavaDoc now = new Date JavaDoc(), mod = new Date JavaDoc(f.lastModified());
101         if(mod.after(now) || Math.abs((now.getTime() - mod.getTime())/1000/60/60/24) > 180) {
102             buff.append(dateFormatOld.format(mod));
103         } else {
104             buff.append(dateFormatNew.format(mod));
105         }
106         buff.append(' ');
107         buff.append(f.getName());
108         buff.append("\r\n");
109     }
110
111     String JavaDoc formatLastModified(FileObject file) {
112         return dateFormat.format(new Date JavaDoc(file.lastModified()));
113     }
114     
115     FileObject getFile(String JavaDoc path) {
116         if(path.indexOf("..") > 0) {
117             path = "/";
118         }
119         while(path.startsWith("/") && root.endsWith("/")) {
120             path = path.substring(1);
121         }
122         while(path.endsWith("/")) {
123             path = path.substring(0, path.length()-1);
124         }
125         log("file: " + root + path);
126         if(db != null) {
127             return FileObjectDatabase.get(db, root + path);
128         } else {
129             return FileObjectNative.get(root + path);
130         }
131     }
132     
133     String JavaDoc getDirectoryListing(FileObject directory, boolean listDirectories) {
134         FileObject[] list = directory.listFiles();
135         StringBuffer JavaDoc buff = new StringBuffer JavaDoc();
136         for(int i=0; list != null && i<list.length; i++) {
137             FileObject f = list[i];
138             if(f.isFile() || (f.isDirectory() && listDirectories)) {
139                 appendFile(buff, f);
140             }
141         }
142         return buff.toString();
143     }
144     
145     public boolean checkUserPassword(String JavaDoc userName, String JavaDoc password) {
146         return userName.equals(this.writeUserName) && password.equals(this.writePassword);
147     }
148
149     public boolean checkUserPasswordReadOnly(String JavaDoc userName, String JavaDoc param) {
150         return userName.equals(this.readUserName);
151     }
152
153     public void init(String JavaDoc[] args) throws Exception JavaDoc {
154         for(int i=0; args != null && i<args.length; i++) {
155             if("-ftpPort".equals(args[i])) {
156                 port = MathUtils.decodeInt(args[++i]);
157             } else if("-ftpDir".equals(args[i])) {
158                 root = args[++i];
159             } else if("-ftpRead".equals(args[i])) {
160                 readUserName = args[++i];
161             } else if("-ftpWrite".equals(args[i])) {
162                 writeUserName = args[++i];
163             } else if("-ftpWritePassword".equals(args[i])) {
164                 writePassword = args[++i];
165             } else if("-log".equals(args[i])) {
166                 log = Boolean.valueOf(args[++i]).booleanValue();
167             } else if("-ftpTask".equals(args[i])) {
168                 allowTask = Boolean.valueOf(args[++i]).booleanValue();
169             }
170         }
171         if(root.startsWith("jdbc:")) {
172             org.h2.Driver.load();
173             Connection JavaDoc conn = DriverManager.getConnection(root);
174             db = new FileSystemDatabase(conn, log);
175             root = "/";
176         }
177     }
178
179     public String JavaDoc getURL() {
180         return "ftp://localhost:"+port;
181     }
182
183     public void start() throws SQLException JavaDoc {
184         getFile("").mkdirs();
185         serverSocket = NetUtils.createServerSocket(port, false);
186     }
187
188     public void stop() {
189         try {
190             serverSocket.close();
191         } catch(IOException JavaDoc e) {
192             logError(e);
193         }
194         serverSocket = null;
195     }
196
197     public boolean isRunning() {
198         if(serverSocket == null) {
199             return false;
200         }
201         try {
202             Socket JavaDoc s = NetUtils.createLoopbackSocket(port, false);
203             s.close();
204             return true;
205         } catch(Exception JavaDoc e) {
206             return false;
207         }
208     }
209
210     public boolean getAllowOthers() {
211         return true;
212     }
213
214     public String JavaDoc getType() {
215         return "FTP";
216     }
217     
218     void log(String JavaDoc s) {
219         if(log) {
220             System.out.println(s);
221         }
222     }
223     
224     void logError(Throwable JavaDoc e) {
225         if (log) {
226             e.printStackTrace();
227         }
228     }
229
230     public boolean getAllowTask() {
231         return allowTask;
232     }
233
234     void startTask(FileObject file) throws IOException JavaDoc {
235         stopTask(file);
236         String JavaDoc processName = file.getName();
237         if(file.getName().endsWith(".zip.task")) {
238             log("expand: " + file.getName());
239             Process JavaDoc p = Runtime.getRuntime().exec("jar -xf " + file.getName(), null, new File JavaDoc(root));
240             String JavaDoc processFile = root + "/" + processName;
241             new StreamRedirect(processFile, p.getInputStream(), null).start();
242             return;
243         }
244         ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
245         file.read(0, out);
246         byte[] data = out.toByteArray();
247         Properties JavaDoc prop = new Properties JavaDoc();
248         prop.load(new ByteArrayInputStream JavaDoc(data));
249         String JavaDoc command = prop.getProperty("command");
250         String JavaDoc outFile = processName.substring(0, processName.length() - TASK_SUFFIX.length());
251         String JavaDoc errorFile = root + "/" + prop.getProperty("error", outFile + ".err.txt");
252         String JavaDoc outputFile= root + "/" + prop.getProperty("output", outFile + ".out.txt");
253         String JavaDoc processFile = root + "/" + processName;
254         log("start process: " + processName + " / " + command);
255         Process JavaDoc p = Runtime.getRuntime().exec(command, null, new File JavaDoc(root));
256         new StreamRedirect(processFile, p.getErrorStream(), errorFile).start();
257         new StreamRedirect(processFile, p.getInputStream(), outputFile).start();
258         tasks.put(processName, p);
259     }
260     
261     private static class StreamRedirect extends Thread JavaDoc {
262         private InputStream JavaDoc in;
263         private OutputStream JavaDoc out;
264         private String JavaDoc outFile;
265         private String JavaDoc processFile;
266         
267         StreamRedirect(String JavaDoc processFile, InputStream JavaDoc in, String JavaDoc outFile) {
268             this.processFile = processFile;
269             this.in = in;
270             this.outFile = outFile;
271         }
272         
273         private void openOutput() {
274             if(outFile != null) {
275                 try {
276                     this.out = new FileOutputStream JavaDoc(outFile);
277                 } catch(IOException JavaDoc e) {
278                     // ignore
279
}
280                 outFile = null;
281             }
282         }
283         
284         public void run() {
285             while(true) {
286                 try {
287                     int x = in.read();
288                     if(x < 0) {
289                         break;
290                     }
291                     openOutput();
292                     if(out != null) {
293                         out.write(x);
294                     }
295                 } catch(IOException JavaDoc e) {
296                     // ignore
297
}
298             }
299             IOUtils.closeSilently(out);
300             IOUtils.closeSilently(in);
301             new File JavaDoc(processFile).delete();
302         }
303     }
304
305     void stopTask(FileObject file) {
306         String JavaDoc processName = file.getName();
307         log("kill process: " + processName);
308         Process JavaDoc p = (Process JavaDoc) tasks.remove(processName);
309         if(p == null) {
310             return;
311         }
312         p.destroy();
313     }
314
315 }
316
Popular Tags