KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > filesrv > Data


1 /*
2  * This file is part of the QuickServer library
3  * Copyright (C) 2003-2005 QuickServer.org
4  *
5  * Use, modification, copying and distribution of this software is subject to
6  * the terms and conditions of the GNU Lesser General Public License.
7  * You should have received a copy of the GNU LGP License along with this
8  * library; if not, you can download a copy from <http://www.quickserver.org/>.
9  *
10  * For questions, suggestions, bug-reports, enhancement-requests etc.
11  * visit http://www.quickserver.org
12  *
13  */

14
15 package filesrv;
16
17 import org.quickserver.net.*;
18 import org.quickserver.net.server.*;
19 import org.quickserver.util.MyString;
20
21 import org.quickserver.util.pool.PoolableObject;
22 import org.apache.commons.pool.BasePoolableObjectFactory;
23 import org.apache.commons.pool.PoolableObjectFactory;
24
25 import java.io.*;
26 import java.net.*;
27 import java.util.*;
28 import java.util.logging.*;
29 import java.nio.*;
30 import java.nio.channels.*;
31
32 /**
33  * FileServer Example
34  * @author Akshathkumar Shetty
35  */

36 public class Data implements ClientData, PoolableObject {
37     public static String JavaDoc serverIP = null;
38     private static Logger logger = Logger.getLogger(Data.class.getName());
39     static {
40         try {
41             serverIP = java.net.InetAddress.getLocalHost().getHostName();
42         } catch(UnknownHostException e) {
43             serverIP = "UnknownHost";
44         }
45     }
46     private static String JavaDoc userRootHome = "dist";
47
48     public static void setUserRootHome(String JavaDoc name) {
49         userRootHome = name;
50     }
51
52     private HashMap httpHeader;
53     private String JavaDoc user_root = userRootHome;
54     private ByteBuffer wrapedByteBuffer;
55     private ByteBuffer pooledByteBuffer;
56     private boolean sendFile = false;
57     private FileChannel fileChannel;
58
59     private long startRange = 0;
60     private long endRange = -1;
61     private long fileLength = -1;
62     private boolean wroteFileHttpHeader;
63     private boolean closeConWhenDone;
64
65     private String JavaDoc nonBlockingWriteDesc = null;
66
67     public boolean isHeaderReady() {
68         return httpHeader!=null;
69     }
70     
71     public void initHeader(String JavaDoc data) {
72         httpHeader = new HashMap();
73         int i = data.lastIndexOf(" HTTP/");
74         httpHeader.put("FILE", data.substring(4, i));
75     }
76
77     public boolean addHeader(String JavaDoc data) {
78         if(data.startsWith("GET /")) {
79             initHeader(data);
80             return false;
81         }
82
83         if(data.length()==0) return true;
84         int i = data.indexOf(": ");
85         if(i==-1) {
86             logger.warning("Got unknown header: "+data);
87             return false;
88         }
89
90         httpHeader.put(data.substring(0, i).toUpperCase(),
91             data.substring(i+2));
92         return false;
93     }
94
95     public File getFile() throws BadRequestException {
96         String JavaDoc reqDir = (String JavaDoc) httpHeader.get("FILE");
97         if(reqDir==null)
98             throw new BadRequestException("No File Requested!");
99         if(reqDir.length()==0) reqDir = File.separator;
100         return new File(user_root+reqDir);
101     }
102
103     public boolean isDirList() throws BadRequestException {
104         File file = getFile();
105         if(file.canRead()==false) {
106             logger.finest("File : "+file.getAbsolutePath());
107             throw new BadRequestException("File Not Found: "+(String JavaDoc)httpHeader.get("FILE"));
108         }
109         if(file.isDirectory()) {
110             String JavaDoc reqDir = (String JavaDoc) httpHeader.get("FILE");
111             if(reqDir.charAt(reqDir.length()-1)!='/') {
112                 httpHeader.put("FILE", reqDir+"/");
113             }
114         }
115         return file.isDirectory();
116     }
117
118     public String JavaDoc getDirList() throws BadRequestException {
119         File file = getFile();
120         File list[] = file.listFiles();
121         String JavaDoc loc = (String JavaDoc)httpHeader.get("FILE");
122
123         StringBuffer JavaDoc content = new StringBuffer JavaDoc();
124         content.append("<html>\r\n<head>\r\n<title>"+serverIP+" - "+loc+"</title>\r\n</head>\r\n<body>\r\n");
125         content.append("<H3>Filesrv Server - File List for "+serverIP+" - "+loc+"</H3>\r\n<hr/>\r\n");
126         content.append("<blockquote>\r\n<table width=\"80%\">");
127         
128         if(loc.equals("/")==false) {
129             content.append("\r\n<tr>\r\n<td colspan=\"5\">");
130             String JavaDoc parent = file.getParent();
131             parent = parent.replace('\\', '/');
132             //parent = parent.replaceAll("\\("+user_root+"\\)", "");
133
parent = MyString.replaceAll(parent, user_root, "");
134             if(parent.equals("")) parent = "/";
135             content.append("[<a HREF=\""+parent+"\">To Parent Directory</a>]"); //to fix
136
content.append("\r\n</td>\r\n</tr>");
137         }
138
139         for(int i=0;i<list.length;i++) {
140             content.append("\r\n<tr>");
141             
142             content.append("\r\n<td align=\"right\">");
143             content.append(new java.util.Date JavaDoc(list[i].lastModified()));
144             content.append("</td>");
145
146             content.append("\r\n<td>&nbsp;&nbsp;</td>");
147
148             content.append("\r\n<td align=\"right\">");
149             if(list[i].isDirectory()) {
150                 content.append(" &lt;dir&gt;");
151             } else {
152                 content.append(" "+list[i].length());
153             }
154             content.append("</td>");
155
156             content.append("\r\n<td>&nbsp;&nbsp;</td>");
157
158             content.append("\r\n<td><a HREF=\"");
159             content.append(loc+list[i].getName());//to fix
160
content.append("\">");
161             content.append(list[i].getName());
162             content.append("</a></td>");
163
164             content.append("\r\n</tr>");
165         }
166         content.append("\r\n</table>\r\n</blockquote>");
167         content.append("\r\n<hr/>\r\n</body>\r\n</html>");
168         return content.toString();
169     }
170
171     private String JavaDoc makeFileResponseHeader(ClientHandler handler) {
172         String JavaDoc range = (String JavaDoc) httpHeader.get("RANGE");
173
174         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
175
176         if(range==null || range.startsWith("bytes=")==false) {
177             sb.append("HTTP/1.1 200 OK\r\n");
178             sb.append("Content-Length: "+fileLength).append("\r\n");
179             startRange = 0;
180             endRange = fileLength-1;
181         } else {
182             try {
183                 range = range.substring(6); //skip bytes=
184
int i = range.indexOf("-");
185                 if(i==-1) i = range.length();
186                 startRange = Integer.parseInt(range.substring(0, i));
187                 i++;
188                 if(i<range.length()) {
189                     endRange = Integer.parseInt(range.substring(i));
190                 } else {
191                     endRange = fileLength-1;
192                 }
193             } catch(Exception JavaDoc e) {
194                 logger.finest("IGNORE Error: "+e);
195             }
196             sb.append("HTTP/1.1 206 Partial content\r\n");
197             sb.append("Content-Range: bytes "+startRange+"-"+endRange+
198                 "/"+fileLength+"\r\n");
199
200         }
201         sb.append("Server: ").append(handler.getServer().getName()).append("\r\n");
202         sb.append("Content-Type: application/octet-stream").append("\r\n");
203         sb.append("\r\n");
204         
205         return sb.toString();
206     }
207
208     public void sendFileNonBlocking(ClientHandler handler)
209             throws IOException, BadRequestException {
210         fileLength = getFile().length();
211         String JavaDoc header = makeFileResponseHeader(handler);
212         logger.fine("Will Send: \n"+header);
213
214         makeNonBlockingWrite(handler, header.getBytes(), true,
215             "Sending HTTP header for file.", false);
216     }
217
218     public void makeNonBlockingWrite(ClientHandler handler, byte data[],
219             boolean sendFileFlag, String JavaDoc desc, boolean closeConWhenDone) throws IOException {
220         if(wrapedByteBuffer!=null) {
221             //this client must have sent another req. with out waiting for res.. let close him..
222
throw new IOException("The old data was still not fully written sorry!");
223         }
224         wrapedByteBuffer = ByteBuffer.wrap(data);
225         sendFile = sendFileFlag;
226         nonBlockingWriteDesc = desc;
227         this.closeConWhenDone = closeConWhenDone;
228         handler.registerForWrite();
229     }
230
231     public void sendFileBlocking(ClientHandler handler)
232             throws IOException, BadRequestException {
233         File file = getFile();
234         
235         fileLength = file.length();
236         String JavaDoc header = makeFileResponseHeader(handler);
237         
238         FileInputStream in = null;
239         byte buffer[] = new byte[1024*1024];
240         try {
241             in = new FileInputStream(file);
242             if(startRange>0) {
243                 logger.finest("Will skip: "+startRange);
244                 in.skip(startRange);
245             }
246             int i = 0;
247             
248             i = in.read(buffer);
249             logger.finest("Sending HTTP header for file.");
250             handler.sendClientBytes(header);
251
252             handler.setDataMode(DataMode.BINARY, DataType.OUT);
253             logger.finest("Sending file data: "+file);
254             long remain = fileLength-startRange;
255             logger.finest("Remain: "+remain+", startRange: "+startRange+", i: "+i);
256
257             while(i!=-1 && remain!=0) {
258                 if(i>remain) i = (int) remain;
259
260                 handler.sendClientBinary(buffer,0, i);
261                 startRange+=i;
262
263                 remain = fileLength-startRange;
264                 i = in.read(buffer);
265                 logger.finest("Remain: "+remain+", startRange: "+startRange+", i: "+i);
266                 Thread.currentThread().yield();
267             }
268             logger.fine("Sent the file!");
269         } catch(Exception JavaDoc er) {
270             logger.info("Error sending file: "+er);
271         } finally {
272             if(in!=null) in.close();
273             handler.setDataMode(DataMode.BYTE, DataType.OUT);
274         }
275         
276         if(false) {
277             handler.closeConnection();
278         } else {
279             //so that we can take more req.
280
clean();
281         }
282     }
283
284     public void writeData(ClientHandler handler) throws Exception JavaDoc {
285         if(wrapedByteBuffer!=null && wrapedByteBuffer.remaining()!=0) {
286             logger.finest(nonBlockingWriteDesc);
287             int written = handler.getSocketChannel().write(wrapedByteBuffer);
288             logger.finest("Written "+written+" Bytes");
289             if(wrapedByteBuffer.remaining()!=0) {
290                 handler.registerForWrite();
291                 return;
292             }
293             wroteFileHttpHeader = true;
294             if(sendFile==false) {
295                 wrapedByteBuffer = null;
296                 if(closeConWhenDone) {
297                     handler.closeConnection();
298                 }
299                 return;
300             }
301         }
302         
303         if(sendFile==true) {
304             if(fileChannel==null) {
305                 File file = getFile();
306                 logger.finest("Sending file data: "+file);
307                 FileInputStream fin = new FileInputStream(file);
308                 fileChannel = fin.getChannel();
309                 fileChannel.position(startRange);
310             }
311             
312             if(pooledByteBuffer==null) {
313                 pooledByteBuffer = (ByteBuffer)
314                     handler.getServer().getByteBufferPool().borrowObject();
315             }
316
317             if(pooledByteBuffer.hasRemaining()) {
318                 int ret = -1;
319                 long remain = fileLength-startRange;
320                 logger.finest("Remain: "+remain);
321
322                 if(pooledByteBuffer.remaining()>remain) {
323                     pooledByteBuffer.limit(
324                         (int) (pooledByteBuffer.position()+remain) );
325                 }
326
327                 ret = fileChannel.read(pooledByteBuffer);
328
329                 logger.finest("Read "+ret+" Bytes from file");
330                 if(ret<0 || remain==0) {//EOF
331
fileChannel.close();
332                     //fileChannel = null;
333
} else {
334                     startRange+=ret;
335                 }
336             }
337             pooledByteBuffer.flip();
338             
339             if(pooledByteBuffer.hasRemaining()) {
340                 int written = handler.getSocketChannel().write(pooledByteBuffer);
341                 logger.finest("Written "+written+" Bytes to socket");
342             }
343
344             long remain = fileLength-startRange;
345             if(remain==0 && pooledByteBuffer.hasRemaining()==false) {
346                 fileChannel.close();
347             }
348
349             if(pooledByteBuffer.hasRemaining()==false && fileChannel.isOpen()==false) {
350                 sendFile = false;
351                 logger.finest("Sent the file!");
352                 
353                 if(false) {
354                     handler.closeConnection();
355                 } else {
356                     //so that we can take more req.
357
clean();
358                 }
359                 return; //work done
360
}
361             pooledByteBuffer.compact(); //In case of partial write
362
handler.registerForWrite();
363         } //end of sendFile
364
}
365
366     public void cleanPooledByteBuffer(QuickServer quickserver) {
367         if(pooledByteBuffer!=null) {
368             try {
369                 quickserver.getByteBufferPool().returnObject(pooledByteBuffer);
370             } catch(Exception JavaDoc er) {
371                 logger.warning("Could not return ByteBuffer back to pool: "+er);
372             }
373             pooledByteBuffer = null;
374         }
375     }
376
377     public boolean getWroteFileHttpHeader() {
378         return wroteFileHttpHeader;
379     }
380
381     //--- pool --
382
public void clean() {
383         httpHeader = null;
384         user_root = userRootHome;
385         wrapedByteBuffer = null;
386         if(pooledByteBuffer!=null) {
387             pooledByteBuffer.clear();
388         }
389         sendFile = false;
390         if(fileChannel!=null) {
391             try {
392                 fileChannel.close();
393             } catch(Exception JavaDoc er) {}
394             fileChannel = null;
395         }
396         startRange = 0;
397         endRange = -1;
398         fileLength = -1;
399         wroteFileHttpHeader = false;
400
401         nonBlockingWriteDesc = null;
402         closeConWhenDone = false;
403     }
404
405
406     public boolean isPoolable() {
407         return true;
408     }
409
410     public PoolableObjectFactory getPoolableObjectFactory() {
411         return new BasePoolableObjectFactory() {
412             public Object JavaDoc makeObject() {
413                 return new Data();
414             }
415             public void passivateObject(Object JavaDoc obj) {
416                 Data d = (Data)obj;
417                 d.clean();
418             }
419             public void destroyObject(Object JavaDoc obj) {
420                 if(obj==null) return;
421                 passivateObject(obj);
422                 obj = null;
423             }
424             public boolean validateObject(Object JavaDoc obj) {
425                 if(obj==null)
426                     return false;
427                 else
428                     return true;
429             }
430         };
431     }
432 }
433
434
435
Popular Tags