1 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 36 public class Data implements ClientData, PoolableObject { 37 public static String 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 userRootHome = "dist"; 47 48 public static void setUserRootHome(String name) { 49 userRootHome = name; 50 } 51 52 private HashMap httpHeader; 53 private String 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 nonBlockingWriteDesc = null; 66 67 public boolean isHeaderReady() { 68 return httpHeader!=null; 69 } 70 71 public void initHeader(String 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 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 reqDir = (String ) 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 )httpHeader.get("FILE")); 108 } 109 if(file.isDirectory()) { 110 String reqDir = (String ) 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 getDirList() throws BadRequestException { 119 File file = getFile(); 120 File list[] = file.listFiles(); 121 String loc = (String )httpHeader.get("FILE"); 122 123 StringBuffer content = new StringBuffer (); 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 parent = file.getParent(); 131 parent = parent.replace('\\', '/'); 132 parent = MyString.replaceAll(parent, user_root, ""); 134 if(parent.equals("")) parent = "/"; 135 content.append("[<a HREF=\""+parent+"\">To Parent Directory</a>]"); 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 (list[i].lastModified())); 144 content.append("</td>"); 145 146 content.append("\r\n<td> </td>"); 147 148 content.append("\r\n<td align=\"right\">"); 149 if(list[i].isDirectory()) { 150 content.append(" <dir>"); 151 } else { 152 content.append(" "+list[i].length()); 153 } 154 content.append("</td>"); 155 156 content.append("\r\n<td> </td>"); 157 158 content.append("\r\n<td><a HREF=\""); 159 content.append(loc+list[i].getName()); 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 makeFileResponseHeader(ClientHandler handler) { 172 String range = (String ) httpHeader.get("RANGE"); 173 174 StringBuffer sb = new StringBuffer (); 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); 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 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 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 desc, boolean closeConWhenDone) throws IOException { 220 if(wrapedByteBuffer!=null) { 221 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 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 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 clean(); 281 } 282 } 283 284 public void writeData(ClientHandler handler) throws Exception { 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) { fileChannel.close(); 332 } 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 clean(); 358 } 359 return; } 361 pooledByteBuffer.compact(); handler.registerForWrite(); 363 } } 365 366 public void cleanPooledByteBuffer(QuickServer quickserver) { 367 if(pooledByteBuffer!=null) { 368 try { 369 quickserver.getByteBufferPool().returnObject(pooledByteBuffer); 370 } catch(Exception 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 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 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 makeObject() { 413 return new Data(); 414 } 415 public void passivateObject(Object obj) { 416 Data d = (Data)obj; 417 d.clean(); 418 } 419 public void destroyObject(Object obj) { 420 if(obj==null) return; 421 passivateObject(obj); 422 obj = null; 423 } 424 public boolean validateObject(Object obj) { 425 if(obj==null) 426 return false; 427 else 428 return true; 429 } 430 }; 431 } 432 } 433 434 435 | Popular Tags |