1 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 ; 45 import java.nio.channels.FileLock ; 46 import java.util.logging.Level ; 47 import java.util.logging.Logger ; 48 49 52 public class FileInputOutput extends AbstractBinaryOutput 53 implements BinaryInput, BinaryOutput, Closeable 54 { 55 private static final Logger 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 _readEncodingName; 66 67 private FileLock _fileLock; 68 private FileChannel _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 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 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 136 public Path getPath() 137 { 138 return _path; 139 } 140 141 147 public void setEncoding(String encoding) 148 throws UnsupportedEncodingException 149 { 150 String 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 173 public void unread() 174 throws IOException 175 { 176 _doUnread = true; 177 } 178 179 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 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 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 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 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 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 308 public void print(char v) 309 throws IOException 310 { 311 _stream.write((byte) v); 312 } 313 314 317 public void print(String v) 318 throws IOException 319 { 320 for (int i = 0; i < v.length(); i++) 321 write(v.charAt(i)); 322 } 323 324 327 public void write(byte []buffer, int offset, int length) 328 throws IOException 329 { 330 _stream.write(buffer, offset, length); 331 } 332 333 336 public void write(int ch) 337 throws IOException 338 { 339 _stream.write(ch); 340 } 341 342 345 public void flush() 346 throws IOException 347 { 348 } 349 350 353 public void closeWrite() 354 { 355 close(); 356 } 357 358 361 public void closeRead() 362 { 363 close(); 364 } 365 366 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 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 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 433 public BinaryInput openCopy() 434 throws IOException 435 { 436 return new FileInputOutput(_env, _path); 437 } 438 439 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 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 494 public String toString() 495 { 496 return "FileInputOutput[" + getPath() + "]"; 497 } 498 } 499 500 | Popular Tags |