[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