[jboss-cvs] JBossAS SVN: r96599 - in projects/embedded/trunk: api/src/main/java/org/jboss/embedded/api/server and 11 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Nov 19 17:43:55 EST 2009


Author: ALRubinger
Date: 2009-11-19 17:43:55 -0500 (Thu, 19 Nov 2009)
New Revision: 96599

Added:
   projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/Deployable.java
   projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableArchive.java
   projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableFile.java
   projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableUrl.java
   projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/UrlCopyUtil.java
   projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/deployable/
   projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/deployable/DeployableImplementationsTestCase.java
   projects/embedded/trunk/core/src/test/resources/file1
   projects/embedded/trunk/core/src/test/resources/file2
   projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/mc/
   projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/mc/StateReportingBean.java
   projects/embedded/trunk/testsuite/src/test/resources/mc/
   projects/embedded/trunk/testsuite/src/test/resources/mc/statereporter-jboss-beans.xml
Removed:
   projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/VfsVdfDeployableImpl.java
   projects/embedded/trunk/core/src/main/java/org/jboss/embedded/spi/
   projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/VfsVdfDeployableImplTestCase.java
Modified:
   projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/DeploymentException.java
   projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/server/JBossASEmbeddedServer.java
   projects/embedded/trunk/core/pom.xml
   projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/server/JBossASEmbeddedServerImpl.java
   projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/ServerTestCase.java
Log:
[EMB-68] Support deployment of File, URL, Deployable, and Archive

Added: projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/Deployable.java
===================================================================
--- projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/Deployable.java	                        (rev 0)
+++ projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/Deployable.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1,48 @@
+/*
+ * 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.embedded.api;
+
+import java.net.URL;
+
+import org.jboss.embedded.api.server.JBossASEmbeddedServer;
+
+/**
+ * Represents an entity capable of being deployed into the 
+ * {@link JBossASEmbeddedServer}.  Anything able to represent itself
+ * as a {@link URL} is supported.  Some implementations may, for instance,
+ * to serialize object state into a backing temporary file and point
+ * to that as the target.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public interface Deployable
+{
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Obtains a copy of the location of the {@link Deployable};
+    * multiple invocations upon this method will produce 
+    * different references (so that no mutable state is exported
+    * to callers)
+    * @return
+    */
+   URL getTarget();
+
+}

Modified: projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/DeploymentException.java
===================================================================
--- projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/DeploymentException.java	2009-11-19 22:37:51 UTC (rev 96598)
+++ projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/DeploymentException.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -16,10 +16,14 @@
  */
 package org.jboss.embedded.api;
 
+import org.jboss.embedded.api.server.JBossASEmbeddedServer;
+
 /**
  * DeploymentException
  *
- * Indicates a problem encountered during deployment to the target {@link Container}
+ * Indicates a problem encountered during deployment to the target 
+ * {@link JBossASEmbeddedServer}.  The underlying error may be obtained via 
+ * {@link DeploymentException#getCause()}.
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
@@ -40,35 +44,49 @@
    //-------------------------------------------------------------------------------------||
 
    /**
+    * Constructs a new {@link DeploymentException} using the specified
+    * message and cause
     * 
-    */
-   public DeploymentException()
-   {
-      super();
-   }
-
-   /**
     * @param message
     * @param cause
+    * @throws IllegalArgumentException If the cause is not specified
     */
-   public DeploymentException(String message, Throwable cause)
+   public DeploymentException(final String message, final Throwable cause)
    {
       super(message, cause);
+
+      // Perform assertions
+      this.assertCause(cause);
    }
 
    /**
-    * @param message
+    * Constructs a new {@link DeploymentException} using the specified
+    * cause
+    * 
+    * @param cause
+    * @throws IllegalArgumentException If the cause is not specified
     */
-   public DeploymentException(String message)
+   public DeploymentException(final Throwable cause)
    {
-      super(message);
+      super(cause);
+
+      // Perform assertions
+      this.assertCause(cause);
    }
 
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
    /**
-    * @param cause
+    * Ensures that a cause is specified, else throws
+    * {@link IllegalArgumentException}
     */
-   public DeploymentException(Throwable cause)
+   private void assertCause(final Throwable cause)
    {
-      super(cause);
+      if (cause == null)
+      {
+         throw new IllegalArgumentException("Cause must be specified");
+      }
    }
 }

Modified: projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/server/JBossASEmbeddedServer.java
===================================================================
--- projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/server/JBossASEmbeddedServer.java	2009-11-19 22:37:51 UTC (rev 96598)
+++ projects/embedded/trunk/api/src/main/java/org/jboss/embedded/api/server/JBossASEmbeddedServer.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -21,8 +21,12 @@
  */
 package org.jboss.embedded.api.server;
 
+import java.io.File;
+import java.net.URL;
+
 import org.jboss.bootstrap.api.as.config.JBossASServerConfig;
 import org.jboss.bootstrap.api.as.server.JBossASBasedServer;
+import org.jboss.embedded.api.Deployable;
 import org.jboss.embedded.api.DeploymentException;
 import org.jboss.shrinkwrap.api.Archive;
 
@@ -42,23 +46,83 @@
    //-------------------------------------------------------------------------------||
 
    /**
-    * Deploys the specified archives into the server as one atomic operation. 
+    * Deploys the specified archives into the server as one atomic operation.  Archives
+    * already deployed will be ignored. 
     * 
     * @param archives
     * @throws DeploymentException
-    * @throws IllegalArgumentException If no archives were specified or the type of archive
-    * is not supported by this server
+    * @throws IllegalArgumentException If no archives were specified
     */
    void deploy(Archive<?>... archives) throws DeploymentException, IllegalArgumentException;
 
    /**
+    * Deploys the specified {@link URL}s into the server as one atomic operation.  URLs
+    * already deployed will be ignored. 
+    * 
+    * @param urls
+    * @throws DeploymentException
+    * @throws IllegalArgumentException If no urls were specified 
+    */
+   void deploy(URL... urls) throws DeploymentException, IllegalArgumentException;
+
+   /**
+    * Deploys the specified {@link File}s into the server as one atomic operation.  Files
+    * already deployed will be ignored. 
+    * 
+    * @param files
+    * @throws DeploymentException
+    * @throws IllegalArgumentException If no files were specified 
+    */
+   void deploy(File... files) throws DeploymentException, IllegalArgumentException;
+
+   /**
+    * Deploys the specified {@link Deployable}s into the server as one atomic operation.  Deployables
+    * already deployed will be ignored. 
+    * 
+    * @param deployables
+    * @throws DeploymentException
+    * @throws IllegalArgumentException If no deployables were specified
+    */
+   void deploy(Deployable... deployables) throws DeploymentException, IllegalArgumentException;
+
+   /**
     * Undeploys the specified archives from the server as one atomic operation.
-    * The archives must have been previously deployed.
+    * The archives must have been previously deployed, else they will be ignored.
     * 
     * @param archives
     * @throws DeploymentException
-    * @throws IllegalArgumentException If no archives were specified or the type of archive
-    * is not supported by this server
+    * @throws IllegalArgumentException If no archives were specified
     */
    void undeploy(Archive<?>... archives) throws DeploymentException, IllegalArgumentException;
+
+   /**
+    * Undeploys the specified {@link URL}s from the server as one atomic operation. 
+    * The URLs must have been previously deployed, else they will be ignored.
+    * 
+    * @param urls
+    * @throws DeploymentException
+    * @throws IllegalArgumentException If no urls were specified 
+    */
+   void undeploy(URL... urls) throws DeploymentException, IllegalArgumentException;
+
+   /**
+    * Undeploys the specified {@link File}s from the server as one atomic operation.
+    * The files must have been previously deployed, else they will be ignored.
+    * 
+    * @param files
+    * @throws DeploymentException
+    * @throws IllegalArgumentException If no files were specified 
+    */
+   void undeploy(File... files) throws DeploymentException, IllegalArgumentException;
+
+   /**
+    * Undeploys the specified {@link Deployable}s from the server as one atomic operation. 
+    * The deployables must have been previously deployed, else they will be ignored.
+    * 
+    * @param deployables
+    * @throws DeploymentException
+    * @throws IllegalArgumentException If no deployables were specified
+    */
+   void undeploy(Deployable... deployables) throws DeploymentException, IllegalArgumentException;
+
 }

Modified: projects/embedded/trunk/core/pom.xml
===================================================================
--- projects/embedded/trunk/core/pom.xml	2009-11-19 22:37:51 UTC (rev 96598)
+++ projects/embedded/trunk/core/pom.xml	2009-11-19 22:43:55 UTC (rev 96599)
@@ -77,5 +77,11 @@
       <artifactId>junit</artifactId>
     </dependency>
 
+    <dependency>
+      <groupId>org.jboss.shrinkwrap</groupId>
+      <artifactId>shrinkwrap-impl-base</artifactId>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 </project>

Added: projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableArchive.java
===================================================================
--- projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableArchive.java	                        (rev 0)
+++ projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableArchive.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1,248 @@
+/*
+ * 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.embedded.core.deployable;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.jboss.embedded.api.Deployable;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+
+/**
+ * {@link Deployable} view backed by a ShrinkWrap
+ * {@link Archive}.  Immutable and Thread-safe.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public final class DeployableArchive implements Deployable
+{
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(DeployableArchive.class.getName());
+
+   /**
+    * System property denoting the location of the temp dir
+    */
+   private static final String SYS_PROP_TMP_DIR = "java.io.tmpdir";
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * The serialized view of this archive which
+    * will act as the delegate
+    */
+   private final Deployable serializedView;
+
+   /**
+    * Archive from which this Deployable was created; we use
+    * this in determining value equality
+    */
+   private final Archive<?> createdFrom;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new {@link Deployable} backed by the specified
+    * {@link Archive}
+    * 
+    * @param archive
+    * @throws IllegalArgumentException If the archive is not specified
+    */
+   public DeployableArchive(final Archive<?> archive) throws IllegalArgumentException
+   {
+      if (archive == null)
+      {
+         throw new IllegalArgumentException("archive must be specified");
+      }
+
+      /*
+       * Make a temp file
+       */
+
+      // Get location for the new temp dir, and validate
+      final String tempDirLocation = AccessController.doPrivileged(GetTempDirAction.INSTANCE);
+      final File tmpDir = new File(tempDirLocation);
+      if (!tmpDir.exists())
+      {
+         throw new IllegalStateException("Could not obtain valid temp directory: " + tmpDir.getAbsolutePath());
+      }
+      if (!tmpDir.isDirectory())
+      {
+         throw new IllegalStateException("Temp location must be a directory: " + tmpDir.getAbsolutePath());
+      }
+
+      // Make the new temp file
+      final String name = archive.getName();
+      final InputStream in = archive.as(ZipExporter.class).exportZip();
+      final File tmpFile = new File(tmpDir, name);
+      tmpFile.deleteOnExit();
+
+      // Write the ZIP to the temp file
+      final OutputStream out;
+      try
+      {
+         out = new FileOutputStream(tmpFile);
+      }
+      catch (final FileNotFoundException fnfe)
+      {
+         throw new RuntimeException("Created temp file could not be found: " + tmpFile);
+      }
+      final int len = 1024;
+      final byte[] buffer = new byte[len];
+      int read = 0;
+      try
+      {
+
+         while (((read = in.read(buffer)) != -1))
+         {
+            out.write(buffer, 0, read);
+         }
+      }
+      catch (final IOException ioe)
+      {
+         throw new RuntimeException("Error in obtainting bytes from " + archive, ioe);
+      }
+      finally
+      {
+         try
+         {
+            in.close();
+         }
+         catch (final IOException ignore)
+         {
+         }
+         try
+         {
+            out.close();
+         }
+         catch (final IOException ignore)
+         {
+
+         }
+      }
+      if (log.isLoggable(Level.FINE))
+      {
+         log.fine("Using temporary file to back deployable: " + tmpFile.getAbsolutePath());
+      }
+
+      // Create a Deployable from the File
+      final Deployable deployableFile = new DeployableFile(tmpFile);
+
+      // Set
+      this.createdFrom = archive;
+      this.serializedView = deployableFile;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.embedded.api.Deployable#getTarget()
+    */
+   @Override
+   public URL getTarget()
+   {
+      return serializedView.getTarget();
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Inner Classes ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Privileged action to obtain the temp directory
+    */
+   private static enum GetTempDirAction implements PrivilegedAction<String> {
+      INSTANCE;
+      @Override
+      public String run()
+      {
+         return System.getProperty(SYS_PROP_TMP_DIR);
+      }
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // OVerridden Implementations ---------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * {@inheritDoc}
+    * @see java.lang.Object#hashCode()
+    */
+   @Override
+   public int hashCode()
+   {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((createdFrom == null) ? 0 : createdFrom.hashCode());
+      return result;
+   }
+
+   /**
+    * {@inheritDoc}
+    * Value equality is based upon the underlying archive; 
+    * if the referents are equal, so are we. 
+    * 
+    * @see java.lang.Object#equals(java.lang.Object)
+    */
+   @Override
+   public boolean equals(final Object obj)
+   {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      final DeployableArchive other = (DeployableArchive) obj;
+      if (createdFrom == null)
+      {
+         // Should never be null
+         throw new IllegalStateException("Created from archive must never be null");
+      }
+      // If the underlying archives created from are equal, so are we
+      else if (createdFrom == other.createdFrom)
+      {
+         return true;
+      }
+
+      return false;
+   }
+
+}

Added: projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableFile.java
===================================================================
--- projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableFile.java	                        (rev 0)
+++ projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableFile.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1,147 @@
+/*
+ * 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.embedded.core.deployable;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.jboss.embedded.api.Deployable;
+
+/**
+ * {@link Deployable} view backed by a {@link File}. 
+ * Immutable and Thread-safe.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public final class DeployableFile implements Deployable
+{
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * The backing file; used in determining 
+    * value equality
+    */
+   private final File file;
+
+   /**
+    * The delegate which will be representing this File as 
+    * a {@link Deployable}
+    */
+   private final Deployable delegate;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new {@link Deployable} backed by the specified
+    * {@link File}. 
+    * 
+    * @param file File or exploded directory to be represented as {@link Deployable}
+    * @throws IllegalArgumentException If the file is not specified or does not exist
+    */
+   public DeployableFile(final File file) throws IllegalArgumentException
+   {
+      // Precondition checks
+      if (file == null)
+      {
+         throw new IllegalArgumentException("file must be specified");
+      }
+      if (!file.exists())
+      {
+         throw new IllegalArgumentException("file does not exist: " + file.getAbsolutePath());
+      }
+
+      // Get a URL to the File
+      final URL url;
+      try
+      {
+         url = file.toURI().toURL();
+      }
+      catch (final MalformedURLException murle)
+      {
+         throw new IllegalArgumentException("URL of file is in improper form", murle);
+      }
+
+      // Create a deployable URL delegate
+      final Deployable delegate = new DeployableUrl(url);
+
+      // Set
+      this.file = file;
+      this.delegate = delegate;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * {@inheritDoc} 
+    * @see org.jboss.embedded.api.Deployable#getTarget()
+    */
+   @Override
+   public URL getTarget()
+   {
+      return delegate.getTarget();
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Overridden Implementations ---------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * {@inheritDoc}
+    * @see java.lang.Object#hashCode()
+    */
+   @Override
+   public int hashCode()
+   {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((file == null) ? 0 : file.hashCode());
+      return result;
+   }
+
+   /**
+    * {@inheritDoc}
+    * Value equality is based upon the value equality of the underlying File
+    * @see java.lang.Object#equals(java.lang.Object)
+    */
+   @Override
+   public boolean equals(final Object obj)
+   {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      final DeployableFile other = (DeployableFile) obj;
+      if (file == null)
+      {
+         if (other.file != null)
+            return false;
+      }
+      else if (!file.equals(other.file))
+         return false;
+      return true;
+   }
+}

Added: projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableUrl.java
===================================================================
--- projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableUrl.java	                        (rev 0)
+++ projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/DeployableUrl.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1,118 @@
+/*
+ * 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.embedded.core.deployable;
+
+import java.net.URL;
+
+import org.jboss.embedded.api.Deployable;
+
+/**
+ * {@link Deployable} view backed by a {@link URL}. 
+ * Immutable and Thread-safe.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public final class DeployableUrl implements Deployable
+{
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * The backing URL
+    */
+   private final URL url;
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates a new {@link Deployable} backed by the specified
+    * {@link URL}. 
+    * 
+    * @param url URL pointing to local or remote File, or local exploded directory to be represented as {@link Deployable}
+    * @throws IllegalArgumentException If the URL is not specified
+    */
+   public DeployableUrl(final URL url) throws IllegalArgumentException
+   {
+      if (url == null)
+      {
+         throw new IllegalArgumentException("url must be specified");
+      }
+
+      // Set (a defensive copy)
+      this.url = UrlCopyUtil.copyURL(url);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * {@inheritDoc} 
+    * @see org.jboss.embedded.api.Deployable#getTarget()
+    */
+   @Override
+   public URL getTarget()
+   {
+      return UrlCopyUtil.copyURL(this.url);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Overridden Implementations ---------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * {@inheritDoc}
+    * @see java.lang.Object#hashCode()
+    */
+   @Override
+   public int hashCode()
+   {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((url == null) ? 0 : url.hashCode());
+      return result;
+   }
+
+   /**
+    * {@inheritDoc}
+    * Value equality is based upon the value equality of the underlying URL
+    * @see java.lang.Object#equals(java.lang.Object)
+    */
+   @Override
+   public boolean equals(final Object obj)
+   {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      final DeployableUrl other = (DeployableUrl) obj;
+      if (url == null)
+      {
+         if (other.url != null)
+            return false;
+      }
+      else if (!url.equals(other.url))
+         return false;
+      return true;
+   }
+}

Added: projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/UrlCopyUtil.java
===================================================================
--- projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/UrlCopyUtil.java	                        (rev 0)
+++ projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/UrlCopyUtil.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1,70 @@
+/*
+ * 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.embedded.core.deployable;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Simple utility to copy URLs
+ * (so that we don't export mutable objects)
+ * 
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+final class UrlCopyUtil
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   private UrlCopyUtil()
+   {
+      throw new UnsupportedOperationException("No instances permitted");
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Functional Methods -----------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Copies and returns the specified URL.  Used
+    * to ensure we don't export mutable URLs (thread safety) 
+    * 
+    * @param url
+    * @return
+    */
+   static URL copyURL(final URL url)
+   {
+      // If null, return
+      if (url == null)
+      {
+         return url;
+      }
+
+      try
+      {
+         // Copy 
+         return new URL(url.toExternalForm());
+      }
+      catch (MalformedURLException e)
+      {
+         throw new RuntimeException("Error in copying URL", e);
+      }
+   }
+}

Deleted: projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/VfsVdfDeployableImpl.java
===================================================================
--- projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/VfsVdfDeployableImpl.java	2009-11-19 22:37:51 UTC (rev 96598)
+++ projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/deployable/VfsVdfDeployableImpl.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -1,348 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jboss.embedded.core.deployable;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.jboss.deployers.client.spi.Deployment;
-import org.jboss.deployers.vfs.spi.client.VFSDeploymentFactory;
-import org.jboss.embedded.spi.VdfDeployable;
-import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.exporter.ZipExporter;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VirtualFile;
-
-/**
- * VfsVdfDeployableImpl
- * 
- * A Deployable entity backed by a Virtual Deployer's Framework Deployment
- *
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
-public class VfsVdfDeployableImpl implements VdfDeployable
-{
-
-   //-------------------------------------------------------------------------------------||
-   // Class Members ----------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Logger
-    */
-   private static final Logger log = Logger.getLogger(VfsVdfDeployableImpl.class.getName());
-
-   /**
-    * System property denoting the location of the temp dir
-    */
-   private static final String SYS_PROP_TMP_DIR = "java.io.tmpdir";
-
-   //-------------------------------------------------------------------------------------||
-   // Instance Members -------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * The underlying deployment
-    */
-   private Deployment deployment;
-
-   //-------------------------------------------------------------------------------------||
-   // Constructor ------------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Internal Constructor
-    */
-   protected VfsVdfDeployableImpl(final Deployment deployment) throws IllegalArgumentException
-   {
-      // Precondition check
-      assert deployment != null : "Deployment must be specified";
-
-      // Set
-      this.setDeployment(deployment);
-   }
-
-   //-------------------------------------------------------------------------------------||
-   // Factory Methods --------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Creates a new {@link VdfDeployable} from the specified archive
-    * 
-    * @param archive The archive to be created into a {@link VdfDeployable}
-    * @throws IllegalArgumentException If the archive or name is not specified 
-    */
-   public static VdfDeployable create(final Archive<?> archive) throws IllegalArgumentException
-   {
-      // Obtain name and Stream
-      final String name = archive.getName();
-      final InputStream in = archive.as(ZipExporter.class).exportZip();
-
-      // Create and return
-      return create(name, in);
-   }
-
-   /**
-    * Creates a new {@link VdfDeployable} from the specified archive and name 
-    * 
-    * @param name The name to assign the deployment
-    * @param archive an InputStream representing a series of bytes deployable by the container (eg, JAR, EAR, XML, etc)
-    * @throws IllegalArgumentException If the archive or name is not specified 
-    */
-   public static VdfDeployable create(final String name, final InputStream archive) throws IllegalArgumentException
-   {
-      // Precondition checks
-      if (name == null || name.length() == 0)
-      {
-         throw new IllegalArgumentException("name must be specified");
-      }
-      if (archive == null)
-      {
-         throw new IllegalArgumentException("archive must be specified");
-      }
-
-      // Make a temp file
-      final String tempDirLocation = AccessController.doPrivileged(new PrivilegedAction<String>()
-      {
-         @Override
-         public String run()
-         {
-            return System.getProperty(SYS_PROP_TMP_DIR);
-         }
-      });
-      final File tmpDir = new File(tempDirLocation);
-      if (!tmpDir.exists())
-      {
-         throw new IllegalStateException("Could not obtain valid temp directory: " + tmpDir.getAbsolutePath());
-      }
-      if (!tmpDir.isDirectory())
-      {
-         throw new IllegalStateException("Temp location must be a directory: " + tmpDir.getAbsolutePath());
-      }
-      final File tmpFile = new File(tmpDir, name);
-      tmpFile.deleteOnExit();
-
-      // Write the ZIP to the temp file
-      final OutputStream out;
-      try
-      {
-         out = new FileOutputStream(tmpFile);
-      }
-      catch (final FileNotFoundException fnfe)
-      {
-         throw new RuntimeException("Created temp file could not be found: " + tmpFile);
-      }
-      final int len = 1024;
-      final byte[] buffer = new byte[len];
-      int read = 0;
-      try
-      {
-
-         while (((read = archive.read(buffer)) != -1))
-         {
-            out.write(buffer, 0, read);
-         }
-      }
-      catch (final IOException ioe)
-      {
-         throw new RuntimeException("Error in obtainting bytes from " + archive, ioe);
-      }
-      finally
-      {
-         try
-         {
-            archive.close();
-         }
-         catch (final IOException ignore)
-         {
-
-         }
-         try
-         {
-            out.close();
-         }
-         catch (final IOException ignore)
-         {
-
-         }
-      }
-      if (log.isLoggable(Level.FINE))
-      {
-         log.fine("Using temporary file to back deployable: " + tmpFile.getAbsolutePath());
-      }
-
-      // Delegate
-      return create(tmpFile);
-   }
-
-   /**
-    * Creates a new {@link VdfDeployable} from the specified archive
-    * 
-    * @throws IllegalArgumentException If the archive is not specified or does not exist
-    */
-   public static VdfDeployable create(final File archive) throws IllegalArgumentException
-   {
-      // Precondition checks
-      if (archive == null)
-      {
-         throw new IllegalArgumentException("archive must be specified");
-      }
-      if (!archive.exists())
-      {
-         throw new IllegalArgumentException("archive must exist: " + archive.getAbsolutePath());
-      }
-
-      // Obtain as a VFS VirtualFile
-      final URI uri = archive.toURI();
-      final VirtualFile file;
-      try
-      {
-         file = VFS.createNewRoot(uri);
-      }
-      catch (final IOException e)
-      {
-         throw new RuntimeException("Could not create new VFS root from " + archive, e);
-      }
-
-      // Create Deployment
-      final Deployment deployment = VFSDeploymentFactory.getInstance().createVFSDeployment(file);
-      log.fine("Created deployment: " + deployment);
-
-      // Create Deployable
-      final VdfDeployable deployable = new VfsVdfDeployableImpl(deployment);
-      return deployable;
-   }
-
-   /**
-    * Constructor
-    * 
-    * Creates a new Deployable from the specified URL, 
-    * @throws IllegalArgumentException If the archive is not specified, or is not a valid archive 
-    */
-   public static VdfDeployable create(final URL archive) throws IllegalArgumentException
-   {
-      // Precondition check
-      if (archive == null)
-      {
-         throw new IllegalArgumentException("archive must be specified");
-      }
-
-      // Obtain InputStream
-      final InputStream in;
-      try
-      {
-         in = archive.openConnection().getInputStream();
-      }
-      catch (final IOException ioe)
-      {
-         throw new RuntimeException("Could not get stream from archive: " + archive, ioe);
-      }
-
-      // Obtain the name
-      final String name = archive.getPath();
-
-      // Create from stream
-      return create(name, in);
-   }
-
-   //-------------------------------------------------------------------------------------||
-   // Required Implementations -----------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.tmpdpl.spi.vdf.VdfDeployable#getDeployment()
-    */
-   @Override
-   public Deployment getDeployment()
-   {
-      return this.deployment;
-   }
-
-   //-------------------------------------------------------------------------------------||
-   // Overridden Implementations ---------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Delegates to the underlying deployment for hash code
-    * {@inheritDoc}
-    * @see java.lang.Object#hashCode()
-    */
-   @Override
-   public int hashCode()
-   {
-      final int prime = 31;
-      int result = 1;
-
-      // Use the deployment hash code
-      result = prime * result + ((deployment == null) ? 0 : deployment.hashCode());
-      return result;
-   }
-
-   /**
-    * Deployables with equal underlying deployments, or
-    * created from archives are equal
-    * {@inheritDoc}
-    * @see java.lang.Object#equals(java.lang.Object)
-    */
-   @Override
-   public boolean equals(final Object obj)
-   {
-      if (this == obj)
-         return true;
-      if (obj == null)
-         return false;
-      if (getClass() != obj.getClass())
-         return false;
-      final VfsVdfDeployableImpl other = (VfsVdfDeployableImpl) obj;
-
-      // Equal if the underlying deployments are equal
-      if (deployment == null)
-      {
-         if (other.deployment != null)
-            return false;
-      }
-      else if (!deployment.equals(other.deployment))
-         return false;
-
-      return true;
-   }
-
-   //-------------------------------------------------------------------------------------||
-   // Accessors / Mutators ---------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * @param deployment the deployment to set
-    */
-   private void setDeployment(final Deployment deployment)
-   {
-      this.deployment = deployment;
-   }
-
-}

Modified: projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/server/JBossASEmbeddedServerImpl.java
===================================================================
--- projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/server/JBossASEmbeddedServerImpl.java	2009-11-19 22:37:51 UTC (rev 96598)
+++ projects/embedded/trunk/core/src/main/java/org/jboss/embedded/core/server/JBossASEmbeddedServerImpl.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -21,11 +21,14 @@
  */
 package org.jboss.embedded.core.server;
 
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import org.jboss.bootstrap.api.as.config.JBossASServerConfig;
 import org.jboss.bootstrap.api.config.InvalidConfigurationException;
@@ -38,18 +41,23 @@
 import org.jboss.dependency.spi.ControllerState;
 import org.jboss.deployers.client.spi.Deployment;
 import org.jboss.deployers.client.spi.main.MainDeployer;
+import org.jboss.deployers.vfs.spi.client.VFSDeploymentFactory;
+import org.jboss.embedded.api.Deployable;
 import org.jboss.embedded.api.DeploymentException;
 import org.jboss.embedded.api.server.JBossASEmbeddedServer;
-import org.jboss.embedded.core.deployable.VfsVdfDeployableImpl;
+import org.jboss.embedded.core.deployable.DeployableArchive;
+import org.jboss.embedded.core.deployable.DeployableFile;
+import org.jboss.embedded.core.deployable.DeployableUrl;
 import org.jboss.embedded.core.lifecycle.IgnoreXbUnorderedSequenceLifecycleEventHandler;
 import org.jboss.embedded.core.lifecycle.InitLoggingManagerLifecycleEventHandler;
 import org.jboss.embedded.core.lifecycle.SetIPv4LifecycleEventHandler;
 import org.jboss.embedded.core.lifecycle.SetRmiHostnameLifecycleEventHandler;
-import org.jboss.embedded.spi.VdfDeployable;
 import org.jboss.kernel.Kernel;
 import org.jboss.kernel.spi.dependency.KernelController;
 import org.jboss.logging.Logger;
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VirtualFile;
 
 /**
  * JBossASEmbeddedServer
@@ -94,15 +102,13 @@
    //-------------------------------------------------------------------------------------||
 
    /**
-    * A mapping of deployable types to their resultant deployments (so we can undeploy)
+    * A mapping of {@link Deployable} types to their resultant {@link Deployment}s which have been deployed
+    * (so we can undeploy).  Synchronized on "this" so that we can guarantee all operations are atomic
+    * (like adding all Deployments, removing Deployments, etc.)  Using a java.util.Concurrent
+    * implementation alone won't suit this need.
     */
-   private final Map<VdfDeployable, Deployment> deployableToDeploymentMap = new ConcurrentHashMap<VdfDeployable, Deployment>();
+   private final Map<Deployable, Deployment> deployed = new HashMap<Deployable, Deployment>();
 
-   /**
-    * A mapping of archives to their resultant Deployables (so we can undeploy)
-    */
-   private final Map<Archive<?>, VdfDeployable> archiveToDeployableMap = new ConcurrentHashMap<Archive<?>, VdfDeployable>();
-
    //-------------------------------------------------------------------------------------||
    // Constructor ------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
@@ -153,29 +159,99 @@
    //-------------------------------------------------------------------------------------||
 
    /**
-    * TODO
+    * @see org.jboss.bootstrap.impl.base.server.AbstractServer#getDefaultServerConfigClass()
     */
-   //@Override 
-   //TODO Required?
-   private void deploy(final VdfDeployable... deployables) throws DeploymentException, IllegalArgumentException
+   @Override
+   protected Class<? extends JBossASServerConfig> getDefaultServerConfigClass()
    {
-      // Precondition checks and obtain as VDF impls
-      final Collection<VdfDeployable> vdfDeployables = this.asVdfDeployables(deployables);
+      return BasicJBossASServerConfig.class;
+   }
 
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#deploy(java.net.URL[])
+    */
+   @Override
+   public void deploy(final URL... urls) throws DeploymentException, IllegalArgumentException
+   {
+      // Make new Deployables
+      final Collection<Deployable> deployables = this.asDeployables(urls);
+
+      // Deploy
+      deploy(deployables);
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#deploy(java.io.File[])
+    */
+   @Override
+   public void deploy(final File... files) throws DeploymentException, IllegalArgumentException
+   {
+      // Make new Deployables
+      final Collection<Deployable> deployables = this.asDeployables(files);
+
+      // Deploy
+      deploy(deployables);
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#deploy(org.jboss.shrinkwrap.api.Archive<?>[])
+    */
+   @Override
+   public void deploy(final Archive<?>... archives) throws DeploymentException, IllegalArgumentException
+   {
+      // Make new Deployables
+      final Collection<Deployable> deployables = this.asDeployables(archives);
+
+      // Deploy
+      deploy(deployables);
+   }
+
+   /**
+    * {@inheritDoc} 
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#deploy(org.jboss.embedded.api.Deployable[])
+    */
+   @Override
+   public synchronized void deploy(final Deployable... deployables) throws DeploymentException,
+         IllegalArgumentException
+   {
+      // Precondition checks
+      if (deployables == null)
+      {
+         throw new IllegalArgumentException("deployables must not be null");
+      }
+
       // Get the MainDeployer
       //TODO Use ProfileService - EMB-39
       final MainDeployer mainDeployer = this.getMainDeployer();
 
-      // Add each deployable 
-      for (final VdfDeployable vdfDeployable : vdfDeployables)
+      // Record the deployments to be added
+      final Map<Deployable, Deployment> deploymentsToBeAdded = new HashMap<Deployable, Deployment>();
+
+      // For all Deployables
+      for (final Deployable deployable : deployables)
       {
 
-         /*
-          * Get the Deployers SPI Deployment
-          */
+         // If already deployed
+         if (deployed.containsKey(deployable))
+         {
+            log.warn("Attempting to re-deploy " + deployable + "; ignoring.");
+         }
 
-         // Declare
-         final Deployment deployment = vdfDeployable.getDeployment();
+         // Make a VFS Deployment
+         final URL target = deployable.getTarget();
+         final VirtualFile vf;
+         try
+         {
+            vf = VFS.createNewRoot(target);
+         }
+         catch (final IOException e)
+         {
+            throw new RuntimeException("Could not create new VFS root from " + target, e);
+         }
+         final Deployment deployment = VFSDeploymentFactory.getInstance().createVFSDeployment(vf);
 
          // Add to the MainDeployer
          log.debug("Adding to " + mainDeployer + ": " + deployment);
@@ -183,29 +259,97 @@
          {
             // Add the deployment to the MainDeployer
             mainDeployer.addDeployment(deployment);
+            deploymentsToBeAdded.put(deployable, deployment);
          }
-         catch (org.jboss.deployers.spi.DeploymentException de)
+         catch (final org.jboss.deployers.spi.DeploymentException de)
          {
-            // Wrap in our own API's DeploymentException
-            throw new DeploymentException(de);
+
+            // Construct a new DeploymentException of this API
+            final DeploymentException wrappedException = new DeploymentException(de);
+
+            // Remove all previously-added deployables from further MainDeployer processing
+            for (final Deployable deployableToRemove : deploymentsToBeAdded.keySet())
+            {
+               try
+               {
+                  mainDeployer.removeDeployment(deploymentsToBeAdded.get(deployableToRemove));
+               }
+               catch (org.jboss.deployers.spi.DeploymentException e)
+               {
+                  log.warn("Atomic deployment of " + Arrays.asList(deployables) + " failed due to " + de.getMessage()
+                        + ", and we could not remove " + deployableToRemove + " from further processing");
+               }
+            }
+
+            // Throw the wrapped exception
+            throw wrappedException;
          }
 
-         // Add to the map (so we can undeploy the deployable later)
-         this.deployableToDeploymentMap.put(vdfDeployable, deployment);
+         // Process and check
+         this.processAndCheckMainDeployer(mainDeployer);
+
+         // Record deployed
+         synchronized (this)
+         {
+            this.deployed.putAll(deploymentsToBeAdded);
+         }
       }
 
-      // Process and check
-      this.processAndCheckMainDeployer(mainDeployer);
+   }
 
+   /**
+    * @see org.jboss.tmpdpl.api.container.Container#undeploy(org.jboss.shrinkwrap.api.Archive[])
+    */
+   @Override
+   public void undeploy(final Archive<?>... archives) throws DeploymentException, IllegalArgumentException
+   {
+      // Make new Deployables
+      final Collection<Deployable> deployables = this.asDeployables(archives);
+
+      // Undeploy
+      undeploy(deployables);
    }
 
    /**
-    * TODO
+    * {@inheritDoc}
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#undeploy(java.net.URL[])
     */
-   //@Override
-   //TODO Required?
-   private void undeploy(final VdfDeployable... deployables) throws DeploymentException, IllegalArgumentException
+   @Override
+   public void undeploy(final URL... urls) throws DeploymentException, IllegalArgumentException
    {
+      // Make new Deployables
+      final Collection<Deployable> deployables = this.asDeployables(urls);
+
+      // Undeploy
+      undeploy(deployables);
+
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#undeploy(java.io.File[])
+    */
+   @Override
+   public void undeploy(final File... files) throws DeploymentException, IllegalArgumentException
+   {
+      // Make new Deployables
+      final Collection<Deployable> deployables = this.asDeployables(files);
+
+      // Undeploy
+      undeploy(deployables);
+   }
+
+   /**
+    * {@inheritDoc}
+    * Synchronized so that we may atomically remove all deployables in {@link JBossASEmbeddedServerImpl#deployed}
+    * without fear of intrusion from the outside (there is no atomic Map.removeAll)
+    * 
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#undeploy(org.jboss.embedded.api.Deployable[])
+    */
+   @Override
+   public synchronized void undeploy(final Deployable... deployables) throws DeploymentException,
+         IllegalArgumentException
+   {
       /*
        * Precondition checks
        */
@@ -220,10 +364,13 @@
       //TODO Use ProfileService - EMB-39
       final MainDeployer mainDeployer = this.getMainDeployer();
 
+      // Record deployables to remove
+      final Collection<Deployable> deployablesToRemove = new ArrayList<Deployable>();
+
       // Get the deployments for each deployable
-      for (final VdfDeployable deployable : deployables)
+      for (final Deployable deployable : deployables)
       {
-         final Deployment deployment = this.getDeployablesToDeploymentsMap().get(deployable);
+         final Deployment deployment = this.deployed.get(deployable);
          if (deployment == null)
          {
             log.warn("Specified deployable " + deployable + " cannot be undeployed because it is not deployed.");
@@ -241,54 +388,18 @@
                throw new DeploymentException(de);
             }
 
-            // Remove from Map
-            this.deployableToDeploymentMap.remove(deployable);
+            // Mark to remove
+            deployablesToRemove.add(deployable);
          }
       }
 
       // Process and check
       this.processAndCheckMainDeployer(mainDeployer);
 
-   }
-
-   /**
-    * @see org.jboss.bootstrap.impl.base.server.AbstractServer#getDefaultServerConfigClass()
-    */
-   @Override
-   protected Class<? extends JBossASServerConfig> getDefaultServerConfigClass()
-   {
-      return BasicJBossASServerConfig.class;
-   }
-
-   /**
-    * @see org.jboss.tmpdpl.api.container.Container#deploy(org.jboss.shrinkwrap.api.Archive[])
-    */
-   @Override
-   public void deploy(final Archive<?>... archives) throws DeploymentException, IllegalArgumentException
-   {
-      // Precondition checks and obtain as array of Deployables
-      final VdfDeployable[] deployables = this.asDeployableArray(archives);
-
-      // Deploy
-      this.deploy(deployables);
-   }
-
-   /**
-    * @see org.jboss.tmpdpl.api.container.Container#undeploy(org.jboss.shrinkwrap.api.Archive[])
-    */
-   @Override
-   public void undeploy(final Archive<?>... archives) throws DeploymentException, IllegalArgumentException
-   {
-      // Precondition checks and obtain as array of Deployables
-      final VdfDeployable[] deployables = this.asDeployableArray(archives);
-
-      // Undeploy
-      this.undeploy(deployables);
-
-      // Remove each from the cache
-      for (final Archive<?> archive : archives)
+      // Mark removed
+      for (final Deployable deployable : deployablesToRemove)
       {
-         this.getArchiveToDeployableMap().remove(archive);
+         this.deployed.remove(deployable);
       }
 
    }
@@ -356,47 +467,116 @@
    }
 
    /**
-    * Obtains the specified archives as an array of 
-    * Deployables
-    *  
+    * Represents the specified {@link URL}s as a {@link Collection} of
+    * {@link Deployable}s
+    * 
+    * @param urls
+    * @return
+    * @throws IllegalArgumentException If the URLs are not specified
+    */
+   private Collection<Deployable> asDeployables(final URL... urls) throws IllegalArgumentException
+   {
+      // Precondition checks
+      if (urls == null)
+      {
+         throw new IllegalArgumentException("urls must not be null");
+      }
+
+      // Make new Deployables
+      final Collection<Deployable> deployables = new ArrayList<Deployable>(urls.length);
+      for (final URL url : urls)
+      {
+         final Deployable deployable = new DeployableUrl(url);
+         deployables.add(deployable);
+      }
+      return deployables;
+   }
+
+   /**
+    * Represents the specified {@link Archive}s as a {@link Collection} of
+    * {@link Deployable}s
+    * 
     * @param archives
-    * @throws IllegalArgumentException If the specified archives are not specified or not of acceptable
-    * (VFS) backing type
+    * @return
+    * @throws IllegalArgumentException If the URLs are not specified
     */
-   private VdfDeployable[] asDeployableArray(final Archive<?>... archives) throws IllegalArgumentException
+   private Collection<Deployable> asDeployables(final Archive<?>... archives) throws IllegalArgumentException
    {
-      // Precondition check
-      if (archives == null || archives.length == 0)
+      // Precondition checks
+      if (archives == null)
       {
-         throw new IllegalArgumentException("At least one archive must be specified");
+         throw new IllegalArgumentException("archives must not be null");
       }
 
-      // Make a deployable from each archive
-      final Collection<VdfDeployable> deployables = new ArrayList<VdfDeployable>();
+      // Make new Deployables
+      final Collection<Deployable> deployables = new ArrayList<Deployable>(archives.length);
       for (final Archive<?> archive : archives)
       {
-         // First check the mapping cache
-         final Map<Archive<?>, VdfDeployable> archiveToDeployableMap = this.getArchiveToDeployableMap();
-         VdfDeployable deployable = archiveToDeployableMap.get(archive);
-         // If not in the cache
-         if (deployable == null)
-         {
-            // Make a Deployable from the archive 
-            deployable = VfsVdfDeployableImpl.create(archive);
-            // Add to the cache
-            this.getArchiveToDeployableMap().put(archive, deployable);
-         }
+         final Deployable deployable = new DeployableArchive(archive);
+         deployables.add(deployable);
+      }
+      return deployables;
+   }
 
-         // Add to the Collection to be returned
+   /**
+    * Represents the specified {@link File}s as a {@link Collection} of
+    * {@link Deployable}s
+    * 
+    * @param archives
+    * @return
+    * @throws IllegalArgumentException If the URLs are not specified
+    */
+   private Collection<Deployable> asDeployables(final File... files) throws IllegalArgumentException
+   {
+      // Precondition checks
+      if (files == null)
+      {
+         throw new IllegalArgumentException("files must not be null");
+      }
+
+      // Make new Deployables
+      final Collection<Deployable> deployables = new ArrayList<Deployable>(files.length);
+      for (final File file : files)
+      {
+         final Deployable deployable = new DeployableFile(file);
          deployables.add(deployable);
       }
+      return deployables;
+   }
 
-      // Return
-      return deployables.toArray(new VdfDeployable[]
+   /**
+    * Deploys the specified {@link Deployable}s
+    * 
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#deploy(org.jboss.embedded.api.Deployable[])
+    * @param deployables
+    * @throws DeploymentException
+    * @throws IllegalArgumentException
+    */
+   private void deploy(final Collection<Deployable> deployables) throws DeploymentException, IllegalArgumentException
+   {
+      // Pass over as an array
+      final Deployable[] deployablesArray = deployables.toArray(new Deployable[]
       {});
+      this.deploy(deployablesArray);
    }
 
    /**
+    * Undeploys the specified {@link Deployable}s
+    * 
+    * @see org.jboss.embedded.api.server.JBossASEmbeddedServer#undeploy(Deployable...)
+    * @param deployables
+    * @throws DeploymentException
+    * @throws IllegalArgumentException
+    */
+   private void undeploy(final Collection<Deployable> deployables) throws DeploymentException, IllegalArgumentException
+   {
+      // Pass over as an array
+      final Deployable[] deployablesArray = deployables.toArray(new Deployable[]
+      {});
+      this.undeploy(deployablesArray);
+   }
+
+   /**
     * Obtains the MainDeployer via MC
     * @return
     * @deprecated EMB-39
@@ -420,69 +600,6 @@
    }
 
    /**
-    * Returns a view of the specified Deployables as {@link VdfDeployable}s.
-    *  
-    * @param deployables
-    * @return
-    * @throws IllegalArgumentException If the deployables are either null, empty, or
-    *   contain any non-VDF types
-    */
-   private Collection<VdfDeployable> asVdfDeployables(final VdfDeployable... deployables)
-         throws IllegalArgumentException
-   {
-      return this.asExpectedTypeCollection(VdfDeployable.class, deployables);
-   }
-
-   /**
-    * Obtains the specified array of objects as a Collection of the specified
-    * type.  Each object in the array must be assignable to the target type.
-    * 
-    * @param <T>
-    * @param expectedType
-    * @param objects
-    * @return
-    * @throws IllegalArgumentException If the objects array is null or empty, or one of the objects
-    * in the array is not assignable to the specified type
-    */
-   private <T> Collection<T> asExpectedTypeCollection(final Class<T> expectedType, final Object[] objects)
-         throws IllegalArgumentException
-   {
-      /*
-       * Precondition checks
-       */
-
-      // Ensure objects are specified
-      assert expectedType != null : "Expected type is required";
-      assert objects != null && objects.length > 0 : "At least one object must be specified";
-
-      // Ensure all objects are of expected type
-      final Collection<T> typedCollection = new ArrayList<T>();
-
-      // For each object
-      for (final Object object : objects)
-      {
-         // Is of expected type?
-         final T typedObject;
-         if (expectedType.isAssignableFrom(object.getClass()))
-         {
-            typedObject = expectedType.cast(object);
-         }
-         else
-         {
-            throw new IllegalArgumentException("Unsupported" + "; must be of type \"" + expectedType.getName()
-                  + "\" but was " + object.getClass().getName());
-         }
-
-         // Add
-         typedCollection.add(typedObject);
-
-      }
-
-      // Return
-      return typedCollection;
-   }
-
-   /**
     * Processes and checks the specified MainDeployer
     * @param mainDeployer
     * @throws DeploymentException
@@ -516,24 +633,4 @@
       }
    }
 
-   //-------------------------------------------------------------------------------------||
-   // Accessors / Mutators ---------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Returns an immutable view of the deployables/deployments map
-    * @return the Deployments
-    */
-   protected final Map<VdfDeployable, Deployment> getDeployablesToDeploymentsMap()
-   {
-      return Collections.unmodifiableMap(deployableToDeploymentMap);
-   }
-
-   /**
-    * @return the archiveToDeployableMap
-    */
-   private Map<Archive<?>, VdfDeployable> getArchiveToDeployableMap()
-   {
-      return archiveToDeployableMap;
-   }
 }

Deleted: projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/VfsVdfDeployableImplTestCase.java
===================================================================
--- projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/VfsVdfDeployableImplTestCase.java	2009-11-19 22:37:51 UTC (rev 96598)
+++ projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/VfsVdfDeployableImplTestCase.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -1,139 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jboss.embedded.core;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.logging.Logger;
-
-import org.jboss.embedded.core.deployable.VfsVdfDeployableImpl;
-import org.jboss.embedded.spi.VdfDeployable;
-import org.jboss.virtual.VFS;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * VfsVdfDeployableImplTestCase
- * 
- * Test Cases to ensure that that {@link VfsVdfDeployableImpl} 
- * is working as contracted
- *
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
-public class VfsVdfDeployableImplTestCase
-{
-
-   //-------------------------------------------------------------------------------------||
-   // Class Members ----------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Logger
-    */
-   private static final Logger log = Logger.getLogger(VfsVdfDeployableImplTestCase.class.getName());
-
-   //-------------------------------------------------------------------------------------||
-   // Lifecycle --------------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Initializes the Virtual File System
-    */
-   @BeforeClass
-   public static void initVfs() throws Exception
-   {
-      VFS.init();
-   }
-
-   //-------------------------------------------------------------------------------------||
-   // Tests ------------------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Ensures that the equals() contract is correct; archive types 
-    * are equal if and only if they have equal references to backing 
-    * archives.
-    * @throws Exception
-    */
-   @Test
-   public void testEqualsAndHashCode() throws Exception
-   {
-      // Log
-      log.info("testEquals");
-
-      // Make names
-      final String name1 = "archive1";
-      final String name2 = "archive2";
-
-      // Make some test archives
-      final File root = new File(this.getRoot().toURI());
-      final File archive1 = new File(root, name1);
-      final File archive2 = new File(root, name2);
-      createIfNecessary(archive1);
-      createIfNecessary(archive2);
-
-      // Make some test Deployables from the archives
-      final VdfDeployable deployable1 = VfsVdfDeployableImpl.create(archive1);
-      final VdfDeployable deployable2 = VfsVdfDeployableImpl.create(archive2);
-
-      // Test equals
-      Assert.assertTrue("Deployable must be equal to itself by value", deployable1.equals(deployable1));
-      Assert.assertFalse("Different deployables should not be equal by value", deployable1.equals(deployable2));
-
-      // Get hashCodes
-      final int deployable1HashCode = deployable1.hashCode();
-      final int deployable1HashCodeAgain = deployable1.hashCode();
-
-      // Test hashCodes
-      Assert.assertEquals("hash code op must be indempotent", deployable1HashCode, deployable1HashCodeAgain);
-
-      /*
-       * Note we don't check for inequal hash codes between deployable1 and deployable2 because technically
-       * they could collide
-       */
-   }
-
-   //-------------------------------------------------------------------------------------||
-   // Internal Helper Methods ------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   /**
-    * Returns the root of these tests
-    */
-   private final URL getRoot()
-   {
-      return this.getClass().getProtectionDomain().getCodeSource().getLocation();
-   }
-
-   /**
-    * Creates the new specified file if necessary, erring if unable
-    * @param file
-    * @throws IOException
-    */
-   private static void createIfNecessary(final File file) throws IOException
-   {
-      if (!file.exists())
-      {
-         Assert.assertTrue("archive could not be created", file.createNewFile());
-         log.info("Created tmp file: " + file);
-      }
-   }
-
-}

Added: projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/deployable/DeployableImplementationsTestCase.java
===================================================================
--- projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/deployable/DeployableImplementationsTestCase.java	                        (rev 0)
+++ projects/embedded/trunk/core/src/test/java/org/jboss/embedded/core/deployable/DeployableImplementationsTestCase.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1,224 @@
+/*
+ * 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.embedded.core.deployable;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.jboss.embedded.api.Deployable;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.Archives;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+
+/**
+ * Test Cases to ensure that the implementations for
+ * {@link Deployable} types are working as expected
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class DeployableImplementationsTestCase
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Name of the first test file
+    */
+   private static final String NAME_FILE1 = "file1";
+
+   /**
+    * Name of the second test file
+    */
+   private static final String NAME_FILE2 = "file2";
+
+   //-------------------------------------------------------------------------------------||
+   // Tests ------------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Ensures that {@link Deployable} types backed by an
+    * {@link Archive} are working
+    */
+   @Test
+   public void testDeployableArchive() throws Exception
+   {
+      // Create an archive
+      final JavaArchive archive = Archives.create("archive.jar", JavaArchive.class);
+
+      // Make a Deployable
+      final Deployable deployable = new DeployableArchive(archive);
+
+      // Get the Deployable target
+      final URL target = deployable.getTarget();
+
+      // Test the streams for equal contents
+      final InputStream expectedStream = archive.as(ZipExporter.class).exportZip();
+      final InputStream roundtripStream = target.openStream();
+      this.assertEqualStreamContents(expectedStream, roundtripStream);
+
+      // Test Equality
+      final JavaArchive unequalArchive = Archives.create("unequal.jar", JavaArchive.class);
+      final Deployable unequalDeployable = new DeployableArchive(unequalArchive);
+      final Deployable equalDeployable = new DeployableArchive(archive);
+      this.assertEquality(deployable, equalDeployable, unequalDeployable);
+
+   }
+
+   /**
+    * Ensures that {@link Deployable} types backed by a
+    * {@link File} are working
+    */
+   @Test
+   public void testDeployableFile() throws Exception
+   {
+      // Create a File
+      final File file = new File(this.getUrl(NAME_FILE1).toURI());
+
+      // Make a Deployable
+      final Deployable deployable = new DeployableFile(file);
+
+      // Get the Deployable target
+      final URL target = deployable.getTarget();
+
+      // Test the streams for equal contents
+      final InputStream expectedStream = file.toURI().toURL().openStream();
+      final InputStream roundtripStream = target.openStream();
+      this.assertEqualStreamContents(expectedStream, roundtripStream);
+
+      // Test Equality
+      final File unequalFile = new File(this.getUrl(NAME_FILE2).toURI());
+      final Deployable unequalDeployable = new DeployableFile(unequalFile);
+      final Deployable equalDeployable = new DeployableFile(file);
+      this.assertEquality(deployable, equalDeployable, unequalDeployable);
+
+      // Test preconditions
+      try
+      {
+         new DeployableFile(null);
+         TestCase.fail("New deployable file with null backing file should be invalid");
+      }
+      catch (final IllegalArgumentException iae)
+      {
+         // Expected
+      }
+      try
+      {
+         final File nonExistantFile = new File("made_up_file");
+         TestCase.assertTrue("Test file should not exist", !nonExistantFile.exists());
+         new DeployableFile(nonExistantFile);
+         TestCase.fail("New deployable file with nonexistant backing file should be invalid");
+      }
+      catch (final IllegalArgumentException iae)
+      {
+         // Expected
+      }
+   }
+
+   /**
+    * Ensures that {@link Deployable} types backed by a
+    * {@link URL} are working
+    */
+   @Test
+   public void testDeployableUrl() throws Exception
+   {
+      // Create a URL
+      final URL url = this.getUrl(NAME_FILE1);
+
+      // Make a Deployable
+      final Deployable deployable = new DeployableUrl(url);
+
+      // Get the Deployable target
+      final URL target = deployable.getTarget();
+
+      // Test the streams for equal contents
+      final InputStream expectedStream = url.openStream();
+      final InputStream roundtripStream = target.openStream();
+      this.assertEqualStreamContents(expectedStream, roundtripStream);
+
+      // Test Equality
+      final URL unequalUrl = this.getUrl(NAME_FILE2);
+      final Deployable unequalDeployable = new DeployableUrl(unequalUrl);
+      final Deployable equalDeployable = new DeployableUrl(url);
+      this.assertEquality(deployable, equalDeployable, unequalDeployable);
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Ensures that the {@link Object#equals(Object)} and {@link Object#hashCode()} 
+    * methods are working as contracted
+    * 
+    * @param original The original deployable
+    * @param expectedEqual A deployable expected to be equal to the original
+    * @param expectedUnequal A deployable expected to be unequal to the original
+    */
+   private void assertEquality(final Deployable original, final Deployable expectedEqual,
+         final Deployable expectedUnequal)
+   {
+      TestCase.assertEquals("Deployable archives with equal backing archives should be equal", original, expectedEqual);
+      TestCase.assertNotSame("Deployable archives with inequal backing archives should not be equal", original,
+            expectedUnequal);
+      TestCase.assertEquals("Hash codes of equal objects mus tbe equal", original.hashCode(), expectedEqual.hashCode());
+   }
+
+   /**
+    * Ensures that the contents of the given streams are equal
+    * @param expected
+    * @param deployable
+    * @throws IOException
+    */
+   private void assertEqualStreamContents(final InputStream expected, final InputStream deployable) throws IOException
+   {
+      int read = 0;
+      while ((read = expected.read()) != -1)
+      {
+         int readFromRoundtrip = deployable.read();
+         TestCase.assertEquals("Contents of streams are not equal", read, readFromRoundtrip);
+      }
+      // Also ensure we're at the end of the second stream
+      TestCase.assertEquals(-1, deployable.read());
+   }
+
+   /**
+    * Obtains the resource of the given name
+    * @param fileName
+    * @return
+    * @throws IllegalArgumentException If the name is not specified
+    */
+   private URL getUrl(final String resourceName) throws IllegalArgumentException
+   {
+      // Precondition check
+      if (resourceName == null || resourceName.length() == 0)
+      {
+         throw new IllegalArgumentException("name must be specified");
+      }
+      // Return
+      return this.getClass().getClassLoader().getResource(resourceName);
+   }
+
+}

Added: projects/embedded/trunk/core/src/test/resources/file1
===================================================================
--- projects/embedded/trunk/core/src/test/resources/file1	                        (rev 0)
+++ projects/embedded/trunk/core/src/test/resources/file1	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1 @@
+Test File 1
\ No newline at end of file

Added: projects/embedded/trunk/core/src/test/resources/file2
===================================================================
--- projects/embedded/trunk/core/src/test/resources/file2	                        (rev 0)
+++ projects/embedded/trunk/core/src/test/resources/file2	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1 @@
+Test File 2
\ No newline at end of file

Modified: projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/ServerTestCase.java
===================================================================
--- projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/ServerTestCase.java	2009-11-19 22:37:51 UTC (rev 96598)
+++ projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/ServerTestCase.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -22,8 +22,10 @@
 package org.jboss.embedded.testsuite;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.InputStreamReader;
 import java.net.URI;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -55,12 +57,14 @@
 import org.jboss.bootstrap.api.lifecycle.LifecycleState;
 import org.jboss.embedded.api.server.JBossASEmbeddedServer;
 import org.jboss.embedded.api.server.JBossASEmbeddedServerFactory;
+import org.jboss.embedded.core.server.JBossASEmbeddedServerImpl;
 import org.jboss.embedded.testsuite.ejb3.entity.Jbossian;
 import org.jboss.embedded.testsuite.ejb3.entity.JbossianRegistrarBean;
 import org.jboss.embedded.testsuite.ejb3.entity.JbossianRegistrarLocalBusiness;
 import org.jboss.embedded.testsuite.ejb3.mdb.MessageStoringMdb;
 import org.jboss.embedded.testsuite.ejb3.slsb.OutputBean;
 import org.jboss.embedded.testsuite.ejb3.slsb.OutputLocalBusiness;
+import org.jboss.embedded.testsuite.mc.StateReportingBean;
 import org.jboss.embedded.testsuite.servlet.JspForwardingServlet;
 import org.jboss.shrinkwrap.api.Archives;
 import org.jboss.shrinkwrap.api.Path;
@@ -185,6 +189,16 @@
 
    private static final String WS_RESPONSE = "hello " + WS_REQUEST_PARAMETER;
 
+   /**
+    * Relative path to the MC Descriptor for the State Reporting Bean 
+    */
+   private static final String PATH_STATEREPORTING_BEAN = "mc/statereporter-jboss-beans.xml";
+
+   /**
+    * MC Name (Context) of the State Reporting Bean
+    */
+   private static final String MC_NAME_STATEREPORTING_BEAN = "org.jboss.embedded.test.StateReporter";
+
    //-------------------------------------------------------------------------------||
    // Lifecycle --------------------------------------------------------------------||
    //-------------------------------------------------------------------------------||
@@ -470,11 +484,82 @@
       server.undeploy(archive);
    }
 
+   /**
+    * Ensures that a URL may be deployed and undeployed
+    * 
+    * @throws Exception
+    */
+   @Test
+   public void testUrlDeployment() throws Exception
+   {
+      // Get a URL
+      final URL url = this.getMcBeanDescriptor();
+
+      // Deploy it
+      server.deploy(url);
+
+      // Lookup the bean
+      final String context = MC_NAME_STATEREPORTING_BEAN;
+      final StateReportingBean bean = (StateReportingBean) ((JBossASEmbeddedServerImpl) server).getKernel()
+            .getController().getInstalledContext(context).getTarget();
+      TestCase.assertNotNull("Bean was not found installed in expected context: " + context, bean);
+
+      // Ensure started
+      TestCase.assertEquals("Bean should be started after installation", StateReportingBean.State.STARTED, bean
+            .getState());
+
+      // Undeploy
+      server.undeploy(url);
+
+      // Ensure stopped
+      TestCase.assertEquals("Bean should be stopped after undeploy", StateReportingBean.State.STOPPED, bean.getState());
+   }
+
+   /**
+    * Ensures that a File may be deployed and undeployed
+    * 
+    * @throws Exception
+    */
+   @Test
+   public void testFileDeployment() throws Exception
+   {
+      // Get a File
+      final File file = new File(this.getMcBeanDescriptor().toURI());
+
+      // Deploy it
+      server.deploy(file);
+
+      // Lookup the bean
+      final String context = MC_NAME_STATEREPORTING_BEAN;
+      final StateReportingBean bean = (StateReportingBean) ((JBossASEmbeddedServerImpl) server).getKernel()
+            .getController().getInstalledContext(context).getTarget();
+      TestCase.assertNotNull("Bean was not found installed in expected context: " + context, bean);
+
+      // Ensure started
+      TestCase.assertEquals("Bean should be started after installation", StateReportingBean.State.STARTED, bean
+            .getState());
+
+      // Undeploy
+      server.undeploy(file);
+
+      // Ensure stopped
+      TestCase.assertEquals("Bean should be stopped after undeploy", StateReportingBean.State.STOPPED, bean.getState());
+   }
+
    //-------------------------------------------------------------------------------------||
    // Internal Helper Methods ------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
 
    /**
+    * Obtains the URL of the MC Bean Descriptor for
+    * the State Reporting Bean
+    */
+   private URL getMcBeanDescriptor()
+   {
+      return this.getClass().getClassLoader().getResource(PATH_STATEREPORTING_BEAN);
+   }
+
+   /**
     * Sends a JMS {@link TextMessage} containing the specified contents to the 
     * queue of the specified name  
     * 

Added: projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/mc/StateReportingBean.java
===================================================================
--- projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/mc/StateReportingBean.java	                        (rev 0)
+++ projects/embedded/trunk/testsuite/src/test/java/org/jboss/embedded/testsuite/mc/StateReportingBean.java	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1,91 @@
+/*
+ * 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.embedded.testsuite.mc;
+
+import org.jboss.beans.metadata.api.annotations.Start;
+import org.jboss.beans.metadata.api.annotations.Stop;
+import org.jboss.embedded.api.server.JBossASEmbeddedServer;
+
+/**
+ * Simple MC Bean to test URL and File deployment
+ * into the {@link JBossASEmbeddedServer}.  Reports 
+ * its current state.
+ * 
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class StateReportingBean
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Possible states
+    * 
+    * 
+    * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+    * @version $Revision: $
+    */
+   public enum State {
+      STARTED, STOPPED
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Current state of this bean
+    */
+   private State state = State.STOPPED;
+
+   //-------------------------------------------------------------------------------------||
+   // Lifecycle Methods ------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Reports that the bean has been started
+    */
+   @Start
+   public void setStateStarted()
+   {
+      state = State.STARTED;
+   }
+
+   /**
+    * Reports that the bean has been stopped
+    */
+   @Stop
+   public void setStateStopped()
+   {
+      state = State.STOPPED;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Functional Methods -----------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * @return the state
+    */
+   public State getState()
+   {
+      return state;
+   }
+}

Added: projects/embedded/trunk/testsuite/src/test/resources/mc/statereporter-jboss-beans.xml
===================================================================
--- projects/embedded/trunk/testsuite/src/test/resources/mc/statereporter-jboss-beans.xml	                        (rev 0)
+++ projects/embedded/trunk/testsuite/src/test/resources/mc/statereporter-jboss-beans.xml	2009-11-19 22:43:55 UTC (rev 96599)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  MC Bean Descriptor to install a state-reporting
+  bean whose state will change alongside its lifecycle
+
+-->
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+  <bean name="org.jboss.embedded.test.StateReporter" class="org.jboss.embedded.testsuite.mc.StateReportingBean" />
+
+</deployment>
\ No newline at end of file




More information about the jboss-cvs-commits mailing list