All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.forge.resource.AbstractFileResource Maven / Gradle / Ivy

package org.jboss.forge.resource;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.jboss.forge.container.util.Assert;
import org.jboss.forge.container.util.OperatingSystemUtils;
import org.jboss.forge.resource.events.ResourceCreated;
import org.jboss.forge.resource.events.ResourceDeleted;
import org.jboss.forge.resource.events.ResourceModified;
import org.jboss.forge.resource.events.ResourceRenamed;
import org.jboss.forge.resource.events.TempResourceCreated;

/**
 * A standard, built-in resource for representing files on the filesystem.
 *
 * @author Mike Brock
 * @author Lincoln Baxter, III
 */
public abstract class AbstractFileResource> extends AbstractResource implements
         FileResource
{
   protected File file;
   protected long lastModification;

   protected AbstractFileResource(final ResourceFactory factory, final File file)
   {
      super(factory, null);

      if ((this.file = file) != null)
      {
         this.lastModification = file.lastModified();
      }
   }

   @Override
   public String getName()
   {
      return file.getName();
   }

   @Override
   public String toString()
   {
      return getFullyQualifiedName();
   }

   /**
    * Get the actual underlying file resource that this resource instance represents, whether existing or non-existing.
    *
    * @return An instance of {@link File}
    */
   @Override
   public File getUnderlyingResourceObject()
   {
      return file;
   }

   @Override
   public InputStream getResourceInputStream()
   {
      try
      {
         return new BufferedInputStream(new FileInputStream(file));
      }
      catch (FileNotFoundException e)
      {
         throw new ResourceException("cannot obtain stream to file: file does not exist: " + file.getAbsolutePath());
      }
   }

   /**
    * Get the parent of the current resource. Returns null if the current resource is the project root.
    *
    * @return An instance of the resource parent.
    */
   @Override
   public DirectoryResource getParent()
   {
      return file.getParentFile() != null ? resourceFactory.create(DirectoryResource.class, file.getParentFile())
               : null;
   }

   @Override
   public Resource getChild(final String name)
   {
      throw new ResourceException("[" + this.getClass().getSimpleName() + "] can have no children");
   }

   /**
    * Create a new {@link Resource} instance for the target file. The new {@link Resource} should be of the same type as
    * this.
    *
    * @param file The file to create the resource instance from.
    * @return A new resource.
    */
   @Override
   public abstract Resource createFrom(File file);

   @Override
   public boolean exists()
   {
      return getUnderlyingResourceObject().exists();
   }

   /**
    * Return true if this {@link AbstractFileResource} exists and is actually a directory, otherwise return false;
    */
   @Override
   public boolean isDirectory()
   {
      return file.isDirectory();
   }

   /**
    * Returns true if the underlying resource has been modified on the file system since it was initially loaded.
    *
    * @return boolean true if resource is changed.
    */
   @Override
   public boolean isStale()
   {
      return lastModification != getUnderlyingResourceObject().lastModified();
   }

   /**
    * Re-read the last modified timestamp for this resource.
    */
   @Override
   public void markUpToDate()
   {
      lastModification = getUnderlyingResourceObject().lastModified();
   }

   /**
    * Create a new single directory for this resource. This will not succeed if any parent directories needed for this
    * resource to exist are missing. You should consider using {@link #mkdirs()}
    */
   @Override
   public boolean mkdir()
   {
      if (file.mkdir())
      {
         resourceFactory.fireEvent(new ResourceCreated(this));
         return true;
      }
      return false;
   }

   /**
    * Create all directories required for this resource to exist.
    */
   @Override
   public boolean mkdirs()
   {
      if (file.mkdirs())
      {
         resourceFactory.fireEvent(new ResourceCreated(this));
         return true;
      }
      return false;
   }

   /**
    * Delete this file, non-recursively.
    */
   @Override
   public boolean delete()
   {
      return delete(false);
   }

   /**
    * Delete this {@link Resource}, and all child resources.
    */
   @Override
   public boolean delete(final boolean recursive)
   {
      if (recursive)
      {
         if (_deleteRecursive(file, true))
         {
            resourceFactory.fireEvent(new ResourceDeleted(this));
            return true;
         }
         return false;
      }

      if ((file.listFiles() != null) && (file.listFiles().length != 0))
      {
         throw new RuntimeException("directory not empty");
      }

      if (OperatingSystemUtils.isWindows())
      {
         System.gc(); // ensure no lingering handles that would prevent deletion
      }

      if (file.delete())
      {
         resourceFactory.fireEvent(new ResourceDeleted(this));
         return true;
      }
      return false;
   }

   /**
    * Requests that the file or directory denoted by this resource be deleted when the virtual machine terminates.
    * 

* Once deletion has been requested, it is not possible to cancel the request. This method should therefore be used * with care. */ @Override public void deleteOnExit() { file.deleteOnExit(); } private static boolean _deleteRecursive(final File file, final boolean collect) { if (collect && OperatingSystemUtils.isWindows()) { System.gc(); // ensure no lingering handles that would prevent deletion } if (file == null) { return false; } File[] children = file.listFiles(); if (children != null) { for (File sf : children) { if (sf.isDirectory()) { _deleteRecursive(sf, false); } else { if (!sf.delete()) { throw new RuntimeException("failed to delete: " + sf.getAbsolutePath()); } } } } return file.delete(); } /** * Set the contents of this {@link AbstractFileResource} to the given {@link String} */ @Override public T setContents(String data) { if (data == null) { data = ""; } return setContents(data.toCharArray()); } /** * Set the contents of this {@link AbstractFileResource} to the given character array. */ @Override public T setContents(final char[] data) { return setContents(new ByteArrayInputStream(new String(data).getBytes())); } @Override @SuppressWarnings("unchecked") /** * Set the contents of this {@link FileResource} to the contents of the given {@link InputStream}. */ public T setContents(final InputStream data) { Assert.notNull(data, "InputStream must not be null."); try { if (!exists()) { mkdirs(); delete(); if (!createNewFile()) { throw new IOException("Failed to create file: " + file); } } file.delete(); OutputStream out = new FileOutputStream(file); try { byte buf[] = new byte[1024]; int len; while ((len = data.read(buf)) > 0) { out.write(buf, 0, len); } } finally { if (data != null) data.close(); out.flush(); out.close(); if (OperatingSystemUtils.isWindows()) { System.gc(); } } resourceFactory.fireEvent(new ResourceModified(this)); } catch (IOException e) { throw new ResourceException(e); } return (T) this; } /** * Create the file in the underlying resource system. Necessary directory paths will be created automatically. */ @Override public boolean createNewFile() { try { if (file.mkdirs()) { file.delete(); } if (file.createNewFile()) { resourceFactory.fireEvent(new ResourceCreated(this)); return true; } return false; } catch (IOException e) { throw new ResourceException(e); } } @Override @SuppressWarnings("unchecked") /** * Create a temporary {@link FileResource} */ public T createTempResource() { try { T result = (T) createFrom(File.createTempFile("forgetemp", "")); resourceFactory.fireEvent(new TempResourceCreated(result)); return result; } catch (IOException e) { throw new ResourceException(e); } } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public > R reify(final Class type) { Resource result = resourceFactory.create((Class) type, file); if (type.isAssignableFrom(result.getClass())) { return (R) result; } else { return null; } } /** * Rename this resource to the given path. */ @Override public boolean renameTo(final String pathspec) { return renameTo(new File(pathspec)); } /** * Rename this resource to the given {@link AbstractFileResource} */ @Override public boolean renameTo(final FileResource target) { return renameTo(target.getUnderlyingResourceObject()); } /** * Rename this resource to the given {@link File} name. */ private boolean renameTo(final File target) { File original = file.getAbsoluteFile(); if (file.renameTo(target)) { resourceFactory.fireEvent(new ResourceRenamed(this, original.getAbsolutePath(), file.getAbsolutePath())); file = target; return true; } return false; } @Override public long getSize() { return file.length(); } @Override public boolean isExecutable() { return (this.file.canExecute() && !this.file.isDirectory()); } @Override public boolean isReadable() { return (this.file.canRead() && !this.file.isDirectory()); } @Override public boolean isWritable() { return (this.file.canWrite() && !this.file.isDirectory()); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy