KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > file > FileInputOutput


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Emil Ong
28  */

29
30 package com.caucho.quercus.lib.file;
31
32 import com.caucho.quercus.env.BinaryBuilderValue;
33 import com.caucho.quercus.env.BinaryValue;
34 import com.caucho.quercus.env.Env;
35 import com.caucho.quercus.env.StringBuilderValue;
36 import com.caucho.quercus.env.StringValue;
37 import com.caucho.quercus.env.Value;
38 import com.caucho.vfs.Encoding;
39 import com.caucho.vfs.FilePath;
40 import com.caucho.vfs.Path;
41 import com.caucho.vfs.RandomAccessStream;
42
43 import java.io.*;
44 import java.nio.channels.FileChannel JavaDoc;
45 import java.nio.channels.FileLock JavaDoc;
46 import java.util.logging.Level JavaDoc;
47 import java.util.logging.Logger JavaDoc;
48
49 /**
50  * Represents a PHP open file
51  */

52 public class FileInputOutput extends AbstractBinaryOutput
53   implements BinaryInput, BinaryOutput, Closeable
54 {
55   private static final Logger JavaDoc log
56     = Logger.getLogger(FileInputOutput.class.getName());
57
58   private Env _env;
59   private Path _path;
60   private RandomAccessStream _stream;
61   private int _buffer;
62   private boolean _doUnread = false;
63
64   private Reader _readEncoding;
65   private String JavaDoc _readEncodingName;
66
67   private FileLock JavaDoc _fileLock;
68   private FileChannel JavaDoc _fileChannel;
69
70   private boolean _temporary;
71
72   public FileInputOutput(Env env, Path path)
73     throws IOException
74   {
75     this(env, path, false, false, false);
76   }
77
78   public FileInputOutput(Env env, Path path, boolean append, boolean truncate)
79     throws IOException
80   {
81     this(env, path, append, truncate, false);
82   }
83
84   public FileInputOutput(Env env, Path path,
85                          boolean append, boolean truncate, boolean temporary)
86     throws IOException
87   {
88     _env = env;
89     
90     env.addClose(this);
91     
92     _path = path;
93
94     if (truncate)
95       path.truncate(0L);
96
97     _stream = path.openRandomAccess();
98
99     if (append && _stream.getLength() > 0)
100       _stream.seek(_stream.getLength());
101
102     _temporary = temporary;
103   }
104
105   /**
106    * Returns the write stream.
107    */

108   public OutputStream getOutputStream()
109   {
110     try {
111       return _stream.getOutputStream();
112     } catch (IOException e) {
113       log.log(Level.FINE, e.toString(), e);
114
115       return null;
116     }
117   }
118
119   /**
120    * Returns the read stream.
121    */

122   public InputStream getInputStream()
123   {
124     try {
125       return _stream.getInputStream();
126     } catch (IOException e) {
127       log.log(Level.FINE, e.toString(), e);
128
129       return null;
130     }
131   }
132
133   /**
134    * Returns the path.
135    */

136   public Path getPath()
137   {
138     return _path;
139   }
140
141   /**
142    * Sets the current read encoding. The encoding can either be a
143    * Java encoding name or a mime encoding.
144    *
145    * @param encoding name of the read encoding
146    */

147   public void setEncoding(String JavaDoc encoding)
148     throws UnsupportedEncodingException
149   {
150     String JavaDoc mimeName = Encoding.getMimeName(encoding);
151     
152     if (mimeName != null && mimeName.equals(_readEncodingName))
153       return;
154     
155     _readEncoding = Encoding.getReadEncoding(getInputStream(), encoding);
156     _readEncodingName = mimeName;
157   }
158
159   private int readChar()
160     throws IOException
161   {
162     if (_readEncoding != null) {
163       int ch = _readEncoding.read();
164       return ch;
165     }
166
167     return read() & 0xff;
168   }
169
170   /**
171    * Unread a character.
172    */

173   public void unread()
174     throws IOException
175   {
176     _doUnread = true;
177   }
178
179   /**
180    * Reads a character from a file, returning -1 on EOF.
181    */

182   public int read()
183     throws IOException
184   {
185     if (_doUnread) {
186       _doUnread = false;
187
188       return _buffer;
189     } else {
190       _buffer = _stream.read();
191       
192       return _buffer;
193     }
194   }
195
196   /**
197    * Reads a buffer from a file, returning -1 on EOF.
198    */

199   public int read(byte []buffer, int offset, int length)
200     throws IOException
201   {
202     _doUnread = false;
203
204     return _stream.read(buffer, offset, length);
205   }
206
207   /**
208    * Reads a Binary string.
209    */

210   public BinaryValue read(int length)
211     throws IOException
212   {
213     BinaryBuilderValue bb = new BinaryBuilderValue();
214
215     while (length > 0) {
216       bb.prepareReadBuffer();
217
218       int sublen = bb.getLength() - bb.getOffset();
219
220       if (length < sublen)
221         sublen = length;
222
223       sublen = read(bb.getBuffer(), bb.getOffset(), sublen);
224
225       if (sublen > 0) {
226         bb.setOffset(bb.getOffset() + sublen);
227         length -= sublen;
228       }
229       else
230         return bb;
231     }
232
233     return bb;
234   }
235
236   /**
237    * Reads the optional linefeed character from a \r\n
238    */

239   public boolean readOptionalLinefeed()
240     throws IOException
241   {
242     int ch = read();
243
244     if (ch == '\n') {
245       return true;
246     }
247     else {
248       unread();
249       return false;
250     }
251   }
252
253  
254   /**
255    * Reads a line from the buffer.
256    */

257   public StringValue readLine(long length)
258     throws IOException
259   {
260     StringBuilderValue sb = new StringBuilderValue();
261
262     int ch;
263
264     InputStream is = getInputStream();
265
266     for (; length > 0 && (ch = readChar()) >= 0; length--) {
267       if (ch == '\n') {
268         sb.append((char) ch);
269         return sb;
270       }
271       else if (ch == '\r') {
272         sb.append('\r');
273
274         int ch2 = read();
275
276         if (ch2 == '\n')
277           sb.append('\n');
278         else
279           unread();
280
281         return sb;
282       }
283       else
284         sb.append((char) ch);
285     }
286
287     if (sb.length() == 0)
288       return null;
289     else
290       return sb;
291   }
292
293   /**
294    * Returns true on the EOF.
295    */

296   public boolean isEOF()
297   {
298     try {
299       return _stream.getFilePointer() == _stream.getLength() - 1;
300     } catch (IOException e) {
301       return true;
302     }
303   }
304     
305   /**
306    * Prints a string to a file.
307    */

308   public void print(char v)
309     throws IOException
310   {
311     _stream.write((byte) v);
312   }
313
314   /**
315    * Prints a string to a file.
316    */

317   public void print(String JavaDoc v)
318     throws IOException
319   {
320     for (int i = 0; i < v.length(); i++)
321       write(v.charAt(i));
322   }
323
324    /**
325    * Writes a buffer to a file.
326    */

327   public void write(byte []buffer, int offset, int length)
328     throws IOException
329   {
330     _stream.write(buffer, offset, length);
331   }
332
333   /**
334    * Writes a buffer to a file.
335    */

336   public void write(int ch)
337     throws IOException
338   {
339     _stream.write(ch);
340   }
341
342   /**
343    * Flushes the output.
344    */

345   public void flush()
346     throws IOException
347   {
348   }
349
350   /**
351    * Closes the file for writing.
352    */

353   public void closeWrite()
354   {
355     close();
356   }
357   
358   /**
359    * Closes the file for reading.
360    */

361   public void closeRead()
362   {
363     close();
364   }
365
366   /**
367    * Closes the file.
368    */

369   public void close()
370   {
371     try {
372       _stream.close();
373
374       if (_temporary)
375         _path.remove();
376     } catch (IOException e) {
377       log.log(Level.FINE, e.toString(), e);
378     }
379   }
380
381   /**
382    * Returns the current location in the file.
383    */

384   public long getPosition()
385   {
386     try {
387       return _stream.getFilePointer();
388     } catch (IOException e) {
389       log.log(Level.FINE, e.toString(), e);
390
391       return -1;
392     }
393   }
394
395   /**
396    * Sets the current location in the stream
397    */

398   public boolean setPosition(long offset)
399   {
400     _stream.seek(offset);
401
402     return true;
403   }
404
405   public long seek(long offset, int whence)
406   {
407     switch (whence) {
408       case BinaryInput.SEEK_CUR:
409         offset = getPosition() + offset;
410         break;
411       case BinaryInput.SEEK_END:
412         try {
413           offset = _stream.getLength() + offset;
414         } catch (IOException e) {
415           log.log(Level.FINE, e.toString(), e);
416
417           return getPosition();
418         }
419         break;
420       case SEEK_SET:
421       default:
422         break;
423     }
424
425     _stream.seek(offset);
426
427     return offset;
428   }
429
430   /**
431    * Opens a copy.
432    */

433   public BinaryInput openCopy()
434     throws IOException
435   {
436     return new FileInputOutput(_env, _path);
437   }
438
439   /**
440    * Lock the shared advisory lock.
441    */

442   public boolean lock(boolean shared, boolean block)
443   {
444     if (! (getPath() instanceof FilePath))
445       return false;
446
447     try {
448       File file = ((FilePath) getPath()).getFile();
449
450       if (_fileChannel == null) {
451         RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
452
453         _fileChannel = randomAccessFile.getChannel();
454       }
455
456       if (block)
457         _fileLock = _fileChannel.lock(0, Long.MAX_VALUE, shared);
458       else
459         _fileLock = _fileChannel.tryLock(0, Long.MAX_VALUE, shared);
460
461       return _fileLock != null;
462     } catch (IOException e) {
463       return false;
464     }
465   }
466
467   /**
468    * Unlock the advisory lock.
469    */

470   public boolean unlock()
471   {
472     try {
473       if (_fileLock != null) {
474         _fileLock.release();
475
476         return true;
477       }
478
479       return false;
480     } catch (IOException e) {
481       return false;
482     }
483   }
484
485   public Value stat()
486   {
487     return FileModule.statImpl(_env, getPath());
488   }
489
490   /**
491    * Converts to a string.
492    * @param env
493    */

494   public String JavaDoc toString()
495   {
496     return "FileInputOutput[" + getPath() + "]";
497   }
498 }
499
500
Popular Tags