cziegeler    2003/02/07 03:21:00

  Added:       sourceresolve/src/java/org/apache/excalibur/source/impl
                        FileSource.java
  Log:
  Adding FileSource from cocoon
  
  Revision  Changes    Path
  1.1                  
avalon-excalibur/sourceresolve/src/java/org/apache/excalibur/source/impl/FileSource.java
  
  Index: FileSource.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.excalibur.source.impl;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.net.URL;
  import java.util.ConcurrentModificationException;
  import java.util.Map;
  
  import org.apache.excalibur.source.ModifiableSource;
  import org.apache.excalibur.source.SourceException;
  import org.apache.excalibur.source.impl.URLSource;
  
  /**
   * A {@link ModifiableSource} for 'file:/' system IDs.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Sylvain Wallez</a>
   * @version $Id: FileSource.java,v 1.1 2003/02/07 11:21:00 cziegeler Exp $
   */
  
  public class FileSource
      extends URLSource
      implements ModifiableSource {
  
      /**
       * Initialize a new object from a <code>URL</code>.
       * @param parameters This is optional
       */
      public void init(URL url,
                       Map parameters )
      throws IOException {
          super.init( url, parameters );
  
          if ( null == this.file ) {
              throw new IllegalArgumentException("Malformed url for a file source : " 
+ url);
          }
      }
  
      /**
       * Get the associated file
       */
      public File getFile() {
          return this.file;
      }
  
      /**
       * A file outputStream that will rename the temp file to the destination file 
upon close()
       * and discard the temp file upon cancel().
       */
      private class FileSourceOutputStream extends FileOutputStream {
  
          private File tmpFile;
          private boolean isClosed = false;
          private FileSource source;
  
          public FileSourceOutputStream(File tmpFile, FileSource source) throws 
IOException {
              super(tmpFile);
              this.tmpFile = tmpFile;
              this.source = source;
          }
  
          public void close() throws IOException {
              if (!this.isClosed) {
                  super.close();
                  try {
                      // Delete destination file
                      if (this.source.getFile().exists()) {
                          this.source.getFile().delete();
                      }
                      // Rename temp file to destination file
                      tmpFile.renameTo(this.source.getFile());
      
                  } finally {
                      // Ensure temp file is deleted, ie lock is released.
                      // If there was a failure above, written data is lost.
                      if (tmpFile.exists()) {
                          tmpFile.delete();
                      }
                      this.isClosed = true;
                  }
              }
  
          }
  
          public boolean canCancel() {
              return !this.isClosed;
          }
  
          public void cancel() throws Exception {
              if (this.isClosed) {
                  throw new IllegalStateException("Cannot cancel : outputstrem is 
already closed");
              }
  
              this.isClosed = true;
              super.close();
              this.tmpFile.delete();
          }
  
          public void finalize() {
              if (!this.isClosed && tmpFile.exists()) {
                  // Something wrong happened while writing : delete temp file
                  tmpFile.delete();
              }
          }
  
          public FileSource getSource() {
              return this.source;
          }
      }
  
      /**
       * Does this source actually exist ?
       *
       * @return true if the resource exists.
       */
      public boolean exists() {
          return this.file.exists();
      }
  
      /**
       * Get an <code>InputStream</code> where raw bytes can be written to.
       * The signification of these bytes is implementation-dependent and
       * is not restricted to a serialized XML document.
       *
       * Get an output stream to write to this source. The output stream returned
       * actually writes to a temp file that replaces the real one on close. This
       * temp file is used as lock to forbid multiple simultaneous writes. The
       * real file is updated atomically when the output stream is closed.
       *
       * @return a stream to write to
       * @throws ConcurrentModificationException if another thread is currently
       *         writing to this file.
       */
      public OutputStream getOutputStream()
      throws IOException, SourceException {
          // Create a temp file. It will replace the right one when writing terminates,
          // and serve as a lock to prevent concurrent writes.
          File tmpFile = new File(this.file.getPath() + ".tmp");
  
          // Ensure the directory exists
          tmpFile.getParentFile().mkdirs();
  
          // Can we write the file ?
          if (this.file.exists() && !this.file.canWrite()) {
              throw new IOException("Cannot write to file " + this.file.getPath());
          }
  
          // Check if it temp file already exists, meaning someone else currently 
writing
          if (!tmpFile.createNewFile()) {
              throw new ConcurrentModificationException("File " + this.file.getPath() +
                " is already being written by another thread");
          }
  
          // Return a stream that will rename the temp file on close.
          return new FileSourceOutputStream(tmpFile, this);
      }
  
      /**
       * Can the data sent to an <code>OutputStream</code> returned by
       * {@link #getOutputStream()} be cancelled ?
       *
       * @return true if the stream can be cancelled
       */
      public boolean canCancel(OutputStream stream) {
          if (stream instanceof FileSourceOutputStream) {
              FileSourceOutputStream fsos = (FileSourceOutputStream)stream;
              if (fsos.getSource() == this) {
                  return fsos.canCancel();
              }
          }
  
          // Not a valid stream for this source
          throw new IllegalArgumentException("The stream is not associated to this 
source");
      }
  
      /**
       * Cancel the data sent to an <code>OutputStream</code> returned by
       * {@link #getOutputStream()}.
       * <p>
       * After cancel, the stream should no more be used.
       */
      public void cancel(OutputStream stream) throws SourceException {
          if (stream instanceof FileSourceOutputStream) {
              FileSourceOutputStream fsos = (FileSourceOutputStream)stream;
              if (fsos.getSource() == this) {
                  try {
                      fsos.cancel();
                  } catch (Exception e) {
                      throw new SourceException("Exception during cancel.", e);
                  }
                  return;
              }
          }
  
          // Not a valid stream for this source
          throw new IllegalArgumentException("The stream is not associated to this 
source");
      }
  
      /**
       * Delete the source.
       */
      public boolean delete()  {
          return this.file.delete();
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to