Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/ClassloaderResourceTestCase.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/ClassloaderResourceTestCase.java	(revision 3449)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/ClassloaderResourceTestCase.java	(working copy)
@@ -20,7 +20,7 @@
 
 import junit.framework.Assert;
 
-import org.jboss.declarchive.spi.Resource;
+import org.jboss.declarchive.api.Resource;
 import org.junit.Test;
 
 /**
@@ -57,6 +57,14 @@
    }
 
    @Test
+   public void shouldBeAbleToReadDefaultPath() throws Exception
+   {
+      Resource resource = new ClassloaderResource(EXISTING_RESOURCE);
+      Assert.assertEquals("A Classloader resource should use given resource path as default path",
+            "/org/jboss/declarchive/impl/base/resource/", resource.getDefaultPath().get());
+   }
+
+   @Test
    public void shouldThrowExceptionOnNullName()
    {
       try
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/FileResourceTestCase.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/FileResourceTestCase.java	(revision 3449)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/FileResourceTestCase.java	(working copy)
@@ -21,7 +21,7 @@
 
 import junit.framework.Assert;
 
-import org.jboss.declarchive.spi.Resource;
+import org.jboss.declarchive.api.Resource;
 import org.junit.Test;
 
 /**
@@ -47,8 +47,8 @@
       InputStream io = resource.getStream();
 
       Assert.assertNotNull(io);
-      Assert.assertEquals("Should be able to read the content of the resource", "declarch=true", TestUtils
-            .convertToString(io));
+      Assert.assertEquals("Should be able to read the content of the resource", "declarch=true", 
+            TestUtils.convertToString(io));
    }
 
    @Test
@@ -60,6 +60,14 @@
    }
 
    @Test
+   public void shouldBeAbleToReadDefaultPath() throws Exception
+   {
+      Resource resource = new FileResource(new File(EXISTING_FILE));
+      Assert.assertEquals("A File resource should use the file parent name as default path",
+            "/src/test/resources/org/jboss/declarchive/impl/base/resource/", resource.getDefaultPath().get());
+   }
+
+   @Test
    public void shouldThrowExceptionOnNullFile() throws Exception
    {
       try
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/URLResourceTestCase.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/URLResourceTestCase.java	(revision 3449)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/URLResourceTestCase.java	(working copy)
@@ -20,7 +20,7 @@
 
 import junit.framework.Assert;
 
-import org.jboss.declarchive.spi.Resource;
+import org.jboss.declarchive.api.Resource;
 import org.junit.Test;
 
 /**
@@ -38,7 +38,8 @@
    @Test
    public void shouldBeAbleToReadURL() throws Exception
    {
-      Resource resource = new URLResource(Thread.currentThread().getContextClassLoader().getResource(EXISTING_RESOURCE));
+      Resource resource = new URLResource(
+            Thread.currentThread().getContextClassLoader().getResource(EXISTING_RESOURCE));
 
       InputStream io = resource.getStream();
 
@@ -50,13 +51,24 @@
    @Test
    public void shouldBeAbleToReadDefaultName() throws Exception
    {
-      Resource resource = new URLResource(Thread.currentThread().getContextClassLoader().getResource(EXISTING_RESOURCE));
+      Resource resource = new URLResource(
+            Thread.currentThread().getContextClassLoader().getResource(EXISTING_RESOURCE));
 
       Assert.assertEquals("A URL resource should use the file name as default name, not absolute path",
             "Test.properties", resource.getDefaultName());
    }
 
    @Test
+   public void shouldBeAbleToReadDefaultPath() throws Exception
+   {
+      Resource resource = new URLResource(
+            Thread.currentThread().getContextClassLoader().getResource(EXISTING_RESOURCE));
+
+      Assert.assertEquals("A URL resource should use / as default path",
+            "/", resource.getDefaultPath().get());
+   }
+
+   @Test
    public void shouldThrowExceptionOnNullURL() throws Exception
    {
       try
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/ClassResourceTestCase.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/ClassResourceTestCase.java	(revision 3449)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/resource/ClassResourceTestCase.java	(working copy)
@@ -18,7 +18,7 @@
 
 import java.io.InputStream;
 
-import org.jboss.declarchive.spi.Resource;
+import org.jboss.declarchive.api.Resource;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -48,11 +48,19 @@
    public void shouldBeAbleToReadDefaultName() throws Exception
    {
       Resource resource = new ClassResource(ClassResourceTestCase.class);
-      Assert.assertEquals("A Class resource should use class name + '.class' as default name",
-            "org/jboss/declarchive/impl/base/resource/ClassResourceTestCase.class", resource.getDefaultName());
+      Assert.assertEquals("A Class resource should use class simple name + '.class' as default name",
+            "ClassResourceTestCase.class", resource.getDefaultName());
    }
 
    @Test
+   public void shouldBeAbleToReadPathName() throws Exception
+   {
+      Resource resource = new ClassResource(ClassResourceTestCase.class);
+      Assert.assertEquals("A Class resource should use class package name as default path",
+            "/org/jboss/declarchive/impl/base/resource/", resource.getDefaultPath().get());
+   }
+
+   @Test
    public void shouldThrowExceptionOnNullClass() throws Exception
    {
       try
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/path/PathTestCase.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/path/PathTestCase.java	(revision 0)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/path/PathTestCase.java	(revision 0)
@@ -0,0 +1,108 @@
+/*
+ * 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.declarchive.impl.base.path;
+
+import junit.framework.Assert;
+
+import org.jboss.declarchive.api.Path;
+import org.junit.Test;
+
+
+/**
+ * PathTestCase
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class PathTestCase
+{
+
+   @Test
+   public void shouldResolveBasePathWithNoPrefixPostfix() throws Exception 
+   {
+      testBasePath(new BasePath("WEB-INF"));
+   }
+
+   @Test
+   public void shouldResolveBasePathWithNoPrefix() throws Exception 
+   {
+      testBasePath(new BasePath("WEB-INF/"));
+   }
+
+   @Test
+   public void shouldResolveBasePathWithNoPostfix() throws Exception 
+   {
+      testBasePath(new BasePath("/WEB-INF"));
+   }
+
+   @Test
+   public void shouldResolveBasePathWithPrefixPostfix() throws Exception 
+   {
+      testBasePath(new BasePath("/WEB-INF/"));
+   }
+   
+   @Test
+   public void shouldResolveRelativePathWithNoPrefixPostfix() throws Exception 
+   {
+      testRelativePath(
+            new RelativePath(
+                  new BasePath("WEB-INF"), 
+                  "classes"));
+   }
+
+   @Test
+   public void shouldResolveRelativePathWithNoPrefix() throws Exception 
+   {
+      testRelativePath(
+            new RelativePath(
+                  new BasePath("WEB-INF"), 
+                  "classes/"));
+   }
+   
+   @Test
+   public void shouldResolveRelativePathWithNoPostfix() throws Exception 
+   {
+      testRelativePath(
+            new RelativePath(
+                  new BasePath("WEB-INF"), 
+                  "/classes"));
+   }
+
+   @Test
+   public void shouldResolveRelativePathWithPrefixPostfix() throws Exception 
+   {
+      testRelativePath(
+            new RelativePath(
+                  new BasePath("WEB-INF"), 
+                  "/classes/"));
+   }
+   
+   private void testRelativePath(Path path) throws Exception {
+      Assert.assertEquals(
+            "Should resolve realtive path",
+           "/WEB-INF/classes/", path.get());
+     
+   }
+   
+   private void testBasePath(Path path) 
+   {
+      Assert.assertEquals(
+            "Should resolve a absolute path to root",
+            "/WEB-INF/", path.get());
+   }
+}
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/ArchiveProxyTestCase.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/ArchiveProxyTestCase.java	(revision 0)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/ArchiveProxyTestCase.java	(revision 0)
@@ -0,0 +1,61 @@
+/*
+ * 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.declarchive.impl.base.jar;
+
+import org.jboss.declarchive.api.jar.WebArchive;
+import org.jboss.declarchive.impl.base.path.BasePath;
+import org.jboss.declarchive.impl.base.path.ResourcePath;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * ArchiveProxyTestCase
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class ArchiveProxyTestCase
+{
+   private WebArchive archive;
+   
+   @Before 
+   public void createArchive() throws Exception {
+      MockArchive<WebArchive> backingArchive = new MockArchive<WebArchive>();
+      archive = ArchiveProxy.createWebArchive(backingArchive);
+   }
+   
+   @After
+   public void printArchive() throws Exception {
+      System.out.println(archive.toString(true));   
+   }
+   
+   @Test
+   public void shouldBeAbleToAssambleProxy() throws Exception {
+      archive
+         .setManifest("org/jboss/declarchive/impl/base/resource/Test.properties")
+         .setWebXML("org/jboss/declarchive/impl/base/resource/Test.properties");
+      
+      Assert.assertTrue(
+            archive.contains(
+                  new ResourcePath(
+                        new BasePath("/WEB-INF/"), 
+                        "web.xml")));
+   }
+}
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/ArchiveProxy.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/ArchiveProxy.java	(revision 0)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/ArchiveProxy.java	(revision 0)
@@ -0,0 +1,136 @@
+/*
+ * 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.declarchive.impl.base.jar;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.jar.WebArchive;
+import org.jboss.declarchive.impl.base.container.ArchiveContainerBase;
+import org.jboss.declarchive.impl.base.container.ManifestContainerBase;
+import org.jboss.declarchive.impl.base.container.WebContainerBase;
+import org.jboss.declarchive.impl.base.path.BasePath;
+
+/**
+ * ArchiveProxy
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class ArchiveProxy
+{
+
+   public static WebArchive createWebArchive(Archive<WebArchive> archive) 
+      throws Exception
+   {
+      Map<Path, Class<?>> handlers = new HashMap<Path, Class<?>>();
+      handlers.put(
+            new BasePath("META-INF"), 
+            ManifestContainerBase.class);
+      handlers.put(
+            new BasePath("WEB-INF"), 
+            WebContainerBase.class);
+      
+      return createProxy(WebArchive.class, handlers, archive);
+   }
+   
+   @SuppressWarnings("unchecked")
+   public static <T extends Archive<T>> T createProxy(
+         Class<T> clazz, Map<Path, Class<?>> handlers, Archive<T> archive) 
+      throws Exception 
+   {
+      T proxy = (T)Proxy.newProxyInstance(
+            Thread.currentThread().getContextClassLoader(),
+            new Class[]{clazz, Handler.class},
+            new ArchiveInvocationHandler());
+      
+      Archive<T> archiveContainer = (Archive<T>)createNewInstnace(
+            new BasePath("/"), clazz, ArchiveContainerBase.class, archive);
+      
+      Map<Class<?>, Object> initializedHandlers = initializeHandlers(clazz, proxy, handlers);
+      initializedHandlers.put(Archive.class, archiveContainer);
+      
+      ((Handler)proxy).setHandlers(initializedHandlers);
+      return proxy;
+   }
+   
+   private static <T extends Archive<T>> Map<Class<?>, Object> initializeHandlers(
+         Class<T> clazz, T proxy, Map<Path, Class<?>> handlers)
+         throws Exception
+   {
+      Map<Class<?>, Object> initHandlers = new HashMap<Class<?>, Object>();
+      for(Map.Entry<Path, Class<?>> handlerEntry : handlers.entrySet())
+      {
+         Object instance = createNewInstnace(handlerEntry.getKey(), clazz, handlerEntry.getValue(), proxy);
+         initHandlers.put(
+               handlerEntry.getValue().getInterfaces()[0], 
+               instance);
+      }
+      return initHandlers;
+   }
+
+   private static <T extends Archive<T>> Object createNewInstnace(Path path, Class<T> clazz, Class<?> base, Archive<T> archive) 
+      throws Exception
+   {
+      for(Constructor<?> constructor : base.getConstructors()) {
+         System.out.println(constructor.toGenericString());
+         return constructor.newInstance(path, archive);
+      }
+      return null;
+   }
+   
+   public static interface Handler {
+      void setHandlers(Map<Class<?>, Object> handlers);
+   }
+   
+   public static class ArchiveInvocationHandler implements InvocationHandler, Handler 
+   {
+      private Map<Class<?>, Object> handlers;
+      
+      public ArchiveInvocationHandler()
+      {
+      }
+      
+      @Override
+      public void setHandlers(Map<Class<?>, Object> handlers)
+      {
+         this.handlers = handlers;
+      }
+      
+      @Override
+      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+      {
+         if(Handler.class == method.getDeclaringClass()) {
+            this.setHandlers((Map<Class<?>, Object>)args[0]);
+            return null;
+         }
+         Object handler = handlers.get(method.getDeclaringClass());
+         Object returnValue = method.invoke(handler, args);
+         if(method.getReturnType() == Archive.class) {
+            return proxy;
+         }
+         return returnValue;
+      }
+   }
+}
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/JavaArchiveImplTest.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/JavaArchiveImplTest.java	(revision 0)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/JavaArchiveImplTest.java	(revision 0)
@@ -0,0 +1,144 @@
+/*
+ * 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.declarchive.impl.base.jar;
+
+import junit.framework.Assert;
+
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.jar.JavaArchive;
+import org.jboss.declarchive.impl.base.jar.donotchange.DummyClassUsedForClassResourceTest;
+import org.jboss.declarchive.impl.base.path.BasePath;
+import org.jboss.declarchive.impl.base.path.RelativePath;
+import org.jboss.declarchive.impl.base.path.ResourcePath;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * JavaArchiveImplTest
+ * 
+ * Test to ensure that the JavaArchiveImpl follow the Java Archive specification.
+ * 
+ * @see JavaArchive
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class JavaArchiveImplTest
+{
+   private static final String TEST_RESOURCE = "org/jboss/declarchive/impl/base/resource/Test.properties";
+
+   private static final Path PATH_MANIFEST = new BasePath("META-INF");
+   private static final Path PATH_RESOURCE = new BasePath("/");
+   private static final Path PATH_CLASS = new BasePath("/");
+   
+   private JavaArchive archive;
+
+   @Before
+   public void createArchive()
+   {
+      archive = new JavaArchiveImpl(new MockArchive<JavaArchive>());
+   }
+
+   @After
+   public void printArchive()
+   {
+      System.out.println("test@jboss:/$ ls -l " + archive.getName());
+      System.out.println(archive.toString(true));
+   }
+
+   @Test
+   public void shouldBeAbleToSetManifestFile() throws Exception
+   {
+      archive.setManifest(TEST_RESOURCE);
+      Assert.assertTrue(
+            "The MANIFEST.MF file should be located under /META-INF/MANIFEST.MF",
+            archive.contains(new ResourcePath(PATH_MANIFEST, "MANIFEST.MF")));
+   }
+   
+   @Test
+   public void shouldBeAbleToAddManifestResource() throws Exception
+   {
+      archive.addManifestResource(TEST_RESOURCE);
+      Assert.assertTrue(
+            "A manifest resource should be located under /META-INF/",
+            archive.contains(new ResourcePath(
+                  new RelativePath(PATH_MANIFEST, "/org/jboss/declarchive/impl/base/resource/"), 
+                  "Test.properties")));
+   }
+
+   @Test
+   public void shouldBeAbleToAddManifestResourceWithNewName() throws Exception
+   {
+      String newName = "test.txt";
+      archive.addManifestResource(TEST_RESOURCE, newName);
+      Assert.assertTrue(
+            "A manifest resoruce should be located under /META-INF/",
+            archive.contains(new ResourcePath(
+                  new RelativePath(PATH_MANIFEST, "/org/jboss/declarchive/impl/base/resource/"), 
+                  newName)));
+   }
+   
+   @Test
+   public void shouldBeAbleToAddResource() throws Exception
+   {
+      archive.addResource(TEST_RESOURCE);
+      Assert.assertTrue(
+            "A resoruce should be located under /",
+            archive.contains(new ResourcePath(
+                  new RelativePath(PATH_RESOURCE, "/org/jboss/declarchive/impl/base/resource/"), 
+                  "Test.properties")));
+   }
+
+   @Test
+   public void shouldBeAbleToAddResourceWithNewName() throws Exception
+   {
+      String newName = "test.txt";
+      archive.addResource(TEST_RESOURCE, newName);
+      Assert.assertTrue(
+            "A resoruce should be located under /",
+            archive.contains(new ResourcePath(
+                  new RelativePath(PATH_RESOURCE, "/org/jboss/declarchive/impl/base/resource/"), 
+                  newName)));
+
+   }
+   
+   @Test
+   public void shouldBeAbleToAddClass() throws Exception
+   {
+      archive.addClass(DummyClassUsedForClassResourceTest.class);
+      
+      Assert.assertTrue(
+            "A classes should be located under /",
+            archive.contains(
+                  new ResourcePath(
+                        new RelativePath(PATH_CLASS, "org/jboss/declarchive/impl/base/jar/donotchange"), 
+                        "DummyClassUsedForClassResourceTest.class")));
+   }
+
+   @Test
+   public void shouldBeAbleToAddPackage() throws Exception
+   {
+      archive.addPackages(DummyClassUsedForClassResourceTest.class.getPackage());
+      
+      Assert.assertTrue(
+            "A classes should be located under /",
+            archive.contains(
+                  new ResourcePath(
+                        new RelativePath(PATH_CLASS, "org/jboss/declarchive/impl/base/jar/donotchange"), 
+                        "DummyClassUsedForClassResourceTest.class")));
+   }
+}
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/donotchange/DummyClassUsedForClassResourceTest.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/donotchange/DummyClassUsedForClassResourceTest.java	(revision 0)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/donotchange/DummyClassUsedForClassResourceTest.java	(revision 0)
@@ -0,0 +1,30 @@
+/*
+ * 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.declarchive.impl.base.jar.donotchange;
+
+/**
+ * DummyClassUsedForClassResourceTest
+ * 
+ * This class is just here for the ClassContainer.addPackage/addClass tests.
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class DummyClassUsedForClassResourceTest
+{
+
+}
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/MockArchive.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/MockArchive.java	(revision 0)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/MockArchive.java	(revision 0)
@@ -0,0 +1,137 @@
+/*
+ * 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.declarchive.impl.base.jar;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.impl.base.path.ResourcePath;
+
+/**
+ * MockArchive
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ * @param <T>
+ */
+public class MockArchive<T extends Archive<T>> implements Archive<T>
+{
+   private Map<String, Resource> content;
+   private String uniqueId;
+   
+   
+   public MockArchive()
+   {
+      this.content = new HashMap<String, Resource>();
+      this.uniqueId = UUID.randomUUID().toString();
+   }
+   
+   @Override
+   public String getName()
+   {
+      return "MockArchive-" + uniqueId + ".jar";
+   }
+   
+   @SuppressWarnings("unchecked")
+   @Override
+   public T add(Resource... resources)
+   {
+      for(Resource resource : resources) {
+         add(resource.getDefaultPath(), resource.getDefaultName(), resource);
+      }
+      return (T)this;
+   }
+   
+   @SuppressWarnings("unchecked")
+   @Override
+   public T add(Path path, Resource... resources)
+   {
+      for(Resource resource : resources) 
+      {
+         add(path, resource.getDefaultName(), resource);
+      }
+      return (T)this;
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public T add(Path path, String name, Resource resource)
+   {
+      content.put(new ResourcePath(path, name).get(), resource);
+      return (T)this;
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public T add(String name, Resource resource)
+   {
+      add(resource.getDefaultPath(), name, resource);
+      return (T)this;
+   }
+
+   @Override
+   public boolean contains(Path path)
+   {
+      return content.containsKey(path.get());
+   }
+
+   @Override
+   public boolean delete(Path path)
+   {
+      return content.remove(path.get()) != null;
+   }
+
+   @Override
+   public Resource get(Path path)
+   {
+      return content.get(path.get());
+   }
+
+   @Override
+   public Map<Path, Resource> getContent()
+   {
+      throw new UnsupportedOperationException("NOT YET IMPLEMENTED");
+   }
+
+   @Override
+   public String toString(boolean verbose)
+   {
+      StringBuilder sb = new StringBuilder();
+      List<String> keys = new ArrayList<String>(content.keySet());
+      Collections.sort(keys);
+      
+      for(String key : keys) 
+      {
+         sb.append(key).append('\n');
+      }
+      return sb.toString();
+   }
+   
+   @Override
+   public String toString()
+   {
+      return toString(false);
+   }
+}
Index: impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/WebArchiveImplTestCase.java
===================================================================
--- impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/WebArchiveImplTestCase.java	(revision 0)
+++ impl-base/src/test/java/org/jboss/declarchive/impl/base/jar/WebArchiveImplTestCase.java	(revision 0)
@@ -0,0 +1,74 @@
+/*
+ * 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.declarchive.impl.base.jar;
+
+import junit.framework.Assert;
+
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.jar.WebArchive;
+import org.jboss.declarchive.impl.base.path.BasePath;
+import org.jboss.declarchive.impl.base.path.ResourcePath;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * Test case to ensure that the WebArchiveImpl follow the 
+ * java Web Archive specification structure.
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class WebArchiveImplTestCase
+{
+   private Path webinfPath = new BasePath("WEB-INF");
+   
+   private WebArchive archive;
+   
+   
+   @Before
+   public void createWebArchive() throws Exception {
+      archive = new WebArchiveImpl(new MockArchive<WebArchive>());
+   }
+
+   @After
+   public void displayArchive() throws Exception {
+      System.out.println("Archive:\n" + archive.toString(true));
+   }
+   
+   @Test
+   public void shouldPlaceWebXMLInWebInf() throws Exception 
+   {
+      archive.setWebXML("org/jboss/declarchive/impl/base/resource/Test.properties");
+      Assert.assertTrue(
+            "web.xml should be located in /WEB-INF/web.xml",
+            archive.contains(new ResourcePath(webinfPath, "web.xml")));
+   }
+
+   @Test
+   public void shouldPlaceLibrariesInWebInf() throws Exception 
+   {
+      
+   }
+
+   @Test
+   public void shouldPlaceClassesInWebInf() throws Exception 
+   {
+      
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ArchiveContainerBase.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ArchiveContainerBase.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ArchiveContainerBase.java	(revision 0)
@@ -0,0 +1,132 @@
+/*
+ * 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.declarchive.impl.base.container;
+
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+
+/**
+ * ArchiveContainerBase
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ * @param <T>
+ */
+public class ArchiveContainerBase<T extends Archive<T>> implements Archive<T>
+{
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(ArchiveContainerBase.class.getName());
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Backing archive for this Container
+    */
+   private final T archive;
+   private final Path basePath;
+   
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   public ArchiveContainerBase(final Path basePath, final T archive)
+   {
+      this.basePath = basePath;
+      this.archive = archive;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   @Override
+   public String getName()
+   {
+      return archive.getName();
+   }
+
+   @Override
+   public T add(Path path, Resource... resources)
+   {
+      archive.add(path, resources);
+      return (T)this;
+   }
+   
+   @Override
+   public T add(Path path, String name, Resource resource)
+   {
+      archive.add(path, name, resource);
+      return (T)this;
+   }
+   
+   @Override
+   public T add(Resource... resources)
+   {
+      archive.add(resources);
+      return (T)this;
+   }
+   
+   @Override
+   public T add(String name, Resource resource)
+   {
+      archive.add(name, resource);
+      return (T)this;
+   }
+   
+   @Override
+   public boolean contains(Path path)
+   {
+      return archive.contains(path);
+   }
+   
+   @Override
+   public boolean delete(Path path)
+   {
+      return archive.delete(path);
+   }
+   
+   @Override
+   public Resource get(Path path)
+   {
+      return archive.get(path);
+   }
+   
+   @Override
+   public Map<Path, Resource> getContent()
+   {
+      return archive.getContent();
+   }
+   
+   @Override
+   public String toString(boolean verbose)
+   {
+      return archive.toString(verbose);
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ManifestContainerBase.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ManifestContainerBase.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ManifestContainerBase.java	(revision 0)
@@ -0,0 +1,100 @@
+/*
+ * 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.declarchive.impl.base.container;
+
+import java.util.logging.Logger;
+
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.container.ManifestContainer;
+import org.jboss.declarchive.impl.base.resource.ClassloaderResource;
+
+/**
+ * ManifestContainerBase
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ * @param <T>
+ */
+public class ManifestContainerBase<T extends Archive<T>> implements ManifestContainer<T>
+{
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(ManifestContainerBase.class.getName());
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Backing archive for this Container
+    */
+   private final T archive;
+   private final Path basePath;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   public ManifestContainerBase(final Path basePath, final T archive)
+   {
+      this.basePath = basePath;
+      this.archive = archive;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   @Override
+   public T addManifestResource(final String resourceName)
+   {
+      return archive.add(basePath, new ClassloaderResource(resourceName));
+   }
+
+   @Override
+   public T addManifestResource(final String resourceName, final String newName)
+   {
+      return archive.add(basePath, newName, new ClassloaderResource(resourceName));
+   }
+
+   @Override
+   public T addManifestResource(String resourceName, String newName, String path)
+   {
+      throw new UnsupportedOperationException("not implemented");
+   }
+   
+   @Override
+   public T setManifest(final String resourceName)
+   {
+      return archive.add(basePath, "MANIFEST.MF", new ClassloaderResource(resourceName));
+   }
+   
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ThreadContextClassLoaderResourceContainer.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ThreadContextClassLoaderResourceContainer.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ThreadContextClassLoaderResourceContainer.java	(revision 0)
@@ -0,0 +1,63 @@
+/*
+ * 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.declarchive.impl.base.container;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.container.ResourceContainer;
+
+/**
+ * ThreadContextClassLoaderResourceContainer
+ * 
+ * A {@link ResourceContainer} which uses the Thread Context ClassLoader
+ * to load requested resources.
+ *
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class ThreadContextClassLoaderResourceContainer<T extends Archive<T>> extends ResourceContainerBase<T>
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new Resource Container targeted to 
+    * the specified archive
+    * 
+    * @param archive
+    * @throws IllegalArgumentException If the archive is not specified
+    */
+   public ThreadContextClassLoaderResourceContainer(final T archive)
+   {
+      // Super
+      super(archive);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * @see org.jboss.declarchive.impl.base.container.ResourceContainerBase#getClassLoader()
+    */
+   @Override
+   ClassLoader getClassLoader()
+   {
+      return SecurityActions.getThreadContextClassLoader();
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ResourceContainerBase.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ResourceContainerBase.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/container/ResourceContainerBase.java	(revision 0)
@@ -0,0 +1,191 @@
+/*
+ * 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.declarchive.impl.base.container;
+
+import java.util.logging.Logger;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.api.container.ResourceContainer;
+import org.jboss.declarchive.impl.base.path.BasePath;
+import org.jboss.declarchive.impl.base.resource.ClassloaderResource;
+
+/**
+ * ResourceContainerBase
+ * 
+ * A {@link ResourceContainer} which uses the Thread Context ClassLoader
+ * to load requested resources.
+ *
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+abstract class ResourceContainerBase<T extends Archive<T>> implements ResourceContainer<T>
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(ResourceContainerBase.class.getName());
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Backing archive for this Container
+    */
+   private final T archive;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new Resource Container targeted to 
+    * the specified archive
+    * 
+    * @param archive
+    * @throws IllegalArgumentException If the archive is not specified
+    */
+   public ResourceContainerBase(final T archive)
+   {
+      // Precondition check
+      if (archive == null)
+      {
+         throw new IllegalArgumentException("archive must be specified");
+      }
+
+      // Set properties
+      this.archive = archive;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * @see org.jboss.declarchive.api.container.ResourceContainer#addResource(java.lang.String)
+    */
+   @Override
+   public T addResource(final String name) throws IllegalArgumentException
+   {
+      // Make a resource
+      final Resource resource = this.getResource(name);
+
+      // Make a Path
+      final Path path = resource.getDefaultPath();
+
+      // Return
+      return this.addResource(resource, path);
+   }
+
+   /**
+    * @see org.jboss.declarchive.api.container.ResourceContainer#addResource(java.lang.String, java.lang.String)
+    */
+   @Override
+   public T addResource(final String name, final String locationWithinContainer) throws IllegalArgumentException
+   {
+      // Make a resource
+      final Resource resource = this.getResource(name);
+
+      // Make a Path using the explicit location
+      final Path path = new BasePath(locationWithinContainer);
+
+      // Return
+      return this.addResource(resource, path);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Obtains the ClassLoader used to look up resources 
+    */
+   abstract ClassLoader getClassLoader();
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Adds the specified resource to the specified path
+    * 
+    * @param resource
+    * @param path
+    * @throws IllegalArgumentException If either the resource or path is not specified
+    */
+   private T addResource(final Resource resource, final Path path) throws IllegalArgumentException
+   {
+      // Precondition checks
+      if (resource == null)
+      {
+         throw new IllegalArgumentException("resource must be specified");
+      }
+      if (path == null)
+      {
+         throw new IllegalArgumentException("path must be specified");
+      }
+
+      // Get Archive
+      final T archive = this.getArchive();
+
+      // Add
+      archive.add(path, resource);
+
+      // Return
+      return archive;
+   }
+
+   /**
+    * Obtains a resource from the specified name
+    * 
+    * @param name
+    * @return
+    * @throws IllegalArgumentException If the name is not specified
+    */
+   private Resource getResource(final String name)
+   {
+      // Precondition checks
+      if (name == null || name.length() == 0)
+      {
+         throw new IllegalArgumentException("name must be specified");
+      }
+
+      // Get the CL
+      final ClassLoader cl = this.getClassLoader();
+
+      // Make a resource
+      final Resource resource = new ClassloaderResource(name, cl);
+
+      // Return
+      return resource;
+   }
+
+   /**
+    * @return the archive
+    */
+   private final T getArchive()
+   {
+      return archive;
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/container/SecurityActions.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/container/SecurityActions.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/container/SecurityActions.java	(revision 0)
@@ -0,0 +1,63 @@
+/*
+ * 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.declarchive.impl.base.container;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * SecurityActions
+ * 
+ * A set of privileged actions that are not to leak out
+ * of this package 
+ *
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+class SecurityActions
+{
+
+   //-------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------||
+
+   /**
+    * No external instantiation
+    */
+   private SecurityActions()
+   {
+
+   }
+
+   //-------------------------------------------------------------------------------||
+   // Utility Methods --------------------------------------------------------------||
+   //-------------------------------------------------------------------------------||
+
+   /**
+    * Obtains the Thread Context ClassLoader
+    */
+   static ClassLoader getThreadContextClassLoader()
+   {
+      return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
+      {
+         public ClassLoader run()
+         {
+            return Thread.currentThread().getContextClassLoader();
+         }
+      });
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/container/WebContainerBase.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/container/WebContainerBase.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/container/WebContainerBase.java	(revision 0)
@@ -0,0 +1,72 @@
+/*
+ * 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.declarchive.impl.base.container;
+
+import java.util.logging.Logger;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.container.WebContainer;
+import org.jboss.declarchive.impl.base.resource.ClassloaderResource;
+
+/**
+ * WebContainerBase
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ * @param <T>
+ */
+public class WebContainerBase<T extends Archive<T>> implements WebContainer<T>
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(WebContainerBase.class.getName());
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Backing archive for this Container
+    */
+   private final T archive;
+   private final Path basePath;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   public WebContainerBase(final Path basePath, final T archive)
+   {
+      this.basePath = basePath;
+      this.archive = archive;
+   }
+   
+   @Override
+   public T setWebXML(String resourceName)
+   {
+      return archive.add(basePath, "web.xml", new ClassloaderResource(resourceName));
+   }
+   
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/ClassloaderResource.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/ClassloaderResource.java	(revision 3449)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/ClassloaderResource.java	(working copy)
@@ -19,7 +19,10 @@
 import java.io.InputStream;
 import java.net.URL;
 
-import org.jboss.declarchive.spi.Resource;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.impl.base.Validate;
+import org.jboss.declarchive.impl.base.path.BasePath;
 
 /**
  * Loads the content of any resource located in the Classloader.
@@ -56,18 +59,12 @@
     */
    public ClassloaderResource(String resourceName, ClassLoader classLoader)
    {
-      if (resourceName == null)
-      {
-         throw new IllegalArgumentException("ResourceName must be specified");
-      }
-      if (classLoader == null)
-      {
-         throw new IllegalArgumentException("ClassLoader must be specified");
-      }
-      if (classLoader.getResource(resourceName) == null)
-      {
-         throw new IllegalArgumentException(resourceName + " not found in classloader " + classLoader);
-      }
+      Validate.notNull(resourceName, "ResourceName must be specified");
+      Validate.notNull(classLoader, "ClassLoader must be specified");
+      Validate.notNull(
+            classLoader.getResource(resourceName), 
+            resourceName + " not found in classloader " + classLoader);
+
       this.resourceName = resourceName;
       this.classLoader = classLoader;
    }
@@ -82,6 +79,12 @@
    {
       return extractFileName(classLoader.getResource(resourceName));
    }
+   
+   @Override
+   public Path getDefaultPath()
+   {
+      return new BasePath(extractPath(resourceName));
+   }
 
    /**
     * Opens up the given resource as a stream.
@@ -102,8 +105,26 @@
       String fileName = url.getFile();
       if (fileName.indexOf('/') != -1)
       {
-         return fileName.substring(fileName.lastIndexOf('/') + 1, fileName.length());
+         return fileName.substring(
+               fileName.lastIndexOf('/') + 1, 
+               fileName.length());
       }
       return fileName;
    }
+   
+   /*
+    * Extract the file part of the given resourcename excluding file name.
+    * ie: /user/test/file.properties = /user/test/
+    */
+   private String extractPath(String resourceName)
+   {
+      if (resourceName.lastIndexOf('/') != -1)
+      {
+         return resourceName.substring(
+                0, 
+                resourceName.lastIndexOf('/'));
+      }
+      return resourceName;
+   }
+
 }
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/FileResource.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/FileResource.java	(revision 3449)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/FileResource.java	(working copy)
@@ -21,7 +21,10 @@
 import java.io.FileNotFoundException;
 import java.io.InputStream;
 
-import org.jboss.declarchive.spi.Resource;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.impl.base.Validate;
+import org.jboss.declarchive.impl.base.path.BasePath;
 
 /**
  * Loads any File.
@@ -43,10 +46,7 @@
    public FileResource(File file)
    {
       // Precondition check
-      if (file == null)
-      {
-         throw new IllegalArgumentException("File must be specified");
-      }
+      Validate.notNull(file, "File must be specified");
       if (!file.exists())
       {
          throw new IllegalArgumentException("File must exist: " + file.getAbsolutePath());
@@ -62,6 +62,12 @@
    {
       return file.getName();
    }
+   
+   @Override
+   public Path getDefaultPath()
+   {
+      return new BasePath(file.getParentFile().getPath());
+   }
 
    /**
     * Opens a new FileInputStream for the given File.
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/URLResource.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/URLResource.java	(revision 3449)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/URLResource.java	(working copy)
@@ -19,10 +19,13 @@
 import java.io.InputStream;
 import java.net.URL;
 
-import org.jboss.declarchive.spi.Resource;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.impl.base.Validate;
+import org.jboss.declarchive.impl.base.path.BasePath;
 
 /**
- * Loads the content of any URL supported by the runtime.
+ * Loads the content of any <code>URL</code> supported by the runtime.
  * 
  * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
  *
@@ -32,23 +35,20 @@
    private URL url;
 
    /**
-    * Create a new resource with a URL source.
+    * Create a new resource with a <code>URL</code> source.
     * 
     * @param url A valid URL
-    * @throws IllegalArgumentException URL can not be null
+    * @throws IllegalArgumentException <Code>URL</code> can not be null
     */
    public URLResource(URL url)
    {
       // Precondition check
-      if (url == null)
-      {
-         throw new IllegalArgumentException("URL must be specified");
-      }
+      Validate.notNull(url, "URL must be specified");
       this.url = url;
    }
 
    /**
-    * Get the default name using URL.getFile().
+    * Get the default name using <code>URL.getFile()</code>.
     */
    @Override
    public String getDefaultName()
@@ -56,8 +56,14 @@
       return extractFileName(url);
    }
 
+   @Override
+   public Path getDefaultPath()
+   {
+      return new BasePath("/");
+   }
+   
    /**
-    * Open the URL stream.
+    * Open the <code>URL</code> stream.
     * 
     * @return A open stream with the content of the URL
     */
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/ClassResource.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/ClassResource.java	(revision 3449)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/resource/ClassResource.java	(working copy)
@@ -18,7 +18,10 @@
 
 import java.io.InputStream;
 
-import org.jboss.declarchive.spi.Resource;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.impl.base.Validate;
+import org.jboss.declarchive.impl.base.path.BasePath;
 
 /**
  * Loads the given class using the class's ClassLoader.
@@ -54,10 +57,7 @@
    public ClassResource(Class<?> clazz)
    {
       // Precondition check
-      if (clazz == null)
-      {
-         throw new IllegalArgumentException("Class must be specified");
-      }
+      Validate.notNull(clazz, "Class must be specified");
       this.clazz = clazz;
    }
 
@@ -67,8 +67,14 @@
    @Override
    public String getDefaultName()
    {
-      return getResourceNameOfClass(clazz);
+      return getNameOfClass(clazz);
    }
+   
+   @Override
+   public Path getDefaultPath()
+   {
+      return new BasePath(getPathOfClass(clazz));
+   }
 
    /**
     * Converts the Class name into a Resource URL and uses the 
@@ -96,4 +102,30 @@
       // Return 
       return resourceName;
    }
+
+   /**
+    * Returns the path of the class
+    * 
+    * @param clazz The class
+    * @throws IllegalArgumentException If the class was not specified
+    */
+   private String getPathOfClass(final Class<?> clazz) throws IllegalArgumentException
+   {
+      // Build the name
+      final String fqn = clazz.getPackage().getName();
+      final String pathName = fqn.replace(DELIMITER_CLASS_NAME_PATH, DELIMITER_RESOURCE_PATH);
+
+      // Return 
+      return pathName;
+   }
+   
+   private String getNameOfClass(final Class<?> clazz) throws IllegalArgumentException
+   {
+      // Build the name
+      final String fqn = clazz.getSimpleName();
+      final String className = fqn + EXTENSION_CLASS;
+
+      // Return 
+      return className;
+   }
 }
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/URLPackageScanner.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/URLPackageScanner.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/URLPackageScanner.java	(revision 0)
@@ -0,0 +1,175 @@
+/*
+ * 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.declarchive.impl.base;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLDecoder;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+/**
+ * Implementation of scanner which can scan a {@link URLClassLoader}
+ *
+ * @author Thomas Heute
+ * @author Gavin King
+ * @author Norman Richards
+ * @author Pete Muir
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ */
+public class URLPackageScanner
+{
+
+   private static final Logger log = Logger.getLogger(URLPackageScanner.class.getName());
+
+   private final String packageName;
+
+   private final String packageNamePath;
+
+   private final boolean addRecursively;
+
+   private final ClassLoader classLoader;
+   
+   private final Set<Class<?>> classes = new HashSet<Class<?>>();
+
+   public URLPackageScanner(Package pkg, boolean addRecursively, ClassLoader classLoader)
+   {
+      this(pkg.getName(), addRecursively, classLoader);
+   }
+
+   public URLPackageScanner(String packageName, boolean addRecursively, ClassLoader classLoader)
+   {
+      Validate.notNull(packageName, "PackageName must be specified");
+      Validate.notNull(addRecursively, "AddRecursively must be specified");
+      Validate.notNull(classLoader, "ClassLoader must be specified");
+      
+      this.packageName = packageName;
+      this.packageNamePath = packageName.replace(".", "/");
+      this.addRecursively = addRecursively;
+      this.classLoader = classLoader;
+   }
+
+   private void scanPackage()
+   {
+      try
+      {
+         Set<String> paths = new HashSet<String>();
+
+         for (URL url : loadResources(packageNamePath))
+         {
+            String urlPath = url.getFile();
+            urlPath = URLDecoder.decode(urlPath, "UTF-8");
+            if (urlPath.startsWith("file:"))
+            {
+               urlPath = urlPath.substring(5);
+            }
+            if (urlPath.indexOf('!') > 0)
+            {
+               urlPath = urlPath.substring(0, urlPath.indexOf('!'));
+            }
+            paths.add(urlPath);
+         }
+         handle(paths);
+      }
+      catch (IOException ioe)
+      {
+         log.log(Level.WARNING, "could not read: " + packageName, ioe);
+      }
+      catch (ClassNotFoundException ioe)
+      {
+         log.log(Level.WARNING, "Class coud not be loaded in package: " + packageName, ioe);
+      }
+   }
+
+   private void handleArchiveByFile(File file) throws IOException, ClassNotFoundException
+   {
+      try
+      {
+         log.fine("archive: " + file);
+         ZipFile zip = new ZipFile(file);
+         Enumeration<? extends ZipEntry> entries = zip.entries();
+         while (entries.hasMoreElements())
+         {
+            ZipEntry entry = entries.nextElement();
+            String name = entry.getName();
+            if (name.startsWith(packageNamePath) && name.endsWith(".class")
+                  && (addRecursively || !name.substring(packageNamePath.length() + 1).contains("/")))
+            {
+               String className = name.replace("/", ".").replace(".class", "");
+               classes.add(classLoader.loadClass(className));
+            }
+         }
+      }
+      catch (ZipException e)
+      {
+         throw new RuntimeException("Error handling file " + file, e);
+      }
+   }
+
+   private void handle(Set<String> paths) throws IOException, ClassNotFoundException
+   {
+      for (String urlPath : paths)
+      {
+         log.fine("scanning: " + urlPath);
+         File file = new File(urlPath);
+         if (file.isDirectory())
+         {
+            handle(file, packageName);
+         }
+         else
+         {
+            handleArchiveByFile(file);
+         }
+      }
+   }
+
+   private void handle(File file, String packageName) throws ClassNotFoundException
+   {
+      for (File child : file.listFiles())
+      {
+         if (!child.isDirectory() && child.getName().endsWith(".class"))
+         {
+            classes.add(classLoader.loadClass(packageName + "." + child.getName().substring(0, child.getName().lastIndexOf(".class"))));
+         }
+         else if (child.isDirectory() && addRecursively)
+         {
+            handle(child, packageName + "." + child.getName());
+         }
+      }
+   }
+
+   public List<URL> loadResources(String name) throws IOException
+   {
+      return Collections.list(classLoader.getResources(name));
+   }
+
+   public Set<Class<?>> getClasses()
+   {
+      scanPackage();
+      return classes;
+   }
+}
\ No newline at end of file
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/ArchiveBaseSupport.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/ArchiveBaseSupport.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/ArchiveBaseSupport.java	(revision 0)
@@ -0,0 +1,322 @@
+/*
+ * 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.declarchive.impl.base;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.api.container.ClassContainer;
+import org.jboss.declarchive.api.container.ManifestContainer;
+import org.jboss.declarchive.api.container.ResourceContainer;
+import org.jboss.declarchive.impl.base.path.RelativePath;
+import org.jboss.declarchive.impl.base.resource.ClassResource;
+import org.jboss.declarchive.impl.base.resource.ClassloaderResource;
+
+/**
+ * ArchiveBaseSupport
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ * @param <T>
+ */
+public abstract class ArchiveBaseSupport<T extends Archive<T>> 
+   implements Archive<T>, ManifestContainer<T>, ResourceContainer<T>, ClassContainer<T>
+{
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+   
+   private static final Logger log = Logger.getLogger(ArchiveBaseSupport.class.getName());
+   
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   private final Archive<?> archive;
+   
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   protected ArchiveBaseSupport(Archive<?> archive) 
+   {
+      Validate.notNull(archive, "Archive should be specified");
+      this.archive = archive;
+   }
+   
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations - Archive Delegation --------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#add(org.jboss.declarchive.api.Resource[])
+    */
+   @Override
+   public T add(Resource... resources)
+   {
+      archive.add(resources);
+      return castThis();
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#add(org.jboss.declarchive.api.Path, org.jboss.declarchive.api.Resource[])
+    */
+   @Override
+   public T add(Path path, Resource... resources)
+   {
+      archive.add(path, resources);
+      return castThis();
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#add(org.jboss.declarchive.api.Path, java.lang.String, org.jboss.declarchive.api.Resource)
+    */
+   @Override
+   public T add(Path path, String name, Resource resource)
+   {
+      archive.add(path, name, resource);
+      return castThis();
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#add(java.lang.String, org.jboss.declarchive.api.Resource)
+    */
+   @Override
+   public T add(String name, Resource resource)
+   {
+      archive.add(name, resource);
+      return castThis();
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#contains(org.jboss.declarchive.api.Path)
+    */
+   @Override
+   public boolean contains(Path path)
+   {
+      return archive.contains(path);
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#delete(org.jboss.declarchive.api.Path)
+    */
+   @Override
+   public boolean delete(Path path)
+   {
+      return archive.delete(path);
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#get(org.jboss.declarchive.api.Path)
+    */
+   @Override
+   public Resource get(Path path)
+   {
+      return archive.get(path);
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#getContent()
+    */
+   @Override
+   public Map<Path, Resource> getContent()
+   {
+      return archive.getContent();
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#getName()
+    */
+   @Override
+   public String getName()
+   {
+      return archive.getName();
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.Archive#toString(boolean)
+    */
+   @Override
+   public String toString(boolean verbose)
+   {
+      return archive.toString(verbose);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations - ManifestContainer ---------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Should be implemented to set the path for Manifest related
+    * resources. 
+    * 
+    * @return Base Path for the ManifestContainer resources
+    */
+   protected abstract Path getManinfestPath();
+   
+   @Override
+   public final T setManifest(String resourceName)
+   {
+      Validate.notNull(resourceName, "ResourceName should be specified");
+      return add(getManinfestPath(), "MANIFEST.MF", new ClassloaderResource(resourceName));
+   }
+   
+   @Override
+   public final T addManifestResource(String resourceName)
+   {
+      Validate.notNull(resourceName, "ResourceName should be specified");
+
+      Resource resource = new ClassloaderResource(resourceName);
+      Path location = new RelativePath(getManinfestPath(), resource.getDefaultPath()); 
+      return add(location, resource);
+   }
+   
+   @Override
+   public final T addManifestResource(String resourceName, String newName)
+   {
+      Validate.notNull(resourceName, "ResourceName should be specified");
+      Validate.notNull(newName, "NewName should be specified");
+      
+      Resource resource = new ClassloaderResource(resourceName);
+      Path location = new RelativePath(getManinfestPath(), resource.getDefaultPath()); 
+      return add(location, newName, resource);
+   }
+   
+   @Override
+   public T addManifestResource(String resourceName, String newName, String path)
+   {
+      Validate.notNull(resourceName, "ResourceName should be specified");
+      Validate.notNull(newName, "NewName should be specified");
+      Validate.notNull(newName, "Path should be specified");
+      
+      Resource resource = new ClassloaderResource(resourceName);
+      Path location = new RelativePath(getManinfestPath(), path); 
+      return add(location, newName, resource);
+   }
+   
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations - ResourceContainer ---------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Should be implemented to set the path for Resource related
+    * resources. 
+    * 
+    * @return Base Path for the ResourceContainer resources
+    */
+   protected abstract Path getResourcePath();
+   
+   @Override
+   public final T addResource(String resourceName) throws IllegalArgumentException
+   {
+      Validate.notNull(resourceName, "ResourceName should be specified");
+      
+      Resource resource = new ClassloaderResource(resourceName);
+      Path location = new RelativePath(getResourcePath(), resource.getDefaultPath());
+      return add(location, resource);
+   }   
+   
+   @Override
+   public final T addResource(String resourceName, String newName) throws IllegalArgumentException 
+   {
+      Validate.notNull(resourceName, "ResourceName should be specified");
+      Validate.notNull(newName, "NewName should be specified");
+      
+      Resource resource = new ClassloaderResource(resourceName);
+      Path location = new RelativePath(getResourcePath(), resource.getDefaultPath());
+      return add(location, newName, resource);
+   };
+   
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations - ClassContainer ------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Should be implemented to set the path for Class related
+    * resources. 
+    * 
+    * @return Base Path for the ClassContainer resources
+    */
+   protected abstract Path getClassesPath();
+
+   @Override
+   public T addClass(Class<?> clazz) throws IllegalArgumentException
+   {
+      Validate.notNull(clazz, "Clazz must be specified");
+      return addClasses(clazz);
+   }
+   
+   public T addClasses(Class<?>... classes) throws IllegalArgumentException 
+   {
+      Validate.notNull(classes, "Classes must be specified");
+      
+      for(Class<?> clazz : classes) 
+      {
+         Resource resource = new ClassResource(clazz);
+         Path location = new RelativePath(getClassesPath(), resource.getDefaultPath());
+         add(location, resource);
+      }
+      return castThis();
+   };
+   
+   @Override
+   public T addPackages(Package... packages) throws IllegalArgumentException
+   {
+      Validate.notNull(packages, "Packages must be specified");
+      
+      for(Package pack : packages) 
+      {
+         URLPackageScanner scanner = new URLPackageScanner(
+               pack, false, Thread.currentThread().getContextClassLoader());
+         Set<Class<?>> classes = scanner.getClasses(); 
+         for(Class<?> clazz : classes) 
+         {
+            Resource resource = new ClassResource(clazz);
+            Path location = new RelativePath(getClassesPath(), resource.getDefaultPath());
+            add(location, resource);
+         }
+      }
+      return castThis();
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   protected T castThis() 
+   {
+      return getActualClass().cast(this);
+   }
+   
+   protected Class<T> getActualClass() 
+   {
+      Type superClassType = this.getClass().getGenericSuperclass();
+      if(superClassType instanceof ParameterizedType) {
+         ParameterizedType paramType = (ParameterizedType)superClassType;
+         for(Type type  : paramType.getActualTypeArguments()) {
+            return (Class<T>)type;
+         }
+      }
+      throw new IllegalStateException("Could not determine actual archive type, please override getActualClass() in " + this.getClass());
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/Validate.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/Validate.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/Validate.java	(revision 0)
@@ -0,0 +1,45 @@
+/*
+ * 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.declarchive.impl.base;
+
+/**
+ * Validator
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class Validate
+{
+   private Validate()
+   {
+   }
+
+   /**
+    * Checks that object is not null, throws exception if it is.
+    * 
+    * @param obj The object to check
+    * @param message The exception message
+    * @throws IllegalArgumentException Thrown if obj is null 
+    */
+   public static void notNull(Object obj, String message) throws IllegalArgumentException
+   {
+      if (obj == null)
+      {
+         throw new IllegalArgumentException(message);
+      }
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/ArchiveBase.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/ArchiveBase.java	(revision 3449)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/ArchiveBase.java	(working copy)
@@ -25,6 +25,9 @@
 import java.util.logging.Logger;
 
 import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.api.container.ResourceContainer;
 
 /**
  * ArchiveBase
@@ -34,7 +37,7 @@
  * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
  * @version $Revision: $
  */
-public abstract class ArchiveBase<T extends Archive<?>> implements Archive<T>
+public abstract class ArchiveBase<T extends Archive<T>> implements Archive<T>, ResourceContainer<T>
 {
 
    //-------------------------------------------------------------------------------------||
@@ -260,6 +263,26 @@
       return this.covarientReturn();
    }
 
+   /**
+    * @see org.jboss.declarchive.api.container.ResourceContainer#addResource(java.lang.String, java.lang.String)
+    */
+   @Override
+   public T addResource(final String name, final String locationWithinContainer) throws IllegalArgumentException
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   /**
+    * @see org.jboss.declarchive.api.Archive#addResource(org.jboss.declarchive.api.Resource, org.jboss.declarchive.api.Path)
+    */
+   @Override
+   public T addResource(final Resource resource, final Path path) throws IllegalArgumentException
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
    //-------------------------------------------------------------------------------------||
    // Contracts --------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/jar/WebArchiveImpl.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/jar/WebArchiveImpl.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/jar/WebArchiveImpl.java	(revision 0)
@@ -0,0 +1,113 @@
+package org.jboss.declarchive.impl.base.jar;
+
+import java.util.logging.Logger;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.jar.WebArchive;
+import org.jboss.declarchive.impl.base.ArchiveBaseSupport;
+import org.jboss.declarchive.impl.base.path.BasePath;
+import org.jboss.declarchive.impl.base.path.RelativePath;
+import org.jboss.declarchive.impl.base.resource.ClassloaderResource;
+
+public class WebArchiveImpl extends ArchiveBaseSupport<WebArchive> implements WebArchive
+{
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(WebArchiveImpl.class.getName());
+
+   /**
+    * Path to the web resource inside of the Archive.
+    */
+   private static final Path PATH_WEB = new BasePath("WEB-INF"); 
+
+   /**
+    * Path to the manifest resources inside of the Archive.
+    */
+   private static final Path PATH_MANIFEST = new RelativePath(PATH_WEB, "META-INF"); 
+   
+   /**
+    * Path to the class resources inside of the Archive.
+    */
+   private static final Path PATH_CLASSES = new RelativePath(PATH_WEB, "classes");
+   
+   /**
+    * Path to the library resources inside of the Archive.
+    */
+   private static final Path PATH_LIBRARY = new RelativePath(PATH_WEB, "lib");
+
+   /**
+    * Path to the library resources inside of the Archive.
+    */
+   private static final Path PATH_RESOURCE = new BasePath("/");
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Constructor
+    * 
+    * @param The underlying archive storage implementation
+    * to which the convenience methods of this archive
+    * will delegate
+    * @throws IllegalArgumentException If the delegate is not specified 
+    */
+   public WebArchiveImpl(final Archive<?> delegate)
+   {
+      super(delegate);
+   }
+   
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.impl.base.ArchiveBaseSupport#getManinfestPath()
+    */
+   @Override
+   protected Path getManinfestPath()
+   {
+      return PATH_MANIFEST;
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.impl.base.ArchiveBaseSupport#getResourcePath()
+    */
+   @Override
+   protected Path getResourcePath()
+   {
+      return PATH_RESOURCE;
+   }
+   
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.impl.base.ArchiveBaseSupport#getClassesPath()
+    */
+   @Override
+   protected Path getClassesPath()
+   {
+      return PATH_CLASSES;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations - WebContainer      ---------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /* (non-Javadoc)
+    * @see org.jboss.declarchive.api.container.WebContainer#setWebXML(java.lang.String)
+    */
+   @Override
+   public WebArchive setWebXML(String resourceName)
+   {
+      return add(PATH_WEB, "web.xml", new ClassloaderResource(resourceName));
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/jar/JavaArchiveImpl.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/jar/JavaArchiveImpl.java	(revision 3449)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/jar/JavaArchiveImpl.java	(working copy)
@@ -16,24 +16,24 @@
  */
 package org.jboss.declarchive.impl.base.jar;
 
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.util.logging.Logger;
 
 import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.Path;
 import org.jboss.declarchive.api.jar.JavaArchive;
+import org.jboss.declarchive.impl.base.ArchiveBaseSupport;
+import org.jboss.declarchive.impl.base.path.BasePath;
 
 /**
  * JavaArchiveImpl
  * 
- * Implementation of an archive with JAR-specific 
- * support.
+ * Implementation of an archive with JAR-specific support.
  *
  * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
  * @version $Revision: $
  */
-public final class JavaArchiveImpl implements JavaArchive
+public final class JavaArchiveImpl extends ArchiveBaseSupport<JavaArchive> implements JavaArchive
 {
 
    //-------------------------------------------------------------------------------------||
@@ -46,19 +46,24 @@
    private static final Logger log = Logger.getLogger(JavaArchiveImpl.class.getName());
 
    /**
-    * Path to the manifest inside of a JAR
+    * Path to the manifest inside of the Archive.
     */
-   private static final String PATH_MANIFEST = "META-INF/MANIFEST.MF";
+   private static final Path PATH_MANIFEST = new BasePath("META-INF");
 
+   /**
+    * Path to the manifest inside of the Archive.
+    */
+   private static final Path PATH_RESOURCE = new BasePath("/");
+   
+   /**
+    * Path to the classes inside of the Archive.
+    */
+   private static final Path PATH_CLASSES = new BasePath("/");
+
    //-------------------------------------------------------------------------------------||
    // Instance Members -------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
 
-   /**
-    * Underlying delegate
-    */
-   private final Archive<?> delegate;
-
    //-------------------------------------------------------------------------------------||
    // Constructor ------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
@@ -73,172 +78,28 @@
     */
    public JavaArchiveImpl(final Archive<?> delegate)
    {
-      // Precondition check
-      if (delegate == null)
-      {
-         throw new IllegalArgumentException("delegate must be specified");
-      }
-
-      // Set properties
-      this.delegate = delegate;
-
-      // Log
-      log.fine("Created new Java Archive from backing delegate: " + delegate);
+      super(delegate);
    }
 
    //-------------------------------------------------------------------------------------||
    // Required Implementations -----------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
 
-   /**
-    * @param clazz
-    * @return
-    * @throws IllegalArgumentException
-    * @see org.jboss.declarchive.api.Archive#addClass(java.lang.Class)
-    */
-   public JavaArchive addClass(final Class<?> clazz) throws IllegalArgumentException
-   {
-      delegate.addClass(clazz);
-      return this;
-   }
-
-   /**
-    * @param classes
-    * @return
-    * @throws IllegalArgumentException
-    * @see org.jboss.declarchive.api.Archive#addClasses(java.lang.Class<?>[])
-    */
-   public JavaArchive addClasses(final Class<?>... classes) throws IllegalArgumentException
-   {
-      delegate.addClasses(classes);
-      return this;
-   }
-
-   /**
-    * @param name
-    * @param cl
-    * @return
-    * @throws IllegalArgumentException
-    * @see org.jboss.declarchive.api.Archive#addResource(java.lang.String, java.lang.ClassLoader)
-    */
-   public JavaArchive addResource(final String name, final ClassLoader cl) throws IllegalArgumentException
-   {
-      delegate.addResource(name, cl);
-      return this;
-   }
-
-   /**
-    * @param name
-    * @return
-    * @throws IllegalArgumentException
-    * @see org.jboss.declarchive.api.Archive#addResource(java.lang.String)
-    */
-   public JavaArchive addResource(final String name) throws IllegalArgumentException
-   {
-      delegate.addResource(name);
-      return this;
-   }
-
-   /**
-    * @param location
-    * @param newPath
-    * @return
-    * @throws IllegalArgumentException
-    * @see org.jboss.declarchive.api.Archive#addResource(java.net.URL, java.lang.String)
-    */
-   public JavaArchive addResource(final URL location, final String newPath) throws IllegalArgumentException
-   {
-      delegate.addResource(location, newPath);
-      return this;
-   }
-
-   /**
-    * @param location
-    * @return
-    * @throws IllegalArgumentException
-    * @see org.jboss.declarchive.api.Archive#addResource(java.net.URL)
-    */
-   public JavaArchive addResource(final URL location) throws IllegalArgumentException
-   {
-      delegate.addResource(location);
-      return this;
-   }
-
-   /**
-    * @param verbose
-    * @return
-    * @see org.jboss.declarchive.api.Archive#toString(boolean)
-    */
-   public String toString(final boolean verbose)
-   {
-      return "Java Archive (JAR): " + delegate.toString(verbose);
-   }
-
-   /**
-    * @throws MalformedURLException 
-    * @see org.jboss.declarchive.api.jar.JavaArchive#addManifest(java.io.File)
-    */
    @Override
-   public JavaArchive addManifest(final File manifestFile) throws IllegalArgumentException
+   protected Path getManinfestPath()
    {
-      // Precondition checks
-      if (manifestFile == null)
-      {
-         throw new IllegalArgumentException("Manifest file must be specified");
-      }
-      if (!manifestFile.exists())
-      {
-         throw new IllegalArgumentException("Specified manifest file does not exist: " + manifestFile.getAbsolutePath());
-      }
-
-      // Get a URL
-      final URL url;
-      try
-      {
-         url = manifestFile.toURI().toURL();
-      }
-      catch (final MalformedURLException murle)
-      {
-         throw new RuntimeException("Unexpected error in obtaining URL from File reference: "
-               + manifestFile.getAbsolutePath(), murle);
-      }
-
-      // Return
-      return this.addManifest(url);
+      return PATH_MANIFEST;
    }
-
-   /**
-    * @see org.jboss.declarchive.api.jar.JavaArchive#addManifest(java.lang.String)
-    */
+   
    @Override
-   public JavaArchive addManifest(final String manifestFilePath) throws IllegalArgumentException
+   protected Path getResourcePath()
    {
-      // Precondition check
-      if (manifestFilePath == null || manifestFilePath.length() == 0)
-      {
-         throw new IllegalArgumentException("path must be specified");
-      }
-
-      // Get a File
-      final File file = new File(manifestFilePath);
-
-      // Return
-      return this.addManifest(file);
+      return PATH_RESOURCE;
    }
-
-   /**
-    * @see org.jboss.declarchive.api.jar.JavaArchive#addManifest(java.net.URL)
-    */
+   
    @Override
-   public JavaArchive addManifest(final URL manifestFile) throws IllegalArgumentException
+   protected Path getClassesPath()
    {
-      // Precondition checks
-      if (manifestFile == null)
-      {
-         throw new IllegalArgumentException("Manifest file must be specified");
-      }
-
-      // Add the resource and return
-      return this.addResource(manifestFile, PATH_MANIFEST);
+      return PATH_CLASSES;
    }
 }
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/path/ResourcePath.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/path/ResourcePath.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/path/ResourcePath.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * 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.declarchive.impl.base.path;
+
+import org.jboss.declarchive.api.Path;
+
+public class ResourcePath extends PrefixPath
+{
+   private Path basePath;
+
+   public ResourcePath(Path basePath, String resourceName)
+   {
+      super(resourceName);
+      this.basePath = basePath;
+   }
+   
+   @Override
+   String getPrefix()
+   {
+      return basePath.get();
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/path/BasePath.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/path/BasePath.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/path/BasePath.java	(revision 0)
@@ -0,0 +1,68 @@
+/*
+ * 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.declarchive.impl.base.path;
+
+import org.jboss.declarchive.api.Path;
+
+/**
+ * BasePath
+ * 
+ * A {@link Path} which has no namespace and is relative to the
+ * root.
+ *
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class BasePath extends PrefixPath
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   private static final String PREFIX = null;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new Path representing the specified
+    * context.  Null or blank may be used to 
+    * denote the root.
+    * 
+    * @param context
+    */
+   public BasePath(final String context)
+   {
+      super(PathUtil.fixBasePath(context));
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * @see org.jboss.declarchive.impl.base.path.PrefixPath#getPrefix()
+    */
+   @Override
+   String getPrefix()
+   {
+      return PREFIX;
+   }
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/path/RelativePath.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/path/RelativePath.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/path/RelativePath.java	(revision 0)
@@ -0,0 +1,54 @@
+/*
+ * 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.declarchive.impl.base.path;
+
+import org.jboss.declarchive.api.Path;
+
+/**
+ * RelativePath
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class RelativePath extends PrefixPath
+{
+   private Path basePath;
+   
+   public RelativePath(Path basePath, Path context)
+   {
+      this(basePath, context.get());
+   }
+   
+   public RelativePath(Path basePath, String context)
+   {
+      this(basePath.get(), context);
+   }
+   
+   public RelativePath(String basePath, String context) 
+   {
+      super(PathUtil.fixRelativePath(context));
+      this.basePath = new BasePath(basePath);
+   }
+   
+   @Override
+   String getPrefix()
+   {
+      return basePath.get();
+   }
+   
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/path/PrefixPath.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/path/PrefixPath.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/path/PrefixPath.java	(revision 0)
@@ -0,0 +1,95 @@
+/*
+ * 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.declarchive.impl.base.path;
+
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.impl.base.Validate;
+
+/**
+ * PrefixPath
+ * 
+ * A Path which may be optionally prefixed with some common
+ * namespace
+ *
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+abstract class PrefixPath implements Path
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Empty String
+    */
+   private static final String EMPTY_STRING = "";
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * The context which this path represents
+    */
+   private final String context;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new Path with the specified Prefix and context
+    * 
+    * @param prefix The prefix to prepend to every context returned
+    * in {@link PrefixPath#get()}.  May be null or blank
+    * @param context The context which this path represents.  Null or 
+    * blank represents the root.
+    */
+   PrefixPath(final String context)
+   {
+      Validate.notNull(context, "Context must be specified");
+      this.context = context;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * @see org.jboss.declarchive.api.Path#get()
+    */
+   @Override
+   public String get()
+   {
+      // Return the prefix plus the context
+      final String prefix = this.getPrefix();
+      final String prefixToUse = prefix == null ? EMPTY_STRING : prefix;
+      final String resolvedContext = prefixToUse + context;
+      return resolvedContext;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Obtains the prefix to prepend to all path contexts
+    */
+   abstract String getPrefix();
+}
Index: impl-base/src/main/java/org/jboss/declarchive/impl/base/path/PathUtil.java
===================================================================
--- impl-base/src/main/java/org/jboss/declarchive/impl/base/path/PathUtil.java	(revision 0)
+++ impl-base/src/main/java/org/jboss/declarchive/impl/base/path/PathUtil.java	(revision 0)
@@ -0,0 +1,76 @@
+/*
+ * 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.declarchive.impl.base.path;
+
+/**
+ * PathUtil
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class PathUtil
+{
+
+   private PathUtil() {}
+   
+   public static String fixRelativePath(String path) 
+   {
+      if(path == null) 
+      {
+         return path;
+      }
+      String removedPrefix = removePrefix(path);
+      String addedPostfix = addPostfix(removedPrefix);
+
+      return addedPostfix;
+   }
+   
+   public static String fixBasePath(String path) 
+   {
+      if(path == null) 
+      {
+         return path;
+      }
+      String prefixedPath = addPrefix(path);
+      String prePostfixedPath = addPostfix(prefixedPath);
+      
+      return prePostfixedPath;
+   }
+
+   private static String removePrefix(String path) {
+      if(path.charAt(0) == '/') {
+         return path.substring(1);
+      }
+      return path;
+   }
+   
+   private static String addPostfix(String path) {
+      if(path.charAt(path.length()-1) != '/') {
+         return path + '/';
+      }
+      return path;
+   }
+
+   private static String addPrefix(String path) {
+      if(path.charAt(0) != '/') {
+         return '/' + path;
+      }
+      return path;
+   }
+   
+}
Index: api/src/main/java/org/jboss/declarchive/api/Archive.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/Archive.java	(revision 3449)
+++ api/src/main/java/org/jboss/declarchive/api/Archive.java	(working copy)
@@ -16,7 +16,7 @@
  */
 package org.jboss.declarchive.api;
 
-import java.net.URL;
+import java.util.Map;
 
 /**
  * Archive
@@ -25,78 +25,34 @@
  * be constructed declaratively / programmatically.
  *
  * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
  * @version $Revision: $
  */
-public interface Archive<T extends Archive<?>>
+public interface Archive<T extends Archive<T>>
 {
    //-------------------------------------------------------------------------------------||
    // Contracts --------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
 
-   /**
-    * Adds the specified Class to the archive
-    * 
-    * @param The class to add
-    * @return This virtual deployment
-    * @throws IllegalArgumentException If no class was specified
-    */
-   T addClass(Class<?> clazz) throws IllegalArgumentException;
+   String getName();
+   
+   T add(Resource... resources);
 
-   /**
-    * Adds the specified Classes to the archive.  
-    * 
-    * @param classes
-    * @return This virtual deployment
-    * @throws IllegalArgumentException If no classes were specified
-    */
-   T addClasses(Class<?>... classes) throws IllegalArgumentException;
+   T add(Path path, Resource... resources);
 
-   /**
-    * Adds the resource with the specified name to the 
-    * deployment.  The resource name must be visible to the ClassLoader
-    * of the archive
-    * 
-    * @param name
-    * @return
-    * @throws IllegalArgumentException If the name was not specified
-    */
-   T addResource(String name) throws IllegalArgumentException;
+   T add(Path path, String name, Resource resource);
+   
+   T add(String name, Resource resource);
+   
+   Resource get(Path path);
+   
+   boolean contains(Path path);
 
-   /**
-    * Adds the specified resource to the archive, using the specified ClassLoader
-    * to load the resource
-    * 
-    * @param name
-    * @param cl
-    * @return
-    * @throws IllegalArgumentException If either the name or ClassLoader is not specified
-    */
-   T addResource(String name, ClassLoader cl) throws IllegalArgumentException;
+   boolean delete(Path path);
+   
+   Map<Path, Resource> getContent();
 
    /**
-    * Adds the resource located at the specified URL to the archive.  The
-    * location within the archive will be equal to the path portion of the 
-    * specified URL.
-    * 
-    * @param location
-    * @return
-    * @throws IllegalArgumentException If the location is not specified
-    */
-   T addResource(URL location) throws IllegalArgumentException;
-
-   /**
-    * Adds the resource located at the specified URL to
-    * the archive at the specified path.
-    * 
-    * @param location
-    * @param newPath The new path to assign, or null if 
-    *   the path portion of the location should be used
-    * @return
-    * @throws IllegalArgumentException If the location is not specified 
-    */
-   T addResource(URL location, String newPath) throws IllegalArgumentException;
-
-   /**
     * Returns a multiline "ls -l"-equse output of the contents of
     * this deployment and (recursively) its children if the verbosity 
     * flag is set to "true".  Otherwise the no-arg version is invoked
Index: api/src/main/java/org/jboss/declarchive/api/container/WebContainer.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/container/WebContainer.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/container/WebContainer.java	(revision 0)
@@ -0,0 +1,36 @@
+/*
+ * 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.declarchive.api.container;
+
+import org.jboss.declarchive.api.Archive;
+
+/**
+ * WebContainer
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ * @param <T>
+ */
+public interface WebContainer<T extends Archive<T>>
+{
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   T setWebXML(String resourceName);
+}
Index: api/src/main/java/org/jboss/declarchive/api/container/LibraryContainer.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/container/LibraryContainer.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/container/LibraryContainer.java	(revision 0)
@@ -0,0 +1,36 @@
+/*
+ * 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.declarchive.api.container;
+
+import org.jboss.declarchive.api.Archive;
+
+/**
+ * LibraryContainer
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public interface LibraryContainer<T extends Archive<T>>
+{
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   T addLibrary(String resourceName);
+   T addLibrary(String resourceName, String newName);
+   T addLibrary(Archive<?> archive);
+}
Index: api/src/main/java/org/jboss/declarchive/api/container/ClassContainer.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/container/ClassContainer.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/container/ClassContainer.java	(revision 0)
@@ -0,0 +1,60 @@
+/*
+ * 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.declarchive.api.container;
+
+import org.jboss.declarchive.api.Archive;
+
+/**
+ * ClassContainer
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public interface ClassContainer<T extends Archive<T>>
+{
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Adds the specified Class to the archive
+    * 
+    * @param The class to add
+    * @return This virtual deployment
+    * @throws IllegalArgumentException If no class was specified
+    */
+   T addClass(Class<?> clazz) throws IllegalArgumentException;
+
+   /**
+    * Adds the specified Classes to the archive.  
+    * 
+    * @param classes
+    * @return This virtual archive
+    * @throws IllegalArgumentException If no classes were specified
+    */
+   T addClasses(Class<?>... classes) throws IllegalArgumentException;
+
+   
+   /**
+    * Adds a whole Package to the archive.
+    * 
+    * @param packages
+    * @return This virtual archive
+    * @throws IllegalArgumentException If no packages were specified
+    */
+   T addPackages(Package... packages) throws IllegalArgumentException;
+}
Index: api/src/main/java/org/jboss/declarchive/api/container/ManifestContainer.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/container/ManifestContainer.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/container/ManifestContainer.java	(revision 0)
@@ -0,0 +1,31 @@
+/*
+ * 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.declarchive.api.container;
+
+import org.jboss.declarchive.api.Archive;
+
+public interface ManifestContainer<T extends Archive<T>>
+{
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   T setManifest(String resourceName);
+   T addManifestResource(String resourceName);
+   T addManifestResource(String resourceName, String newName);
+   T addManifestResource(String resourceName, String newName, String path);
+}
Index: api/src/main/java/org/jboss/declarchive/api/container/ResourceContainer.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/container/ResourceContainer.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/container/ResourceContainer.java	(revision 0)
@@ -0,0 +1,111 @@
+/*
+ * 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.declarchive.api.container;
+
+import org.jboss.declarchive.api.Archive;
+
+/**
+ * ResourceContainer
+ * 
+ * Defines the contract for a component capable of storing 
+ * a series of ClassLoader resources
+ *
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public interface ResourceContainer<T extends Archive<T>>
+{
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Adds the resource with the specified name
+    * to the container, returning the container itself.
+    * The ClassLoader used to obtain the resource is up to
+    * the implementation.  The resource will be placed into 
+    * the Container under the same context from which it was retrieved.
+    * For instance a name of "META-INF/resource.xml" will be placed
+    * at the same location within the Container.
+    * 
+    * @param resourceName Name of the ClassLoader resource to add
+    * @throws IllegalArgumentException If the name is not specified
+    */
+   T addResource(String resourceName) throws IllegalArgumentException;
+
+   /**
+    * Adds the resource with the specified name
+    * to the container, returning the container itself.
+    * The ClassLoader used to obtain the resource is up to
+    * the implementation.  The resource will be placed into 
+    * the Container under the same context specified by
+    * "locationWithinContainer"
+    * 
+    * @param resourceName Name of the ClassLoader resource to add
+    * @param newName Context within the Container
+    *       under which to place the resource
+    * @throws IllegalArgumentException If the name or location is not specified
+    */
+   T addResource(String resourceName, String newName) throws IllegalArgumentException;
+
+   /**
+    * Adds the specified resource to the archive at the specified Path
+    * 
+    * @param resource
+    * @param path
+    * @return
+    * @throws IllegalArgumentException If either the resource or path is
+    * unspecified
+    */
+   //T addResource(Resource resource, Path path) throws IllegalArgumentException;
+
+   /**
+    * Adds the specified resource to the archive, using the specified ClassLoader
+    * to load the resource
+    * 
+    * @param name
+    * @param cl
+    * @return
+    * @throws IllegalArgumentException If either the name or ClassLoader is not specified
+    */
+   //T addResource(String name, ClassLoader cl) throws IllegalArgumentException;
+
+   /**
+    * Adds the resource located at the specified URL to the archive.  The
+    * location within the archive will be equal to the path portion of the 
+    * specified URL.
+    * 
+    * @param location
+    * @return
+    * @throws IllegalArgumentException If the location is not specified
+    */
+   //T addResource(URL location) throws IllegalArgumentException;
+
+   /**
+    * Adds the resource located at the specified URL to
+    * the archive at the specified path.
+    * 
+    * @param location
+    * @param newPath The new path to assign, or null if 
+    *   the path portion of the location should be used
+    * @return
+    * @throws IllegalArgumentException If the location is not specified 
+    */
+   //T addResource(URL location, String newPath) throws IllegalArgumentException;
+   
+}
Index: api/src/main/java/org/jboss/declarchive/api/Resource.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/Resource.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/Resource.java	(revision 0)
@@ -0,0 +1,56 @@
+/*
+ * 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.declarchive.api;
+
+import java.io.InputStream;
+
+/**
+ * Represents a Class, file, or any other collection
+ * of bytes stored under some context within an {@link Archive} 
+ * 
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ */
+public interface Resource
+{
+
+   /**
+    * Get the default name for this resource, which will 
+    * be the name under with the resource is placed into
+    * an archive unless explicitly specified otherwise.
+    * 
+    * @return A name for this Resource
+    */
+   String getDefaultName();
+
+   /**
+    * Get the default path for this resource, which will 
+    * be the context under with the resource is placed into
+    * an archive unless explicitly specified otherwise.
+    * 
+    * @return A path for this Resource
+    */
+   Path getDefaultPath();
+
+   /**
+    * Get a open stream for the resource content.
+    * The caller is responsible for closing the stream. 
+    * 
+    * @return A new open inputstream for each call.
+    */
+   InputStream getStream();
+}
Index: api/src/main/java/org/jboss/declarchive/api/ArchiveFactory.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/ArchiveFactory.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/ArchiveFactory.java	(revision 0)
@@ -0,0 +1,104 @@
+package org.jboss.declarchive.api;
+
+import java.lang.reflect.Constructor;
+import java.util.logging.Logger;
+
+public class ArchiveFactory
+{
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(ArchiveFactory.class.getName());
+
+   private static final Class<?>[] ARCHIVE_IMPL_CONSTRUCTOR_ARGUMENTS = new Class[]{String.class};
+   
+   private ArchiveFactory() {  }
+   
+   public static Archive createTmpArchive(String name) 
+   {
+      Class<? extends Archive> implClass = null;
+      try 
+      {
+         implClass = getClass("org.jboss.declarchive.impl.jdkfile.TempFileArchiveImpl")
+            .asSubclass(Archive.class);
+      } 
+      catch (ClassNotFoundException e) 
+      {
+         throw new RuntimeException(
+               "Declarative Archives implementation \"JDK File\" not in classpath", 
+               e);
+      }
+      return createArchive(
+            name, 
+            Archive.class, 
+            implClass);
+   }
+   
+   public static Archive createVirtualArchive(String name) 
+   {
+      Class<? extends Archive> implClass = null;
+      try 
+      {
+         implClass = getClass("org.jboss.declarchive.impl.vfs.MemoryArchiveImpl")
+            .asSubclass(Archive.class);
+      } 
+      catch (ClassNotFoundException e) 
+      {
+         throw new RuntimeException(
+               "Declarative Archives implementation \"Virtual File System\" not in classpath", 
+               e);
+      }
+      return createArchive(
+            name, 
+            Archive.class,
+            implClass);
+   }
+
+   public static <T extends Archive> T createArchive(final String name, final Class<T> archiveType, final Class<? extends T> archiveImpl) 
+   {
+      if(archiveType == null) {
+         throw new IllegalArgumentException("ArchiveType can not be null");
+      }
+      if(archiveImpl == null) {
+         throw new IllegalArgumentException("ArchiveImpl can not be null");
+      }
+      
+      Constructor<?> implConstructor = findConstructor(archiveImpl, ARCHIVE_IMPL_CONSTRUCTOR_ARGUMENTS); 
+      
+      Object archive = null;
+      try 
+      {
+         archive = implConstructor.newInstance(name);
+      } 
+      catch (Exception e) {
+         throw new RuntimeException("Error in creating new " + archiveImpl.getName(), e);
+      }
+      
+      return archiveType.cast(archive);
+   }
+   
+   private static Constructor<?> findConstructor(final Class<?> implClass, final Class<?>[] arguments) 
+   {
+      try 
+      {
+         return SecurityActions.getConstructor(implClass, arguments);
+      } 
+      catch (NoSuchMethodException e) 
+      {
+         throw new RuntimeException("Could not find constructor to be used in factory creation of a new "
+               + Archive.class.getSimpleName(), e);
+      }
+   }
+   
+   /**
+    * Obtains the class with the specified name from the TCCL
+    *  
+    * @param className
+    * @return
+    */
+   static Class<?> getClass(final String className) throws ClassNotFoundException
+   {
+      final ClassLoader cl = SecurityActions.getThreadContextClassLoader();
+      return Class.forName(className, false, cl);
+   }
+}
Index: api/src/main/java/org/jboss/declarchive/api/jar/WebArchive.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/jar/WebArchive.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/jar/WebArchive.java	(revision 0)
@@ -0,0 +1,31 @@
+/*
+ * 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.declarchive.api.jar;
+
+import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.container.ManifestContainer;
+import org.jboss.declarchive.api.container.WebContainer;
+
+/**
+ * WebArchive
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public interface WebArchive extends Archive<WebArchive>, ManifestContainer<WebArchive>, WebContainer<WebArchive>
+{
+}
Index: api/src/main/java/org/jboss/declarchive/api/jar/JavaArchive.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/jar/JavaArchive.java	(revision 3449)
+++ api/src/main/java/org/jboss/declarchive/api/jar/JavaArchive.java	(working copy)
@@ -16,56 +16,24 @@
  */
 package org.jboss.declarchive.api.jar;
 
-import java.io.File;
-import java.net.URL;
-
 import org.jboss.declarchive.api.Archive;
+import org.jboss.declarchive.api.container.ClassContainer;
+import org.jboss.declarchive.api.container.ManifestContainer;
+import org.jboss.declarchive.api.container.ResourceContainer;
 
 /**
  * JavaArchive
  * 
- * Traditional JAR (Java ARchive) structure.  Used in 
+ * Traditional JAR (Java Archive) structure.  Used in 
  * construction of libraries and applications.
  *
  * @see http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html
  * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a> 
  * @version $Revision: $
  */
-public interface JavaArchive extends Archive<JavaArchive>
+public interface JavaArchive extends Archive<JavaArchive>, 
+      ResourceContainer<JavaArchive>, ManifestContainer<JavaArchive>, ClassContainer<JavaArchive>
 {
 
-   //-------------------------------------------------------------------------------------||
-   // Contracts --------------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Adds the File with the specified path as the JAR Manifest.  This will
-    * be placed into the archive as <code>META-INF/MANIFEST.MF</code>
-    * 
-    * @param manifestFilePath The path to the file file to use as the JAR Manifest.
-    * @throws IllegalArgumentException If the path does not point to a valid file 
-    *       or was not specified
-    */
-   JavaArchive addManifest(String manifestFilePath) throws IllegalArgumentException;
-
-   /**
-    * Adds the specified File as the JAR Manifest.  This will
-    * be placed into the archive as <code>META-INF/MANIFEST.MF</code>
-    * 
-    * @param manifestFile The file to use as the JAR Manifest.
-    * @throws IllegalArgumentException If the file does not exist or
-    *       was not specified
-    */
-   JavaArchive addManifest(File manifestFile) throws IllegalArgumentException;
-
-   /**
-    * Adds the specified URL as the JAR Manifest.  This will
-    * be placed into the archive as <code>META-INF/MANIFEST.MF</code>
-    * 
-    * @param manifestFile The file to use as the JAR Manifest.
-    * @throws IllegalArgumentException If the URL could not be obtained or
-    *       was not specified
-    */
-   JavaArchive addManifest(URL manifestFile) throws IllegalArgumentException;
-
 }
Index: api/src/main/java/org/jboss/declarchive/api/Path.java
===================================================================
--- api/src/main/java/org/jboss/declarchive/api/Path.java	(revision 0)
+++ api/src/main/java/org/jboss/declarchive/api/Path.java	(revision 0)
@@ -0,0 +1,36 @@
+/*
+ * 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.declarchive.api;
+
+/**
+ * Path
+ * 
+ * Represents a target context within an {@link Archive} under
+ * which a {@link Resource} may be found.
+ *
+ * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public interface Path
+{
+   /**
+    * Obtains the context which this Path represents
+    * 
+    * @return
+    */
+   String get();
+}
Index: api/pom.xml
===================================================================
--- api/pom.xml	(revision 3449)
+++ api/pom.xml	(working copy)
@@ -33,6 +33,14 @@
   <!-- Dependencies -->
   <dependencies>
 
+    <!-- 
+    External Projects
+     -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>
Index: impl-vfs/src/main/java/org/jboss/declarchive/impl/vfs/VfsArchiveBaseSupport.java
===================================================================
--- impl-vfs/src/main/java/org/jboss/declarchive/impl/vfs/VfsArchiveBaseSupport.java	(revision 0)
+++ impl-vfs/src/main/java/org/jboss/declarchive/impl/vfs/VfsArchiveBaseSupport.java	(revision 0)
@@ -0,0 +1,205 @@
+/*
+ * 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.declarchive.impl.vfs;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.jboss.declarchive.api.Path;
+import org.jboss.declarchive.api.Resource;
+import org.jboss.declarchive.impl.base.Validate;
+import org.jboss.declarchive.impl.base.path.BasePath;
+import org.jboss.declarchive.impl.base.resource.URLResource;
+import org.jboss.declarchive.spi.vfs.VfsArchive;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.VirtualFileVisitor;
+import org.jboss.virtual.VisitorAttributes;
+
+/**
+ * VfsArchive
+ *
+ * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public abstract class VfsArchiveBaseSupport implements VfsArchive
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(VfsArchiveBaseSupport.class.getName());
+
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * The root of the deployment
+    */
+   private VirtualFile root;
+
+   /**
+    * The URL to the root deployment
+    */
+   private URL rootURL;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   public VfsArchiveBaseSupport(VirtualFile root, URL rootURL) 
+   {
+      Validate.notNull(root, "Root must be specified");
+      Validate.notNull(rootURL, "RootURL must be specified");
+      
+      this.root = root;
+      this.rootURL = rootURL;
+   }
+   
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations - Archive Delegation --------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   @Override
+   public String getName()
+   {
+      return root.getName();
+   }
+
+   @Override
+   public VfsArchive add(Path path, Resource... resources)
+   {
+      Validate.notNull(path, "Path must be specified");
+      Validate.notNull(resources, "Resources must be specified");
+      
+      for(Resource resource : resources) 
+      {
+         add(path, resource.getDefaultName(), resource);
+      }
+      return this;
+   }
+   
+   @Override
+   public VfsArchive add(Resource... resources)
+   {
+      Validate.notNull(resources, "Resources must be specified");
+      
+      for(Resource resource : resources) 
+      {
+         add(resource.getDefaultPath(), resource.getDefaultName(), resource);
+      }
+      return this;
+   }
+   
+   @Override
+   public VfsArchive add(String name, Resource resource)
+   {
+      return add(resource.getDefaultPath(), name, resource);
+   }
+   
+   @Override
+   public boolean contains(Path path)
+   {
+      try 
+      {
+         return root.getChild(path.get()).exists();   
+      }
+      catch (Exception e) 
+      {
+         throw new RuntimeException("Could not check archive", e);
+      }
+   }
+   
+   @Override
+   public boolean delete(Path path)
+   {
+      try 
+      {
+         return root.getChild(path.get()).delete();
+      } 
+      catch (Exception e) 
+      {
+         throw new RuntimeException("Could not delete resource", e);
+      }
+   }
+   
+   @Override
+   public Resource get(Path path)
+   {
+      try 
+      {
+         return new URLResource(root.getChild(path.get()).toURL());
+      } 
+      catch (Exception e) 
+      {
+         throw new RuntimeException("Could not get resource", e);
+      }
+   }
+   
+   @Override
+   public Map<Path, Resource> getContent()
+   {
+      final Map<Path, Resource> content = new HashMap<Path, Resource>();
+      try
+      {
+         root.visit(new VirtualFileVisitor()
+         {
+            @Override
+            public void visit(VirtualFile virtualFile)
+            {
+               try 
+               {
+                  content.put(new BasePath(""), new URLResource(virtualFile.toURL()));
+               } 
+               catch (Exception e) 
+               {
+                  throw new RuntimeException("Could not convert file to url: " + virtualFile, e);
+               }
+            }
+            @Override
+            public VisitorAttributes getAttributes()
+            {
+               return VisitorAttributes.RECURSE;
+            }
+         });
+      }
+      catch (Exception e) 
+      {
+         throw new RuntimeException("Could not get content", e);
+      }
+      return content;
+   }
+   
+   @Override
+   public String toString(boolean verbose)
+   {
+      return root.toString();
+   }
+   
+   @Override
+   public VirtualFile getRoot()
+   {
+      return root;
+   }
+}
