Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: raining/server/FileInfo.java


1   package raining.server;
2   import raining.core.*;
3   import raining.protocol.http.*;
4   import raining.util.*;
5   import java.util.*;
6   import java.io.*;
7   import java.nio.ByteBuffer;
8   /** Maintains cacheable information of a file such as content, when last
9    * updated in cache, and methods to update the cache, and tell the cache
10   * if it needs updating.
11   * TODO: should store as ByteBuffers
12   *       also i can keep header and content separate, and use a gathered
13   *       write. First i need to change that in NioSocket. <br>
14   * TODO: server_root needs to be set, i think.
15   * RK modified on 20031116 14:44:39: header is now part of content.
16   *
17   * Taken from Bulka's code (Java Performance and Scalability)
18   * and modified.
19   * This needs to be redone. The server sample wasn't written in an OO
20   * manner.
21   * I need to look into caching the header. Currently headers are managed by
22   * HTTPResponse implementations.
23   * We need to have a CachedObject interface with a needsRefreshing and
24   * update() contract.
25   */
26  public class FileInfo {
27      /** HTTP header.
28       * ignored for the present. header is now part of content.
29       */
30      private byte[] headers;
31      /** file content along with header.
32       */
33      //protected byte[] content;
34      protected ByteBuffer content;
35      /** when was the content last updated.
36       */
37      protected long lastUpdate;
38      /** when was the file updated - required for if-modified-since -
39       * this is a cached time.
40       */
41      protected long lastModified;
42      /** unused currently
43       */
44      private byte[] logSecondHalf;
45      /** the url or filename associated with this object. No longer
46       * required to be stored since the File object is being stored. But
47       * maybe can be kept for some time.
48       */
49      protected String url = null;
50      /** file object, stored here since its required to check whether the
51       * file has been modified or not since it was last read up.
52       */
53      protected File targ;
54  
55      /** constructor taking a header but no content. 
56       * why would you use this ?
57       * @param h byte[] h  header 
58       * @param lu long   lu time updated in cache
59       * @param u url of file
60       */
61      public FileInfo (byte[] h, long lu, String u) {
62          this.url = u;
63          this.targ = urlToFile (url);
64          this.lastModified = this.targ.lastModified();
65          headers = h;
66          content = null;
67          lastUpdate = lu;
68          logSecondHalf = null;
69      }
70      /** constructor taking header and content and url. 
71       * Header and content are concatenated and stored as content.
72       * This approach exists if you
73       * wish to keep sending fresh headers with current/lazy date.
74       * however, i wish to keep static headers. need to ascertain whether
75       * this breaks the rfc.
76       * @param h   header 
77       * @param c   content 
78       * @param u   url
79       */
80      public FileInfo (byte[] h, byte[] c, String u) {
81          this.url = u;
82          this.targ = urlToFile (url);
83          this.lastModified = this.targ.lastModified();
84          headers = h;
85          byte [] tmpcontent;
86          if (h == null)
87              tmpcontent = c;
88          else
89              tmpcontent = join (h, c);
90          this.content = ByteBuffer.wrap(tmpcontent);
91  
92          this.lastUpdate = System.currentTimeMillis();
93          this.logSecondHalf = null;
94      }
95      /** constructor that takes only filename. 
96       * This allows us to create
97       * the OK header since that needs file date also.
98       */
99      public FileInfo (String u) {
100         this.url = u;
101         this.targ = urlToFile (url);
102         this.lastModified = this.targ.lastModified();
103         //this.content = ByteBuffer.wrap(getBytes(url));
104         lastUpdate = System.currentTimeMillis();
105         logSecondHalf = null;
106     }
107     /** static method to get a file info object.
108      * @param url String url name of file
109      * @return FileInfo file info object
110      */
111     public static FileInfo getFileInfo (String url) throws java.io.IOException {
112 
113         byte[] tmp = getBytes(url);
114         FileInfo fi = new FileInfo( url );
115         Response resp = new HttpOKResponse( null,  tmp, fi.lastModified );
116         fi.setContent(resp.getBytes());
117         return fi;
118     }
119     /** updates the cache whenever the file is updated. 
120      * this also recreates the header RK modified on 20031116 14:44:11
121      */
122     public void update() throws java.io.IOException {
123         byte[] tmp = getBytes(this.url);
124         Response resp = new HttpOKResponse( null,  tmp, this.lastModified );
125         this.content = ByteBuffer.wrap(resp.getBytes());
126         this.lastUpdate = System.currentTimeMillis();
127     }
128     // a file can be deleted after caching
129     /** read up the files contents into a byte array.
130      * why am i adding the CRLF at start. doesnt the header have that at
131      * end already. RK 20031116 15:12:54
132      * @param url files url
133      * @return byte array file content.
134      */
135     public static byte[] getBytes (String url) throws java.io.IOException{
136         File targ = urlToFile (url);
137         byte b[] = null;
138         InputStream is = null;
139         try {
140             is = new FileInputStream(targ.getAbsolutePath());
141             int n;
142             b = new byte[2+(int)targ.length()];
143             byte [] buf = new byte[2048];
144             b[0] = (byte) '\r';
145             b[1] = (byte) '\n';
146             int blen = 2;
147             while ((n = is.read(buf)) > 0) {
148                 //ps.write(buf, 0, n);
149                 // Assuming everything fits in a single buffer...
150                 System.arraycopy(buf,0,b,blen,n);
151                 blen += n;
152             }
153         } catch (FileNotFoundException exc) { 
154             //System.err.println(  "throwing exc!"+ exc.toString());
155             
156             throw exc;
157         } catch (IOException exc) { System.err.println( P+" L 135 EXC:"+ exc.toString()); exc.printStackTrace();  
158         } finally {
159             try {
160             is.close();
161             } catch (Exception ignoredexc) { } 
162         }
163         return b;
164     }
165 
166 
167     public void setHeaders(byte[] h) {
168         headers = h;
169     }
170     public void setContent(byte[] c) {
171         content = ByteBuffer.wrap(c);
172     }
173     public void setContent(ByteBuffer c) {
174         content = c;
175     }
176     public void setLastUpdate(long t) {
177         lastUpdate = t;
178     }
179     public void setLogSecondHalf(byte[] s) {
180         logSecondHalf = s;
181     }
182     public byte[] getHeaders() {
183         return headers;
184     }
185     /** returns content as a ByteByffer, after duplicating the buffer.
186      * Thus, multiple threads may use the same at a time.
187      */
188     public ByteBuffer getContent() {
189         return content.duplicate();
190     }
191     public long getLastUpdate() {
192         return lastUpdate;
193     }
194     public byte[] getLogSecondHalf() {
195         return logSecondHalf;
196     }
197     public static File urlToFile(String url) {
198         String fname = url.replace('/', File.separatorChar);
199         if (fname.startsWith(File.separator)) {
200             fname = fname.substring(1);
201         }
202         File targ = new File(server_root, fname);
203         if (targ.isDirectory()) {
204             File ind = new File(targ, "index.html");
205             if (ind.exists()) {
206                 targ = ind;
207             }
208         }
209         return targ;
210     }
211     public static String server_root = null;
212 
213     /*
214     public void needsRefreshing (boolean b){
215         needsRefreshing = b;
216     }
217     */
218     /** returns true if the files actual lastModified is greater than
219      * the cache update time.
220      * This invokes an expensive system call to find out file update
221      * time.
222      */
223     public boolean needsRefreshing (){
224         return targ.lastModified()>lastUpdate;
225     }
226 
227     /** joins 2 byte arrays and returns a new array.
228      * written for the ctor that takes header and content as separate
229      * arrays. 
230      */
231     public static byte[] join (byte[] a, byte b[]){
232 
233         assert a != null : "Received a null byte array"       ;
234         byte[] n = new byte[ a.length + b.length ];
235         System.arraycopy(a, 0, n, 0, a.length);
236         System.arraycopy(b, 0, n, a.length, b.length);
237         return n;
238 
239     }
240     /** returns true if the file has been modified since the
241      * time requested by the user (in if-Modified-Since field of
242      * header).
243      */
244     public boolean ifModifiedSince (long requestedTime){
245         return lastModified > requestedTime;
246     }
247 
248     public static void main (String args[]){ 
249 
250         if (args.length==0){
251             System.out.println(  "pls give a file name");
252             System.exit(-1);
253         }
254             
255         try {
256             FileInfo fi = FileInfo.getFileInfo(args[0]);
257             System.out.println(  fi.getContent());
258             //System.out.println(  new String(fi.getContent()));
259             System.out.println( " needs:" + fi.needsRefreshing());
260             try {
261                 Thread.sleep(15000);
262             } catch (Exception exc) { System.err.println( " L EXC:"+ exc.toString()); exc.printStackTrace(); } 
263             System.out.println( " needs:" + fi.needsRefreshing());
264         } catch (Exception exc) { System.err.println( " L EXC:"+ exc.toString()); exc.printStackTrace(); } 
265     }
266 
267 
268 
269     private static final String P = "FileInfo";
270         
271             /*
272         // RFC 822 and RFC 1123
273     SimpleDateFormat fo =
274       new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
275     fo.setTimeZone(TimeZone.getTimeZone("GMT"));
276                 requests.setIfNotSet("If-Modified-Since", fo.format(date));
277                 */
278 
279 }