[jboss-cvs] JBossAS SVN: r102120 - in projects/profileservice/trunk: core/src/main/java/org/jboss/profileservice/config and 29 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Mar 9 05:44:07 EST 2010


Author: emuckenhuber
Date: 2010-03-09 05:44:04 -0500 (Tue, 09 Mar 2010)
New Revision: 102120

Added:
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/Hack.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/ArtifactRepositoriesConfig.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/VirtualAssemblyConfiguration.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/ProfileDeploymentModificationChecker.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/BasicModificationStatus.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/TwoPCActionWrapper.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractScanningProfile.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/ImmutableScanningProfile.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/MutableScanningProfile.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/ScanningProfileFactory.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/CopyStreamArtifactTransformer.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/ExplodedArtifactTransformer.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileRepositoryConfiguration.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/MutableFileArtifactRepository.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractImmutableProfile.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractVFSProfileSource.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/DelegateProfile.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/support/
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/support/TestArtifactFilter.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/test/ArtifactRepositoryBackupUnitTestCase.java
   projects/profileservice/trunk/core/src/test/resources/system/static/empty/
   projects/profileservice/trunk/plugins/src/main/java/org/jboss/profileservice/plugins/deploy/actions/
   projects/profileservice/trunk/plugins/src/main/java/org/jboss/profileservice/plugins/deploy/actions/DeploymentDistributeAction.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactTransformer.java
Removed:
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractImmutableProfile.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractVFSProfileSource.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/DelegateProfile.java
Modified:
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/ProfileServiceConfig.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/AbstractDeploymentInfo.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/AbstractProfileDeployment.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/AbstractActionController.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/BasicProfileFactory.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/bootstrap/BootstrapProfileFactory.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/metadata/BasicProfileDeploymentMetaData.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/BasicProfileDeployment.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/ProfileDeploymentFactory.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/AbstractArtifact.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/AbstractArtifactRepository.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/BasicRepositoryConfiguration.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/DefaultNotFoundHandler.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifact.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifactId.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifactRepositoryFactory.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/LocalFileArtifactRepository.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/maven/LocalMavenArtifactRepository.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractDeploymentRepository.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/AbstractVirtualDeploymentRepository.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/AbstractVirtualProfileFactory.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/DelegatingDeploymentRepository.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/VirtualDeploymentProfile.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/virtual/assembly/AbstractVirtualDeploymentAssembly.java
   projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/virtual/assembly/BasicVirtualAssemblyContext.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/metadata/test/BasicDomainMetaDataUnitTestCase.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/test/ArtifactRepositoryUnitTestCase.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/support/NoopArtifactRepository.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/support/TestArtifactRepository.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/support/TestVirtualDeploymentRepository.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/test/StructureMetaDataUnitTestCase.java
   projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/test/VirtualDeploymentAssemblyUnitTestCase.java
   projects/profileservice/trunk/core/src/test/resources/system/bootstrap.xml
   projects/profileservice/trunk/core/src/test/resources/system/static/bootstrap/profile.xml
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/ProfileDeployment.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/VirtualDeploymentRepository.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/TwoPhaseCommitProfileAction.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/engine/ActionController.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/engine/ModificationStatus.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/deployment/ProfileDeploymentInfo.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/Artifact.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactFilter.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactRepository.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactRepositoryConfiguration.java
   projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/MutableArtifactRepository.java
Log:
initial work on preserving the original directory view and scanning profiles

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/Hack.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/Hack.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/Hack.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,49 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice;
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class Hack
+{
+
+   static volatile boolean checkHack = false;
+   
+   public static boolean checkHack()
+   {
+      return checkHack;
+   }
+   
+   /**
+    * Set to true to enable all hacks to be checked
+    * 
+    * @param check
+    */
+   public static void setCheckHack(boolean check)
+   {
+      checkHack = check;
+   }
+   
+}
+

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/ArtifactRepositoriesConfig.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/ArtifactRepositoriesConfig.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/ArtifactRepositoriesConfig.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,96 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.config;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.SecureRandom;
+import java.util.Random;
+
+import org.jboss.vfs.VFS;
+import org.jboss.vfs.VirtualFile;
+import org.jboss.vfs.VirtualFileFilter;
+import org.jboss.vfs.util.ExtensibleFilter;
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class ArtifactRepositoriesConfig
+{
+
+   private static final Random RANDOM_NUM_GEN = new SecureRandom();
+   private static final String JBOSS_TMP_DIR_PROPERTY = "jboss.server.temp.dir";
+   private static final String JVM_TMP_DIR_PROPERTY = "java.io.tmpdir";
+   private static final String BACKUP_ROOT_NAME = "original-backup";
+   private static final URI tmpDirURI;
+   
+   /** The exclude filter. */
+   private VirtualFileFilter excludeFilter = new ExtensibleFilter();
+   
+   static
+   {
+      String configTmpDir = System.getProperty(JBOSS_TMP_DIR_PROPERTY);
+      if (configTmpDir == null)
+          configTmpDir = System.getProperty(JVM_TMP_DIR_PROPERTY);
+      File tempDirFile = new File(configTmpDir);
+      tmpDirURI = tempDirFile.toURI();
+   }
+
+   /**
+    * Create a URI for a repository backup location.
+    * 
+    * @return the backup uri
+    */
+   public URI createBackupURI() throws URISyntaxException
+   {
+      VirtualFile tmpDir = VFS.getChild(tmpDirURI).getChild(BACKUP_ROOT_NAME);
+      return tmpDir.getChild(Long.toHexString(RANDOM_NUM_GEN.nextLong())).asDirectoryURI();
+   }
+   
+   /**
+    * Get the default exclude filter.
+    * 
+    * @return the default exclude filter
+    */
+   public VirtualFileFilter getExcludeFilter()
+   {
+      return excludeFilter;
+   }
+   
+   /**
+    * Set the default exclude filter.
+    * 
+    * @param excludeFilter
+    */
+   public void setExcludeFilter(VirtualFileFilter excludeFilter)
+   {
+      if(excludeFilter == null)
+      {
+         throw new IllegalArgumentException("null exclude filter");
+      }
+      this.excludeFilter = excludeFilter;
+   }
+   
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/ProfileServiceConfig.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/ProfileServiceConfig.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/ProfileServiceConfig.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -30,6 +30,7 @@
 /**
  * Configuration helper to initialize ProfileService.
  *
+ * TODO connect this to the domain meta data
  * TODO differentiate between domain and server specific configuration
  * TODO create interfaces
  * 
@@ -54,6 +55,12 @@
    /** The deployer registry. */
    private ProfileDeployerPluginRegistry deployerRegistry;
    
+   /** The common artifact repository configuration options. */
+   private ArtifactRepositoriesConfig repositoriesConfiguration = new ArtifactRepositoriesConfig();
+   
+   /** The assembly configuration. */
+   private VirtualAssemblyConfiguration assemblyConfiguration = new VirtualAssemblyConfiguration();
+   
    public ProfileServiceConfig()
    {
       //
@@ -114,5 +121,26 @@
    {
       this.profileFactory = profileFactory;
    }
+
+   public ArtifactRepositoriesConfig getRepositoriesConfiguration()
+   {
+      return repositoriesConfiguration;
+   }
+   
+   public void setRepositoriesConfiguration(ArtifactRepositoriesConfig repositoriesConfiguration)
+   {
+      this.repositoriesConfiguration = repositoriesConfiguration;
+   }
+   
+   public VirtualAssemblyConfiguration getAssemblyConfiguration()
+   {
+      return assemblyConfiguration;
+   }
+   
+   public void setAssemblyConfiguration(VirtualAssemblyConfiguration assemblyConfiguration)
+   {
+      this.assemblyConfiguration = assemblyConfiguration;
+   }
+   
 }
 

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/VirtualAssemblyConfiguration.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/VirtualAssemblyConfiguration.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/config/VirtualAssemblyConfiguration.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,58 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.config;
+
+import java.io.File;
+import java.net.URI;
+
+import org.jboss.vfs.VFS;
+import org.jboss.vfs.VirtualFile;
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class VirtualAssemblyConfiguration
+{
+
+   private static final String JBOSS_TMP_DIR_PROPERTY = "jboss.server.temp.dir";
+   private static final String JVM_TMP_DIR_PROPERTY = "java.io.tmpdir";
+   private static final String VIRTUAL_DEPLOYMENTS_NAME = "virtual-deployments";
+   private static final URI tmpDirURI;
+   
+   static 
+   {
+      String configTmpDir = System.getProperty(JBOSS_TMP_DIR_PROPERTY);
+      if (configTmpDir == null)
+          configTmpDir = System.getProperty(JVM_TMP_DIR_PROPERTY);
+      File tempDirFile = new File(configTmpDir);
+      tmpDirURI = tempDirFile.toURI();
+   }
+
+   public VirtualFile getVirtualAssemblyRoot()
+   {
+      VirtualFile tmpDir = VFS.getChild(tmpDirURI);
+      return tmpDir.getChild(VIRTUAL_DEPLOYMENTS_NAME);
+   }
+    
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/AbstractDeploymentInfo.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/AbstractDeploymentInfo.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/AbstractDeploymentInfo.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -23,6 +23,7 @@
 
 import org.jboss.profileservice.spi.deployment.ProfileDeploymentFlag;
 import org.jboss.profileservice.spi.deployment.ProfileDeploymentInfo;
+import org.jboss.profileservice.spi.virtual.VirtualDeploymentMetaData;
 
 /**
  * The abstract deployment info.
@@ -36,12 +37,16 @@
    /** The deployment name. */
    private final String name;
    
+   /** The virtual deployment meta data. */
+   private final VirtualDeploymentMetaData deploymentMetaData;
+   
    /** The flags. */
    private int dFlags = 0;
    
-   public AbstractDeploymentInfo(String name)
+   public AbstractDeploymentInfo(String name, VirtualDeploymentMetaData deploymentMetaData)
    {
       this.name = name;
+      this.deploymentMetaData = deploymentMetaData;
    }
    
    /**
@@ -55,6 +60,14 @@
    /**
     * {@inheritDoc}
     */
+   public VirtualDeploymentMetaData getMetaData()
+   {
+      return this.deploymentMetaData;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
    public boolean hasFlag(ProfileDeploymentFlag flag)
    {
       return ((dFlags & flag.getFlag()) == flag.getFlag());

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/AbstractProfileDeployment.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/AbstractProfileDeployment.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/AbstractProfileDeployment.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -25,6 +25,7 @@
 import org.jboss.profileservice.spi.ProfileDeployment;
 import org.jboss.profileservice.spi.deployment.DeploymentAttachments;
 import org.jboss.profileservice.spi.deployment.ProfileDeploymentInfo;
+import org.jboss.profileservice.spi.virtual.VirtualDeploymentMetaData;
 import org.jboss.vfs.VirtualFile;
 
 /**
@@ -51,7 +52,7 @@
    /** The transient attachments. */
    private transient DeploymentAttachments transientAttachments = new DefaultAttachments();
    
-   protected AbstractProfileDeployment(String name)
+   protected AbstractProfileDeployment(String name, VirtualDeploymentMetaData deploymentMetaData)
    {
       if(name == null)
       {
@@ -62,7 +63,7 @@
       {
          throw new IllegalArgumentException("empty name");
       }
-      this.info = new AbstractDeploymentInfo(name);
+      this.info = new AbstractDeploymentInfo(name, deploymentMetaData);
    }
    
    /**

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/ProfileDeploymentModificationChecker.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/ProfileDeploymentModificationChecker.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/deployment/ProfileDeploymentModificationChecker.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,48 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.deployment;
+
+import org.jboss.profileservice.spi.ProfileDeployment;
+import org.jboss.vfs.VirtualFile;
+
+/**
+ * Modification checker interface.
+ * 
+ * This will usually delegate to the {@code StructureModificationChecker}.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public interface ProfileDeploymentModificationChecker
+{
+
+   /**
+    * Check a deployment for modifications. 
+    * 
+    * @param deployment the profile deployment
+    * @param deploymentRoot the unmounted virtual file
+    * @return true when the deployment was modified, false otherwise
+    */
+   boolean isDeploymentModified(ProfileDeployment deployment, VirtualFile deploymentRoot);
+   
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/AbstractActionController.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/AbstractActionController.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/AbstractActionController.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -21,6 +21,7 @@
 */
 package org.jboss.profileservice.management;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -34,6 +35,7 @@
 import org.jboss.profileservice.spi.ProfileKey;
 import org.jboss.profileservice.spi.action.ProfileModificationAction;
 import org.jboss.profileservice.spi.action.ProfileModificationActions;
+import org.jboss.profileservice.spi.action.ProfileModificationContext;
 import org.jboss.profileservice.spi.action.ProfileModificationType;
 import org.jboss.profileservice.spi.action.TwoPhaseCommitProfileAction;
 import org.jboss.profileservice.spi.action.engine.ActionController;
@@ -50,6 +52,11 @@
    private List<ProfileKey> profiles = new CopyOnWriteArrayList<ProfileKey>();
    private Map<ProfileKey, ProfileWrapper> profilesByName = new ConcurrentHashMap<ProfileKey, ProfileWrapper>();
 
+   /**
+    * Register a profile.
+    * 
+    * @param profile the profile to register
+    */
    public void addProfile(Profile profile)
    {
       ProfileKey key = profile.getKey();
@@ -58,6 +65,11 @@
       fireModificationEvent(new ProfileLifeCycleEvent(key, LifeCycleState.INSTALLED));
    }
    
+   /**
+    * Unregister a profile.
+    * 
+    * @param profile the profile to unregister
+    */
    public void removeProfile(Profile profile)
    {
       ProfileKey key = profile.getKey();
@@ -79,14 +91,18 @@
       }
    }
    
-   @Override
+   /**
+    * {@inheritDoc}
+    */
    public List<ProfileKey> getActiveProfiles()
    {
       return Collections.unmodifiableList(this.profiles);
    }
    
-   @Override
-   public ModificationStatus perfom(ProfileKey key, ProfileModificationActions<?> actions)
+   /**
+    * {@inheritDoc}
+    */
+   public ModificationStatus perfom(ProfileKey key, ProfileModificationActions<ProfileModificationContext> actions)
    {
       if(key == null)
       {
@@ -108,7 +124,14 @@
       }
    }
 
-   ModificationStatus performRead(ProfileWrapper wrapper, ProfileModificationActions<?> actions)
+   /**
+    * Perform read operations on a profile.
+    * 
+    * @param wrapper the wrapper
+    * @param actions the read actions
+    * @return the status
+    */
+   ModificationStatus performRead(ProfileWrapper wrapper, ProfileModificationActions<ProfileModificationContext> actions)
    {
       wrapper.lockRead();
       try
@@ -121,7 +144,14 @@
       }      
    }
    
-   ModificationStatus performWrite(ProfileWrapper wrapper, ProfileModificationActions<?> actions)
+   /**
+    * Perform a write operations on a profile. 
+    * 
+    * @param wrapper the wrapper
+    * @param actions the write actions
+    * @return the status
+    */
+   ModificationStatus performWrite(ProfileWrapper wrapper, ProfileModificationActions<ProfileModificationContext> actions)
    {
       wrapper.lockWrite();
       try
@@ -134,13 +164,54 @@
       }      
    }
 
-   ModificationStatus internalPerfom(Profile profile, ProfileModificationActions<?> actions)
+   /**
+    * Run() the actions.
+    * 
+    * @param profile the profile
+    * @param actions the actions
+    * @return the status
+    */
+   ModificationStatus internalPerfom(Profile profile, ProfileModificationActions<ProfileModificationContext> actions)
    {
-      for(ProfileModificationAction<?> action : actions.getActions())
+      boolean success = true;
+      final List<TwoPhaseCommitProfileAction<?>> prepared = new ArrayList<TwoPhaseCommitProfileAction<?>>();
+      for(ProfileModificationAction<ProfileModificationContext> action : actions.getActions())
       {
-         ((TwoPhaseCommitProfileAction<?>) action).complete();
+         // In case a previous action failed to prepare, cancel others
+         if(success == false)
+         {
+            action.cancel();
+            continue;
+         }
+         TwoPhaseCommitProfileAction<?> tpca = null;
+         if(action instanceof TwoPhaseCommitProfileAction<?>)
+         {
+            tpca = TwoPhaseCommitProfileAction.class.cast(action);
+         }
+         else
+         {
+            // Wrap others
+            tpca = new TwoPCActionWrapper(action);
+         }
+         // Prepare
+         success &= tpca.prepare();
+         prepared.add(tpca);
       }
-      return null;
+      if(success)
+      {
+         for(TwoPhaseCommitProfileAction<?> tpca : prepared)
+         {
+            tpca.commit();
+         }
+      }
+      else
+      {
+         for(TwoPhaseCommitProfileAction<?> tpca : prepared)
+         {
+            tpca.rollback();
+         }
+      }
+      return new BasicModificationStatus(success);
    }
 
    /**
@@ -152,7 +223,7 @@
       private final Profile profile;
       private final ReentrantReadWriteLock lock;
       
-      ProfileWrapper(Profile profile)
+      ProfileWrapper(final Profile profile)
       {
          this.profile = profile;
          this.lock = new ReentrantReadWriteLock(true); 

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/BasicModificationStatus.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/BasicModificationStatus.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/BasicModificationStatus.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,61 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.management;
+
+import org.jboss.profileservice.spi.action.engine.ModificationStatus;
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class BasicModificationStatus implements ModificationStatus
+{
+
+   final boolean success;
+   
+   public BasicModificationStatus(boolean success)
+   {
+      this.success = success;
+   }
+   
+   public Exception getFailure()
+   {
+      return null;
+   }
+
+   public boolean isCompleted()
+   {
+      return true;
+   }
+
+   public boolean isFailed()
+   {
+      return success == false;
+   }
+
+   public boolean isRunning()
+   {
+      return false;
+   }
+
+}
+

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/TwoPCActionWrapper.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/TwoPCActionWrapper.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/management/TwoPCActionWrapper.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,90 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.management;
+
+import org.jboss.profileservice.spi.action.ActionStatus;
+import org.jboss.profileservice.spi.action.ProfileModificationAction;
+import org.jboss.profileservice.spi.action.ProfileModificationContext;
+import org.jboss.profileservice.spi.action.TwoPhaseCommitProfileAction;
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+class TwoPCActionWrapper implements TwoPhaseCommitProfileAction<ProfileModificationContext>
+{
+
+   /** The delegate. */
+   private final ProfileModificationAction<ProfileModificationContext> delegate;
+   
+   public TwoPCActionWrapper(ProfileModificationAction<ProfileModificationContext> delegate)
+   {
+      this.delegate = delegate;
+   }
+   
+   public void commit()
+   {
+      this.delegate.complete();
+   }
+
+   public ActionStatus getStatus()
+   {
+      return ActionStatus.UNKNOWN;
+   }
+
+   public boolean prepare()
+   {
+      return true;
+   }
+
+   public void rollback()
+   {
+      //
+   }
+
+   public void cancel()
+   {
+      this.delegate.cancel();
+   }
+
+   public void complete()
+   {
+      this.delegate.complete();
+   }
+
+   public ProfileModificationContext getContext()
+   {
+      return this.delegate.getContext();
+   }
+
+   public boolean isCancelled()
+   {
+      return this.delegate.isCancelled();
+   }
+
+   public boolean isComplete()
+   {
+      return this.delegate.isComplete();
+   }
+
+}
+

Deleted: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractImmutableProfile.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractImmutableProfile.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractImmutableProfile.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -1,142 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */ 
-package org.jboss.profileservice.profile;
-
-import java.net.URI;
-import java.util.List;
-
-import org.jboss.logging.Logger;
-import org.jboss.profileservice.spi.NoSuchDeploymentException;
-import org.jboss.profileservice.spi.Profile;
-import org.jboss.profileservice.spi.ProfileDeployment;
-import org.jboss.profileservice.spi.ProfileKey;
-import org.jboss.vfs.VirtualFile;
-
-/**
- * A immutable vfs based profile.
- * 
- * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
- * @version $Revision$
- */
-public class AbstractImmutableProfile extends AbstractVFSProfileSource implements Profile
-{
-
-   /** The profile key. */
-   private ProfileKey key;
-  
-   /** The logger. */
-   private static final Logger log = Logger.getLogger(AbstractImmutableProfile.class);
-   
-   public AbstractImmutableProfile(ProfileKey key, URI[] uris)
-   {
-      super(uris);
-      //
-      if(key == null)
-         throw new IllegalArgumentException("Null profile key.");
-      
-      this.key = key;
-   }
-   
-   public void create() throws Exception
-   {
-      for(URI uri : getRepositoryURIs())
-      {
-         VirtualFile root = getCachedVirtualFile(uri);
-         loadApplications(root);
-      }
-      updateLastModfied();
-   }
-   
-   public ProfileKey getKey()
-   {
-      return this.key;
-   }
-   
-   @Override
-   public ProfileDeployment getDeployment(String vfsPath) throws NoSuchDeploymentException
-   {
-      if(vfsPath == null)
-         throw new IllegalArgumentException("Null name");
-      
-      ProfileDeployment ctx = super.getDeployment(vfsPath);
-      if(ctx == null)
-      {
-         List<String> names = findDeploymentContent(vfsPath);
-         if(names.size() == 1)
-         {
-            ctx = super.getDeployment(names.get(0));
-         }
-         else if(names.size() > 1)
-         {
-            throw new NoSuchDeploymentException("Multiple deployments found for: "+ vfsPath +", available: " + names);            
-         }
-      }
-      if(ctx == null)
-      {
-         log.debug("Failed to find application for: "+vfsPath+", available: " + getDeploymentNames());
-         throw new NoSuchDeploymentException("Failed to find deployment in file: " + vfsPath);
-      }
-      return ctx;
-   }
-
-   public boolean hasDeployment(String name)
-   {
-      if(name == null)
-         throw new IllegalArgumentException("Null name.");
-
-      try
-      {
-         return super.getDeployment(name) != null;
-      }
-      catch(Exception e)
-      {
-         return false;
-      }
-   }
-
-   public boolean isMutable()
-   {
-      return false;
-   }
-   
-   public String toString()
-   {
-      StringBuilder builder = new StringBuilder();
-      builder.append(getClass().getSimpleName());
-      builder.append('@').append(Integer.toHexString(System.identityHashCode(this)));
-      builder.append("{key = ").append(getKey());
-      toString(builder);
-      builder.append("}");
-      return builder.toString();
-   }
-   
-   /**
-    * Additional information for toString().
-    * 
-    * @param builder the builder.
-    */
-   protected void toString(StringBuilder builder)
-   {
-      //
-   }
-
-}

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractScanningProfile.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractScanningProfile.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractScanningProfile.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,436 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.profile;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.jboss.logging.Logger;
+import org.jboss.profileservice.profile.metadata.BasicProfileDeploymentMetaData;
+import org.jboss.profileservice.repository.artifact.file.FileArtifact;
+import org.jboss.profileservice.repository.artifact.file.FileArtifactId;
+import org.jboss.profileservice.spi.NoSuchDeploymentException;
+import org.jboss.profileservice.spi.Profile;
+import org.jboss.profileservice.spi.ProfileDeployment;
+import org.jboss.profileservice.spi.ProfileKey;
+import org.jboss.profileservice.spi.VirtualDeploymentRepository;
+import org.jboss.profileservice.spi.repository.Artifact;
+import org.jboss.profileservice.spi.repository.ArtifactFilter;
+import org.jboss.profileservice.spi.repository.ArtifactId;
+import org.jboss.profileservice.spi.repository.ArtifactRepository;
+import org.jboss.profileservice.spi.virtual.VirtualDeploymentMetaData;
+
+/**
+ * The abstract scanning profile. This profile type uses a {@code FileArtifactId} artifact
+ * repository to manage and retrieve deployment contents.  
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public abstract class AbstractScanningProfile implements Profile, ArtifactFilter<FileArtifactId>
+{
+
+   /** The profile key. */
+   private final ProfileKey key;
+   
+   /** The virtual deployment repository. */
+   private final VirtualDeploymentRepository deploymentRepository;
+   
+   /** The artifact repository. */
+   private ArtifactRepository<FileArtifactId> artifactRepository;
+
+   /** The deployments. */
+   private Map<String, ProfileDeployment> deployments = new ConcurrentHashMap<String, ProfileDeployment>();
+   
+   /** Repository name, deployment name mapping. */
+   private Map<String, String> repositoryNames = new ConcurrentHashMap<String, String>();
+   
+   /** The last modified. */
+   private volatile long lastModified;
+   
+   public AbstractScanningProfile(ProfileKey key, VirtualDeploymentRepository deploymentRepository)
+   {
+      if(key == null)
+      {
+         throw new IllegalArgumentException("null profile key");
+      }
+      if(deploymentRepository == null)
+      {
+         throw new IllegalArgumentException("null virtual profile repository");
+      }
+      this.key = key;
+      this.deploymentRepository = deploymentRepository;
+   }
+   
+   /**
+    * Specify the logger on the implementing class.
+    * 
+    * @return the logger
+    */
+   protected abstract Logger getLog();
+   
+   /**
+    * Lifecycle create method.
+    *
+    * @throws IllegalStateException if the artifact repository can't be resolved
+    */
+   public void create() throws IllegalStateException
+   {
+      // Resolve our file artifact repository
+      // for scanning we need to have direct access
+      this.artifactRepository = getRepository().resolveArtifactRepository(FileArtifactId.EMPTY_ARTIFACT);
+      if(this.artifactRepository == null)
+      {
+         throw new IllegalStateException("failed to resolve artifact repository");
+      }      
+   }
+
+   /**
+    * Lifecycle start method.
+    * 
+    * This will ask the repository for all artifacts and create
+    * deployments based on this information.
+    * 
+    * @throws IOException for any error
+    */
+   public void start() throws IOException
+   {
+      // Scan
+      scanRepository();
+      updateLastModified();
+   }
+   
+   /**
+    * Lifecycle stop method, this will try to cleanup all deployments. 
+    */
+   public void stop()
+   {
+      for(ProfileDeployment deployment : this.deployments.values())
+      {
+         try
+         {
+            deployment.cleanup();
+         }
+         catch(Exception e)
+         {
+            getLog().debug("failed to cleanup deployment " + deployment);
+         }
+      }
+      this.deployments.clear();
+      this.repositoryNames.clear();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ProfileKey getKey()
+   {
+      return this.key;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public boolean hasDeployment(final String name)
+   {
+      return this.deployments.containsKey(name);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public ProfileDeployment getDeployment(final String name) throws NoSuchDeploymentException
+   {
+      final ProfileDeployment deployment = resolveDeployment(name);
+      if(deployment == null)
+      {
+         throw new NoSuchDeploymentException(name);
+      }
+      return deployment;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public Set<String> getDeploymentNames()
+   {
+      return this.deployments.keySet();
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public Collection<ProfileDeployment> getDeployments()
+   {
+      return this.deployments.values();
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public long getLastModified()
+   {
+      return lastModified;
+   }
+   
+   /**
+    * Scan the repository. This class implements {@code ArtifactFilter} to control
+    * which artifacts are included and represent a deployment. 
+    * 
+    * @return a collection of created deployments
+    * @throws IOException for any error
+    */
+   protected Collection<ProfileDeployment> scanRepository() throws IOException
+   {
+      final Collection<Artifact<FileArtifactId>> artifacts = getArtifacts();
+      if(artifacts != null && artifacts.isEmpty() == false)
+      {
+         Collection<ProfileDeployment> deployments = new ArrayList<ProfileDeployment>();
+         for(final Artifact<FileArtifactId> artifact : getArtifacts())
+         {
+            //
+            final FileArtifactId artifactId = artifact.getIdentifier();
+            final ProfileDeployment deployment = createDeployment(artifactId);
+            //
+            internalAddDeployment(deployment, artifactId);
+            //
+            deployments.add(deployment);
+         }
+         return deployments;
+      }
+      return Collections.emptySet();
+   }
+   
+   /**
+    * Get the artifacts.
+    * 
+    * @return the scanned artifacts
+    */
+   protected Collection<Artifact<FileArtifactId>> getArtifacts()
+   {
+      return getArtifactRepository().getArtifacts(this);
+   }
+   
+   // Artifact filter
+   
+   @SuppressWarnings("deprecation")
+   public boolean accepts(final Artifact<FileArtifactId> artifact)
+   {
+      final FileArtifactId id = artifact.getIdentifier();
+      boolean exists = repositoryNames.keySet().contains(id.getPath());
+      if(exists)
+      {
+         return false;
+      }
+      // Support the "directory grouping feature" of AS5
+      if(artifact instanceof FileArtifact)
+      {
+         // If it's a file we accept it
+         if(((FileArtifact) artifact).isFile())
+         {
+            return true;
+         }
+         else
+         {
+            return id.getPath().contains(".");
+         }
+      }
+      return false; 
+   }
+
+   @SuppressWarnings("deprecation")
+   public boolean recurse(final Artifact<FileArtifactId> artifact)
+   {
+      // Support the "directory grouping feature" of AS5
+      if(artifact instanceof FileArtifact)
+      {
+         // If it's a directory and does not contain a "."
+         if(((FileArtifact) artifact).isFile() == false)
+         {
+            final FileArtifactId id = artifact.getIdentifier();
+            final String path = id.getPath();  
+            return path.contains(".") == false;            
+         }
+      }
+      return false;
+   }   
+   
+   // protected
+   
+   /**
+    * Resolve a deployment name.
+    */
+   protected ProfileDeployment resolveDeployment(final String name)
+   {
+      ProfileDeployment deployment = this.deployments.get(name);
+      if(deployment == null)
+      {
+         for(ProfileDeployment d : getDeployments())
+         {
+            if(d.getSimpleName().equals(name))
+            {
+               deployment = d;
+               break;
+            }
+         }
+      }
+      return deployment;
+   }
+   
+   /**
+    * Internal add a profile deployment.
+    * 
+    * @param deployment the deployment
+    * @param artifactId the associated artifact id
+    */
+   protected void internalAddDeployment(final ProfileDeployment deployment, final FileArtifactId artifactId)
+   {
+      this.deployments.put(deployment.getName(), deployment);
+      this.repositoryNames.put(artifactId.getPath(), deployment.getName());
+      // Mark as modified if it already exists ?
+   }
+   
+   /**
+    * Remove a deployment. This will call the {@code ProfileDeployment#cleanup()} method.
+    * 
+    * @param name the deployment name
+    * @return the profile deployment
+    * @throws NoSuchDeploymentException if the deployment was not found
+    */
+   protected ProfileDeployment internalRemoveDeployment(final String name) throws NoSuchDeploymentException
+   {
+      return internalRemoveDeployment(name, true);
+   }
+   
+   /**
+    * Remove a deployment. The cleanup flag can be used to specify if the
+    * {@code ProfileDeployment#cleanup()} method should be called. 
+    * 
+    * @param name the deployment name
+    * @param cleanup flag indicating if the cleanup method should be called
+    * @return the profile deployment
+    * @throws NoSuchDeploymentException if the deployment cannot be resolved
+    */
+   protected ProfileDeployment internalRemoveDeployment(final String name, final boolean cleanup) throws NoSuchDeploymentException
+   {
+      // Get deployment
+      final ProfileDeployment deployment = getDeployment(name);
+      final FileArtifactId artifactId = getArtifactMetaData(deployment);
+      // remove
+      this.deployments.remove(deployment.getName());
+      this.repositoryNames.remove(artifactId.getPath());
+      // Cleanup
+      if(cleanup)
+      {
+         try
+         {
+            deployment.cleanup();
+         }
+         catch(Exception e)
+         {
+            getLog().debug("failed to cleanup deployment " + deployment);
+         }
+      }
+      return deployment;
+   }
+   
+   /**
+    * Create a deployment based on a {@code FileArtifactId}.
+    * 
+    * @param artifactId the artifact id.
+    * @return the profile deployment
+    * @throws IOException for any error
+    */
+   protected ProfileDeployment createDeployment(FileArtifactId artifactId) throws IOException
+   {
+      // Create a virtual deployment meta data
+      return createDeployment(new BasicProfileDeploymentMetaData(artifactId.getPath()));
+   }
+   
+   /**
+    * Create a deployment based on it's virtual deployment descriptor.
+    * 
+    * @param virtual the virtual deployment meta data
+    * @return the profile deployment
+    * @throws IOException for any error
+    */
+   protected ProfileDeployment createDeployment(VirtualDeploymentMetaData virtual) throws IOException
+   {
+      return getRepository().createDeployment(virtual);
+   }
+   
+   /**
+    * Get the artifact meta data from the {@code ProfielDeploymentInfo}.
+    * 
+    * @param deployment the profile deployment
+    * @return the file artifact
+    * @throws if the {@code FileArtifactId} does not exist
+    */
+   protected FileArtifactId getArtifactMetaData(ProfileDeployment deployment)
+   {
+      final ArtifactId artifactId = deployment.getDeploymentInfo().getMetaData().getArtifact();
+      if(artifactId == null || artifactId instanceof FileArtifactId == false)
+      {
+         throw new IllegalStateException("failed to get file artifact id " + artifactId);
+      }
+      return FileArtifactId.class.cast(artifactId);
+   }
+   
+   /**
+    * Get the artifact repository.
+    * 
+    * @return the artifact repository
+    */
+   protected ArtifactRepository<FileArtifactId> getArtifactRepository()
+   {
+      if(this.artifactRepository == null)
+      {
+         throw new IllegalStateException("null artifact repository");
+      }
+      return this.artifactRepository;
+   }
+
+   /**
+    * Get the virtual deployment repository.
+    * 
+    * @return the virtual deployment repository
+    */
+   protected VirtualDeploymentRepository getRepository()
+   {
+      return this.deploymentRepository;
+   }
+
+   /**
+    * internal update the last modified info.
+    */
+   protected void updateLastModified()
+   {
+      this.lastModified = System.currentTimeMillis();
+   }
+   
+}
+

Deleted: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractVFSProfileSource.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractVFSProfileSource.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractVFSProfileSource.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -1,380 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */ 
-package org.jboss.profileservice.profile;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.jboss.logging.Logger;
-import org.jboss.profileservice.repository.ProfileDeploymentFactory;
-import org.jboss.profileservice.spi.NoSuchDeploymentException;
-import org.jboss.profileservice.spi.NoSuchProfileException;
-import org.jboss.profileservice.spi.ProfileDeployment;
-import org.jboss.vfs.VFS;
-import org.jboss.vfs.VirtualFile;
-import org.jboss.vfs.VirtualFileFilter;
-
-/**
- * A abstract VFS based source for profile deployments.
- * 
- * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
- * @version $Revision$
- */
-public abstract class AbstractVFSProfileSource
-{
-   
-   /** The repository uris. */
-   protected final Collection<URI> uris;
-
-   /** The VFSDeployments. */
-   private Map<String, ProfileDeployment> applicationCtxs = new ConcurrentHashMap<String, ProfileDeployment>();
-   
-   /** Allowed deployments filter. */
-   private VirtualFileFilter deploymentFilter;
-   
-   /** The application files keyed by VirtualFile URI string. */
-   private final Map<String, VirtualFile> applicationVFCache = new ConcurrentHashMap<String, VirtualFile>();
-   
-   /** Do a recursive search - default == true. */
-   private boolean recursiveScan = true;
-
-   /** The last time the profile was modified. */
-   private volatile long lastModified;
-   
-   /** The logger. */
-   private final static Logger log = Logger.getLogger(AbstractVFSProfileSource.class);
-   
-   /** The deployment factory. */
-   private final static ProfileDeploymentFactory deploymentFactory = ProfileDeploymentFactory.getInstance();
-   
-   public AbstractVFSProfileSource(URI[] uris)
-   {
-      if(uris == null)
-         throw new IllegalArgumentException("Null uris");
-      
-      this.uris = new ArrayList<URI>();
-      for(URI uri : uris)
-      {
-         this.uris.add(uri);
-      }
-   }
-
-   public VirtualFileFilter getDeploymentFilter()
-   {
-      return deploymentFilter;
-   }
-   
-   public void setDeploymentFilter(VirtualFileFilter deploymentFilter)
-   {
-      this.deploymentFilter = deploymentFilter;
-   }
-   
-   public boolean isRecursiveScan()
-   {
-      return recursiveScan;
-   }
-   
-   public void setRecursiveScan(boolean recursiveScan)
-   {
-      this.recursiveScan = recursiveScan;
-   }
-   
-   public URI[] getRepositoryURIs()
-   {
-      return uris.toArray(new URI[uris.size()]);
-   }
-   
-   public Set<String> getDeploymentNames()
-   {
-      return this.applicationCtxs.keySet();
-   }
-
-   public Collection<ProfileDeployment> getDeployments()
-   {
-      return this.applicationCtxs.values();
-   }
-   
-   public long getLastModified()
-   {
-      return this.lastModified;
-   }
-   
-   public void destroy()
-   {
-      // Unload
-      this.applicationCtxs.clear();
-      this.applicationVFCache.clear();
-      updateLastModfied();
-   }
-   
-   /**
-    * Add a deployment to this profile source. 
-    * 
-    * @param d the deployment
-    * @throws IllegalArgumentException for a null deployment
-    */
-   protected void addDeployment(ProfileDeployment d)
-   {
-      if(d == null)
-         throw new IllegalArgumentException("null deployment");
-      
-      // Add deployment and vfs
-      this.applicationCtxs.put(d.getName(), d);
-      if(d.getRoot() != null)
-         this.applicationVFCache.put(d.getName(), d.getRoot());
-      updateLastModfied();
-   }
-   
-   /**
-    * Get the deployment
-    * 
-    * @param vfsPath the deployment
-    * @return the deployment or null if it does not exist
-    */
-   protected ProfileDeployment getDeployment(String vfsPath) throws NoSuchDeploymentException
-   {
-      if(vfsPath == null)
-         throw new IllegalArgumentException("Null vfsPath");
-
-      return this.applicationCtxs.get(vfsPath);
-   }
-   
-   /**
-    * Remove a deployment from this source.
-    * 
-    * @param vfsPath the deployment name
-    * @return the deployment
-    * @throws NoSuchProfileException if the deployment does not exist
-    */
-   public ProfileDeployment removeDeployment(String vfsPath) throws Exception
-   {
-      if(vfsPath == null)
-         throw new IllegalArgumentException("Null vfsPath");
-      
-      // Get the deployment
-      ProfileDeployment deployment = getDeployment(vfsPath);
-      // Remove the entries
-      this.applicationCtxs.remove(deployment.getName());
-      this.applicationVFCache.remove(deployment.getName());
-      // Update last modified
-      updateLastModfied();
-      // Return
-      return deployment;
-   }
-   
-   /**
-    * Load all the applications under the applicationDir.
-    * 
-    * @param applicationDir the application directory
-    * @throws IOException
-    */
-   protected void loadApplications(VirtualFile applicationDir) throws Exception
-   {
-      ArrayList<VirtualFile> added = new ArrayList<VirtualFile>();
-      addedDeployment(added, applicationDir);
-      for (VirtualFile vf : added)
-      {
-         ProfileDeployment vfCtx = createDeployment(vf);
-         addDeployment(vfCtx);
-      }
-   }
-   
-   /**
-    * Scan the children of the root for deployments.
-    * 
-    * @param list a list of virtual files, where new deployments are added to
-    * @param root the root to scan
-    * @throws IOException
-    * @throws URISyntaxException
-    */
-   protected void addedDeployments(List<VirtualFile> list, VirtualFile root) throws IOException, URISyntaxException
-   {
-      if(root.isFile())
-      {
-         addedDeployment(list, root);
-      }
-      else
-      {
-         List<VirtualFile> components = root.getChildren();
-         for (VirtualFile component : components)
-         {
-            addedDeployment(list, component);
-         }         
-      }
-   }
-   
-   /**
-    * Scan a given virtualFile for deployments.
-    * 
-    * @param list a list of virtual files, where new deployments are added to
-    * @param component the root file
-    * @throws IOException
-    * @throws URISyntaxException
-    */
-   protected void addedDeployment(List<VirtualFile> list, VirtualFile component) throws IOException, URISyntaxException
-   {
-      // Excluding files from scanning
-      if(deploymentFilter != null && this.deploymentFilter.accepts(component) == false)
-      {
-         if(log.isTraceEnabled())
-            log.trace("ignoring "+ component);
-         return;
-      }
-      
-      // Check if we accept this deployment
-      String key = component.asFileURI().toString();
-      if(acceptsDeployment(key) == false)
-         return;
-
-      // If it's a directory or exploded deployment
-      if(component.isFile() == false)
-      {
-         // Check the name
-         if(isRecursiveScan() && component.getName().indexOf('.') == -1)
-         {
-            // recurse if not '.' in name and recursive search is enabled
-            addedDeployments(list, component);            
-         }
-         else
-         {
-            list.add(component);
-         }
-      }
-      else
-      {
-         list.add(component);
-      }
-   }
-   
-   /**
-    * Check if the deployment should be added.
-    * 
-    * @param name the deployment name
-    * @return  
-    */
-   protected boolean acceptsDeployment(String name)
-   {
-      return applicationCtxs.containsKey(name) == false;
-   }
-   
-   /**
-    * Try to find a deployment, based on the cached
-    * virtual roots of deployments we have.
-    * 
-    * @param name the deployment name
-    * @return a collection of matching names
-    */
-   protected List<String> findDeploymentContent(String name)
-   {
-      if(this.applicationVFCache.containsKey(name))
-      {
-         return Collections.singletonList(name);
-      }
-      
-      List<String> contents = new ArrayList<String>();
-      for(String cacheName : this.applicationVFCache.keySet())
-      {
-         String fixedName = cacheName;
-         if(cacheName.endsWith("/"))
-            fixedName = cacheName.substring(0, cacheName.length() -1);
-         
-         if(fixedName.endsWith(name))
-         {
-            contents.add(cacheName);
-         }
-      }
-      return contents;
-   }
-   
-   /**
-    * Add a virtualFile to the local virtualFileCache
-    * 
-    * @param vf the virtual file
-    * @return the name
-    * @throws MalformedURLException
-    * @throws URISyntaxException
-    */
-   protected String addVirtualFileCache(VirtualFile vf) throws MalformedURLException, URISyntaxException
-   {
-      String uri = vf.asFileURI().toString();
-      this.applicationVFCache.put(uri, vf);
-      return uri;
-   }
-
-   /**
-    * Get a cached virtual file.
-    * 
-    * @param name the name
-    * @return the virtual file or null, if it does not exist
-    */
-   protected VirtualFile getCachedVirtualFile(String name)
-   {
-      return this.applicationVFCache.get(name);
-   }
-   
-   /**
-    * Get a cached virtual file. This will add the uri to the
-    * virtualFile if it does not exist.
-    * 
-    * @param uri the uri
-    * @return the virtual file
-    * @throws IOException
-    */
-   protected VirtualFile getCachedVirtualFile(URI uri) throws IOException 
-   {
-      VirtualFile vf = getCachedVirtualFile(uri.toString());
-      if(vf == null)
-      {
-         vf = VFS.getChild(uri);
-         this.applicationVFCache.put(uri.toString(), vf);
-      }
-      return vf;
-   }
-   
-   /**
-    * Create a ProfileDeployment, based on the virtual file.
-    * 
-    * @param vf the deployment root
-    * @return the profile deployment
-    */
-   protected static ProfileDeployment createDeployment(VirtualFile vf)
-   {
-      return deploymentFactory.createDeployment(vf); 
-   }
-   
-   /**
-    * Internally update the lastModified timestamp.
-    */
-   protected void updateLastModfied()
-   {
-      this.lastModified = System.currentTimeMillis();
-   }
-}

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/BasicProfileFactory.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/BasicProfileFactory.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/BasicProfileFactory.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -23,6 +23,7 @@
 
 import java.util.Collection;
 
+import org.jboss.profileservice.config.ProfileServiceConfig;
 import org.jboss.profileservice.profile.metadata.BasicProfileMetaData;
 import org.jboss.profileservice.profile.metadata.FileRepositorySourceConfiguration;
 import org.jboss.profileservice.repository.virtual.AbstractVirtualProfileFactory;
@@ -49,13 +50,16 @@
       };
    }
 
-   @Override
+   public BasicProfileFactory(ProfileServiceConfig config)
+   {
+      super(config);
+   }
+   
    public String[] getTypes()
    {
       return types;
    }
    
-   @Override
    public VirtualDeploymentProfile createProfile(ProfileKey key, BasicProfileMetaData metaData) throws Exception
    {
       if(key == null)

Deleted: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/DelegateProfile.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/DelegateProfile.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/DelegateProfile.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -1,172 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */ 
-package org.jboss.profileservice.profile;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-import org.jboss.profileservice.spi.DeploymentRepository;
-import org.jboss.profileservice.spi.ModificationInfo;
-import org.jboss.profileservice.spi.MutableProfile;
-import org.jboss.profileservice.spi.NoSuchDeploymentException;
-import org.jboss.profileservice.spi.ProfileDeployment;
-import org.jboss.profileservice.spi.ProfileKey;
-
-/**
- * A basic profile implementation, which delegates all the deployment
- * actions a DeploymentRepository.
- * 
- * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
- * @version $Revision$
- */
-public class DelegateProfile implements MutableProfile
-{
-
-   /** The profile key */
-   final private ProfileKey key;
-   
-   /** The repository containing the deployment contents */
-   final private DeploymentRepository repository;
-   
-   /** Is hot deployment checking enabled */
-   private volatile boolean hotdeployEnabled = false;
-
-   public DelegateProfile(DeploymentRepository repository, ProfileKey key)
-   {
-      if(key == null)
-         throw new IllegalArgumentException("Null profile key.");
-      if(repository == null)
-         throw new IllegalArgumentException("Null deployment repository.");
-            
-      this.key = key;
-      this.repository = repository;
-   }
-
-   public void addDeployment(ProfileDeployment d) throws Exception
-   {
-      if(d == null)
-         throw new IllegalArgumentException("Null deployment");
-      this.repository.addDeployment(d.getName(), d);
-   }
-
-   public void enableModifiedDeploymentChecks(boolean flag)
-   {
-      this.hotdeployEnabled = flag;
-   }
-   
-   public ProfileDeployment getDeployment(String name) throws NoSuchDeploymentException
-   {
-      if(name == null)
-         throw new IllegalArgumentException("Null name.");
-      return this.repository.getDeployment(name);
-   }
-
-   public Set<String> getDeploymentNames()
-   {
-      return this.repository.getDeploymentNames();
-   }
-
-   public Collection<ProfileDeployment> getDeployments()
-   {
-      return this.repository.getDeployments();
-   }
-
-   public ProfileKey getKey()
-   {
-      return this.key;
-   }
-
-   public long getLastModified()
-   {
-      return this.repository.getLastModified();
-   }
-
-   public Collection<ModificationInfo> getModifiedDeployments() throws Exception
-   {
-      if(this.hotdeployEnabled == false)
-         return Collections.emptySet();
-      return this.repository.getModifiedDeployments();
-   }
-
-   public boolean hasDeployment(String name)
-   {
-      if(name == null)
-         throw new IllegalArgumentException("Null name.");
-
-      try
-      {
-         return this.repository.getDeployment(name) != null;
-      }
-      catch(Exception e)
-      {
-         return false;
-      }
-   }
-
-   public ProfileDeployment removeDeployment(String name) throws Exception
-   {
-      if(name == null)
-         throw new IllegalArgumentException("Null name.");
-      return this.repository.removeDeployment(name);
-   }
-   
-   public void create() throws Exception
-   {
-      if(this.repository == null)
-         throw new IllegalStateException("Null deployment repository.");
-      // Load
-      this.repository.load();
-   }
-   
-   public void destroy()
-   {
-      this.repository.unload();
-   }
-   
-   public String toString()
-   {
-      StringBuilder builder = new StringBuilder();
-      builder.append(getClass().getSimpleName());
-      builder.append('@').append(Integer.toHexString(System.identityHashCode(this)));
-      builder.append("{key = ").append(getKey());
-      toString(builder);
-      builder.append("}");
-      return builder.toString();
-   }
-   
-   /**
-    * Additional information for toString().
-    * 
-    * @param builder the builder.
-    */
-   protected void toString(StringBuilder builder)
-   {
-      //
-   }
-
-   public boolean isMutable()
-   {
-      return true;
-   }
-}
-

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/ImmutableScanningProfile.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/ImmutableScanningProfile.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/ImmutableScanningProfile.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,56 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.profile;
+
+import org.jboss.logging.Logger;
+import org.jboss.profileservice.spi.ProfileKey;
+import org.jboss.profileservice.spi.VirtualDeploymentRepository;
+
+/**
+ * A immutable scanning profile.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class ImmutableScanningProfile extends AbstractScanningProfile
+{
+ 
+   /** The logger. */
+   private static final Logger log = Logger.getLogger("org.jboss.profileservice.profile");
+   
+   public ImmutableScanningProfile(ProfileKey key, VirtualDeploymentRepository repository)
+   {
+      super(key, repository);
+   }
+   
+   public boolean isMutable()
+   {
+      return false;
+   }
+
+   protected Logger getLog()
+   {
+      return log;
+   }
+   
+}
+

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/MutableScanningProfile.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/MutableScanningProfile.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/MutableScanningProfile.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,251 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.profile;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.jboss.logging.Logger;
+import org.jboss.profileservice.deployment.ProfileDeploymentModificationChecker;
+import org.jboss.profileservice.repository.artifact.file.FileArtifactId;
+import org.jboss.profileservice.spi.ModificationInfo;
+import org.jboss.profileservice.spi.MutableProfile;
+import org.jboss.profileservice.spi.NoSuchDeploymentException;
+import org.jboss.profileservice.spi.ProfileDeployment;
+import org.jboss.profileservice.spi.ProfileKey;
+import org.jboss.profileservice.spi.VirtualDeploymentRepository;
+import org.jboss.profileservice.spi.deployment.ProfileDeploymentFlag;
+import org.jboss.profileservice.spi.deployment.ProfileDeploymentInfo;
+import org.jboss.vfs.VirtualFile;
+
+/**
+ * A mutable scanning profile. 
+ *  
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class MutableScanningProfile extends AbstractScanningProfile implements MutableProfile
+{
+
+   /** The logger. */
+   private static final Logger log = Logger.getLogger("org.jboss.profileservice.profile");
+   
+   /** enable modification checks. */
+   private volatile boolean enableChecks;
+   
+   /** The modification checker delegate. */
+   private ProfileDeploymentModificationChecker modificationChecker;
+   
+   /** The lock. */
+   private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+   
+   public MutableScanningProfile(ProfileKey key, VirtualDeploymentRepository repository)
+   {
+      super(key, repository);
+   }
+
+   public ProfileDeploymentModificationChecker getModificationChecker()
+   {
+      return modificationChecker;
+   }
+   
+   public void setModificationChecker(ProfileDeploymentModificationChecker modificationChecker)
+   {
+      this.modificationChecker = modificationChecker;
+   }
+   
+   /**
+    * Check if a deployment is modified. This needs the {@code ProfileDeployment} and the repository file.
+    * 
+    * NOTE: the repository file is supposed to be the real file, not the one passed to the deployers. Since
+    * the one passed to the deployers could point to temp files.
+    * 
+    * @param deployment the deployment
+    * @param repositoryFile the repository file
+    * @return true if the deployment was modified since the last check
+    */
+   protected boolean isModified(ProfileDeployment deployment, VirtualFile repositoryFile)
+   {
+      return modificationChecker != null && modificationChecker.isDeploymentModified(deployment, repositoryFile);
+   }
+   
+   /**
+    * Is modification checks enabled. This can be used by implementing classes
+    * to override the default behavior. E.g. always disable content modification 
+    * checking, but allowing distributing content using the DeploymentManager.
+    * 
+    * @return true or false
+    */
+   protected boolean isModificationCheckEnabled()
+   {
+      return this.enableChecks;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public void addDeployment(final ProfileDeployment deployment) throws Exception
+   {
+      if(deployment == null)
+      {
+         throw new IllegalArgumentException("null deployment");
+      }
+      lockWrite();
+      try
+      {
+         // Check if the artifact exists
+         final FileArtifactId artifactId = getArtifactMetaData(deployment);
+         getArtifactRepository().getArtifact(artifactId);
+         // 
+         internalAddDeployment(deployment, artifactId);
+      }
+      finally
+      {
+         unlockWrite();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void enableModifiedDeploymentChecks(boolean flag)
+   {
+      this.enableChecks = flag;
+   }
+
+   /**
+    * {@inheritDoc} 
+    */
+   public Collection<ModificationInfo> getModifiedDeployments() throws Exception
+   {
+      if(isModificationCheckEnabled() == false)
+      {
+         return Collections.emptySet();
+      }
+      lockRead();
+      final Map<String, ModificationInfo> modifications = new HashMap<String, ModificationInfo>();
+      try
+      {
+         final long lastModified = System.currentTimeMillis();
+         for(final ProfileDeployment deployment : getDeployments())
+         {
+            final ProfileDeploymentInfo info = deployment.getDeploymentInfo();
+            // Ignore locked deployments
+            if(info.isLocked())
+            {
+               continue;
+            }
+            final String deploymentName = deployment.getName();
+            // Resolve the repository VirtualFile, which has to point to a backup location
+            final FileArtifactId artifactId = getArtifactMetaData(deployment);
+            final VirtualFile repositoryFile = getArtifactRepository().getArtifactFile(artifactId);
+            if(repositoryFile.exists() == false)
+            {
+               internalRemoveDeployment(deploymentName);
+               final ModificationInfo modification = new ModificationInfo(deployment, lastModified, ModificationInfo.ModifyStatus.REMOVED);
+               modifications.put(deploymentName, modification);
+            }
+            else if(info.hasFlag(ProfileDeploymentFlag.MODIFIED) || isModified(deployment, repositoryFile))
+            {
+               final ModificationInfo modification = new ModificationInfo(deployment, lastModified, ModificationInfo.ModifyStatus.MODIFIED);
+               modifications.put(deploymentName, modification);               
+            }
+         }
+         // Scan the repository
+         final Collection<ProfileDeployment> additions = scanRepository();
+         if(additions != null && additions.isEmpty() == false)
+         {
+            for(final ProfileDeployment deployment : additions)
+            {
+               final ModificationInfo modification = new ModificationInfo(deployment, lastModified, ModificationInfo.ModifyStatus.ADDED);
+               modifications.put(deployment.getName(), modification);
+            }
+         }
+         if(modifications.size() > 0)
+         {
+            updateLastModified();
+         }
+      }
+      finally
+      {
+         unlockRead();
+      }
+      return modifications.values();
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public ProfileDeployment removeDeployment(final String name) throws NoSuchDeploymentException, Exception
+   {
+      if(name == null)
+      {
+         throw new IllegalArgumentException("null deployment name");
+      }
+      lockWrite();
+      try
+      {
+         // TODO remove contents here ?
+         return internalRemoveDeployment(name);
+      }
+      finally
+      {
+         unlockWrite();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isMutable()
+   {
+      return true;
+   }
+
+   protected Logger getLog()
+   {
+      return log;
+   }
+   
+   void lockRead()
+   {
+      lock.readLock().lock();
+   }
+   void unlockRead()
+   {
+      lock.readLock().unlock();
+   }
+   
+   void lockWrite()
+   {
+      lock.writeLock().lock();
+   }
+   void unlockWrite()
+   {
+      lock.writeLock().unlock();
+   }
+   
+}
+

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/ScanningProfileFactory.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/ScanningProfileFactory.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/ScanningProfileFactory.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,134 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.profile;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.jboss.profileservice.config.ProfileServiceConfig;
+import org.jboss.profileservice.profile.metadata.plugin.HotDeploymentProfileMetaData;
+import org.jboss.profileservice.profile.metadata.plugin.PropertyProfileMetaData;
+import org.jboss.profileservice.profile.metadata.plugin.PropertyProfileSourceMetaData;
+import org.jboss.profileservice.repository.artifact.AbstractRepositoryId;
+import org.jboss.profileservice.repository.artifact.ArtifactRepositoryManager;
+import org.jboss.profileservice.repository.artifact.file.FileArtifactId;
+import org.jboss.profileservice.repository.artifact.file.FileRepositoryConfiguration;
+import org.jboss.profileservice.repository.virtual.DelegatingDeploymentRepository;
+import org.jboss.profileservice.spi.ProfileFactory;
+import org.jboss.profileservice.spi.ProfileKey;
+import org.jboss.profileservice.spi.VirtualDeploymentRepository;
+import org.jboss.profileservice.spi.repository.ArtifactId;
+import org.jboss.profileservice.spi.repository.ArtifactRepository;
+import org.jboss.profileservice.spi.repository.ArtifactRepositoryConfiguration;
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class ScanningProfileFactory implements ProfileFactory<PropertyProfileMetaData, AbstractScanningProfile>
+{
+
+   /** The types. */
+   private static final String[] types;
+   
+   /** The PS config. */
+   private final ProfileServiceConfig config;
+   
+   /** The artifact repository manager. */
+   private ArtifactRepositoryManager repositoryManager;
+   
+   static
+   {
+      types = new String[] {
+        PropertyProfileMetaData.class.getName(),
+        HotDeploymentProfileMetaData.class.getName()
+      };
+   }
+   
+   public ScanningProfileFactory(ProfileServiceConfig config)
+   {
+      if(config == null)
+      {
+         throw new IllegalArgumentException("null profile service config");
+      }
+      this.config = config;
+   }   
+   
+   public String[] getTypes()
+   {
+      return types;
+   }
+   
+   public ArtifactRepositoryManager getRepositoryManager()
+   {
+      return repositoryManager;
+   }
+   
+   public void setRepositoryManager(ArtifactRepositoryManager repositoryManager)
+   {
+      this.repositoryManager = repositoryManager;
+   }
+   
+   public AbstractScanningProfile createProfile(ProfileKey key, PropertyProfileMetaData metaData) throws Exception
+   {
+      boolean isMutable = metaData.isHotDeploymentEnabled();
+      PropertyProfileSourceMetaData source = metaData.getSource();
+      // 
+      VirtualDeploymentRepository repository = createDeploymentRepository(Integer.toString(key.hashCode()), source, isMutable);
+      if(isMutable)
+      {
+         return new MutableScanningProfile(key, repository);
+      }
+      else
+      {
+         return new ImmutableScanningProfile(key, repository);
+      }
+   }
+
+   protected VirtualDeploymentRepository createDeploymentRepository(String artifactRepoName, PropertyProfileSourceMetaData source, boolean isMutable)
+      throws IOException, URISyntaxException
+   {
+      // Create the file repository, based on the group
+      ArtifactRepository<ArtifactId> fileRepository = repositoryManager.createArtifactRepository(
+            createFileRepositoryId(artifactRepoName),
+            createRepositoryConfiguration(source, isMutable));
+      // Create the virtual deployment repository
+      return new DelegatingDeploymentRepository(getRepositoryManager(), config.getAssemblyConfiguration(),
+            fileRepository.getIdentifier());      
+   }
+   
+   protected AbstractRepositoryId createFileRepositoryId(String group)
+   {
+      return new AbstractRepositoryId(group, FileArtifactId.TYPE);
+   }
+   
+   protected ArtifactRepositoryConfiguration<ArtifactId> createRepositoryConfiguration(PropertyProfileSourceMetaData source, boolean mutable) throws URISyntaxException
+   {
+      FileRepositoryConfiguration configuration = new FileRepositoryConfiguration();
+      configuration.setOverrideURI(new URI(source.getPath()));
+      configuration.setMutable(mutable);
+      return ArtifactRepositoryConfiguration.class.cast(configuration);
+   }
+   
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/bootstrap/BootstrapProfileFactory.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/bootstrap/BootstrapProfileFactory.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/bootstrap/BootstrapProfileFactory.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -23,6 +23,7 @@
 
 import java.util.Collection;
 
+import org.jboss.profileservice.config.ProfileServiceConfig;
 import org.jboss.profileservice.profile.metadata.FileRepositorySourceConfiguration;
 import org.jboss.profileservice.repository.virtual.AbstractVirtualProfileFactory;
 import org.jboss.profileservice.repository.virtual.VirtualDeploymentProfile;
@@ -43,13 +44,16 @@
    /** The types. */
    private static final String[] types = new String[] { BootstrapProfileMetaData.class.getName() };
    
-   @Override
+   public BootstrapProfileFactory(ProfileServiceConfig config)
+   {
+      super(config);
+   }
+   
    public String[] getTypes()
    {
       return types;
    }
 
-   @Override
    public VirtualDeploymentProfile createProfile(ProfileKey key, BootstrapProfileMetaData metaData) throws Exception
    {
       if(key == null)

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/metadata/BasicProfileDeploymentMetaData.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/metadata/BasicProfileDeploymentMetaData.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/metadata/BasicProfileDeploymentMetaData.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -47,6 +47,16 @@
    /** The name. */
    private String name;
    
+   public BasicProfileDeploymentMetaData()
+   {
+      //
+   }
+   
+   public BasicProfileDeploymentMetaData(String name)
+   {
+      this.name = name;
+   }
+   
    @Override
    public List<VirtualArtifactMetaData> getArtifacts()
    {

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/BasicProfileDeployment.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/BasicProfileDeployment.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/BasicProfileDeployment.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -22,6 +22,7 @@
 package org.jboss.profileservice.repository;
 
 import org.jboss.profileservice.deployment.AbstractProfileDeployment;
+import org.jboss.profileservice.spi.virtual.VirtualDeploymentMetaData;
 import org.jboss.vfs.VirtualFile;
 
 /**
@@ -36,14 +37,14 @@
    /** The serialVersionUID */
    private static final long serialVersionUID = -1L;
 
-   public BasicProfileDeployment(String name)
+   public BasicProfileDeployment(String name, VirtualDeploymentMetaData deploymentMetaData)
    {
-      super(name);
+      super(name, deploymentMetaData);
    }
    
-   public BasicProfileDeployment(VirtualFile vf)
+   public BasicProfileDeployment(VirtualFile vf, VirtualDeploymentMetaData deploymentMetaData)
    {
-      this(safeVirtualFileName(vf));
+      this(safeVirtualFileName(vf), deploymentMetaData);
       setRoot(vf);
    }
 

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/ProfileDeploymentFactory.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/ProfileDeploymentFactory.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/ProfileDeploymentFactory.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -22,6 +22,7 @@
 package org.jboss.profileservice.repository;
 
 import org.jboss.profileservice.spi.ProfileDeployment;
+import org.jboss.profileservice.spi.virtual.VirtualDeploymentMetaData;
 import org.jboss.vfs.VirtualFile;
 
 /**
@@ -52,16 +53,16 @@
       {
          throw new IllegalArgumentException("null deployment name");
       }
-      return new BasicProfileDeployment(name);
+      return new BasicProfileDeployment(name, null);
    }
    
-   public ProfileDeployment createDeployment(VirtualFile vf)
+   public ProfileDeployment createDeployment(VirtualFile vf, VirtualDeploymentMetaData metaData)
    {
       if(vf == null)
       {
          throw new IllegalArgumentException("null virtual file");
       }
-      return new BasicProfileDeployment(vf);
+      return new BasicProfileDeployment(vf, metaData);
    }
    
 }

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/AbstractArtifact.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/AbstractArtifact.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/AbstractArtifact.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -56,39 +56,36 @@
       this.repository = repository;
    }
    
-   @Override
    public T getIdentifier()
    {
       return this.identifier;
    }
 
-   @Override
    public long getLastModified()
    {
-      return getFile().getLastModified();
+      try
+      {
+         return getFile().getLastModified();
+      }
+      catch(Exception e)
+      {
+         return 0L;
+      }
    }
    
-   @Override
    public ArtifactRepositoryId getRepository()
    {
       return this.repository.getIdentifier();
    }
    
-   public InputStream getInputStream() throws IOException
+   protected InputStream getInputStream() throws IOException
    {
       return getFile().openStream();
    }
    
-   public VirtualFile getFile()
+   protected VirtualFile getFile() throws IOException
    {
-      try
-      {
-         return this.repository.getArtifactFile(getIdentifier());
-      }
-      catch(IOException ioe) // TODO this is unlikely?
-      {
-         throw new RuntimeException("failed to get file", ioe);
-      }
+      return this.repository.getArtifactFile(getIdentifier());
    }
 
    protected ArtifactRepository<T> getArtifactRepository()

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/AbstractArtifactRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/AbstractArtifactRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/AbstractArtifactRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -54,6 +54,9 @@
    /** The repository root. */
    private final VirtualFile repositoryRoot;
    
+   /** The repository uri. */
+   private final URI repositoryURI; 
+   
    public AbstractArtifactRepository(ArtifactRepositoryId identifier, URI root) throws IOException
    {
       if(identifier == null)
@@ -65,6 +68,7 @@
          throw new IllegalArgumentException("null repository root.");
       }
       this.repositoryRoot = VFS.getChild(root);
+      this.repositoryURI = root;
       this.identifier = identifier;
       this.configuration = new BasicRepositoryConfiguration(root, false);;
    }
@@ -80,30 +84,21 @@
          throw new IllegalArgumentException("null repository root.");
       }
       this.repositoryRoot = root;
+      this.repositoryURI = root.toURI();
       this.identifier = identifier;
       this.configuration = new BasicRepositoryConfiguration(root.toURI(), false);
    }
    
-   public Collection<Artifact<T>> getArtifacts(ArtifactFilter<T> filter)
+   public URI getRepositoryURI()
    {
-      Collection<Artifact<T>> filtered = new ArrayList<Artifact<T>>();
-      for(Artifact<T> artifact : getArtifacts())
-      {
-         if(filter.accepts(artifact))
-         {
-            filtered.add(artifact);
-         }
-      }
-      return filtered;
+      return repositoryURI;
    }
-   
-   @Override
+
    public ArtifactRepositoryId getIdentifier()
    {
       return this.identifier;
    }
-   
-   @Override
+
    public ArtifactRepositoryConfiguration<T> getConfiguration()
    {
       return this.configuration;

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/BasicRepositoryConfiguration.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/BasicRepositoryConfiguration.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/BasicRepositoryConfiguration.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -37,10 +37,10 @@
 {
    
    /** The not found handler. */
-   ArtifactNotFoundHandler<T> notFoundHandler = DefaultNotFoundHandler.getInstance();
+   private ArtifactNotFoundHandler<T> notFoundHandler = DefaultNotFoundHandler.getInstance();
    
    /** The repository location. */
-   private URI location;
+   private final URI location;
    
    /** IsMutable. */
    private final boolean mutable;
@@ -60,6 +60,11 @@
       return location;
    }
    
+   public VFSBackupPolicy getBackupPolicy()
+   {
+      return VFSBackupPolicy.ORIGINAL;
+   }
+   
    public boolean isMutable()
    {
       return mutable;

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/CopyStreamArtifactTransformer.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/CopyStreamArtifactTransformer.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/CopyStreamArtifactTransformer.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,67 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.repository.artifact;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.jboss.profileservice.spi.repository.ArtifactId;
+import org.jboss.profileservice.spi.repository.ArtifactTransformer;
+import org.jboss.vfs.VFSUtils;
+import org.jboss.vfs.VirtualFile;
+
+/**
+ * Copy stream artifact transformer.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class CopyStreamArtifactTransformer implements ArtifactTransformer<ArtifactId>
+{
+
+   /** The instance. */
+   private static final CopyStreamArtifactTransformer INSTANCE = new CopyStreamArtifactTransformer();
+   
+   public static CopyStreamArtifactTransformer getInstance()
+   {
+      return INSTANCE;
+   }
+   
+   public void transform(ArtifactId artifactId, InputStream is, VirtualFile target)
+         throws IOException
+   {
+      File file = target.getPhysicalFile();
+      FileOutputStream os = new FileOutputStream(file);
+      try
+      {
+         VFSUtils.copyStream(is, os);
+      }
+      finally
+      {
+         VFSUtils.safeClose(os);
+      }
+   }
+   
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/DefaultNotFoundHandler.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/DefaultNotFoundHandler.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/DefaultNotFoundHandler.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -45,11 +45,10 @@
       return instance;
    }
    
-   @Override
    public Artifact<T> handleArtifactNotFound(ArtifactRepository<T> repsoitory, T artifactId)
          throws IOException
    {
-      throw new FileNotFoundException("could not find artifact" + artifactId);
+      throw new FileNotFoundException("could not find artifact " + artifactId);
    }
    
 }

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/ExplodedArtifactTransformer.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/ExplodedArtifactTransformer.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/ExplodedArtifactTransformer.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,152 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.repository.artifact;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+import org.jboss.profileservice.spi.repository.ArtifactId;
+import org.jboss.profileservice.spi.repository.ArtifactTransformer;
+import org.jboss.util.file.JarUtils;
+import org.jboss.vfs.VirtualFile;
+
+/**
+ * Exploded artifact transformer.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class ExplodedArtifactTransformer implements ArtifactTransformer<ArtifactId>
+{
+
+   /** The instance. */
+   private static final ExplodedArtifactTransformer INSTANCE = new ExplodedArtifactTransformer();
+   
+   public static ExplodedArtifactTransformer getInstance()
+   {
+      return INSTANCE;
+   }
+   
+   /** The buffer size. */
+   static final int BUFFER_SIZE = 4096;
+   
+   public void transform(ArtifactId artifactId, InputStream is, VirtualFile target)
+         throws IOException
+   {
+      unjar(is, target.getPhysicalFile());
+   }
+
+   /**
+    * Try to unpack an inputStream.
+    * This is a fork of {@link JarUtils#unjar}, but does not close the
+    * InputStream itself, as this is done by the remote deploymentTarget.
+    * 
+    * @param in the InputStream
+    * @param dest the destination file
+    * @throws IOException
+    */
+   static void unjar(InputStream in, File dest) throws IOException
+   {
+      if (!dest.exists())
+      {
+         dest.mkdirs();
+      }
+      if (!dest.isDirectory())
+      {
+         throw new IOException("Destination must be a directory.");
+      }
+      JarInputStream jin = new JarInputStream(in);
+      byte[] buffer = new byte[BUFFER_SIZE];
+      
+      ZipEntry entry = jin.getNextEntry();
+      while (entry != null)
+      {
+         String fileName = entry.getName();
+         if (fileName.charAt(fileName.length() - 1) == '/')
+         {
+            fileName = fileName.substring(0, fileName.length() - 1);
+         }
+         if (fileName.charAt(0) == '/')
+         {
+            fileName = fileName.substring(1);
+         }
+         if (File.separatorChar != '/')
+         {
+            fileName = fileName.replace('/', File.separatorChar);
+         }
+         File file = new File(dest, fileName);
+         if (entry.isDirectory())
+         {
+            // make sure the directory exists
+            file.mkdirs();
+            jin.closeEntry();
+         } 
+         else
+         {
+            // make sure the directory exists
+            File parent = file.getParentFile();
+            if (parent != null && !parent.exists())
+            {
+               parent.mkdirs();
+            }
+            
+            // dump the file
+            OutputStream out = new FileOutputStream(file);
+            int len = 0;
+            while ((len = jin.read(buffer, 0, buffer.length)) != -1)
+            {
+               out.write(buffer, 0, len);
+            }
+            out.flush();
+            out.close();
+            jin.closeEntry();
+            file.setLastModified(entry.getTime());
+         }
+         entry = jin.getNextEntry();
+      }
+      /* Explicity write out the META-INF/MANIFEST.MF so that any headers such
+      as the Class-Path are see for the unpackaged jar
+      */
+      Manifest mf = jin.getManifest();
+      if (mf != null)
+      {
+         File file = new File(dest, "META-INF/MANIFEST.MF");
+         File parent = file.getParentFile();
+         if( parent.exists() == false )
+         {
+            parent.mkdirs();
+         }
+         OutputStream out = new FileOutputStream(file);
+         mf.write(out);
+         out.flush();
+         out.close();
+      }
+   }
+   
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifact.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifact.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifact.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -21,6 +21,8 @@
 */
 package org.jboss.profileservice.repository.artifact.file;
 
+import java.io.IOException;
+
 import org.jboss.profileservice.repository.artifact.AbstractArtifact;
 import org.jboss.profileservice.spi.repository.ArtifactRepository;
 
@@ -43,5 +45,37 @@
       return getIdentifier().getPath();
    }
    
+   /**
+    * Check whether this artifact represents a file or not.
+    * 
+    * TODO is there a better way?
+    * 
+    * @return true if this artifact represents a file, false otherwise
+    */
+   @Deprecated
+   public boolean isFile()
+   {
+      try
+      {
+         return getFile().isFile();
+      }
+      catch(IOException e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+   
+   public String toString()
+   {
+         StringBuilder tmp = new StringBuilder();
+         tmp.append(getClass().getSimpleName());
+         tmp.append('@').append(Integer.toHexString(System.identityHashCode(this)));
+         tmp.append('[');
+         tmp.append("path=");
+         tmp.append(getIdentifier().getPath());
+         tmp.append(']');
+         return tmp.toString();
+   }
+   
 }
 

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifactId.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifactId.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifactId.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -38,7 +38,7 @@
    private static final long serialVersionUID = 5979865973627325317L;
 
    /** An empty artifact. */
-   public final static ArtifactId EMPTY_ARTIFACT = new FileArtifactId();
+   public final static FileArtifactId EMPTY_ARTIFACT = new FileArtifactId();
    
    /** The type. */
    public final static String TYPE = FileArtifactId.class.getName();
@@ -77,5 +77,15 @@
       return TYPE;
    }
    
+   public String toString()
+   {
+         StringBuilder tmp = new StringBuilder();
+         tmp.append(getClass().getSimpleName());
+         tmp.append('[');
+         tmp.append("path=").append(getPath());
+         tmp.append(']');
+         return tmp.toString();
+   }
+   
 }
 

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifactRepositoryFactory.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifactRepositoryFactory.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileArtifactRepositoryFactory.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -25,6 +25,7 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 
+import org.jboss.profileservice.config.ProfileServiceConfig;
 import org.jboss.profileservice.spi.repository.ArtifactRepository;
 import org.jboss.profileservice.spi.repository.ArtifactRepositoryConfiguration;
 import org.jboss.profileservice.spi.repository.ArtifactRepositoryFactory;
@@ -43,13 +44,16 @@
 
    /** The file repository root. */
    private final VirtualFile root;
+
+   /** The profile service config. */
+   private ProfileServiceConfig config;
    
-   public FileArtifactRepositoryFactory(URI rootURI) throws IOException
+   public FileArtifactRepositoryFactory(URI rootURI, ProfileServiceConfig config) throws IOException
    {
       this.root = VFS.getChild(rootURI);
+      this.config = config;
    }
 
-   @Override
    public String getRepositoryType()
    {
       return FileArtifactId.TYPE;
@@ -64,11 +68,13 @@
    {
       if(getRoot().exists() == false)
       {
-         throw new IllegalStateException("non existing root repository " + getRoot().getPathName());
+         throw new IllegalStateException("non existing repository root " + getRoot().getPathName());
       }
    }
 
-   @Override
+   /**
+    * {@inheritDoc}
+    */
    public ArtifactRepository<FileArtifactId> createArtifactRepository(ArtifactRepositoryId repositoryId,
          ArtifactRepositoryConfiguration<FileArtifactId> configuration) throws IOException
    {
@@ -76,17 +82,102 @@
       {
          throw new IllegalArgumentException("null repository id");
       }
-      String name = repositoryId.getName();
-      VirtualFile vf = getRoot().getChild(name);
+      LocalFileArtifactRepository repository = null;
       try
       {
-         return new LocalFileArtifactRepository(repositoryId, vf);
+         final String name = repositoryId.getName();
+         final FileRepositoryConfiguration config = createConfiguration(configuration);
+
+         URI location = config.getOverrideURI();
+         if(location == null)
+         {
+            // The default name.
+            final VirtualFile vf = getRoot().getChild(name);
+            location = vf.asDirectoryURI();
+         }
+         if(config.isMutable())
+         {
+            repository = new MutableFileArtifactRepository(repositoryId, location, config);
+         }
+         else
+         {
+            repository = new LocalFileArtifactRepository(repositoryId, location, config);
+         }
+          
+         // Create the repository as well
+         repository.create();
       }
       catch(URISyntaxException e)
       {
          throw new RuntimeException("failed to create file artifact repository ", e);
       }
+      return repository;
    }
 
+   /**
+    * Create the configuration and merge some predefined suff.
+    * 
+    * @param predefined the predefined configuration
+    * @return the file repository configuration
+    * @throws URISyntaxException
+    */
+   protected FileRepositoryConfiguration createConfiguration(ArtifactRepositoryConfiguration<FileArtifactId> predefined) throws URISyntaxException
+   {
+      FileRepositoryConfiguration configuration = createDefaultConfiguration();
+      if(predefined != null)
+      {
+         // mutable
+         configuration.setMutable(predefined.isMutable());
+         // backup policy
+         if(predefined.getBackupPolicy() != null)
+         {
+            configuration.setBackupPolicy(predefined.getBackupPolicy());
+         }
+         // NotFoundHandler
+         if(predefined.getNotFoundHandler() != null)
+         {
+            configuration.setNotFoundHandler(predefined.getNotFoundHandler());
+         }
+         //
+         if(predefined instanceof FileRepositoryConfiguration)
+         {
+            FileRepositoryConfiguration other = FileRepositoryConfiguration.class.cast(predefined);
+            // Override URI used by the PropertyProfileMetaData
+            if(other.getOverrideURI() != null)
+            {
+               configuration.setOverrideURI(other.getOverrideURI());
+            }
+            // In case it's mutable construct a backup URI
+            if(other.isMutable())
+            {
+               // Create the backup URI
+               if(other.getBackupURI() != null) 
+               {
+                  // Reuse predefined
+                  configuration.setBackupURI(other.getBackupURI());
+               }
+               else 
+               {
+                  // Use default
+                  configuration.setBackupURI(config.getRepositoriesConfiguration().createBackupURI());
+               }
+            }
+            // Mount overrides
+            if(other.getMountOverrides() != null)
+            {
+               configuration.setMountOverrides(other.getMountOverrides());
+            }
+         }
+      }
+      return configuration;
+   }
+   
+   protected FileRepositoryConfiguration createDefaultConfiguration()
+   {
+      FileRepositoryConfiguration configuration = new FileRepositoryConfiguration();
+      configuration.setExcludeFilter(config.getRepositoriesConfiguration().getExcludeFilter());
+      return configuration;
+   }
+   
 }
 

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileRepositoryConfiguration.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileRepositoryConfiguration.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/FileRepositoryConfiguration.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,120 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.repository.artifact.file;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.Map;
+
+import org.jboss.profileservice.repository.artifact.DefaultNotFoundHandler;
+import org.jboss.profileservice.spi.repository.ArtifactNotFoundHandler;
+import org.jboss.profileservice.spi.repository.ArtifactRepositoryConfiguration;
+import org.jboss.vfs.VirtualFileFilter;
+import org.jboss.vfs.util.ExtensibleFilter;
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class FileRepositoryConfiguration implements ArtifactRepositoryConfiguration<FileArtifactId>
+{
+
+   private URI overrideURI;
+   private URI backupURI;
+   private boolean mutable = false;
+   private VirtualFileFilter excludeFilter = new ExtensibleFilter();
+   private VFSBackupPolicy backupPolicy = VFSBackupPolicy.ORIGINAL;
+   private Map<String, URI> mountOverrides = Collections.emptyMap();
+   private ArtifactNotFoundHandler<FileArtifactId> notFoundHandler = DefaultNotFoundHandler.getInstance();
+   
+   public URI getOverrideURI()
+   {
+      return overrideURI;
+   }
+   
+   public void setOverrideURI(URI overrideURI)
+   {
+      this.overrideURI = overrideURI;
+   }
+   
+   public Map<String, URI> getMountOverrides()
+   {
+      return mountOverrides;
+   }
+
+   public void setMountOverrides(Map<String, URI> mountOverrides)
+   {
+      this.mountOverrides = mountOverrides;
+   }
+   
+   public VFSBackupPolicy getBackupPolicy()
+   {
+      return backupPolicy;
+   }
+   
+   public void setBackupPolicy(VFSBackupPolicy backupPolicy)
+   {
+      this.backupPolicy = backupPolicy;
+   }
+   
+   public ArtifactNotFoundHandler<FileArtifactId> getNotFoundHandler()
+   {
+      return notFoundHandler;
+   }
+
+   public void setNotFoundHandler(ArtifactNotFoundHandler<FileArtifactId> notFoundHandler)
+   {
+      this.notFoundHandler = notFoundHandler;
+   }
+
+   public VirtualFileFilter getExcludeFilter()
+   {
+      return excludeFilter;
+   }
+   
+   public void setExcludeFilter(VirtualFileFilter excludeFilter)
+   {
+      this.excludeFilter = excludeFilter;
+   }
+   
+   public URI getBackupURI()
+   {
+      return backupURI;
+   }
+   
+   public void setBackupURI(URI backupURI)
+   {
+      this.backupURI = backupURI;
+   }
+   
+   public boolean isMutable()
+   {
+      return mutable;
+   }
+   
+   public void setMutable(boolean mutable)
+   {
+      this.mutable = mutable;
+   }
+   
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/LocalFileArtifactRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/LocalFileArtifactRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/LocalFileArtifactRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -21,72 +21,287 @@
 */
 package org.jboss.profileservice.repository.artifact.file;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.net.URI;
-import java.net.URISyntaxException;
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
+import java.util.List;
 
-import org.jboss.profileservice.repository.artifact.AbstractArtifactRepository;
+import org.jboss.profileservice.Hack;
 import org.jboss.profileservice.spi.repository.Artifact;
+import org.jboss.profileservice.spi.repository.ArtifactFilter;
+import org.jboss.profileservice.spi.repository.ArtifactRepository;
 import org.jboss.profileservice.spi.repository.ArtifactRepositoryId;
+import org.jboss.profileservice.spi.repository.ArtifactRepositoryConfiguration.VFSBackupPolicy;
+import org.jboss.vfs.VFS;
+import org.jboss.vfs.VFSUtils;
 import org.jboss.vfs.VirtualFile;
+import org.jboss.vfs.util.PathTokenizer;
 
 /**
+ * A local file artifact repository.
+ * 
  * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
  * @version $Revision$
  */
-public class LocalFileArtifactRepository extends AbstractArtifactRepository<FileArtifactId>
+public class LocalFileArtifactRepository implements ArtifactRepository<FileArtifactId>
 {
 
-   public LocalFileArtifactRepository(ArtifactRepositoryId identifier, URI rootURI) throws IOException
+   /** The repository id. */
+   private final ArtifactRepositoryId identifier;
+   
+   /** The repository uri· */
+   private final URI repositoryURI;
+
+   /** The repository configuration. */
+   private final FileRepositoryConfiguration configuration;
+   
+   /** The repository root. */
+   // Note: this can be a backup location as well
+   private VirtualFile repositoryRoot;
+
+   /** The closable mount, for backup locations. */
+   private Closeable mount;
+
+   public LocalFileArtifactRepository(ArtifactRepositoryId identifier, URI repositoryURI, FileRepositoryConfiguration configuration)
    {
-      super(identifier, rootURI);
+      if(identifier == null)
+      {
+         throw new IllegalArgumentException("null repository id");
+      }
+      if(repositoryURI == null)
+      {
+         throw new IllegalArgumentException("null repository uri");
+      }
+      if(configuration == null)
+      {
+         throw new IllegalArgumentException("null repository configuration");
+      }
+      this.identifier = identifier;
+      this.repositoryURI = repositoryURI;
+      this.configuration = configuration;
    }
    
-   public LocalFileArtifactRepository(ArtifactRepositoryId identifier, VirtualFile root) throws IOException, URISyntaxException
+   /**
+    * Create the repository. NOTE artifact repositories are not
+    * installed as MCBean, so this method has to be called manually.
+    * 
+    * @throws IOException
+    */
+   public void create() throws IOException
    {
-      super(identifier, root);
+      VirtualFile originalLocation = VFS.getChild(getRepositoryURI());
+      if(originalLocation.isDirectory() == false)
+      {
+         // TODO
+         if(Hack.checkHack())
+            throw new IOException(originalLocation + " is not a directory");
+      }
+      // In case we only use backups we need to remount
+      if(getConfiguration().getBackupPolicy() == VFSBackupPolicy.BACKUP)
+      {
+         VirtualFile backupLocation = VFS.getChild(getConfiguration().getBackupURI());
+         this.mount = VFS.mountReal(originalLocation.getPhysicalFile(), backupLocation);
+         // The root is not different from the original URI
+         this.repositoryRoot = backupLocation;
+      }
+      else
+      {
+         this.repositoryRoot = originalLocation;
+      }
    }
    
-   @Override
+   public void destroy()
+   {
+      VFSUtils.safeClose(this.mount);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public FileRepositoryConfiguration getConfiguration()
+   {
+      return this.configuration;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ArtifactRepositoryId getIdentifier()
+   {
+      return this.identifier;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public URI getRepositoryURI()
+   {
+      return this.repositoryURI;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
    public boolean containsArtifact(FileArtifactId artifact)
    {
+      validateArtifactID(artifact);
       VirtualFile vf = getRepositoryRoot().getChild(artifact.getPath());
       return vf != null ? vf.exists() : false;
    }
    
-   @Override
+   /**
+    * {@inheritDoc}
+    */
    public FileArtifact getArtifact(FileArtifactId artifactId)
    {
+      validateArtifactID(artifactId);
       return new FileArtifact(artifactId, this);
    }
    
-   @Override
+   /**
+    * {@inheritDoc}
+    */
    public Collection<Artifact<FileArtifactId>> getArtifacts()
    {
-      return Collections.emptySet();
+      List<Artifact<FileArtifactId>> artifacts = new ArrayList<Artifact<FileArtifactId>>();
+      getArtifacts(getRepositoryRoot(), artifacts, true);
+      return artifacts;
    }
    
-   @Override
-   public VirtualFile getArtifactFile(FileArtifactId artifact) throws IOException
+   /**
+    * {@inheritDoc}
+    */
+   public Collection<Artifact<FileArtifactId>> getArtifacts(ArtifactFilter<FileArtifactId> filter)
    {
-      if(artifact == null)
+      List<Artifact<FileArtifactId>> artifacts = new ArrayList<Artifact<FileArtifactId>>();
+      getArtifacts(getRepositoryRoot(), artifacts, filter);
+      return artifacts;
+   }
+
+   /**
+    * Get all artifacts based on the repository root. This will only include files.
+    * 
+    * @param vf the root
+    * @param artifacts the artifacts
+    * @param recurse flag whether to recurse into directories or not
+    */
+   protected void getArtifacts(VirtualFile vf, List<Artifact<FileArtifactId>> artifacts, final boolean recurse)
+   {
+      getArtifacts(vf, artifacts, new ArtifactFilter<FileArtifactId>()
       {
-         throw new IllegalArgumentException("null artifact");
-      }
-      if(artifact.getPath() == null)
+         public boolean accepts(Artifact<FileArtifactId> artifact)
+         {
+            return true;
+         }
+         public boolean recurse(Artifact<FileArtifactId> artifact)
+         {
+            return recurse;
+         }
+      });
+   }
+
+   /**
+    * Get the filtered artifacts based on the root. 
+    * 
+    * @param vf a directory
+    * @param artifacts the artifacts
+    * @param artifactFilter the artifact filter
+    */
+   protected void getArtifacts(VirtualFile vf, List<Artifact<FileArtifactId>> artifacts, ArtifactFilter<FileArtifactId> artifactFilter)
+   {
+      for(VirtualFile child : vf.getChildren())
       {
-         throw new IllegalArgumentException("null artifact path");
+         if(getConfiguration().getExcludeFilter().accepts(child))
+         {
+            String path = child.getPathNameRelativeTo(getRepositoryRoot());
+            FileArtifact artifact = new FileArtifact(new FileArtifactId(path), this);
+            if(artifactFilter.accepts(artifact))
+            {
+               artifacts.add(artifact);            
+            }
+            if(child.isDirectory() && artifactFilter.recurse(artifact))
+            {
+               getArtifacts(child, artifacts, artifactFilter);
+            }
+         }
       }
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public VirtualFile getArtifactFile(FileArtifactId artifact) throws IOException
+   {
+      validateArtifactID(artifact);
       VirtualFile vf = getRepositoryRoot().getChild(artifact.getPath());
-      if(vf == null) // vf.exists()
+      if(vf.exists() == false)
       {
-         getConfiguration().getNotFoundHandler().handleArtifactNotFound(this, artifact);
+         if(Hack.checkHack())
+            getConfiguration().getNotFoundHandler().handleArtifactNotFound(this, artifact);
       }
       return vf;
    }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public VirtualFile getOriginalFile(FileArtifactId artifactId) throws IOException
+   {
+      if(containsArtifact(artifactId) == false)
+      {
+         if(Hack.checkHack())
+            getConfiguration().getNotFoundHandler().handleArtifactNotFound(this, artifactId);         
+      }
+      if(getConfiguration().getBackupPolicy() == VFSBackupPolicy.BACKUP)
+      {
+         VirtualFile repositoryRoot = VFS.getChild(getRepositoryURI());
+         Artifact<FileArtifactId> artifact = getArtifact(artifactId);
+         return repositoryRoot.getChild(artifact.getRelativePath());
+      }
+      else
+      {
+         return getArtifactFile(artifactId);
+      }
+   }
 
+   /**
+    * Validate the artifactId. this checks for not null and that it does not
+    * contain reverse tokens.
+    * 
+    * @param artifactId the artifact id to check
+    */
+   protected void validateArtifactID(FileArtifactId artifactId)
+   {
+      if(artifactId == null)
+      {
+         throw new IllegalStateException("null artifact id");
+      }
+      String pathString = artifactId.getPath();
+      List<String> tokens = PathTokenizer.getTokens(pathString);
+      // TODO better check, we just need to make sure that artifacts are always relative and inside our root 
+      for(String token : tokens)
+      {
+         if(PathTokenizer.isReverseToken(token))
+         {
+            throw new IllegalStateException("Illegal artifact path, no reverse tokens allowed " + pathString);
+         }
+      }
+   }
    
+   /**
+    * Get the repository root.
+    * 
+    * NOTE this can be a different VF than the repositoryURI, in
+    * case it uses a backup location.
+    * 
+    * @return the repository root
+    */
+   protected VirtualFile getRepositoryRoot()
+   {
+      return this.repositoryRoot;
+   }
+   
 }
 

Added: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/MutableFileArtifactRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/MutableFileArtifactRepository.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/file/MutableFileArtifactRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,207 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.repository.artifact.file;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Collection;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.jboss.logging.Logger;
+import org.jboss.profileservice.spi.repository.Artifact;
+import org.jboss.profileservice.spi.repository.ArtifactFilter;
+import org.jboss.profileservice.spi.repository.ArtifactRepositoryId;
+import org.jboss.profileservice.spi.repository.ArtifactTransformer;
+import org.jboss.profileservice.spi.repository.MutableArtifactRepository;
+import org.jboss.profileservice.spi.repository.ArtifactRepositoryConfiguration.VFSBackupPolicy;
+import org.jboss.vfs.VFSUtils;
+import org.jboss.vfs.VirtualFile;
+
+/**
+ * The mutable file artifact repository.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class MutableFileArtifactRepository extends LocalFileArtifactRepository implements MutableArtifactRepository<FileArtifactId>
+{
+
+   /** The logger. */
+   private static Logger log = Logger.getLogger("org.jboss.profileservice.repository.file");
+   
+   /** The lock. */
+   private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+   
+   public MutableFileArtifactRepository(ArtifactRepositoryId identifier, URI rootURI, FileRepositoryConfiguration configuration)
+   {
+      super(identifier, rootURI, configuration);
+   }
+   
+   public void create() throws IOException
+   {
+      super.create();
+      // TODO
+      if(getConfiguration().getBackupPolicy() != VFSBackupPolicy.BACKUP)
+      {
+         log.warn("using a mutable repository without backing up real files will most likely lead to unexpected behavior.");
+      }
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public void addArtifact(FileArtifactId artifactId, InputStream is,
+         ArtifactTransformer<FileArtifactId> transformer) throws IOException
+   {
+      if(artifactId == null)
+      {
+         throw new IllegalArgumentException("null artifact");
+      }
+      if(is == null)
+      {
+         throw new IllegalArgumentException("null input stream");
+      }
+      if(transformer == null)
+      {
+         throw new IllegalArgumentException("null artifact transformer");
+      }
+      VirtualFile target = getArtifactFile(artifactId);
+      lockWrite();
+      try
+      {
+         transformer.transform(artifactId, is, target);
+      }
+      finally
+      {
+         unlockWrite();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public FileArtifact getArtifact(FileArtifactId artifactId)
+   {
+      lockRead();
+      try
+      {
+         return super.getArtifact(artifactId);
+      }
+      finally
+      {
+         unlockRead();
+      }
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public Collection<Artifact<FileArtifactId>> getArtifacts()
+   {
+      lockRead();
+      try
+      {
+         return super.getArtifacts();
+      }
+      finally
+      {
+         unlockRead();
+      }
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public Collection<Artifact<FileArtifactId>> getArtifacts(ArtifactFilter<FileArtifactId> filter)
+   {
+      lockRead();
+      try
+      {
+         return super.getArtifacts(filter);
+      }
+      finally
+      {
+         unlockRead();
+      }
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public VirtualFile getArtifactFile(FileArtifactId artifact) throws IOException
+   {
+      lockRead();
+      try
+      {
+         return super.getArtifactFile(artifact);
+      }
+      finally
+      {
+         unlockRead();
+      }
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public void removeArtifact(FileArtifactId artifactId) throws IOException
+   {
+      VirtualFile vf = getArtifactFile(artifactId);
+      if(vf == null || vf.exists() == false)
+      {
+         return;
+      }
+      lockWrite();
+      try
+      {
+         if(VFSUtils.recursiveDelete(vf) == false)
+         {
+            throw new IOException("Failed to delete " + vf);
+         }
+      }
+      finally
+      {
+         unlockWrite();
+      }
+   }
+
+   void lockRead()
+   {
+      lock.readLock().lock();
+   }
+   void unlockRead()
+   {
+      lock.readLock().unlock();
+   }
+   
+   void lockWrite()
+   {
+      lock.writeLock().lock();
+   }
+   void unlockWrite()
+   {
+      lock.writeLock().unlock();
+   }
+   
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/maven/LocalMavenArtifactRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/maven/LocalMavenArtifactRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/artifact/maven/LocalMavenArtifactRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -75,19 +75,16 @@
       initialize();
    }
    
-   @Override
    public boolean containsArtifact(MavenArtifactId artifactId)
    {
       return resolveArtifact(artifactId) != null;
    }
    
-   @Override
    public Artifact<MavenArtifactId> getArtifact(MavenArtifactId artifactId)
    {
       return resolveArtifact(artifactId);
    }
    
-   @Override
    public Collection<Artifact<MavenArtifactId>> getArtifacts()
    {
       Collection<Artifact<MavenArtifactId>> artifacts = new ArrayList<Artifact<MavenArtifactId>>();
@@ -111,7 +108,6 @@
       return filtered;
    }
    
-   @Override
    public VirtualFile getArtifactFile(MavenArtifactId artifactId) throws IOException
    {
       MavenArtifact artifact = resolveArtifact(artifactId);
@@ -122,6 +118,12 @@
       return resolveArtifactFile(artifact.getIdentifier());
    }
    
+   public VirtualFile getOriginalFile(MavenArtifactId artifact) throws IOException
+   {
+      // We don't support VFSBackupPolicy.BACKUP
+      return getArtifactFile(artifact);
+   }
+   
    protected MavenArtifact resolveArtifact(MavenArtifactId artifactId)
    {
       for(MavenArtifact artifact : artifacts)
@@ -138,14 +140,12 @@
     * Override create artifact repository to only return
     * this instance of a local maven repository.
     */
-   @Override
    public ArtifactRepository<MavenArtifactId> createArtifactRepository(ArtifactRepositoryId repositoryId,
          ArtifactRepositoryConfiguration<MavenArtifactId> configuration) throws IOException
    {
       return this;
    }
    
-   @Override
    public String getRepositoryType()
    {
       return MavenArtifactId.TYPE;

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractDeploymentRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractDeploymentRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractDeploymentRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -31,7 +31,6 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.jboss.logging.Logger;
-import org.jboss.profileservice.profile.AbstractVFSProfileSource;
 import org.jboss.profileservice.spi.DeploymentContentFlags;
 import org.jboss.profileservice.spi.DeploymentRepository;
 import org.jboss.profileservice.spi.NoSuchDeploymentException;

Copied: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractImmutableProfile.java (from rev 101460, projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractImmutableProfile.java)
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractImmutableProfile.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractImmutableProfile.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */ 
+package org.jboss.profileservice.repository.legacy;
+
+import java.net.URI;
+import java.util.List;
+
+import org.jboss.logging.Logger;
+import org.jboss.profileservice.spi.NoSuchDeploymentException;
+import org.jboss.profileservice.spi.Profile;
+import org.jboss.profileservice.spi.ProfileDeployment;
+import org.jboss.profileservice.spi.ProfileKey;
+import org.jboss.vfs.VirtualFile;
+
+/**
+ * A immutable vfs based profile.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class AbstractImmutableProfile extends AbstractVFSProfileSource implements Profile
+{
+
+   /** The profile key. */
+   private ProfileKey key;
+  
+   /** The logger. */
+   private static final Logger log = Logger.getLogger(AbstractImmutableProfile.class);
+   
+   public AbstractImmutableProfile(ProfileKey key, URI[] uris)
+   {
+      super(uris);
+      //
+      if(key == null)
+         throw new IllegalArgumentException("Null profile key.");
+      
+      this.key = key;
+   }
+   
+   public void create() throws Exception
+   {
+      for(URI uri : getRepositoryURIs())
+      {
+         VirtualFile root = getCachedVirtualFile(uri);
+         loadApplications(root);
+      }
+      updateLastModfied();
+   }
+   
+   public ProfileKey getKey()
+   {
+      return this.key;
+   }
+   
+   @Override
+   public ProfileDeployment getDeployment(String vfsPath) throws NoSuchDeploymentException
+   {
+      if(vfsPath == null)
+         throw new IllegalArgumentException("Null name");
+      
+      ProfileDeployment ctx = super.getDeployment(vfsPath);
+      if(ctx == null)
+      {
+         List<String> names = findDeploymentContent(vfsPath);
+         if(names.size() == 1)
+         {
+            ctx = super.getDeployment(names.get(0));
+         }
+         else if(names.size() > 1)
+         {
+            throw new NoSuchDeploymentException("Multiple deployments found for: "+ vfsPath +", available: " + names);            
+         }
+      }
+      if(ctx == null)
+      {
+         log.debug("Failed to find application for: "+vfsPath+", available: " + getDeploymentNames());
+         throw new NoSuchDeploymentException("Failed to find deployment in file: " + vfsPath);
+      }
+      return ctx;
+   }
+
+   public boolean hasDeployment(String name)
+   {
+      if(name == null)
+         throw new IllegalArgumentException("Null name.");
+
+      try
+      {
+         return super.getDeployment(name) != null;
+      }
+      catch(Exception e)
+      {
+         return false;
+      }
+   }
+
+   public boolean isMutable()
+   {
+      return false;
+   }
+   
+   public String toString()
+   {
+      StringBuilder builder = new StringBuilder();
+      builder.append(getClass().getSimpleName());
+      builder.append('@').append(Integer.toHexString(System.identityHashCode(this)));
+      builder.append("{key = ").append(getKey());
+      toString(builder);
+      builder.append("}");
+      return builder.toString();
+   }
+   
+   /**
+    * Additional information for toString().
+    * 
+    * @param builder the builder.
+    */
+   protected void toString(StringBuilder builder)
+   {
+      //
+   }
+
+}

Copied: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractVFSProfileSource.java (from rev 101822, projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/AbstractVFSProfileSource.java)
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractVFSProfileSource.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/AbstractVFSProfileSource.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,380 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */ 
+package org.jboss.profileservice.repository.legacy;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.jboss.logging.Logger;
+import org.jboss.profileservice.repository.ProfileDeploymentFactory;
+import org.jboss.profileservice.spi.NoSuchDeploymentException;
+import org.jboss.profileservice.spi.NoSuchProfileException;
+import org.jboss.profileservice.spi.ProfileDeployment;
+import org.jboss.vfs.VFS;
+import org.jboss.vfs.VirtualFile;
+import org.jboss.vfs.VirtualFileFilter;
+
+/**
+ * A abstract VFS based source for profile deployments.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public abstract class AbstractVFSProfileSource
+{
+   
+   /** The repository uris. */
+   protected final Collection<URI> uris;
+
+   /** The VFSDeployments. */
+   private Map<String, ProfileDeployment> applicationCtxs = new ConcurrentHashMap<String, ProfileDeployment>();
+   
+   /** Allowed deployments filter. */
+   private VirtualFileFilter deploymentFilter;
+   
+   /** The application files keyed by VirtualFile URI string. */
+   private final Map<String, VirtualFile> applicationVFCache = new ConcurrentHashMap<String, VirtualFile>();
+   
+   /** Do a recursive search - default == true. */
+   private boolean recursiveScan = true;
+
+   /** The last time the profile was modified. */
+   private volatile long lastModified;
+   
+   /** The logger. */
+   private final static Logger log = Logger.getLogger(AbstractVFSProfileSource.class);
+   
+   /** The deployment factory. */
+   private final static ProfileDeploymentFactory deploymentFactory = ProfileDeploymentFactory.getInstance();
+   
+   public AbstractVFSProfileSource(URI[] uris)
+   {
+      if(uris == null)
+         throw new IllegalArgumentException("Null uris");
+      
+      this.uris = new ArrayList<URI>();
+      for(URI uri : uris)
+      {
+         this.uris.add(uri);
+      }
+   }
+
+   public VirtualFileFilter getDeploymentFilter()
+   {
+      return deploymentFilter;
+   }
+   
+   public void setDeploymentFilter(VirtualFileFilter deploymentFilter)
+   {
+      this.deploymentFilter = deploymentFilter;
+   }
+   
+   public boolean isRecursiveScan()
+   {
+      return recursiveScan;
+   }
+   
+   public void setRecursiveScan(boolean recursiveScan)
+   {
+      this.recursiveScan = recursiveScan;
+   }
+   
+   public URI[] getRepositoryURIs()
+   {
+      return uris.toArray(new URI[uris.size()]);
+   }
+   
+   public Set<String> getDeploymentNames()
+   {
+      return this.applicationCtxs.keySet();
+   }
+
+   public Collection<ProfileDeployment> getDeployments()
+   {
+      return this.applicationCtxs.values();
+   }
+   
+   public long getLastModified()
+   {
+      return this.lastModified;
+   }
+   
+   public void destroy()
+   {
+      // Unload
+      this.applicationCtxs.clear();
+      this.applicationVFCache.clear();
+      updateLastModfied();
+   }
+   
+   /**
+    * Add a deployment to this profile source. 
+    * 
+    * @param d the deployment
+    * @throws IllegalArgumentException for a null deployment
+    */
+   protected void addDeployment(ProfileDeployment d)
+   {
+      if(d == null)
+         throw new IllegalArgumentException("null deployment");
+      
+      // Add deployment and vfs
+      this.applicationCtxs.put(d.getName(), d);
+      if(d.getRoot() != null)
+         this.applicationVFCache.put(d.getName(), d.getRoot());
+      updateLastModfied();
+   }
+   
+   /**
+    * Get the deployment
+    * 
+    * @param vfsPath the deployment
+    * @return the deployment or null if it does not exist
+    */
+   protected ProfileDeployment getDeployment(String vfsPath) throws NoSuchDeploymentException
+   {
+      if(vfsPath == null)
+         throw new IllegalArgumentException("Null vfsPath");
+
+      return this.applicationCtxs.get(vfsPath);
+   }
+   
+   /**
+    * Remove a deployment from this source.
+    * 
+    * @param vfsPath the deployment name
+    * @return the deployment
+    * @throws NoSuchProfileException if the deployment does not exist
+    */
+   public ProfileDeployment removeDeployment(String vfsPath) throws Exception
+   {
+      if(vfsPath == null)
+         throw new IllegalArgumentException("Null vfsPath");
+      
+      // Get the deployment
+      ProfileDeployment deployment = getDeployment(vfsPath);
+      // Remove the entries
+      this.applicationCtxs.remove(deployment.getName());
+      this.applicationVFCache.remove(deployment.getName());
+      // Update last modified
+      updateLastModfied();
+      // Return
+      return deployment;
+   }
+   
+   /**
+    * Load all the applications under the applicationDir.
+    * 
+    * @param applicationDir the application directory
+    * @throws IOException
+    */
+   protected void loadApplications(VirtualFile applicationDir) throws Exception
+   {
+      ArrayList<VirtualFile> added = new ArrayList<VirtualFile>();
+      addedDeployment(added, applicationDir);
+      for (VirtualFile vf : added)
+      {
+         ProfileDeployment vfCtx = createDeployment(vf);
+         addDeployment(vfCtx);
+      }
+   }
+   
+   /**
+    * Scan the children of the root for deployments.
+    * 
+    * @param list a list of virtual files, where new deployments are added to
+    * @param root the root to scan
+    * @throws IOException
+    * @throws URISyntaxException
+    */
+   protected void addedDeployments(List<VirtualFile> list, VirtualFile root) throws IOException, URISyntaxException
+   {
+      if(root.isFile())
+      {
+         addedDeployment(list, root);
+      }
+      else
+      {
+         List<VirtualFile> components = root.getChildren();
+         for (VirtualFile component : components)
+         {
+            addedDeployment(list, component);
+         }         
+      }
+   }
+   
+   /**
+    * Scan a given virtualFile for deployments.
+    * 
+    * @param list a list of virtual files, where new deployments are added to
+    * @param component the root file
+    * @throws IOException
+    * @throws URISyntaxException
+    */
+   protected void addedDeployment(List<VirtualFile> list, VirtualFile component) throws IOException, URISyntaxException
+   {
+      // Excluding files from scanning
+      if(deploymentFilter != null && this.deploymentFilter.accepts(component) == false)
+      {
+         if(log.isTraceEnabled())
+            log.trace("ignoring "+ component);
+         return;
+      }
+      
+      // Check if we accept this deployment
+      String key = component.asFileURI().toString();
+      if(acceptsDeployment(key) == false)
+         return;
+
+      // If it's a directory or exploded deployment
+      if(component.isFile() == false)
+      {
+         // Check the name
+         if(isRecursiveScan() && component.getName().indexOf('.') == -1)
+         {
+            // recurse if not '.' in name and recursive search is enabled
+            addedDeployments(list, component);            
+         }
+         else
+         {
+            list.add(component);
+         }
+      }
+      else
+      {
+         list.add(component);
+      }
+   }
+   
+   /**
+    * Check if the deployment should be added.
+    * 
+    * @param name the deployment name
+    * @return  
+    */
+   protected boolean acceptsDeployment(String name)
+   {
+      return applicationCtxs.containsKey(name) == false;
+   }
+   
+   /**
+    * Try to find a deployment, based on the cached
+    * virtual roots of deployments we have.
+    * 
+    * @param name the deployment name
+    * @return a collection of matching names
+    */
+   protected List<String> findDeploymentContent(String name)
+   {
+      if(this.applicationVFCache.containsKey(name))
+      {
+         return Collections.singletonList(name);
+      }
+      
+      List<String> contents = new ArrayList<String>();
+      for(String cacheName : this.applicationVFCache.keySet())
+      {
+         String fixedName = cacheName;
+         if(cacheName.endsWith("/"))
+            fixedName = cacheName.substring(0, cacheName.length() -1);
+         
+         if(fixedName.endsWith(name))
+         {
+            contents.add(cacheName);
+         }
+      }
+      return contents;
+   }
+   
+   /**
+    * Add a virtualFile to the local virtualFileCache
+    * 
+    * @param vf the virtual file
+    * @return the name
+    * @throws MalformedURLException
+    * @throws URISyntaxException
+    */
+   protected String addVirtualFileCache(VirtualFile vf) throws MalformedURLException, URISyntaxException
+   {
+      String uri = vf.asFileURI().toString();
+      this.applicationVFCache.put(uri, vf);
+      return uri;
+   }
+
+   /**
+    * Get a cached virtual file.
+    * 
+    * @param name the name
+    * @return the virtual file or null, if it does not exist
+    */
+   protected VirtualFile getCachedVirtualFile(String name)
+   {
+      return this.applicationVFCache.get(name);
+   }
+   
+   /**
+    * Get a cached virtual file. This will add the uri to the
+    * virtualFile if it does not exist.
+    * 
+    * @param uri the uri
+    * @return the virtual file
+    * @throws IOException
+    */
+   protected VirtualFile getCachedVirtualFile(URI uri) throws IOException 
+   {
+      VirtualFile vf = getCachedVirtualFile(uri.toString());
+      if(vf == null)
+      {
+         vf = VFS.getChild(uri);
+         this.applicationVFCache.put(uri.toString(), vf);
+      }
+      return vf;
+   }
+   
+   /**
+    * Create a ProfileDeployment, based on the virtual file.
+    * 
+    * @param vf the deployment root
+    * @return the profile deployment
+    */
+   protected static ProfileDeployment createDeployment(VirtualFile vf)
+   {
+      return deploymentFactory.createDeployment(vf, null); 
+   }
+   
+   /**
+    * Internally update the lastModified timestamp.
+    */
+   protected void updateLastModfied()
+   {
+      this.lastModified = System.currentTimeMillis();
+   }
+}

Copied: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/DelegateProfile.java (from rev 101460, projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/profile/DelegateProfile.java)
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/DelegateProfile.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/legacy/DelegateProfile.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,172 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */ 
+package org.jboss.profileservice.repository.legacy;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.jboss.profileservice.spi.DeploymentRepository;
+import org.jboss.profileservice.spi.ModificationInfo;
+import org.jboss.profileservice.spi.MutableProfile;
+import org.jboss.profileservice.spi.NoSuchDeploymentException;
+import org.jboss.profileservice.spi.ProfileDeployment;
+import org.jboss.profileservice.spi.ProfileKey;
+
+/**
+ * A basic profile implementation, which delegates all the deployment
+ * actions a DeploymentRepository.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class DelegateProfile implements MutableProfile
+{
+
+   /** The profile key */
+   final private ProfileKey key;
+   
+   /** The repository containing the deployment contents */
+   final private DeploymentRepository repository;
+   
+   /** Is hot deployment checking enabled */
+   private volatile boolean hotdeployEnabled = false;
+
+   public DelegateProfile(DeploymentRepository repository, ProfileKey key)
+   {
+      if(key == null)
+         throw new IllegalArgumentException("Null profile key.");
+      if(repository == null)
+         throw new IllegalArgumentException("Null deployment repository.");
+            
+      this.key = key;
+      this.repository = repository;
+   }
+
+   public void addDeployment(ProfileDeployment d) throws Exception
+   {
+      if(d == null)
+         throw new IllegalArgumentException("Null deployment");
+      this.repository.addDeployment(d.getName(), d);
+   }
+
+   public void enableModifiedDeploymentChecks(boolean flag)
+   {
+      this.hotdeployEnabled = flag;
+   }
+   
+   public ProfileDeployment getDeployment(String name) throws NoSuchDeploymentException
+   {
+      if(name == null)
+         throw new IllegalArgumentException("Null name.");
+      return this.repository.getDeployment(name);
+   }
+
+   public Set<String> getDeploymentNames()
+   {
+      return this.repository.getDeploymentNames();
+   }
+
+   public Collection<ProfileDeployment> getDeployments()
+   {
+      return this.repository.getDeployments();
+   }
+
+   public ProfileKey getKey()
+   {
+      return this.key;
+   }
+
+   public long getLastModified()
+   {
+      return this.repository.getLastModified();
+   }
+
+   public Collection<ModificationInfo> getModifiedDeployments() throws Exception
+   {
+      if(this.hotdeployEnabled == false)
+         return Collections.emptySet();
+      return this.repository.getModifiedDeployments();
+   }
+
+   public boolean hasDeployment(String name)
+   {
+      if(name == null)
+         throw new IllegalArgumentException("Null name.");
+
+      try
+      {
+         return this.repository.getDeployment(name) != null;
+      }
+      catch(Exception e)
+      {
+         return false;
+      }
+   }
+
+   public ProfileDeployment removeDeployment(String name) throws Exception
+   {
+      if(name == null)
+         throw new IllegalArgumentException("Null name.");
+      return this.repository.removeDeployment(name);
+   }
+   
+   public void create() throws Exception
+   {
+      if(this.repository == null)
+         throw new IllegalStateException("Null deployment repository.");
+      // Load
+      this.repository.load();
+   }
+   
+   public void destroy()
+   {
+      this.repository.unload();
+   }
+   
+   public String toString()
+   {
+      StringBuilder builder = new StringBuilder();
+      builder.append(getClass().getSimpleName());
+      builder.append('@').append(Integer.toHexString(System.identityHashCode(this)));
+      builder.append("{key = ").append(getKey());
+      toString(builder);
+      builder.append("}");
+      return builder.toString();
+   }
+   
+   /**
+    * Additional information for toString().
+    * 
+    * @param builder the builder.
+    */
+   protected void toString(StringBuilder builder)
+   {
+      //
+   }
+
+   public boolean isMutable()
+   {
+      return true;
+   }
+}
+

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/AbstractVirtualDeploymentRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/AbstractVirtualDeploymentRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/AbstractVirtualDeploymentRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -64,18 +64,19 @@
       {
          throw new IllegalStateException("Assembled null virtual file");
       }
-      ProfileDeployment profileDeployment = deploymentFactory.createDeployment(vf);
+      ProfileDeployment profileDeployment = deploymentFactory.createDeployment(vf, deployment);
       profileDeployment.getTransientAttachments().putAttachment(VirtualDeploymentAssemblyContext.class.getName(), ctx);
       return profileDeployment;
    }
 
    /**
-    * {@inheritDoc}
+    * {@inheritDoc} 
     */
    @Override
-   protected VirtualFile getVirtualFile(ArtifactId artifact) throws IOException
+   protected VirtualFile getOriginalVirtualFile(ArtifactId artifactId) throws IOException
    {
-      return resolveRepository(artifact).getArtifactFile(artifact);
+      // return the original
+      return resolveRepository(artifactId).getOriginalFile(artifactId);
    }
 
    /**

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/AbstractVirtualProfileFactory.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/AbstractVirtualProfileFactory.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/AbstractVirtualProfileFactory.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -22,7 +22,10 @@
 package org.jboss.profileservice.repository.virtual;
 
 import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
 
+import org.jboss.profileservice.config.ProfileServiceConfig;
 import org.jboss.profileservice.profile.metadata.FileRepositorySourceConfiguration;
 import org.jboss.profileservice.repository.artifact.AbstractRepositoryId;
 import org.jboss.profileservice.repository.artifact.ArtifactRepositoryManager;
@@ -45,15 +48,27 @@
 public class AbstractVirtualProfileFactory
 {
 
-   /** The artifact repository manager. */
-   private ArtifactRepositoryManager repositoryManager;
-   
    /** The maven artifact repository id. */
    protected static final ArtifactRepositoryId MVN_ID = LocalMavenArtifactRepository.REPOSITORY_ID;
    
    /** A unconfigured virtual repository instance. */
    protected final static VirtualDeploymentRepository UNCONFIGURED;
+
+   /** The PS config. */
+   private final ProfileServiceConfig config;
    
+   /** The artifact repository manager. */
+   private ArtifactRepositoryManager repositoryManager;
+   
+   public AbstractVirtualProfileFactory(ProfileServiceConfig config)
+   {
+      if(config == null)
+      {
+         throw new IllegalArgumentException("null configuration");
+      }
+      this.config = config;
+   }
+   
    static
    {
       UNCONFIGURED = new UnconfiguredVirtualDeploymentRepository();
@@ -85,7 +100,7 @@
          ArtifactRepository<ArtifactId> fileRepository = repositoryManager.
                      createArtifactRepository(createFileRepositoryId(source.getGroup()), null);
          // Create the virtual deployment repository
-         return new DelegatingDeploymentRepository(getRepositoryManager(),
+         return new DelegatingDeploymentRepository(getRepositoryManager(), config.getAssemblyConfiguration(),
                fileRepository.getIdentifier(), MVN_ID);
       }
       return UNCONFIGURED;
@@ -98,6 +113,16 @@
 
    static class UnconfiguredVirtualDeploymentRepository implements VirtualDeploymentRepository
    {
+      public Collection<ArtifactRepository<ArtifactId>> getArtifactRepositories()
+      {
+         return Collections.emptySet();
+      }
+      
+      public ArtifactRepository<ArtifactId> resolveArtifactRepository(ArtifactId artifactId)
+      {
+         return null;
+      }
+      
       @Override
       public ProfileDeployment createDeployment(VirtualDeploymentMetaData virtual) throws IOException
       {

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/DelegatingDeploymentRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/DelegatingDeploymentRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/DelegatingDeploymentRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -21,15 +21,18 @@
 */
 package org.jboss.profileservice.repository.virtual;
 
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
+import org.jboss.profileservice.config.VirtualAssemblyConfiguration;
 import org.jboss.profileservice.repository.artifact.ArtifactRepositoryManager;
 import org.jboss.profileservice.spi.VirtualDeploymentRepository;
 import org.jboss.profileservice.spi.repository.ArtifactId;
 import org.jboss.profileservice.spi.repository.ArtifactRepository;
 import org.jboss.profileservice.spi.repository.ArtifactRepositoryId;
-import org.jboss.vfs.VFS;
 import org.jboss.vfs.VirtualFile;
 
 
@@ -48,27 +51,49 @@
    /** The artifact repository manager. */
    private final ArtifactRepositoryManager repositoryManager;
 
-   public DelegatingDeploymentRepository(ArtifactRepositoryManager repositoryManager, ArtifactRepositoryId... repositoryIds)
+   /** The assembly configuration. */
+   private final VirtualAssemblyConfiguration assemblyConfiguration;
+   
+   public DelegatingDeploymentRepository(ArtifactRepositoryManager repositoryManager, VirtualAssemblyConfiguration configuration, 
+         ArtifactRepositoryId... repositoryIds)
    {
       if(repositoryManager == null)
       {
          throw new IllegalArgumentException("null repository manager");
       }
       processMappings(repositoryIds);
+      this.assemblyConfiguration = configuration;
       this.repositoryManager = repositoryManager;
    }
 
    protected VirtualFile getAssembledRoot()
    {
-      // FIXME
-      return VFS.getChild("virtual-deployments");
+      return assemblyConfiguration.getVirtualAssemblyRoot();
    }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Collection<ArtifactRepository<ArtifactId>> getArtifactRepositories()
+   {
+      Set<ArtifactRepository<ArtifactId>> repositories = new HashSet<ArtifactRepository<ArtifactId>>();
+      for(ArtifactRepositoryId id : repositoryRefs.values())
+      {
+         ArtifactRepository<ArtifactId> artifactRepository = resolveRepository(id);
+         repositories.add(artifactRepository);
+      }
+      return repositories;
+   }
+
+   public ArtifactRepository<ArtifactId> resolveArtifactRepository(ArtifactId artifactId)
+   {
+      return resolveRepository(artifactId);
+   }
    
    /**
     * {@inheritDoc}
     */
-   @Override
-   protected ArtifactRepository<ArtifactId> resolveRepository(ArtifactId artifactId)
+   public ArtifactRepository<ArtifactId> resolveRepository(ArtifactId artifactId)
    {
       ArtifactRepositoryId repositoryId = resolveRepositoryId(artifactId);
       return resolveRepository(repositoryId);

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/VirtualDeploymentProfile.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/VirtualDeploymentProfile.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/repository/virtual/VirtualDeploymentProfile.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -99,13 +99,13 @@
       {
          this.deployments = new ArrayList<ProfileDeployment>();
          this.deploymentsByName = new HashMap<String, ProfileDeployment>();
-         for(ProfileDeploymentMetaData virtual: deploymentMetaData)
+         for(ProfileDeploymentMetaData virtual : deploymentMetaData)
          {
             try
             {
                ProfileDeployment deployment = createDeployment(virtual);
-               this.deployments.add(deployment);
                this.deploymentsByName.put(deployment.getName(), deployment);
+               this.deployments.add(deployment);
             }
             catch(Exception e)
             {
@@ -120,7 +120,6 @@
     * Clean up the created {@code ProfileDeployment}s as part of
     * the lifecycle of the profile. At this point the deployments
     * should be undeployed already.
-    *
     */
    public void destroy()
    {
@@ -146,7 +145,6 @@
    /**
     * {@inheritDoc}
     */
-   @Override
    public ProfileDeployment getDeployment(String name) throws NoSuchDeploymentException
    {
       return this.deploymentsByName.get(name);
@@ -155,7 +153,6 @@
    /**
     * {@inheritDoc}
     */
-   @Override
    public Set<String> getDeploymentNames()
    {
       return this.deploymentsByName.keySet();
@@ -164,7 +161,6 @@
    /**
     * {@inheritDoc}
     */
-   @Override
    public List<ProfileDeployment> getDeployments()
    {
       return Collections.unmodifiableList(this.deployments);
@@ -173,7 +169,6 @@
    /**
     * {@inheritDoc}
     */
-   @Override
    public ProfileKey getKey()
    {
       return this.key;
@@ -182,7 +177,6 @@
    /**
     * {@inheritDoc}
     */
-   @Override
    public long getLastModified()
    {
       return this.lastModified;
@@ -191,7 +185,6 @@
    /**
     * {@inheritDoc}
     */
-   @Override
    public boolean hasDeployment(String name)
    {
       return this.deploymentsByName.containsKey(name);
@@ -200,7 +193,6 @@
    /**
     * {@inheritDoc}
     */
-   @Override
    public boolean isMutable()
    {
       return false;

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/virtual/assembly/AbstractVirtualDeploymentAssembly.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/virtual/assembly/AbstractVirtualDeploymentAssembly.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/virtual/assembly/AbstractVirtualDeploymentAssembly.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -33,7 +33,6 @@
 import org.jboss.vfs.VirtualFile;
 import org.jboss.vfs.VirtualFileAssembly;
 
-
 /**
  * The virtual deployment builder assembles a VirtualFile
  * based on the VirtualDeployment meta data.
@@ -44,13 +43,18 @@
 public abstract class AbstractVirtualDeploymentAssembly implements VirtualDeploymentAssembly
 {
    /**
-    * Get the virtual file for an artifact.
+    * Get the original virtual file for an artifact.
     * 
+    * This has to check whether the {@code ArtifactRepository} returns the original VirtualFile
+    * or not. In case the repository is configured to return the a backup the file has to be fixed.
+    * When assembling deployments we always need the original root - backups are usually only needed
+    * for hot-deployment/modification operations.
+    * 
     * @param artifact the artifact id
     * @return the file
     * @throws IOException
     */
-   protected abstract VirtualFile getVirtualFile(ArtifactId artifact) throws IOException;
+   protected abstract VirtualFile getOriginalVirtualFile(ArtifactId artifact) throws IOException;
    
    /**
     * Get the assembled root.
@@ -196,7 +200,7 @@
    {
       if(deployment.getArtifact() != null)
       {
-         VirtualFile vf = getVirtualFile(deployment.getArtifact()); 
+         VirtualFile vf = getOriginalVirtualFile(deployment.getArtifact()); 
          return new ImmutableAssemblyContext(vf);         
       }
       return null;

Modified: projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/virtual/assembly/BasicVirtualAssemblyContext.java
===================================================================
--- projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/virtual/assembly/BasicVirtualAssemblyContext.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/main/java/org/jboss/profileservice/virtual/assembly/BasicVirtualAssemblyContext.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -174,7 +174,7 @@
     */
    protected VirtualFile resolveRealArtifact(VirtualArtifactMetaData path) throws IOException
    {
-      return assembly.getVirtualFile(path);
+      return assembly.getOriginalVirtualFile(path);
    }
 
    protected static class RecurseFilter implements VirtualFileFilter

Modified: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/metadata/test/BasicDomainMetaDataUnitTestCase.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/metadata/test/BasicDomainMetaDataUnitTestCase.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/metadata/test/BasicDomainMetaDataUnitTestCase.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -26,9 +26,7 @@
 import java.util.Collection;
 import java.util.List;
 
-import org.jboss.profileservice.dependency.ProfileMetaDataRegistry;
 import org.jboss.profileservice.dependency.ProfileDependencyContext;
-import org.jboss.profileservice.domain.spi.DomainFeatureNode;
 import org.jboss.profileservice.domain.spi.DomainMetaData;
 import org.jboss.profileservice.metadata.ProfileMetaDataFactory;
 import org.jboss.profileservice.spi.ProfileKey;
@@ -36,7 +34,6 @@
 import org.jboss.profileservice.spi.dependency.ProfileRequirement;
 import org.jboss.profileservice.spi.metadata.ProfileMetaData;
 import org.jboss.test.profileservice.ProfileServiceTestBase;
-import org.jboss.test.profileservice.domain.support.AbstractDomainMetaDataVisitor;
 import org.jboss.test.profileservice.domain.support.DomainMetaDataRepoSupport;
 
 /**

Added: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/support/TestArtifactFilter.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/support/TestArtifactFilter.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/support/TestArtifactFilter.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,86 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.profileservice.repository.support;
+
+import java.util.Collection;
+
+import org.jboss.profileservice.repository.artifact.file.FileArtifact;
+import org.jboss.profileservice.repository.artifact.file.FileArtifactId;
+import org.jboss.profileservice.spi.repository.Artifact;
+import org.jboss.profileservice.spi.repository.ArtifactFilter;
+
+/**
+ * Test filter, simulating the original file scanning.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class TestArtifactFilter implements ArtifactFilter<FileArtifactId>
+{
+
+   private final Collection<String> names;
+   
+   public TestArtifactFilter(Collection<String> names)
+   {
+      this.names = names;
+   }
+   
+   @SuppressWarnings("deprecation")
+   public boolean accepts(final Artifact<FileArtifactId> artifact)
+   {
+      final FileArtifactId id = artifact.getIdentifier();
+      boolean exists = names.contains(id.getPath());
+      if(exists)
+      {
+         return false;
+      }
+      if(artifact instanceof FileArtifact)
+      {
+         if(((FileArtifact) artifact).isFile())
+         {
+            return true;
+         }
+         else
+         {
+            return id.getPath().contains(".");
+         }
+      }
+      return false; 
+   }
+
+   @SuppressWarnings("deprecation")
+   public boolean recurse(final Artifact<FileArtifactId> artifact)
+   {
+      if(artifact instanceof FileArtifact)
+      {
+         if(((FileArtifact) artifact).isFile() == false)
+         {
+            final FileArtifactId id = artifact.getIdentifier();
+            final String path = id.getPath();  
+            return path.contains(".") == false;            
+         }
+      }
+      return false;
+   }
+   
+}
+

Added: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/test/ArtifactRepositoryBackupUnitTestCase.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/test/ArtifactRepositoryBackupUnitTestCase.java	                        (rev 0)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/test/ArtifactRepositoryBackupUnitTestCase.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,230 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.profileservice.repository.test;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jboss.profileservice.Hack;
+import org.jboss.profileservice.config.ArtifactRepositoriesConfig;
+import org.jboss.profileservice.repository.artifact.AbstractRepositoryId;
+import org.jboss.profileservice.repository.artifact.file.FileArtifactId;
+import org.jboss.profileservice.repository.artifact.file.FileRepositoryConfiguration;
+import org.jboss.profileservice.repository.artifact.file.LocalFileArtifactRepository;
+import org.jboss.profileservice.spi.repository.Artifact;
+import org.jboss.profileservice.spi.repository.ArtifactRepositoryConfiguration.VFSBackupPolicy;
+import org.jboss.test.profileservice.ProfileServiceTestBase;
+import org.jboss.test.profileservice.repository.support.TestArtifactFilter;
+import org.jboss.vfs.VFS;
+import org.jboss.vfs.VFSUtils;
+import org.jboss.vfs.VirtualFile;
+import org.jboss.vfs.VirtualFileAssembly;
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public class ArtifactRepositoryBackupUnitTestCase extends ProfileServiceTestBase
+{
+   /** The noop repository id */
+   private static final AbstractRepositoryId noopRepositoryID = new AbstractRepositoryId("test", FileArtifactId.TYPE);
+
+   static
+   {
+      Hack.setCheckHack(true);
+   }
+   
+   static URL findResource(String name)
+   {
+      return Thread.currentThread().getContextClassLoader().getResource(name);
+   }
+   
+   public ArtifactRepositoryBackupUnitTestCase(String name)
+   {
+      super(name);
+   }
+   
+   public void testMount() throws Exception
+   {
+      FileRepositoryConfiguration repositoryConfiguration = createBackupConfiguration();
+      // When using mounts we need to use original
+      repositoryConfiguration.setBackupPolicy(VFSBackupPolicy.ORIGINAL);
+      VirtualFile repoRoot = VFS.getChild(findResource("system/static"));
+
+      URL file = findResource("system/bootstrap.xml");
+      Closeable cl1 = createMount(file.toURI(), repoRoot.getChild("bootstrap.xml"));
+      Closeable cl2 = createMount(file.toURI(), repoRoot.getChild("foobar/test.xml"));
+
+      LocalFileArtifactRepository repo = new LocalFileArtifactRepository(noopRepositoryID, repoRoot.asDirectoryURI(), repositoryConfiguration);
+      repo.create();
+      try
+      {
+         assertNotNull(repo.getArtifactFile(new FileArtifactId("bootstrap.xml")));
+         assertNotNull(repo.getArtifactFile(new FileArtifactId("foobar/test.xml")));
+      }
+      finally
+      {
+         repo.destroy();
+         VFSUtils.safeClose(cl1);
+         VFSUtils.safeClose(cl2);
+      }
+   }
+   
+   
+   public void testFilter() throws Exception
+   {
+      // Test the legacy scanning behavior
+      Set<String> includedNames = new HashSet<String>();
+      TestArtifactFilter filter = new TestArtifactFilter(includedNames);
+      
+      FileRepositoryConfiguration repositoryConfiguration = createBackupConfiguration();
+      // When using mounts we need to use original
+      repositoryConfiguration.setBackupPolicy(VFSBackupPolicy.ORIGINAL);
+      VirtualFile repoRoot = VFS.getChild(findResource("system/static"));
+
+      URL file = findResource("system/bootstrap.xml");
+      
+      
+      LocalFileArtifactRepository repo = new LocalFileArtifactRepository(noopRepositoryID, repoRoot.asDirectoryURI(), repositoryConfiguration);
+      repo.create();
+      Collection<Closeable> closeables = new ArrayList<Closeable>();
+      try
+      {
+         Collection<Artifact<FileArtifactId>> artifacts = repo.getArtifacts(filter);
+         assertTrue(artifacts.size() > 0);
+         for(Artifact<FileArtifactId> artifact : artifacts)
+         {
+            VirtualFile vf = repo.getArtifactFile(artifact.getIdentifier());
+            // There are only files in there
+            assertTrue(vf.getName(), vf.isFile());
+            includedNames.add(artifact.getIdentifier().getPath());
+         }
+         artifacts = repo.getArtifacts(filter);
+         // No new artifacts
+         assertTrue(artifacts.size() == 0);
+         
+         closeables.add(createMount(file.toURI(), repoRoot.getChild("bootstrap.xml")));
+         artifacts = repo.getArtifacts(filter);
+         // one new artifacts
+         assertTrue(artifacts.size() == 1);
+         includedNames.add("bootstrap.xml");
+         
+         closeables.add(createAssembly(repoRoot.getChild("testFolder")));
+         artifacts = repo.getArtifacts(filter);
+         // No new artifacts
+         assertTrue(artifacts.size() == 0);
+
+         closeables.add(createAssembly(repoRoot.getChild("testFolder.deployment")));
+         artifacts = repo.getArtifacts(filter);
+         // One new artifacts
+         assertTrue(artifacts.size() == 1);
+         includedNames.add("testFolder.deployment");
+         
+         closeables.add(createMount(file.toURI(), repoRoot.getChild("testFoler.deployment/bootstrap.xml")));
+         artifacts = repo.getArtifacts(filter);
+         assertTrue(artifacts.size() == 0);
+         
+      }
+      finally
+      {
+         repo.destroy();
+         for(Closeable cl : closeables)
+         {
+            VFSUtils.safeClose(cl);
+         }
+         
+      }
+   }
+   
+   
+   public void testBasic() throws Exception
+   {
+      FileRepositoryConfiguration repositoryConfiguration = createBackupConfiguration();
+      VirtualFile backupRoot = VFS.getChild(repositoryConfiguration.getBackupURI());
+
+      VirtualFile repoRoot = VFS.getChild(findResource("system"));
+      
+      LocalFileArtifactRepository repo = new LocalFileArtifactRepository(noopRepositoryID, repoRoot.asDirectoryURI(), repositoryConfiguration);
+      repo.create();
+      try
+      {
+         for(Artifact<FileArtifactId> artifact : repo.getArtifacts())
+         {
+            getLog().debug(artifact);
+            String relativePath = "/" + artifact.getRelativePath();
+            VirtualFile realFile = repoRoot.getChild(relativePath);
+            VirtualFile repositoryFile = repo.getArtifactFile(artifact.getIdentifier());
+            // has to exist
+            assertTrue(relativePath, realFile.exists());
+            // id.path == relative path to existing root
+            assertEquals(artifact.getIdentifier().getPath(), realFile.getPathNameRelativeTo(repoRoot));
+            // the real and the artifact files don't match
+            assertFalse(realFile.equals(repositoryFile));
+            getLog().debug(repositoryFile);
+            try
+            {
+               String relative = realFile.getPathNameRelativeTo(backupRoot); 
+               fail("could resolve relative path " + relative);
+            }
+            catch(Exception e)
+            {
+               // ok
+            }
+         }
+      }
+      finally
+      {
+         repo.destroy();
+      }
+   }
+   
+   protected FileRepositoryConfiguration createBackupConfiguration() throws URISyntaxException
+   {
+      ArtifactRepositoriesConfig config = new ArtifactRepositoriesConfig();
+      URI backupURI = config.createBackupURI();
+      FileRepositoryConfiguration repositoryConfiguration = new FileRepositoryConfiguration();
+      repositoryConfiguration.setBackupPolicy(VFSBackupPolicy.BACKUP);
+      repositoryConfiguration.setBackupURI(backupURI);
+      return repositoryConfiguration;
+   }
+   
+   protected Closeable createMount(URI real, VirtualFile mountPoint) throws IOException
+   {
+      File realRoot = new File(real);
+      return VFS.mountReal(realRoot, mountPoint);
+   }
+   
+   protected Closeable createAssembly(VirtualFile mountPoint) throws IOException
+   {
+      VirtualFileAssembly assembly = new VirtualFileAssembly();
+      return VFS.mountAssembly(assembly, mountPoint);
+   }
+}
+

Modified: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/test/ArtifactRepositoryUnitTestCase.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/test/ArtifactRepositoryUnitTestCase.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/repository/test/ArtifactRepositoryUnitTestCase.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -88,7 +88,7 @@
       // <artifact groupId="org.jboss.test" artifactId="test-common" from="2.0.0" to="2.1.0" />
       id.setArtifactId("test-common");
       id.setGroupId("org.jboss.test");
-      VirtualFile art = ((TestVirtualDeploymentRepository)factory).getVirtualFile(id);
+      VirtualFile art = ((TestVirtualDeploymentRepository)factory).getOriginalVirtualFile(id);
       log.debug(art.getPhysicalFile());
       
       Automounter.cleanup(vf);

Modified: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/support/NoopArtifactRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/support/NoopArtifactRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/support/NoopArtifactRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -22,6 +22,7 @@
 package org.jboss.test.profileservice.support;
 
 import java.io.IOException;
+import java.net.URI;
 import java.util.Collection;
 
 import org.jboss.profileservice.spi.repository.Artifact;
@@ -39,31 +40,36 @@
 public class NoopArtifactRepository implements ArtifactRepository<ArtifactId>
 {
 
-   @Override
+   public URI getRepositoryURI()
+   {
+      return null;
+   }
+   
    public ArtifactRepositoryId getIdentifier()
    {
       return null;
    }
    
-   @Override
    public boolean containsArtifact(ArtifactId artifact)
    {
       return false;
    }
 
-   @Override
    public Artifact<ArtifactId> getArtifact(ArtifactId artifactId)
    {
       return null;
    }
 
-   @Override
    public VirtualFile getArtifactFile(ArtifactId artifact) throws IOException
    {
       return null;
    }
 
-   @Override
+   public VirtualFile getOriginalFile(ArtifactId artifact) throws IOException
+   {
+      return null;
+   }
+   
    public Collection<Artifact<ArtifactId>> getArtifacts()
    {
       return null;

Modified: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/support/TestArtifactRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/support/TestArtifactRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/support/TestArtifactRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -26,6 +26,7 @@
 
 import org.jboss.profileservice.repository.artifact.AbstractRepositoryId;
 import org.jboss.profileservice.repository.artifact.file.FileArtifactId;
+import org.jboss.profileservice.repository.artifact.file.FileRepositoryConfiguration;
 import org.jboss.profileservice.repository.artifact.file.LocalFileArtifactRepository;
 import org.jboss.profileservice.spi.repository.ArtifactRepositoryId;
 import org.jboss.vfs.VirtualFile;
@@ -44,7 +45,8 @@
    
    public TestArtifactRepository(URI rootURI) throws IOException
    {
-      super(TEST_ID, rootURI);
+      super(TEST_ID, rootURI, new FileRepositoryConfiguration());
+      create();
    }
 
    @Override

Modified: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/support/TestVirtualDeploymentRepository.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/support/TestVirtualDeploymentRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/support/TestVirtualDeploymentRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -22,9 +22,11 @@
 package org.jboss.test.profileservice.virtual.support;
 
 import java.io.IOException;
+import java.util.Collection;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.jboss.profileservice.config.VirtualAssemblyConfiguration;
 import org.jboss.profileservice.repository.ProfileDeploymentFactory;
 import org.jboss.profileservice.spi.ProfileDeployment;
 import org.jboss.profileservice.spi.VirtualDeploymentRepository;
@@ -33,7 +35,6 @@
 import org.jboss.profileservice.spi.virtual.VirtualDeploymentMetaData;
 import org.jboss.profileservice.spi.virtual.assembly.VirtualDeploymentAssemblyContext;
 import org.jboss.profileservice.virtual.assembly.AbstractVirtualDeploymentAssembly;
-import org.jboss.vfs.VFS;
 import org.jboss.vfs.VirtualFile;
 
 /**
@@ -49,11 +50,25 @@
    /** The repositories. */
    private Map<String, ArtifactRepository<ArtifactId>> repositories = new ConcurrentHashMap<String, ArtifactRepository<ArtifactId>>();
    
+   /** The assembly configuration. */
+   private static final VirtualAssemblyConfiguration assemblyConfiguration = new VirtualAssemblyConfiguration();
+   
    protected VirtualFile getAssembledRoot()
    {
-      return VFS.getChild("virtual-deployments");
+      return assemblyConfiguration.getVirtualAssemblyRoot();
    }
    
+   public Collection<ArtifactRepository<ArtifactId>> getArtifactRepositories()
+   {
+      // FIXME getArtifactRepositories
+      return null;
+   }
+   
+   public ArtifactRepository<ArtifactId> resolveArtifactRepository(ArtifactId artifactId)
+   {
+      return null;
+   }
+   
    /**
     * Create a ProfileDeployment.
     * TODO - ProfileDeployment should maybe be a virtual deployment?
@@ -75,13 +90,13 @@
       {
          throw new IllegalStateException("Assembled null virtual file");
       }
-      ProfileDeployment profileDeployment = deploymentFactory.createDeployment(vf);
+      ProfileDeployment profileDeployment = deploymentFactory.createDeployment(vf, deployment);
       profileDeployment.getTransientAttachments().putAttachment(VirtualDeploymentAssemblyContext.class.getName(), ctx);
       return profileDeployment;
    }
 
    @Override
-   public VirtualFile getVirtualFile(ArtifactId artifact) throws IOException
+   public VirtualFile getOriginalVirtualFile(ArtifactId artifact) throws IOException
    {
       return getRepository(artifact).getArtifactFile(artifact);
    }

Modified: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/test/StructureMetaDataUnitTestCase.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/test/StructureMetaDataUnitTestCase.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/test/StructureMetaDataUnitTestCase.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -31,6 +31,7 @@
 import org.jboss.deployers.spi.structure.ClassPathEntry;
 import org.jboss.deployers.spi.structure.ContextInfo;
 import org.jboss.deployers.spi.structure.StructureMetaData;
+import org.jboss.profileservice.Hack;
 import org.jboss.profileservice.deployers.VDFDeploymentBuilder;
 import org.jboss.profileservice.spi.ProfileDeployment;
 import org.jboss.profileservice.spi.VirtualDeploymentRepository;
@@ -56,6 +57,8 @@
    
    public void test() throws Exception
    {
+      Hack.setCheckHack(true);
+      
       // Set the jboss.deployment.resources
       System.setProperty("jboss.deployment.resources", getResource(REPOSITORY_LOCATION).toExternalForm());
       

Modified: projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/test/VirtualDeploymentAssemblyUnitTestCase.java
===================================================================
--- projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/test/VirtualDeploymentAssemblyUnitTestCase.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/java/org/jboss/test/profileservice/virtual/test/VirtualDeploymentAssemblyUnitTestCase.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -23,6 +23,7 @@
 
 import java.util.Map;
 
+import org.jboss.profileservice.Hack;
 import org.jboss.profileservice.spi.ProfileDeployment;
 import org.jboss.profileservice.spi.VirtualDeploymentRepository;
 import org.jboss.profileservice.spi.deployment.ProfileDeploymentFlag;
@@ -49,6 +50,7 @@
 
    public void test() throws Exception
    {
+      Hack.setCheckHack(true);
       // Set the jboss.deployment.resources
       System.setProperty("jboss.deployment.resources", getResource(REPOSITORY_LOCATION).toExternalForm());
       

Modified: projects/profileservice/trunk/core/src/test/resources/system/bootstrap.xml
===================================================================
--- projects/profileservice/trunk/core/src/test/resources/system/bootstrap.xml	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/resources/system/bootstrap.xml	2010-03-09 10:44:04 UTC (rev 102120)
@@ -26,6 +26,7 @@
 	
 	<!-- The bootstrap profile factory -->
 	<bean name="BootstrapProfileFactory" class="org.jboss.profileservice.profile.bootstrap.BootstrapProfileFactory">
+		<constructor><parameter><inject bean="ProfileServiceConfig" /></parameter></constructor>
 		<property name="repositoryManager"><inject bean="ArtifactRepositoryManager" /></property>
 	</bean>
 	
@@ -59,6 +60,7 @@
 	<bean name="FileArtifactRepositoryFactory" class="org.jboss.profileservice.repository.artifact.file.FileArtifactRepositoryFactory">
 		<constructor>
 			<parameter class="java.net.URI">${jboss.file.repository.url}</parameter>
+			<parameter><inject bean="ProfileServiceConfig" /></parameter>
 		</constructor>
 	</bean>
 	

Modified: projects/profileservice/trunk/core/src/test/resources/system/static/bootstrap/profile.xml
===================================================================
--- projects/profileservice/trunk/core/src/test/resources/system/static/bootstrap/profile.xml	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/core/src/test/resources/system/static/bootstrap/profile.xml	2010-03-09 10:44:04 UTC (rev 102120)
@@ -9,6 +9,7 @@
 	</bean>
 
 	<bean name="Basic Profile Factory" class="org.jboss.profileservice.profile.BasicProfileFactory">
+		<constructor><parameter><inject bean="ProfileServiceConfig" /></parameter></constructor>
 		<property name="repositoryManager"><inject bean="ArtifactRepositoryManager" /></property>
 	</bean>
 	<bean name="Legacy Profile Factory" class="org.jboss.profileservice.repository.legacy.LegacyProfileFactory" />

Added: projects/profileservice/trunk/plugins/src/main/java/org/jboss/profileservice/plugins/deploy/actions/DeploymentDistributeAction.java
===================================================================
--- projects/profileservice/trunk/plugins/src/main/java/org/jboss/profileservice/plugins/deploy/actions/DeploymentDistributeAction.java	                        (rev 0)
+++ projects/profileservice/trunk/plugins/src/main/java/org/jboss/profileservice/plugins/deploy/actions/DeploymentDistributeAction.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,107 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.plugins.deploy.actions;
+
+import java.io.InputStream;
+
+import org.jboss.logging.Logger;
+import org.jboss.profileservice.repository.artifact.CopyStreamArtifactTransformer;
+import org.jboss.profileservice.repository.artifact.file.FileArtifactId;
+import org.jboss.profileservice.spi.MutableProfile;
+import org.jboss.profileservice.spi.Profile;
+import org.jboss.profileservice.spi.ProfileDeployment;
+import org.jboss.profileservice.spi.VirtualDeploymentRepository;
+import org.jboss.profileservice.spi.deployment.ProfileDeploymentFlag;
+import org.jboss.profileservice.spi.repository.ArtifactId;
+import org.jboss.profileservice.spi.repository.ArtifactRepository;
+import org.jboss.profileservice.spi.repository.ArtifactTransformer;
+import org.jboss.profileservice.spi.repository.MutableArtifactRepository;
+
+
+/**
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public abstract class DeploymentDistributeAction
+{
+
+   private static final Logger log = Logger.getLogger("org.jboss.profileservice.deployment.action");
+   private static final ArtifactId noopArtifactId = FileArtifactId.EMPTY_ARTIFACT;
+   
+   abstract String getDeploymentName();
+   abstract InputStream getDeploymentInputStream();
+   abstract Profile getProfile();
+   abstract VirtualDeploymentRepository getVirtualDeploymentRepository();
+   abstract boolean isExplode();
+
+   protected boolean prepare()
+   {
+      if(getProfile().isMutable() == false)
+      {
+         return false;
+      }
+      ArtifactRepository<ArtifactId> artifactRepository = getVirtualDeploymentRepository().resolveArtifactRepository(noopArtifactId);
+      if(artifactRepository == null || artifactRepository.getConfiguration().isMutable() == false)
+      {
+         return false;
+      }
+      // Create the artifact based on the deployment name
+      FileArtifactId artifactId = new FileArtifactId(getDeploymentName());
+      // We need a mutable repository
+      MutableArtifactRepository<ArtifactId> mutable = MutableArtifactRepository.class.cast(artifactRepository);
+      // Create the transformer
+      ArtifactTransformer<ArtifactId> transformer = createTransformer();
+
+      try
+      {
+         // Add IS
+         mutable.addArtifact(artifactId, getDeploymentInputStream(), transformer);
+         // Assemble
+         ProfileDeployment deployment = getVirtualDeploymentRepository().createDeployment(null);
+         // Lock hd-scanning
+         deployment.getDeploymentInfo().setFlag(ProfileDeploymentFlag.LOCKED);
+         // Add deployment
+         MutableProfile m = MutableProfile.class.cast(getProfile());
+         m.addDeployment(deployment);
+      }
+      catch(Exception e)
+      {
+         log.warn("failed to distribute content.", e);
+         return false;
+      }
+      return true;
+   }
+
+   protected ArtifactTransformer<ArtifactId> createTransformer()
+   {
+      if(isExplode())
+      {
+         return CopyStreamArtifactTransformer.getInstance();
+      }
+      else
+      {
+         return CopyStreamArtifactTransformer.getInstance();
+      }      
+   }
+   
+}
+

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/ProfileDeployment.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/ProfileDeployment.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/ProfileDeployment.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -34,7 +34,6 @@
  * @version $Revision$
  */
 // TODO remove dependency on VFS
-// TODO extends VirtualDeployment ?
 public interface ProfileDeployment extends Serializable
 {
 

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/VirtualDeploymentRepository.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/VirtualDeploymentRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/VirtualDeploymentRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -23,6 +23,8 @@
 
 import java.io.IOException;
 
+import org.jboss.profileservice.spi.repository.ArtifactId;
+import org.jboss.profileservice.spi.repository.ArtifactRepository;
 import org.jboss.profileservice.spi.virtual.VirtualDeploymentMetaData;
 
 /**
@@ -33,8 +35,18 @@
  */
 public interface VirtualDeploymentRepository
 {
-
+   
    /**
+    * Resolve a artifact repository for a given {@code ArtifactId}. For the resolution
+    * only the {@link ArtifactId#getType()} is taken into account.
+    * 
+    * @param <T> the type of the repository
+    * @param artifactId the artifact id
+    * @return the artifact repository, null if cannot be resolved
+    */
+   <T extends ArtifactId> ArtifactRepository<T> resolveArtifactRepository(T artifactId);
+   
+   /**
     * Create a profile deployment based on a virtual
     * deployment assembly descriptor.
     * 

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/TwoPhaseCommitProfileAction.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/TwoPhaseCommitProfileAction.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/TwoPhaseCommitProfileAction.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -38,7 +38,7 @@
    /**
     * Prepare this action.
     */
-   void prepare();
+   boolean prepare();
    
    /**
     * Attempt to commit this action.

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/engine/ActionController.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/engine/ActionController.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/engine/ActionController.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -25,6 +25,7 @@
 
 import org.jboss.profileservice.spi.ProfileKey;
 import org.jboss.profileservice.spi.action.ProfileModificationActions;
+import org.jboss.profileservice.spi.action.ProfileModificationContext;
 
 /**
  * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
@@ -47,7 +48,7 @@
     * @param actions the modification actions
     * @return the modification status
     */
-   ModificationStatus perfom(ProfileKey key, ProfileModificationActions<?> actions); 
+   ModificationStatus perfom(ProfileKey key, ProfileModificationActions<ProfileModificationContext> actions); 
    
 }
 

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/engine/ModificationStatus.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/engine/ModificationStatus.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/action/engine/ModificationStatus.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -21,7 +21,6 @@
 */
 package org.jboss.profileservice.spi.action.engine;
 
-import java.util.Collection;
 
 /**
  * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
@@ -31,13 +30,6 @@
 {
 
    /**
-    * Get the children.
-    * 
-    * @return the children
-    */
-   Collection<ModificationStatus> getChildren();
-
-   /**
     * Get the failure exception.
     * 
     * @return any failure exception associated with reaching the FAILED state.

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/deployment/ProfileDeploymentInfo.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/deployment/ProfileDeploymentInfo.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/deployment/ProfileDeploymentInfo.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -21,6 +21,8 @@
 */
 package org.jboss.profileservice.spi.deployment;
 
+import org.jboss.profileservice.spi.virtual.VirtualDeploymentMetaData;
+
 /**
  * The profile deployment info.
  * 
@@ -38,6 +40,13 @@
    String getName();
    
    /**
+    * Get the virtual deployment meta data.
+    * 
+    * @return the virtual deployment meta data.
+    */
+   VirtualDeploymentMetaData getMetaData();
+   
+   /**
     * Flag indicating if a deployment is deployed.
     * 
     * @return true if deployed, false otherwise

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/Artifact.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/Artifact.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/Artifact.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -21,12 +21,6 @@
 */
 package org.jboss.profileservice.spi.repository;
 
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.jboss.vfs.VirtualFile;
-
-
 /**
  * The artifact.
  * 
@@ -57,19 +51,5 @@
     */
    long getLastModified();
    
-   /**
-    * Get the file.
-    * 
-    * @return the file.
-    */
-   VirtualFile getFile();
-   
-   /**
-    * Get the artifacts input stream.
-    * 
-    * @return the input stream
-    */
-   InputStream getInputStream() throws IOException;
-   
 }
 

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactFilter.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactFilter.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactFilter.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -39,9 +39,8 @@
    boolean accepts(Artifact<T> artifact);
 
    /**
-    * Determine whether to recurse into a
-    * artifact - e.g. for file artifacts
-    * if it's a directory. 
+    * Determine whether to recurse into a artifact 
+    * e.g. for file artifacts if it's a directory. 
     * 
     * TODO does this make sense?
     * 
@@ -49,5 +48,6 @@
     * @return 
     */
    boolean recurse(Artifact<T> artifact);
+   
 }
 

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactRepository.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -22,6 +22,7 @@
 package org.jboss.profileservice.spi.repository;
 
 import java.io.IOException;
+import java.net.URI;
 import java.util.Collection;
 
 import org.jboss.vfs.VirtualFile;
@@ -32,11 +33,18 @@
  * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
  * @version $Revision$
  */
-// TODO move this out of the PS spi?
+// TODO move this out of the ProfileService SPI
 public interface ArtifactRepository<T extends ArtifactId> extends Identifiable<ArtifactRepositoryId>
 {
    
    /**
+    * Get the artifact repository location.
+    * 
+    * @return the repository location
+    */
+   URI getRepositoryURI();
+   
+   /**
     * Get the repository configuration.
     * 
     * @return the configuration
@@ -76,13 +84,23 @@
    Collection<Artifact<T>> getArtifacts(ArtifactFilter<T> filter);
    
    /**
-    * Get the artifact file from the repository.
+    * Get the artifact file from the repository. 
     * 
     * @param artifact the artifact
     * @return the virtual file
     * @throws IOException
     */
    VirtualFile getArtifactFile(T artifact) throws IOException;
+   
+   /**
+    * Get the original file of the artifact.
+    * {@see ArtifactRepositoryConfiguration.VFSBackupPolicy}.
+    * 
+    * @param artifact the artifact
+    * @return the original virtual file
+    * @throws IOException
+    */
+   VirtualFile getOriginalFile(T artifact) throws IOException;
 
 }
 

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactRepositoryConfiguration.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactRepositoryConfiguration.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactRepositoryConfiguration.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -21,7 +21,6 @@
 */
 package org.jboss.profileservice.spi.repository;
 
-import java.net.URI;
 
 /**
  * The artifact repository configuration.
@@ -33,13 +32,6 @@
 {
    
    /**
-    * Get the repository location. 
-    * 
-    * @return the location
-    */
-   URI getLocation();
-   
-   /**
     * Returns <code>true</code> if this repository can be modified.
     * 
     * @return whether this repository is mutable or not
@@ -47,11 +39,42 @@
    boolean isMutable();
 
    /**
+    * Get the vfs backup policy.
+    * 
+    * @return the backup policy
+    */
+   VFSBackupPolicy getBackupPolicy();
+   
+   /**
     * Get the not found handler.
     * 
     * @return the not found handler.
     */
    ArtifactNotFoundHandler<T> getNotFoundHandler();
+
+   /**
+    * The repository backup policy. This is needed for any hot-deployment
+    * profile using a artifact repository preserving the original view on
+    * the file system.
+    * 
+    * For BACKUP the semantics are that all artifacts reference
+    * the backup location, therefore the location of the {@code VirtualFile}
+    * will be different from it's original root.
+    * The original can be reconstructed using the {@code ArtifactRepository#getRepositoryURI()}
+    * and the {@code Artifact#getRelativePath()}.
+    *
+    * USE_ORIGINAL will return the real location, where the actual view on the virtual file
+    * system can change during the deployment process.
+    * 
+    */
+   public enum VFSBackupPolicy
+   {
+      // return a backup artifact
+      BACKUP,
+      
+      // return the original file
+      ORIGINAL,
+   }
    
 }
 

Added: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactTransformer.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactTransformer.java	                        (rev 0)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/ArtifactTransformer.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -0,0 +1,49 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, Red Hat Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.profileservice.spi.repository;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.jboss.vfs.VirtualFile;
+
+/**
+ * The artifact transformer.
+ * 
+ * @author <a href="mailto:emuckenh at redhat.com">Emanuel Muckenhuber</a>
+ * @version $Revision$
+ */
+public interface ArtifactTransformer<T extends ArtifactId>
+{
+
+   /**
+    * Transform.
+    * 
+    * @param artifactId the artifact id
+    * @param is the input stream
+    * @param target the target virtual file
+    * @throws IOException for any error
+    */
+   void transform(T artifactId, InputStream is, VirtualFile target) throws IOException;
+   
+}
+

Modified: projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/MutableArtifactRepository.java
===================================================================
--- projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/MutableArtifactRepository.java	2010-03-09 10:20:14 UTC (rev 102119)
+++ projects/profileservice/trunk/spi/src/main/java/org/jboss/profileservice/spi/repository/MutableArtifactRepository.java	2010-03-09 10:44:04 UTC (rev 102120)
@@ -22,6 +22,7 @@
 package org.jboss.profileservice.spi.repository;
 
 import java.io.IOException;
+import java.io.InputStream;
 
 /**
  * The mutable artifact repository.
@@ -35,9 +36,14 @@
    /**
     * Add a artifact to the repository.
     * 
-    * @param artifact the artifact to add
+    * NOTE closing the <code>InputStream</code> has to be handled by the caller.
+    * 
+    * @param artifactId the artifact to add
+    * @param is the input stream
+    * @param transformer the artifact transformer
+    * @throws IOException for any error
     */
-   void addArtifact(Artifact<T> artifact) throws IOException;
+   void addArtifact(T artifactId, InputStream is, ArtifactTransformer<T> transformer) throws IOException;
    
    /**
     * Remove a artifact from the repository.




More information about the jboss-cvs-commits mailing list