1 10 package org.mmbase.module; 11 12 import java.io.*; 13 import java.sql.Date ; 14 import java.util.Hashtable ; 15 16 import javax.servlet.http.HttpServletResponse ; 17 18 import org.mmbase.module.builders.NetFileSrv; 19 import org.mmbase.module.core.MMBase; 20 import org.mmbase.module.gui.html.scanparser; 21 import org.mmbase.util.*; 22 import org.mmbase.util.logging.*; 23 24 40 public class scancache extends Module implements scancacheInterface { 41 42 45 public static final int MAX_CACHE_POOL_SIZE = 200; 46 47 private static Logger log = Logging.getLoggerInstance(scancache.class.getName()); 49 50 private scanparser scanparser; 51 52 57 private static int defaultExpireTime = 21600; 58 59 66 Hashtable pools = new Hashtable (); 67 68 74 LRUHashtable timepool = new LRUHashtable(MAX_CACHE_POOL_SIZE*4); 75 76 78 82 MMBase mmbase; 83 87 boolean status=false; 88 89 93 private String cachepath=""; 94 95 98 public scancache() { 99 } 100 101 105 public void onload() { 106 } 107 108 112 public void shutdown() { 113 } 114 115 119 public void unload() { 120 } 121 122 126 public void init() { 127 String tmp=getInitParameter("status"); 128 log.debug("status "+tmp); 129 if (tmp!=null && tmp.equals("active")) status=true; 130 131 cachepath=getInitParameter("CacheRoot"); 132 if (cachepath==null) { 133 log.error("SCANCACHE -> No CacheRoot property set in the scancache.xml configuration file"); 135 } 136 mmbase=(MMBase)getModule("MMBASEROOT"); 137 144 scanparser=(scanparser)getModule("SCANPARSER"); 145 } 146 147 158 public String get(String poolName, String key,scanpage sp) { 159 if (status==false) return null; log.debug("poolName="+poolName+" key="+key); 161 if (poolName.equals("HENK")) { 162 String tmp=get(poolName,key,">",sp); 163 return tmp; 164 } else if (poolName.equals("PAGE")) { 165 return getPage(poolName,key); 166 } 167 log.error("get("+poolName+","+key+"): poolname("+poolName+") is an unknown cachetype!"); 168 return null; 169 } 170 171 184 205 221 public String get(String poolName, String key, String line,scanpage sp) { 222 if (status==false) return null; 224 String tmp=line.substring(0,line.indexOf('>')).trim(); 227 int interval = getExpireInterval(tmp); 228 229 int now=(int)(System.currentTimeMillis()/1000); 230 231 LRUHashtable pool=(LRUHashtable)pools.get(poolName); 233 if (pool!=null) { 234 String value=(String )pool.get(key); 235 if (value!=null) { 238 try { 239 Integer tmp2=(Integer )timepool.get(poolName+key); 241 int then=tmp2.intValue(); 242 log.debug("scancache -> file="+then+" now="+now 243 +" now-then="+(now-then)+" interval="+interval); 244 if (((now-then)-interval)<0) { 245 return value; 246 } else { 247 if (key.indexOf(".flashvar")<0) { 249 log.debug("get("+poolName+","+key+","+line+"): Request is expired, return old version"); 250 signalProcessor(sp,key); 252 return value; 253 } else return null; 254 } 255 } catch(Exception e) {} 256 } 257 } 258 fileInfo fileinfo=loadFile(poolName,key); 260 if (fileinfo!=null && fileinfo.value!=null) { 261 if (((now-fileinfo.time)-interval)>0) { 262 if (key.indexOf(".flashvar")>=0) { return null; 264 } 265 log.debug("get("+poolName+","+key+","+line+"): Diskfile expired for file("+fileinfo.time+"), now("+now+") and interval("+interval+") , return old version "); 266 signalProcessor(sp,key); 268 } 269 if (pool==null) { 270 pool=new LRUHashtable(MAX_CACHE_POOL_SIZE); 272 pools.put(poolName,pool); 273 } 274 pool.put(key,fileinfo.value); timepool.put(poolName+key,new Integer (fileinfo.time)); return fileinfo.value; 277 } 278 return null; 279 } 280 281 288 public long getExpireDate(String poolName, String key, String expireStr) { 289 int interval = getExpireInterval(expireStr); 290 return getLastModDate(poolName, key) + (interval * 1000); 291 } 292 293 299 public long getLastModDate(String poolName, String key) { 300 if (timepool.containsKey(poolName+key)) { 301 Integer tmp2=(Integer )timepool.get(poolName+key); 302 log.debug("scancache last modified in timepool " + (tmp2.intValue())); 303 return ((long)tmp2.intValue()) * 1000; 304 } 305 log.debug("scancache last modified NOT in timepool"); 306 return 0; } 308 309 314 private int getExpireInterval(String cacheExpire) { 315 int interval; 316 if ("".equals(cacheExpire)) { 317 interval = defaultExpireTime; 318 } 319 else { 320 if ("NOEXPIRE".equals(cacheExpire.toUpperCase())) { 321 interval = Integer.MAX_VALUE; 322 } 323 else { 324 try { 325 interval = Integer.parseInt(cacheExpire); 326 } 327 catch (NumberFormatException n) { 328 log.error("Number format exception for expiration time ("+cacheExpire+")"); 329 interval = defaultExpireTime; 330 } 331 } 332 } 333 log.debug("scancache expire interval: " + interval); 334 return interval; 335 } 336 337 348 private String getPage(String poolName, String key) { 349 if (status==false) return null; 350 fileInfo fileinfo=loadFile(poolName,key); 351 if (fileinfo!=null && fileinfo.value!=null) { 352 return fileinfo.value; 353 } else { 354 return null; 355 } 356 } 357 358 374 public String newput(String poolName,HttpServletResponse res, String key,String value, String mimeType) { 375 if (status==false) return null; LRUHashtable pool=(LRUHashtable)pools.get(poolName); 377 if (pool==null) { 378 pool=new LRUHashtable(); 380 pools.put(poolName,pool); 381 } 382 if (poolName.equals("HENK")) { 384 saveFile(poolName,key,value); 385 timepool.put(poolName+key,new Integer ((int)(System.currentTimeMillis()/1000))); return (String )pool.put(key,value); 387 } else if (poolName.equals("PAGE")) { 388 saveFile(poolName,key,value); 389 int pos=key.indexOf('?'); 391 String filename=key; 392 if (pos!=-1) { 393 filename=filename.replace('?',':'); 394 filename+=".asis"; 395 } else { 396 filename+=":.asis"; 397 } 398 String body=getWriteHeaders(value, mimeType); 402 body+=value; 403 saveFile(poolName,filename,body); 404 signalNetFileSrv(filename); 406 return (String )pool.put(key,value); 407 } 408 log.error("newPut("+poolName+",HttpServletRequest,"+key+","+value+"): poolname("+poolName+") is not a valid cache name!"); 409 return null; 410 } 411 412 426 public String newput2(String poolName,String key,String value,int cachetype, String mimeType) { 427 if (status==false) return null; LRUHashtable pool=(LRUHashtable)pools.get(poolName); 429 if (pool==null) { 430 pool=new LRUHashtable(); 432 pools.put(poolName,pool); 433 } 434 log.debug("newput2("+poolName+","+key+","+value+","+cachetype+"): NEWPUT"); 435 if (poolName.equals("HENK")) { 438 saveFile(poolName,key,value); 439 timepool.put(poolName+key,new Integer ((int)(System.currentTimeMillis()/1000))); return (String )pool.put(key,value); 442 } else if (poolName.equals("PAGE")) { 443 saveFile(poolName,key,value); 444 int pos=key.indexOf('?'); 447 String filename=key; 448 if (pos!=-1) { 449 filename=filename.replace('?',':'); 450 filename+=".asis"; 451 } else { 452 filename+=":.asis"; 453 } 454 String body=getWriteHeaders(value, mimeType); 456 body+=value; 457 log.debug("newput2("+poolName+","+key+","+value+","+cachetype+"): NEWPUT=SAVE"); 458 saveFile(poolName,filename,body); 459 if (cachetype!=0) signalNetFileSrv(filename); 460 return (String )pool.put(key,value); 461 } 462 log.error("newput2("+poolName+","+key+","+value+","+cachetype+"): poolName("+poolName+") is not a valid cachetype!"); 463 return null; 464 } 465 466 474 public String put(String poolName, String key,String value) { 475 if (status==false) return null; LRUHashtable pool=(LRUHashtable)pools.get(poolName); 477 if (pool==null) { 478 pool=new LRUHashtable(); 480 pools.put(poolName,pool); 481 } 482 saveFile(poolName,key,value); 484 485 return (String )pool.put(key,value); 486 } 487 488 public Hashtable state() { 489 493 return state; 494 } 495 496 499 public String getModuleInfo() { 500 return "This module provides cache functionality for text pages"; 501 } 502 503 511 private boolean saveFile(String pool,String filename,String value) { 512 log.debug("saveFile("+pool+","+filename+",length("+value.length()+" bytes): saving!"); 513 File sfile = new File(cachepath+pool+filename); 514 try { 515 DataOutputStream scan = new DataOutputStream(new FileOutputStream(sfile)); 516 scan.writeBytes(value); 517 scan.flush(); 518 scan.close(); 519 } catch(Exception e) { 520 String dname=cachepath+pool+filename; 523 int pos=dname.lastIndexOf('/'); 524 String dirname=dname.substring(0,pos); 525 File file = new File(dirname); 526 try { 527 if (file.mkdirs()) { 528 DataOutputStream scan = new DataOutputStream(new FileOutputStream(sfile)); 529 scan.writeBytes(value); 530 scan.flush(); 531 scan.close(); 532 } else { 533 log.error("scandisk cache -> making "+dirname+" failed "); 534 } 535 } catch (Exception f) { 536 log.error("scandisk cache -> Saving file "+filename+" failed "+f); 537 } 538 return false; 539 } 540 return true; 541 } 542 543 551 public fileInfo loadFile(String pool,String filename) { 552 fileInfo fileinfo=new fileInfo(); 553 try { 554 File sfile = new File(cachepath+pool+filename); 555 FileInputStream scan =new FileInputStream(sfile); 556 int filesize = (int)sfile.length(); 557 byte[] buffer=new byte[filesize]; 558 int len=scan.read(buffer,0,filesize); 559 if (len!=-1) { 560 String value=new String (buffer,0); 561 fileinfo.value=value; 562 fileinfo.time=(int)(sfile.lastModified()/1000); 563 log.debug("loadFile last modified " + sfile.lastModified()/1000); 564 return fileinfo; 565 } 566 scan.close(); 567 } catch(Exception e) { 568 return null; 570 } 571 return null; 572 } 573 574 580 public void signalNetFileSrv(String filename) { 581 log.debug("signalNetFileSrv("+filename+"): SIGNAL"); 582 if (mmbase!=null) { 583 NetFileSrv bul=(NetFileSrv)mmbase.getMMObject("netfilesrv"); 584 if (bul!=null) { 585 ((NetFileSrv)bul).fileChange("pages","main",filename); 586 } 587 } else { 588 log.error("signalNetFileSrv("+filename+"): can't use NetFileSrv builder"); 589 } 590 } 591 592 598 String getWriteHeaders(String value, String mimeType) { 599 if ((mimeType==null) || mimeType.equals("") || mimeType.equals("text/html")) 600 mimeType = "text/html; charset=\"iso-8859-1\""; 601 String now = RFC1123.makeDate(new Date (System.currentTimeMillis())); 602 String expireTime = RFC1123.makeDate(new Date (System.currentTimeMillis()+15000)); 603 String body="Status: 200 OK\n"; 604 body+="Server: OrionCache\n"; body+="Content-type: "+mimeType+"\n"; 606 body+="Content-length: "+value.length()+"\n"; 607 body+="Expires: "+expireTime+"\n"; 608 body+="Date: "+now+"\n"; 609 body+="Pragma: no-cache\n"; 613 body+="Last-Modified: "+now+"\n\n"; 614 return body; 615 } 616 617 624 public void remove(String poolName, String key) { 625 File file = new File(cachepath + poolName + key); 626 file.delete(); 627 LRUHashtable pool=(LRUHashtable)pools.get(poolName); 628 if (pool!=null) pool.remove(key); 629 timepool.remove(poolName + key); 630 } 631 632 636 public boolean getStatus() { 637 return status; 638 } 639 640 647 private void signalProcessor(scanpage sp, String uri) { 648 scanpage fakesp=sp.duplicate(); 649 scanparser.processPage(fakesp,uri); 650 } 651 } 652 | Popular Tags |