import java.io.*;
import java.util.*;
import java.net.*;

class FCache {
  private String base="c:\\jcache\\";

  public FCache(String host,String file,int port) {
    myPort=port;
    myFile=base+host+file;
    myOFile=file;
    myHost=host;

    // fix path for windows
    int p;
    while((p=myFile.indexOf('/'))>=0) {
      myFile=myFile.substring(0,p)+"\\"
        +myFile.substring(p+1,myFile.length());
    }

    // handle directory/default sites    
    if(myFile.lastIndexOf('.')<myFile.lastIndexOf('\\')) 
      myFile=myFile+".dir";
System.out.println("Got here");
    if(!exists(myFile)) {
      if(verify(myFile)) {
        write=true;
      }
      else {
        System.out.println("Can't write!");
      }
    }
    else  {
      if(!expired(myFile))
        good=true;
      else
        System.out.println("Expired--------------------");
    }
  }

  public boolean expired(String s) {
    File f=new File(s);
    Date d=new Date();
    Date d1=new Date(f.lastModified());
    d.setHours(d.getHours()-1);
    boolean result=d1.before(d);
System.out.println("pre:"+d1+":date:"+d+":"+result);

// else result keeps file if network does not respond
    if(!result)
      return false;
    else
      result=false;
System.out.println("Checking network date");
    // ***************** check network expiration date
    String myCmd="HEAD "+myOFile+" HTTP/1.0";
    // send request
    try {
      Socket so=new Socket(myHost,myPort);
      PrintWriter pOut=new PrintWriter(so.getOutputStream(),true);
      DataInputStream uin=new DataInputStream(so.getInputStream());
    
      pOut.println(myCmd);
      pOut.println();

      String s2;
      s2=uin.readLine();
      while(s2.length()!=0) { 
        if(s2.length()>14 && 
            s2.substring(0,13).toLowerCase().equals("last-modified")) {
          Date date=new Date(s2.substring(14,s2.length()));
          result=d1.before(date);
System.out.println(d1+":date:"+date);
        }
        s2=uin.readLine();
      }
    }
    catch(Exception e) {
      System.out.println(e);
      return false;
    }
System.out.println("Finished Checking network date:"+result);

    if(result) {
System.out.println(s+" Has expired --------------------");
      f.delete();
    }
    else
      updateFile(s);

    return result;
/*
    try {
      FileInputStream aInStream=new FileInputStream(s);
      DataInputStream uin=new DataInputStream(aInStream);

      s=uin.readLine();
      while(s.length()!=0) { 
        System.out.println("data:"+s);
        s=uin.readLine();
      }
      uin.close();
    }
    catch(Exception e) {
      return true;
    }
    return false;
*/
  }

  public boolean isCached() {
    return good;
  }

  public boolean canCache() {
    return write;
  }

  public boolean exists(String s) {
    File aFile=new File(s);
    try {
    if(aFile.exists() && aFile.isFile())
      return true;
    else
      return false;
    }
    catch(Exception e) {
      System.out.println("fcache.exists:"+e);
      return false;
    }
  }

  public String getName() {
    return myFile;
  }

  public boolean verify(String s) {
    File aFile=new File(s);
    if(aFile.exists()) {
     if(aFile.isDirectory())
        return true;
      else
        return false;
    }
    else {
      File nFile=new File(aFile.getParent());
      boolean result=true;
      if(!nFile.exists() && !nFile.mkdirs())
        return false;
      try {
        FileOutputStream fOut=new FileOutputStream(s); 
        fOut.close();
      }
      catch(Exception e) {
        System.out.println("FCache.verify:"+e);
        result=false;
      }
      return result;
    }
  } 

  public void updateFile(String s) {
    File f=new File(s);
    File temp=new File(s+".tmp");
    if(!temp.exists()) {
      f.renameTo(temp);
      try {
        FileInputStream fIn=new FileInputStream(s+".tmp");
        FileOutputStream fOut=new FileOutputStream(s);
        byte []buf=new byte[512];
        int len;
        while((len=fIn.read(buf))>0) {
          fOut.write(buf,0,len);
        }
        fOut.flush();
        fOut.close();
        fIn.close();
      }
      catch(Exception e) {
        System.out.println(e);
      }
      temp.delete();
    }
  }

  private String myFile;
  private String myOFile;
  private String myHost;
  private int myPort;
  private boolean write=false;
  private boolean good=false;
}