1 17 package org.apache.excalibur.source.impl; 18 19 import java.io.File ; 20 import java.io.FileInputStream ; 21 import java.io.FileNotFoundException ; 22 import java.io.FileOutputStream ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.OutputStream ; 26 import java.net.MalformedURLException ; 27 import java.net.URLConnection ; 28 import java.util.Arrays ; 29 import java.util.Collection ; 30 import java.util.ConcurrentModificationException ; 31 32 import org.apache.excalibur.source.ModifiableSource; 33 import org.apache.excalibur.source.ModifiableTraversableSource; 34 import org.apache.excalibur.source.MoveableSource; 35 import org.apache.excalibur.source.Source; 36 import org.apache.excalibur.source.SourceException; 37 import org.apache.excalibur.source.SourceNotFoundException; 38 import org.apache.excalibur.source.SourceUtil; 39 import org.apache.excalibur.source.SourceValidity; 40 import org.apache.excalibur.source.impl.validity.FileTimeStampValidity; 41 42 48 49 public class FileSource implements ModifiableTraversableSource, MoveableSource 50 { 51 52 53 private File m_file; 54 55 56 private String m_scheme; 57 58 59 private String m_uri; 60 61 67 public FileSource(String uri) throws SourceException, MalformedURLException 68 { 69 int pos = SourceUtil.indexOfSchemeColon(uri); 70 if (pos == -1) 71 { 72 throw new MalformedURLException ("Invalid URI : " + uri); 73 } 74 75 String scheme = uri.substring(0, pos); 76 String fileName = uri.substring(pos + 1); 77 fileName = SourceUtil.decodePath(fileName); 78 init(scheme, new File (fileName)); 79 } 80 81 88 public FileSource(String scheme, File file) throws SourceException 89 { 90 init(scheme, file); 91 } 92 93 private void init(String scheme, File file) throws SourceException 94 { 95 m_scheme = scheme; 96 97 String uri; 98 try 99 { 100 uri = file.toURL().toExternalForm(); 101 } 102 catch (MalformedURLException mue) 103 { 104 throw new SourceException("Failed to get URL for file " + file, mue); 106 } 107 108 if (!uri.startsWith(scheme)) 109 { 110 uri = scheme + ':' + uri.substring(uri.indexOf(':') + 1); 112 } 113 114 m_uri = uri; 115 116 m_file = file; 117 } 118 119 122 public File getFile() 123 { 124 return m_file; 125 } 126 127 131 134 public long getContentLength() 135 { 136 return m_file.length(); 137 } 138 139 142 public InputStream getInputStream() throws IOException , SourceNotFoundException 143 { 144 try 145 { 146 return new FileInputStream (m_file); 147 } 148 catch (FileNotFoundException fnfe) 149 { 150 throw new SourceNotFoundException(m_uri + " doesn't exist.", fnfe); 151 } 152 } 153 154 157 public long getLastModified() 158 { 159 return m_file.lastModified(); 160 } 161 162 165 public String getMimeType() 166 { 167 return URLConnection.getFileNameMap().getContentTypeFor(m_file.getName()); 168 } 169 170 173 public String getScheme() 174 { 175 return m_scheme; 176 177 } 178 179 182 public String getURI() 183 { 184 return m_uri; 185 } 186 187 192 public SourceValidity getValidity() 193 { 194 if (m_file.exists()) 195 { 196 return new FileTimeStampValidity(m_file); 197 } 198 else 199 { 200 return null; 201 } 202 } 203 204 207 public void refresh() 208 { 209 } 211 212 217 public boolean exists() 218 { 219 return getFile().exists(); 220 } 221 222 226 229 public Source getChild(String name) throws SourceException 230 { 231 if (!m_file.isDirectory()) 232 { 233 throw new SourceException(getURI() + " is not a directory"); 234 } 235 236 return new FileSource(this.getScheme(), new File (m_file, name)); 237 238 } 239 240 243 public Collection getChildren() throws SourceException 244 { 245 246 if (!m_file.isDirectory()) 247 { 248 throw new SourceException(getURI() + " is not a directory"); 249 } 250 251 File [] files = m_file.listFiles(); 253 254 FileSource[] children = new FileSource[files.length]; 255 for (int i = 0; i < files.length; i++) 256 { 257 children[i] = new FileSource(this.getScheme(), files[i]); 258 } 259 260 return Arrays.asList(children); 262 } 263 264 267 public String getName() 268 { 269 return m_file.getName(); 270 } 271 272 275 public Source getParent() throws SourceException 276 { 277 return new FileSource(getScheme(), m_file.getParentFile()); 278 } 279 280 283 public boolean isCollection() 284 { 285 return m_file.isDirectory(); 286 } 287 288 292 306 public OutputStream getOutputStream() throws IOException 307 { 308 File tmpFile = new File (getFile().getPath() + ".tmp"); 311 312 tmpFile.getParentFile().mkdirs(); 314 315 if (getFile().exists() && !getFile().canWrite()) 317 { 318 throw new IOException ("Cannot write to file " + getFile().getPath()); 319 } 320 321 if (!tmpFile.createNewFile()) 323 { 324 throw new ConcurrentModificationException ( 325 "File " + getFile().getPath() + " is already being written by another thread"); 326 } 327 328 return new FileSourceOutputStream(tmpFile, this); 330 } 331 332 338 public boolean canCancel(OutputStream stream) 339 { 340 if (stream instanceof FileSourceOutputStream) 341 { 342 FileSourceOutputStream fsos = (FileSourceOutputStream) stream; 343 if (fsos.getSource() == this) 344 { 345 return fsos.canCancel(); 346 } 347 } 348 349 throw new IllegalArgumentException ("The stream is not associated to this source"); 351 } 352 353 359 public void cancel(OutputStream stream) throws SourceException 360 { 361 if (stream instanceof FileSourceOutputStream) 362 { 363 FileSourceOutputStream fsos = (FileSourceOutputStream) stream; 364 if (fsos.getSource() == this) 365 { 366 try 367 { 368 fsos.cancel(); 369 } 370 catch (Exception e) 371 { 372 throw new SourceException("Exception during cancel.", e); 373 } 374 return; 375 } 376 } 377 378 throw new IllegalArgumentException ("The stream is not associated to this source"); 380 } 381 382 385 public void delete() throws SourceException 386 { 387 if (!m_file.exists()) 388 { 389 throw new SourceNotFoundException("Cannot delete non-existing file " + m_file.toString()); 390 } 391 392 if (!m_file.delete()) 393 { 394 throw new SourceException("Could not delete " + m_file.toString() + " (unknown reason)"); 395 } 396 } 397 398 402 405 public void makeCollection() throws SourceException 406 { 407 m_file.mkdirs(); 408 } 409 410 414 417 public void copyTo(Source destination) throws SourceException 418 { 419 try 420 { 421 SourceUtil.copy(this.getInputStream(), ((ModifiableSource) destination).getOutputStream()); 422 } 423 catch (IOException ioe) 424 { 425 throw new SourceException("Couldn't copy " + getURI() + " to " + destination.getURI(), ioe); 426 } 427 } 428 429 432 public void moveTo(Source destination) throws SourceException 433 { 434 if (destination instanceof FileSource) 435 { 436 final File dest = ((FileSource) destination).getFile(); 437 final File parent = dest.getParentFile(); 438 439 if (parent != null) 440 { 441 parent.mkdirs(); } 443 444 if (!m_file.renameTo(dest)) 445 { 446 throw new SourceException("Couldn't move " + getURI() + " to " + destination.getURI()); 447 } 448 } 449 else 450 { 451 SourceUtil.move(this, destination); 452 } 453 454 } 455 456 460 464 private static class FileSourceOutputStream extends FileOutputStream 465 { 466 467 private File m_tmpFile; 468 private boolean m_isClosed = false; 469 private FileSource m_source; 470 471 public FileSourceOutputStream(File tmpFile, FileSource source) throws IOException 472 { 473 super(tmpFile); 474 m_tmpFile = tmpFile; 475 m_source = source; 476 } 477 478 public void close() throws IOException 479 { 480 if (!m_isClosed) 481 { 482 super.close(); 483 try 484 { 485 if (m_source.getFile().exists()) 487 { 488 m_source.getFile().delete(); 489 } 490 if (!m_tmpFile.renameTo(m_source.getFile())) 492 { 493 throw new IOException ("Could not rename " + 494 m_tmpFile.getAbsolutePath() + 495 " to " + m_source.getFile().getAbsolutePath()); 496 } 497 498 } 499 finally 500 { 501 if (m_tmpFile.exists()) 504 { 505 m_tmpFile.delete(); 506 } 507 m_isClosed = true; 508 } 509 } 510 511 } 512 513 public boolean canCancel() 514 { 515 return !m_isClosed; 516 } 517 518 public void cancel() throws Exception 519 { 520 if (m_isClosed) 521 { 522 throw new IllegalStateException ("Cannot cancel : outputstrem is already closed"); 523 } 524 525 m_isClosed = true; 526 super.close(); 527 m_tmpFile.delete(); 528 } 529 530 public void finalize() 531 { 532 if (!m_isClosed && m_tmpFile.exists()) 533 { 534 m_tmpFile.delete(); 536 } 537 } 538 539 public FileSource getSource() 540 { 541 return m_source; 542 } 543 } 544 } 545 | Popular Tags |