[jboss-svn-commits] JBoss Common SVN: r4048 - in shrinkwrap/trunk: api/src/main/java/org/jboss/shrinkwrap/api/formatter and 12 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Feb 22 18:14:59 EST 2010


Author: ALRubinger
Date: 2010-02-22 18:14:56 -0500 (Mon, 22 Feb 2010)
New Revision: 4048

Modified:
   shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/Archive.java
   shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/FullFormatter.java
   shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/SimpleFormatter.java
   shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/VerboseFormatter.java
   shrinkwrap/trunk/extension-glassfish/src/main/java/org/jboss/shrinkwrap/glassfish/impl/ShrinkwrapReadableArchiveImpl.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveBase.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveBase.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/asset/DirectoryAsset.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/container/ContainerBase.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/AbstractExporterDelegate.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ExplodedExporterDelegate.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/JdkZipExporterDelegate.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/importer/ExplodedImporterImpl.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImpl.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/path/PathUtil.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/asset/DirectoryAssetTestCase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExportTestBase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterTestCase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/formatter/VerboseFormatterTestCase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImplTestCase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/DynamicContainerTestBase.java
Log:
[SHRINKWRAP-134] Organize Archives backed by a tree; submitted by community contributor German Escobar

Modified: shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/Archive.java
===================================================================
--- shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/Archive.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/Archive.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -49,6 +49,7 @@
     * @param asset
     * @return
     * @throws IllegalArgumentException If no target or assets were specified
+    * @throws IllegalArchivePathException If the target is invalid.
     */
    T add(Asset asset, ArchivePath target) throws IllegalArgumentException;
 
@@ -62,6 +63,7 @@
     * @param asset
     * @return
     * @throws IllegalArgumentException If the target, name, or asset was not specified
+    * @throws IllegalArchivePathException If the target is invalid.
     */
    T add(Asset asset, ArchivePath target, String name) throws IllegalArgumentException;
 
@@ -72,6 +74,7 @@
     * @param asset
     * @return
     * @throws IllegalArgumentException If either the target or asset is not specified 
+    * @throws IllegalArchivePathException If the target is invalid.
     */
    T add(Asset asset, String target) throws IllegalArgumentException;
    
@@ -81,6 +84,7 @@
     * @param path The path to add
     * @return This archive
     * @throws IllegalArgumentException If no path was specified
+    * @throws IllegalArchivePathException If the path is invalid.
     */
    T addDirectory(String path) throws IllegalArgumentException;
 
@@ -90,6 +94,7 @@
     * @param paths The paths to add
     * @return This archive
     * @throws IllegalArgumentException If no paths were specified
+    * @throws IllegalArchivePathException If at least one path is invalid.
     */
    T addDirectories(String... paths) throws IllegalArgumentException;
 
@@ -99,6 +104,7 @@
     * @param path The path to add
     * @return This archive
     * @throws IllegalArgumentException If no path was specified
+    * @throws IllegalArchivePathException If the path is invalid.
     */
    T addDirectory(ArchivePath path) throws IllegalArgumentException;
 
@@ -108,26 +114,27 @@
     * @param paths The paths to add
     * @return This archive
     * @throws IllegalArgumentException If no paths were specified
+    * @throws IllegalArchivePathException If at least one path is invalid.
     */
    T addDirectories(ArchivePath... paths) throws IllegalArgumentException;
 
    /**
-    * Obtains the asset located at the specified path
+    * Obtains the {@link Node} located at the specified path
     * 
     * @param path
-    * @return The asset, or null if nothing is found at the Path
+    * @return The {@link Node}, or null if nothing is found at the specified path
     * @throws IllegalArgumentException If the path is not specified
     */
-   Asset get(ArchivePath path) throws IllegalArgumentException;
+   Node get(ArchivePath path) throws IllegalArgumentException;
 
    /**
-    * Obtains the asset located at the specified path
+    * Obtains the {@link Node} located at the specified path
     * 
     * @param path
-    * @return The asset, or null if nothing is found at the Path
+    * @return The {@link Node}, or null if nothing is found at the Path
     * @throws IllegalArgumentException If the path is not specified
     */
-   Asset get(String path) throws IllegalArgumentException;
+   Node get(String path) throws IllegalArgumentException;
 
    /**
     * Denotes whether this archive contains a resource at the specified
@@ -153,14 +160,14 @@
     * The returned Map will be an immutable view.
     * @return
     */
-   Map<ArchivePath, Asset> getContent();
+   Map<ArchivePath, Node> getContent();
 
    /**
     * Obtains all assets matching given filter in this archive, along with its respective Path.
     * The returned Map will be an immutable view.
     * @return
     */
-   Map<ArchivePath, Asset> getContent(Filter<ArchivePath> filter);
+   Map<ArchivePath, Node> getContent(Filter<ArchivePath> filter);
 
    /**
     * Add an archive under a specific context and maintain the archive name as context path.

Modified: shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/FullFormatter.java
===================================================================
--- shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/FullFormatter.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/FullFormatter.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -17,11 +17,8 @@
 
 package org.jboss.shrinkwrap.api.formatter;
 
-import java.util.SortedSet;
-import java.util.TreeSet;
-
 import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.Node;
 
 /**
  * {@link Formatter} implementation to provide the full path (including parents) of
@@ -34,33 +31,47 @@
    @Override
    public String format(final Archive<?> archive) throws IllegalArgumentException
    {
+      // Precondition checks
+      if (archive == null)
+      {
+         throw new IllegalArgumentException("archive must be specified");
+      }
+      
       // Start the output with the name of the archive
       StringBuilder sb = new StringBuilder(archive.getName()).append(FormattingConstants.COLON)
          .append(FormattingConstants.NEWLINE);
-      SortedSet<String> archiveContents = new TreeSet<String>();
 
-      // I know it's ugly, but we have to do two iterations per entry so we get everything
-      for (ArchivePath path : archive.getContent().keySet())
+      // Format recursively, except the parent 
+      Node rootNode = archive.get("/");
+      for (Node child : rootNode.getChildren()) 
       {
-         archiveContents.add(path.get());
-         ArchivePath parentPath = path.getParent();
-
-         while (parentPath != null)
-         {
-            archiveContents.add(parentPath.get());
-            parentPath = parentPath.getParent();
-         }
+         format(sb, child);
       }
 
-      // spit out the correct format now
-      for (String pathEntry : archiveContents)
-      {
-         sb.append(pathEntry).append(FormattingConstants.NEWLINE);
-      }
-      int firstLeadingSlash = sb.indexOf(String.valueOf(FormattingConstants.SLASH));
-      sb.delete(firstLeadingSlash, firstLeadingSlash + 2);
+      // remove the last NEWLINE
       sb.deleteCharAt(sb.length() - 1);
       
       return sb.toString();
    }
+   
+   /**
+    * Helper method to format recursively
+    * @param sb
+    * @param node
+    */
+   private void format(StringBuilder sb, Node node) 
+   {
+      sb.append(node.getPath().get());
+      if (node.getAsset() == null) 
+      {
+         sb.append(FormattingConstants.SLASH);
+      }
+      
+      sb.append(FormattingConstants.NEWLINE);
+      
+      for (Node child : node.getChildren()) 
+      {
+         format(sb, child);
+      }
+   }
 }

Modified: shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/SimpleFormatter.java
===================================================================
--- shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/SimpleFormatter.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/SimpleFormatter.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -16,7 +16,11 @@
  */
 package org.jboss.shrinkwrap.api.formatter;
 
+import java.util.Map;
+
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.Node;
 
 /**
  * {@link Formatter} implementation to provide a simple, one-line
@@ -52,8 +56,31 @@
 
       // Format: "name: X assets"
       return new StringBuilder().append(archive.getName()).append(FormattingConstants.COLON).append(
-            FormattingConstants.SPACE).append(archive.getContent().size()).append(FormattingConstants.SPACE).append(
+            FormattingConstants.SPACE).append(this.getNumAssets(archive)).append(FormattingConstants.SPACE).append(
             ASSETS).toString();
    }
+   
+   /**
+    * Returns the number of assets on an {@link Archive}.
+    * 
+    * @param archive the Archive from which we are goint to obtain the 
+    *       number of assets.
+    * @return the number of assets inside the archive
+    */
+   private int getNumAssets(final Archive<?> archive) 
+   {
+      int assets = 0;
+      
+      Map<ArchivePath, Node> content = archive.getContent();
+      for (Map.Entry<ArchivePath, Node> entry : content.entrySet()) 
+      {
+         if (entry.getValue().getAsset() != null) 
+         {
+            assets++;
+         }
+      }
+      
+      return assets;
+   }
 
 }

Modified: shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/VerboseFormatter.java
===================================================================
--- shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/VerboseFormatter.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/formatter/VerboseFormatter.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -16,12 +16,8 @@
  */
 package org.jboss.shrinkwrap.api.formatter;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
 import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.Node;
 
 /**
  * {@link Formatter} implementation to provide an "ls -l"-esque
@@ -47,29 +43,37 @@
          throw new IllegalArgumentException("archive must be specified");
       }
 
-      // Make a builder
-      final StringBuilder sb = new StringBuilder();
+      // Start the output with the name of the archive
+      StringBuilder sb = new StringBuilder(archive.getName()).append(FormattingConstants.COLON)
+         .append(FormattingConstants.NEWLINE);
 
-      // Add the name
-      sb.append(archive.getName()).append(FormattingConstants.COLON).append(FormattingConstants.NEWLINE);
-
-      // Sort all paths
-      final List<ArchivePath> paths = new ArrayList<ArchivePath>(archive.getContent().keySet());
-      Collections.sort(paths);
-      final int numPaths = paths.size();
-      int count = 0;
-      for (final ArchivePath path : paths)
+      // format recursively, except the parent 
+      Node rootNode = archive.get("/");
+      for (Node child : rootNode.getChildren()) 
       {
-         count++;
-         sb.append(path.get());
-         if (count != numPaths)
-         {
-            sb.append(FormattingConstants.NEWLINE);
-         }
+         format(sb, child);
       }
-
-      // Return
+      
+      // remove the last NEWLINE
+      sb.deleteCharAt(sb.length() - 1);
+      
       return sb.toString();
    }
+   
+   private void format(StringBuilder sb, Node node) 
+   {
+      sb.append(node.getPath().get());
+      if (node.getAsset() == null) 
+      {
+         sb.append(FormattingConstants.SLASH);
+      }
+      
+      sb.append(FormattingConstants.NEWLINE);
+      
+      for (Node child : node.getChildren()) 
+      {
+         format(sb, child);
+      }
+   }
 
 }

Modified: shrinkwrap/trunk/extension-glassfish/src/main/java/org/jboss/shrinkwrap/glassfish/impl/ShrinkwrapReadableArchiveImpl.java
===================================================================
--- shrinkwrap/trunk/extension-glassfish/src/main/java/org/jboss/shrinkwrap/glassfish/impl/ShrinkwrapReadableArchiveImpl.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/extension-glassfish/src/main/java/org/jboss/shrinkwrap/glassfish/impl/ShrinkwrapReadableArchiveImpl.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -32,12 +32,11 @@
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.ArchivePath;
 import org.jboss.shrinkwrap.api.ArchivePaths;
-import org.jboss.shrinkwrap.api.Asset;
+import org.jboss.shrinkwrap.api.Node;
 import org.jboss.shrinkwrap.glassfish.api.ShrinkwrapReadableArchive;
 import org.jboss.shrinkwrap.impl.base.AssignableBase;
 import org.jboss.shrinkwrap.impl.base.Validate;
 import org.jboss.shrinkwrap.impl.base.asset.ArchiveAsset;
-import org.jboss.shrinkwrap.impl.base.asset.DirectoryAsset;
 
 /**
  * ShrinkWrap extension to support GlassFishs {@link ReadableArchive}
@@ -108,7 +107,7 @@
    @Override
    public InputStream getEntry(String path) throws IOException
    {
-      return archive.get(ArchivePaths.create(path)).openStream();
+      return archive.get(ArchivePaths.create(path)).getAsset().openStream();
    }
 
    /**
@@ -151,10 +150,10 @@
    @Override
    public ReadableArchive getSubArchive(String path) throws IOException
    {
-      Asset archiveAsset = archive.get(ArchivePaths.create(path));
-      if (archiveAsset instanceof ArchiveAsset)
+      Node archiveNode = archive.get(ArchivePaths.create(path));
+      if (archiveNode.getAsset() instanceof ArchiveAsset)
       {
-         return ((ArchiveAsset) archiveAsset).getArchive().as(ShrinkwrapReadableArchive.class);
+         return ((ArchiveAsset) archiveNode.getAsset()).getArchive().as(ShrinkwrapReadableArchive.class);
       }
       throw new IOException(path + " not a Archive");
    }
@@ -194,9 +193,12 @@
    {
       List<String> entries = new ArrayList<String>();
 
-      for (Entry<ArchivePath, Asset> entry : archive.getContent().entrySet())
+      for (Entry<ArchivePath, Node> entry : archive.getContent().entrySet())
       {
-         entries.add(entry.getKey().get());
+         if (entry.getValue().getAsset() != null) 
+         {
+            entries.add(entry.getKey().get());
+         }
       }
       return Collections.enumeration(entries);
    }
@@ -209,11 +211,14 @@
    {
       List<String> entries = new ArrayList<String>();
 
-      for (Entry<ArchivePath, Asset> entry : archive.getContent().entrySet())
+      for (Entry<ArchivePath, Node> entry : archive.getContent().entrySet())
       {
          if (entry.getKey().get().startsWith(path))
          {
-            entries.add(entry.getKey().get());
+            if (entry.getValue().getAsset() != null) 
+            {
+               entries.add(entry.getKey().get());
+            }
          }
       }
       return Collections.enumeration(entries);
@@ -238,9 +243,9 @@
    {
       List<String> entries = new ArrayList<String>();
 
-      for (Entry<ArchivePath, Asset> entry : archive.getContent().entrySet())
+      for (Entry<ArchivePath, Node> entry : archive.getContent().entrySet())
       {
-         if (entry.getValue() == DirectoryAsset.INSTANCE)
+         if (entry.getValue().getAsset() == null)
          {
             entries.add(entry.getKey().get());
          }
@@ -257,7 +262,7 @@
       ArchivePath manifestPath = ArchivePaths.create("META-INF/MANIFEST.MF");
       if (archive.contains(manifestPath))
       {
-         return new Manifest(archive.get(manifestPath).openStream());
+         return new Manifest(archive.get(manifestPath).getAsset().openStream());
       }
       return null;
    }
@@ -293,6 +298,6 @@
    @Override
    public boolean isDirectory(String path)
    {
-      return archive.get(ArchivePaths.create(path)) == DirectoryAsset.INSTANCE;
+      return archive.get(ArchivePaths.create(path)).getAsset() == null;
    }
 }
\ No newline at end of file

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveBase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveBase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -24,17 +24,17 @@
 import java.util.logging.Logger;
 
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
 import org.jboss.shrinkwrap.api.ArchivePaths;
 import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.Assignable;
 import org.jboss.shrinkwrap.api.ExtensionLoader;
 import org.jboss.shrinkwrap.api.Filter;
 import org.jboss.shrinkwrap.api.Filters;
-import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.Node;
 import org.jboss.shrinkwrap.api.formatter.Formatter;
 import org.jboss.shrinkwrap.api.formatter.Formatters;
 import org.jboss.shrinkwrap.impl.base.asset.ArchiveAsset;
-import org.jboss.shrinkwrap.impl.base.asset.DirectoryAsset;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
 
 /**
@@ -145,7 +145,7 @@
     * @see org.jboss.shrinkwrap.api.Archive#get(java.lang.String)
     */
    @Override
-   public Asset get(final String path) throws IllegalArgumentException
+   public Node get(final String path) throws IllegalArgumentException
    {
       // Precondition checks
       Validate.notNullOrEmpty(path, "No path was specified");
@@ -178,20 +178,6 @@
       // Delegate
       return add(archiveAsset, contentPath);
    }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.shrinkwrap.api.Archive#addDirectory(org.jboss.shrinkwrap.api.ArchivePath)
-    */
-   @Override
-   public T addDirectory(final ArchivePath path) throws IllegalArgumentException
-   {
-      // Precondition check
-      Validate.notNull(path, "path must be specified");
-      
-      // Delegate and return
-      return this.addDirectories(path);
-   }
 
    /**
     * {@inheritDoc}
@@ -220,7 +206,7 @@
       // Add
       for (final ArchivePath path : paths)
       {
-         this.add(DirectoryAsset.INSTANCE, path);
+         this.addDirectory(path);
       }
       
       // Return
@@ -267,7 +253,8 @@
       return merge(source, new BasicPath());
    }
 
-   /* (non-Javadoc)
+   /** 
+    * {@inheritDoc}
     * @see org.jboss.shrinkwrap.api.Archive#merge(org.jboss.shrinkwrap.api.Archive, org.jboss.shrinkwrap.api.Filter)
     */
    @Override
@@ -289,7 +276,8 @@
       return merge(source, path, Filters.includeAll());
    }
    
-   /* (non-Javadoc)
+   /**
+    * {@inheritDoc}
     * @see org.jboss.shrinkwrap.api.Archive#merge(org.jboss.shrinkwrap.api.Archive, org.jboss.shrinkwrap.api.Path, org.jboss.shrinkwrap.api.Filter)
     */
    @Override
@@ -301,25 +289,33 @@
       Validate.notNull(filter, "No filter was specified");
 
       // Get existing contents from source archive
-      final Map<ArchivePath, Asset> sourceContent = source.getContent();
+      final Map<ArchivePath, Node> sourceContent = source.getContent();
       Validate.notNull(sourceContent, "Source archive content can not be null.");
 
       // Add each asset from the source archive
-      for (final Entry<ArchivePath, Asset> contentEntry : sourceContent.entrySet())
+      for (final Entry<ArchivePath, Node> contentEntry : sourceContent.entrySet())
       {
-         final Asset asset = contentEntry.getValue();
-         ArchivePath assetPath = new BasicPath(path, contentEntry.getKey());
-         if( !filter.include(assetPath)) 
+         final Node node = contentEntry.getValue();
+         ArchivePath nodePath = new BasicPath(path, contentEntry.getKey());
+         if( !filter.include(nodePath)) 
          {
             continue;
          }
          // Delegate
-         add(asset, assetPath);
+         if (node.getAsset() == null) 
+         {
+            addDirectory(nodePath);
+         } 
+         else 
+         {
+            add(node.getAsset(), nodePath);
+         }
       }
       return covariantReturn();
    }
 
-   /* (non-Javadoc)
+   /**
+    * {@inheritDoc}
     * @see org.jboss.shrinkwrap.api.Specializer#as(java.lang.Class)
     */
    @Override

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveBase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveBase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -22,15 +22,17 @@
 import java.util.UUID;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Logger;
 
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
 import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.ExtensionLoader;
 import org.jboss.shrinkwrap.api.Filter;
-import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.IllegalArchivePathException;
+import org.jboss.shrinkwrap.api.Node;
 import org.jboss.shrinkwrap.impl.base.asset.ArchiveAsset;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
+import org.jboss.shrinkwrap.impl.base.path.PathUtil;
 
 /**
  * MemoryMapArchiveBase
@@ -46,32 +48,13 @@
 {
 
    //-------------------------------------------------------------------------------------||
-   // Class Members ----------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Logger
-    */
-   private static final Logger log = Logger.getLogger(MemoryMapArchiveBase.class.getName());
-
-   /**
-    * Newline character
-    */
-   private static final char NEWLINE = '\n';
-
-   /**
-    * Colon character
-    */
-   private static final char COLON = ':';
-
-   //-------------------------------------------------------------------------------------||
    // Instance Members -------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
 
    /**
-    * Storage for the {@link Asset}s.
+    * Storage for the {@link Node}s.
     */
-   private final Map<ArchivePath, Asset> content = new ConcurrentHashMap<ArchivePath, Asset>();
+   private final Map<ArchivePath, NodeImpl> content = new ConcurrentHashMap<ArchivePath, NodeImpl>();
 
    /**
     * Storage for the {@link ArchiveAsset}s.  Used to help get access to nested archive content.
@@ -106,27 +89,52 @@
    public MemoryMapArchiveBase(final String archiveName, ExtensionLoader extensionLoader)
    {
       super(archiveName, extensionLoader);
+      
+      // Add the root node to the content
+      ArchivePath rootPath = new BasicPath("/");
+      content.put(rootPath, new NodeImpl(rootPath));
    }
 
    //-------------------------------------------------------------------------------------||
    // Required Implementations - Archive -------------------------------------------------||
    //-------------------------------------------------------------------------------------||
 
-   /* (non-Javadoc)
-    * @see org.jboss.shrinkwrap.api.Archive#add(org.jboss.shrinkwrap.api.Asset, org.jboss.shrinkwrap.api.Path)
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.shrinkwrap.api.Archive#add(org.jboss.shrinkwrap.api.Asset, org.jboss.shrinkwrap.api.ArchivePath)
     */
    @Override
    public T add(Asset asset, ArchivePath path)
    {
       Validate.notNull(asset, "No asset was specified");
       Validate.notNull(path, "No path was specified");
+      
+      // Retrieve the parent
+      NodeImpl parentNode = obtainParent(path.getParent());
+      
+      // Check if a the path already contains a node so we remove it from the parent's children
+      NodeImpl existingNode = content.get(path);
+      if (parentNode != null && existingNode != null) 
+      {
+         parentNode.removeChild(existingNode);
+      }
+      
+      // Add the node to the content of the archive
+      NodeImpl node = new NodeImpl(path, asset);
+      content.put(path, node);
 
-      content.put(path, asset);
+      // Add the new node to the parent as a child
+      if (parentNode != null) 
+      {
+         parentNode.addChild(node);
+      }
+      
       return covariantReturn();
    }
 
-   /* (non-Javadoc)
-    * @see org.jboss.shrinkwrap.impl.base.ArchiveBase#add(org.jboss.shrinkwrap.api.Archive, org.jboss.shrinkwrap.api.Path)
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.shrinkwrap.impl.base.ArchiveBase#add(org.jboss.shrinkwrap.api.Archive, org.jboss.shrinkwrap.api.ArchivePath)
     */
    @Override
    public T add(Archive<?> archive, ArchivePath path)
@@ -138,21 +146,52 @@
       ArchivePath archivePath = new BasicPath(path, archive.getName());
 
       // Get the Asset that was just added 
-      Asset asset = get(archivePath);
+      Node node = get(archivePath);
 
       // Make sure it is an ArchiveAsset
-      if (asset instanceof ArchiveAsset)
+      if (node.getAsset() != null && node.getAsset() instanceof ArchiveAsset)
       {
-         ArchiveAsset archiveAsset = ArchiveAsset.class.cast(asset);
+         ArchiveAsset archiveAsset = ArchiveAsset.class.cast(node.getAsset());
          // Add asset to ArchiveAsset Map
          nestedArchives.put(archivePath, archiveAsset);
       }
 
       return covariantReturn();
    }
+   
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.shrinkwrap.api.Archive#addDirectory(org.jboss.shrinkwrap.api.ArchivePath)
+    */
+   @Override
+   public T addDirectory(final ArchivePath path) throws IllegalArgumentException
+   {
+      // Precondition check
+      Validate.notNull(path, "path must be specified");
+      
+      // Adjust the path to remove any trailing slash
+      ArchivePath adjustedPath = new BasicPath(PathUtil.optionallyRemoveFollowingSlash(path.get()));
+      
+      // Check if it exists. If it doesn't, create it and add it. The same with all the
+      // non-existing parents
+      if (!contains(adjustedPath)) 
+      {
+         NodeImpl node = new NodeImpl(adjustedPath);
+         content.put(adjustedPath, node);
+         
+         // retrieve the parent and add the node as a child
+         NodeImpl parentNode = obtainParent(adjustedPath.getParent());
+         if (parentNode != null) {
+            parentNode.addChild(node);
+         }
+      }
+      
+      return covariantReturn();
+   }
 
-   /* {@inheritDoc}
-    * @see org.jboss.declarchive.api.Archive#contains(org.jboss.declarchive.api.Path)
+   /** 
+    * {@inheritDoc}
+    * @see org.jboss.shrinkwrap.api.Archive#contains(org.jboss.shrinkwrap.api.ArchivePath)
     */
    @Override
    public boolean contains(ArchivePath path)
@@ -167,54 +206,83 @@
       return found;
    }
 
-   /* {@inheritDoc}
-    * @see org.jboss.declarchive.api.Archive#delete(org.jboss.declarchive.api.Path)
+   /** 
+    * {@inheritDoc}
+    * @see org.jboss.shrinkwrap.api.Archive#delete(org.jboss.declarchive.api.ArchivePath)
     */
    @Override
    public boolean delete(ArchivePath path)
    {
       Validate.notNull(path, "No path was specified");
+      
+      NodeImpl node = content.get(path);
+      if (node == null) 
+      {
+         return false;
+      }
+      
+      NodeImpl parentNode = content.get(path.getParent());
+      if (parentNode != null) 
+      {
+         parentNode.removeChild(node);
+      }
+      
       return content.remove(path) != null;
    }
 
-   /* {@inheritDoc}
-    * @see org.jboss.declarchive.api.Archive#get(org.jboss.declarchive.api.Path)
+   /** 
+    * {@inheritDoc}
+    * @see org.jboss.shrinkwrap.api.Archive#get(org.jboss.shrinkwrap.api.ArchivePath)
     */
    @Override
-   public Asset get(ArchivePath path)
+   public Node get(ArchivePath path)
    {
       Validate.notNull(path, "No path was specified");
-      Asset asset = content.get(path);
-      if (asset == null && contains(path))
+      Node node = content.get(path);
+      if (node == null && contains(path))
       {
-         asset = getNestedAsset(path);
+         node = getNestedNode(path);
       }
-      return asset;
+      return node;
    }
 
-   /* {@inheritDoc}
-    * @see org.jboss.declarchive.api.Archive#getContent()
+   /** 
+    * {@inheritDoc}
+    * @see org.jboss.shrinkwrap.api.Archive#getContent()
     */
    @Override
-   public Map<ArchivePath, Asset> getContent()
+   public Map<ArchivePath, Node> getContent()
    {
-      return Collections.unmodifiableMap(content);
+      Map<ArchivePath, Node> ret = new HashMap<ArchivePath, Node>();
+      for (Map.Entry<ArchivePath, NodeImpl> item : content.entrySet()) 
+      {
+         if (!item.getKey().equals(new BasicPath("/"))) 
+         {
+            ret.put(item.getKey(), item.getValue());
+         }
+      }
+      
+      return Collections.unmodifiableMap(ret);
    }
    
-   /* (non-Javadoc)
+   /**
+    * {@inheritDoc}
     * @see org.jboss.shrinkwrap.api.Archive#getContent(org.jboss.shrinkwrap.api.Filter)
     */
    @Override
-   public Map<ArchivePath, Asset> getContent(Filter<ArchivePath> filter)
+   public Map<ArchivePath, Node> getContent(Filter<ArchivePath> filter)
    {
       Validate.notNull(filter, "Filter must be specified");
       
-      Map<ArchivePath, Asset> filteredContent = new HashMap<ArchivePath, Asset>();
-      for(Map.Entry<ArchivePath, Asset> contentEntry : content.entrySet())
+      Map<ArchivePath, Node> filteredContent = new HashMap<ArchivePath, Node>();
+      for(Map.Entry<ArchivePath, NodeImpl> contentEntry : content.entrySet())
       {
          if(filter.include(contentEntry.getKey()))
          {
-            filteredContent.put(contentEntry.getKey(), contentEntry.getValue());
+            if (!contentEntry.getKey().equals(new BasicPath("/"))) 
+            {
+               filteredContent.put(contentEntry.getKey(), contentEntry.getValue());
+            }
          }
       }
       return filteredContent;
@@ -256,7 +324,7 @@
     * @param path
     * @return
     */
-   private Asset getNestedAsset(ArchivePath path)
+   private Node getNestedNode(ArchivePath path)
    {
       // Iterate through nested archives
       for (Entry<ArchivePath, ArchiveAsset> nestedArchiveEntry : nestedArchives.entrySet())
@@ -312,4 +380,50 @@
 
       return new BasicPath(nestedArchiveContext);
    }
+   
+   /**
+    * Used to retrieve a {@link Node} from the content of the {@link Archive}. If the 
+    * {@link Node} doesn´t exists in the specified location, it is created and added 
+    * to the {@link Archive}. The same happens to all its non-existing parents. However, 
+    * if the {@link Node} is an asset, an IllegalArchivePathException is thrown.
+    *  
+    * @param path The {@link ArchivePath} from which we are obtaining the {@link Node}
+    * @return The {@link Node} in the specified path
+    * @throws IllegalArchivePathException if the node is an {@link Asset}
+    */
+   private NodeImpl obtainParent(ArchivePath path) 
+   {
+      if (path == null) {
+         return null;
+      }
+      
+      NodeImpl node = content.get(path);
+      
+      // If the node exists, just return it
+      if (node != null) 
+      {
+         // if the node is an asset, throw an exception
+         if (node.getAsset() != null) 
+         {
+            throw new IllegalArchivePathException("Could not create node under " 
+                  + path.getParent() + ". It points to an asset.");
+         }
+         
+         return node;
+      }
+      
+      // If the node doesn't exists, create it. Also create all possible non-existing 
+      // parents
+      node = new NodeImpl(path);
+      NodeImpl parentNode = obtainParent(path.getParent());
+      
+      if (parentNode != null) {
+         parentNode.addChild(node);
+      }
+      
+      // Add the node to the contents of the archive
+      content.put(path, node);
+      
+      return node;
+   }
 }

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/asset/DirectoryAsset.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/asset/DirectoryAsset.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/asset/DirectoryAsset.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -1,61 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jboss.shrinkwrap.impl.base.asset;
-
-import java.io.InputStream;
-
-import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.ArchivePath;
-import org.jboss.shrinkwrap.api.Asset;
-
-/**
- * {@link Asset} implementation used to denote no backing
- * resource, but simply a directory structure.  When placed 
- * into an {@link Archive} under some {@link ArchivePath}, only the 
- * path context will be respected.  Modeled as a singleton
- * as this implementation has no real state or identity (all
- * directory assets are equal).  Calls to {@link DirectoryAsset#openStream()}
- * will always return null.
- * 
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
-public enum DirectoryAsset implements Asset {
-
-   /**
-    * Singleton Instance
-    */
-   INSTANCE;
-
-   //-------------------------------------------------------------------------------------||
-   // Required Implementations -----------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.shrinkwrap.api.Asset#openStream()
-    */
-   @Override
-   public InputStream openStream()
-   {
-      // To signify that we've got nothing to back us (we're just a directory),
-      // we use null.  A stream backed by an empty byte array would be an 
-      // empty file, which is different.
-      return null;
-   }
-
-}

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/container/ContainerBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/container/ContainerBase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/container/ContainerBase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -28,6 +28,7 @@
 import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.Filter;
 import org.jboss.shrinkwrap.api.Filters;
+import org.jboss.shrinkwrap.api.Node;
 import org.jboss.shrinkwrap.api.container.ClassContainer;
 import org.jboss.shrinkwrap.api.container.LibraryContainer;
 import org.jboss.shrinkwrap.api.container.ManifestContainer;
@@ -247,7 +248,7 @@
     * @see org.jboss.declarchive.api.Archive#get(org.jboss.declarchive.api.Path)
     */
    @Override
-   public Asset get(ArchivePath path)
+   public Node get(ArchivePath path)
    {
       return archive.get(path);
    }
@@ -256,7 +257,7 @@
     * @see org.jboss.declarchive.api.Archive#get(java.lang.String)
     */
    @Override
-   public Asset get(String path) throws IllegalArgumentException
+   public Node get(String path) throws IllegalArgumentException
    {
       return archive.get(path);
    }
@@ -265,7 +266,7 @@
     * @see org.jboss.declarchive.api.Archive#getContent()
     */
    @Override
-   public Map<ArchivePath, Asset> getContent()
+   public Map<ArchivePath, Node> getContent()
    {
       return archive.getContent();
    }
@@ -274,7 +275,7 @@
     * @see org.jboss.shrinkwrap.api.Archive#getContent(org.jboss.shrinkwrap.api.Filter)
     */
    @Override
-   public Map<ArchivePath, Asset> getContent(Filter<ArchivePath> filter)
+   public Map<ArchivePath, Node> getContent(Filter<ArchivePath> filter)
    {
       return archive.getContent(filter);
    }

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/AbstractExporterDelegate.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/AbstractExporterDelegate.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/AbstractExporterDelegate.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -16,16 +16,14 @@
  */
 package org.jboss.shrinkwrap.impl.base.exporter;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.ArchivePaths;
+import org.jboss.shrinkwrap.api.Node;
 
 /**
  * AbstractExporterDelegate
@@ -81,23 +79,28 @@
          log.fine("Exporting archive - " + archive.getName());
       }
 
-      // Obtain all contents
-      final Map<ArchivePath, Asset> content = archive.getContent();
+      // Obtain all content
+      final Node rootNode = archive.get(ArchivePaths.create("/"));
       
-      // Process in reverse order such that we can check for parent relationships, 
-      // and not write directories twice
-      final List<ArchivePath> paths = new ArrayList<ArchivePath>(content.keySet());
-      Collections.reverse(paths);
+      // recursively process the node childs
+      for (Node child : rootNode.getChildren()) 
+      {
+         processNode(child);
+      }
+   }
+   
+   /**
+    * Recursive call to process all the node hierarchy
+    * @param node
+    */
+   protected void processNode(final Node node) 
+   {
+      processNode(node.getPath(), node);
       
-      // For every Path in the Archive
-      for (final ArchivePath entry : paths)
+      Set<Node> children = node.getChildren();
+      for (Node child : children) 
       {
-         // Get Asset information
-         final ArchivePath path = entry;
-         final Asset asset = content.get(entry);
-
-         // Process the asset
-         processAsset(path, asset);
+         processNode(child);
       }
    }
 
@@ -106,12 +109,12 @@
    //-------------------------------------------------------------------------------------||
 
    /**
-    * Template method for processing a single asset.
+    * Template method for processing a single node.
     * 
     * @param path
-    * @param asset
+    * @param node
     */
-   protected abstract void processAsset(ArchivePath path, Asset asset);
+   protected abstract void processNode(ArchivePath path, Node node);
 
    /**
     * Return the results of the export.  Should process any tasks required to finalize the export.  

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ExplodedExporterDelegate.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ExplodedExporterDelegate.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/ExplodedExporterDelegate.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -25,7 +25,7 @@
 
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.ArchivePath;
-import org.jboss.shrinkwrap.api.Asset;
+import org.jboss.shrinkwrap.api.Node;
 import org.jboss.shrinkwrap.api.exporter.ArchiveExportException;
 import org.jboss.shrinkwrap.api.exporter.ExplodedExporter;
 import org.jboss.shrinkwrap.impl.base.asset.ArchiveAsset;
@@ -79,10 +79,10 @@
 
    /**
     * {@inheritDoc}
-    * @see org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate#processAsset(ArchivePath, Asset)
+    * @see org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate#processNode(ArchivePath, Node)
     */
    @Override
-   protected void processAsset(ArchivePath path, Asset asset)
+   protected void processNode(ArchivePath path, Node node)
    {
       // Get path to file
       final String assetFilePath = path.get();
@@ -101,9 +101,9 @@
       }
 
       // Handle Archive assets separately 
-      if (asset instanceof ArchiveAsset)
+      if (node != null && node.getAsset() instanceof ArchiveAsset)
       {
-         ArchiveAsset nesteArchiveAsset = ArchiveAsset.class.cast(asset);
+         ArchiveAsset nesteArchiveAsset = ArchiveAsset.class.cast(node.getAsset());
          processArchiveAsset(assetParent, nesteArchiveAsset);
          return;
       }
@@ -111,7 +111,7 @@
       // Handle directory assets separately
       try
       {
-         final boolean isDirectory = (asset.openStream() == null);
+         final boolean isDirectory = (node.getAsset() == null);
          if (isDirectory)
          {
             // If doesn't already exist
@@ -135,7 +135,7 @@
                   log.fine("Writing asset " + path.get() + " to " + assetFile.getAbsolutePath());
                }
                // Get the asset streams
-               final InputStream assetInputStream = asset.openStream();
+               final InputStream assetInputStream = node.getAsset().openStream();
                final FileOutputStream assetFileOutputStream = new FileOutputStream(assetFile);
                final BufferedOutputStream assetBufferedOutputStream = new BufferedOutputStream(assetFileOutputStream,
                      8192);
@@ -152,7 +152,7 @@
       }
       catch (final Exception e)
       {
-         throw new ArchiveExportException("Unexpected error encountered in export of " + asset, e);
+         throw new ArchiveExportException("Unexpected error encountered in export of " + node, e);
       }
    }
 

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/JdkZipExporterDelegate.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/JdkZipExporterDelegate.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/exporter/JdkZipExporterDelegate.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -36,8 +36,8 @@
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.ArchivePath;
 import org.jboss.shrinkwrap.api.Asset;
+import org.jboss.shrinkwrap.api.Node;
 import org.jboss.shrinkwrap.api.exporter.ArchiveExportException;
-import org.jboss.shrinkwrap.impl.base.asset.DirectoryAsset;
 import org.jboss.shrinkwrap.impl.base.io.IOUtil;
 import org.jboss.shrinkwrap.impl.base.io.StreamErrorHandler;
 import org.jboss.shrinkwrap.impl.base.io.StreamTask;
@@ -84,10 +84,9 @@
     * {@link InputStream} to be returned to the caller
     */
    private InputStream inputStream;
-
+   
    /**
-    * A Set of Paths we've exported so far (so that we don't write
-    * any entries twice)
+    * Used to see if we have exported at least one node
     */
    private Set<ArchivePath> pathsExported = new HashSet<ArchivePath>();
 
@@ -144,13 +143,22 @@
             }
             catch (final Exception e)
             {
+               
                // Log this and rethrow; otherwise if we go into deadlock we won't ever 
                // be able to get the underlying cause from the Future 
                log.log(Level.WARNING, "Exception encountered during export of archive", e);
+               
+               // SHRINKWRAP-133 - if the Zip is empty, it won't close and a deadlock is triggered
+               if (pathsExported.isEmpty()) 
+               {
+                  zipOutputStream.putNextEntry(new ZipEntry("dummy.txt"));
+               }
+               
                throw e;
             }
             finally
             {
+               
                try
                {
                   zipOutputStream.close();
@@ -160,7 +168,7 @@
                   // Ignore, but warn of danger
                   log.log(Level.WARNING,
                         "[SHRINKWRAP-120] Possible deadlock scenario: Got exception on closing the ZIP out stream: "
-                              + ioe.getMessage(), ioe);
+                        + ioe.getMessage(), ioe);
                }
             }
 
@@ -206,115 +214,89 @@
 
    /**
     * {@inheritDoc}
-    * @see org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate#processAsset(ArchivePath, Asset)
+    * @see org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate#processNode(ArchivePath, Node)
     */
    @Override
-   protected void processAsset(final ArchivePath path, final Asset asset)
+   protected void processNode(final ArchivePath path, final Node node)
    {
       // Precondition checks
       if (path == null)
       {
          throw new IllegalArgumentException("Path must be specified");
       }
-      if (asset == null)
+      if (node == null)
       {
          throw new IllegalArgumentException("asset must be specified");
       }
-
-      if (isParentOfAnyPathsExported(path))
+      
+      // Mark if we're writing a directory
+      final boolean isDirectory = node.getAsset() == null;
+      
+      InputStream stream = null;
+      if (!isDirectory) 
       {
-         return;
+         stream = node.getAsset().openStream();
       }
 
-      /*
-       * SHRINKWRAP-94
-       * Add entries for all parents of this Path
-       * by recursing first and adding parents that
-       * haven't already been written.
-       */
-      final ArchivePath parent = path.getParent();
-      if (parent != null && !this.pathsExported.contains(parent))
-      {
-         // If this is not the root
-         // SHRINKWRAP-96
-         final ArchivePath grandParent = parent.getParent();
-         final boolean isRoot = grandParent == null;
-         if (!isRoot)
-         {
-            // Process the parent as directory
-            this.processAsset(parent, DirectoryAsset.INSTANCE);
-         }
-      }
-
-      // Get Asset InputStream if the asset is specified (else it's a directory so use null)
-      final InputStream assetStream = asset.openStream();
-
-      // Mark if we're writing a directory
-      final boolean isDirectory = assetStream == null;
-
-      // If we haven't already written this path
       final String pathName = PathUtil.optionallyRemovePrecedingSlash(path.get());
-      if (!this.pathsExported.contains(path))
+      
+      // Make a task for this stream and close when done
+      IOUtil.closeOnComplete(stream, new StreamTask<InputStream>()
       {
-         // Make a task for this stream and close when done
-         IOUtil.closeOnComplete(assetStream, new StreamTask<InputStream>()
-         {
 
-            @Override
-            public void execute(InputStream stream) throws Exception
+         @Override
+         public void execute(InputStream stream) throws Exception
+         {
+            String resolvedPath = pathName;
+            if (isDirectory)
             {
-               // If we're writing a directory, ensure we trail a slash for the ZipEntry
-               String resolvedPath = pathName;
-               if (isDirectory)
-               {
-                  resolvedPath = PathUtil.optionallyAppendSlash(resolvedPath);
-               }
+               resolvedPath = PathUtil.optionallyAppendSlash(resolvedPath);
+            }
 
-               // Make a ZipEntry
-               final ZipEntry entry = new ZipEntry(resolvedPath);
+            // Make a ZipEntry
+            final ZipEntry entry = new ZipEntry(resolvedPath);
 
-               /*
-                * Wait until all streams have been set up for encoding, or
-                * do nothing if everything's set up already
-                */
-               latch.await();
+            /*
+             * Wait until all streams have been set up for encoding, or
+             * do nothing if everything's set up already
+             */
+            latch.await();
 
-               // Write the Asset under the same Path name in the Zip
-               try
-               {
-                  zipOutputStream.putNextEntry(entry);
-               }
-               catch (final ZipException ze)
-               {
-                  log.log(Level.SEVERE, pathsExported.toString());
-                  throw new RuntimeException(ze);
-               }
-
-               // Mark that we've written this Path 
-               pathsExported.add(path);
-
-               // Read the contents of the asset and write to the JAR, 
-               // if we're not just a directory
-               if (!isDirectory)
-               {
-                  IOUtil.copy(stream, zipOutputStream);
-               }
-
-               // Close up the instream and the entry
-               zipOutputStream.closeEntry();
+            // Write the Asset under the same Path name in the Zip
+            try
+            {
+               zipOutputStream.putNextEntry(entry);
             }
+            catch (final ZipException ze)
+            {
+               log.log(Level.SEVERE, pathsExported.toString());
+               throw new RuntimeException(ze);
+            }
 
-         }, new StreamErrorHandler()
-         {
+            // Mark that we've written this Path 
+            pathsExported.add(path);
 
-            @Override
-            public void handle(Throwable t)
+            // Read the contents of the asset and write to the JAR, 
+            // if we're not just a directory
+            if (!isDirectory)
             {
-               throw new ArchiveExportException("Failed to write asset to Zip: " + pathName, t);
+               IOUtil.copy(stream, zipOutputStream);
             }
 
-         });
-      }
+            // Close up the instream and the entry
+            zipOutputStream.closeEntry();
+         }
+
+      }, new StreamErrorHandler()
+      {
+
+         @Override
+         public void handle(Throwable t)
+         {
+            throw new ArchiveExportException("Failed to write asset to Zip: " + path.get(), t);
+         }
+
+      });
    }
 
    /* (non-Javadoc)
@@ -326,47 +308,5 @@
       return inputStream;
    }
 
-   /**
-    * Returns whether or not this Path is a parent of any Paths exported 
-    * @param path
-    * @return
-    */
-   //TODO The performance here will degrade geometrically with size of the archive
-   private boolean isParentOfAnyPathsExported(final ArchivePath path)
-   {
-      // For all Paths already exported
-      for (final ArchivePath exportedPath : this.pathsExported)
-      {
-         if (this.isParentOfSpecifiedHierarchy(path, exportedPath))
-         {
-            return true;
-         }
-      }
 
-      return false;
-   }
-
-   /**
-    * 
-    * @param path
-    * @param compare
-    * @return
-    */
-   private boolean isParentOfSpecifiedHierarchy(final ArchivePath path, final ArchivePath compare)
-   {
-      // If we've reached the root, we're not a parent of any paths already exported
-      final ArchivePath parent = compare.getParent();
-      if (parent == null)
-      {
-         return false;
-      }
-      // If equal to me, yes
-      if (path.equals(compare))
-      {
-         return true;
-      }
-
-      // Check my parent
-      return this.isParentOfSpecifiedHierarchy(path, parent);
-   }
 }

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/importer/ExplodedImporterImpl.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/importer/ExplodedImporterImpl.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/importer/ExplodedImporterImpl.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -25,7 +25,6 @@
 import org.jboss.shrinkwrap.api.importer.ExplodedImporter;
 import org.jboss.shrinkwrap.impl.base.AssignableBase;
 import org.jboss.shrinkwrap.impl.base.Validate;
-import org.jboss.shrinkwrap.impl.base.asset.DirectoryAsset;
 import org.jboss.shrinkwrap.impl.base.asset.FileAsset;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
 
@@ -129,7 +128,7 @@
          final ArchivePath path  = calculatePath(root, file);
          if (file.isDirectory())
          {
-            archive.add(DirectoryAsset.INSTANCE,path);
+            archive.addDirectory(path);
             doImport(root, file.listFiles());
          } else
          {

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImpl.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImpl.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImpl.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -31,7 +31,6 @@
 import org.jboss.shrinkwrap.impl.base.AssignableBase;
 import org.jboss.shrinkwrap.impl.base.Validate;
 import org.jboss.shrinkwrap.impl.base.asset.ByteArrayAsset;
-import org.jboss.shrinkwrap.impl.base.asset.DirectoryAsset;
 import org.jboss.shrinkwrap.impl.base.asset.ZipFileEntryAsset;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
 
@@ -104,7 +103,7 @@
             // Handle directories separately
             if(entry.isDirectory()) 
             {
-               archive.add(DirectoryAsset.INSTANCE, entryName);
+               archive.addDirectory(entryName);
                continue; 
             }
 
@@ -160,7 +159,7 @@
               // Handle directories separately
               if(entry.isDirectory())
               {
-                 archive.add(DirectoryAsset.INSTANCE, entryName);
+                 archive.addDirectory(entryName);
                  continue;
               }
 

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/path/PathUtil.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/path/PathUtil.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/path/PathUtil.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -262,7 +262,7 @@
       // Get the parent context
       final String sub = resolvedContext.substring(0, lastIndex);
       // Return
-      return new BasicPath(PathUtil.optionallyAppendSlash(sub));
+      return new BasicPath(sub);
    }
 
    //-------------------------------------------------------------------------------------||

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/asset/DirectoryAssetTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/asset/DirectoryAssetTestCase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/asset/DirectoryAssetTestCase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -1,56 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jboss.shrinkwrap.impl.base.asset;
-
-import java.io.InputStream;
-
-import junit.framework.TestCase;
-
-import org.jboss.shrinkwrap.api.Asset;
-import org.junit.Test;
-
-/**
- * Enforces the contract of {@link DirectoryAsset}
- * 
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
-public class DirectoryAssetTestCase
-{
-
-   //-------------------------------------------------------------------------------------||
-   // Tests ------------------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Ensures the {@link DirectoryAsset} always has a null stream
-    */
-   @Test
-   public void directoryAssetHasNullStream()
-   {
-
-      // Get the asset
-      final Asset asset = DirectoryAsset.INSTANCE;
-
-      // Get the stream
-      final InputStream stream = asset.openStream();
-
-      // Ensure null
-      TestCase.assertNull("Directory assets should always have null streams (contents)", stream);
-   }
-
-}

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExportTestBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExportTestBase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExportTestBase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -22,14 +22,13 @@
 import java.util.logging.Logger;
 
 import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.Archives;
-import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.ArchivePath;
 import org.jboss.shrinkwrap.api.ArchivePaths;
+import org.jboss.shrinkwrap.api.Archives;
+import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.jboss.shrinkwrap.impl.base.TestIOUtil;
 import org.jboss.shrinkwrap.impl.base.asset.ClassLoaderAsset;
-import org.jboss.shrinkwrap.impl.base.asset.DirectoryAsset;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
 import org.junit.Assert;
 
@@ -194,8 +193,8 @@
       archive.add(nestedArchiveTwo, NESTED_PATH);
       
       // Add empty directories
-      archive.add(DirectoryAsset.INSTANCE, PATH_EMPTY_NESTED_DIR);
-      archive.add(DirectoryAsset.INSTANCE, PATH_EMPTY_TOPLEVEL_DIR);
+      archive.addDirectory(PATH_EMPTY_NESTED_DIR);
+      archive.addDirectory(PATH_EMPTY_TOPLEVEL_DIR);
 
       // Return archive
       return archive;

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterTestCase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ZipExporterTestCase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -103,6 +103,19 @@
       // Attempt to export an empty archive, should fail
       Archives.create(NAME_ARCHIVE, JavaArchive.class).as(ZipExporter.class).exportZip();
    }
+   
+   /**
+    * Test to ensure that the {@link JdkZipExporterDelegate} accepts an archive
+    * with only directories, no assets.
+    * 
+    * @throws Exception
+    */
+   @Test
+   public void testExportArchiveWithOnlyDirectories() 
+   {
+      // Attempt to export an archive with some directories, should pass
+      Archives.create(NAME_ARCHIVE, JavaArchive.class).addDirectories("/test/game").as(ZipExporter.class).exportZip();
+   }
 
    /**
     * Test to make sure an archive can be exported to Zip (file) and all 

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/formatter/VerboseFormatterTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/formatter/VerboseFormatterTestCase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/formatter/VerboseFormatterTestCase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -34,7 +34,9 @@
    //-------------------------------------------------------------------------------------||
 
    private static final String EXPECTED_OUTPUT = NAME_ARCHIVE
-         + ":\n/org/jboss/shrinkwrap/impl/base/formatter/FormatterTestBase.class\n/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.class";
+      + ":\n/org/\n/org/jboss/\n/org/jboss/shrinkwrap/\n/org/jboss/shrinkwrap/impl/\n/org/jboss/shrinkwrap/impl/base/\n"
+      + "/org/jboss/shrinkwrap/impl/base/formatter/\n/org/jboss/shrinkwrap/impl/base/formatter/FormatterTestBase.class\n"
+      + "/org/jboss/shrinkwrap/impl/base/test/\n/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.class";
 
    //-------------------------------------------------------------------------------------||
    // Required Implementations -----------------------------------------------------------||

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImplTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImplTestCase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/importer/ZipImporterImplTestCase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -232,7 +232,7 @@
          
          byte[] originalContent = IOUtil.asByteArray(testZip.getInputStream(originalEntry));
          byte[] importedContent = IOUtil.asByteArray(
-               importedArchive.get(new BasicPath(originalEntry.getName())).openStream());
+               importedArchive.get(new BasicPath(originalEntry.getName())).getAsset().openStream());
 
          log.fine(
                Arrays.equals(importedContent, originalContent) + "\t" +

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -23,11 +23,13 @@
 import junit.framework.TestCase;
 
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
 import org.jboss.shrinkwrap.api.ArchivePaths;
 import org.jboss.shrinkwrap.api.Archives;
 import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.Filters;
-import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.IllegalArchivePathException;
+import org.jboss.shrinkwrap.api.Node;
 import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.jboss.shrinkwrap.impl.base.Validate;
 import org.jboss.shrinkwrap.impl.base.asset.ArchiveAsset;
@@ -371,9 +373,9 @@
       Asset asset = new ClassLoaderAsset(NAME_TEST_PROPERTIES);
       archive.add(asset, location);
 
-      Asset fetchedAsset = archive.get(location);
+      Node fetchedNode = archive.get(location);
 
-      Assert.assertTrue("Asset should be returned from path: " + location.get(), compareAssets(asset, fetchedAsset));
+      Assert.assertTrue("Asset should be returned from path: " + location.get(), compareAssets(asset, fetchedNode.getAsset()));
    }
 
    /**
@@ -406,9 +408,9 @@
       Asset asset = new ClassLoaderAsset(NAME_TEST_PROPERTIES);
       archive.add(asset, location);
 
-      Asset fetchedAsset = archive.get(location.get());
+      Node fetchedNode = archive.get(location.get());
 
-      Assert.assertTrue("Asset should be returned from path: " + location.get(), compareAssets(asset, fetchedAsset));
+      Assert.assertTrue("Asset should be returned from path: " + location.get(), compareAssets(asset, fetchedNode.getAsset()));
    }
 
    /**
@@ -444,16 +446,16 @@
       Asset assetTwo = new ClassLoaderAsset(NAME_TEST_PROPERTIES_2);
       archive.add(asset, location).add(assetTwo, locationTwo);
 
-      Map<ArchivePath, Asset> content = archive.getContent();
+      Map<ArchivePath, Node> content = archive.getContent();
 
-      final Asset asset1 = content.get(location);
-      final Asset asset2 = content.get(locationTwo);
+      final Node node1 = content.get(location);
+      final Node node2 = content.get(locationTwo);
 
       Assert.assertTrue("Asset should existing in content with key: " + location.get(), this.compareAssets(asset,
-            asset1));
+            node1.getAsset()));
 
       Assert.assertTrue("Asset should existing in content with key: " + locationTwo.get(), this.compareAssets(assetTwo,
-            asset2));
+            node2.getAsset()));
    }
 
    /**
@@ -471,10 +473,10 @@
       Asset assetTwo = new ClassLoaderAsset(NAME_TEST_PROPERTIES_2);
       archive.add(asset, location).add(assetTwo, locationTwo);
 
-      Map<ArchivePath, Asset> content = archive.getContent(Filters.include(".*test2.*"));
+      Map<ArchivePath, Node> content = archive.getContent(Filters.include(".*test2.*"));
 
-      final Asset asset1 = content.get(location);
-      final Asset asset2 = content.get(locationTwo);
+      final Node node1 = content.get(location);
+      final Node node2 = content.get(locationTwo);
       
       Assert.assertEquals(
             "Only 1 Asset should have been included",
@@ -482,11 +484,11 @@
             content.size());
       Assert.assertNull(
             "Should not be included in content", 
-            asset1);
+            node1);
       
       Assert.assertNotNull(
             "Should be included in content", 
-            asset2);
+            node2);
    }
    
    /**
@@ -524,6 +526,46 @@
       {
       }
    }
+   
+   /**
+    * Ensure that trying to add an asset on an illegal path throws an Exception
+    * @throws Exception
+    */
+   @Test(expected=IllegalArchivePathException.class)
+   public void shouldNotBeAbleToAddAssetOnIllegalPath() throws Exception 
+   {
+      Archive<T> archive = getArchive();
+      
+      // add an asset
+      Asset asset = new ClassLoaderAsset(NAME_TEST_PROPERTIES);
+      ArchivePath location = new BasicPath("/", "test.properties");
+      archive.add(asset, location);
+      
+      // try to add an asset on an illegal path
+      Asset assetTwo = new ClassLoaderAsset(NAME_TEST_PROPERTIES_2);
+      ArchivePath locationTwo = ArchivePaths.create("/test.properties/somewhere");
+      archive.add(assetTwo, locationTwo);
+      
+   }
+   
+   /**
+    * Ensure that trying to add a directory on an illegal path throws an Exception
+    * @throws Exception
+    */
+   @Test(expected=IllegalArchivePathException.class)
+   public void shouldNotBeAbleToAddDirectoryOnIllegalPath() throws Exception 
+   {
+      Archive<T> archive = getArchive();
+      
+      // add an asset
+      Asset asset = new ClassLoaderAsset(NAME_TEST_PROPERTIES);
+      ArchivePath location = new BasicPath("/somewhere/test.properties");
+      archive.add(asset, location);
+      
+      // try to add a directory on an illegal path
+      archive.addDirectory("/somewhere/test.properties/test");
+      
+   }
 
    /**
     * Ensure merging content requires a source archive
@@ -560,11 +602,13 @@
       sourceArchive.add(asset, location).add(assetTwo, locationTwo);
 
       archive.merge(sourceArchive);
-      Assert.assertTrue("Asset should have been added to path: " + location.get(), this.compareAssets(archive
-            .get(location), asset));
+      
+      Node node1 = archive.get(location);
+      Node node2 = archive.get(locationTwo);
+      
+      Assert.assertTrue("Asset should have been added to path: " + location.get(), this.compareAssets(node1.getAsset(), asset));
 
-      Assert.assertTrue("Asset should have been added to path: " + location.get(), this.compareAssets(archive
-            .get(locationTwo), assetTwo));
+      Assert.assertTrue("Asset should have been added to path: " + location.get(), this.compareAssets(node2.getAsset(), assetTwo));
    }
 
    /**
@@ -589,12 +633,14 @@
 
       ArchivePath expectedPath = new BasicPath(baseLocation, location);
       ArchivePath expectedPathTwo = new BasicPath(baseLocation, locationTwo);
+      
+      Node nodeOne = archive.get(expectedPath);
+      Node nodeTwo = archive.get(expectedPathTwo);
 
-      Assert.assertTrue("Asset should have been added to path: " + expectedPath.get(), this.compareAssets(archive
-            .get(expectedPath), asset));
+      Assert.assertTrue("Asset should have been added to path: " + expectedPath.get(), this.compareAssets(nodeOne.getAsset(), asset));
 
       Assert.assertTrue("Asset should have been added to path: " + expectedPathTwo.getClass(), this.compareAssets(
-            archive.get(expectedPathTwo), assetTwo));
+            nodeTwo.getAsset(), assetTwo));
    }
 
    /**
@@ -620,13 +666,13 @@
       Assert.assertEquals(
             "Should only have merged 1",
             1, 
-            archive.getContent().size());
+            numAssets(archive));
       
       ArchivePath expectedPath = new BasicPath(baseLocation, locationTwo);
 
       Assert.assertTrue(
             "Asset should have been added to path: " + expectedPath.get(), 
-            this.compareAssets(archive.get(expectedPath), asset));
+            this.compareAssets(archive.get(expectedPath).getAsset(), asset));
    }
 
    /**
@@ -650,11 +696,11 @@
       Assert.assertEquals(
             "Should only have merged 1",
             1, 
-            archive.getContent().size());
+            numAssets(archive));
       
       Assert.assertTrue(
             "Asset should have been added to path: " + locationTwo.get(), 
-            this.compareAssets(archive.get(locationTwo), asset));
+            this.compareAssets(archive.get(locationTwo).getAsset(), asset));
    }
 
    /**
@@ -691,11 +737,11 @@
 
       ArchivePath expectedPath = new BasicPath(baseLocation, sourceArchive.getName());
 
-      Asset asset = archive.get(expectedPath);
-      Assert.assertNotNull("Asset should have been added to path: " + expectedPath.get(), asset);
+      Node node = archive.get(expectedPath);
+      Assert.assertNotNull("Asset should have been added to path: " + expectedPath.get(), node);
       Assert.assertTrue("An instance of ArchiveAsset should have been added to path: " + expectedPath.get(),
-            asset instanceof ArchiveAsset);
-      ArchiveAsset archiveAsset = ArchiveAsset.class.cast(asset);
+            node.getAsset() instanceof ArchiveAsset);
+      ArchiveAsset archiveAsset = ArchiveAsset.class.cast(node.getAsset());
 
       Archive<?> nestedArchive = archiveAsset.getArchive();
       Assert.assertEquals("Nested Archive should be same archive that was added", sourceArchive, nestedArchive);
@@ -762,10 +808,10 @@
 
       ArchivePath expectedPath = new BasicPath(nestedNestedArchivePath, "test.properties");
 
-      Asset nestedAsset = archive.get(expectedPath);
+      Node nestedNode = archive.get(expectedPath);
 
       Assert.assertNotNull("Nested archive asset should be available through partent archive at " + expectedPath.get(),
-            nestedAsset);
+            nestedNode.getAsset());
    }
 
    //-------------------------------------------------------------------------------------||
@@ -793,5 +839,31 @@
 
       return Arrays.equals(oneData, twoData);
    }
+   
+   /**
+    * Returns the number of assets in a file.
+    * 
+    * @param archive the Archive from which we want to retrieve the number
+    * of assets
+    * @return the number of assets in the archive
+    * @throws IllegalArgumentException If the archive is not specified
+    */
+   protected int numAssets(final Archive<?> archive) 
+   {
+      // Precondition check
+      Validate.notNull(archive, "Archive must be specified");
+      
+      int assets = 0;
+      
+      Map<ArchivePath, Node> content = archive.getContent();
+      for (Map.Entry<ArchivePath, Node> entry : content.entrySet()) {
+         if (entry.getValue().getAsset() != null) 
+         {
+            assets++;
+         }
+      }
+      
+      return assets;
+   }
 
 }

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/DynamicContainerTestBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/DynamicContainerTestBase.java	2010-02-22 19:26:38 UTC (rev 4047)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/DynamicContainerTestBase.java	2010-02-22 23:14:56 UTC (rev 4048)
@@ -557,7 +557,7 @@
       Assert.assertEquals(
             "Should only be one class added",
             1,
-            getArchive().getContent().size());
+            numAssets(getArchive()));
 
       Assert.assertTrue(
             "A class should be located at " + expectedPath.get(), 



More information about the jboss-svn-commits mailing list