[jboss-cvs] JBossAS SVN: r91736 - in projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual: spi and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Jul 28 16:12:18 EDT 2009


Author: david.lloyd at jboss.com
Date: 2009-07-28 16:12:13 -0400 (Tue, 28 Jul 2009)
New Revision: 91736

Added:
   projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/TempDir.java
Modified:
   projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/TempFileProvider.java
   projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/spi/JZipFileSystem.java
   projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/spi/JavaZipFileSystem.java
Log:
Fix temp provider API so that it doesn't suck

Added: projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/TempDir.java
===================================================================
--- projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/TempDir.java	                        (rev 0)
+++ projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/TempDir.java	2009-07-28 20:12:13 UTC (rev 91736)
@@ -0,0 +1,123 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.virtual;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.File;
+import java.io.InputStream;
+import java.io.FileOutputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * A temporary directory which exists until it is closed, at which time its contents will be removed.
+ */
+public final class TempDir implements Closeable
+{
+   private final TempFileProvider provider;
+   private final File root;
+   private final AtomicBoolean open = new AtomicBoolean(true);
+
+   TempDir(TempFileProvider provider, File root)
+   {
+      this.provider = provider;
+      this.root = root;
+   }
+
+   /**
+    * Get the {@code File} that represents the root of this temporary directory.  The returned file is only valid
+    * as long as the tempdir exists.
+    *
+    * @return the root file
+    * @throws IOException if the directory was closed at the time of this invocation
+    */
+   public File getRoot() throws IOException
+   {
+      if (! open.get()) {
+         throw new IOException("Temp directory closed");
+      }
+      return root;
+   }
+
+   /**
+    * Get the {@code File} for a relative path.  The returned file is only valid
+    * as long as the tempdir exists.
+    *
+    * @param relativePath the relative path
+    * @return the corresponding file
+    * @throws IOException if the directory was closed at the time of this invocation
+    */
+   public File getFile(String relativePath) throws IOException {
+      if (! open.get()) {
+         throw new IOException("Temp directory closed");
+      }
+      return new File(root, relativePath);
+   }
+
+   /**
+    * Create a file within this temporary directory, prepopulating the file from the given
+    * input stream.
+    *
+    * @param relativePath the relative path name
+    * @param sourceData the source input stream to use
+    * @return the file
+    * @throws IOException if the directory was closed at the time of this invocation or an error occurs
+    */
+   public File createFile(String relativePath, InputStream sourceData) throws IOException {
+      final File tempFile = getFile(relativePath);
+      boolean ok = false;
+      try {
+         final FileOutputStream fos = new FileOutputStream(tempFile);
+         try {
+            VFSUtils.copyStream(sourceData, fos);
+            fos.close();
+            sourceData.close();
+            return tempFile;
+         } finally {
+            VFSUtils.safeClose(fos);
+         }
+      } finally {
+         VFSUtils.safeClose(sourceData);
+         if (! ok) {
+            tempFile.delete();
+         }
+      }
+   }
+
+   /**
+    * Close this directory.  The contents of the directory will be removed.
+    *
+    * @throws IOException if an I/O error occurs
+    */
+   public void close() throws IOException
+   {
+      if (open.getAndSet(false)) {
+         provider.new DeleteTask(root).run();
+      }
+   }
+
+   protected void finalize() throws Throwable
+   {
+      VFSUtils.safeClose(this);
+   }
+}

Modified: projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/TempFileProvider.java
===================================================================
--- projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/TempFileProvider.java	2009-07-28 19:18:22 UTC (rev 91735)
+++ projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/TempFileProvider.java	2009-07-28 20:12:13 UTC (rev 91736)
@@ -25,8 +25,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.Closeable;
-import java.io.InputStream;
-import java.io.FileOutputStream;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -40,6 +38,7 @@
 {
    private static final String TMP_DIR_PROPERTY = "jboss.server.temp.dir";
    private static final File TMP_ROOT;
+   private static final int RETRIES = 10;
    private final AtomicBoolean open = new AtomicBoolean(true);
 
    static {
@@ -64,133 +63,53 @@
     */
    public static TempFileProvider create(String providerType, ScheduledExecutorService executor) throws IOException
    {
-      return new TempFileProvider(createTempDir(providerType, "", TMP_ROOT), 0, executor);
+      return new TempFileProvider(createTempDir(providerType, "", TMP_ROOT), executor);
    }
 
-   /**
-    * Create a temporary file provider for a given type and hash depth.  The hash depth is used to limit the number
-    * of files in a single directory.
-    *
-    * @param providerType the provider type string (used as a prefix in the temp file dir name)
-    * @param hashDepth the hash directory tree depth
-    * @return the new provider
-    * @throws IOException if an I/O error occurs
-    */
-   public static TempFileProvider create(String providerType, int hashDepth, ScheduledExecutorService executor) throws IOException
-   {
-      return new TempFileProvider(createTempDir(providerType, "", TMP_ROOT), hashDepth, executor);
-   }
-
    private final File providerRoot;
-   private final int hashDepth;
    private final ScheduledExecutorService executor;
 
-   private TempFileProvider(File providerRoot, int hashDepth, ScheduledExecutorService executor)
+   private TempFileProvider(File providerRoot, ScheduledExecutorService executor)
    {
       this.providerRoot = providerRoot;
       this.executor = executor;
-      if (hashDepth < 0 || hashDepth > 4) {
-         throw new IllegalArgumentException("Bad hashDepth");
-      }
-      this.hashDepth = hashDepth;
    }
 
    /**
-    * Create a temp file within this provider.
+    * Create a temp directory, into which temporary files may be placed.
     *
     * @param originalName the original file name
-    * @return the temporary file
-    * @throws IOException if an error occurs
+    * @return the temp directory
+    * @throws IOException
     */
-   public File createTempFile(String originalName) throws IOException {
-      return createTempFile(originalName, originalName.hashCode());
-   }
-
-   /**
-    * Create a temp file within this provider, using an alternate hash code.
-    *
-    * @param originalName the original file name
-    * @param hashCode the hash code to use
-    * @return the temporary file
-    * @throws IOException if an error occurs
-    */
-   public File createTempFile(String originalName, int hashCode) throws IOException {
+   public TempDir createTempDir(String originalName) throws IOException {
       if (! open.get()) {
          throw new IOException("Temp file provider closed");
       }
-      File root = providerRoot;
-      for (int i = 0; i < hashDepth; i ++) {
-         final int dc = hashCode & 0x7f;
-         root = new File(root, dc < 16 ? "0" + Integer.toHexString(dc) : Integer.toHexString(dc));
-         root.mkdir();
-         hashCode >>= 7;
+      final String name = createTempName(originalName + "-", "");
+      final File f = new File(providerRoot, name);
+      for (int i = 0; i < RETRIES; i ++) {
+         if (f.mkdir())
+            return new TempDir(this, f);
       }
-      return createTempFile("tmp", "-" + originalName, root);
+      final IOException eo = new IOException("Could not create directory after " + RETRIES + " attempts");
+      throw eo;
    }
 
-   /**
-    * Create a temp file within this provider, using an alternate hash code, and prepopulating the file from the given
-    * input stream.
-    *
-    * @param originalName the original file name
-    * @param hashCode the hash code to use
-    * @param sourceData the source input stream to use
-    * @return the temporary file
-    * @throws IOException if an error occurs
-    */
-   public File createTempFile(String originalName, int hashCode, InputStream sourceData) throws IOException {
-      if (! open.get()) {
-         throw new IOException("Temp file provider closed");
-      }
-      final File tempFile = createTempFile(originalName, hashCode);
-      boolean ok = false;
-      try {
-         final FileOutputStream fos = new FileOutputStream(tempFile);
-         try {
-            VFSUtils.copyStream(sourceData, fos);
-            fos.close();
-            sourceData.close();
-            return tempFile;
-         } finally {
-            VFSUtils.safeClose(fos);
-         }
-      } finally {
-         VFSUtils.safeClose(sourceData);
-         if (! ok) {
-            tempFile.delete();
-         }
-      }
-   }
-
    private static final Random rng = new SecureRandom();
 
    private static File createTempDir(String prefix, String suffix, File root) throws IOException
    {
-      for (int i = 0; i < 100; i ++) {
+      for (int i = 0; i < RETRIES; i ++) {
          final File f = new File(root, createTempName(prefix, suffix));
          if (f.mkdir())
             return f;
       }
-      final IOException eo = new IOException("Could not create directory after 100 attempts");
+      final IOException eo = new IOException("Could not create directory after " + RETRIES + " attempts");
       throw eo;
    }
 
-   private static File createTempFile(String prefix, String suffix, File root) throws IOException
-   {
-      IOException e = null;
-      for (int i = 0; i < 100; i ++) try {
-         final File f = new File(root, createTempName(prefix, suffix));
-         f.createNewFile();
-         return f;
-      } catch (IOException e2) {
-         e = e2;
-      }
-      final IOException eo = new IOException("Could not create file after 100 attempts");
-      eo.initCause(e);
-      throw eo;
-   }
-
-   private static String createTempName(String prefix, String suffix) {
+   static String createTempName(String prefix, String suffix) {
       return prefix + Long.toHexString(rng.nextLong()) + suffix;
    }
 
@@ -200,16 +119,7 @@
    public void close() throws IOException
    {
       if (open.getAndSet(false)) {
-         final Runnable task = new Runnable()
-         {
-            public void run()
-            {
-               if (! recursiveDelete(providerRoot)) {
-                  executor.schedule(this, 30L, TimeUnit.SECONDS);
-               }
-            }
-         };
-         task.run();
+         new DeleteTask(providerRoot).run();
       }
    }
 
@@ -232,4 +142,21 @@
       }
       return ok;
    }
+
+   class DeleteTask implements Runnable
+   {
+      private final File root;
+
+      public DeleteTask(File root)
+      {
+         this.root = root;
+      }
+
+      public void run()
+      {
+         if (! recursiveDelete(root)) {
+            executor.schedule(this, 30L, TimeUnit.SECONDS);
+         }
+      }
+   }
 }

Modified: projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/spi/JZipFileSystem.java
===================================================================
--- projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/spi/JZipFileSystem.java	2009-07-28 19:18:22 UTC (rev 91735)
+++ projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/spi/JZipFileSystem.java	2009-07-28 20:12:13 UTC (rev 91736)
@@ -28,8 +28,8 @@
 import org.jboss.jzipfile.ZipEntryType;
 import org.jboss.virtual.plugins.vfs.helpers.PathTokenizer;
 import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.TempFileProvider;
 import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.TempDir;
 
 import java.io.File;
 import java.io.IOException;
@@ -56,24 +56,31 @@
    private final File zipFile;
    private final long zipTime;
    private final ZipNode rootNode;
-   private final TempFileProvider tempFileProvider;
+   private final TempDir tempDir;
+   private final File contentsDir;
 
    /**
     * Create a new instance.
     *
     * @param name the name of the source archive
     * @param inputStream an input stream from the source archive
-    * @param tempFileProvider the temp file provider to use
+    * @param tempDir the temp dir into which zip information is stored
     * @throws java.io.IOException if an I/O error occurs
     */
-   public JZipFileSystem(String name, InputStream inputStream, TempFileProvider tempFileProvider) throws IOException {
-      this(tempFileProvider.createTempFile(name, name.hashCode(), inputStream), tempFileProvider);
+   public JZipFileSystem(String name, InputStream inputStream, TempDir tempDir) throws IOException {
+      this(tempDir.createFile(name, inputStream), tempDir);
    }
 
-   public JZipFileSystem(File zipFile, TempFileProvider tempFileProvider) throws IOException
+   /**
+    * Create a new instance.
+    *
+    * @param zipFile the original archive file
+    * @param tempDir the temp dir into which zip information is stored
+    * @throws java.io.IOException if an I/O error occurs
+    */
+   public JZipFileSystem(File zipFile, TempDir tempDir) throws IOException
    {
       zipTime = zipFile.lastModified();
-      this.tempFileProvider = tempFileProvider;
       this.zipFile = zipFile;
       final ZipCatalog catalog = Zip.readCatalog(zipFile);
       final ZipNode rootNode = new ZipNode(new HashMap<String, ZipNode>(), "", null);
@@ -106,6 +113,9 @@
          }
       }
       this.rootNode = rootNode;
+      this.tempDir = tempDir;
+      contentsDir = tempDir.getFile("contents");
+      contentsDir.mkdir();
    }
 
    public File getFile(VirtualFile mountPoint, VirtualFile target) throws IOException
@@ -127,7 +137,7 @@
          // nope, create a cached temp
          final ZipEntry entry = getNodeEntry(zipNode);
          final String name = entry.getName();
-         cachedFile = tempFileProvider.createTempFile(name, entry.hashCode());
+         cachedFile = new File(contentsDir, name);
          VFSUtils.copyStreamAndClose(Zip.openEntry(zipFile, entry), new BufferedOutputStream(new FileOutputStream(cachedFile)));
          zipNode.cachedFile = cachedFile;
          return cachedFile;
@@ -228,7 +238,7 @@
 
    public void close() throws IOException
    {
-      tempFileProvider.close();
+      tempDir.close();
    }
 
    private static final class ZipNode {

Modified: projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/spi/JavaZipFileSystem.java
===================================================================
--- projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/spi/JavaZipFileSystem.java	2009-07-28 19:18:22 UTC (rev 91735)
+++ projects/vfs/branches/dml-zip-rework/src/main/java/org/jboss/virtual/spi/JavaZipFileSystem.java	2009-07-28 20:12:13 UTC (rev 91736)
@@ -24,8 +24,8 @@
 
 import org.jboss.virtual.plugins.vfs.helpers.PathTokenizer;
 import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.TempFileProvider;
 import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.TempDir;
 
 import java.io.File;
 import java.io.IOException;
@@ -56,26 +56,34 @@
    private final ZipFile zipFile;
    private final long zipTime;
    private final ZipNode rootNode;
-   private final TempFileProvider tempFileProvider;
+   private final TempDir tempDir;
+   private final File contentsDir;
 
    /**
     * Create a new instance.
     *
     * @param name the name of the source archive
     * @param inputStream an input stream from the source archive
-    * @param tempFileProvider the temp file provider to use
+    * @param tempDir the temp dir into which zip information is stored
     * @throws java.io.IOException if an I/O error occurs
     */
-   public JavaZipFileSystem(String name, InputStream inputStream, TempFileProvider tempFileProvider) throws IOException {
-      this(tempFileProvider.createTempFile(name, name.hashCode(), inputStream), tempFileProvider);
+   public JavaZipFileSystem(String name, InputStream inputStream, TempDir tempDir) throws IOException {
+      this(tempDir.createFile(name, inputStream), tempDir);
    }
 
-   public JavaZipFileSystem(File file, TempFileProvider tempFileProvider) throws IOException
+   /**
+    * Create a new instance.
+    *
+    * @param archiveFile the original archive file
+    * @param tempDir the temp dir into which zip information is stored
+    * @throws java.io.IOException if an I/O error occurs
+    */
+   public JavaZipFileSystem(File archiveFile, TempDir tempDir) throws IOException
    {
-      zipTime = file.lastModified();
+      zipTime = archiveFile.lastModified();
       final ZipFile zipFile;
-      this.zipFile = zipFile = new ZipFile(file);
-      this.tempFileProvider = tempFileProvider;
+      this.zipFile = zipFile = new ZipFile(archiveFile);
+      this.tempDir = tempDir;
       final Enumeration<? extends ZipEntry> entries = zipFile.entries();
       final ZipNode rootNode = new ZipNode(new HashMap<String, ZipNode>(), "", null);
       FILES: for (ZipEntry entry : iter(entries))
@@ -108,6 +116,8 @@
          }
       }
       this.rootNode = rootNode;
+      contentsDir = tempDir.getFile("contents");
+      contentsDir.mkdir();
    }
 
    private static <T> Iterable<T> iter(final Enumeration<T> entries)
@@ -134,7 +144,7 @@
          // nope, create a cached temp
          final ZipEntry zipEntry = getNodeEntry(zipNode);
          final String name = zipEntry.getName();
-         cachedFile = tempFileProvider.createTempFile(name, zipEntry.hashCode());
+         cachedFile = new File(contentsDir, name);
          VFSUtils.copyStreamAndClose(zipFile.getInputStream(zipEntry), new BufferedOutputStream(new FileOutputStream(cachedFile)));
          zipNode.cachedFile = cachedFile;
          return cachedFile;
@@ -240,7 +250,7 @@
             zipFile.close();
          }
       });
-      tempFileProvider.close();
+      tempDir.close();
    }
 
    private static final class ZipNode {




More information about the jboss-cvs-commits mailing list