[maven-release-plugin]  copy for tag mercury-1.0-alpha-6

git-svn-id: https://svn.apache.org/repos/asf/maven/mercury/tags/mercury-1.0-alpha-6@762963 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/mercury-ant-tasks/pom.xml b/mercury-ant-tasks/pom.xml
index 7efe349..22f7f94 100644
--- a/mercury-ant-tasks/pom.xml
+++ b/mercury-ant-tasks/pom.xml
@@ -36,6 +36,11 @@
 
   <dependencies>
 
+      <dependency><!-- somebody always trying to mess this one up. I need 1.8+  -->
+        <groupId>org.sonatype.spice</groupId>
+        <artifactId>model-builder</artifactId>
+      </dependency>
+ 
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
@@ -71,22 +76,18 @@
     </dependency>
 
     <dependency>
-      <groupId>org.apache.maven.mercury
-      </groupId>
+      <groupId>org.apache.maven.mercury</groupId>
       <artifactId>mercury-repo-local-map
       </artifactId>
     </dependency>
 
     <dependency>
-      <groupId>org.apache.maven.mercury
-      </groupId>
-      <artifactId>mercury-repo-remote-m2
-      </artifactId>
+      <groupId>org.apache.maven.mercury</groupId>
+      <artifactId>mercury-repo-remote-m2</artifactId>
     </dependency>
 
     <dependency>
-      <groupId>org.apache.maven.mercury
-      </groupId>
+      <groupId>org.apache.maven.mercury</groupId>
       <artifactId>mercury-md-sat</artifactId>
     </dependency>
 
diff --git a/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Dep.java b/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Dep.java
index 7c9f705..4145a3a 100644
--- a/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Dep.java
+++ b/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Dep.java
@@ -27,7 +27,6 @@
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactExclusionList;
 import org.apache.maven.mercury.artifact.ArtifactInclusionList;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
@@ -86,7 +85,7 @@
     
     List<String> _exclusions;
 
-    private List<ArtifactBasicMetadata> getDependencies( VirtualRepositoryReader vr )
+    private List<ArtifactMetadata> getDependencies( VirtualRepositoryReader vr )
         throws RepositoryException
     {
         if ( Util.isEmpty( _dependencies ) )
@@ -94,7 +93,7 @@
             return null;
         }
 
-        List<ArtifactBasicMetadata> res = new ArrayList<ArtifactBasicMetadata>( _dependencies.size() );
+        List<ArtifactMetadata> res = new ArrayList<ArtifactMetadata>( _dependencies.size() );
 
         for ( Dependency d : _dependencies )
         {
@@ -135,7 +134,7 @@
 
                 if ( deps != null && !Util.isEmpty( deps.getDependencies() ) )
                 {
-                    for ( ArtifactBasicMetadata bmd : deps.getDependencies() )
+                    for ( ArtifactMetadata bmd : deps.getDependencies() )
                     {
                         res.add( bmd );
                     }
@@ -199,7 +198,7 @@
         
         _pomRepo.setMetadataReader( vr );
 
-        List<ArtifactBasicMetadata> depList = getDependencies( vr );
+        List<ArtifactMetadata> depList = getDependencies( vr );
         
         ArtifactQueryList aql = new ArtifactQueryList( depList );
         
@@ -210,6 +209,8 @@
         List<ArtifactMetadata> res =
             _transitive ? db.resolveConflicts( scope, aql, ail, ael )
                             : toArtifactMetadataList( depList );
+            
+        db.close();
 
         if ( Util.isEmpty( res ) )
         {
@@ -236,10 +237,10 @@
             return null;
         }
 
-        Map<ArtifactBasicMetadata, List<Artifact>> resMap = aRes.getResults();
+        Map<ArtifactMetadata, List<Artifact>> resMap = aRes.getResults();
 
         int count = 0;
-        for ( ArtifactBasicMetadata key : resMap.keySet() )
+        for ( ArtifactMetadata key : resMap.keySet() )
         {
             List<Artifact> artifacts = resMap.get( key );
             if ( artifacts != null )
@@ -255,7 +256,7 @@
 
         _artifacts = new ArrayList<Artifact>( count );
 
-        for ( ArtifactBasicMetadata key : resMap.keySet() )
+        for ( ArtifactMetadata key : resMap.keySet() )
         {
             List<Artifact> artifacts = resMap.get( key );
 
@@ -291,14 +292,14 @@
      * @param depList
      * @return
      */
-    private List<ArtifactMetadata> toArtifactMetadataList( List<ArtifactBasicMetadata> depList )
+    private List<ArtifactMetadata> toArtifactMetadataList( List<ArtifactMetadata> depList )
     {
         if ( Util.isEmpty( depList ) )
             return null;
 
         List<ArtifactMetadata> res = new ArrayList<ArtifactMetadata>( depList.size() );
 
-        for ( ArtifactBasicMetadata bmd : depList )
+        for ( ArtifactMetadata bmd : depList )
             res.add( new ArtifactMetadata( bmd ) );
 
         return res;
diff --git a/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Dependency.java b/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Dependency.java
index 158df9a..5892c63 100644
--- a/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Dependency.java
+++ b/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Dependency.java
@@ -23,7 +23,7 @@
 import java.util.Collection;
 import java.util.List;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.util.Util;
 import org.codehaus.plexus.lang.DefaultLanguage;
 import org.codehaus.plexus.lang.Language;
@@ -37,7 +37,7 @@
 {
     private static final Language LANG = new DefaultLanguage( Dependency.class );
 
-    protected ArtifactBasicMetadata _amd;
+    protected ArtifactMetadata _amd;
 
     protected String _pom;
 
@@ -52,7 +52,7 @@
     
     private static long _count = 0L;
     
-    public ArtifactBasicMetadata getMetadata()
+    public ArtifactMetadata getMetadata()
     {
         _amd.setInclusions( getInclusions() );
         
@@ -61,28 +61,28 @@
         return _amd;
     }
     
-    private Collection<ArtifactBasicMetadata> getExclusions()
+    private Collection<ArtifactMetadata> getExclusions()
     {
         if( Util.isEmpty( _exclusions ))
             return null;
         
-        List<ArtifactBasicMetadata> res = new ArrayList<ArtifactBasicMetadata>( _exclusions.size() );
+        List<ArtifactMetadata> res = new ArrayList<ArtifactMetadata>( _exclusions.size() );
         
         for( String name : _exclusions )
-            res.add( new ArtifactBasicMetadata(name) );
+            res.add( new ArtifactMetadata(name) );
         
         return res;
     }
 
-    private Collection<ArtifactBasicMetadata> getInclusions()
+    private Collection<ArtifactMetadata> getInclusions()
     {
         if( Util.isEmpty( _inclusions ))
             return null;
         
-        List<ArtifactBasicMetadata> res = new ArrayList<ArtifactBasicMetadata>( _inclusions.size() );
+        List<ArtifactMetadata> res = new ArrayList<ArtifactMetadata>( _inclusions.size() );
         
         for( String name : _inclusions )
-            res.add( new ArtifactBasicMetadata(name) );
+            res.add( new ArtifactMetadata(name) );
         
         return res;
     }
@@ -92,7 +92,7 @@
         if( _pom != null )
             throw new IllegalArgumentException( LANG.getMessage( "dependency.amd.pom.exists", _pom, name ) );
         
-        _amd = new ArtifactBasicMetadata( name );
+        _amd = new ArtifactMetadata( name );
 
         _amd.setOptional( _optional );
     }
@@ -141,7 +141,7 @@
     {
         if ( _amd == null )
         {
-            _amd = new ArtifactBasicMetadata();
+            _amd = new ArtifactMetadata();
         }
 
         _amd.setGroupId( groupId );
@@ -156,7 +156,7 @@
     {
         if ( _amd == null )
         {
-            _amd = new ArtifactBasicMetadata();
+            _amd = new ArtifactMetadata();
         }
 
         _amd.setArtifactId( artifactId );
@@ -171,7 +171,7 @@
     {
         if ( _amd == null )
         {
-            _amd = new ArtifactBasicMetadata();
+            _amd = new ArtifactMetadata();
         }
 
         _amd.setVersion( version );
diff --git a/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Repo.java b/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Repo.java
index ec00045..df0d6dd 100644
--- a/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Repo.java
+++ b/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/Repo.java
@@ -30,12 +30,15 @@
 import java.util.Set;
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
+import org.apache.maven.mercury.artifact.QualityRange;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
 import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
 import org.apache.maven.mercury.crypto.pgp.PgpStreamVerifierFactory;
 import org.apache.maven.mercury.crypto.sha.SHA1VerifierFactory;
 import org.apache.maven.mercury.repository.api.Repository;
+import org.apache.maven.mercury.repository.api.RepositoryUpdatePolicy;
+import org.apache.maven.mercury.repository.api.RepositoryUpdatePolicyFactory;
 import org.apache.maven.mercury.repository.local.m2.LocalRepositoryM2;
 import org.apache.maven.mercury.repository.remote.m2.RemoteRepositoryM2;
 import org.apache.maven.mercury.transport.api.Credentials;
@@ -70,10 +73,16 @@
 
     private String _proxyauthid;
 
+    private String _updatePolicy;
+
     private boolean _readable = true;
 
     private boolean _writeable = false;
 
+    private boolean _releases = true;
+
+    private boolean _snapshots = true;
+
     private Auth _auth;
 
     private Auth _proxyAuth;
@@ -134,6 +143,20 @@
         processDefaults();
     }
 
+    public void setReleases( boolean releases )
+    {
+        this._releases = releases;
+
+        processDefaults();
+    }
+    
+    public void setSnapshots( boolean snapshots )
+    {
+        this._snapshots = snapshots;
+
+        processDefaults();
+    }
+
     public void setReadable( boolean readable )
     {
         this._readable = readable;
@@ -233,6 +256,13 @@
 
         processDefaults();
     }
+    
+    public void setUpdatePolicy( String updatePolicy )
+    {
+        this._updatePolicy = updatePolicy;
+
+        processDefaults();
+    }
 
     boolean isLocal()
     {
@@ -309,6 +339,7 @@
 
                 server.setReaderStreamVerifierFactories( getVerifiers( _readVerifiers ) );
                 server.setWriterStreamVerifierFactories( getVerifiers( _writeVerifiers ) );
+                    
             }
             catch ( MalformedURLException e )
             {
@@ -316,6 +347,10 @@
             }
 
             r = new LocalRepositoryM2( server, dp );
+            
+            QualityRange qr = QualityRange.create( _releases, _snapshots );
+            
+            r.setRepositoryQualityRange( qr );
         }
         else
         {
@@ -381,6 +416,15 @@
             }
 
             r = new RemoteRepositoryM2( server, dp );
+            
+            _updatePolicy = System.getProperty( RepositoryUpdatePolicy.SYSTEM_PROPERTY_UPDATE_POLICY, _updatePolicy );
+            
+            if( !Util.isEmpty( _updatePolicy) )
+                ((RemoteRepositoryM2)r).setUpdatePolicy( RepositoryUpdatePolicyFactory.create( _updatePolicy ) );
+            
+            QualityRange qr = QualityRange.create( _releases, _snapshots );
+            
+            r.setRepositoryQualityRange( qr );
         }
 
         return r;
diff --git a/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/WriteTask.java b/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/WriteTask.java
index 0825504..0946835 100644
--- a/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/WriteTask.java
+++ b/mercury-ant-tasks/src/main/java/org/apache/maven/mercury/ant/tasks/WriteTask.java
@@ -25,7 +25,7 @@
 import java.util.Hashtable;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.util.Util;
@@ -165,7 +165,7 @@
 
             if ( !Util.isEmpty( _name ) )
             {
-                a = new DefaultArtifact( new ArtifactBasicMetadata( _name ) );
+                a = new DefaultArtifact( new ArtifactMetadata( _name ) );
 
                 String pomStr =
                     "?xml version='1.0' encoding='UTF-8'?>\n"
diff --git a/mercury-ant-tasks/src/main/resources/org/apache/maven/mercury/ant/tasks/Messages.properties b/mercury-ant-tasks/src/main/resources/org/apache/maven/mercury/ant/tasks/Messages.properties
index caef0e1..7e9185b 100644
--- a/mercury-ant-tasks/src/main/resources/org/apache/maven/mercury/ant/tasks/Messages.properties
+++ b/mercury-ant-tasks/src/main/resources/org/apache/maven/mercury/ant/tasks/Messages.properties
@@ -17,7 +17,7 @@
 empty.map=internal error - please report to the authors: bucket map cannot be empty at this juncture - found {0}
 empty.map.2=internal error 2 - please report to the authors: bucket map cannot be empty at this juncture - found {0}
 resolve.cannot.read=cannot read artifacts from any repository in config {0}. Query is: {1}
-resolve.empty.classpath=resolved classpath for scope {0} is empty.\nDependency that failed to resolve is below:\n{1}
+resolve.empty.classpath=resolved classpath for scope {0} is empty.\nDependency list that failed to resolve is below, for details - turn on debug logging\n{1}
 
 write.repo.id.mandatory=repo id is mandatory for write task - none supplied
 write.repo.not.found=Repository {0} not yet declared in the build file.
diff --git a/mercury-artifact/pom.xml b/mercury-artifact/pom.xml
index daceaaf..d705dd0 100644
--- a/mercury-artifact/pom.xml
+++ b/mercury-artifact/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-artifact</artifactId>
diff --git a/mercury-artifact/src/main/ArtifactMetadata.java b/mercury-artifact/src/main/ArtifactMetadata.java
new file mode 100644
index 0000000..d3a5a55
--- /dev/null
+++ b/mercury-artifact/src/main/ArtifactMetadata.java
@@ -0,0 +1,66 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.artifact;
+
+import java.util.Map;
+
+/**
+ * Artifact Metadata that is resolved independent of Artifact itself. It's built on top of ArtifactBasicMetadata
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ */
+public class ArtifactMetadata
+    extends ArtifactBasicMetadata
+{
+    /**
+     * for testing - required for mock MetadataSource
+     */
+    public ArtifactMetadata()
+    {
+    }
+
+    // ------------------------------------------------------------------
+
+    public ArtifactMetadata( String groupId, String name, String version, String type, ArtifactScopeEnum artifactScope,
+                             String classifier, String artifactUri, String why, boolean resolved, String error,
+                             Map<String, String> attributes )
+    {
+        this.groupId = groupId;
+        this.artifactId = name;
+        setVersion( version );
+        this.type = type;
+        this.artifactScope = artifactScope;
+        this.classifier = classifier;
+        this.artifactUri = artifactUri;
+        this.attributes = attributes;
+    }
+
+    public ArtifactMetadata( ArtifactBasicMetadata bmd )
+    {
+        this( bmd.getGroupId(), bmd.getArtifactId(), bmd.getVersion(), bmd.getType(), null, bmd.getClassifier(), null,
+              null, true, null, bmd.getAttributes() );
+    }
+
+    public ArtifactMetadata( String gav )
+    {
+        this( new ArtifactBasicMetadata( gav ) );
+    }
+
+}
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactBasicMetadata.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactBasicMetadata.java
deleted file mode 100644
index 4ca7107..0000000
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactBasicMetadata.java
+++ /dev/null
@@ -1,661 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.maven.mercury.artifact;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
-import org.apache.maven.mercury.artifact.version.VersionException;
-import org.apache.maven.mercury.artifact.version.VersionRange;
-import org.apache.maven.mercury.artifact.version.VersionRangeFactory;
-import org.codehaus.plexus.lang.DefaultLanguage;
-import org.codehaus.plexus.lang.Language;
-
-/**
- * this is the most primitive metadata there is, usually used to query repository for "real" metadata. It holds
- * everything a project.dependencies.dependency element can have
- *
- * @author Oleg Gusakov
- * @version $Id$
- */
-public class ArtifactBasicMetadata
-{
-    public static final String DEFAULT_ARTIFACT_TYPE = "jar";
-
-    private static final Language LANG = new DefaultLanguage( ArtifactBasicMetadata.class );
-
-
-    /**
-     * standard glorified artifact coordinates
-     */
-    protected String groupId;
-
-    protected String artifactId;
-
-    private String version;
-    
-    private transient VersionRange versionRange;
-
-    /**
-     * relocation chain after processing by ProjectBuilder
-     */
-    protected List<ArtifactCoordinates> relocations;
-
-    protected ArtifactCoordinates effectiveCoordinates;
-
-    // This is Maven specific. jvz/
-    protected String classifier;
-
-    protected String type = DEFAULT_ARTIFACT_TYPE;
-
-    protected ArtifactScopeEnum artifactScope;
-
-    protected String scope;
-
-    protected boolean optional;
-
-    protected Collection<ArtifactBasicMetadata> inclusions;
-
-    protected Collection<ArtifactBasicMetadata> exclusions;
-
-    protected Map<String, String> attributes;
-
-    /**
-     * transient helper objects, used by DependencyBuilder.
-     */
-    transient Object tracker;
-
-    transient Boolean local = false;
-
-    // ------------------------------------------------------------------
-    public ArtifactBasicMetadata()
-    {
-    }
-
-    // ------------------------------------------------------------------
-    private void processAttributes( String as )
-    {
-        if ( as == null || as.length() < 1 )
-        {
-            return;
-        }
-
-        String attrString = as.trim();
-
-        if ( attrString == null || attrString.length() < 1 )
-        {
-            return;
-        }
-
-        int fromCh = attrString.indexOf( '{' );
-        int toCh = attrString.indexOf( '}' );
-
-        if ( fromCh != -1 && toCh != -1 )
-        {
-            attrString = attrString.substring( fromCh + 1, toCh );
-        }
-
-        String[] entries = attrString.split( "," );
-
-        if ( entries != null )
-        {
-            for ( int i = 0; i < entries.length; i++ )
-            {
-                String e = entries[i];
-
-                if ( e == null )
-                {
-                    continue;
-                }
-
-                int eq = e.indexOf( '=' );
-
-                if ( eq == -1 )
-                {
-                    continue;
-                }
-
-                if ( attributes == null )
-                {
-                    attributes = new LinkedHashMap<String, String>( entries.length );
-                }
-
-                String name = e.substring( 0, eq );
-
-                if ( name == null )
-                {
-                    continue;
-                }
-
-                name = name.trim();
-
-                String val = e.substring( eq + 1 );
-
-                if ( val != null )
-                {
-                    val = val.trim();
-                }
-
-                attributes.put( name, val );
-            }
-        }
-    }
-
-    // ------------------------------------------------------------------
-    /**
-     * create basic out of <b>group:artifact:version:classifier:type</b> string, use empty string to specify missing
-     * component - for instance query for common-1.3.zip can be specified as ":common:1.3::zip" - note missing groupId
-     * and classifier.
-     */
-    public ArtifactBasicMetadata( String gavQuery )
-    {
-        if ( gavQuery == null )
-        {
-            return;
-        }
-
-        String[] tokens = gavQuery.split( ":" );
-
-        if ( tokens == null || tokens.length < 1 )
-        {
-            return;
-        }
-
-        int count = tokens.length;
-
-        this.groupId = nullify( tokens[0] );
-
-        if ( count > 1 )
-        {
-            this.artifactId = nullify( tokens[1] );
-        }
-
-        if ( count > 2 )
-        {
-            this.version = nullify( tokens[2] );
-        }
-
-        if ( count > 3 )
-        {
-            this.classifier = nullify( tokens[3] );
-        }
-
-        if ( count > 4 )
-        {
-            this.type = nullify( tokens[4] );
-        }
-
-        if ( this.type == null || this.type.length() < 1 )
-        {
-            this.type = DEFAULT_ARTIFACT_TYPE;
-        }
-
-        if ( count > 5 )
-        {
-            this.scope = nullify( tokens[5] );
-        }
-
-        if ( count > 6 )
-        {
-            processAttributes( nullify( tokens[6] ) );
-        }
-    }
-
-    // ------------------------------------------------------------------
-    /**
-     * create basic out of <b>group:artifact:version:classifier:type</b> string, use empty string to specify missing
-     * component - for instance query for common-1.3.zip can be specified as ":common:1.3::zip" - note missing groupId
-     * and classifier.
-     */
-    public static ArtifactBasicMetadata create( String query )
-    {
-        ArtifactBasicMetadata mdq = new ArtifactBasicMetadata( query );
-
-        return mdq;
-    }
-
-    // ---------------------------------------------------------------------------
-    private static final String nullify( String s )
-    {
-        if ( s == null || s.length() < 1 )
-        {
-            return null;
-        }
-        return s;
-    }
-
-    // ---------------------------------------------------------------------
-    public boolean sameGAV( ArtifactBasicMetadata md )
-    {
-        if ( md == null )
-        {
-            return false;
-        }
-
-        return sameGA( md ) && version != null && version.equals( md.getVersion() );
-    }
-
-    // ---------------------------------------------------------------------
-    public boolean sameGA( ArtifactBasicMetadata md )
-    {
-        if ( md == null )
-        {
-            return false;
-        }
-
-        return groupId != null && artifactId != null && groupId.equals( md.getGroupId() )
-            && artifactId.equals( md.getArtifactId() );
-    }
-
-    public String getGA()
-    {
-        return toDomainString();
-    }
-
-    public String getGAV()
-    {
-        return toString();
-    }
-
-    private static final String nvl( String val, String dflt )
-    {
-        return val == null ? dflt : val;
-    }
-
-    private static final String nvl( String val )
-    {
-        return nvl( val, "" );
-    }
-
-    @Override
-    public String toString()
-    {
-        return nvl( groupId ) + ":" + nvl( artifactId ) + ":" + nvl( version ) + ":" + nvl( classifier ) + ":"
-            + nvl( type, DEFAULT_ARTIFACT_TYPE );
-    }
-
-    public String toScopedString()
-    {
-        return toString() + "-scope:" + getArtifactScope();
-    }
-
-    public String toDomainString()
-    {
-        return groupId + ":" + artifactId;
-    }
-
-    public String toManagementString()
-    {
-        return groupId + ":" + artifactId + ":" + type + ( classifier != null ? ":" + classifier : "" );
-    }
-
-    public String getBaseName()
-    {
-        return artifactId + "-" + version + ( classifier == null ? "" : "-" + classifier );
-    }
-
-    public String getFileName()
-    {
-        return getBaseName() + "." + ( type == null ? DEFAULT_ARTIFACT_TYPE : type );
-    }
-
-    public String getBaseName( String classifier )
-    {
-        return artifactId + "-" + version
-            + ( ( classifier == null || classifier.length() < 1 ) ? "" : "-" + classifier );
-    }
-
-    public String getCheckedType()
-    {
-        return type == null ? "jar" : type;
-    }
-
-    // ---------------------------------------------------------------------------
-    public String getGroupId()
-    {
-        return groupId;
-    }
-
-    public void setGroupId( String groupId )
-    {
-        this.groupId = groupId;
-    }
-
-    public String getArtifactId()
-    {
-        return artifactId;
-    }
-
-    public void setArtifactId( String artifactId )
-    {
-        this.artifactId = artifactId;
-    }
-
-    public String getVersion()
-    {
-        return version;
-    }
-
-    public boolean hasVersion()
-    {
-        return version != null && version.length() > 0;
-    }
-
-    public void setVersion( String version )
-    {
-        this.version = version;
-    }
-    
-    private void checkRangeExists()
-    {
-        if( versionRange == null )
-        {
-            if( version == null )
-                throw new IllegalArgumentException( LANG.getMessage( "artifact.metadata.no.version", toString() ) );
-            else
-            {
-                try
-                {
-                    versionRange = VersionRangeFactory.create( version );
-                }
-                catch ( VersionException e )
-                {
-                    throw new IllegalArgumentException( e.getMessage() );
-                }
-            }
-        }
-    }
-
-    public boolean isSingleton()
-    {
-        checkRangeExists();
-        
-        return versionRange.isSingleton();
-    }
-
-    public boolean isRange()
-    {
-        return !isSingleton();
-    }
-
-    public String getClassifier()
-    {
-        return classifier;
-    }
-
-    public void setClassifier( String classifier )
-    {
-        this.classifier = classifier;
-    }
-
-    public String getType()
-    {
-        return type;
-    }
-
-    public void setType( String type )
-    {
-        this.type = type;
-    }
-
-    public Map<String, String> getAttributes()
-    {
-        return attributes;
-    }
-
-    public String getScope()
-    {
-        return getArtifactScope().getScope();
-    }
-
-    public ArtifactScopeEnum getScopeAsEnum()
-    {
-        return artifactScope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : artifactScope;
-    }
-
-    public ArtifactScopeEnum getArtifactScope()
-    {
-        return artifactScope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : artifactScope;
-    }
-
-    public void setArtifactScope( ArtifactScopeEnum artifactScope )
-    {
-        this.artifactScope = artifactScope;
-    }
-
-    public void setScope( String scope )
-    {
-        this.artifactScope = scope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : ArtifactScopeEnum.valueOf( scope );
-    }
-
-    public boolean isOptional()
-    {
-        return optional;
-    }
-
-    public void setOptional( boolean optional )
-    {
-        this.optional = optional;
-    }
-
-    public void setOptional( String optional )
-    {
-        this.optional = "true".equals( optional );
-    }
-
-    public Object getTracker()
-    {
-        return tracker;
-    }
-
-    public void setTracker( Object tracker )
-    {
-        this.tracker = tracker;
-    }
-
-    public boolean hasClassifier()
-    {
-        return classifier != null && classifier.length() > 0;
-    }
-
-    public Boolean isLocal()
-    {
-        return local;
-    }
-
-    public void setLocal( Boolean local )
-    {
-        this.local = local;
-    }
-
-    public boolean isVirtual()
-    {
-        return DefaultArtifactVersion.isVirtual( version );
-    }
-
-    public ArtifactCoordinates getEffectiveCoordinates()
-    {
-        if ( relocations == null || relocations.isEmpty() )
-        {
-            return new ArtifactCoordinates( groupId, artifactId, version );
-        }
-
-        return relocations.get( relocations.size() - 1 );
-    }
-
-    public ArtifactBasicMetadata addRelocation( ArtifactCoordinates coord )
-    {
-        if ( coord == null )
-        {
-            return this;
-        }
-
-        if ( relocations == null )
-        {
-            relocations = new ArrayList<ArtifactCoordinates>( 2 );
-        }
-
-        if ( coord.getGroupId() == null )
-        {
-            coord.setGroupId( groupId );
-        }
-
-        if ( coord.getArtifactId() == null )
-        {
-            coord.setArtifactId( artifactId );
-        }
-
-        if ( coord.getVersion() == null )
-        {
-            coord.setVersion( version );
-        }
-
-        relocations.add( coord );
-        effectiveCoordinates = coord;
-
-        return this;
-    }
-
-    public String getEffectiveGroupId()
-    {
-        return effectiveCoordinates == null ? groupId : effectiveCoordinates.getGroupId();
-    }
-
-    public String getEffectiveArtifactId()
-    {
-        return effectiveCoordinates == null ? artifactId : effectiveCoordinates.getArtifactId();
-    }
-
-    public String getEffectiveersion()
-    {
-        return effectiveCoordinates == null ? version : effectiveCoordinates.getVersion();
-    }
-
-    public boolean hasInclusions()
-    {
-        return inclusions == null ? false : !inclusions.isEmpty();
-    }
-
-    public Collection<ArtifactBasicMetadata> getInclusions()
-    {
-        return inclusions;
-    }
-
-    public void setInclusions( Collection<ArtifactBasicMetadata> inclusions )
-    {
-        this.inclusions = inclusions;
-    }
-
-    public boolean hasExclusions()
-    {
-        return exclusions == null ? false : !exclusions.isEmpty();
-    }
-
-    public Collection<ArtifactBasicMetadata> getExclusions()
-    {
-        return exclusions;
-    }
-
-    public void setExclusions( Collection<ArtifactBasicMetadata> exclusions )
-    {
-        this.exclusions = exclusions;
-    }
-
-    /**
-     * run dependency through inclusion/exclusion filters. Inclusion filter is always a "hole"-filter, which is then
-     * enhanced by exclusion "cork"-filter
-     *
-     * @param dep dependency to vet
-     * @return vet result
-     * @throws VersionException
-     */
-    public boolean allowDependency( ArtifactBasicMetadata dep )
-        throws VersionException
-    {
-        boolean includeDependency = true;
-        if ( hasInclusions() )
-        {
-            includeDependency = !passesFilter( inclusions, dep );
-        }
-
-        if ( !includeDependency )
-        {
-            return false;
-        }
-
-        if ( !hasExclusions() )
-        {
-            return true;
-        }
-
-        if ( passesFilter( exclusions, dep ) )
-        {
-            return true;
-        }
-
-        return false;
-
-    }
-
-    private boolean passesFilter( Collection<ArtifactBasicMetadata> filter, ArtifactBasicMetadata dep )
-        throws VersionException
-    {
-        for ( ArtifactBasicMetadata filterMd : filter )
-        {
-            if ( filterMd.sameGA( dep ) )
-            {
-                if ( !filterMd.hasVersion() )
-                {
-                    return false; // no version in the filter - catch by GA
-                }
-                VersionRange vr = VersionRangeFactory.create( filterMd.getVersion() );
-                if ( vr.includes( dep.getVersion() ) )
-                {
-                    return false; // catch by version query
-                }
-            }
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        if ( obj == null || !( obj instanceof ArtifactBasicMetadata ) )
-        {
-            return false;
-        }
-
-        return toString().equals( obj.toString() );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return toString().hashCode();
-    }
-
-    // ---------------------------------------------------------------------------
-    // ---------------------------------------------------------------------------
-}
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactExclusionList.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactExclusionList.java
index 3f058f6..4ee5989 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactExclusionList.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactExclusionList.java
@@ -31,7 +31,7 @@
     /**
      * @param md
      */
-    public ArtifactExclusionList( ArtifactBasicMetadata... md )
+    public ArtifactExclusionList( ArtifactMetadata... md )
     {
         super( md );
     }
@@ -39,7 +39,7 @@
     /**
      * @param md
      */
-    public ArtifactExclusionList( Collection<ArtifactBasicMetadata> md )
+    public ArtifactExclusionList( Collection<ArtifactMetadata> md )
     {
         super( md );
     }
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactInclusionList.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactInclusionList.java
index 5491375..c4d929e 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactInclusionList.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactInclusionList.java
@@ -31,7 +31,7 @@
     /**
      * @param md
      */
-    public ArtifactInclusionList( ArtifactBasicMetadata... md )
+    public ArtifactInclusionList( ArtifactMetadata... md )
     {
         super( md );
     }
@@ -39,7 +39,7 @@
     /**
      * @param md
      */
-    public ArtifactInclusionList( Collection<ArtifactBasicMetadata> md )
+    public ArtifactInclusionList( Collection<ArtifactMetadata> md )
     {
         super( md );
     }
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactMetadata.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactMetadata.java
index 93c22e1..2044d16 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactMetadata.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactMetadata.java
@@ -18,68 +18,744 @@
  */
 package org.apache.maven.mercury.artifact;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
+import org.apache.maven.mercury.artifact.version.VersionException;
+import org.apache.maven.mercury.artifact.version.VersionRange;
+import org.apache.maven.mercury.artifact.version.VersionRangeFactory;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
 /**
- * Artifact Metadata that is resolved independent of Artifact itself. It's built on top of ArtifactBasicMetadata
+ * this is the most primitive metadata there is, usually used to query repository for "real" metadata. It holds
+ * everything a project.dependencies.dependency element can have
  *
  * @author Oleg Gusakov
  * @version $Id$
  */
 public class ArtifactMetadata
-    extends ArtifactBasicMetadata
 {
+    public static final String DEFAULT_ARTIFACT_TYPE = "jar";
+
+    private static final Language LANG = new DefaultLanguage( ArtifactMetadata.class );
+
+
+    /**
+     * standard glorified artifact coordinates
+     */
+    protected String groupId;
+
+    protected String artifactId;
+
+    private String version;
+
+    private transient VersionRange versionRange;
+
+    private Quality quality;
+
+    /**
+     * relocation chain after processing by ProjectBuilder
+     */
+    protected List<ArtifactCoordinates> relocations;
+
+    protected ArtifactCoordinates effectiveCoordinates;
+
+    // This is Maven specific. jvz/
+    protected String classifier;
+
+    protected String type = DEFAULT_ARTIFACT_TYPE;
+
+    protected ArtifactScopeEnum artifactScope;
+
+    protected String scope;
+
+    protected boolean optional;
+
+    protected Collection<ArtifactMetadata> inclusions;
+
+    protected Collection<ArtifactMetadata> exclusions;
+
+    protected Map<String, String> attributes;
+
+    /**
+     * transient helper objects, used by DependencyBuilder.
+     */
+    transient Object tracker;
+
+    transient Boolean local = false;
+
+    /**
+     * transient external datum to carry along
+     */
+    transient Object datum;
+    
     /** dependencies of the artifact behind this metadata */
-    protected List<ArtifactBasicMetadata> dependencies;
+    protected List<ArtifactMetadata> dependencies;
 
     /** artifact URI */
     protected String artifactUri;
 
-    /**
-     * for testing - required for mock MetadataSource
-     */
+    // ------------------------------------------------------------------
     public ArtifactMetadata()
     {
     }
 
     // ------------------------------------------------------------------
+    private void processAttributes( String as )
+    {
+        if ( as == null || as.length() < 1 )
+        {
+            return;
+        }
 
-    public ArtifactMetadata( String groupId, String name, String version, String type, ArtifactScopeEnum artifactScope,
-                             String classifier, String artifactUri, String why, boolean resolved, String error,
-                             Map<String, String> attributes )
+        String attrString = as.trim();
+
+        if ( attrString == null || attrString.length() < 1 )
+        {
+            return;
+        }
+
+        int fromCh = attrString.indexOf( '{' );
+        int toCh = attrString.indexOf( '}' );
+
+        if ( fromCh != -1 && toCh != -1 )
+        {
+            attrString = attrString.substring( fromCh + 1, toCh );
+        }
+
+        String[] entries = attrString.split( "," );
+
+        if ( entries != null )
+        {
+            for ( int i = 0; i < entries.length; i++ )
+            {
+                String e = entries[i];
+
+                if ( e == null )
+                {
+                    continue;
+                }
+
+                int eq = e.indexOf( '=' );
+
+                if ( eq == -1 )
+                {
+                    continue;
+                }
+
+                if ( attributes == null )
+                {
+                    attributes = new LinkedHashMap<String, String>( entries.length );
+                }
+
+                String name = e.substring( 0, eq );
+
+                if ( name == null )
+                {
+                    continue;
+                }
+
+                name = name.trim();
+
+                String val = e.substring( eq + 1 );
+
+                if ( val != null )
+                {
+                    val = val.trim();
+                }
+
+                attributes.put( name, val );
+            }
+        }
+    }
+
+    // ------------------------------------------------------------------
+    /**
+     * create basic out of <b>group:artifact:version:classifier:type</b> string, use empty string to specify missing
+     * component - for instance query for common-1.3.zip can be specified as ":common:1.3::zip" - note missing groupId
+     * and classifier.
+     */
+    public ArtifactMetadata( String gavQuery )
+    {
+        if ( gavQuery == null )
+        {
+            return;
+        }
+
+        String[] tokens = gavQuery.split( ":" );
+
+        if ( tokens == null || tokens.length < 1 )
+        {
+            return;
+        }
+
+        int count = tokens.length;
+
+        this.groupId = nullify( tokens[0] );
+
+        if ( count > 1 )
+        {
+            this.artifactId = nullify( tokens[1] );
+        }
+
+        if ( count > 2 )
+        {
+            this.version = nullify( tokens[2] );
+        }
+
+        if ( count > 3 )
+        {
+            this.classifier = nullify( tokens[3] );
+        }
+
+        if ( count > 4 )
+        {
+            setType( nullify( tokens[4] ) );
+        }
+
+        if ( this.type == null || this.type.length() < 1 )
+        {
+            this.type = DEFAULT_ARTIFACT_TYPE;
+        }
+
+        if ( count > 5 )
+        {
+            this.scope = nullify( tokens[5] );
+        }
+
+        if ( count > 6 )
+        {
+            processAttributes( nullify( tokens[6] ) );
+        }
+    }
+    
+    /**
+     * copy constructor
+     * 
+     * @param copyFrom
+     */
+    public ArtifactMetadata( ArtifactMetadata copyFrom )
+    {
+        if( copyFrom == null )
+            throw new IllegalArgumentException( LANG.getMessage( "null.copy.from.md") );
+
+       setGroupId( copyFrom.getGroupId() );
+       setArtifactId( copyFrom.getArtifactId() );
+       setVersion( copyFrom.getVersion() );
+       setClassifier( copyFrom.getClassifier() );
+       setType( copyFrom.getType() );
+       setScope( copyFrom.getScope() );
+       
+       Map<String, String> a = copyFrom.getAttributes(); 
+       if(  a != null && a.size() > 0 )
+       {
+           attributes = new HashMap<String, String>( a.size() );
+           
+           attributes.putAll( a );
+       }
+       
+       setTracker( copyFrom.getTracker() );
+       
+    }
+
+    // ------------------------------------------------------------------
+    /**
+     * create basic out of <b>group:artifact:version:classifier:type</b> string, use empty string to specify missing
+     * component - for instance query for common-1.3.zip can be specified as ":common:1.3::zip" - note missing groupId
+     * and classifier.
+     */
+    public static ArtifactMetadata create( String query )
+    {
+        ArtifactMetadata mdq = new ArtifactMetadata( query );
+
+        return mdq;
+    }
+
+    // ---------------------------------------------------------------------------
+    private static final String nullify( String s )
+    {
+        if ( s == null || s.length() < 1 )
+        {
+            return null;
+        }
+        return s;
+    }
+
+    // ---------------------------------------------------------------------
+    public boolean sameGAV( ArtifactMetadata md )
+    {
+        if ( md == null )
+        {
+            return false;
+        }
+
+        return sameGA( md ) && version != null && version.equals( md.getVersion() );
+    }
+
+    // ---------------------------------------------------------------------
+    public boolean sameGA( ArtifactMetadata md )
+    {
+        if ( md == null )
+        {
+            return false;
+        }
+
+        return groupId != null && artifactId != null && groupId.equals( md.getGroupId() )
+            && artifactId.equals( md.getArtifactId() );
+    }
+
+    public String getGA()
+    {
+        return toDomainString();
+    }
+
+    public String getGAV()
+    {
+        return toString();
+    }
+
+    private static final String nvl( String val, String dflt )
+    {
+        return val == null ? dflt : val;
+    }
+
+    private static final String nvl( String val )
+    {
+        return nvl( val, "" );
+    }
+
+    @Override
+    public String toString()
+    {
+        return nvl( groupId ) + ":" + nvl( artifactId ) + ":" + nvl( version ) + ":" + nvl( classifier ) + ":"
+            + nvl( type, DEFAULT_ARTIFACT_TYPE );
+    }
+
+    public String toScopedString()
+    {
+        return toString() + "-scope:" + getArtifactScope();
+    }
+
+    public String toDomainString()
+    {
+        return groupId + ":" + artifactId;
+    }
+
+    public String toManagementString()
+    {
+        return groupId + ":" + artifactId + ":" + type + ( classifier != null ? ":" + classifier : "" );
+    }
+
+    public String getBaseName()
+    {
+        return artifactId + "-" + version + ( classifier == null ? "" : "-" + classifier );
+    }
+
+    public String getFileName()
+    {
+        return getBaseName() + "." + ( type == null ? DEFAULT_ARTIFACT_TYPE : type );
+    }
+
+    public String getBaseName( String classifier )
+    {
+        return artifactId + "-" + version
+            + ( ( classifier == null || classifier.length() < 1 ) ? "" : "-" + classifier );
+    }
+
+    public String getCheckedType()
+    {
+        return type == null ? "jar" : type;
+    }
+
+    // ---------------------------------------------------------------------------
+    public String getGroupId()
+    {
+        return groupId;
+    }
+
+    public void setGroupId( String groupId )
     {
         this.groupId = groupId;
-        this.artifactId = name;
-        setVersion( version );
-        this.type = type;
-        this.artifactScope = artifactScope;
+    }
+
+    public String getArtifactId()
+    {
+        return artifactId;
+    }
+
+    public void setArtifactId( String artifactId )
+    {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public boolean hasVersion()
+    {
+        return version != null && version.length() > 0;
+    }
+
+    public void setVersion( String version )
+    {
+        this.version = version;
+    }
+    
+    private void checkRangeExists()
+    {
+        if( versionRange == null )
+        {
+            if( version == null )
+                throw new IllegalArgumentException( LANG.getMessage( "artifact.metadata.no.version", toString() ) );
+            else
+            {
+                try
+                {
+                    versionRange = VersionRangeFactory.create( version );
+                }
+                catch ( VersionException e )
+                {
+                    throw new IllegalArgumentException( e.getMessage() );
+                }
+            }
+        }
+    }
+
+    public boolean isSingleton()
+    {
+        checkRangeExists();
+        
+        return versionRange.isSingleton();
+    }
+
+    public boolean isRange()
+    {
+        return !isSingleton();
+    }
+
+    /** code quality used to decide whether try or skip a repository - see repository code quality  */
+    public Quality getRequestedQuality()
+    {
+        if( isRange() )
+            return null;
+        
+        if( isVirtual() )
+        {
+            if( isVirtualSnapshot() )
+                return Quality.SNAPSHOT_QUALITY;
+            else
+                if( isVirtualRelease() )
+                    return Quality.RELEASE_QUALITY;
+            
+            return null;
+        }
+        
+        if( quality != null )
+            return quality;
+        
+        quality = new Quality( getVersion() );
+        
+        return quality;
+    }
+
+    public String getClassifier()
+    {
+        return classifier;
+    }
+
+    public void setClassifier( String classifier )
+    {
         this.classifier = classifier;
-        this.artifactUri = artifactUri;
-        this.attributes = attributes;
     }
 
-    public ArtifactMetadata( ArtifactBasicMetadata bmd )
+    public String getType()
     {
-        this( bmd.getGroupId(), bmd.getArtifactId(), bmd.getVersion(), bmd.getType(), null, bmd.getClassifier(), null,
-              null, true, null, bmd.getAttributes() );
+        return type;
     }
 
-    public ArtifactMetadata( Artifact af )
+    public void setType( String type )
     {
+        if( "test-jar".equals( type ) )
+        {
+            setClassifier( "tests" );
+            setType( "jar" );
+        }
+        else
+            this.type = type;
     }
 
-    public ArtifactMetadata( String gav )
+    public Map<String, String> getAttributes()
     {
-        this( new ArtifactBasicMetadata( gav ) );
+        return attributes;
     }
 
-    public List<ArtifactBasicMetadata> getDependencies()
+    public String getScope()
+    {
+        return getArtifactScope().getScope();
+    }
+
+    public ArtifactScopeEnum getScopeAsEnum()
+    {
+        return artifactScope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : artifactScope;
+    }
+
+    public ArtifactScopeEnum getArtifactScope()
+    {
+        return artifactScope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : artifactScope;
+    }
+
+    public void setArtifactScope( ArtifactScopeEnum artifactScope )
+    {
+        this.artifactScope = artifactScope;
+    }
+
+    public void setScope( String scope )
+    {
+        this.artifactScope = scope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : ArtifactScopeEnum.valueOf( scope );
+    }
+
+    public boolean isOptional()
+    {
+        return optional;
+    }
+
+    public void setOptional( boolean optional )
+    {
+        this.optional = optional;
+    }
+
+    public void setOptional( String optional )
+    {
+        this.optional = "true".equals( optional );
+    }
+
+    public Object getTracker()
+    {
+        return tracker;
+    }
+
+    public void setTracker( Object tracker )
+    {
+        this.tracker = tracker;
+    }
+
+    public boolean hasClassifier()
+    {
+        return classifier != null && classifier.length() > 0;
+    }
+
+    public Boolean isLocal()
+    {
+        return local;
+    }
+
+    public void setLocal( Boolean local )
+    {
+        this.local = local;
+    }
+    
+    public boolean isPom()
+    {
+        return "pom".regionMatches( 0, type, 0, 3 );
+    }
+
+    public boolean isVirtual()
+    {
+        return DefaultArtifactVersion.isVirtual( version );
+    }
+
+    public boolean isVirtualSnapshot()
+    {
+        return DefaultArtifactVersion.isVirtualSnapshot( version );
+    }
+
+    public boolean isVirtualRelease()
+    {
+        return DefaultArtifactVersion.isVirtualRelease( version );
+    }
+
+    public boolean isVirtualLatest()
+    {
+        return DefaultArtifactVersion.isVirtualLatest( version );
+    }
+
+    public ArtifactCoordinates getEffectiveCoordinates()
+    {
+        if ( relocations == null || relocations.isEmpty() )
+        {
+            return new ArtifactCoordinates( groupId, artifactId, version );
+        }
+
+        return relocations.get( relocations.size() - 1 );
+    }
+
+    public ArtifactMetadata addRelocation( ArtifactCoordinates coord )
+    {
+        if ( coord == null )
+        {
+            return this;
+        }
+
+        if ( relocations == null )
+        {
+            relocations = new ArrayList<ArtifactCoordinates>( 2 );
+        }
+
+        if ( coord.getGroupId() == null )
+        {
+            coord.setGroupId( groupId );
+        }
+
+        if ( coord.getArtifactId() == null )
+        {
+            coord.setArtifactId( artifactId );
+        }
+
+        if ( coord.getVersion() == null )
+        {
+            coord.setVersion( version );
+        }
+
+        relocations.add( coord );
+        effectiveCoordinates = coord;
+
+        return this;
+    }
+
+    public String getEffectiveGroupId()
+    {
+        return effectiveCoordinates == null ? groupId : effectiveCoordinates.getGroupId();
+    }
+
+    public String getEffectiveArtifactId()
+    {
+        return effectiveCoordinates == null ? artifactId : effectiveCoordinates.getArtifactId();
+    }
+
+    public String getEffectiveersion()
+    {
+        return effectiveCoordinates == null ? version : effectiveCoordinates.getVersion();
+    }
+
+    public boolean hasInclusions()
+    {
+        return inclusions == null ? false : !inclusions.isEmpty();
+    }
+
+    public Collection<ArtifactMetadata> getInclusions()
+    {
+        return inclusions;
+    }
+
+    public void setInclusions( Collection<ArtifactMetadata> inclusions )
+    {
+        this.inclusions = inclusions;
+    }
+
+    public boolean hasExclusions()
+    {
+        return exclusions == null ? false : !exclusions.isEmpty();
+    }
+
+    public Collection<ArtifactMetadata> getExclusions()
+    {
+        return exclusions;
+    }
+
+    public void setExclusions( Collection<ArtifactMetadata> exclusions )
+    {
+        this.exclusions = exclusions;
+    }
+
+    /**
+     * run dependency through inclusion/exclusion filters. Inclusion filter is always a "hole"-filter, which is then
+     * enhanced by exclusion "cork"-filter
+     *
+     * @param dep dependency to vet
+     * @return vet result
+     * @throws VersionException
+     */
+    public boolean allowDependency( ArtifactMetadata dep )
+        throws VersionException
+    {
+        boolean includeDependency = true;
+        if ( hasInclusions() )
+        {
+            includeDependency = !passesFilter( inclusions, dep );
+        }
+
+        if ( !includeDependency )
+        {
+            return false;
+        }
+
+        if ( !hasExclusions() )
+        {
+            return true;
+        }
+
+        if ( passesFilter( exclusions, dep ) )
+        {
+            return true;
+        }
+
+        return false;
+
+    }
+
+    private boolean passesFilter( Collection<ArtifactMetadata> filter, ArtifactMetadata dep )
+        throws VersionException
+    {
+        for ( ArtifactMetadata filterMd : filter )
+        {
+            if ( filterMd.sameGA( dep ) )
+            {
+                if ( !filterMd.hasVersion() )
+                {
+                    return false; // no version in the filter - catch by GA
+                }
+                VersionRange vr = VersionRangeFactory.create( filterMd.getVersion() );
+                if ( vr.includes( dep.getVersion() ) )
+                {
+                    return false; // catch by version query
+                }
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( obj == null || !( obj instanceof ArtifactMetadata ) )
+        {
+            return false;
+        }
+
+        return toString().equals( obj.toString() );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return toString().hashCode();
+    }
+
+    public List<ArtifactMetadata> getDependencies()
     {
         return dependencies;
     }
 
-    public void setDependencies( List<ArtifactBasicMetadata> dependencies )
+    public void setDependencies( List<ArtifactMetadata> dependencies )
     {
         this.dependencies = dependencies;
     }
@@ -94,4 +770,15 @@
         this.artifactUri = artifactUri;
     }
 
+    public Object getDatum()
+    {
+        return datum;
+    }
+
+    public void setDatum( Object datum )
+    {
+        this.datum = datum;
+    }
+    // ---------------------------------------------------------------------------
+    // ---------------------------------------------------------------------------
 }
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactMetadataList.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactMetadataList.java
index 33972c9..f17baac 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactMetadataList.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactMetadataList.java
@@ -28,15 +28,15 @@
  */
 public abstract class ArtifactMetadataList
 {
-    List<ArtifactBasicMetadata> _artifacts = new ArrayList<ArtifactBasicMetadata>( 8 );
+    List<ArtifactMetadata> _artifacts = new ArrayList<ArtifactMetadata>( 8 );
 
-    public ArtifactMetadataList( ArtifactBasicMetadata... md )
+    public ArtifactMetadataList( ArtifactMetadata... md )
     {
-        for ( ArtifactBasicMetadata m : md )
+        for ( ArtifactMetadata m : md )
             add( m );
     }
 
-    public ArtifactMetadataList( Collection<ArtifactBasicMetadata> md )
+    public ArtifactMetadataList( Collection<ArtifactMetadata> md )
     {
         add( md );
     }
@@ -44,33 +44,33 @@
     public ArtifactMetadataList( String... mds )
     {
         for ( String m : mds )
-            add( new ArtifactBasicMetadata( m ) );
+            add( new ArtifactMetadata( m ) );
     }
 
-    public void add( ArtifactBasicMetadata md )
+    public void add( ArtifactMetadata md )
     {
         _artifacts.add( md );
     }
 
-    public void add( Collection<ArtifactBasicMetadata> md )
+    public void add( Collection<ArtifactMetadata> md )
     {
         _artifacts.addAll( md );
     }
 
     public void addGav( String md )
     {
-        _artifacts.add( new ArtifactBasicMetadata( md ) );
+        _artifacts.add( new ArtifactMetadata( md ) );
     }
 
     public void addByGav( Collection<String> mds )
     {
         for ( String m : mds )
         {
-            _artifacts.add( new ArtifactBasicMetadata( m ) );
+            _artifacts.add( new ArtifactMetadata( m ) );
         }
     }
 
-    public List<ArtifactBasicMetadata> getMetadataList()
+    public List<ArtifactMetadata> getMetadataList()
     {
         return _artifacts;
     }
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactQueryList.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactQueryList.java
index 8857fb8..487b0e1 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactQueryList.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/ArtifactQueryList.java
@@ -31,7 +31,7 @@
     /**
      * @param md
      */
-    public ArtifactQueryList( ArtifactBasicMetadata... md )
+    public ArtifactQueryList( ArtifactMetadata... md )
     {
         super( md );
     }
@@ -39,7 +39,7 @@
     /**
      * @param md
      */
-    public ArtifactQueryList( Collection<ArtifactBasicMetadata> md )
+    public ArtifactQueryList( Collection<ArtifactMetadata> md )
     {
         super( md );
     }
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/DefaultArtifact.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/DefaultArtifact.java
index fee4141..f6f47e3 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/DefaultArtifact.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/DefaultArtifact.java
@@ -35,19 +35,14 @@
     private String inheritedScope;
 
     private byte[] pomBlob;
+    
+    /** 
+     * for temporary holding the reference
+     *  to the pom file during data transfer
+     */
+    transient private File pomFile;
 
-    public DefaultArtifact( String groupId, String artifactId, String version, String type, String classifier,
-                            boolean optional, String scope, String inheritedScope )
-    {
-        if ( version == null )
-        {
-            throw new IllegalArgumentException( "Version cannot be null." );
-        }
-
-        initialize( groupId, artifactId, version, type, classifier, optional, scope, inheritedScope );
-    }
-
-    public DefaultArtifact( ArtifactBasicMetadata bmd )
+    public DefaultArtifact( ArtifactMetadata bmd )
     {
         if ( bmd.getVersion() == null )
         {
@@ -156,6 +151,16 @@
         return file;
     }
 
+    public void setPomFile( File file )
+    {
+        this.pomFile = file;
+    }
+
+    public File getPomFile()
+    {
+        return pomFile;
+    }
+
     public void setStream( InputStream stream )
     {
         this.stream = stream;
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/Messages.properties b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/Messages.properties
index 0305f64..855d544 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/Messages.properties
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/Messages.properties
@@ -18,3 +18,6 @@
 #
 
 artifact.metadata.no.version=no version in this metadata: {0}
+null.copy.from.md=cannot create a copy of a null metadata
+
+quality.no.sn.no.rel=cannot decide how to create a quality range when releases=false and snapshots=false
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/MetadataTreeNode.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/MetadataTreeNode.java
new file mode 100644
index 0000000..5c3e460
--- /dev/null
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/MetadataTreeNode.java
@@ -0,0 +1,399 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.artifact;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
+
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+/**
+ * metadata [dirty] Tree
+ * 
+ * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
+ */
+public class MetadataTreeNode
+{
+    /** prevailing # of queries (dependencies) in the dirty tree node */
+    private static final int DEFAULT_QUERY_COUNT = 8;
+
+    /** prevailing # of children in the dirty tree node. If all queries are ranges - 2 hits per range */
+    private static final int DEFAULT_CHILDREN_COUNT = 16;
+
+    private static final Language LANG = new DefaultLanguage( MetadataTreeNode.class );
+
+    /**
+     * this node's artifact MD
+     */
+    ArtifactMetadata md;
+
+    /**
+     * fail resolution if it could not be found?
+     */
+    boolean optional = false;
+
+    /**
+     * is there a real artifact behind this node, or it's just a helper ?
+     */
+    boolean real = true;
+
+    /**
+     * parent node
+     */
+    MetadataTreeNode parent;
+
+    /**
+     * node unique id, used to identify this node in external tree manipulations, such as
+     */
+    int id;
+
+    /**
+     * query node - the one that originated this actual node
+     */
+    ArtifactMetadata query;
+
+    /**
+     * queries - one per POM dependency
+     */
+    List<ArtifactMetadata> queries;
+
+    /**
+     * actual found versions
+     */
+    List<MetadataTreeNode> children;
+    
+    /** unique name of this node. Used in SAT solver */
+    String name;
+
+    // ------------------------------------------------------------------------
+    public int countNodes()
+    {
+        return countNodes( this );
+    }
+
+    // ------------------------------------------------------------------------
+    public static int countNodes( MetadataTreeNode node )
+    {
+        int res = 1;
+
+        if ( node.children != null && node.children.size() > 0 )
+        {
+            for ( MetadataTreeNode child : node.children )
+            {
+                res += countNodes( child );
+            }
+        }
+
+        return res;
+    }
+
+    // ------------------------------------------------------------------------
+    public int countDistinctNodes()
+    {
+        TreeSet<String> nodes = new TreeSet<String>();
+
+        getDistinctNodes( this, nodes );
+
+        return nodes.size();
+    }
+
+    // ------------------------------------------------------------------------
+    public static void getDistinctNodes( MetadataTreeNode node, TreeSet<String> nodes )
+    {
+        if ( node.getMd() == null )
+            throw new IllegalArgumentException( "tree node without metadata" );
+
+        nodes.add( node.getMd().getGAV() );
+
+        if ( node.children != null && node.children.size() > 0 )
+            for ( MetadataTreeNode child : node.children )
+                getDistinctNodes( child, nodes );
+    }
+
+    // ------------------------------------------------------------------------
+    public MetadataTreeNode()
+    {
+    }
+
+    // ------------------------------------------------------------------------
+    /**
+     * pointers to parent and query are a must.
+     */
+    public MetadataTreeNode( ArtifactMetadata md, MetadataTreeNode parent, ArtifactMetadata query )
+    {
+        if ( md != null )
+        {
+            md.setArtifactScope( ArtifactScopeEnum.checkScope( md.getArtifactScope() ) );
+        }
+
+        this.md = md;
+        this.parent = parent;
+        this.query = query;
+    }
+
+    // ------------------------------------------------------------------------
+    /**
+     * dependencies are ordered in the POM - they should be added in the POM order
+     */
+    public MetadataTreeNode addChild( MetadataTreeNode kid )
+    {
+        if ( kid == null )
+        {
+            return this;
+        }
+
+        if ( children == null )
+        {
+            children = new ArrayList<MetadataTreeNode>( DEFAULT_CHILDREN_COUNT );
+        }
+
+        kid.setParent( this );
+        children.add( kid );
+
+        return this;
+    }
+
+    // ------------------------------------------------------------------------
+    /**
+     * dependencies are ordered in the POM - they should be added in the POM order
+     */
+    public MetadataTreeNode addQuery( ArtifactMetadata query )
+    {
+        if ( query == null )
+        {
+            return this;
+        }
+
+        if ( queries == null )
+        {
+            queries = new ArrayList<ArtifactMetadata>( DEFAULT_QUERY_COUNT );
+        }
+
+        queries.add( query );
+
+        return this;
+    }
+
+    // ------------------------------------------------------------------
+    @Override
+    public String toString()
+    {
+        return md == null ? "no metadata, parent " + ( parent == null ? "null" : parent.toString() ) : md.toString()
+            + ":d=" + getDepth();
+    }
+
+    // ------------------------------------------------------------------------
+    public boolean hasChildren()
+    {
+        return children != null;
+    }
+
+    // ------------------------------------------------------------------------
+    public ArtifactMetadata getMd()
+    {
+        return md;
+    }
+
+    public MetadataTreeNode getParent()
+    {
+        return parent;
+    }
+
+    public int getDepth()
+    {
+        int depth = 0;
+
+        for ( MetadataTreeNode p = parent; p != null; p = p.parent )
+            ++depth;
+
+        return depth;
+    }
+
+    public int getMaxDepth( int depth )
+    {
+        int res = 0;
+
+        if ( !hasChildren() )
+            return depth + 1;
+
+        for ( MetadataTreeNode kid : children )
+        {
+            int kidDepth = kid.getMaxDepth( depth + 1 );
+            if ( kidDepth > res )
+                res = kidDepth;
+        }
+
+        return res;
+    }
+
+    public void setParent( MetadataTreeNode parent )
+    {
+        this.parent = parent;
+    }
+
+    public List<MetadataTreeNode> getChildren()
+    {
+        return children;
+    }
+
+    public boolean isOptional()
+    {
+        return optional;
+    }
+
+    public boolean isReal()
+    {
+        return real;
+    }
+
+    public void setReal( boolean real)
+    {
+        this.real = real;
+    }
+
+    public ArtifactMetadata getQuery()
+    {
+        return query;
+    }
+
+    public List<ArtifactMetadata> getQueries()
+    {
+        return queries;
+    }
+
+    // ------------------------------------------------------------------------
+    public static final MetadataTreeNode deepCopy( MetadataTreeNode node )
+    {
+        MetadataTreeNode res = new MetadataTreeNode( node.getMd(), node.getParent(), node.getQuery() );
+        res.setId( node.getId() );
+
+        if ( node.hasChildren() )
+            for ( MetadataTreeNode kid : node.children )
+            {
+                MetadataTreeNode deepKid = deepCopy( kid );
+                res.addChild( deepKid );
+            }
+
+        return res;
+    }
+
+    // ----------------------------------------------------------------
+    /**
+     * helper method to print the tree into a Writer
+     */
+    public static final void showNode( MetadataTreeNode n, int level, Writer wr )
+        throws IOException
+    {
+        if( n == null )
+        {
+            wr.write( "null node" );
+            return;
+        }
+        for ( int i = 0; i < level; i++ )
+            wr.write( "  " );
+
+        wr.write( level + " " + n.getMd() + "\n" );
+
+        if ( n.hasChildren() )
+        {
+            for ( MetadataTreeNode kid : n.getChildren() )
+                showNode( kid, level + 1, wr );
+        }
+    }
+
+    // ----------------------------------------------------------------
+    /**
+     * helper method to print the tree into sysout
+     */
+    public static final void showNode( MetadataTreeNode n, int level )
+        throws IOException
+    {
+        StringWriter sw = new StringWriter();
+        MetadataTreeNode.showNode( n, 0, sw );
+        System.out.println( sw.toString() );
+    }
+
+    // ------------------------------------------------------------------------
+    public int getId()
+    {
+        return id;
+    }
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    // ------------------------------------------------------------------------
+    public static void reNumber( MetadataTreeNode node, int startNum )
+    {
+        reNum( node, new Counter( startNum ) );
+    }
+
+    // ------------------------------------------------------------------------
+    private static void reNum( MetadataTreeNode node, Counter num )
+    {
+        node.setId( num.next() );
+
+        if ( node.hasChildren() )
+            for ( MetadataTreeNode kid : node.getChildren() )
+                reNum( kid, num );
+    }
+    
+    public String getName()
+    {
+        return name;
+    }
+
+    public void createNames( int level, int seq )
+    {
+        name = md.toScopedString()+":"+level+"."+seq;
+        
+        if( hasChildren() )
+        {
+            int no = 0;
+            
+            for( MetadataTreeNode kid : children )
+                kid.createNames( level+1, no++ );
+        }
+    }
+    // ------------------------------------------------------------------------
+    // ------------------------------------------------------------------------
+}
+
+// ------------------------------------------------------------------------
+class Counter
+{
+    int n;
+
+    public Counter( int n )
+    {
+        this.n = n;
+    }
+
+    int next()
+    {
+        return n++;
+    }
+}
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/QualityRange.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/QualityRange.java
index e5c986a..a60c186 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/QualityRange.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/QualityRange.java
@@ -18,12 +18,17 @@
  */
 package org.apache.maven.mercury.artifact;
 
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
 /**
  * @author Oleg Gusakov
  * @version $Id$
  */
 public class QualityRange
 {
+    private static final Language LANG = new DefaultLanguage( QualityRange.class );
+    
     public static final QualityRange SNAPSHOTS_ONLY =
         new QualityRange( Quality.SNAPSHOT_QUALITY, true, Quality.SNAPSHOT_TS_QUALITY, true );
 
@@ -61,13 +66,28 @@
         this.qualityTo = qualityTo;
         this.toInclusive = toInclusive;
     }
+    
+    public static QualityRange create( boolean releases, boolean snapshots )
+    {
+        if( releases && snapshots )
+            return ALL;
+        else
+            if( releases )
+                return new QualityRange( Quality.ALPHA_QUALITY, true, Quality.RELEASE_QUALITY, true );
+            else
+                if( snapshots )
+                    return new QualityRange( Quality.SNAPSHOT_QUALITY, true, Quality.SNAPSHOT_TS_QUALITY, true );
+        
+        throw new IllegalArgumentException( LANG.getMessage( "quality.no.sn.no.rel" ) );
+    }
 
     // ---------------------------------------------------------------------------
     public boolean isAcceptedQuality( Quality quality )
     {
+        // null quality means anything goes
         if ( quality == null )
         {
-            return false;
+            return true;
         }
 
         int from = quality.compareTo( qualityFrom );
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ArtifactListProcessor.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ArtifactListProcessor.java
index 0a37001..86e7229 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ArtifactListProcessor.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ArtifactListProcessor.java
@@ -21,7 +21,7 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 
 /**
  * generic interface to be implemented by helper components
@@ -54,6 +54,6 @@
      *
      * @throws ArtifactListProcessorException
      */
-    public List<ArtifactBasicMetadata> process( List<ArtifactBasicMetadata> artifacts )
+    public List<ArtifactMetadata> process( List<ArtifactMetadata> artifacts )
         throws ArtifactListProcessorException;
 }
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/Configurable.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/Configurable.java
index 591d90a..f9db94a 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/Configurable.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/Configurable.java
@@ -20,7 +20,7 @@
 
 /**
  * provides a way to configure an object instance, if that object supports the idea
- *
+ * 
  * @author Oleg Gusakov
  * @version $Id$
  */
@@ -29,9 +29,10 @@
 
     /**
      * configure this instance
-     *
+     * 
      * @param name of the configurable property
      * @param val configuration value
      */
-    public void setOption( String name, String val );
+    public void setOption( String name, Object val )
+        throws ConfigurationException;
 }
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ConfigurationException.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ConfigurationException.java
new file mode 100644
index 0000000..f32fc77
--- /dev/null
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ConfigurationException.java
@@ -0,0 +1,26 @@
+package org.apache.maven.mercury.artifact.api;
+
+public class ConfigurationException
+    extends Exception
+{
+
+    public ConfigurationException()
+    {
+    }
+
+    public ConfigurationException( String message )
+    {
+        super( message );
+    }
+
+    public ConfigurationException( Throwable cause )
+    {
+        super( cause );
+    }
+
+    public ConfigurationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+}
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ConfigurationUtil.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ConfigurationUtil.java
new file mode 100644
index 0000000..c16f0fa
--- /dev/null
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/api/ConfigurationUtil.java
@@ -0,0 +1,42 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.maven.mercury.artifact.api;
+
+import java.util.Map;
+
+/**
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class ConfigurationUtil
+{
+    public static void configure( Configurable impl, Map<String,Object> config )
+    throws ConfigurationException
+    {
+        if( impl == null || config == null )
+            return;
+        
+        for( Map.Entry<String, Object> e : config.entrySet() )
+            impl.setOption( e.getKey(), e.getValue() );
+    }
+}
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/DefaultArtifactVersion.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/DefaultArtifactVersion.java
index 4d279d1..e2d1584 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/DefaultArtifactVersion.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/DefaultArtifactVersion.java
@@ -128,6 +128,39 @@
         return false;
     }
 
+    public static boolean isVirtualRelease( String version )
+    {
+        if ( version == null )
+            return false;
+
+        if ( version.endsWith( Artifact.RELEASE_VERSION ) )
+            return true;
+
+        return false;
+    }
+
+    public static boolean isVirtualLatest( String version )
+    {
+        if ( version == null )
+            return false;
+
+        if ( version.endsWith( Artifact.LATEST_VERSION ) )
+            return true;
+
+        return false;
+    }
+
+    public static boolean isVirtualSnapshot( String version )
+    {
+        if ( version == null )
+            return false;
+
+        if ( version.endsWith( Artifact.SNAPSHOT_VERSION ) )
+            return true;
+
+        return false;
+    }
+
     public final void parseVersion( String version )
     {
         comparable = new ComparableVersion( version );
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/MavenVersionRange.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/MavenVersionRange.java
index 2e9adac..7aa0a53 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/MavenVersionRange.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/MavenVersionRange.java
@@ -259,14 +259,14 @@
         return false;
     }
 
-    public void setOption( String name, String val )
+    public void setOption( String name, Object val )
     {
         if ( SYSTEM_PARAMETER_OSGI_VERSION.equals( name ) )
         {
-            _osgiVersion = Boolean.parseBoolean( System.getProperty( val, SYSTEM_PARAMETER_OSGI_VERSION_DEFAULT ) );
+            _osgiVersion = Boolean.parseBoolean( System.getProperty( (String)val, SYSTEM_PARAMETER_OSGI_VERSION_DEFAULT ) );
         }
     }
-
+    
     public boolean isSingleton()
     {
         return _singleton;
diff --git a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/MetadataVersionComparator.java b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/MetadataVersionComparator.java
index bee6677..079e3c8 100644
--- a/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/MetadataVersionComparator.java
+++ b/mercury-artifact/src/main/java/org/apache/maven/mercury/artifact/version/MetadataVersionComparator.java
@@ -20,7 +20,7 @@
 
 import java.util.Comparator;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.codehaus.plexus.lang.DefaultLanguage;
 import org.codehaus.plexus.lang.Language;
 
@@ -31,11 +31,11 @@
  * @version $Id$
  */
 public class MetadataVersionComparator
-    implements Comparator<ArtifactBasicMetadata>
+    implements Comparator<ArtifactMetadata>
 {
     private static final Language _lang = new DefaultLanguage( MetadataVersionComparator.class );
 
-    public int compare( ArtifactBasicMetadata v1, ArtifactBasicMetadata v2 )
+    public int compare( ArtifactMetadata v1, ArtifactMetadata v2 )
     {
         if ( v1 == null || v2 == null )
         {
diff --git a/mercury-artifact/src/test/java/org/apache/maven/mercury/artifact/ArtifactMetadataTest.java b/mercury-artifact/src/test/java/org/apache/maven/mercury/artifact/ArtifactMetadataTest.java
new file mode 100644
index 0000000..f680544
--- /dev/null
+++ b/mercury-artifact/src/test/java/org/apache/maven/mercury/artifact/ArtifactMetadataTest.java
@@ -0,0 +1,42 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.maven.mercury.artifact;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class ArtifactMetadataTest
+    extends TestCase
+{
+    public void testTestJar()
+    {
+        ArtifactMetadata md = new ArtifactMetadata("a:a:1::test-jar");
+        
+        assertEquals( "tests", md.getClassifier() );
+        
+        assertEquals( "jar", md.getType() );
+    }
+}
diff --git a/mercury-artifact/src/test/java/org/apache/maven/mercury/artifact/DependencyFilterTest.java b/mercury-artifact/src/test/java/org/apache/maven/mercury/artifact/DependencyFilterTest.java
index a513125..9336fad 100644
--- a/mercury-artifact/src/test/java/org/apache/maven/mercury/artifact/DependencyFilterTest.java
+++ b/mercury-artifact/src/test/java/org/apache/maven/mercury/artifact/DependencyFilterTest.java
@@ -31,34 +31,34 @@
 public class DependencyFilterTest
     extends TestCase
 {
-    ArtifactBasicMetadata a1;
+    ArtifactMetadata a1;
 
-    ArtifactBasicMetadata a2;
+    ArtifactMetadata a2;
 
-    ArtifactBasicMetadata a3;
+    ArtifactMetadata a3;
 
-    ArtifactBasicMetadata a4;
+    ArtifactMetadata a4;
 
-    ArrayList<ArtifactBasicMetadata> inc;
+    ArrayList<ArtifactMetadata> inc;
 
-    ArrayList<ArtifactBasicMetadata> exc;
+    ArrayList<ArtifactMetadata> exc;
 
     @Override
     protected void setUp()
         throws Exception
     {
-        a1 = new ArtifactBasicMetadata( "a:a:1.1" );
-        a2 = new ArtifactBasicMetadata( "a:a:2.1" );
-        a3 = new ArtifactBasicMetadata( "a:a:3.1" );
-        a4 = new ArtifactBasicMetadata( "a:a:4.1" );
+        a1 = new ArtifactMetadata( "a:a:1.1" );
+        a2 = new ArtifactMetadata( "a:a:2.1" );
+        a3 = new ArtifactMetadata( "a:a:3.1" );
+        a4 = new ArtifactMetadata( "a:a:4.1" );
 
-        inc = new ArrayList<ArtifactBasicMetadata>();
-        inc.add( new ArtifactBasicMetadata( "a:a" ) );
-        inc.add( new ArtifactBasicMetadata( "b:b:2.0.0" ) );
+        inc = new ArrayList<ArtifactMetadata>();
+        inc.add( new ArtifactMetadata( "a:a" ) );
+        inc.add( new ArtifactMetadata( "b:b:2.0.0" ) );
 
-        exc = new ArrayList<ArtifactBasicMetadata>();
-        exc.add( new ArtifactBasicMetadata( "c:c" ) );
-        exc.add( new ArtifactBasicMetadata( "b:b:2.0.1" ) );
+        exc = new ArrayList<ArtifactMetadata>();
+        exc.add( new ArtifactMetadata( "c:c" ) );
+        exc.add( new ArtifactMetadata( "b:b:2.0.1" ) );
 
         a2.setInclusions( inc );
 
@@ -71,39 +71,39 @@
     public void testNoFilter()
         throws VersionException
     {
-        assertTrue( a1.allowDependency( new ArtifactBasicMetadata( "a:a:2.0.0" ) ) );
-        assertTrue( a1.allowDependency( new ArtifactBasicMetadata( "b:b:1.0.0" ) ) );
-        assertTrue( a1.allowDependency( new ArtifactBasicMetadata( "c:c:1.0.0" ) ) );
+        assertTrue( a1.allowDependency( new ArtifactMetadata( "a:a:2.0.0" ) ) );
+        assertTrue( a1.allowDependency( new ArtifactMetadata( "b:b:1.0.0" ) ) );
+        assertTrue( a1.allowDependency( new ArtifactMetadata( "c:c:1.0.0" ) ) );
     }
 
     public void testInclusionsFilter()
         throws VersionException
     {
-        assertTrue( a2.allowDependency( new ArtifactBasicMetadata( "a:a:2.0.0" ) ) );
-        assertFalse( a2.allowDependency( new ArtifactBasicMetadata( "b:b:1.0.0" ) ) );
-        assertTrue( a2.allowDependency( new ArtifactBasicMetadata( "b:b:2.0.0" ) ) );
-        assertFalse( a2.allowDependency( new ArtifactBasicMetadata( "b:b:2.0.1" ) ) );
-        assertFalse( a2.allowDependency( new ArtifactBasicMetadata( "c:c:1.0.0" ) ) );
+        assertTrue( a2.allowDependency( new ArtifactMetadata( "a:a:2.0.0" ) ) );
+        assertFalse( a2.allowDependency( new ArtifactMetadata( "b:b:1.0.0" ) ) );
+        assertTrue( a2.allowDependency( new ArtifactMetadata( "b:b:2.0.0" ) ) );
+        assertFalse( a2.allowDependency( new ArtifactMetadata( "b:b:2.0.1" ) ) );
+        assertFalse( a2.allowDependency( new ArtifactMetadata( "c:c:1.0.0" ) ) );
     }
 
     public void testExclusionsFilter()
         throws VersionException
     {
-        assertTrue( a3.allowDependency( new ArtifactBasicMetadata( "a:a:2.0.0" ) ) );
-        assertTrue( a3.allowDependency( new ArtifactBasicMetadata( "b:b:1.0.0" ) ) );
-        assertFalse( a3.allowDependency( new ArtifactBasicMetadata( "b:b:2.0.1" ) ) );
-        assertFalse( a3.allowDependency( new ArtifactBasicMetadata( "c:c:1.0.0" ) ) );
+        assertTrue( a3.allowDependency( new ArtifactMetadata( "a:a:2.0.0" ) ) );
+        assertTrue( a3.allowDependency( new ArtifactMetadata( "b:b:1.0.0" ) ) );
+        assertFalse( a3.allowDependency( new ArtifactMetadata( "b:b:2.0.1" ) ) );
+        assertFalse( a3.allowDependency( new ArtifactMetadata( "c:c:1.0.0" ) ) );
     }
 
     public void testInclusionsExclusionsFilter()
         throws VersionException
     {
-        assertTrue( a4.allowDependency( new ArtifactBasicMetadata( "a:a:2.0.0" ) ) );
-        assertFalse( a4.allowDependency( new ArtifactBasicMetadata( "b:b:1.0.0" ) ) );
-        assertTrue( a4.allowDependency( new ArtifactBasicMetadata( "b:b:2.0.0" ) ) );
-        assertFalse( a4.allowDependency( new ArtifactBasicMetadata( "b:b:2.0.1" ) ) );
-        assertFalse( a4.allowDependency( new ArtifactBasicMetadata( "b:b:3.0.1" ) ) );
-        assertFalse( a4.allowDependency( new ArtifactBasicMetadata( "c:c:1.0.0" ) ) );
+        assertTrue( a4.allowDependency( new ArtifactMetadata( "a:a:2.0.0" ) ) );
+        assertFalse( a4.allowDependency( new ArtifactMetadata( "b:b:1.0.0" ) ) );
+        assertTrue( a4.allowDependency( new ArtifactMetadata( "b:b:2.0.0" ) ) );
+        assertFalse( a4.allowDependency( new ArtifactMetadata( "b:b:2.0.1" ) ) );
+        assertFalse( a4.allowDependency( new ArtifactMetadata( "b:b:3.0.1" ) ) );
+        assertFalse( a4.allowDependency( new ArtifactMetadata( "c:c:1.0.0" ) ) );
     }
 
 }
diff --git a/mercury-crypto/mercury-crypto-api/pom.xml b/mercury-crypto/mercury-crypto-api/pom.xml
index 81f322b..2f31cd6 100644
--- a/mercury-crypto/mercury-crypto-api/pom.xml
+++ b/mercury-crypto/mercury-crypto-api/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-crypto</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-crypto-api</artifactId>
diff --git a/mercury-crypto/mercury-crypto-basic/pom.xml b/mercury-crypto/mercury-crypto-basic/pom.xml
index 1631edb..301c2a6 100644
--- a/mercury-crypto/mercury-crypto-basic/pom.xml
+++ b/mercury-crypto/mercury-crypto-basic/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-crypto</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-crypto-basic</artifactId>
diff --git a/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties b/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties
index e212d79..a0c1f8f 100644
--- a/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties
+++ b/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/Messages.properties
@@ -40,3 +40,6 @@
 no.trusted.ring=trusted ring seem to be empty. There is no one I can trust, so signature verification is pointless.
 no.signature.string=there is signature supplied, so signature verification is pointless.
 
+null.ring=public ring cannot be null
+
+null.os=output stream cannot be null
\ No newline at end of file
diff --git a/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java b/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java
index d0917c6..f2d35c1 100644
--- a/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java
+++ b/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpHelper.java
@@ -22,14 +22,19 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.math.BigInteger;
 import java.security.Security;
 import java.util.Iterator;
 
+import org.apache.maven.mercury.crypto.api.StreamObserverException;
+import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
+import org.apache.maven.mercury.crypto.api.StreamVerifierException;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.openpgp.PGPCompressedData;
 import org.bouncycastle.openpgp.PGPException;
 import org.bouncycastle.openpgp.PGPObjectFactory;
+import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
 import org.bouncycastle.openpgp.PGPSecretKey;
 import org.bouncycastle.openpgp.PGPSecretKeyRing;
 import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
@@ -48,6 +53,9 @@
 {
   public static final String PROVIDER = "BC";
   public static final String EXTENSION = "asc";
+  
+  private static final byte [] _buf = new byte[10240];
+
 
   private static final Language LANG = new DefaultLanguage( PgpHelper.class );
   //---------------------------------------------------------------------------------
@@ -99,6 +107,14 @@
     return bi.longValue();
   }
   //---------------------------------------------------------------------------------
+  public static long getKeyId( InputStream inSig )
+  throws IOException, PGPException
+  {
+      PGPSignature sig = readSignature( inSig );
+      
+      return sig.getKeyID();
+  }
+  //---------------------------------------------------------------------------------
   public static PGPSignature readSignature( InputStream inS )
   throws IOException, PGPException
   {
@@ -166,5 +182,57 @@
     }
   }
   //---------------------------------------------------------------------------------
+  public static final boolean verifyStream( InputStream in, InputStream asc, InputStream publicKeyRingStream )
+  throws IOException, StreamObserverException
+  {
+      StreamVerifierAttributes attributes = new StreamVerifierAttributes(PgpStreamVerifierFactory.DEFAULT_EXTENSION, false, true);
+      
+      PgpStreamVerifierFactory svf = new PgpStreamVerifierFactory( attributes, publicKeyRingStream );
+      String sig = PgpHelper.streamToString( asc );
+      
+      return verifyStream( in, sig, svf );
+  }
+  //---------------------------------------------------------------------------------
+  public static final boolean verifyStream( InputStream in, String sig, PgpStreamVerifierFactory factory )
+  throws IOException, StreamObserverException
+  {
+
+      PgpStreamVerifier sv = (PgpStreamVerifier)factory.newInstance();
+      
+      sv.initSignature( sig );
+      
+      int nBytes = -1;
+      while( (nBytes = in.read(_buf)) != -1 )
+        sv.bytesReady( _buf, 0, nBytes );
+      
+      boolean verified = sv.verifySignature();
+
+      return verified;
+  }
+  
+  public static final PGPPublicKeyRingCollection readPublicRing( InputStream in )
+  throws IOException, PGPException
+  {
+      if( in == null )
+          return null;
+      
+      PGPPublicKeyRingCollection res = new PGPPublicKeyRingCollection( PGPUtil.getDecoderStream( in ) );
+      
+      return res;
+  }
+  
+  public static final void writePublicRing( PGPPublicKeyRingCollection  prc, OutputStream out )
+  throws IOException
+  {
+      if( prc == null )
+          throw new IllegalArgumentException( LANG.getMessage( "null.ring" ) );
+      
+      if( out == null )
+          throw new IllegalArgumentException( LANG.getMessage( "null.os" ) );
+      
+      prc.encode( out );
+      
+  }
+  //---------------------------------------------------------------------------------
   //---------------------------------------------------------------------------------
 }
diff --git a/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java b/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java
index 83e57ee..1349bdb 100644
--- a/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java
+++ b/mercury-crypto/mercury-crypto-basic/src/main/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierFactory.java
@@ -69,6 +69,15 @@
   }
   //--------------------------------------------------------------------------------------------
   public PgpStreamVerifierFactory( StreamVerifierAttributes attributes
+                                  , PGPPublicKeyRingCollection publicKeyRing
+                                  )
+  throws StreamVerifierException
+  {
+    super( attributes );
+    this.trustedPublicKeyRing = publicKeyRing;
+  }
+  //--------------------------------------------------------------------------------------------
+  public PgpStreamVerifierFactory( StreamVerifierAttributes attributes
                                   , InputStream secretKeyRingStream
                                   , String secretKeyId
                                   , String secretKeyPass
diff --git a/mercury-crypto/mercury-crypto-basic/src/test/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierTest.java b/mercury-crypto/mercury-crypto-basic/src/test/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierTest.java
index 7030426..7a001bb 100644
--- a/mercury-crypto/mercury-crypto-basic/src/test/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierTest.java
+++ b/mercury-crypto/mercury-crypto-basic/src/test/java/org/apache/maven/mercury/crypto/pgp/PgpStreamVerifierTest.java
@@ -123,25 +123,32 @@
     System.out.println("BouncyCastle Signature is "+verified);
   }
   //-------------------------------------------------------------------------------------------------
-  public void testVerifyExternalSignature()
+  public void testVerifyExternalSignature2()
   throws IOException, StreamObserverException
   {
-    PgpStreamVerifier sv = (PgpStreamVerifier)svf.newInstance();
-
     InputStream in = getClass().getResourceAsStream( "/file.gif" );
-    String sig = PgpHelper.streamToString( getClass().getResourceAsStream( "/file.gif.asc.external" ) );
+    InputStream sig = getClass().getResourceAsStream( "/file.gif.asc.external" );
+    InputStream publicKeyRingStream = getClass().getResourceAsStream( publicKeyFile );
     
-    sv.initSignature( sig );
-    
-    int b;
-    while( (b = in.read()) != -1 )
-      sv.byteReady( b );
-    
-    boolean verified = sv.verifySignature();
+    boolean verified = PgpHelper.verifyStream( in, sig, publicKeyRingStream );
     
     assertTrue( verified );
     
     System.out.println("3rd Party Signature is "+verified);
   }
   //-------------------------------------------------------------------------------------------------
+  public void testVerifyBCSignature()
+  throws IOException, StreamObserverException
+  {
+    InputStream in = getClass().getResourceAsStream( "/file.gif" );
+    InputStream sig = getClass().getResourceAsStream( "/file.gif.asc" );
+    InputStream publicKeyRingStream = getClass().getResourceAsStream( publicKeyFile );
+    
+    boolean verified = PgpHelper.verifyStream( in, sig, publicKeyRingStream );
+    
+    assertTrue( verified );
+    
+    System.out.println("BC Signature is "+verified);
+  }
+  //-------------------------------------------------------------------------------------------------
 }
diff --git a/mercury-crypto/pom.xml b/mercury-crypto/pom.xml
index e5b2afb..a96120a 100644
--- a/mercury-crypto/pom.xml
+++ b/mercury-crypto/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-crypto</artifactId>
diff --git a/mercury-event/pom.xml b/mercury-event/pom.xml
index fa8fe36..596b970 100644
--- a/mercury-event/pom.xml
+++ b/mercury-event/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-event</artifactId>
diff --git a/mercury-external/pom.xml b/mercury-external/pom.xml
index bd747c0..fb7d168 100644
--- a/mercury-external/pom.xml
+++ b/mercury-external/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version> </parent>
+    <version>1.0-alpha-6</version> </parent>
 
   <groupId>org.apache.maven.mercury</groupId>
 
diff --git a/mercury-external/src/main/java/org/apache/maven/mercury/builder/api/DependencyProcessor.java b/mercury-external/src/main/java/org/apache/maven/mercury/builder/api/DependencyProcessor.java
index c9f9ccb..011f9a3 100644
--- a/mercury-external/src/main/java/org/apache/maven/mercury/builder/api/DependencyProcessor.java
+++ b/mercury-external/src/main/java/org/apache/maven/mercury/builder/api/DependencyProcessor.java
@@ -21,14 +21,14 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 
 public interface DependencyProcessor
 {
-
+    /** dummy processor to create M2 repositories when metadata processing is not required */
     public static final DependencyProcessor NULL_PROCESSOR = new DependencyProcessor()
     {
-        public List<ArtifactBasicMetadata> getDependencies( ArtifactBasicMetadata bmd, MetadataReader mdReader,
+        public List<ArtifactMetadata> getDependencies( ArtifactMetadata bmd, MetadataReader mdReader,
                                                             Map<String, String> env, Map<?, ?> sysProps )
             throws MetadataReaderException, DependencyProcessorException
         {
@@ -37,7 +37,9 @@
     };
 
     // TODO: shouldn't sysProps be changed to Properties because of System.getProperties() API?
-    public List<ArtifactBasicMetadata> getDependencies( ArtifactBasicMetadata bmd, MetadataReader mdReader,
+    // Oleg: sysProp may help to experiment with Objects, different from Strings, so I'd 
+    //  stay with the Map until this is stable enough
+    public List<ArtifactMetadata> getDependencies( ArtifactMetadata bmd, MetadataReader mdReader,
                                                         Map<String, String> env, Map<?, ?> sysProps )
         throws MetadataReaderException, DependencyProcessorException;
 }
diff --git a/mercury-external/src/main/java/org/apache/maven/mercury/builder/api/MetadataReader.java b/mercury-external/src/main/java/org/apache/maven/mercury/builder/api/MetadataReader.java
index db0e797..2557f8d 100644
--- a/mercury-external/src/main/java/org/apache/maven/mercury/builder/api/MetadataReader.java
+++ b/mercury-external/src/main/java/org/apache/maven/mercury/builder/api/MetadataReader.java
@@ -18,7 +18,7 @@
  */
 package org.apache.maven.mercury.builder.api;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 
 /**
  * This interface implementation is supplied to MetadataProcessor to simplify it's access to remote repositories
@@ -41,10 +41,10 @@
      * @throws MetadataReaderException
      * @throws RepositoryException
      */
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type, boolean exempt )
+    public byte[] readRawData( ArtifactMetadata bmd, String classifier, String type, boolean exempt )
         throws MetadataReaderException;
 
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type )
+    public byte[] readRawData( ArtifactMetadata bmd, String classifier, String type )
         throws MetadataReaderException;
 
   /**
@@ -55,9 +55,9 @@
      * @return
      * @throws MetadataReaderException
      */
-    public byte[] readMetadata( ArtifactBasicMetadata bmd, boolean exempt )
+    public byte[] readMetadata( ArtifactMetadata bmd, boolean exempt )
         throws MetadataReaderException;
 
-    public byte[] readMetadata( ArtifactBasicMetadata bmd )
+    public byte[] readMetadata( ArtifactMetadata bmd )
         throws MetadataReaderException;
 }
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/all/it/AbstractTestCase.java b/mercury-it/src/test/java/org/apache/maven/mercury/all/it/AbstractTestCase.java
index 2aede4a..c04c9f6 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/all/it/AbstractTestCase.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/all/it/AbstractTestCase.java
@@ -21,8 +21,6 @@
 
 import org.codehaus.plexus.PlexusTestCase;
 
-import junit.framework.TestCase;
-
 /**
  * Common tests code
  *
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/all/it/AllTestCases.java b/mercury-it/src/test/java/org/apache/maven/mercury/all/it/AllTestCases.java
index 5b4af9c..beda432 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/all/it/AllTestCases.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/all/it/AllTestCases.java
@@ -19,6 +19,9 @@
 
 package org.apache.maven.mercury.all.it;
 
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 import org.apache.maven.mercury.dependency.tests.DependencyTreeBuilderTest;
 import org.apache.maven.mercury.plexus.DefaultPlexusMercuryTest;
 import org.apache.maven.mercury.repository.tests.ComprehensiveRepositoryTest;
@@ -31,9 +34,6 @@
 import org.apache.maven.mercury.repository.tests.RemoteRepositoryWriterM2Test;
 import org.apache.maven.mercury.repository.tests.VirtualRepositoryReaderIntegratedTest;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 /**
  * adopted from Maven ITs structure
  *
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/dependency/tests/DependencyTreeBuilderTest.java b/mercury-it/src/test/java/org/apache/maven/mercury/dependency/tests/DependencyTreeBuilderTest.java
index a9b7bd5..84a8861 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/dependency/tests/DependencyTreeBuilderTest.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/dependency/tests/DependencyTreeBuilderTest.java
@@ -31,16 +31,15 @@
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.event.DumbListener;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.metadata.DependencyBuilder;
 import org.apache.maven.mercury.metadata.DependencyBuilderFactory;
 import org.apache.maven.mercury.metadata.MetadataTreeException;
-import org.apache.maven.mercury.metadata.MetadataTreeNode;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.api.RepositoryReader;
@@ -184,7 +183,7 @@
     
     List<Artifact> artifacts = new ArrayList<Artifact>();
     
-    for( ArtifactBasicMetadata abm : aRes.getResults().keySet() )
+    for( ArtifactMetadata abm : aRes.getResults().keySet() )
       artifacts.addAll(  aRes.getResults(abm) );
     
     localRepo.getWriter().writeArtifacts( artifacts );
@@ -265,7 +264,7 @@
 
     assertTrue( ar.hasResults() );
     
-    Map<ArtifactBasicMetadata, List<Artifact>> arts = ar.getResults();
+    Map<ArtifactMetadata, List<Artifact>> arts = ar.getResults();
     
     for( List<Artifact> al : arts.values() )
     {
@@ -274,5 +273,46 @@
     }
   }
   //----------------------------------------------------------------------------------------------
+  public void testResolvePluginAsTree()
+  throws Exception
+  {
+    String centralUrl = "http://repo1.maven.org/maven2";
+
+    String artifactId = "org.apache.maven.plugins:maven-clean-plugin:2.2";
+    
+    reps.clear();
+    
+    File pluginRepo = new File( "./target/repoPlugin" );
+    localRepo = new LocalRepositoryM2( "testLocalPluginRepo", pluginRepo, new MavenDependencyProcessor() );
+    reps.add(  localRepo );
+
+    Server server = new Server( "id", new URL(centralUrl) );
+    remoteRepo = new RemoteRepositoryM2(server, new MavenDependencyProcessor());
+    remoteRepo.setUpdatePolicy( RepositoryUpdateIntervalPolicy.UPDATE_POLICY_NEVER );
+    reps.add( remoteRepo );
+    
+    depBuilder = DependencyBuilderFactory.create( DependencyBuilderFactory.JAVA_DEPENDENCY_MODEL, reps );
+//    depBuilder.register( new DumbListener() );
+    
+    ArtifactMetadata md = new ArtifactMetadata( artifactId );
+
+    MetadataTreeNode root = depBuilder.buildTree( md, ArtifactScopeEnum.compile );
+
+    assertNotNull( root );
+    
+    MetadataTreeNode res = depBuilder.resolveConflictsAsTree( root );
+    
+    assertNotNull( res );
+    
+    int nodeCount = res.countNodes();
+    
+    assertEquals( 15, nodeCount);
+    
+    System.out.println("Unique feature - junit is in the compile scope thanks to plexus-container-default 1.0.9");
+
+    MetadataTreeNode.showNode( res, 0 );
+
+  }
+  //----------------------------------------------------------------------------------------------
   //----------------------------------------------------------------------------------------------
 }
\ No newline at end of file
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/plexus/DefaultPlexusMercuryTest.java b/mercury-it/src/test/java/org/apache/maven/mercury/plexus/DefaultPlexusMercuryTest.java
index a772ce9..dc6b6db 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/plexus/DefaultPlexusMercuryTest.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/plexus/DefaultPlexusMercuryTest.java
@@ -27,13 +27,13 @@
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactExclusionList;
 import org.apache.maven.mercury.artifact.ArtifactInclusionList;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.ArtifactQueryList;
 import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
 import org.apache.maven.mercury.crypto.pgp.PgpStreamVerifierFactory;
@@ -116,7 +116,7 @@
         File artifactBinary = File.createTempFile( "test-repo-writer", "bin" );
         FileUtil.writeRawData( getClass().getResourceAsStream( "/maven-core-2.0.9.jar" ), artifactBinary );
 
-        a = new DefaultArtifact( new ArtifactBasicMetadata( "org.apache.maven.mercury:mercury-core:2.0.9" ) );
+        a = new DefaultArtifact( new ArtifactMetadata( "org.apache.maven.mercury:mercury-core:2.0.9" ) );
 
         a.setPomBlob( FileUtil.readRawData( getClass().getResourceAsStream( "/maven-core-2.0.9.pom" ) ) );
         a.setFile( artifactBinary );
@@ -182,7 +182,7 @@
     {
         ArtifactMetadata gavMd = new ArtifactMetadata( gav );
 
-        for ( ArtifactBasicMetadata md : res )
+        for ( ArtifactMetadata md : res )
             if ( md.sameGAV( gavMd ) )
                 return true;
 
@@ -233,13 +233,13 @@
     {
         ArtifactMetadata bmd = new ArtifactMetadata( artifactCoord );
 
-        List<ArtifactBasicMetadata> res = pm.readVersions( repos, bmd );
+        List<ArtifactMetadata> res = pm.readVersions( repos, bmd );
 
         assertNotNull( res );
 
         assertFalse( res.isEmpty() );
 
-        ArtifactBasicMetadata a = res.get( 0 );
+        ArtifactMetadata a = res.get( 0 );
 
         assertEquals( "1.0.0-alpha-2-20081104.001322-2", a.getVersion() );
 
@@ -341,6 +341,82 @@
     }
 
     // -------------------------------------------------------------------------------------
+    public void testResolveAsTree()
+        throws Exception
+    {
+        Server central = new Server( "central", new URL( "http://repo1.maven.org/maven2" ) );
+        // Server central = new Server( "central", new URL("http://repository.sonatype.org/content/groups/public") );
+
+        repos.add( new RemoteRepositoryM2( central, pm.findDependencyProcessor() ) );
+
+        String artifactId = "asm:asm-xml:3.0";
+
+        MetadataTreeNode res =
+            pm.resolveAsTree( repos, ArtifactScopeEnum.compile, new ArtifactQueryList( artifactId ), null, null );
+
+        System.out.println( "Resolved as tree:" );
+        MetadataTreeNode.showNode( res, 0 );
+        
+        assertNotNull( res );
+        
+        assertTrue( res.hasChildren() );
+        
+        int nodes = res.countNodes();
+
+        /* tree structure:
+            0 asm:asm-xml:3.0::jar
+              1 asm:asm-util:3.0::jar
+                2 asm:asm-tree:3.0::jar
+                  3 asm:asm:3.0::jar
+         */
+        
+        assertEquals( 4, nodes );
+
+        assertTrue( res.getMd().equals( new ArtifactMetadata( "asm:asm-xml:3.0" ) ) );
+        assertTrue( res.getChildren().get( 0 ).getMd().equals( new ArtifactMetadata( "asm:asm-util:3.0" ) ) );
+        assertTrue( res.getChildren().get( 0 ).getChildren().get( 0 ).getMd().equals( new ArtifactMetadata( "asm:asm-tree:3.0" ) ) );
+        assertTrue( res.getChildren().get( 0 ).getChildren().get( 0 ).getChildren().get( 0 ).getMd().equals( new ArtifactMetadata( "asm:asm:3.0" ) ) );
+    }
+
+    // -------------------------------------------------------------------------------------
+    public void testResolvePomAsTree()
+        throws Exception
+    {
+        Server central = new Server( "central", new URL( "http://repo1.maven.org/maven2" ) );
+        // Server central = new Server( "central", new URL("http://repository.sonatype.org/content/groups/public") );
+
+        repos.add( new RemoteRepositoryM2( central, pm.findDependencyProcessor() ) );
+
+        String artifactId = "asm:asm-xml:3.0::pom";
+
+        MetadataTreeNode res =
+            pm.resolveAsTree( repos, ArtifactScopeEnum.compile, new ArtifactQueryList( artifactId ), null, null );
+
+        System.out.println( "Resolved as tree:" );
+        MetadataTreeNode.showNode( res, 0 );
+        
+        assertNotNull( res );
+        
+        assertTrue( res.hasChildren() );
+        
+        int nodes = res.countNodes();
+
+        /* tree structure:
+            0 asm:asm-xml:3.0::pom
+              1 asm:asm-util:3.0::jar
+                2 asm:asm-tree:3.0::jar
+                  3 asm:asm:3.0::jar
+         */
+        
+        assertEquals( 4, nodes );
+
+        assertTrue( res.getMd().equals( new ArtifactMetadata( "asm:asm-xml:3.0::pom" ) ) );
+        assertTrue( res.getChildren().get( 0 ).getMd().equals( new ArtifactMetadata( "asm:asm-util:3.0" ) ) );
+        assertTrue( res.getChildren().get( 0 ).getChildren().get( 0 ).getMd().equals( new ArtifactMetadata( "asm:asm-tree:3.0" ) ) );
+        assertTrue( res.getChildren().get( 0 ).getChildren().get( 0 ).getChildren().get( 0 ).getMd().equals( new ArtifactMetadata( "asm:asm:3.0" ) ) );
+    }
+
+    // -------------------------------------------------------------------------------------
     @SuppressWarnings( "unchecked" )
     public void testResolveWithExclusion()
         throws Exception
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/AbstractRepositoryReaderM2Test.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/AbstractRepositoryReaderM2Test.java
index 6486d98..e347fa5 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/AbstractRepositoryReaderM2Test.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/AbstractRepositoryReaderM2Test.java
@@ -18,6 +18,8 @@
  */
 package org.apache.maven.mercury.repository.tests;
 
+import java.io.File;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -25,7 +27,7 @@
 import junit.framework.TestCase;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.QualityRange;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
@@ -33,7 +35,7 @@
 import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
 import org.apache.maven.mercury.crypto.pgp.PgpStreamVerifierFactory;
 import org.apache.maven.mercury.crypto.sha.SHA1VerifierFactory;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.api.RepositoryException;
@@ -53,9 +55,9 @@
   Repository repo;
   DependencyProcessor mdProcessor;
   RepositoryReader reader;
-  List<ArtifactBasicMetadata> query;
+  List<ArtifactMetadata> query;
   
-  ArtifactBasicMetadata bmd;
+  ArtifactMetadata bmd;
   
   private static final String publicKeyFile = "/pgp/pubring.gpg";
   private static final String secretKeyFile = "/pgp/secring.gpg";
@@ -75,6 +77,10 @@
     if( "Mac OS X".equals( os ) )
       goodOs = true;
     
+    File sn = new File("target/test-classes/repo/a/a/5-SNAPSHOT/a-5-SNAPSHOT.jar");
+    
+    sn.setLastModified( new Date().getTime() + 10000L );
+    
   }
   
     @Override
@@ -88,10 +94,10 @@
   public void testReadReleaseVersion()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:[3,3]");
+    bmd = new ArtifactMetadata("a:a:[3,3]");
     query.add( bmd );
     
-    ArtifactBasicResults res = reader.readVersions( query );
+    MetadataResults res = reader.readVersions( query );
     
     assertNotNull( res );
     assertFalse( res.hasExceptions() );
@@ -99,7 +105,7 @@
     
     assertEquals( 1, res.getResults().size() );
     
-    List<ArtifactBasicMetadata> ror = res.getResult( bmd );
+    List<ArtifactMetadata> ror = res.getResult( bmd );
     
     assertNotNull( ror );
     
@@ -116,10 +122,10 @@
   {
     repo.setRepositoryQualityRange( QualityRange.RELEASES_ONLY );
   
-    bmd = new ArtifactBasicMetadata("a:a:[3,)");
+    bmd = new ArtifactMetadata("a:a:[3,)");
     query.add( bmd );
     
-    ArtifactBasicResults res = reader.readVersions( query );
+    MetadataResults res = reader.readVersions( query );
     
     assertNotNull( res );
     
@@ -131,40 +137,40 @@
     
     assertEquals( 1, res.getResults().size() );
     
-    List<ArtifactBasicMetadata> qr = res.getResult( bmd );
+    List<ArtifactMetadata> qr = res.getResult( bmd );
     
     assertNotNull( qr );
     assertTrue( qr.size() > 1 );
     
-    assertFalse( qr.contains( new ArtifactBasicMetadata("a:a:5-SNAPSHOT") ) );
+    assertFalse( qr.contains( new ArtifactMetadata("a:a:5-SNAPSHOT") ) );
     
     System.out.println("query "+bmd+"->"+qr);
     
-    ArtifactBasicResults depRes = reader.readDependencies( qr );
+    MetadataResults depRes = reader.readDependencies( qr );
     
     assertNotNull( depRes );
     assertFalse( depRes.hasExceptions() );
     assertTrue( depRes.hasResults() );
     
-    ArtifactBasicMetadata a3 = new ArtifactBasicMetadata("a:a:3");
+    ArtifactMetadata a3 = new ArtifactMetadata("a:a:3");
     
     assertTrue( depRes.hasResults( a3 ) );
     
-    List<ArtifactBasicMetadata> deps = depRes.getResult( a3 );
+    List<ArtifactMetadata> deps = depRes.getResult( a3 );
     assertNotNull( deps );
     assertFalse( deps.isEmpty() );
 
     System.out.println(deps);
 
-    assertTrue( deps.contains( new ArtifactBasicMetadata("b:b:2") ) );
-    assertTrue( deps.contains( new ArtifactBasicMetadata("c:c:(1,)") ) );
+    assertTrue( deps.contains( new ArtifactMetadata("b:b:2") ) );
+    assertTrue( deps.contains( new ArtifactMetadata("c:c:(1,)") ) );
     
   }
   //------------------------------------------------------------------------------
   public void testReadArtifacts()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:3");
+    bmd = new ArtifactMetadata("a:a:3");
     query.add( bmd );
 
     ArtifactResults ror = reader.readArtifacts( query );
@@ -193,7 +199,7 @@
   public void testReadSnapshot()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:5-SNAPSHOT");
+    bmd = new ArtifactMetadata("a:a:5-SNAPSHOT");
     query.add( bmd );
 
     ArtifactResults ror = reader.readArtifacts( query );
@@ -223,7 +229,7 @@
   public void testReadSnapshotTS()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:5-20080807.234713-11");
+    bmd = new ArtifactMetadata("a:a:5-20080807.234713-11");
     query.add( bmd );
 
     ArtifactResults ror = reader.readArtifacts( query );
@@ -253,18 +259,18 @@
   public void testReadVersionsLatest()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:LATEST");
+    bmd = new ArtifactMetadata("a:a:LATEST");
     query.add( bmd );
 
-    ArtifactBasicResults ror = reader.readVersions( query );
+    MetadataResults ror = reader.readVersions( query );
     
     assertNotNull( ror );
     
     if( ror.hasExceptions() )
     {
-      Map<ArtifactBasicMetadata, Exception> exs = ror.getExceptions();
+      Map<ArtifactMetadata, Exception> exs = ror.getExceptions();
       
-      for( ArtifactBasicMetadata bmd : exs.keySet() )
+      for( ArtifactMetadata bmd : exs.keySet() )
       {
         System.out.println( "\n==========> "+bmd.toString());
         exs.get( bmd ).printStackTrace();
@@ -274,21 +280,21 @@
     assertFalse( ror.hasExceptions() );
     assertTrue( ror.hasResults() );
     
-    List<ArtifactBasicMetadata> deps = ror.getResult(bmd);
+    List<ArtifactMetadata> deps = ror.getResult(bmd);
     
     assertNotNull( deps );
     assertEquals( 1, deps.size() );
-    assertTrue( deps.contains( new ArtifactBasicMetadata("a:a:5-SNAPSHOT") ) );
+    assertTrue( deps.contains( new ArtifactMetadata("a:a:5-SNAPSHOT") ) );
     
   }
   //------------------------------------------------------------------------------
   public void testReadVersionsRelease()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:RELEASE");
+    bmd = new ArtifactMetadata("a:a:RELEASE");
     query.add( bmd );
 
-    ArtifactBasicResults ror = reader.readVersions( query );
+    MetadataResults ror = reader.readVersions( query );
     
     assertNotNull( ror );
     
@@ -298,18 +304,18 @@
     assertFalse( ror.hasExceptions() );
     assertTrue( ror.hasResults() );
     
-    List<ArtifactBasicMetadata> deps = ror.getResult(bmd);
+    List<ArtifactMetadata> deps = ror.getResult(bmd);
     
     assertNotNull( deps );
     assertEquals( 1, deps.size() );
-    assertTrue( deps.contains( new ArtifactBasicMetadata("a:a:4") ) );
+    assertTrue( deps.contains( new ArtifactMetadata("a:a:4") ) );
     
   }
   //------------------------------------------------------------------------------
   public void testReadLatest()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:LATEST");
+    bmd = new ArtifactMetadata("a:a:LATEST");
     query.add( bmd );
 
     ArtifactResults ror = reader.readArtifacts( query );
@@ -342,7 +348,7 @@
   public void testReadRelease()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:RELEASE");
+    bmd = new ArtifactMetadata("a:a:RELEASE");
     query.add( bmd );
 
     ArtifactResults ror = reader.readArtifacts( query );
@@ -387,7 +393,7 @@
     if( goodOs )
       server.setReaderStreamVerifierFactories(factories);
 
-    bmd = new ArtifactBasicMetadata("a:a:4");
+    bmd = new ArtifactMetadata("a:a:4");
     query.add( bmd );
 
     ArtifactResults ror = reader.readArtifacts( query );
@@ -432,7 +438,7 @@
     
     server.setReaderStreamVerifierFactories(factories);
 
-    bmd = new ArtifactBasicMetadata("a:a:3");
+    bmd = new ArtifactMetadata("a:a:3");
     query.add( bmd );
 
     ArtifactResults ror = null;
@@ -465,7 +471,7 @@
                   );
     server.setReaderStreamVerifierFactories(factories);
 
-    bmd = new ArtifactBasicMetadata("a:a:2");
+    bmd = new ArtifactMetadata("a:a:2");
     query.add( bmd );
 
     ArtifactResults ror = null;
@@ -502,7 +508,7 @@
       server.setReaderStreamVerifierFactories(factories);
     }
 
-    bmd = new ArtifactBasicMetadata("a:a:3");
+    bmd = new ArtifactMetadata("a:a:3");
     query.add( bmd );
 
     ArtifactResults ror = null;
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/AbstractRepositoryWriterM2Test.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/AbstractRepositoryWriterM2Test.java
index 3b5fd35..bde46c9 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/AbstractRepositoryWriterM2Test.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/AbstractRepositoryWriterM2Test.java
@@ -25,15 +25,13 @@
 import java.util.Set;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
 import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
 import org.apache.maven.mercury.crypto.pgp.PgpStreamVerifierFactory;
 import org.apache.maven.mercury.crypto.sha.SHA1VerifierFactory;
-import org.apache.maven.mercury.logging.IMercuryLogger;
-import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.api.RepositoryReader;
 import org.apache.maven.mercury.repository.api.RepositoryWriter;
@@ -63,9 +61,9 @@
   RepositoryReader reader;
   RepositoryWriter writer;
 
-  List<ArtifactBasicMetadata> query;
+  List<ArtifactMetadata> query;
   
-  ArtifactBasicMetadata bmd;
+  ArtifactMetadata bmd;
   
   String pomBlob;
   
@@ -171,7 +169,7 @@
     assertFalse( new File( targetDirectory, "/org/apache/maven/maven-core/2.0.9/"+repo.getMetadataName()+".sha1").exists() );
 
     Set<Artifact> artifacts = new HashSet<Artifact>(3);
-    DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata("org.apache.maven:maven-core:2.0.9") );
+    DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata("org.apache.maven:maven-core:2.0.9") );
     
     da.setPomBlob( pomBytes );
     da.setFile( artifactBinary );
@@ -218,7 +216,7 @@
     setSnapshots();
     
     Set<Artifact> artifacts = new HashSet<Artifact>(3);
-    DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata("org.apache.maven:maven-core:2.0.9-20080805.215925-8") );
+    DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata("org.apache.maven:maven-core:2.0.9-20080805.215925-8") );
     da.setPomBlob( pomBytes );
     da.setFile( artifactBinary );
     artifacts.add( da );
@@ -240,7 +238,7 @@
     setSnapshots();
     
     Set<Artifact> set = new HashSet<Artifact>(3);
-    DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata("org.apache.maven:maven-core:2.0.9-SNAPSHOT") );
+    DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata("org.apache.maven:maven-core:2.0.9-SNAPSHOT") );
     da.setPomBlob( pomBytes );
     da.setFile( artifactBinary );
     set.add( da );
@@ -262,7 +260,7 @@
     setSnapshots();
     
     Set<Artifact> set = new HashSet<Artifact>(3);
-    DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata("org.apache.maven:maven-core:2.0.9:all") );
+    DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata("org.apache.maven:maven-core:2.0.9:all") );
     da.setFile( artifactBinary );
     set.add( da );
     
@@ -285,7 +283,7 @@
     {
       String si = ""+i;
       
-      DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata("org.apache.maven:maven-core:2.0.9-20080805.215925-"+si) );
+      DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata("org.apache.maven:maven-core:2.0.9-20080805.215925-"+si) );
       da.setPomBlob( pomBytes );
       File ab = File.createTempFile( "test-core-", "-bin" );
       FileUtil.writeRawData( getClass().getResourceAsStream( "/maven-core-2.0.9.jar" ), ab );
@@ -354,14 +352,14 @@
     {
       String si = ""+i;
       
-      DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata("org.apache.maven:maven-core:2.0."+si+"-SNAPSHOT") );
+      DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata("org.apache.maven:maven-core:2.0."+si+"-SNAPSHOT") );
       da.setPomBlob( pomBytes );
       File ab = File.createTempFile( "test-core-", "-bin" );
       FileUtil.writeRawData( getClass().getResourceAsStream( "/maven-core-2.0.9.jar" ), ab );
       da.setFile( ab );
       set.add( da );
 
-      da = new DefaultArtifact( new ArtifactBasicMetadata("org.apache.maven:maven-mercury:2.0."+si+"-SNAPSHOT") );
+      da = new DefaultArtifact( new ArtifactMetadata("org.apache.maven:maven-mercury:2.0."+si+"-SNAPSHOT") );
       da.setPomBlob( pomBytes );
       ab = File.createTempFile( "test-mercury-", "-bin" );
       FileUtil.writeRawData( getClass().getResourceAsStream( "/maven-core-2.0.9.jar" ), ab );
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/ComprehensiveRepositoryTest.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/ComprehensiveRepositoryTest.java
index aebac29..cd278de 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/ComprehensiveRepositoryTest.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/ComprehensiveRepositoryTest.java
@@ -27,10 +27,11 @@
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
+import org.apache.maven.mercury.artifact.QualityRange;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.local.m2.LocalRepositoryM2;
@@ -197,7 +198,7 @@
     public void writeArtifact( String name, File af, File ap, Repository repo, File expectedFile )
     throws Exception
     {
-        DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata(name) );
+        DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata(name) );
         
         da.setPomBlob( FileUtil.readRawData( ap ) );
         da.setFile( af );
@@ -222,9 +223,9 @@
     public List<Artifact> readArtifact( String name , List<Repository> repos )
     throws Exception
     {
-        ArtifactBasicMetadata bmd = new ArtifactBasicMetadata(name);
+        ArtifactMetadata bmd = new ArtifactMetadata(name);
         
-        List<ArtifactBasicMetadata> al = new ArrayList<ArtifactBasicMetadata>();
+        List<ArtifactMetadata> al = new ArrayList<ArtifactMetadata>();
         al.add( bmd );
         
         VirtualRepositoryReader vr = new VirtualRepositoryReader( repos );
@@ -241,17 +242,17 @@
         return res.getResults( bmd );
     }
     
-    public List<ArtifactBasicMetadata> readVersions( String name , List<Repository> repos )
+    public List<ArtifactMetadata> readVersions( String name , List<Repository> repos )
     throws Exception
     {
-        ArtifactBasicMetadata bmd = new ArtifactBasicMetadata(name);
+        ArtifactMetadata bmd = new ArtifactMetadata(name);
         
-        List<ArtifactBasicMetadata> al = new ArrayList<ArtifactBasicMetadata>();
+        List<ArtifactMetadata> al = new ArrayList<ArtifactMetadata>();
         al.add( bmd );
         
         VirtualRepositoryReader vr = new VirtualRepositoryReader( repos );
         
-        ArtifactBasicResults  res = vr.readVersions( al );
+        MetadataResults  res = vr.readVersions( al );
         
         assertNotNull( res );
         
@@ -298,6 +299,41 @@
         assertFalse( localRepo2Jar.exists() );
     }
     
+    public void testWriteReadArtifactPom()
+    throws Exception
+    {
+        String name = "org.apache.maven:maven-core:2.0.9::pom";
+        
+        File af = new File( _resourceBase, "maven-core-2.0.9.pom" );
+        File ap = new File( _resourceBase, "maven-core-2.0.9.pom" );
+        
+        File aJar1 = new File( _base1, "org/apache/maven/maven-core/2.0.9/maven-core-2.0.9.pom");
+        File aJar2 = new File( _base2, "org/apache/maven/maven-core/2.0.9/maven-core-2.0.9.pom");
+        
+        assertFalse( aJar1.exists() );
+        assertFalse( aJar2.exists() );
+        
+        writeArtifact( name, af, ap, _rr2, aJar2 );
+
+        assertFalse( aJar1.exists() );
+        assertTrue( aJar2.exists() );
+        
+        List<Artifact> al = readArtifact( name, _rrs );
+        
+        System.out.println(al);
+        
+        File localRepo1Jar = new File( _lbase1, "org/apache/maven/maven-core/2.0.9/maven-core-2.0.9.pom" );
+        File localRepo2Jar = new File( _lbase2, "org/apache/maven/maven-core/2.0.9/maven-core-2.0.9.pom" );
+        
+        assertFalse( localRepo1Jar.exists() );
+        assertFalse( localRepo2Jar.exists() );
+        
+        al = readArtifact( name, _repos );
+        
+        assertTrue( localRepo1Jar.exists() );
+        assertFalse( localRepo2Jar.exists() );
+    }
+    
     public void testWriteReadTimeStamp()
     throws Exception
     {
@@ -473,7 +509,7 @@
         writeArtifact( nameTS2, af, ap, _rr2, null );
         writeArtifact( nameSN, af, ap, _rr2, null );
         
-        List<ArtifactBasicMetadata> vl = readVersions( nameSN, _rrs );
+        List<ArtifactMetadata> vl = readVersions( nameSN, _rrs );
         
         System.out.println(vl);
         
@@ -514,7 +550,7 @@
         aJar = new File( _base1, "org/apache/maven/maven-core/2.0.9-SNAPSHOT/maven-core-2.0.9-20090204.232324-24.jar");
         writeArtifact( nameTS2, af, ap, _rr1, aJar );
         
-        List<ArtifactBasicMetadata> vl = readVersions( nameSN, _rrs );
+        List<ArtifactMetadata> vl = readVersions( nameSN, _rrs );
         
         System.out.println(vl);
         
@@ -555,7 +591,7 @@
         aJar = new File( _base2, "org/apache/maven/maven-core/2.0.9-SNAPSHOT/maven-core-2.0.9-20090204.232324-24.jar");
         writeArtifact( nameTS2, af, ap, _rr2, aJar );
         
-        List<ArtifactBasicMetadata> vl = readVersions( nameSN, _rrs );
+        List<ArtifactMetadata> vl = readVersions( nameSN, _rrs );
         
         System.out.println(vl);
         
@@ -727,4 +763,65 @@
         
         assertEquals( "2.0.8", aSN.getVersion() );
     }
+    
+    public void testReadReleasePolicy()
+    throws Exception
+    {
+        String name = "org.apache.maven:maven-core:2.0.9";
+        
+        File af = new File( _resourceBase, "maven-core-2.0.9.jar" );
+        File ap = new File( _resourceBase, "maven-core-2.0.9.pom" );
+        
+        File aJar1 = new File( _base1, "org/apache/maven/maven-core/2.0.9/maven-core-2.0.9.jar");
+        File aJar2 = new File( _base2, "org/apache/maven/maven-core/2.0.9-SNAPSHOT/maven-core-2.0.9-20090204.232324-24.jar");
+        
+        assertFalse( aJar1.exists() );
+        assertFalse( aJar2.exists() );
+        
+        writeArtifact( "org.apache.maven:maven-core:2.0.9",                    af, ap, _rr1, aJar1 );
+        writeArtifact( "org.apache.maven:maven-core:2.0.9-20090204.232324-24", af, ap, _rr2, aJar2 );
+        
+        _rr1.setRepositoryQualityRange( QualityRange.RELEASES_ONLY );
+        _rr2.setRepositoryQualityRange( QualityRange.SNAPSHOTS_ONLY );
+        
+        List<ArtifactMetadata> al = readVersions( name, _rrs );
+        
+        assertNotNull( al );
+
+        assertEquals( 1, al.size() );
+
+        assertEquals( "2.0.9", al.get( 0 ).getVersion() );
+    }
+    
+    public void testReadReleasePolicySwapped()
+    throws Exception
+    {
+        String name = "org.apache.maven:maven-core:2.0.9";
+        
+        File af = new File( _resourceBase, "maven-core-2.0.9.jar" );
+        File ap = new File( _resourceBase, "maven-core-2.0.9.pom" );
+        
+        File aJar1 = new File( _base1, "org/apache/maven/maven-core/2.0.9/maven-core-2.0.9.jar");
+        File aJar2 = new File( _base2, "org/apache/maven/maven-core/2.0.9-SNAPSHOT/maven-core-2.0.9-20090204.232324-24.jar");
+        
+        assertFalse( aJar1.exists() );
+        assertFalse( aJar2.exists() );
+        
+        writeArtifact( "org.apache.maven:maven-core:2.0.9",                    af, ap, _rr1, aJar1 );
+        writeArtifact( "org.apache.maven:maven-core:2.0.9-20090204.232324-24", af, ap, _rr2, aJar2 );
+        
+        _rr2.setRepositoryQualityRange( QualityRange.RELEASES_ONLY );
+        _rr1.setRepositoryQualityRange( QualityRange.SNAPSHOTS_ONLY );
+        
+        ArtifactMetadata bmd = new ArtifactMetadata(name);
+        
+        List<ArtifactMetadata> al = new ArrayList<ArtifactMetadata>();
+        al.add( bmd );
+        
+        VirtualRepositoryReader vr = new VirtualRepositoryReader( _rrs );
+        
+        MetadataResults  res = vr.readVersions( al );
+        
+        assertTrue( res  == null || !res.hasResults() );
+    }
 }
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/DavServerTest.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/DavServerTest.java
index c195665..a52b6bb 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/DavServerTest.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/DavServerTest.java
@@ -26,7 +26,7 @@
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.RepositoryReader;
@@ -153,7 +153,7 @@
         File pom = new File("./target/test.pom");
         FileUtil.writeRawData( pom, "test-pom" );
 
-        DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata("a:test:1.0") );
+        DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata("a:test:1.0") );
         da.setFile( jar );
         da.setPomBlob( FileUtil.readRawData( pom ) );
 
@@ -176,9 +176,9 @@
     {
         testDavWrite();
         
-        ArtifactBasicMetadata bmd = new ArtifactBasicMetadata("a:test:1.0");
+        ArtifactMetadata bmd = new ArtifactMetadata("a:test:1.0");
         
-        List<ArtifactBasicMetadata> query = new ArrayList<ArtifactBasicMetadata>( 1 );
+        List<ArtifactMetadata> query = new ArrayList<ArtifactMetadata>( 1 );
 
         query.add( bmd );
         
@@ -218,7 +218,7 @@
         File pom = new File("./target/test.pom");
         FileUtil.writeRawData( pom, "test-pom" );
 
-        DefaultArtifact da = new DefaultArtifact( new ArtifactBasicMetadata("a:test:1.0") );
+        DefaultArtifact da = new DefaultArtifact( new ArtifactMetadata("a:test:1.0") );
         da.setFile( jar );
         da.setPomBlob( FileUtil.readRawData( pom ) );
 
@@ -241,9 +241,9 @@
     {
         testDavWrite2();
         
-        ArtifactBasicMetadata bmd = new ArtifactBasicMetadata("a:test:1.0");
+        ArtifactMetadata bmd = new ArtifactMetadata("a:test:1.0");
         
-        List<ArtifactBasicMetadata> query = new ArrayList<ArtifactBasicMetadata>( 1 );
+        List<ArtifactMetadata> query = new ArrayList<ArtifactMetadata>( 1 );
 
         query.add( bmd );
         
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/LocalRepositoryReaderM2Test.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/LocalRepositoryReaderM2Test.java
index 3d36e22..4abfbba 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/LocalRepositoryReaderM2Test.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/LocalRepositoryReaderM2Test.java
@@ -22,7 +22,7 @@
 import java.util.ArrayList;
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.repository.local.m2.LocalRepositoryM2;
 import org.apache.maven.mercury.repository.local.m2.MetadataProcessorMock;
 import org.apache.maven.mercury.transport.api.Server;
@@ -44,7 +44,7 @@
   {
     mdProcessor = new MetadataProcessorMock();
 
-    query = new ArrayList<ArtifactBasicMetadata>();
+    query = new ArrayList<ArtifactMetadata>();
 
     server = new Server( "test", new File("./target/test-classes/repo").toURL() );
       
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/LocalRepositoryWriterM2Test.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/LocalRepositoryWriterM2Test.java
index 185f341..3a1f1fb 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/LocalRepositoryWriterM2Test.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/LocalRepositoryWriterM2Test.java
@@ -24,7 +24,7 @@
 import java.util.HashSet;
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
 import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
 import org.apache.maven.mercury.crypto.pgp.PgpStreamVerifierFactory;
@@ -58,7 +58,7 @@
     FileUtil.copy( new File("./target/test-classes/repo"), targetDirectory, true );
     FileUtil.delete( new File(targetDirectory, "org") );
     
-    query = new ArrayList<ArtifactBasicMetadata>();
+    query = new ArrayList<ArtifactMetadata>();
     
     server = new Server( "test", targetDirectory.toURL() );
     // verifiers
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/ReadWriteTest.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/ReadWriteTest.java
index 4e77c8c..590f09d 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/ReadWriteTest.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/ReadWriteTest.java
@@ -28,7 +28,7 @@
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
@@ -69,9 +69,9 @@
   File localRepoBase;
   RepositoryWriter writer;
 
-  List<ArtifactBasicMetadata> query;
+  List<ArtifactMetadata> query;
   
-  ArtifactBasicMetadata bmd;
+  ArtifactMetadata bmd;
   
   Server server;
   
@@ -100,7 +100,7 @@
     lr = new LocalRepositoryM2( "lr", localRepoBase, new MavenDependencyProcessor() );
     writer = lr.getWriter(); 
 
-    query = new ArrayList<ArtifactBasicMetadata>();
+    query = new ArrayList<ArtifactMetadata>();
   }
 
   protected void tearDown()
@@ -114,7 +114,7 @@
   public void testOneArtifact()
   throws IllegalArgumentException, RepositoryException
   {
-    bmd = new ArtifactBasicMetadata("a:a:4");
+    bmd = new ArtifactMetadata("a:a:4");
     query.add( bmd );
     
     ArtifactResults res = reader.readArtifacts( query );
@@ -123,7 +123,7 @@
     assertFalse( res.hasExceptions() );
     assertTrue( res.hasResults() );
     
-    Map< ArtifactBasicMetadata, List<Artifact>> resMap = res.getResults();
+    Map< ArtifactMetadata, List<Artifact>> resMap = res.getResults();
     
     assertNotNull( resMap );
     assertFalse( resMap.isEmpty() );
@@ -151,7 +151,7 @@
   public void testOneArtifactWithClassifier()
   throws IllegalArgumentException, RepositoryException
   {
-    ArtifactBasicMetadata bm = new ArtifactBasicMetadata("a:a:4:sources");
+    ArtifactMetadata bm = new ArtifactMetadata("a:a:4:sources");
     query.add( bm );
     
     ArtifactResults res = reader.readArtifacts( query );
@@ -160,7 +160,7 @@
     assertFalse( res.hasExceptions() );
     assertTrue( res.hasResults() );
     
-    Map< ArtifactBasicMetadata, List<Artifact>> resMap = res.getResults();
+    Map< ArtifactMetadata, List<Artifact>> resMap = res.getResults();
     
     assertNotNull( resMap );
     assertFalse( resMap.isEmpty() );
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryCachingReaderM2Test.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryCachingReaderM2Test.java
index fdb0d35..ce822ed 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryCachingReaderM2Test.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryCachingReaderM2Test.java
@@ -28,7 +28,7 @@
 import java.util.List;
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.MetadataReaderException;
 import org.apache.maven.mercury.repository.api.RemoteRepository;
 import org.apache.maven.mercury.repository.api.RepositoryException;
@@ -78,7 +78,7 @@
 
     mdProcessor = new MetadataProcessorMock();
 
-    query = new ArrayList<ArtifactBasicMetadata>();
+    query = new ArrayList<ArtifactMetadata>();
 
     server = new Server( "test", new URL("http://localhost:"+_port+"/repo") );
     
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryReaderM2Test.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryReaderM2Test.java
index 1c6f7c2..5250ebc 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryReaderM2Test.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryReaderM2Test.java
@@ -29,7 +29,7 @@
 import java.util.List;
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.MetadataReaderException;
 import org.apache.maven.mercury.repository.api.RepositoryException;
 import org.apache.maven.mercury.repository.local.m2.MetadataProcessorMock;
@@ -73,7 +73,7 @@
 
     mdProcessor = new MetadataProcessorMock();
 
-    query = new ArrayList<ArtifactBasicMetadata>();
+    query = new ArrayList<ArtifactMetadata>();
 
     server = new Server( "test", new URL("http://localhost:"+_port+"/repo") );
     repo = new RemoteRepositoryM2( "testRepo", server, new MavenDependencyProcessor() );
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryWriterM2Test.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryWriterM2Test.java
index 57e87e9..0339ead 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryWriterM2Test.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/RemoteRepositoryWriterM2Test.java
@@ -23,8 +23,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 
-import org.apache.maven.mercury.MavenDependencyProcessor;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
 import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
 import org.apache.maven.mercury.crypto.pgp.PgpStreamVerifierFactory;
@@ -128,7 +127,7 @@
   {
     super.setUp();
 
-    query = new ArrayList<ArtifactBasicMetadata>();
+    query = new ArrayList<ArtifactMetadata>();
 
     startDavServer( _basePath, "mercury-test"  );
   }
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/THelper.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/THelper.java
index 9e71294..763fbf8 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/THelper.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/THelper.java
@@ -21,7 +21,7 @@
 import java.util.Arrays;
 import java.util.List;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 
 /**
  *
@@ -32,7 +32,7 @@
  */
 public class THelper
 {
-  public static List<ArtifactBasicMetadata> toList( ArtifactBasicMetadata... bmds)
+  public static List<ArtifactMetadata> toList( ArtifactMetadata... bmds)
   {
     return Arrays.asList( bmds );
   }
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/VirtualRepositoryReaderIntegratedTest.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/VirtualRepositoryReaderIntegratedTest.java
index ca2cb6d..e33ecbd 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/VirtualRepositoryReaderIntegratedTest.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/VirtualRepositoryReaderIntegratedTest.java
@@ -27,13 +27,12 @@
 import junit.framework.TestCase;
 
 import org.apache.maven.mercury.MavenDependencyProcessor;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.Repository;
-import org.apache.maven.mercury.repository.api.RepositoryException;
+import org.apache.maven.mercury.repository.api.RepositoryMetadataCache;
 import org.apache.maven.mercury.repository.api.RepositoryUpdateIntervalPolicy;
 import org.apache.maven.mercury.repository.local.m2.LocalRepositoryM2;
 import org.apache.maven.mercury.repository.local.m2.MetadataProcessorMock;
@@ -57,7 +56,7 @@
   public String _port;
   HttpTestServer _server;
   
-  List<ArtifactBasicMetadata> _query;
+  List<ArtifactMetadata> _query;
   
   RemoteRepositoryM2 _remoteRepo;
   LocalRepositoryM2  _localRepo;
@@ -80,7 +79,7 @@
     _server.start();
     _port = String.valueOf( _server.getPort() );
 
-    _query = new ArrayList<ArtifactBasicMetadata>();
+    _query = new ArrayList<ArtifactMetadata>();
 
     DependencyProcessor mdProcessor = new MetadataProcessorMock();
 
@@ -113,10 +112,10 @@
   {
     try
     {
-    ArtifactBasicMetadata bmd = new ArtifactBasicMetadata("a:a:[1,)");
-    List<ArtifactBasicMetadata> q = THelper.toList( bmd );
+    ArtifactMetadata bmd = new ArtifactMetadata("a:a:[1,)");
+    List<ArtifactMetadata> q = THelper.toList( bmd );
     
-    ArtifactBasicResults vres = _vr.readVersions( q );
+    MetadataResults vres = _vr.readVersions( q );
      
     assertNotNull( vres );
      
@@ -126,7 +125,7 @@
     
     assertTrue( vres.hasResults(bmd) );
     
-    List<ArtifactBasicMetadata> versions = vres.getResult( bmd );
+    List<ArtifactMetadata> versions = vres.getResult( bmd );
     
     assertNotNull( versions );
     
@@ -140,7 +139,7 @@
     
     FileUtil.writeRawData( mdf, newBytes );
     
-    // repository policy is 2 sec, this should be still 5 versions
+    // version MD is in memory, there should be still be 5 versions
     vres = _vr.readVersions( q );
     
     assertNotNull( vres );
@@ -156,11 +155,15 @@
     assertNotNull( versions );
     
     assertEquals( 5, versions.size() );
-
+    
+    // clean in-memory cache, so that on-disk expiration rules apply
+    RepositoryMetadataCache cache = _vr.getCache();
+    
+    cache.clearSession();
+    
     Thread.sleep( 4000L );
     
-    // repository policy is 2 sec, this should cause VR to re-read metadata
-    // should now have 6 versions
+    // We are past the expiration point of 5 sec - should now have 6 versions.  
     vres = _vr.readVersions( q );
     
     assertNotNull( vres );
@@ -189,10 +192,10 @@
   //-------------------------------------------------------------------------
   public void testReadBadVersions()
   {
-    ArtifactBasicMetadata bmd = new ArtifactBasicMetadata("does.not:exist:1.0");
-    List<ArtifactBasicMetadata> q = THelper.toList( bmd );
+    ArtifactMetadata bmd = new ArtifactMetadata("does.not:exist:1.0");
+    List<ArtifactMetadata> q = THelper.toList( bmd );
     
-    ArtifactBasicResults vres = null;
+    MetadataResults vres = null;
     try
     {
         vres = _vr.readVersions( q );
@@ -208,7 +211,7 @@
   //-------------------------------------------------------------------------
   public void testReadBadDependencies()
   {
-    ArtifactBasicMetadata bmd = new ArtifactBasicMetadata("does.not:exist:1.0");
+    ArtifactMetadata bmd = new ArtifactMetadata("does.not:exist:1.0");
     
     ArtifactMetadata vres = null;
     try
@@ -226,8 +229,8 @@
   //-------------------------------------------------------------------------
   public void testReadBadArtifact()
   {
-      ArtifactBasicMetadata bmd = new ArtifactBasicMetadata("does.not:exist:1.0");
-      List<ArtifactBasicMetadata> q = THelper.toList( bmd );
+      ArtifactMetadata bmd = new ArtifactMetadata("does.not:exist:1.0");
+      List<ArtifactMetadata> q = THelper.toList( bmd );
       
     ArtifactResults vres = null;
     try
diff --git a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/WebDavServer.java b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/WebDavServer.java
index 5b0de6e..d746f9e 100644
--- a/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/WebDavServer.java
+++ b/mercury-it/src/test/java/org/apache/maven/mercury/repository/tests/WebDavServer.java
@@ -20,17 +20,11 @@
 package org.apache.maven.mercury.repository.tests;
 
 import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.Servlet;
 
 import org.codehaus.plexus.PlexusConstants;
 import org.codehaus.plexus.PlexusContainer;
 import org.mortbay.jetty.Server;
 import org.mortbay.jetty.handler.ContextHandlerCollection;
-import org.mortbay.jetty.handler.DefaultHandler;
-import org.mortbay.jetty.handler.HandlerCollection;
 import org.mortbay.jetty.servlet.Context;
 import org.mortbay.jetty.servlet.ServletHolder;
 import org.sonatype.webdav.WebdavServlet;
diff --git a/mercury-logging/pom.xml b/mercury-logging/pom.xml
index 2f27aac..8970c7f 100644
--- a/mercury-logging/pom.xml
+++ b/mercury-logging/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-logging</artifactId>
diff --git a/mercury-md/mercury-md-sat/pom.xml b/mercury-md/mercury-md-sat/pom.xml
index c82cc1a..0c645ce 100644
--- a/mercury-md/mercury-md-sat/pom.xml
+++ b/mercury-md/mercury-md-sat/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-md</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-md-sat</artifactId>
@@ -93,6 +93,30 @@
           </execution>
         </executions>
       </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.modello</groupId>
+        <artifactId>modello-maven-plugin</artifactId>
+        <version>${modello.version}</version>
+        <configuration>
+          <version>1.0.0</version>
+          <useJava5>true</useJava5>
+          <models>
+            <model>src/main/mdo/forest.mdo</model>
+          </models>
+        </configuration>
+        <executions>
+          <execution>
+            <id>standard</id>
+            <goals>
+              <goal>java</goal>
+              <goal>xpp3-reader</goal>
+              <goal>xpp3-writer</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
     </plugins>
   </build>
 </project>
\ No newline at end of file
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClassicDepthComparator.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClassicDepthComparator.java
index 8a67aca..aae4f2c 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClassicDepthComparator.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClassicDepthComparator.java
@@ -20,6 +20,8 @@
 
 import java.util.Comparator;
 
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
+
 /**
  * classical depth comparator: shallower is better by default, but that could 
  * be changed by appropriate constructor
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClassicVersionComparator.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClassicVersionComparator.java
index 68b8787..cd971a8 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClassicVersionComparator.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClassicVersionComparator.java
@@ -21,6 +21,7 @@
 import java.util.Comparator;
 
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
 
 /**
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClasspathContainer.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClasspathContainer.java
index 2d28400..0660b58 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClasspathContainer.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/ClasspathContainer.java
@@ -24,6 +24,7 @@
 
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 
 /*
  * classpath container that is aware of the classpath scope
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyBuilder.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyBuilder.java
index 46aab02..1fd8cc1 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyBuilder.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyBuilder.java
@@ -20,12 +20,13 @@
 
 import java.util.List;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactExclusionList;
 import org.apache.maven.mercury.artifact.ArtifactInclusionList;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.ArtifactQueryList;
 import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
+import org.apache.maven.mercury.artifact.api.Configurable;
 import org.apache.maven.mercury.event.MercuryEventListener;
 
 /**
@@ -36,9 +37,14 @@
  *
  */
 public interface DependencyBuilder
+extends Configurable
 {
   public static final String TREE_BUILD_EVENT = "tree.build";
   public static final String TREE_NODE_BUILD_EVENT = "tree.node.build";
+
+  public static final String SYSTEM_PROPERTY_ALLOW_CIRCULAR_DEPENDENCIES = "mercury.circular.allow";
+
+  public static final String CONFIGURATION_PROPERTY_VERSION_MAP = "mercury.version.map";
   //------------------------------------------------------------------------
   /**
    * build the tree, using the repositories specified in the
@@ -49,7 +55,7 @@
    * @return the root of the tree built
    * @throws MetadataTreeException
    */
-  public abstract MetadataTreeNode buildTree( ArtifactBasicMetadata startMD, ArtifactScopeEnum scope )
+  public abstract MetadataTreeNode buildTree( ArtifactMetadata startMD, ArtifactScopeEnum scope )
   throws MetadataTreeException;
 
   /**
@@ -80,6 +86,23 @@
   throws MetadataTreeException;
 
   /**
+   * consolidated entry point: give it a collection of GAVs, it 
+   * will create a tree out of it
+   * 
+   * @param root the tree to resolve conflicts on
+   * @return resolved metadata tree
+   * @throws MetadataTreeException
+   */
+  public abstract MetadataTreeNode resolveConflictsAsTree( 
+                                          ArtifactScopeEnum   scope
+                                        , ArtifactQueryList artifacts
+                                        , ArtifactInclusionList inclusions
+                                        , ArtifactExclusionList exclusions
+                                        )
+
+  throws MetadataTreeException;
+
+  /**
    *  this one resolves the conflicts, removing all duplicate GAVs from the tree and
    *  returning a copy of the resulting subtree - original tree should be intact
    * 
@@ -103,6 +126,12 @@
    * @param listener
    */
   public abstract void unRegister( MercuryEventListener listener );
+  
+  /**
+   * release all resources 
+   * 
+   */
+  public abstract void close();
   //-----------------------------------------------------
   //-----------------------------------------------------
 
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyBuilderFactory.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyBuilderFactory.java
index 82e06a7..14ac1c4 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyBuilderFactory.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyBuilderFactory.java
@@ -23,7 +23,11 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.artifact.api.ArtifactListProcessor;
+import org.apache.maven.mercury.artifact.api.Configurable;
+import org.apache.maven.mercury.artifact.api.ConfigurationException;
+import org.apache.maven.mercury.artifact.api.ConfigurationUtil;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.api.RepositoryException;
 import org.codehaus.plexus.lang.DefaultLanguage;
@@ -61,8 +65,34 @@
                      )
   throws RepositoryException
   {
+      return create( dependencyModel, repositories, null, null, null, null );
+  }
+  
+  public static final DependencyBuilder create(
+        String dependencyModel
+      , Collection<Repository> repositories
+      , Collection<MetadataTreeArtifactFilter> filters
+      , List<Comparator<MetadataTreeNode>> comparators
+      , Map<String,ArtifactListProcessor> processors
+      , Map<String,Object> config 
+                     )
+  throws RepositoryException
+  {
     if( JAVA_DEPENDENCY_MODEL.equals( dependencyModel ) )
-      return new DependencyTreeBuilder( repositories,  filters, comparators, processors );
+    {
+        DependencyBuilder db = new DependencyTreeBuilder( repositories,  filters, comparators, processors );
+        
+        try
+        {
+            ConfigurationUtil.configure( db, config );
+        }
+        catch ( ConfigurationException e )
+        {
+            throw new RepositoryException( e );
+        }
+        
+        return db;
+    }
     
     throw new IllegalArgumentException( LANG.getMessage( "dependency.model.not.implemented", dependencyModel ) );
   }
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyTreeBuilder.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyTreeBuilder.java
index d31b88e..7c80fd5 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyTreeBuilder.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyTreeBuilder.java
@@ -25,13 +25,14 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactExclusionList;
 import org.apache.maven.mercury.artifact.ArtifactInclusionList;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.ArtifactQueryList;
 import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.artifact.api.ArtifactListProcessor;
+import org.apache.maven.mercury.artifact.api.ConfigurationException;
 import org.apache.maven.mercury.artifact.version.VersionException;
 import org.apache.maven.mercury.event.EventGenerator;
 import org.apache.maven.mercury.event.EventManager;
@@ -42,7 +43,7 @@
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.metadata.sat.DefaultSatSolver;
 import org.apache.maven.mercury.metadata.sat.SatException;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.api.RepositoryException;
 import org.apache.maven.mercury.repository.virtual.VirtualRepositoryReader;
@@ -62,7 +63,15 @@
     public static final ArtifactMetadata DUMMY_ROOT = new ArtifactMetadata( "__fake:__fake:1.0" );
 
     private static final Language LANG = new DefaultLanguage( DependencyTreeBuilder.class );
+    
+    public static final String SYSTEM_PROPERTY_DUMP_DEPENDENCY_TREE = "mercury.dump.tree";
+    
+    private static final String _depTreeDumpFileName = System.getProperty( SYSTEM_PROPERTY_DUMP_DEPENDENCY_TREE );
 
+    private static final boolean _dumpDepTree = _depTreeDumpFileName != null;
+    
+    private static final DependencyTreeDumper _dumper = _dumpDepTree ? new DependencyTreeDumper(_depTreeDumpFileName ) : null;
+    
     private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( DependencyTreeBuilder.class );
 
     private Collection<MetadataTreeArtifactFilter> _filters;
@@ -77,7 +86,32 @@
 
     private EventManager _eventManager;
     
-    private boolean _buildAllTrees = true;
+    private boolean _buildIndividualTrees = true;
+    
+    private boolean _allowCircularDependencies = Boolean.parseBoolean( System.getProperty( SYSTEM_PROPERTY_ALLOW_CIRCULAR_DEPENDENCIES, "false" ) );
+    
+    /** mandated versions in the format G:A -> V */
+    private Map<String, String> _versionMap;
+    
+    class TruckLoad
+    {
+        List<ArtifactMetadata> cp;
+        MetadataTreeNode root;
+        
+        public TruckLoad()
+        {
+        }
+        
+        public TruckLoad( List<ArtifactMetadata> cp )
+        {
+            this.cp = cp;
+        }
+        
+        public TruckLoad( MetadataTreeNode root )
+        {
+            this.root = root;
+        }
+    }
 
     /**
      * creates an instance of MetadataTree. Use this instance to
@@ -118,7 +152,7 @@
     }
 
     // ------------------------------------------------------------------------
-    public MetadataTreeNode buildTree( ArtifactBasicMetadata startMD, ArtifactScopeEnum treeScope )
+    public MetadataTreeNode buildTree( ArtifactMetadata startMD, ArtifactScopeEnum treeScope )
         throws MetadataTreeException
     {
         if ( startMD == null )
@@ -156,18 +190,45 @@
 
     // ------------------------------------------------------------------------
     public List<ArtifactMetadata> resolveConflicts( 
-                                        ArtifactScopeEnum   scope
-                                      , ArtifactQueryList artifacts
+                                        ArtifactScopeEnum     scope
+                                      , ArtifactQueryList     artifacts
                                       , ArtifactInclusionList inclusions
                                       , ArtifactExclusionList exclusions
                                                   )
+    throws MetadataTreeException
+    {
+        TruckLoad tl = resolveConflictsInternally( scope, artifacts, inclusions, exclusions, false );
+        
+        return tl == null ? null : tl.cp;
+    }
+    // ------------------------------------------------------------------------
+    public MetadataTreeNode resolveConflictsAsTree( 
+                                        ArtifactScopeEnum     scope
+                                      , ArtifactQueryList     artifacts
+                                      , ArtifactInclusionList inclusions
+                                      , ArtifactExclusionList exclusions
+                                                  )
+    throws MetadataTreeException
+    {
+        TruckLoad tl = resolveConflictsInternally( scope, artifacts, inclusions, exclusions, true );
+        
+        return tl == null ? null : tl.root;
+    }
+    // ------------------------------------------------------------------------
+    public TruckLoad resolveConflictsInternally( 
+                                        ArtifactScopeEnum     scope
+                                      , ArtifactQueryList     artifacts
+                                      , ArtifactInclusionList inclusions
+                                      , ArtifactExclusionList exclusions
+                                      , boolean asTree
+                                                  )
 
     throws MetadataTreeException
     {
         if ( artifacts == null )
             throw new MetadataTreeException( LANG.getMessage( "empty.md.collection" ) );
 
-        List<ArtifactBasicMetadata> startMDs = artifacts.getMetadataList();
+        List<ArtifactMetadata> startMDs = artifacts.getMetadataList();
         
         if ( Util.isEmpty( startMDs ) )
             throw new MetadataTreeException( LANG.getMessage( "empty.md.collection" ) );
@@ -176,22 +237,45 @@
 
         if ( nodeCount == 1 && inclusions == null && exclusions == null )
         {
-            ArtifactBasicMetadata bmd = startMDs.get( 0 );
+            ArtifactMetadata bmd = startMDs.get( 0 );
             MetadataTreeNode rooty = buildTree( bmd, scope );
-            List<ArtifactMetadata> res = resolveConflicts( rooty );
-            return res;
+
+            TruckLoad tl = null;
+            
+            if( asTree )
+            {
+                MetadataTreeNode tr = resolveConflictsAsTree( rooty );
+                
+                tl = new TruckLoad( tr );
+            }
+            else
+            {
+                List<ArtifactMetadata> res = resolveConflicts( rooty );
+                
+                tl = new TruckLoad( res );
+    
+                if(_dumpDepTree )
+                    _dumper.dump( scope, artifacts, inclusions, exclusions, rooty, res );
+            }
+
+            return tl;
         }
 
         DUMMY_ROOT.setDependencies( startMDs );
         DUMMY_ROOT.setInclusions( inclusions == null ? null : inclusions.getMetadataList() );
         DUMMY_ROOT.setExclusions( exclusions == null ? null : exclusions.getMetadataList() );
-
-        List<MetadataTreeNode> deps = new ArrayList<MetadataTreeNode>( nodeCount );
         
-        if( _buildAllTrees )
+        MetadataTreeNode root = null;
+        
+        if( _buildIndividualTrees )
         {
-            for ( ArtifactBasicMetadata bmd : startMDs )
+            List<MetadataTreeNode> deps = new ArrayList<MetadataTreeNode>( nodeCount );
+           
+            for ( ArtifactMetadata bmd : startMDs )
             {
+                if( scope != null && !scope.encloses( bmd.getArtifactScope() ) )
+                    continue;
+                
                 try
                 {
                     if( ! DUMMY_ROOT.allowDependency( bmd ) )
@@ -204,17 +288,17 @@
            
                 if( inclusions != null )
                 {
-                    List<ArtifactBasicMetadata> inc = inclusions.getMetadataList();
+                    List<ArtifactMetadata> inc = inclusions.getMetadataList();
                     
                     if( bmd.hasInclusions() )
                         bmd.getInclusions().addAll( inc );
                     else
                         bmd.setInclusions( inc );
                 }
-                
+    
                 if( exclusions != null )
                 {
-                    List<ArtifactBasicMetadata> excl = exclusions.getMetadataList();
+                    List<ArtifactMetadata> excl = exclusions.getMetadataList();
                     
                     if( bmd.hasExclusions() )
                         bmd.getExclusions().addAll( excl );
@@ -229,29 +313,47 @@
             
             if( Util.isEmpty( deps ) ) // all dependencies are filtered out 
                 return null;
-        }
-
-        // combine into one tree
-        MetadataTreeNode root = _buildAllTrees
-                                ? new MetadataTreeNode( DUMMY_ROOT, null, null ) 
-                                : buildTree( DUMMY_ROOT, scope )
-                                ;
-        if(_buildAllTrees)
-        {
+    
+            // combine into one tree
+            root = new MetadataTreeNode( DUMMY_ROOT, null, null );
+    
             for ( MetadataTreeNode kid : deps )
                 root.addChild( kid );
-        }
     
-        List<ArtifactMetadata> res = resolveConflicts( root );
+        }
+        else
+        {
+            DUMMY_ROOT.setDependencies( startMDs );
+            root = buildTree( DUMMY_ROOT, scope );
+        }
+        
+        
+        TruckLoad tl = null;
+        
+        if( asTree )
+        {
+            MetadataTreeNode tr = resolveConflictsAsTree( root );
+            
+            tl = new TruckLoad( tr );
+        }
+        else
+        {
+            List<ArtifactMetadata> cp = resolveConflicts( root ); 
 
-        if( res != null )
-            res.remove( DUMMY_ROOT );
+            if( cp != null )
+                cp.remove( DUMMY_ROOT );
+    
+                if(_dumpDepTree )
+                    _dumper.dump( scope, artifacts, inclusions, exclusions, root, cp );
+                
+                tl = new TruckLoad( cp );
+        }
 
-        return res;
+        return tl;
     }
     // -----------------------------------------------------
-    private MetadataTreeNode createNode( ArtifactBasicMetadata nodeMD, MetadataTreeNode parent
-                                         , ArtifactBasicMetadata nodeQuery, ArtifactScopeEnum globalScope
+    private MetadataTreeNode createNode( ArtifactMetadata nodeMD, MetadataTreeNode parent
+                                         , ArtifactMetadata nodeQuery, ArtifactScopeEnum globalScope
                                        )
         throws MetadataTreeException
     {
@@ -262,7 +364,21 @@
 
         try
         {
-            checkForCircularDependency( nodeMD, parent );
+            try
+            {
+                checkForCircularDependency( nodeMD, parent );
+            }
+            catch ( MetadataTreeCircularDependencyException e )
+            {
+                if( _allowCircularDependencies )
+                {
+                    String line = LANG.getMessage( "attention.line" );
+                    LOG.info( line + e.getMessage() + line );
+                    return null;
+                }
+                else
+                    throw e;
+            }
 
             ArtifactMetadata mr;
 
@@ -281,14 +397,14 @@
 
             MetadataTreeNode node = new MetadataTreeNode( mr, parent, nodeQuery );
 
-            List<ArtifactBasicMetadata> allDependencies = mr.getDependencies();
+            List<ArtifactMetadata> allDependencies = mr.getDependencies();
 
             if ( allDependencies == null || allDependencies.size() < 1 )
                 return node;
 
-            List<ArtifactBasicMetadata> dependencies = new ArrayList<ArtifactBasicMetadata>( allDependencies.size() );
+            List<ArtifactMetadata> dependencies = new ArrayList<ArtifactMetadata>( allDependencies.size() );
             if ( globalScope != null )
-                for ( ArtifactBasicMetadata md : allDependencies )
+                for ( ArtifactMetadata md : allDependencies )
                 {
                     ArtifactScopeEnum mdScope = md.getArtifactScope();
                     if ( globalScope.encloses( mdScope ) )
@@ -300,20 +416,20 @@
             if ( Util.isEmpty( dependencies ) )
                 return node;
 
-            ArtifactBasicResults res = _reader.readVersions( dependencies );
+            MetadataResults res = _reader.readVersions( dependencies );
             
             if( res == null )
                 throw new MetadataTreeException( LANG.getMessage( "no.versions", dependencies.toString() ) );
 
-            Map<ArtifactBasicMetadata, List<ArtifactBasicMetadata>> expandedDeps = res.getResults();
+            Map<ArtifactMetadata, List<ArtifactMetadata>> expandedDeps = res.getResults();
 
-            for ( ArtifactBasicMetadata md : dependencies )
+            for ( ArtifactMetadata md : dependencies )
             {
 
                 if ( LOG.isDebugEnabled() )
                     LOG.debug( "node " + nodeQuery + ", dep " + md );
 
-                List<ArtifactBasicMetadata> versions = expandedDeps.get( md );
+                List<ArtifactMetadata> versions = expandedDeps.get( md );
                 if ( versions == null || versions.size() < 1 )
                 {
                     if ( md.isOptional() )
@@ -325,7 +441,7 @@
                 boolean noVersions = true;
                 boolean noGoodVersions = true;
 
-                for ( ArtifactBasicMetadata ver : versions )
+                for ( ArtifactMetadata ver : versions )
                 {
                     if ( veto( ver, _filters ) || vetoInclusionsExclusions( node, ver ) )
                     {
@@ -335,7 +451,8 @@
                     }
 
                     MetadataTreeNode kid = createNode( ver, node, md, globalScope );
-                    node.addChild( kid );
+                    if( kid != null )
+                        node.addChild( kid );
 
                     noVersions = false;
 
@@ -393,7 +510,7 @@
     }
 
     // -----------------------------------------------------
-    private void checkForCircularDependency( ArtifactBasicMetadata md, MetadataTreeNode parent )
+    private void checkForCircularDependency( ArtifactMetadata md, MetadataTreeNode parent )
         throws MetadataTreeCircularDependencyException
     {
         MetadataTreeNode p = parent;
@@ -402,29 +519,29 @@
         {
             count++;
             // System.out.println("circ "+md+" vs "+p.md);
-            if ( md.sameGA( p.md ) )
+            if ( md.sameGA( p.getMd() ) )
             {
                 p = parent;
                 StringBuilder sb = new StringBuilder( 128 );
                 sb.append( md.toString() );
                 while ( p != null )
                 {
-                    sb.append( " <- " + p.md.toString() );
+                    sb.append( " <- " + p.getMd().toString() );
 
-                    if ( md.sameGA( p.md ) )
+                    if ( md.sameGA( p.getMd() ) )
                     {
                         throw new MetadataTreeCircularDependencyException( "circular dependency " + count
-                            + " levels up. " + sb.toString() + " <= " + ( p.parent == null ? "no parent" : p.parent.md ) );
+                            + " levels up. " + sb.toString() + " <= " + ( p.getParent() == null ? "no parent" : p.getParent().getMd() ) );
                     }
-                    p = p.parent;
+                    p = p.getParent();
                 }
             }
-            p = p.parent;
+            p = p.getParent();
         }
     }
 
     // -----------------------------------------------------
-    private boolean veto( ArtifactBasicMetadata md, Collection<MetadataTreeArtifactFilter> filters )
+    private boolean veto( ArtifactMetadata md, Collection<MetadataTreeArtifactFilter> filters )
     {
         if ( filters != null && filters.size() > 1 )
             for ( MetadataTreeArtifactFilter filter : filters )
@@ -434,12 +551,12 @@
     }
 
     // -----------------------------------------------------
-    private boolean vetoInclusionsExclusions( MetadataTreeNode node, ArtifactBasicMetadata ver )
+    private boolean vetoInclusionsExclusions( MetadataTreeNode node, ArtifactMetadata ver )
         throws VersionException
     {
         for ( MetadataTreeNode n = node; n != null; n = n.getParent() )
         {
-            ArtifactBasicMetadata md = n.getQuery();
+            ArtifactMetadata md = n.getQuery();
 
             if ( !md.allowDependency( ver ) ) // veto it
                 return true;
@@ -453,6 +570,8 @@
     {
         if ( root == null )
             throw new MetadataTreeException( LANG.getMessage( "empty.tree" ) );
+        
+        root.createNames( 0, 0 );
 
         try
         {
@@ -526,7 +645,7 @@
 
             comma = " <== ";
 
-            p = p.parent;
+            p = p.getParent();
         }
 
         return sb.toString();
@@ -554,4 +673,20 @@
             _eventManager.getListeners().addAll( eventManager.getListeners() );
 
     }
+    
+    public void close()
+    {
+        if( _reader != null )
+            _reader.close();
+    }
+
+    @SuppressWarnings("unchecked")
+    public void setOption( String name, Object val )
+        throws ConfigurationException
+    {
+        if( SYSTEM_PROPERTY_ALLOW_CIRCULAR_DEPENDENCIES.equals( name ) )
+            _allowCircularDependencies = Boolean.parseBoolean( (String)val );
+        else if( CONFIGURATION_PROPERTY_VERSION_MAP.equals( name ) )
+            _versionMap = (Map<String, String>) val;
+    }
 }
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyTreeDumper.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyTreeDumper.java
new file mode 100644
index 0000000..96ae029
--- /dev/null
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/DependencyTreeDumper.java
@@ -0,0 +1,286 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.maven.mercury.metadata;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import java.util.TreeSet;
+
+import org.apache.maven.mercury.artifact.ArtifactExclusionList;
+import org.apache.maven.mercury.artifact.ArtifactInclusionList;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.ArtifactQueryList;
+import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
+import org.apache.maven.mercury.metadata.forest.Forest;
+import org.apache.maven.mercury.metadata.forest.Node;
+import org.apache.maven.mercury.metadata.forest.Tree;
+import org.apache.maven.mercury.metadata.forest.io.xpp3.ForrestXpp3Reader;
+import org.apache.maven.mercury.metadata.forest.io.xpp3.ForrestXpp3Writer;
+import org.apache.maven.mercury.util.TimeUtil;
+
+/**
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class DependencyTreeDumper
+{
+    String _dumpFileName;
+    File _dumpFile;
+    Writer _wr;
+    
+    public DependencyTreeDumper( String name )
+    {
+        _dumpFileName = name;
+    }
+    
+    /**
+     * this one does not work because the writer runs out of stack memory on
+     * huge trees
+     * 
+     * @param scope
+     * @param artifacts
+     * @param inclusions
+     * @param exclusions
+     * @param dirty
+     * @param result
+     * @throws MetadataTreeException
+     */
+    public synchronized void realDump( ArtifactScopeEnum   scope
+                      , ArtifactQueryList artifacts
+                      , ArtifactInclusionList inclusions
+                      , ArtifactExclusionList exclusions
+                      , MetadataTreeNode dirty
+                      , List<ArtifactMetadata> result
+                    )
+    throws MetadataTreeException
+    {
+        try
+        {
+            if( artifacts == null || artifacts.getMetadataList() == null  )
+                return;
+            
+            Forest forest;
+            if( _dumpFile.exists() )
+            {
+                forest = new ForrestXpp3Reader().read( new FileInputStream(_dumpFile) );
+            }
+            else
+                forest = new Forest();
+            
+            Tree tree = new Tree();
+            
+            forest.addTree( tree );
+            
+            tree.setScope( scope == null ? "null" : scope.toString() );
+            
+            tree.setTimestamp( TimeUtil.getUTCTimestamp() );
+            
+            for( ArtifactMetadata md : artifacts.getMetadataList() )
+            {
+                Node n = new Node();
+                n.setName( md.toString() );
+                n.setScope( md.getScope() );
+                tree.addRequest( n );
+            }
+            
+            if( inclusions != null )
+                for( ArtifactMetadata md : inclusions.getMetadataList() )
+                {
+                    Node n = new Node();
+                    n.setName( md.toString() );
+                    n.setScope( md.getScope() );
+                    tree.addInclusion( n );
+                    
+                }
+                    
+            if( exclusions != null )
+                for( ArtifactMetadata md : exclusions.getMetadataList() )
+                {
+                    Node n = new Node();
+                    n.setName( md.toString() );
+                    n.setScope( md.getScope() );
+                    tree.addExclusion( n );
+                    
+                }
+            
+            Node root = createNode( dirty, 0L );
+            
+            tree.addDirtyTree( root );
+            
+            if( result != null )
+                for( ArtifactMetadata md : result )
+                {
+                    Node n = new Node();
+                    n.setName( md.toString() );
+                    n.setScope( md.getScope() );
+                    tree.addResult( n );
+                }
+            
+            new ForrestXpp3Writer().write( new FileWriter(_dumpFile), forest );
+        }
+        catch (Exception e)
+        {
+            throw new MetadataTreeException(e);
+        }
+    }
+    
+    public synchronized void dump( ArtifactScopeEnum   scope
+                      , ArtifactQueryList artifacts
+                      , ArtifactInclusionList inclusions
+                      , ArtifactExclusionList exclusions
+                      , MetadataTreeNode dirty
+                      , List<ArtifactMetadata> result
+                    )
+    throws MetadataTreeException
+    {
+        try
+        {
+            _dumpFile = new File(_dumpFileName+"-"+TimeUtil.getUTCTimestamp()+"-"+System.currentTimeMillis()+".xml" );
+            _wr = new FileWriter(_dumpFile);
+            _wr.write( "<tree>\n" );
+        }
+        catch ( IOException e )
+        {
+            throw new MetadataTreeException(e);
+        }
+        try
+        {
+            if( artifacts != null && artifacts.getMetadataList() != null  )
+            {
+                if( scope != null )
+                    _wr.write( "<scope>"+scope+"</scope>\n" );
+                
+                _wr.write( "<timestamp>"+ TimeUtil.getUTCTimestamp() +"</timestamp>\n" );
+                
+                _wr.write( "<request>\n" );
+                for( ArtifactMetadata md : artifacts.getMetadataList() )
+                {
+                    _wr.write( "  <node scope='"+md.getScope()+"'>"+md.toString()+"</node>\n" );
+                }
+                _wr.write( "</request>\n" );
+                
+                if( inclusions != null )
+                {
+                    _wr.write( "<inclusions>\n" );
+                    for( ArtifactMetadata md : inclusions.getMetadataList() )
+                    {
+                        _wr.write( "  <inclusion>"+md.toString()+"</inclusion>\n" );
+                    }
+                    _wr.write( "</inclusions>\n" );
+                }
+                        
+                if( exclusions != null )
+                {
+                    _wr.write( "<exclusions>\n" );
+                    for( ArtifactMetadata md : exclusions.getMetadataList() )
+                    {
+                        _wr.write( "  <exclusion>"+md.toString()+"</exclusion>\n" );
+                    }
+                    _wr.write( "</exclusions>\n" );
+                }
+                
+                _wr.write( "<source>\n" );
+                showNode( dirty, 0L );
+                _wr.write( "</source>\n" );
+                
+                if( result != null )
+                {
+                    TreeSet<String> ts = new TreeSet<String>();
+                    for( ArtifactMetadata md : result )
+                        ts.add( md.toString() );
+                        
+                    _wr.write( "<result>\n" );
+                    for( String name : ts )
+                    {
+                        _wr.write( "  <node>"+name+"</node>\n" );
+                    }
+                    _wr.write( "</result>\n" );
+                }
+                
+            }
+        }
+        catch (Exception e)
+        {
+            throw new MetadataTreeException(e);
+        }
+        finally
+        {
+            if( _wr != null )
+                try { _wr.write( "</tree>\n" );_wr.flush(); _wr.close(); } catch( Exception ee ) {}
+                
+            _wr = null;
+        }
+    }
+    
+    private void showNode( MetadataTreeNode mtn, long level )
+    throws IOException
+    {
+        if( mtn == null )
+            return;
+        
+        ArtifactMetadata md = mtn.getMd();
+        for( int i=0; i<level; i++ )
+            _wr.write( "  " );
+            
+        _wr.write( "  <node level='"+level+"'>"+md.toString()+"</node>\n" );
+        
+        if( mtn.hasChildren() )
+        {
+            _wr.write( "  <kids>\n" );
+            for( MetadataTreeNode kid : mtn.getChildren() )
+                showNode( kid, level+1 );
+            _wr.write( "  </kids>\n" );
+        }
+    }
+    
+    private static Node createNode( MetadataTreeNode mtn, long level )
+    {
+        if( mtn == null )
+            return null;
+        
+        Node n = new Node();
+        
+        ArtifactMetadata md = mtn.getMd();
+        
+        n.setName( md.toString() );
+        
+        n.setLevel( level );
+        
+        if( mtn.hasChildren() )
+        {
+            for( MetadataTreeNode kid : mtn.getChildren() )
+                n.addChildren( createNode( kid, level+1 ) );
+        }
+        
+        return n;
+
+    }
+}
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/Messages.properties b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/Messages.properties
index 655864b..6473070 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/Messages.properties
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/Messages.properties
@@ -24,4 +24,6 @@
 
 no.versions=cannot find any versions for {0} - exit
 
-not.optional.missing="did not find non-optional artifact for "
\ No newline at end of file
+not.optional.missing="did not find non-optional artifact for "
+
+attention.line=\n\n*************************************************************************************\n\n
\ No newline at end of file
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeArtifactFilter.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeArtifactFilter.java
index 507ece5..9f98c19 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeArtifactFilter.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeArtifactFilter.java
@@ -18,7 +18,7 @@
  */
 package org.apache.maven.mercury.metadata;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 
 /**
  * This is a member of a chain of filters that can stop an ArtifactMetadata 
@@ -28,5 +28,5 @@
  */
 public interface MetadataTreeArtifactFilter
 {
-  public boolean veto( ArtifactBasicMetadata md );
+  public boolean veto( ArtifactMetadata md );
 }
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeArtifactFilterMap.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeArtifactFilterMap.java
index ca1deb3..34bd176 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeArtifactFilterMap.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeArtifactFilterMap.java
@@ -22,7 +22,7 @@
 import java.util.Collection;
 import java.util.Map;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.util.Util;
 
 /**
@@ -42,7 +42,7 @@
         _vetos = vetos;
     }
     
-    public boolean veto( ArtifactBasicMetadata md )
+    public boolean veto( ArtifactMetadata md )
     {
         String key = md.toManagementString();
         
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNode.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNode.java
deleted file mode 100644
index ee184ee..0000000
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNode.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.maven.mercury.metadata;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.TreeSet;
-
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
-import org.apache.maven.mercury.artifact.ArtifactMetadata;
-import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
-import org.apache.maven.mercury.logging.IMercuryLogger;
-import org.apache.maven.mercury.logging.MercuryLoggerManager;
-import org.codehaus.plexus.lang.DefaultLanguage;
-import org.codehaus.plexus.lang.Language;
-/**
- * metadata [dirty] Tree
- * 
- * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
- *
- */
-public class MetadataTreeNode
-{
-  private static final int DEFAULT_CHILDREN_COUNT = 8;
-  
-  private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( MetadataTreeNode.class ); 
-  private static final Language LANG = new DefaultLanguage( MetadataTreeNode.class );
-  
-  /**
-   * this node's artifact MD
-   */
-  ArtifactMetadata md;
-  
-  /**
-   * fail resolution if it could not be found?
-   */
-  boolean optional = false;
-
-  /**
-   * parent node
-   */
-  MetadataTreeNode parent;
-  
-  /**
-   * node unique id, used to identify this node in external tree manipulations, such as  
-   */
-  int id;
-  
-  /**
-   * query node - the one that originated this actual node
-   */
-  ArtifactBasicMetadata query;
-
-  /**
-   * queries - one per POM dependency
-   */
-  List<ArtifactBasicMetadata> queries;
-
-  /**
-   * actual found versions
-   */
-  List<MetadataTreeNode> children;
-  //------------------------------------------------------------------------
-  public int countNodes()
-  {
-    return countNodes(this);
-  }
-  //------------------------------------------------------------------------
-  public static int countNodes( MetadataTreeNode node )
-  {
-    int res = 1;
-    
-    if( node.children != null && node.children.size() > 0)
-    {
-      for( MetadataTreeNode child : node.children )
-      {
-        res += countNodes( child );
-      }
-    }
-    
-    return res;
-  }
-  //------------------------------------------------------------------------
-  public int countDistinctNodes()
-  {
-    TreeSet<String> nodes = new TreeSet<String>();
-    
-    getDistinctNodes( this, nodes );
-if( LOG.isDebugEnabled() )
-{
-  LOG.debug( "tree distinct nodes count" );
-  LOG.debug( nodes.toString() );
-}
-
-    return nodes.size();
-  }
-  //------------------------------------------------------------------------
-  public static void getDistinctNodes( MetadataTreeNode node, TreeSet<String> nodes )
-  {
-    if( node.getMd() == null )
-      throw new IllegalArgumentException( "tree node without metadata" );
-    
-    nodes.add( node.getMd().getGAV() );
-    
-    if( node.children != null && node.children.size() > 0)
-      for( MetadataTreeNode child : node.children )
-        getDistinctNodes( child, nodes );
-  }
-	//------------------------------------------------------------------------
-  public MetadataTreeNode()
-  {
-  }
-  //------------------------------------------------------------------------
-  /**
-   * pointers to parent and query are a must. 
-   */
-  public MetadataTreeNode( ArtifactMetadata md
-                           , MetadataTreeNode parent
-                           , ArtifactBasicMetadata query
-                         )
-  {
-        if ( md != null )
-        {
-            md.setArtifactScope( ArtifactScopeEnum.checkScope(md.getArtifactScope()) );
-        }
-
-        this.md = md;
-        this.parent = parent;
-        this.query = query;
-  }
-  //------------------------------------------------------------------------
-  /**
-   * dependencies are ordered in the POM - they should be added in the POM order
-   */
-  public MetadataTreeNode addChild( MetadataTreeNode kid )
-  {
-      if ( kid == null )
-      {
-          return this;
-      }
-
-      if( children == null )
-      {
-      	children = new ArrayList<MetadataTreeNode>( DEFAULT_CHILDREN_COUNT );
-      }
-              
-      kid.setParent( this );
-      children.add( kid );
-      
-      return this;
-  }
-  //------------------------------------------------------------------------
-  /**
-   * dependencies are ordered in the POM - they should be added in the POM order
-   */
-  public MetadataTreeNode addQuery( ArtifactBasicMetadata query )
-  {
-      if ( query == null )
-      {
-          return this;
-      }
-
-      if( queries == null )
-      {
-        queries = new ArrayList<ArtifactBasicMetadata>( DEFAULT_CHILDREN_COUNT );
-      }
-              
-      queries.add( query );
-      
-      return this;
-  }
-    //------------------------------------------------------------------
-    @Override
-    public String toString()
-    {
-        return md == null 
-            ? "no metadata, parent " + 
-                ( parent == null ? "null" : parent.toString() ) 
-            : md.toString()+":d="+getDepth()
-            ;
-    }
-    //------------------------------------------------------------------------
-    public boolean hasChildren()
-    {
-        return children != null;
-    }
-    //------------------------------------------------------------------------
-    public ArtifactMetadata getMd()
-    {
-        return md;
-    }
-
-    public MetadataTreeNode getParent()
-    {
-        return parent;
-    }
-
-    public int getDepth()
-    {
-      int depth = 0;
-      
-      for( MetadataTreeNode p = parent; p != null; p = p.parent )
-        ++depth;
-      
-      return depth;
-    }
-
-    public int getMaxDepth( int depth )
-    {
-      int res = 0;
-      
-      if( ! hasChildren() )
-        return depth + 1;
-      
-      for( MetadataTreeNode kid : children )
-      {
-        int kidDepth = kid.getMaxDepth( depth + 1 );
-        if( kidDepth > res )
-          res = kidDepth;
-      }
-      
-      return res;
-    }
-
-    public void setParent( MetadataTreeNode parent )
-    {
-        this.parent = parent;
-    }
-
-    public List<MetadataTreeNode> getChildren()
-    {
-        return children;
-    }
-
-    public boolean isOptional()
-    {
-        return optional;
-    }
-    
-    public ArtifactBasicMetadata getQuery()
-    {
-      return query;
-    }
-    
-    public List<ArtifactBasicMetadata> getQueries()
-    {
-      return queries;
-    }
-    //------------------------------------------------------------------------
-    public static final MetadataTreeNode deepCopy( MetadataTreeNode node )
-    {
-      MetadataTreeNode res = new MetadataTreeNode( node.getMd()
-                                                  , node.getParent()
-                                                  , node.getQuery()
-                                                  );
-      res.setId( node.getId() );
-      
-      if( node.hasChildren() )
-        for( MetadataTreeNode kid : node.children )
-        {
-          MetadataTreeNode deepKid = deepCopy( kid );
-          res.addChild( deepKid );
-        }
-      
-      return res;
-    }
-    //----------------------------------------------------------------
-    /**
-     * helper method to print the tree into a Writer
-     */
-    public static final void showNode( MetadataTreeNode n, int level, Writer wr )
-    throws IOException
-    {
-      for( int i=0; i<level; i++ )
-        wr.write("  ");
-      
-      wr.write( level+"."+n.getMd()+"\n" );
-      
-      if( n.hasChildren() )
-      {
-        for( MetadataTreeNode kid : n.getChildren() )
-          showNode( kid, level+1, wr );
-      }
-    }
-    //----------------------------------------------------------------
-    /**
-     * helper method to print the tree into sysout
-     */
-    public static final void showNode( MetadataTreeNode n, int level )
-    throws IOException
-    {
-      StringWriter sw = new StringWriter();
-      MetadataTreeNode.showNode( n, 0, sw );
-      System.out.println( sw.toString() );
-    }
-    //------------------------------------------------------------------------
-    public int getId()
-    {
-      return id;
-    }
-    public void setId( int id )
-    {
-      this.id = id;
-    }
-    //------------------------------------------------------------------------
-    public static void reNumber( MetadataTreeNode node, int startNum )
-    {
-      reNum( node, new Counter(startNum) );
-    }
-    //------------------------------------------------------------------------
-    private static void reNum( MetadataTreeNode node, Counter num )
-    {
-      node.setId( num.next() );
-
-      if( node.hasChildren() )
-        for( MetadataTreeNode kid : node.getChildren() )
-          reNum( kid, num );
-    }
-    //------------------------------------------------------------------------
-    //------------------------------------------------------------------------
-}
-//------------------------------------------------------------------------
-class Counter
-{
-  int n;
-  
-  public Counter( int n )
-  {
-    this.n = n;
-  }
-  
-  int next()
-  {
-    return n++;
-  }
-}
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNodeGAComparator.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNodeGAComparator.java
index 4ad35cd..80667cd 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNodeGAComparator.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNodeGAComparator.java
@@ -20,6 +20,8 @@
 
 import java.util.Comparator;
 
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
+
 /**
  * utility class for DefaultSatSolver. Assumes good data - no null's
  * 
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNodeGAVComparator.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNodeGAVComparator.java
index a4d1bbe..172c143 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNodeGAVComparator.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/MetadataTreeNodeGAVComparator.java
@@ -20,6 +20,8 @@
 
 import java.util.Comparator;
 
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
+
 /**
  * utility class for DefaultSatSolver. Assumes good data - no null's
  * 
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/DefaultSatSolver.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/DefaultSatSolver.java
index 9181cc9..99e1b8a 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/DefaultSatSolver.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/DefaultSatSolver.java
@@ -27,15 +27,14 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.event.EventManager;
 import org.apache.maven.mercury.event.EventTypeEnum;
 import org.apache.maven.mercury.event.GenericEvent;
 import org.apache.maven.mercury.event.MercuryEventListener;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
-import org.apache.maven.mercury.metadata.MetadataTreeNode;
 import org.apache.maven.mercury.metadata.MetadataTreeNodeGAComparator;
 import org.apache.maven.mercury.metadata.MetadataTreeNodeGAVComparator;
 import org.codehaus.plexus.lang.DefaultLanguage;
@@ -68,6 +67,8 @@
   protected MetadataTreeNode _root;
   
   protected EventManager _eventManager;
+
+  public static final BigInteger TWO = new BigInteger("2");
   
   protected static final Comparator<MetadataTreeNode> gaComparator = new MetadataTreeNodeGAComparator();
   //-----------------------------------------------------------------------
@@ -90,7 +91,7 @@
     GenericEvent event = null;
     
     if( tree == null)
-      throw new SatException("cannot create a solver for an empty [null] tree");
+      throw new SatException( LANG.getMessage( "null.tree.arg" ) );
     
     try
     {
@@ -193,9 +194,9 @@
         {
           vars.push( varLiteral );
           
-          long cf = (long)Math.pow( 2, count++ );
+          BigInteger cf = TWO.pow( count++ );
           
-          coeffs.push( BigInteger.valueOf( cf ) );
+          coeffs.push( cf );
 
 if( LOG.isDebugEnabled() )
     LOG.debug( "    "+cf+" x"+var.getLiteral() );
@@ -408,8 +409,8 @@
   LOG.debug(( ge ? " >= " : " < ")+" "+cardinality );
   }
   //-----------------------------------------------------------------------
-  private final Map<ArtifactBasicMetadata, List<MetadataTreeNode>> processChildren(
-                                                        List<ArtifactBasicMetadata> queries
+  private final Map<ArtifactMetadata, List<MetadataTreeNode>> processChildren(
+                                                        List<ArtifactMetadata> queries
                                                         , List<MetadataTreeNode> children
                                                                               )
   throws SatException
@@ -421,9 +422,9 @@
       throw new SatException("there are queries, but not results. Queries: "+queries);
     
     // TODO og: MERCURY-40
-    Map<ArtifactBasicMetadata, List<MetadataTreeNode>> res = new LinkedHashMap<ArtifactBasicMetadata, List<MetadataTreeNode>>( queries.size() );
+    Map<ArtifactMetadata, List<MetadataTreeNode>> res = new LinkedHashMap<ArtifactMetadata, List<MetadataTreeNode>>( queries.size() );
 
-    for( ArtifactBasicMetadata q : queries )
+    for( ArtifactMetadata q : queries )
     {
       List<MetadataTreeNode> bucket = new ArrayList<MetadataTreeNode>(4);
       String queryGA = q.getGA();
@@ -466,15 +467,15 @@
     if( ! node.hasChildren() )
       return;
     
-    Map<ArtifactBasicMetadata,List<MetadataTreeNode>> kids = processChildren( node.getQueries(), node.getChildren() );
+    Map<ArtifactMetadata,List<MetadataTreeNode>> kids = processChildren( node.getQueries(), node.getChildren() );
     
     // leaf node in this scope
     if( kids == null )
       return;
     
-    for( Map.Entry<ArtifactBasicMetadata,List<MetadataTreeNode>> kid : kids.entrySet() )
+    for( Map.Entry<ArtifactMetadata,List<MetadataTreeNode>> kid : kids.entrySet() )
     {
-      ArtifactBasicMetadata query = kid.getKey();
+      ArtifactMetadata query = kid.getKey();
       
       List<MetadataTreeNode> range = kid.getValue();
 
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/HelpingSatSolver.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/HelpingSatSolver.java
new file mode 100644
index 0000000..31e69f8
--- /dev/null
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/HelpingSatSolver.java
@@ -0,0 +1,651 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.metadata.sat;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
+import org.apache.maven.mercury.event.EventManager;
+import org.apache.maven.mercury.event.EventTypeEnum;
+import org.apache.maven.mercury.event.GenericEvent;
+import org.apache.maven.mercury.event.MercuryEventListener;
+import org.apache.maven.mercury.logging.IMercuryLogger;
+import org.apache.maven.mercury.logging.MercuryLoggerManager;
+import org.apache.maven.mercury.metadata.MetadataTreeNodeGAComparator;
+import org.apache.maven.mercury.metadata.MetadataTreeNodeGAVComparator;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+import org.sat4j.core.Vec;
+import org.sat4j.core.VecInt;
+import org.sat4j.pb.IPBSolver;
+import org.sat4j.pb.ObjectiveFunction;
+import org.sat4j.pb.SolverFactory;
+import org.sat4j.specs.ContradictionException;
+import org.sat4j.specs.IConstr;
+import org.sat4j.specs.IVec;
+import org.sat4j.specs.IVecInt;
+import org.sat4j.specs.TimeoutException;
+
+/**
+ * Default SAT4J implementation.
+ * 
+ * @author Oleg Gusakov
+ * @version $Id$
+ */
+public class HelpingSatSolver
+{}
+//implements SatSolver
+//{
+//  private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( HelpingSatSolver.class ); 
+//  private static final Language LANG = new DefaultLanguage( HelpingSatSolver.class );
+//  
+//  private DependencyHelper<MetadataTreeNode,String> _helper = new DependencyHelper<MetadataTreeNode,String>( SolverFactory.newEclipseP2() );
+//  protected MetadataTreeNode _root;
+//  
+//  protected EventManager _eventManager;
+//  
+//  protected static final Comparator<MetadataTreeNode> gaComparator = new MetadataTreeNodeGAComparator();
+//  //-----------------------------------------------------------------------
+//  public static SatSolver create( MetadataTreeNode tree )
+//  throws SatException
+//  {
+//    return new HelpingSatSolver( tree );
+//  }
+//  //-----------------------------------------------------------------------
+//  public static SatSolver create( MetadataTreeNode tree, EventManager eventManager )
+//  throws SatException
+//  {
+//    return new HelpingSatSolver( tree, eventManager );
+//  }
+//  //-----------------------------------------------------------------------
+//  public HelpingSatSolver( MetadataTreeNode tree, EventManager eventManager )
+//  throws SatException
+//  {
+//    this._eventManager = eventManager;
+//    GenericEvent event = null;
+//    
+//    if( tree == null)
+//      throw new SatException( LANG.getMessage( "null.tree.arg" ) );
+//    
+//    try
+//    {
+//      if( _eventManager != null )
+//        event = new GenericEvent( EventTypeEnum.satSolver, EVENT_CREATE_SOLVER, tree.toString() );
+//        
+//      if( tree.getId() == 0 )
+//        MetadataTreeNode.reNumber( tree, 1 );
+//      
+//      int nNodes = tree.countDistinctNodes();
+//  
+//      LOG.debug( "SatContext: # of variables: "+nNodes );
+//  
+//      _root = tree;
+//      
+//      try
+//      {
+//        addNode( tree );
+//      }
+//      catch (ContradictionException e)
+//      {
+//        throw new SatException(e);
+//      }
+//    }
+//    finally
+//    {
+//      if( _eventManager != null )
+//      {
+//        event.stop();
+//        _eventManager.fireEvent( event );
+//      }
+//    }
+//  }
+//  //-----------------------------------------------------------------------
+//  public HelpingSatSolver( MetadataTreeNode tree )
+//  throws SatException
+//  {
+//    this( tree, null );
+//  }
+//  //-----------------------------------------------------------------------
+//  public final void applyPolicies( List<Comparator<MetadataTreeNode>> comparators )
+//  throws SatException
+//  {
+//    if( comparators == null || comparators.size() < 1 )
+//      return;
+//    
+//    if( _root == null )
+//      throw new SatException( "cannot apply policies to a null tree" );
+//    
+//    // TODO og: assumption - around 128 GA's per tree. If more - map reallocates - slow down.
+//    // TODO og: MERCURY-40
+//    Map<String, List<MetadataTreeNode>> buckets = new LinkedHashMap<String, List<MetadataTreeNode>>(128);
+//    fillBuckets( buckets, _root );
+//    sortBuckets( buckets, comparators );
+//    useBuckets( buckets );
+//  }
+//  //-----------------------------------------------------------------------
+//  private void useBuckets( Map<String, List<MetadataTreeNode>> buckets )
+//  throws SatException
+//  {
+//    if( buckets == null || buckets.size() < 1 )
+//      return;
+//    
+//    IVecInt vars            = new VecInt( 128 );
+//    IVec<BigInteger> coeffs = new Vec<BigInteger>( 128 );
+//    
+//    int count = 0;
+//    
+//    for( String key : buckets.keySet() )
+//    {
+//      List<MetadataTreeNode> bucket = buckets.get( key );
+//  
+//// oleg: ? this is needed if optimization is "maximize"       
+////      Collections.reverse(  bucket );
+//      
+//      int bucketSize = bucket.size(); 
+//      
+//      boolean bigBucket = bucketSize > 1;
+//
+//if( LOG.isDebugEnabled() )
+//    LOG.debug( "\n\nBucket "+key );
+//
+//      IVecInt bucketVars = new VecInt( bucketSize );
+//      
+//      for( int i=0; i<bucketSize; i++ )
+//      {
+//        MetadataTreeNode n  = bucket.get(i);
+//
+//if( LOG.isDebugEnabled() )
+//    LOG.debug( n.toString() );
+//
+//        SatVar var = _context.findOrAdd(n);
+//        int varLiteral = var.getLiteral(); 
+//        
+//        bucketVars.push( varLiteral );
+//        
+//        if( bigBucket )
+//        {
+//          vars.push( varLiteral );
+//          
+//          long cf = (long)Math.pow( 2, count++ );
+//          
+//          coeffs.push( BigInteger.valueOf( cf ) );
+//
+//if( LOG.isDebugEnabled() )
+//    LOG.debug( "    "+cf+" x"+var.getLiteral() );
+//        }
+//
+//      }
+//
+//      try
+//      {
+//        if( bucketVars != null && !bucketVars.isEmpty() )
+//        {
+//          _solver.addAtMost( bucketVars, 1 );
+//          _solver.addAtLeast( bucketVars, 1 );
+//        }
+//      }
+//      catch( ContradictionException e )
+//      {
+//        throw new SatException(e);
+//      }
+//      
+//if( LOG.isDebugEnabled() )
+//  LOG.debug( "\n" );
+//    }
+//
+//    if( vars.isEmpty() )
+//      return;
+//    
+//    _solver.setObjectiveFunction( new ObjectiveFunction( vars, coeffs ) );
+//  }
+//  //-----------------------------------------------------------------------
+//  protected static final void sortBuckets(
+//        Map<String, List<MetadataTreeNode>> buckets
+//      , List<Comparator<MetadataTreeNode>> comparators
+//                                          )
+//  {
+//    Comparator<MetadataTreeNode> lastComparator;
+//    for( List<MetadataTreeNode> bucket : buckets.values() )
+//    {
+//      lastComparator = gaComparator;
+//      for( Comparator<MetadataTreeNode> comparator : comparators )
+//      {
+//        sortBucket( bucket, comparator, lastComparator );
+//        lastComparator = comparator;
+//      }
+//      // due to the nature of Comparator need to reverse the result
+//      // as the best fit is now last
+//      Collections.reverse( bucket );
+//
+//      // the best fit now first, and we don't need duplicate GAVs
+//      removeDuplicateGAVs( bucket );
+//
+//    }
+//  }
+//  //-----------------------------------------------------------------------
+//  // remove duplicates, preserving the order. The first one is the most fit,
+//  // so need to delete from tail
+//  protected static final void removeDuplicateGAVs( List<MetadataTreeNode> bucket )
+//  {
+//    if( bucket == null || bucket.size() < 2 )
+//      return;
+//
+//    Comparator<MetadataTreeNode> gav = new MetadataTreeNodeGAVComparator();
+//    
+//    int len = bucket.size();
+//    int [] dups = new int[ len-1 ];
+//    int cnt = 0;
+//    
+//    for( int i=1; i<len; i++ )
+//    {
+//      MetadataTreeNode ti = bucket.get(i);
+//      
+//      for( int j=0; j<i; j++ )
+//        if( gav.compare( ti, bucket.get(j) ) == 0 )
+//        {
+//          dups[cnt++] = i;
+//          break;
+//        }
+//    }
+//    
+//    if( cnt > 0 )
+//      for( int i=0; i<cnt; i++ )
+//        bucket.remove( dups[cnt-i-1] );
+//  }
+//  //-----------------------------------------------------------------------
+//  /**
+//   * reorders the bucket's lastComparator equal subsets with comparator.
+//   */
+//  protected static final void sortBucket(
+//               List<MetadataTreeNode> bucket
+//               , Comparator<MetadataTreeNode> comparator
+//               , Comparator<MetadataTreeNode> lastComparator
+//               )
+//  {
+//    if( bucket == null || bucket.size() < 2 )
+//      return;
+//    
+//    int bLen = bucket.size();
+//    MetadataTreeNode [] temp = bucket.toArray( new MetadataTreeNode[ bLen ] );
+//    
+//    int wStart = -1;
+//    int wLen = 0;
+//    MetadataTreeNode [] work = new MetadataTreeNode[ bLen ];
+//    
+//    MetadataTreeNode lastNode = null;
+//    for( int i=0; i<bLen; i++ )
+//    {
+//      MetadataTreeNode n = temp[i];
+//      
+//      if( lastNode == null )
+//      {
+//        lastNode = n;
+//        continue;
+//      }
+//      
+//      if( lastComparator.compare(lastNode, n) == 0 )
+//      {
+//        if( wLen == 0 )
+//        {
+//          work[ wLen++ ] = lastNode;
+//          wStart = i-1;
+//        }
+//        
+//        work[ wLen++ ] = n;
+//
+//        lastNode = n;
+//
+//        if( i < (bLen-1) )
+//          continue;
+//      }
+//      
+//      if( wLen > 0 ) // eq list formed
+//      {
+//        reorder( work, wLen, comparator );
+//        for( int j=0; j<wLen; j++ )
+//          temp[ wStart+j ] = work[ j ];
+//        wLen = 0;
+//        wStart = -1;
+//      }
+//      
+//      lastNode = n;
+//    }
+//    
+//    bucket.clear();
+//    for( int i=0; i<bLen; i++ )
+//      bucket.add( temp[ i ] );
+//  }
+//  //-----------------------------------------------------------------------
+//  private static final void reorder(
+//                          MetadataTreeNode[] work
+//                          , int wLen
+//                          , Comparator<MetadataTreeNode> comparator
+//                                   )
+//  {
+//    MetadataTreeNode[] temp = new MetadataTreeNode[ wLen ];
+//    
+//    for( int i=0; i< wLen; i++ )
+//      temp[i] = work[i];
+//    
+//    Arrays.sort( temp, comparator );
+//    
+//    for( int i=0; i<wLen; i++ )
+//      work[i] = temp[i];
+//    
+//  }
+//  //-----------------------------------------------------------------------
+//  protected static final void fillBuckets(
+//        Map<String, List<MetadataTreeNode>> buckets
+//      , MetadataTreeNode node
+//                          )
+//  {
+//    String ga = node.getMd().getGA();
+//    List<MetadataTreeNode> bucket = buckets.get(ga);
+//    if( bucket == null )
+//    {
+//      // TODO og: assumption - around 32 GAVs per GA
+//      bucket = new ArrayList<MetadataTreeNode>( 32 );
+//      buckets.put( ga, bucket );
+//    }
+//    
+//    bucket.add( node );
+//    
+//    if( ! node.hasChildren() )
+//      return;
+//    
+//    for( MetadataTreeNode kid : node.getChildren() )
+//    {
+//      fillBuckets( buckets, kid );
+//    }
+//  }
+//  //-----------------------------------------------------------------------
+//  private final void addPB( IVecInt lits, IVec<BigInteger> coeff, boolean ge, BigInteger cardinality )
+//  throws ContradictionException
+//  {
+//    _solver.addPseudoBoolean( lits, coeff, ge, cardinality );
+//    
+//if( LOG.isDebugEnabled() )
+//  LOG.debug("PB: ");
+//    
+//    for( int i=0; i<lits.size(); i++ )
+//    {
+//      int co = Integer.parseInt( ""+coeff.get(i) );
+//      String sign = co < 0 ? "-" : "+";
+//      int    val = Math.abs(co);
+//      String space = val == 1 ? "" : " ";
+//      
+//if( LOG.isDebugEnabled() )
+//  LOG.debug( " " + sign + (val==1?"":val) + space  + "x"+lits.get(i) );
+//    }
+//if( LOG.isDebugEnabled() )
+//  LOG.debug(( ge ? " >= " : " < ")+" "+cardinality );
+//  }
+//  //-----------------------------------------------------------------------
+//  private final Map<ArtifactMetadata, List<MetadataTreeNode>> processChildren(
+//                                                        List<ArtifactMetadata> queries
+//                                                        , List<MetadataTreeNode> children
+//                                                                              )
+//  throws SatException
+//  {
+//    if( queries == null || queries.size() < 1 )
+//      return null;
+//    
+//    if( children == null || children.size() < 1 )
+//      throw new SatException("there are queries, but not results. Queries: "+queries);
+//    
+//    // TODO og: MERCURY-40
+//    Map<ArtifactMetadata, List<MetadataTreeNode>> res = new LinkedHashMap<ArtifactMetadata, List<MetadataTreeNode>>( queries.size() );
+//
+//    for( ArtifactMetadata q : queries )
+//    {
+//      List<MetadataTreeNode> bucket = new ArrayList<MetadataTreeNode>(4);
+//      String queryGA = q.getGA();
+//      
+//      for( MetadataTreeNode tn : children )
+//      {
+//        if( tn.getMd() == null )
+//          throw new SatException("resulting tree node without metadata for query "+q );
+//        
+//        if( queryGA.equals( tn.getMd().getGA()) )
+//        {
+//          bucket.add(tn);
+//        }
+//      }
+//      
+//      if( bucket.size() < 1 )
+//        throw new SatException("No children for query "+queryGA );
+//      
+//      res.put( q, bucket );
+//    }
+//
+//    return res;
+//  } 
+//  //-----------------------------------------------------------------------
+//  private final void addNode( MetadataTreeNode node )
+//  throws ContradictionException, SatException
+//  {
+//    if( node == null )
+//      return;
+//    
+//    if( node.getMd() == null )
+//      throw new SatException("found a node without metadata");
+//    
+//    // this one is a must :)
+//    if( node.getParent() == null )
+//      _helper.setTrue( node, node.getName() );
+//    
+//    if( ! node.hasChildren() )
+//      return;
+//    
+//    Map<ArtifactMetadata,List<MetadataTreeNode>> kids = processChildren( node.getQueries(), node.getChildren() );
+//    
+//    // leaf node in this scope
+//    if( kids == null )
+//      return;
+//    
+//    for( Map.Entry<ArtifactMetadata,List<MetadataTreeNode>> kid : kids.entrySet() )
+//    {
+//      ArtifactMetadata query = kid.getKey();
+//      
+//      List<MetadataTreeNode> range = kid.getValue();
+//
+//      if( range.size() > 1 )
+//      {
+//        addRange( nodeLit.getLiteral(), range, query.isOptional() );
+//        for( MetadataTreeNode tn : range )
+//        {
+//          addNode( tn );
+//        }
+//      }
+//      else
+//      {
+//        MetadataTreeNode child = range.get(0);
+//        SatVar kidLit = _context.findOrAdd( child );
+//        
+//        addPB( SatHelper.getSmallOnes( new int [] { nodeLit.getLiteral(), kidLit.getLiteral() } )
+//            , SatHelper.getBigOnes( 1, -1 )
+//            , true, BigInteger.ZERO
+//            );
+////        addRange( nodeLit.getLiteral(), range, query.isOptional() );
+//        addNode( child );
+//      }
+//
+//    }
+//  }
+//  //-----------------------------------------------------------------------
+//  private final int [] addRange( int parentLiteral, List<MetadataTreeNode> range, boolean optional )
+//  throws ContradictionException, SatException
+//  {
+//    SatVar literal;
+//    
+//    int [] literals = new int[ range.size() ];
+//    
+//    int count = 0;
+//    
+//    for( MetadataTreeNode tn : range )
+//    {
+//      literal = _context.findOrAdd( tn );
+//      literals[count++] = literal.getLiteral();
+//
+//      // implication to parent
+//      addPB( SatHelper.getSmallOnes( new int [] { parentLiteral, literal.getLiteral() } )
+//          , SatHelper.getBigOnes( 1, -1 )
+//          , true, BigInteger.ZERO
+//          );
+//    }
+//    
+//    IVecInt rangeVector = SatHelper.getSmallOnes( literals );
+//    
+//    if( optional ) // Sxi >= 0
+//    {
+//if( LOG.isDebugEnabled() )
+//  LOG.debug( "optional range: atMost 1: "+ SatHelper.vectorToString( rangeVector) );
+//    
+//      _solver.addAtMost( rangeVector, 1 );
+//    }
+//    else // Sxi = 1
+//    {
+//if( LOG.isDebugEnabled() )
+//  LOG.debug( "range: " + SatHelper.vectorToString( rangeVector) );
+//
+//    IConstr atLeast = _solver.addAtLeast( rangeVector, 1 );
+//    if( LOG.isDebugEnabled() )
+//      LOG.debug( "atLeast: " + SatHelper.vectorToString( atLeast) );
+//
+//    IConstr atMost  = _solver.addAtMost( rangeVector, 1 );
+//    if( LOG.isDebugEnabled() )
+//      LOG.debug( "atMost: " + SatHelper.vectorToString( atMost) );
+//
+//    }
+//    
+//    return literals;
+//  }
+//  //-----------------------------------------------------------------------
+//  public final List<ArtifactMetadata> solve()
+//  throws SatException
+//  {
+//    List<ArtifactMetadata> res = null;
+//    GenericEvent event = null;
+//    
+//    try
+//    {
+//      if( _eventManager != null )
+//        event = new GenericEvent( EventTypeEnum.satSolver, EVENT_SOLVE, _root.toString() );
+//      
+//      if( _solver.isSatisfiable() )
+//      {
+//        res = new ArrayList<ArtifactMetadata>( _root.countNodes() );
+//        
+//        int [] model = _solver.model();
+//
+//if( LOG.isDebugEnabled() )
+//  if( model != null )
+//  {
+//    StringBuilder sb = new StringBuilder();
+//    String comma = "";
+//    for( int m : model )
+//    {
+//      sb.append( comma+m );
+//      comma = ", ";
+//    }
+//    LOG.debug( '['+sb.toString()+']' );
+//  }
+//  else 
+//    LOG.debug( "model is null" );
+//
+//        for( int i : model )
+//          if( i > 0 )
+//            res.add( _context.getMd( i ) );
+//      }
+//    }
+//    catch (TimeoutException e)
+//    {
+//      throw new SatException( e );
+//    }
+//    finally
+//    {
+//      if( _eventManager != null )
+//      {
+//        event.stop();
+//        _eventManager.fireEvent( event );
+//      }
+//    }
+//    return res;
+//  }
+//  //-----------------------------------------------------------------------
+//  public final MetadataTreeNode solveAsTree()
+//  throws SatException
+//  {
+//    try
+//    {
+//      if( _helper.hasASolution() )
+//      {
+//          
+//         IVec<MetadataTreeNode> solution = _helper.getSolution();
+//         
+//         if( solution == null )
+//             return null;
+//         
+//         for( Iterator<MetadataTreeNode> i = solution.iterator(); i.hasNext(); )
+//         {
+//             MetadataTreeNode mtn = i.next();
+//             
+//             if( mtn.getParent() == null )
+//                 return mtn;
+//         }
+//         
+//      return null;
+//      }
+//    }
+//    catch (TimeoutException e)
+//    {
+//      throw new SatException( e );
+//    }
+//    
+//  }
+//  //-----------------------------------------------------------------------
+//  public void register( MercuryEventListener listener )
+//  {
+//    if( _eventManager == null )
+//      _eventManager = new EventManager();
+//
+//    _eventManager.register( listener );
+//  }
+//
+//  public void setEventManager( EventManager eventManager )
+//  {
+//    _eventManager = eventManager;
+//  }
+//
+//  public void unRegister( MercuryEventListener listener )
+//  {
+//    if( _eventManager != null )
+//      _eventManager.unRegister( listener );
+//  }
+//  //-----------------------------------------------------------------------
+//}
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/Messages.properties b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/Messages.properties
index 9200332..fda7b16 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/Messages.properties
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/Messages.properties
@@ -20,3 +20,5 @@
 null.tree.md=tree root metadata is null
 null.model=model is null
 empty.model=model is null
+
+null.tree.arg=cannot create a solver for an empty [null] tree
\ No newline at end of file
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatContext.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatContext.java
index 15d39d3..a125549 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatContext.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatContext.java
@@ -24,9 +24,9 @@
 import java.util.Map;
 
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
-import org.apache.maven.mercury.metadata.MetadataTreeNode;
 import org.codehaus.plexus.lang.DefaultLanguage;
 import org.codehaus.plexus.lang.Language;
 
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatOptimizer.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatOptimizer.java
index 2ed7ae3..2a59ddd 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatOptimizer.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatOptimizer.java
@@ -18,7 +18,7 @@
  */
 package org.apache.maven.mercury.metadata.sat;
 
-import org.apache.maven.mercury.metadata.MetadataTreeNode;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.sat4j.pb.ObjectiveFunction;
 
 /**
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatSolver.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatSolver.java
index 6a37977..ec9f4ae 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatSolver.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatSolver.java
@@ -22,8 +22,8 @@
 import java.util.List;
 
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.event.EventGenerator;
-import org.apache.maven.mercury.metadata.MetadataTreeNode;
 
 /**
  * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
diff --git a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatVar.java b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatVar.java
index b2a0726..921e98f 100644
--- a/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatVar.java
+++ b/mercury-md/mercury-md-sat/src/main/java/org/apache/maven/mercury/metadata/sat/SatVar.java
@@ -19,7 +19,7 @@
 package org.apache.maven.mercury.metadata.sat;
 
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
-import org.apache.maven.mercury.metadata.MetadataTreeNode;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 
 /**
  * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
diff --git a/mercury-md/mercury-md-sat/src/main/mdo/forest.mdo b/mercury-md/mercury-md-sat/src/main/mdo/forest.mdo
new file mode 100644
index 0000000..c460b50
--- /dev/null
+++ b/mercury-md/mercury-md-sat/src/main/mdo/forest.mdo
@@ -0,0 +1,153 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<model>
+  <id>forest</id>
+  
+  <name>Forrest</name>
+  
+  <defaults>
+    <default>
+      <key>package</key>
+      <value>org.apache.maven.mercury.metadata.forest</value>
+    </default>
+  </defaults>
+  
+  <classes>
+
+    <class rootElement="true">
+      <name>Forest</name>
+      <version>1.0.0</version>
+      <fields>
+
+        <field>
+          <name>trees</name>
+          <version>1.0.0</version>
+          <association>
+            <type>Tree</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+
+      </fields>
+   </class>
+
+    <class>
+      <name>Tree</name>
+      <version>1.0.0</version>
+      <fields>
+
+        <field>
+          <name>timestamp</name>
+          <version>1.0.0</version>
+          <type>String</type>
+        </field>
+
+        <field>
+          <name>scope</name>
+          <version>1.0.0</version>
+          <type>String</type>
+        </field>
+        
+        <field>
+          <name>request</name>
+          <version>1.0.0</version>
+          <association>
+            <type>Node</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        
+        <field>
+          <name>inclusions</name>
+          <version>1.0.0</version>
+          <association>
+            <type>Node</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        
+        <field>
+          <name>exclusions</name>
+          <version>1.0.0</version>
+          <association>
+            <type>Node</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+        
+        <field>
+          <name>dirtyTree</name>
+          <version>1.0.0</version>
+          <association>
+            <type>Node</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+         
+        <field>
+          <name>result</name>
+          <version>1.0.0</version>
+          <association>
+            <type>Node</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+
+      </fields>
+   </class>
+
+    <class>
+      <name>Node</name>
+      <version>1.0.0</version>
+
+      <fields>
+
+        <field>
+          <name>name</name>
+          <version>1.0.0</version>
+          <type>String</type>
+        </field>
+
+        <field>
+          <name>scope</name>
+          <version>1.0.0</version>
+          <type>String</type>
+        </field>
+
+        <field>
+          <name>level</name>
+          <version>1.0.0</version>
+          <type>long</type>
+        </field>
+         
+        <field>
+          <name>children</name>
+          <version>1.0.0</version>
+          <association>
+            <type>Node</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+
+      </fields>
+    </class>
+
+  </classes>
+</model>
diff --git a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/AbstractSimpleTreeTest.java b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/AbstractSimpleTreeTest.java
index d6bfdf9..6c6ed75 100644
--- a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/AbstractSimpleTreeTest.java
+++ b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/AbstractSimpleTreeTest.java
@@ -21,6 +21,7 @@
 import junit.framework.TestCase;
 
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 
 public abstract class AbstractSimpleTreeTest
 extends TestCase
diff --git a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/ClassicDepthComparatorTest.java b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/ClassicDepthComparatorTest.java
index b4cfa58..77e149b 100644
--- a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/ClassicDepthComparatorTest.java
+++ b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/ClassicDepthComparatorTest.java
@@ -20,6 +20,8 @@
 
 import java.util.Comparator;
 
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
+
 public class ClassicDepthComparatorTest
 extends AbstractSimpleTreeTest
 {
diff --git a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/ClassicVersionComparatorTest.java b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/ClassicVersionComparatorTest.java
index 274cdc2..73ed74d 100644
--- a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/ClassicVersionComparatorTest.java
+++ b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/ClassicVersionComparatorTest.java
@@ -20,6 +20,8 @@
 
 import java.util.Comparator;
 
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
+
 
 public class ClassicVersionComparatorTest
 extends AbstractSimpleTreeTest
diff --git a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/DependencyTreeBuilderTest.java b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/DependencyTreeBuilderTest.java
index 336f046..1a0a4d9 100644
--- a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/DependencyTreeBuilderTest.java
+++ b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/DependencyTreeBuilderTest.java
@@ -24,9 +24,9 @@
 
 import junit.framework.TestCase;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
@@ -160,8 +160,8 @@
     String title = "testResolveScopedConflictsWithFiltering";
     ArtifactMetadata md = new ArtifactMetadata( "a:a:4" );
     
-    List<ArtifactBasicMetadata> exclusions = new ArrayList<ArtifactBasicMetadata>();
-    exclusions.add( new ArtifactBasicMetadata("c:c:3") );
+    List<ArtifactMetadata> exclusions = new ArrayList<ArtifactMetadata>();
+    exclusions.add( new ArtifactMetadata("c:c:3") );
     md.setExclusions( exclusions );
     
     MetadataTreeNode root = mt.buildTree( md, ArtifactScopeEnum.compile );
@@ -185,8 +185,8 @@
     String title = "testResolveScopedConflictsWithFilteringOne";
     ArtifactMetadata md = new ArtifactMetadata( "a:a:2" );
     
-    List<ArtifactBasicMetadata> exclusions = new ArrayList<ArtifactBasicMetadata>();
-    exclusions.add( new ArtifactBasicMetadata("c:c:2") );
+    List<ArtifactMetadata> exclusions = new ArrayList<ArtifactMetadata>();
+    exclusions.add( new ArtifactMetadata("c:c:2") );
     md.setExclusions( exclusions );
     
     MetadataTreeNode root = mt.buildTree( md, ArtifactScopeEnum.compile );
@@ -211,9 +211,9 @@
     String title = "testResolveScopedConflictsWithFilteringTwo";
     ArtifactMetadata md = new ArtifactMetadata( "a:a:2" );
     
-    List<ArtifactBasicMetadata> exclusions = new ArrayList<ArtifactBasicMetadata>();
-    exclusions.add( new ArtifactBasicMetadata("b:b:2") );
-    exclusions.add( new ArtifactBasicMetadata("c:c:2") );
+    List<ArtifactMetadata> exclusions = new ArrayList<ArtifactMetadata>();
+    exclusions.add( new ArtifactMetadata("b:b:2") );
+    exclusions.add( new ArtifactMetadata("c:c:2") );
     md.setExclusions( exclusions );
     
     MetadataTreeNode root = mt.buildTree( md, ArtifactScopeEnum.compile );
@@ -239,10 +239,10 @@
     String title = "testResolveScopedConflictsWithFilteringTwo";
     ArtifactMetadata md = new ArtifactMetadata( "a:a:2" );
     
-    List<ArtifactBasicMetadata> exclusions = new ArrayList<ArtifactBasicMetadata>();
-    exclusions.add( new ArtifactBasicMetadata("b:b:1") );
-    exclusions.add( new ArtifactBasicMetadata("b:b:2") );
-    exclusions.add( new ArtifactBasicMetadata("c:c:2") );
+    List<ArtifactMetadata> exclusions = new ArrayList<ArtifactMetadata>();
+    exclusions.add( new ArtifactMetadata("b:b:1") );
+    exclusions.add( new ArtifactMetadata("b:b:2") );
+    exclusions.add( new ArtifactMetadata("c:c:2") );
     md.setExclusions( exclusions );
     
     MetadataTreeNode root = mt.buildTree( md, ArtifactScopeEnum.compile );
diff --git a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/sat/DefaultSatSolverTest.java b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/sat/DefaultSatSolverTest.java
index 5751667..e78d94a 100644
--- a/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/sat/DefaultSatSolverTest.java
+++ b/mercury-md/mercury-md-sat/src/test/java/org/apache/maven/mercury/metadata/sat/DefaultSatSolverTest.java
@@ -27,11 +27,10 @@
 
 import junit.framework.TestCase;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.metadata.ClassicDepthComparator;
 import org.apache.maven.mercury.metadata.ClassicVersionComparator;
-import org.apache.maven.mercury.metadata.MetadataTreeNode;
 
 /**
  * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
@@ -101,7 +100,7 @@
       .addQuery(b2)
     ;
     
-    ArtifactBasicMetadata c2q = new ArtifactBasicMetadata("t:c:[2,4)");
+    ArtifactMetadata c2q = new ArtifactMetadata("t:c:[2,4)");
     
     MetadataTreeNode nd1 = new MetadataTreeNode( d1, na1, d1 )
       .addQuery( c2q )
@@ -363,7 +362,7 @@
       .addQuery(b2)
     ;
     
-    ArtifactBasicMetadata c2q = new ArtifactBasicMetadata("t:c:[2,4)");
+    ArtifactMetadata c2q = new ArtifactMetadata("t:c:[2,4)");
     
     MetadataTreeNode nb1 = new MetadataTreeNode( b1, na1, b1 )
       .addQuery( c2q )
@@ -440,7 +439,7 @@
       .addQuery(b2)
     ;
     
-    ArtifactBasicMetadata c2q = new ArtifactBasicMetadata("t:c:[2,4)");
+    ArtifactMetadata c2q = new ArtifactMetadata("t:c:[2,4)");
     
     MetadataTreeNode nd1 = new MetadataTreeNode( d1, na1, d1 )
       .addQuery( c2q )
@@ -519,7 +518,7 @@
       .addQuery(b2)
     ;
     
-    ArtifactBasicMetadata c2q = new ArtifactBasicMetadata("t:c:[2,4)");
+    ArtifactMetadata c2q = new ArtifactMetadata("t:c:[2,4)");
     
     MetadataTreeNode nd1 = new MetadataTreeNode( d1, na1, d1 )
       .addQuery( c2q )
diff --git a/mercury-md/mercury-md-shared/pom.xml b/mercury-md/mercury-md-shared/pom.xml
index df920e8..f0f0af4 100644
--- a/mercury-md/mercury-md-shared/pom.xml
+++ b/mercury-md/mercury-md-shared/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-md</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <groupId>org.apache.maven.mercury</groupId>
@@ -63,7 +63,6 @@
       <plugin>
         <groupId>org.codehaus.modello</groupId>
         <artifactId>modello-maven-plugin</artifactId>
-        <version>1.0-alpha-21</version>
         <configuration>
           <version>1.0.0</version>
           <models>
diff --git a/mercury-md/mercury-md-shared/src/main/java/org/apache/maven/mercury/repository/metadata/AddPluginOperation.java b/mercury-md/mercury-md-shared/src/main/java/org/apache/maven/mercury/repository/metadata/AddPluginOperation.java
index 68160fc..563efef 100644
--- a/mercury-md/mercury-md-shared/src/main/java/org/apache/maven/mercury/repository/metadata/AddPluginOperation.java
+++ b/mercury-md/mercury-md-shared/src/main/java/org/apache/maven/mercury/repository/metadata/AddPluginOperation.java
@@ -18,6 +18,8 @@
  */
 package org.apache.maven.mercury.repository.metadata;
 
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 import org.codehaus.plexus.lang.DefaultLanguage;
@@ -35,6 +37,12 @@
     private static final Language LANG = new DefaultLanguage( AddPluginOperation.class );
 
     private Plugin plugin;
+    
+    private static PluginComparator pluginComparator;
+    
+    {
+        pluginComparator = new PluginComparator();
+    }
 
     /**
      * @throws MetadataException
@@ -87,7 +95,29 @@
         // not found, add it
         plugins.add( plugin );
 
+        Collections.sort( plugins, pluginComparator );
+        
         return true;
     }
+    
+    class PluginComparator
+        implements Comparator<Plugin>
+    {
+        public int compare( Plugin p1, Plugin p2 )
+        {
+            if ( p1 == null || p2 == null )
+            {
+                throw new IllegalArgumentException( LANG.getMessage( "null.plugin.to.compare" ) );
+            }
+
+            if ( p1.getArtifactId() == null || p2.getArtifactId() == null )
+            {
+                throw new IllegalArgumentException( LANG.getMessage( "null.plugin.artifactId.to.compare", p1
+                    .getArtifactId(), p2.getArtifactId() ) );
+            }
+
+            return p1.getArtifactId().compareTo( p2.getArtifactId() );
+        }
+    }
 
 }
diff --git a/mercury-md/mercury-md-shared/src/test/java/org/apache/maven/mercury/repository/metadata/MetadataBuilderTest.java b/mercury-md/mercury-md-shared/src/test/java/org/apache/maven/mercury/repository/metadata/MetadataBuilderTest.java
index 56f669a..c364688 100644
--- a/mercury-md/mercury-md-shared/src/test/java/org/apache/maven/mercury/repository/metadata/MetadataBuilderTest.java
+++ b/mercury-md/mercury-md-shared/src/test/java/org/apache/maven/mercury/repository/metadata/MetadataBuilderTest.java
@@ -129,40 +129,52 @@
      assertEquals( 2, versions.size() );
   }
   //-------------------------------------------------------------------------
-  public void testAddPluginOperation()
-  throws FileNotFoundException, IOException, XmlPullParserException, MetadataException
-  {
-    File groupMd = new File( testBase, "group-maven-metadata.xml");
-    byte [] targetBytes = FileUtil.readRawData( groupMd );
+    public void testAddPluginOperation()
+        throws Exception
+    {
+        File mdFileBefore = new File( testBase, "group-maven-metadata.xml" );
+        Metadata mdBefore = getMetadata( mdFileBefore );
 
-    Plugin plugin = new Plugin();
-    plugin.setArtifactId( "some-artifact-id" );
-    plugin.setName( "Some Plugin" );
-    plugin.setPrefix( "some" );
+        Plugin pluginA = new Plugin();
+        pluginA.setArtifactId( "maven-testa-plugin" );
+        pluginA.setName( "Some Plugin A" );
+        pluginA.setPrefix( "testa" );
+        Plugin pluginB = new Plugin();
+        pluginB.setArtifactId( "maven-testb-plugin" );
+        pluginB.setName( "Some Plugin B" );
+        pluginB.setPrefix( "testb" );
+        Plugin pluginC = new Plugin();
+        pluginC.setArtifactId( "maven-testc-plugin" );
+        pluginC.setName( "Some Plugin C" );
+        pluginC.setPrefix( "testc" );
 
-    byte [] resBytes = MetadataBuilder.changeMetadata( targetBytes, new AddPluginOperation( new PluginOperand(plugin) ) );
+        List<MetadataOperation> opsAdd = new ArrayList<MetadataOperation>();
 
-    File resFile = new File( testBase, "group-maven-metadata-write.xml");
+        opsAdd.add( new AddPluginOperation( new PluginOperand( pluginC ) ) );
+        opsAdd.add( new AddPluginOperation( new PluginOperand( pluginB ) ) );
+        opsAdd.add( new AddPluginOperation( new PluginOperand( pluginA ) ) );
 
-    FileUtil.writeRawData( resFile, resBytes );
+        File mdFileAfter = new File( testBase, "group-maven-metadata-write.xml" );
+        Metadata mdAfterAdd = applyOpsAndGetMetadata( mdBefore, opsAdd, mdFileAfter );
 
-     Metadata mmd = MetadataBuilder.read( new FileInputStream(resFile) );
+        assertEquals( 3, mdAfterAdd.getPlugins().size() );
+        assertEquals( "maven-testa-plugin", ( (Plugin) mdAfterAdd.getPlugins().get( 0 ) ).getArtifactId() );
+        assertEquals( "testa", ( (Plugin) mdAfterAdd.getPlugins().get( 0 ) ).getPrefix() );
+        assertEquals( "Some Plugin A", ( (Plugin) mdAfterAdd.getPlugins().get( 0 ) ).getName() );
+        assertEquals( "maven-testb-plugin", ( (Plugin) mdAfterAdd.getPlugins().get( 1 ) ).getArtifactId() );
+        assertEquals( "maven-testc-plugin", ( (Plugin) mdAfterAdd.getPlugins().get( 2 ) ).getArtifactId() );
 
-     assertNotNull( mmd );
-     assertEquals(1, mmd.getPlugins().size() );
-     assertEquals("some-artifact-id", ((Plugin)mmd.getPlugins().get( 0 )).getArtifactId() );
-     assertEquals("Some Plugin", ((Plugin)mmd.getPlugins().get( 0 )).getName() );
-     assertEquals("some", ((Plugin)mmd.getPlugins().get( 0 )).getPrefix() );
+        List<MetadataOperation> opsRemove = new ArrayList<MetadataOperation>();
 
-     // now let's drop plugin
-     targetBytes = FileUtil.readRawData( resFile );
-     resBytes = MetadataBuilder.changeMetadata( targetBytes, new RemovePluginOperation( new PluginOperand(plugin) ) );
+        opsRemove.add( new RemovePluginOperation( new PluginOperand( pluginA ) ) );
+        opsRemove.add( new RemovePluginOperation( new PluginOperand( pluginB ) ) );
+        opsRemove.add( new RemovePluginOperation( new PluginOperand( pluginC ) ) );
 
-     Metadata mmd2 = MetadataBuilder.read( new ByteArrayInputStream(resBytes) );
+        Metadata mdAfterRemove = applyOpsAndGetMetadata( mdAfterAdd, opsRemove, mdFileAfter );
 
-     assertNotNull( mmd2 );
-     assertEquals(0, mmd2.getPlugins().size() );
-  }
+        assertEquals( 0, mdAfterRemove.getPlugins().size() );
+    }
+    
   //-------------------------------------------------------------------------
   public void testMergeOperation()
   throws FileNotFoundException, IOException, XmlPullParserException, MetadataException
diff --git a/mercury-md/pom.xml b/mercury-md/pom.xml
index a0f30e7..3f1df48 100644
--- a/mercury-md/pom.xml
+++ b/mercury-md/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-md</artifactId>
diff --git a/mercury-plexus/pom.xml b/mercury-plexus/pom.xml
index e9220f9..364a5af 100644
--- a/mercury-plexus/pom.xml
+++ b/mercury-plexus/pom.xml
@@ -23,13 +23,28 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-plexus</artifactId>
   <name>Mercury Plexus Component</name>
 
   <dependencies>
+  
+    <dependency>
+      <groupId>bouncycastle</groupId>
+      <artifactId>bcprov-jdk15</artifactId>
+      <optional>true</optional>
+    </dependency>
+
+    <dependency>
+      <groupId>bouncycastle</groupId>
+      <artifactId>bcpg-jdk15</artifactId>
+      <optional>true</optional>
+    </dependency>
+<!-- 
+ -->
+  
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
diff --git a/mercury-plexus/src/main/java/org/apache/maven/mercury/plexus/DefaultPlexusMercury.java b/mercury-plexus/src/main/java/org/apache/maven/mercury/plexus/DefaultPlexusMercury.java
index fe6c6ea..c8fc0f9 100644
--- a/mercury-plexus/src/main/java/org/apache/maven/mercury/plexus/DefaultPlexusMercury.java
+++ b/mercury-plexus/src/main/java/org/apache/maven/mercury/plexus/DefaultPlexusMercury.java
@@ -30,12 +30,12 @@
 import java.util.Set;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactExclusionList;
 import org.apache.maven.mercury.artifact.ArtifactInclusionList;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.ArtifactQueryList;
 import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.crypto.api.StreamObserverFactory;
 import org.apache.maven.mercury.crypto.api.StreamVerifierAttributes;
@@ -47,7 +47,7 @@
 import org.apache.maven.mercury.metadata.DependencyBuilder;
 import org.apache.maven.mercury.metadata.DependencyBuilderFactory;
 import org.apache.maven.mercury.metadata.MetadataTreeException;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.api.RepositoryException;
@@ -83,6 +83,9 @@
     @Configuration( name = "defaultDependencyProcessorHint", value = "maven" )
     String _defaultDpHint = "maven";
 
+    @Configuration( name = "allowCircularDependencies", value = "true" )
+    boolean _allowCircularDependencies = true;
+
     @Requirement
     private Map<String, DependencyProcessor> _dependencyProcessors;
 
@@ -113,6 +116,11 @@
         _defaultDpHint = hint;
     }
     // ---------------------------------------------------------------
+    public void setAllowCircularDependencies( boolean allow )
+    {
+        _allowCircularDependencies = allow;
+    }
+    // ---------------------------------------------------------------
     public RemoteRepositoryM2 constructRemoteRepositoryM2( String id, URL serverUrl, String serverUser,
                                                            String serverPass, URL proxyUrl, String proxyUser,
                                                            String proxyPass,
@@ -200,7 +208,7 @@
 
     // ---------------------------------------------------------------
     // ---------------------------------------------------------------
-    public List<Artifact> read( List<Repository> repos, List<? extends ArtifactBasicMetadata> artifacts )
+    public List<Artifact> read( List<Repository> repos, List<? extends ArtifactMetadata> artifacts )
         throws RepositoryException
     {
         if ( Util.isEmpty( repos ) )
@@ -219,17 +227,17 @@
         if ( !ar.hasResults() )
             return null;
 
-        Map<ArtifactBasicMetadata, List<Artifact>> am = ar.getResults();
+        Map<ArtifactMetadata, List<Artifact>> am = ar.getResults();
 
         List<Artifact> al = new ArrayList<Artifact>();
-        for ( Map.Entry<ArtifactBasicMetadata, List<Artifact>> e : am.entrySet() )
+        for ( Map.Entry<ArtifactMetadata, List<Artifact>> e : am.entrySet() )
             al.addAll( e.getValue() );
 
         return al;
 
     }
 
-    public List<Artifact> read( List<Repository> repos, ArtifactBasicMetadata... artifacts )
+    public List<Artifact> read( List<Repository> repos, ArtifactMetadata... artifacts )
         throws RepositoryException
     {
         return read( repos, Arrays.asList( artifacts ) );
@@ -274,9 +282,44 @@
         try
         {
             DependencyBuilder depBuilder =
-                DependencyBuilderFactory.create( DependencyBuilderFactory.JAVA_DEPENDENCY_MODEL, repos, null, null, null );
+                DependencyBuilderFactory.create( DependencyBuilderFactory.JAVA_DEPENDENCY_MODEL, repos, null, null, null
+                    , Util.mapOf( new Object [][] { {DependencyBuilder.SYSTEM_PROPERTY_ALLOW_CIRCULAR_DEPENDENCIES, ""+_allowCircularDependencies} } ) 
+                                                );
 
             List<ArtifactMetadata> res = depBuilder.resolveConflicts( scope, artifacts, inclusions, exclusions );
+            
+            depBuilder.close();
+
+            return res;
+        }
+        catch ( MetadataTreeException e )
+        {
+            throw new RepositoryException( e );
+        }
+    }
+
+    // ---------------------------------------------------------------
+    public MetadataTreeNode resolveAsTree( List<Repository> repos
+                                           , ArtifactScopeEnum scope
+                                           , ArtifactQueryList artifacts
+                                           , ArtifactInclusionList inclusions
+                                           , ArtifactExclusionList exclusions
+                                           )
+        throws RepositoryException
+    {
+        if ( Util.isEmpty( artifacts ) || artifacts.isEmpty() )
+            throw new IllegalArgumentException( LANG.getMessage( "no.artifacts" ) );
+
+        try
+        {
+            DependencyBuilder depBuilder =
+                DependencyBuilderFactory.create( DependencyBuilderFactory.JAVA_DEPENDENCY_MODEL, repos, null, null, null
+                       , Util.mapOf( new String [][] { {DependencyBuilder.SYSTEM_PROPERTY_ALLOW_CIRCULAR_DEPENDENCIES, ""+_allowCircularDependencies} } ) 
+                );
+
+            MetadataTreeNode res = depBuilder.resolveConflictsAsTree( scope, artifacts, inclusions, exclusions );
+            
+            depBuilder.close();
 
             return res;
         }
@@ -295,14 +338,14 @@
      * @return list of found version metadatas
      * @throws PlexusMercuryException
      */
-    public List<ArtifactBasicMetadata> readVersions( List<Repository> repos, ArtifactBasicMetadata query )
+    public List<ArtifactMetadata> readVersions( List<Repository> repos, ArtifactMetadata query )
         throws RepositoryException
     {
         VirtualRepositoryReader vr = new VirtualRepositoryReader( repos );
-        List<ArtifactBasicMetadata> q = new ArrayList<ArtifactBasicMetadata>( 1 );
+        List<ArtifactMetadata> q = new ArrayList<ArtifactMetadata>( 1 );
         q.add( query );
 
-        ArtifactBasicResults res = vr.readVersions( q );
+        MetadataResults res = vr.readVersions( q );
 
         if ( res == null )
             return null;
diff --git a/mercury-plexus/src/main/java/org/apache/maven/mercury/plexus/PlexusMercury.java b/mercury-plexus/src/main/java/org/apache/maven/mercury/plexus/PlexusMercury.java
index 52c5318..27209f1 100644
--- a/mercury-plexus/src/main/java/org/apache/maven/mercury/plexus/PlexusMercury.java
+++ b/mercury-plexus/src/main/java/org/apache/maven/mercury/plexus/PlexusMercury.java
@@ -26,12 +26,12 @@
 import java.util.Set;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactExclusionList;
 import org.apache.maven.mercury.artifact.ArtifactInclusionList;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.ArtifactQueryList;
 import org.apache.maven.mercury.artifact.ArtifactScopeEnum;
+import org.apache.maven.mercury.artifact.MetadataTreeNode;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.crypto.api.StreamObserverFactory;
 import org.apache.maven.mercury.crypto.api.StreamVerifierException;
@@ -172,10 +172,10 @@
      * @return
      * @throws PlexusMercuryException
      */
-    public List<Artifact> read( List<Repository> repo, List<? extends ArtifactBasicMetadata> artifacts )
+    public List<Artifact> read( List<Repository> repo, List<? extends ArtifactMetadata> artifacts )
         throws RepositoryException;
 
-    public List<Artifact> read( List<Repository> repo, ArtifactBasicMetadata... artifacts )
+    public List<Artifact> read( List<Repository> repo, ArtifactMetadata... artifacts )
         throws RepositoryException;
 
     /**
@@ -194,6 +194,11 @@
                                            ArtifactExclusionList exclusions )
         throws RepositoryException;
 
+    public MetadataTreeNode resolveAsTree( List<Repository> repos, ArtifactScopeEnum scope,
+                                           ArtifactQueryList artifacts, ArtifactInclusionList inclusions,
+                                           ArtifactExclusionList exclusions )
+        throws RepositoryException;
+
     public List<ArtifactMetadata> resolve( List<Repository> repos, ArtifactScopeEnum scope, ArtifactMetadata metadata )
         throws RepositoryException;
 
@@ -205,6 +210,6 @@
      * @return list of found version metadatas
      * @throws PlexusMercuryException
      */
-    public List<ArtifactBasicMetadata> readVersions( List<Repository> repos, ArtifactBasicMetadata query )
+    public List<ArtifactMetadata> readVersions( List<Repository> repos, ArtifactMetadata query )
         throws RepositoryException;
 }
diff --git a/mercury-repo/mercury-repo-api/pom.xml b/mercury-repo/mercury-repo-api/pom.xml
index 16ef3db..5811bf4 100644
--- a/mercury-repo/mercury-repo-api/pom.xml
+++ b/mercury-repo/mercury-repo-api/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-repo</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <groupId>org.apache.maven.mercury</groupId>
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstracRepositoryReader.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstracRepositoryReader.java
index 3594df0..d671b26 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstracRepositoryReader.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstracRepositoryReader.java
@@ -18,73 +18,71 @@
  */
 package org.apache.maven.mercury.repository.api;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.builder.api.MetadataReader;
 import org.apache.maven.mercury.builder.api.MetadataReaderException;
 
-
 /**
  * This is to keep MetadataProcessor for all readers
- *
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public abstract class AbstracRepositoryReader
-implements RepositoryReader, MetadataReader
+    implements RepositoryReader, MetadataReader
 {
-  protected DependencyProcessor    _mdProcessor;
-  
-  protected MetadataReader         _mdReader;
-  
-  protected RepositoryMetadataCache _mdCache;
-  
-  public void setDependencyProcessor( DependencyProcessor mdProcessor )
-  {
-    _mdProcessor = mdProcessor;
-  }
-  
-  public DependencyProcessor getDependencyProcessor()
-  {
-    return _mdProcessor;
-  }
-  
-  public void setMetadataReader( MetadataReader mdReader )
-  {
-    _mdReader = mdReader;
-  }
-  
-  public MetadataReader getMetadataReader()
-  {
-    return _mdReader;
-  }
-  
-  public void setMetadataCache( RepositoryMetadataCache mdCache )
-  {
-    this._mdCache = mdCache;
-  }
-  
-  public RepositoryMetadataCache getMetadataCache()
-  {
-    return _mdCache;
-  }
-  
-  public boolean hasMetadataCache()
-  {
-    return _mdCache != null;
-  }
-  
-  public byte[] readMetadata( ArtifactBasicMetadata bmd, boolean exempt  )
-  throws MetadataReaderException
-  {
-    return readRawData( bmd, "", "pom", exempt );
-  }
-  
-  public byte[] readMetadata( ArtifactBasicMetadata bmd )
-  throws MetadataReaderException
-  {
-    return readMetadata( bmd, false );
-  }
-  
+    protected DependencyProcessor _mdProcessor;
+
+    protected MetadataReader _mdReader;
+
+    protected RepositoryMetadataCache _mdCache;
+
+    public void setDependencyProcessor( DependencyProcessor mdProcessor )
+    {
+        _mdProcessor = mdProcessor;
+    }
+
+    public DependencyProcessor getDependencyProcessor()
+    {
+        return _mdProcessor;
+    }
+
+    public void setMetadataReader( MetadataReader mdReader )
+    {
+        _mdReader = mdReader;
+    }
+
+    public MetadataReader getMetadataReader()
+    {
+        return _mdReader;
+    }
+
+    public void setMetadataCache( RepositoryMetadataCache mdCache )
+    {
+        this._mdCache = mdCache;
+    }
+
+    public RepositoryMetadataCache getMetadataCache()
+    {
+        return _mdCache;
+    }
+
+    public boolean hasMetadataCache()
+    {
+        return _mdCache != null;
+    }
+
+    public byte[] readMetadata( ArtifactMetadata bmd, boolean exempt )
+        throws MetadataReaderException
+    {
+        return readRawData( bmd, "", "pom", exempt );
+    }
+
+    public byte[] readMetadata( ArtifactMetadata bmd )
+        throws MetadataReaderException
+    {
+        return readMetadata( bmd, false );
+    }
+
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepOpResult.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepOpResult.java
index 4434a5b..51c4b41 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepOpResult.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepOpResult.java
@@ -21,7 +21,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 
 /**
  * generic repository operation result. Represents a Map of query object to AbstractRepositoryOperationResult
@@ -31,38 +31,38 @@
  */
 public abstract class AbstractRepOpResult
 {
-    private Map<ArtifactBasicMetadata, Exception> _exceptions;
+    private Map<ArtifactMetadata, Exception> _exceptions;
 
     public AbstractRepOpResult()
     {
     }
 
-    public Map<ArtifactBasicMetadata, Exception> getExceptions()
+    public Map<ArtifactMetadata, Exception> getExceptions()
     {
         return _exceptions;
     }
 
     public abstract boolean hasResults();
 
-    public abstract boolean hasResults( ArtifactBasicMetadata key );
+    public abstract boolean hasResults( ArtifactMetadata key );
 
     public boolean hasExceptions()
     {
         return _exceptions != null && !_exceptions.isEmpty();
     }
 
-    public void addError( ArtifactBasicMetadata key, Exception error )
+    public void addError( ArtifactMetadata key, Exception error )
     {
         if ( _exceptions == null )
-            _exceptions = new HashMap<ArtifactBasicMetadata, Exception>( 8 );
+            _exceptions = new HashMap<ArtifactMetadata, Exception>( 8 );
 
         _exceptions.put( key, error );
     }
 
-    public void addError( Map<ArtifactBasicMetadata, Exception> error )
+    public void addError( Map<ArtifactMetadata, Exception> error )
     {
         if ( _exceptions == null )
-            _exceptions = new HashMap<ArtifactBasicMetadata, Exception>( 8 );
+            _exceptions = new HashMap<ArtifactMetadata, Exception>( 8 );
 
         _exceptions.putAll( error );
     }
@@ -73,13 +73,13 @@
             return;
 
         if ( _exceptions == null )
-            _exceptions = new HashMap<ArtifactBasicMetadata, Exception>( 8 );
-        
-        for( ArtifactBasicMetadata bmd : res.getExceptions().keySet() )
-           _exceptions.put( bmd, res.getError( bmd ) );
+            _exceptions = new HashMap<ArtifactMetadata, Exception>( 8 );
+
+        for ( ArtifactMetadata bmd : res.getExceptions().keySet() )
+            _exceptions.put( bmd, res.getError( bmd ) );
     }
 
-    public Exception getError( ArtifactBasicMetadata key )
+    public Exception getError( ArtifactMetadata key )
     {
         if ( _exceptions == null )
             return null;
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepository.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepository.java
index 862d467..1ae282d 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepository.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepository.java
@@ -83,14 +83,15 @@
 
         this.type = type;
     }
+
     // ---------------------------------------------------------------------------
     public static String hashId( String id )
     {
         try
         {
-            if( id == null || (id.indexOf('/') == -1 && id.indexOf('\\') == -1) )
+            if ( id == null || ( id.indexOf( '/' ) == -1 && id.indexOf( '\\' ) == -1 ) )
                 return id;
-            
+
             MessageDigest digest = MessageDigest.getInstance( "SHA-1" );
 
             digest.update( id.getBytes() );
@@ -124,7 +125,7 @@
     // ---------------------------------------------------------------------------
     public QualityRange getRepositoryQualityRange()
     {
-        return repositoryQualityRange;
+        return repositoryQualityRange == null ? QualityRange.ALL : repositoryQualityRange;
     }
 
     // ---------------------------------------------------------------------------
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepositoryWriter.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepositoryWriter.java
index 89cb3fd..1f693da 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepositoryWriter.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/AbstractRepositoryWriter.java
@@ -18,32 +18,30 @@
  */
 package org.apache.maven.mercury.repository.api;
 
-
 /**
  * helper class for writing repository writers
- *
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class AbstractRepositoryWriter
-extends Thread
+    extends Thread
 {
-  
-  protected RepositoryMetadataCache _mdCache;
-  
-  public void setMetadataCache( RepositoryMetadataCache mdCache )
-  {
-    this._mdCache = mdCache;
-  }
-  
-  public RepositoryMetadataCache getMetadataCache()
-  {
-    return _mdCache;
-  }
-  
-  public boolean hasMetadataCache()
-  {
-    return _mdCache != null;
-  }
+
+    protected RepositoryMetadataCache _mdCache;
+
+    public void setMetadataCache( RepositoryMetadataCache mdCache )
+    {
+        this._mdCache = mdCache;
+    }
+
+    public RepositoryMetadataCache getMetadataCache()
+    {
+        return _mdCache;
+    }
+
+    public boolean hasMetadataCache()
+    {
+        return _mdCache != null;
+    }
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/ArtifactBasicResults.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/ArtifactBasicResults.java
deleted file mode 100644
index 4427b7f..0000000
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/ArtifactBasicResults.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.maven.mercury.repository.api;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
-
-/**
- *
- * @author Oleg Gusakov
- * @version $Id$
- *
- */
-public class ArtifactBasicResults
-extends AbstractRepOpResult
-{
-  Map< ArtifactBasicMetadata, List<ArtifactBasicMetadata>> _result = new HashMap<ArtifactBasicMetadata, List<ArtifactBasicMetadata>>(8);
-
-  /**
-   * first result is ready 
-   */
-  public ArtifactBasicResults( ArtifactBasicMetadata query, List<ArtifactBasicMetadata> result )
-  {
-    this._result.put( query, result );
-  }
-  
-  /**
-   * optimization opportunity
-   * 
-   * @param size
-   */
-  public ArtifactBasicResults( int size )
-  {
-  }
-
-  private ArtifactBasicResults()
-  {
-  }
-
-  public static ArtifactBasicResults add( final ArtifactBasicResults res, final ArtifactBasicMetadata key, final Exception err )
-  {
-    ArtifactBasicResults ret = res;
-    if( res == null )
-      ret = new ArtifactBasicResults();
-    
-    ret.addError( key, err );
-    
-    return ret;
-  }
-
-  public static ArtifactBasicResults add( final ArtifactBasicResults res, final ArtifactBasicMetadata key, final List<ArtifactBasicMetadata> result )
-  {
-    ArtifactBasicResults ret = res;
-    if( res == null )
-      ret = new ArtifactBasicResults();
-    
-    ret.add( key, result );
-    
-    return ret;
-  }
-
-  public static ArtifactBasicResults add( final ArtifactBasicResults res, final ArtifactBasicMetadata key, final ArtifactBasicMetadata result )
-  {
-    ArtifactBasicResults ret = res;
-    if( res == null )
-      ret = new ArtifactBasicResults();
-    
-    ret.add( key, result );
-    
-    return ret;
-  }
-  
-  private List<ArtifactBasicMetadata> getOrCreate( ArtifactBasicMetadata query )
-  {
-    List<ArtifactBasicMetadata> res = _result.get( query );
-    if( res == null )
-    {
-      res = new ArrayList<ArtifactBasicMetadata>(8);
-      _result.put( query, res );
-    }
-    return res;
-  }
-  
-  /**
-   * add results if they are not there yet
-   * 
-   * @param query
-   * @param result
-   */
-  public void add( ArtifactBasicMetadata query, List<ArtifactBasicMetadata> result )
-  {
-    List<ArtifactBasicMetadata> res = getOrCreate( query );
-    for( ArtifactBasicMetadata r : result )
-    {
-      if( res.contains( r ) )
-        continue;
-
-      res.add( r );
-    }
-  }
-  
-  public void add( ArtifactBasicMetadata query, ArtifactBasicMetadata result )
-  {
-    List<ArtifactBasicMetadata> res = getOrCreate( query );
-    res.add( result );
-  }
-
-  public Map< ArtifactBasicMetadata, List<ArtifactBasicMetadata>> getResults()
-  {
-    return _result;
-  }
-
-  public List<ArtifactBasicMetadata> getResult( ArtifactBasicMetadata query )
-  {
-    return _result.get( query );
-  }
-
-  @Override
-  public boolean hasResults()
-  {
-    return ! _result.isEmpty();
-  }
-
-  @Override
-  public boolean hasResults( ArtifactBasicMetadata key )
-  {
-    return ! _result.isEmpty() && _result.containsKey( key ) && ! _result.get( key ).isEmpty();
-  }
-
-}
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/ArtifactResults.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/ArtifactResults.java
index 99e1ef7..b2a8adc 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/ArtifactResults.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/ArtifactResults.java
@@ -24,72 +24,70 @@
 import java.util.Map;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 
 /**
- *
- *
  * @author Oleg Gusakov
  * @version $Id$
  */
 public class ArtifactResults
-extends AbstractRepOpResult
+    extends AbstractRepOpResult
 {
-  Map< ArtifactBasicMetadata, List<Artifact>> _result = new HashMap<ArtifactBasicMetadata, List<Artifact>>(8);
+    Map<ArtifactMetadata, List<Artifact>> _result = new HashMap<ArtifactMetadata, List<Artifact>>( 8 );
 
-  public ArtifactResults()
-  {
-  }
-  
-  public ArtifactResults( ArtifactBasicMetadata query, List<Artifact> result )
-  {
-    this._result.put( query, result );
-  }
-  
-  public void add( ArtifactBasicMetadata query, Artifact result )
-  {
-    List<Artifact> res = _result.get( query );
-    if( res == null )
+    public ArtifactResults()
     {
-      res = new ArrayList<Artifact>(8);
-      _result.put( query, res );
     }
 
-    res.add( result );
-  }
-  
-  public void addAll( ArtifactBasicMetadata query, List<Artifact> result )
-  {
-    List<Artifact> res = _result.get( query );
-    if( res == null )
+    public ArtifactResults( ArtifactMetadata query, List<Artifact> result )
     {
-      res = new ArrayList<Artifact>(8);
-      _result.put( query, res );
+        this._result.put( query, result );
     }
 
-    res.addAll( result );
-  }
+    public void add( ArtifactMetadata query, Artifact result )
+    {
+        List<Artifact> res = _result.get( query );
+        if ( res == null )
+        {
+            res = new ArrayList<Artifact>( 8 );
+            _result.put( query, res );
+        }
 
-  public Map< ArtifactBasicMetadata, List<Artifact>> getResults()
-  {
-    return _result;
-  }
+        res.add( result );
+    }
 
-  public List<Artifact> getResults( ArtifactBasicMetadata query )
-  {
-    return _result.get( query );
-  }
+    public void addAll( ArtifactMetadata query, List<Artifact> result )
+    {
+        List<Artifact> res = _result.get( query );
+        if ( res == null )
+        {
+            res = new ArrayList<Artifact>( 8 );
+            _result.put( query, res );
+        }
 
-  @Override
-  public boolean hasResults()
-  {
-    return ! _result.isEmpty();
-  }
+        res.addAll( result );
+    }
 
-  @Override
-  public boolean hasResults( ArtifactBasicMetadata key )
-  {
-    return ! _result.isEmpty() && _result.containsKey( key ) && ! _result.get( key ).isEmpty();
-  }
-  
+    public Map<ArtifactMetadata, List<Artifact>> getResults()
+    {
+        return _result;
+    }
+
+    public List<Artifact> getResults( ArtifactMetadata query )
+    {
+        return _result.get( query );
+    }
+
+    @Override
+    public boolean hasResults()
+    {
+        return !_result.isEmpty();
+    }
+
+    @Override
+    public boolean hasResults( ArtifactMetadata key )
+    {
+        return !_result.isEmpty() && _result.containsKey( key ) && !_result.get( key ).isEmpty();
+    }
+
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/LocalRepository.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/LocalRepository.java
index fd21917..13f6f74 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/LocalRepository.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/LocalRepository.java
@@ -2,7 +2,6 @@
 
 import java.io.File;
 
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -25,7 +24,7 @@
 /**
  */
 public interface LocalRepository
-extends Repository
+    extends Repository
 {
     File getDirectory();
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataCacheException.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataCacheException.java
index 38b645b..ec0d4af 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataCacheException.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataCacheException.java
@@ -19,54 +19,47 @@
 package org.apache.maven.mercury.repository.api;
 
 /**
- *
- *
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class MetadataCacheException
-extends Exception
+    extends Exception
 {
 
-  /**
+    /**
    * 
    */
-  public MetadataCacheException()
-  {
-    // TODO Auto-generated constructor stub
-  }
+    public MetadataCacheException()
+    {
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param message
-   */
-  public MetadataCacheException(
-      String message )
-  {
-    super( message );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param message
+     */
+    public MetadataCacheException( String message )
+    {
+        super( message );
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param cause
-   */
-  public MetadataCacheException(
-      Throwable cause )
-  {
-    super( cause );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param cause
+     */
+    public MetadataCacheException( Throwable cause )
+    {
+        super( cause );
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param message
-   * @param cause
-   */
-  public MetadataCacheException(
-      String message,
-      Throwable cause )
-  {
-    super( message, cause );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param message
+     * @param cause
+     */
+    public MetadataCacheException( String message, Throwable cause )
+    {
+        super( message, cause );
+        // TODO Auto-generated constructor stub
+    }
 
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataCorruptionException.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataCorruptionException.java
index 9de376e..8b9908a 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataCorruptionException.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataCorruptionException.java
@@ -19,54 +19,47 @@
 package org.apache.maven.mercury.repository.api;
 
 /**
- *
- *
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class MetadataCorruptionException
     extends Exception
 {
 
-  /**
+    /**
    * 
    */
-  public MetadataCorruptionException()
-  {
-    // TODO Auto-generated constructor stub
-  }
+    public MetadataCorruptionException()
+    {
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param message
-   */
-  public MetadataCorruptionException(
-      String message )
-  {
-    super( message );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param message
+     */
+    public MetadataCorruptionException( String message )
+    {
+        super( message );
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param cause
-   */
-  public MetadataCorruptionException(
-      Throwable cause )
-  {
-    super( cause );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param cause
+     */
+    public MetadataCorruptionException( Throwable cause )
+    {
+        super( cause );
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param message
-   * @param cause
-   */
-  public MetadataCorruptionException(
-      String message,
-      Throwable cause )
-  {
-    super( message, cause );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param message
+     * @param cause
+     */
+    public MetadataCorruptionException( String message, Throwable cause )
+    {
+        super( message, cause );
+        // TODO Auto-generated constructor stub
+    }
 
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataResults.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataResults.java
new file mode 100644
index 0000000..d1caa0b
--- /dev/null
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/MetadataResults.java
@@ -0,0 +1,151 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.maven.mercury.repository.api;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
+
+/**
+ * @author Oleg Gusakov
+ * @version $Id$
+ */
+public class MetadataResults
+    extends AbstractRepOpResult
+{
+    Map<ArtifactMetadata, List<ArtifactMetadata>> _result = new HashMap<ArtifactMetadata, List<ArtifactMetadata>>( 8 );
+
+    /**
+     * first result is ready
+     */
+    public MetadataResults( ArtifactMetadata query, List<ArtifactMetadata> result )
+    {
+        this._result.put( query, result );
+    }
+
+    /**
+     * optimization opportunity
+     * 
+     * @param size
+     */
+    public MetadataResults( int size )
+    {
+    }
+
+    private MetadataResults()
+    {
+    }
+
+    public static MetadataResults add( final MetadataResults res, final ArtifactMetadata key,
+                                            final Exception err )
+    {
+        MetadataResults ret = res;
+        if ( res == null )
+            ret = new MetadataResults();
+
+        ret.addError( key, err );
+
+        return ret;
+    }
+
+    public static MetadataResults add( final MetadataResults res, final ArtifactMetadata key,
+                                            final List<ArtifactMetadata> result )
+    {
+        MetadataResults ret = res;
+        if ( res == null )
+            ret = new MetadataResults();
+
+        ret.add( key, result );
+
+        return ret;
+    }
+
+    public static MetadataResults add( final MetadataResults res, final ArtifactMetadata key,
+                                            final ArtifactMetadata result )
+    {
+        MetadataResults ret = res;
+        if ( res == null )
+            ret = new MetadataResults();
+
+        ret.add( key, result );
+
+        return ret;
+    }
+
+    private List<ArtifactMetadata> getOrCreate( ArtifactMetadata query )
+    {
+        List<ArtifactMetadata> res = _result.get( query );
+        if ( res == null )
+        {
+            res = new ArrayList<ArtifactMetadata>( 8 );
+            _result.put( query, res );
+        }
+        return res;
+    }
+
+    /**
+     * add results if they are not there yet
+     * 
+     * @param query
+     * @param result
+     */
+    public void add( ArtifactMetadata query, List<ArtifactMetadata> result )
+    {
+        List<ArtifactMetadata> res = getOrCreate( query );
+        for ( ArtifactMetadata r : result )
+        {
+            if ( res.contains( r ) )
+                continue;
+
+            res.add( r );
+        }
+    }
+
+    public void add( ArtifactMetadata query, ArtifactMetadata result )
+    {
+        List<ArtifactMetadata> res = getOrCreate( query );
+        res.add( result );
+    }
+
+    public Map<ArtifactMetadata, List<ArtifactMetadata>> getResults()
+    {
+        return _result;
+    }
+
+    public List<ArtifactMetadata> getResult( ArtifactMetadata query )
+    {
+        return _result.get( query );
+    }
+
+    @Override
+    public boolean hasResults()
+    {
+        return !_result.isEmpty();
+    }
+
+    @Override
+    public boolean hasResults( ArtifactMetadata key )
+    {
+        return !_result.isEmpty() && _result.containsKey( key ) && !_result.get( key ).isEmpty();
+    }
+
+}
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/NonExistentProtocolException.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/NonExistentProtocolException.java
index 677e58b..dff051c 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/NonExistentProtocolException.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/NonExistentProtocolException.java
@@ -22,31 +22,27 @@
     extends RepositoryException
 {
 
-  public NonExistentProtocolException()
-  {
-    // TODO Auto-generated constructor stub
-  }
+    public NonExistentProtocolException()
+    {
+        // TODO Auto-generated constructor stub
+    }
 
-  public NonExistentProtocolException(
-      String message )
-  {
-    super( message );
-    // TODO Auto-generated constructor stub
-  }
+    public NonExistentProtocolException( String message )
+    {
+        super( message );
+        // TODO Auto-generated constructor stub
+    }
 
-  public NonExistentProtocolException(
-      Throwable cause )
-  {
-    super( cause );
-    // TODO Auto-generated constructor stub
-  }
+    public NonExistentProtocolException( Throwable cause )
+    {
+        super( cause );
+        // TODO Auto-generated constructor stub
+    }
 
-  public NonExistentProtocolException(
-      String message,
-      Throwable cause )
-  {
-    super( message, cause );
-    // TODO Auto-generated constructor stub
-  }
+    public NonExistentProtocolException( String message, Throwable cause )
+    {
+        super( message, cause );
+        // TODO Auto-generated constructor stub
+    }
 
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RemoteRepository.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RemoteRepository.java
index 59f560a..8949b99 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RemoteRepository.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RemoteRepository.java
@@ -2,7 +2,6 @@
 
 import org.apache.maven.mercury.transport.api.Server;
 
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -25,13 +24,13 @@
 /**
  */
 public interface RemoteRepository
-extends Repository
+    extends Repository
 {
-  /**
-   *  this is the Server with many useful fields to describe the home of this remote repo
-   */
+    /**
+     * this is the Server with many useful fields to describe the home of this remote repo
+     */
     Server getServer();
-    
+
     /**
      * get the update policy configured for this remote repository
      * 
@@ -41,7 +40,6 @@
 
     /**
      * set the update policy configured for this remote repository
-     * 
      */
     void setUpdatePolicy( RepositoryUpdatePolicy updatePolicy );
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/Repository.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/Repository.java
index 3fd0ead..bfb76d9 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/Repository.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/Repository.java
@@ -5,7 +5,6 @@
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.transport.api.Server;
 
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -29,68 +28,72 @@
  */
 public interface Repository
 {
-  String getId();
-  
+    String getId();
 
-  /**
-   * repository type - m2, nexus, ivy, p2 - to name a few. It defines the RepositoryReader/Writer 
-   * that will be searched for in the registry.
-   */
-  public String getType();
+    /**
+     * repository type - m2, nexus, ivy, p2 - to name a few. It defines the RepositoryReader/Writer that will be
+     * searched for in the registry.
+     */
+    public String getType();
 
-  /**
-   * Indicates whether this is local Repository. This flag defines the necessity to download
-   * the artifact, if it was cleared by the conflict resolver but not read from a localRepo.
-   */
-  public boolean isLocal();
+    /**
+     * Indicates whether this is local Repository. This flag defines the necessity to download the artifact, if it was
+     * cleared by the conflict resolver but not read from a localRepo.
+     */
+    public boolean isLocal();
 
-  /**
-   * Indicates whether it's possible to read from this Repository. 
-   */
-  public boolean isReadable();
+    /**
+     * Indicates whether it's possible to read from this Repository.
+     */
+    public boolean isReadable();
 
-  /**
-   * Indicates whether it's possible to write to this Repository. Good example is the flat repo, which is used to
-   * only collect dependencies for some 3rd party reasons, but not read them.
-   * 
-   * If there are multiple localRepo's and Artifact needs to be downloaded - it will be "written" to all 
-   * "local" repositories that are writeable.
-   */
-  public boolean isWriteable();
+    /**
+     * Indicates whether it's possible to write to this Repository. Good example is the flat repo, which is used to only
+     * collect dependencies for some 3rd party reasons, but not read them. If there are multiple localRepo's and
+     * Artifact needs to be downloaded - it will be "written" to all "local" repositories that are writeable.
+     */
+    public boolean isWriteable();
 
-  /**
-   * Indicates whether this repository contains releases
-   */
-  public boolean isReleases();
+    /**
+     * Indicates whether this repository contains releases
+     */
+    public boolean isReleases();
 
-  /**
-   * Indicates whether this repository contains snapshots
-   */
-  public boolean isSnapshots();
+    /**
+     * Indicates whether this repository contains snapshots
+     */
+    public boolean isSnapshots();
 
-  /**
-   * reserved
-   */
-  public boolean isAcceptedQuality( Quality quality );
-  
-  /**
-   * defines how VersionRnage treats upper boundary - which Artifacts should be treated as belonging 
-   * to the vicinity - http://docs.codehaus.org/x/twDPBQ  
-   * 
-   * @return
-   * @throws NonExistentProtocolException if protocol not supported
-   */
-  public QualityRange getVersionRangeQualityRange();
-  
+    /**
+     * indicates if the supplied code quality is served by this repository
+     */
+    public boolean isAcceptedQuality( Quality quality );
+
+    /**
+     * defines the code quality range for this repository
+     */
+    public QualityRange getRepositoryQualityRange();
+    void setRepositoryQualityRange( QualityRange qualityRange );
+
+    /**
+     * defines how VersionRnage treats upper boundary - which Artifacts should be treated as belonging to the vicinity -
+     * http://docs.codehaus.org/x/twDPBQ
+     * 
+     * note: don't mix this with repository quality range - this one is for version range calculations only!
+     * 
+     */
+    public QualityRange getVersionRangeQualityRange();
+    public void setVersionRangeQualityRange( QualityRange qualityRange );
+    
     /**
      * get default reader, if any
      * 
      * @return default reader or null, if none exists
-     * @throws RepositoryException 
+     * @throws RepositoryException
      */
     RepositoryReader getReader()
-    throws RepositoryException;
-    
+        throws RepositoryException;
+
     /**
      * get protocol specific reader, if any
      * 
@@ -99,54 +102,51 @@
      * @throws NonExistentProtocolException if protocol not supported
      */
     RepositoryReader getReader( String protocol )
-    throws RepositoryException;
+        throws RepositoryException;
 
     /**
      * get default writer, if any
      * 
      * @return default writer or null, if none exists
-     * @throws RepositoryException 
+     * @throws RepositoryException
      */
     RepositoryWriter getWriter()
-    throws RepositoryException;
-    
+        throws RepositoryException;
+
     /**
-     * 
      * @param protocol
      * @return writer instance for the specified protocol
      * @throws NonExistentProtocolException if protocol not supported
+     * @throws RepositoryException 
      */
     RepositoryWriter getWriter( String protocol )
-    throws NonExistentProtocolException;
-    
+        throws NonExistentProtocolException, RepositoryException;
+
     /**
      * server where this repo resides. For local repo - folder as URL and stream verifiers are important.
      * 
      * @return server
      */
     boolean hasServer();
+
     Server getServer();
-    
+
     /**
      * DependencyProcessor used by this repo resides
      * 
      * @return server
      */
     boolean hasDependencyProcessor();
+
     DependencyProcessor getDependencyProcessor();
+
     void setDependencyProcessor( DependencyProcessor dependencyProcessor );
 
     /**
-     * maven-metadata.xml file name for this repository. This is internal to repository and should never be used 
-     * outside of readers and wrters
+     * maven-metadata.xml file name for this repository. This is internal to repository and should never be used outside
+     * of readers and wrters
      * 
      * @return server
      */
     String getMetadataName();
-
-
-    /**
-     * @param releasesOnly
-     */
-    void setRepositoryQualityRange( QualityRange releasesOnly );
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryCallback.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryCallback.java
index 6ff5405..89e4cc5 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryCallback.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryCallback.java
@@ -18,17 +18,14 @@
  */
 package org.apache.maven.mercury.repository.api;
 
-
 /**
- * This is a generic repository event callback. Used by all repository operations
- * to signal end of operation and represents a list of exceptions plus a list
- * of ArtifactBasicMetadata derivatives
- *
+ * This is a generic repository event callback. Used by all repository operations to signal end of operation and
+ * represents a list of exceptions plus a list of ArtifactBasicMetadata derivatives
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public interface RepositoryCallback
 {
-  public void done( AbstractRepOpResult results );
+    public void done( AbstractRepOpResult results );
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryException.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryException.java
index b28c801..48f20cb 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryException.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryException.java
@@ -19,59 +19,52 @@
 package org.apache.maven.mercury.repository.api;
 
 /**
- *
- *
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class RepositoryException
     extends Exception
 {
 
-  /**
+    /**
    * 
    */
-  private static final long serialVersionUID = -1193169088723411771L;
+    private static final long serialVersionUID = -1193169088723411771L;
 
-  /**
+    /**
    * 
    */
-  public RepositoryException()
-  {
-    // TODO Auto-generated constructor stub
-  }
+    public RepositoryException()
+    {
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param message
-   */
-  public RepositoryException(
-      String message )
-  {
-    super( message );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param message
+     */
+    public RepositoryException( String message )
+    {
+        super( message );
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param cause
-   */
-  public RepositoryException(
-      Throwable cause )
-  {
-    super( cause );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param cause
+     */
+    public RepositoryException( Throwable cause )
+    {
+        super( cause );
+        // TODO Auto-generated constructor stub
+    }
 
-  /**
-   * @param message
-   * @param cause
-   */
-  public RepositoryException(
-      String message,
-      Throwable cause )
-  {
-    super( message, cause );
-    // TODO Auto-generated constructor stub
-  }
+    /**
+     * @param message
+     * @param cause
+     */
+    public RepositoryException( String message, Throwable cause )
+    {
+        super( message, cause );
+        // TODO Auto-generated constructor stub
+    }
 
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryGAMetadata.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryGAMetadata.java
index 15a7ee8..86a1204 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryGAMetadata.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryGAMetadata.java
@@ -15,125 +15,123 @@
 import org.codehaus.plexus.lang.Language;
 
 /**
- * This is a data object to carry GA level repository 
- * metadata, namely - a list of versions and last check timestamp
- *
+ * This is a data object to carry GA level repository metadata, namely - a list of versions and last check timestamp
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class RepositoryGAMetadata
 {
-  private static final Language LANG = new DefaultLanguage( RepositoryGAVMetadata.class );
-  
-  protected ArtifactCoordinates ga;
+    private static final Language LANG = new DefaultLanguage( RepositoryGAVMetadata.class );
 
-  /** a list of last discovered versions, ordered ascending */
-  protected TreeSet<String> versions = new TreeSet<String>( new VersionComparator() );
-  
-  /** GMT timestamp of the last metadata check */
-  protected long lastCheck;
-  
-  /** is set true by cache implementation when determined that it's time to refresh */
-  protected transient boolean expired = false;
+    protected ArtifactCoordinates ga;
 
-  protected RepositoryGAMetadata()
-  {
-  }
+    /** a list of last discovered versions, ordered ascending */
+    protected TreeSet<String> versions = new TreeSet<String>( new VersionComparator() );
 
-  /**
-   * @param versions
-   * @param lastCheck
-   */
-  public RepositoryGAMetadata( ArtifactCoordinates ga, Collection<String> versions )
-  {
-    this.ga = ga;
-    
-    if( ! Util.isEmpty( versions ) )
-      this.versions.addAll( versions );
-    
-    this.lastCheck = TimeUtil.getUTCTimestampAsLong();
-  }
+    /** GMT timestamp of the last metadata check */
+    protected long lastCheck;
 
-  /**
-   * construct from maven 2.x maven-metadata.xml object
-   * 
-   * @param md
-   * @throws MetadataException 
-   */
-  public RepositoryGAMetadata( Metadata md )
-  throws MetadataException
-  {
-    if( md == null )
-      throw new IllegalArgumentException( LANG.getMessage( "empty.md" ) );
-    
-    this.ga = new ArtifactCoordinates( md.getGroupId(), md.getArtifactId(), md.getVersion() );
+    /** is set true by cache implementation when determined that it's time to refresh */
+    protected transient boolean expired = false;
 
-    List<String> vers = null;
-    
-    if( md.getVersioning() != null )
+    protected RepositoryGAMetadata()
     {
-      vers = md.getVersioning().getVersions();
-      this.versions.addAll( vers );
-    }
-    
-    this.lastCheck = TimeUtil.getUTCTimestampAsLong();
-  }
-  
-  /**
-   * copy constructor
-   * 
-   * @param md
-   * @throws MetadataException 
-   */
-  public RepositoryGAMetadata( RepositoryGAMetadata md )
-  throws MetadataException
-  {    
-    this.ga = md.getGA();
-
-    if( !Util.isEmpty( md.getVersions() ) )
-    {
-      this.versions.addAll( md.getVersions() );
     }
 
-    this.lastCheck = TimeUtil.getUTCTimestampAsLong();
-  }
+    /**
+     * @param versions
+     * @param lastCheck
+     */
+    public RepositoryGAMetadata( ArtifactCoordinates ga, Collection<String> versions )
+    {
+        this.ga = ga;
 
-  public TreeSet<String> getVersions()
-  {
-    return versions;
-  }
+        if ( !Util.isEmpty( versions ) )
+            this.versions.addAll( versions );
 
-  public long getLastCheckTs()
-  {
-    return lastCheck;
-  }
-  
-  public long getLastCheckMillis()
-  throws ParseException
-  {
-    return TimeUtil.toMillis(  lastCheck );
-  }
-  
-  public void update( Collection<String> versions )
-  {
-    this.versions.addAll( versions );
-    this.lastCheck = TimeUtil.getUTCTimestampAsLong();
-  }
-  
-  public ArtifactCoordinates getGA()
-  {
-    return ga;
-  }
+        this.lastCheck = TimeUtil.getUTCTimestampAsLong();
+    }
 
-  public boolean isExpired()
-  {
-    return expired;
-  }
+    /**
+     * construct from maven 2.x maven-metadata.xml object
+     * 
+     * @param md
+     * @throws MetadataException
+     */
+    public RepositoryGAMetadata( Metadata md )
+        throws MetadataException
+    {
+        if ( md == null )
+            throw new IllegalArgumentException( LANG.getMessage( "empty.md" ) );
 
-  public void setExpired( boolean expired )
-  {
-    this.expired = expired;
-  }
+        this.ga = new ArtifactCoordinates( md.getGroupId(), md.getArtifactId(), md.getVersion() );
+
+        List<String> vers = null;
+
+        if ( md.getVersioning() != null )
+        {
+            vers = md.getVersioning().getVersions();
+            this.versions.addAll( vers );
+        }
+
+        this.lastCheck = TimeUtil.getUTCTimestampAsLong();
+    }
+
+    /**
+     * copy constructor
+     * 
+     * @param md
+     * @throws MetadataException
+     */
+    public RepositoryGAMetadata( RepositoryGAMetadata md )
+        throws MetadataException
+    {
+        this.ga = md.getGA();
+
+        if ( !Util.isEmpty( md.getVersions() ) )
+        {
+            this.versions.addAll( md.getVersions() );
+        }
+
+        this.lastCheck = TimeUtil.getUTCTimestampAsLong();
+    }
+
+    public TreeSet<String> getVersions()
+    {
+        return versions;
+    }
+
+    public long getLastCheckTs()
+    {
+        return lastCheck;
+    }
+
+    public long getLastCheckMillis()
+        throws ParseException
+    {
+        return TimeUtil.toMillis( lastCheck );
+    }
+
+    public void update( Collection<String> versions )
+    {
+        this.versions.addAll( versions );
+        this.lastCheck = TimeUtil.getUTCTimestampAsLong();
+    }
+
+    public ArtifactCoordinates getGA()
+    {
+        return ga;
+    }
+
+    public boolean isExpired()
+    {
+        return expired;
+    }
+
+    public void setExpired( boolean expired )
+    {
+        this.expired = expired;
+    }
 
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryGAVMetadata.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryGAVMetadata.java
index 85c5fe0..fefc739 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryGAVMetadata.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryGAVMetadata.java
@@ -35,151 +35,149 @@
 import org.codehaus.plexus.lang.Language;
 
 /**
- * This is a data object to carry GA level repository 
- * metadata, namely - a list of versions and last check timestamp
- *
+ * This is a data object to carry GA level repository metadata, namely - a list of versions and last check timestamp
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class RepositoryGAVMetadata
 {
-  private static final Language LANG = new DefaultLanguage( RepositoryGAVMetadata.class );
-  
-  protected ArtifactCoordinates gav;
-  
-  /** a list of last discovered snapshots, ordered descending */
-  protected TreeSet<String> snapshots = new TreeSet<String>( new VersionComparator() );
+    private static final Language LANG = new DefaultLanguage( RepositoryGAVMetadata.class );
 
-  /** a list of last discovered versions, ordered ascending */
-  protected Collection<String> classifiers;
-  
-  /** GMT timestamp of the last metadata check */
-  protected long lastCheck;
-  
-  /** is set true by cache implementation when determined that it's time to refresh */
-  protected transient boolean expired = false;
-  
-  protected RepositoryGAVMetadata()
-  {
-  }
+    protected ArtifactCoordinates gav;
 
-  /**
-   * construct from maven 2.x maven-metadata.xml object
-   * 
-   * @param md
-   * @throws MetadataException 
-   */
-  public RepositoryGAVMetadata( Metadata md )
-  throws MetadataException
-  {
-    if( md == null )
-      throw new IllegalArgumentException( LANG.getMessage( "empty.mdbytes" ) );
-    
-    this.gav = new ArtifactCoordinates( md.getGroupId(), md.getArtifactId(), md.getVersion() );
+    /** a list of last discovered snapshots, ordered descending */
+    protected TreeSet<String> snapshots = new TreeSet<String>( new VersionComparator() );
 
-    List<String> versions = null;
-    
-    if( md.getVersioning() != null )
-      versions = md.getVersioning().getVersions(); 
-      
-    if( !Util.isEmpty( versions ) )
-        this.snapshots.addAll( versions );
+    /** a list of last discovered versions, ordered ascending */
+    protected Collection<String> classifiers;
 
-    String version = md.getVersion();
+    /** GMT timestamp of the last metadata check */
+    protected long lastCheck;
 
-    if( version != null && version.endsWith( Artifact.SNAPSHOT_VERSION ) )
+    /** is set true by cache implementation when determined that it's time to refresh */
+    protected transient boolean expired = false;
+
+    protected RepositoryGAVMetadata()
     {
-        Snapshot sn = md.getVersioning().getSnapshot();
-        
-        if( sn != null && !Util.isEmpty( sn.getTimestamp() ) &&  !Util.isEmpty( sn.getBuildNumber() ) )
-        {
-            String ts = version.replaceAll( Artifact.SNAPSHOT_VERSION, sn.getTimestamp()+'-'+sn.getBuildNumber() );
-            snapshots.add( ts );
-        }
     }
 
-    this.lastCheck = TimeUtil.getUTCTimestampAsLong();
-  }
+    /**
+     * construct from maven 2.x maven-metadata.xml object
+     * 
+     * @param md
+     * @throws MetadataException
+     */
+    public RepositoryGAVMetadata( Metadata md )
+        throws MetadataException
+    {
+        if ( md == null )
+            throw new IllegalArgumentException( LANG.getMessage( "empty.mdbytes" ) );
 
-  /**
-   * copy constructor
-   * 
-   * @param md
-   * @throws MetadataException 
-   */
-  public RepositoryGAVMetadata( RepositoryGAVMetadata md )
-  throws MetadataException
-  {
-    this.gav = md.getGAV();
+        this.gav = new ArtifactCoordinates( md.getGroupId(), md.getArtifactId(), md.getVersion() );
 
-    if( ! Util.isEmpty( md.getSnapshots() ) )
-      this.snapshots.addAll( md.getSnapshots() );
-    
-    this.lastCheck = TimeUtil.getUTCTimestampAsLong();
-  }
-  
-  public TreeSet<String> getSnapshots()
-  {
-    return snapshots;
-  }
+        List<String> versions = null;
 
-  public Collection<String> getClassifiers()
-  {
-    return classifiers;
-  }
+        if ( md.getVersioning() != null )
+            versions = md.getVersioning().getVersions();
 
-  /**
-   * find the most recent snapshot timestamp
-   * 
-   * @return
-   */
-  public String getSnapshot()
-  {
-    return snapshots.last();
-  }
+        if ( !Util.isEmpty( versions ) )
+            this.snapshots.addAll( versions );
 
-  public long getLastCheck()
-  {
-    return lastCheck;
-  }
-  
-  public long getLastCheckMillis()
-  throws ParseException
-  {
-    return TimeUtil.toMillis(  lastCheck );
-  }
+        String version = md.getVersion();
 
-  public void updateSnapshots( Collection<String> snapshots )
-  {
-    this.snapshots.clear();
+        if ( version != null && version.endsWith( Artifact.SNAPSHOT_VERSION ) )
+        {
+            Snapshot sn = md.getVersioning().getSnapshot();
 
-    if( !Util.isEmpty( snapshots ) )
-      this.snapshots.addAll( snapshots );
-    
-    this.lastCheck = TimeUtil.getUTCTimestampAsLong();
-  }
+            if ( sn != null && !Util.isEmpty( sn.getTimestamp() ) && !Util.isEmpty( sn.getBuildNumber() ) )
+            {
+                String ts =
+                    version.replaceAll( Artifact.SNAPSHOT_VERSION, sn.getTimestamp() + '-' + sn.getBuildNumber() );
+                snapshots.add( ts );
+            }
+        }
 
-  public void updateClassifiers( Collection<String> classifiers )
-  {
-    this.classifiers = classifiers;
-    this.lastCheck = TimeUtil.getUTCTimestampAsLong();
-  }
-  
-  
-  public ArtifactCoordinates getGAV()
-  {
-    return gav;
-  }
+        this.lastCheck = TimeUtil.getUTCTimestampAsLong();
+    }
 
-  public boolean isExpired()
-  {
-    return expired;
-  }
+    /**
+     * copy constructor
+     * 
+     * @param md
+     * @throws MetadataException
+     */
+    public RepositoryGAVMetadata( RepositoryGAVMetadata md )
+        throws MetadataException
+    {
+        this.gav = md.getGAV();
 
-  public void setExpired( boolean expired )
-  {
-    this.expired = expired;
-  }
+        if ( !Util.isEmpty( md.getSnapshots() ) )
+            this.snapshots.addAll( md.getSnapshots() );
+
+        this.lastCheck = TimeUtil.getUTCTimestampAsLong();
+    }
+
+    public TreeSet<String> getSnapshots()
+    {
+        return snapshots;
+    }
+
+    public Collection<String> getClassifiers()
+    {
+        return classifiers;
+    }
+
+    /**
+     * find the most recent snapshot timestamp
+     * 
+     * @return
+     */
+    public String getSnapshot()
+    {
+        return snapshots.last();
+    }
+
+    public long getLastCheck()
+    {
+        return lastCheck;
+    }
+
+    public long getLastCheckMillis()
+        throws ParseException
+    {
+        return TimeUtil.toMillis( lastCheck );
+    }
+
+    public void updateSnapshots( Collection<String> snapshots )
+    {
+        this.snapshots.clear();
+
+        if ( !Util.isEmpty( snapshots ) )
+            this.snapshots.addAll( snapshots );
+
+        this.lastCheck = TimeUtil.getUTCTimestampAsLong();
+    }
+
+    public void updateClassifiers( Collection<String> classifiers )
+    {
+        this.classifiers = classifiers;
+        this.lastCheck = TimeUtil.getUTCTimestampAsLong();
+    }
+
+    public ArtifactCoordinates getGAV()
+    {
+        return gav;
+    }
+
+    public boolean isExpired()
+    {
+        return expired;
+    }
+
+    public void setExpired( boolean expired )
+    {
+        this.expired = expired;
+    }
 
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryManager.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryManager.java
index a3593d2..1c18113 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryManager.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryManager.java
@@ -25,33 +25,31 @@
 import org.apache.maven.mercury.artifact.Quality;
 
 /**
- *
- *
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class RepositoryManager
 {
-  protected static transient List<Repository> _repoList = Collections.synchronizedList( new ArrayList<Repository>(8) );
-  
-  void setRepositories()
-  {
-    
-  }
-  
-  List<Repository> getRepositories()
-  {
-    return _repoList;
-  }
-  
-  LocalRepository findLocal( Quality aq )
-  {
-    for( Repository r : _repoList )
+    protected static transient List<Repository> _repoList =
+        Collections.synchronizedList( new ArrayList<Repository>( 8 ) );
+
+    void setRepositories()
     {
-      if( r.isLocal() && r.isWriteable() && r.isAcceptedQuality( aq ) )
-        return (LocalRepository)r;
+
     }
-    return null;
-  }
+
+    List<Repository> getRepositories()
+    {
+        return _repoList;
+    }
+
+    LocalRepository findLocal( Quality aq )
+    {
+        for ( Repository r : _repoList )
+        {
+            if ( r.isLocal() && r.isWriteable() && r.isAcceptedQuality( aq ) )
+                return (LocalRepository) r;
+        }
+        return null;
+    }
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryMetadataCache.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryMetadataCache.java
index 46da67f..8f91a6d 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryMetadataCache.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryMetadataCache.java
@@ -18,86 +18,94 @@
  */
 package org.apache.maven.mercury.repository.api;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactCoordinates;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.event.EventGenerator;
 
 /**
- * this object abstracts the existence of multiple repositories and repository
- * policies. Given a metadata request, implementor of this interface will
- * either return a local copy if one exists, or will go out and read from a remote repo
- * if either local copy does not exist or remote repository policy allows a read 
- *
+ * this object abstracts the existence of multiple repositories and repository policies. Given a metadata request,
+ * implementor of this interface will either return a local copy if one exists, or will go out and read from a remote
+ * repo if either local copy does not exist or remote repository policy allows a read
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public interface RepositoryMetadataCache
-extends EventGenerator
+    extends EventGenerator
 {
-  /**
-   * check if GA level metadata exists in this cache for the given repo. Read from repo, if does not exists
-   * 
-   * @param repoGuid repository GUID
-   * @param up repository update policy 
-   * @param coord bare GA coordinates of the requisted metadata
-   * @return  metadata object or null, if data does not exist or has been expired
-   */
-  public RepositoryGAMetadata findGA( String repoGuid, RepositoryUpdatePolicy up, ArtifactCoordinates coord )
-  throws MetadataCorruptionException;
-  
-  /**
-   * check if GAV level metadata exists in this cache for the given repo. Read from repo, if does not exists
-   * 
-   * @param repoGuid repository GUID
-   * @param up repository update policy 
-   * @param coord bare GAV coordinates of the requisted metadata
-   * @return 
-   */
-  public RepositoryGAVMetadata findGAV( String repoGuid, RepositoryUpdatePolicy up, ArtifactCoordinates coord )
-  throws MetadataCorruptionException;
+    /**
+     * check if GA level metadata exists in this cache for the given repo. Read from repo, if does not exists
+     * 
+     * @param repoGuid repository GUID
+     * @param up repository update policy
+     * @param coord bare GA coordinates of the requisted metadata
+     * @return metadata object or null, if data does not exist or has been expired
+     */
+    public RepositoryGAMetadata findGA( String repoGuid, RepositoryUpdatePolicy up, ArtifactCoordinates coord )
+        throws MetadataCorruptionException;
 
-  /**
-   * update stored GA metadata with a fresh copy
-   * 
-   * @param repoGuid
-   * @param gam
-   * @throws MetadataCacheException
-   */
-  public void updateGA( String repoGuid, RepositoryGAMetadata gam )
-  throws MetadataCacheException;
+    /**
+     * check if GAV level metadata exists in this cache for the given repo. Read from repo, if does not exists
+     * 
+     * @param repoGuid repository GUID
+     * @param up repository update policy
+     * @param coord bare GAV coordinates of the requisted metadata
+     * @return
+     */
+    public RepositoryGAVMetadata findGAV( String repoGuid, RepositoryUpdatePolicy up, ArtifactCoordinates coord )
+        throws MetadataCorruptionException;
 
-  /**
-   * update stored GA metadata with a fresh copy
-   * 
-   * @param repoGuid
-   * @param gavm fresh metadata
-   * @throws MetadataCacheException
-   */
-  public void updateGAV( String repoGuid, RepositoryGAVMetadata gavm )
-  throws MetadataCacheException;
+    /**
+     * update stored GA metadata with a fresh copy
+     * 
+     * @param repoGuid
+     * @param gam
+     * @throws MetadataCacheException
+     */
+    public void updateGA( String repoGuid, RepositoryGAMetadata gam )
+        throws MetadataCacheException;
 
-  /**
-   * find cached raw data. Raw data is different from metadata in a sense
-   * that it does not expire, so it's either found or not.
-   * This call is crafted for caching POMs and thus ignores classifier
-   * 
-   * @param bmd
-   * @return found bytes or null, if no data was cached for this coordinates before
-   * @throws MetadataCacheException
-   */
-  public byte [] findRaw( ArtifactBasicMetadata bmd )
-  throws MetadataCacheException;
+    /**
+     * update stored GA metadata with a fresh copy
+     * 
+     * @param repoGuid
+     * @param gavm fresh metadata
+     * @throws MetadataCacheException
+     */
+    public void updateGAV( String repoGuid, RepositoryGAVMetadata gavm )
+        throws MetadataCacheException;
 
-  /**
-   * cache raw data. Raw data is different from metadata in a sense
-   * that it does not expire, so it's either found or not
-   * This call is crafted for caching POMs and thus ignores classifier
-   * 
-   * @param bmd
-   * @param rawBytes - bytes to cache
-   * @throws MetadataCacheException
-   */
-  public void saveRaw( ArtifactBasicMetadata bmd, byte [] rawBytes )
-  throws MetadataCacheException;
+    /**
+     * find cached raw data. Raw data is different from metadata in a sense that it does not expire, so it's either
+     * found or not. This call is crafted for caching POMs and thus ignores classifier
+     * 
+     * @param bmd
+     * @return found bytes or null, if no data was cached for this coordinates before
+     * @throws MetadataCacheException
+     */
+    public byte[] findRaw( ArtifactMetadata bmd )
+        throws MetadataCacheException;
+
+    /**
+     * cache raw data. Raw data is different from metadata in a sense that it does not expire, so it's either found or
+     * not This call is crafted for caching POMs and thus ignores classifier
+     * 
+     * @param bmd
+     * @param rawBytes - bytes to cache
+     * @throws MetadataCacheException
+     */
+    public void saveRaw( ArtifactMetadata bmd, byte[] rawBytes )
+    throws MetadataCacheException;
+    
+    /**
+     * clears all session data (in-memory cache). Only on-disk data should remain and it
+     * complies with expiration policies. Session data is different in this regard and once in 
+     * memory - ignores expiration time; this is done for faster access of the same data if
+     * expiration is set to "always" - first time data is read from remote repository, cached in
+     * the session, and all subsequent call use this data.  
+     * 
+     * @throws MetadataCacheException
+     */
+    public void clearSession()
+    throws MetadataCacheException;
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryOperator.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryOperator.java
index 0eaa68e..31b405a 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryOperator.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryOperator.java
@@ -20,15 +20,15 @@
 
 /**
  * parent of all repository accessors - readers and writers
- *
- *
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public interface RepositoryOperator
 {
-  public String [] getProtocols();
-  public boolean canHandle( String protocol );
-  public void close();
+    public String[] getProtocols();
+
+    public boolean canHandle( String protocol );
+
+    public void close();
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryReader.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryReader.java
index fbb8233..4d5e9f6 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryReader.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryReader.java
@@ -20,207 +20,199 @@
 
 import java.util.Collection;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.builder.api.MetadataReader;
 import org.apache.maven.mercury.builder.api.MetadataReaderException;
 
 /**
- * Repository reader API to be implemented by any repo implementation that wishes 
- * to serve artifacts to the build process
- *
- *
+ * Repository reader API to be implemented by any repo implementation that wishes to serve artifacts to the build
+ * process
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public interface RepositoryReader
-extends RepositoryOperator, MetadataReader
+    extends RepositoryOperator, MetadataReader
 {
-  /**
-   * given basic coordinates query - instantiate all available matches as ArtifactBasicMetadata objects. 
-   * <b>Analogous to reading maven-metadata.xml</b> file from GA folder i.e. this transforms
-   * GA[Vrange] -> [GAV1, GAV2, ... GAVn]
-   * 
-   * @param query list of MD coordinate queries to find 
-   * @return map of results - lists of available matches.  
-   * <b>If no results are found, reader should return null<b> If there were exceptions, map element will indicate 
-   * it with hasExceptions() 
-   * @throws RepositoryException
-   */
-  public ArtifactBasicResults readVersions( Collection<ArtifactBasicMetadata> query )
-  throws RepositoryException;
-  
-  /**
-   * given basic coordinates query read dependencies as a GAV list
-   * with dependencies as queries i.e. each dependency at this stage is an ArtifactBasicMetadata
-   * <b>Analogous to reading pom.xml</b> file for given GAV
-   * 
-   * @param query list of MD coordinate queries to read. They are found by previous call to findMetadata 
-   * @return result as a map GAV -> [GAV1, GAV2, ... GAVn]
-   * @throws RepositoryException
-   */
-  public ArtifactBasicResults readDependencies( Collection<ArtifactBasicMetadata> query )
-  throws RepositoryException;
+    /**
+     * given basic coordinates query - instantiate all available matches as ArtifactBasicMetadata objects. <b>Analogous
+     * to reading maven-metadata.xml</b> file from GA folder i.e. this transforms GA[Vrange] -> [GAV1, GAV2, ... GAVn]
+     * 
+     * @param query list of MD coordinate queries to find
+     * @return map of results - lists of available matches. <b>If no results are found, reader should return null<b> If
+     *         there were exceptions, map element will indicate it with hasExceptions()
+     * @throws RepositoryException
+     */
+    public MetadataResults readVersions( Collection<ArtifactMetadata> query )
+        throws RepositoryException;
 
-  /**
-   * Given basic coordinates query read Artifact objects
-   * Analogous to downloading artifact binary  file into local repo for given GAV
-   * 
-   * @param query list of MD coordinate queries to read. 
-   * @return array of results - lists of available matches. Order is the same as in query list. null means not found or worse
-   * @throws RepositoryException
-   */
-  public ArtifactResults readArtifacts( Collection<ArtifactBasicMetadata> query )
-  throws RepositoryException;
+    /**
+     * given basic coordinates query read dependencies as a GAV list with dependencies as queries i.e. each dependency
+     * at this stage is an ArtifactBasicMetadata <b>Analogous to reading pom.xml</b> file for given GAV
+     * 
+     * @param query list of MD coordinate queries to read. They are found by previous call to findMetadata
+     * @return result as a map GAV -> [GAV1, GAV2, ... GAVn]
+     * @throws RepositoryException
+     */
+    public MetadataResults readDependencies( Collection<ArtifactMetadata> query )
+        throws RepositoryException;
 
-  /**
-   * Need if for explanation function - where and how(protocol) this artifact is found.
-   */
-  public Repository getRepository();
+    /**
+     * Given basic coordinates query read Artifact objects Analogous to downloading artifact binary file into local repo
+     * for given GAV
+     * 
+     * @param query list of MD coordinate queries to read.
+     * @return array of results - lists of available matches. Order is the same as in query list. null means not found
+     *         or worse
+     * @throws RepositoryException
+     */
+    public ArtifactResults readArtifacts( Collection<ArtifactMetadata> query )
+        throws RepositoryException;
 
-  /**
-   * Abstracted POM reader. First projectBuilder, then any type of dependency reader
-   */
-  public void setDependencyProcessor( DependencyProcessor mdProcessor );
-  public DependencyProcessor getDependencyProcessor();
+    /**
+     * Need if for explanation function - where and how(protocol) this artifact is found.
+     */
+    public Repository getRepository();
 
-  /**
-   * MetadataReader field. Single repository uses itself, virtual reader injects itself 
-   * to be able to find metadata across repositories
-   */
-  public void setMetadataReader( MetadataReader mdReader );
-  public MetadataReader getMetadataReader();
+    /**
+     * Abstracted POM reader. First projectBuilder, then any type of dependency reader
+     */
+    public void setDependencyProcessor( DependencyProcessor mdProcessor );
 
-  /**
-   * Abstracted metadata cache is used to store/retrieve metadata faster. It usually implements 
-   * repository update policy
-   */
-  public void setMetadataCache( RepositoryMetadataCache mdCache );
-  public RepositoryMetadataCache getMetadataCache();
-  
-  /**
-   * read content pointed by relative path. It will return content bytes
-   * 
-   * @param path - realative resource path in this repository
-   * @return byte [] of the resource content, pointed by the path
-   * @throws MetadataReaderException 
-   */
-  public byte [] readRawData( String path, boolean exempt )
-  throws MetadataReaderException;
+    public DependencyProcessor getDependencyProcessor();
 
-  public byte [] readRawData( String path )
-  throws MetadataReaderException;
-  
-  public static final RepositoryReader NULL_READER = 
-    new RepositoryReader()
+    /**
+     * MetadataReader field. Single repository uses itself, virtual reader injects itself to be able to find metadata
+     * across repositories
+     */
+    public void setMetadataReader( MetadataReader mdReader );
+
+    public MetadataReader getMetadataReader();
+
+    /**
+     * Abstracted metadata cache is used to store/retrieve metadata faster. It usually implements repository update
+     * policy
+     */
+    public void setMetadataCache( RepositoryMetadataCache mdCache );
+
+    public RepositoryMetadataCache getMetadataCache();
+
+    /**
+     * read content pointed by relative path. It will return content bytes
+     * 
+     * @param path - realative resource path in this repository
+     * @return byte [] of the resource content, pointed by the path
+     * @throws MetadataReaderException
+     */
+    public byte[] readRawData( String path, boolean exempt )
+        throws MetadataReaderException;
+
+    public byte[] readRawData( String path )
+        throws MetadataReaderException;
+
+    public static final RepositoryReader NULL_READER = new RepositoryReader()
     {
-      public DependencyProcessor getDependencyProcessor()
-      {
-        return null;
-      }
-      public RepositoryMetadataCache getMetadataCache()
-      {
-        return null;
-      }
+        public DependencyProcessor getDependencyProcessor()
+        {
+            return null;
+        }
 
-      public Repository getRepository()
-      {
-        return null;
-      }
+        public RepositoryMetadataCache getMetadataCache()
+        {
+            return null;
+        }
 
-      public ArtifactResults readArtifacts( Collection<ArtifactBasicMetadata> query )
-      throws RepositoryException
-      {
-        return null;
-      }
+        public Repository getRepository()
+        {
+            return null;
+        }
 
-      public ArtifactBasicResults readDependencies( Collection<ArtifactBasicMetadata> query )
-          throws RepositoryException
-      {
-        return null;
-      }
+        public ArtifactResults readArtifacts( Collection<ArtifactMetadata> query )
+            throws RepositoryException
+        {
+            return null;
+        }
 
-      public byte[] readRawData( String path, boolean exempt )
-      throws MetadataReaderException
-      {
-        return null;
-      }
-      
-      public byte[] readRawData( String path  )
-      throws MetadataReaderException
-      {
-        return null;
-      }
+        public MetadataResults readDependencies( Collection<ArtifactMetadata> query )
+            throws RepositoryException
+        {
+            return null;
+        }
 
-      public ArtifactBasicResults readVersions( Collection<ArtifactBasicMetadata> query )
-          throws RepositoryException
-      {
-        return null;
-      }
+        public byte[] readRawData( String path, boolean exempt )
+            throws MetadataReaderException
+        {
+            return null;
+        }
 
-      public void setDependencyProcessor( DependencyProcessor mdProcessor )
-      {
-      }
+        public byte[] readRawData( String path )
+            throws MetadataReaderException
+        {
+            return null;
+        }
 
-      public void setMetadataCache( RepositoryMetadataCache mdCache )
-      {
-      }
+        public MetadataResults readVersions( Collection<ArtifactMetadata> query )
+            throws RepositoryException
+        {
+            return null;
+        }
 
-      public boolean canHandle( String protocol )
-      {
-        return false;
-      }
+        public void setDependencyProcessor( DependencyProcessor mdProcessor )
+        {
+        }
 
-      public void close()
-      {
-      }
+        public void setMetadataCache( RepositoryMetadataCache mdCache )
+        {
+        }
 
-      public String[] getProtocols()
-      {
-        return null;
-      }
+        public boolean canHandle( String protocol )
+        {
+            return false;
+        }
 
-      public byte[] readMetadata( ArtifactBasicMetadata bmd, boolean exempt  )
-      throws MetadataReaderException
-      {
-        return null;
-      }
+        public void close()
+        {
+        }
 
-      public byte[] readMetadata( ArtifactBasicMetadata bmd  )
-      throws MetadataReaderException
-      {
-        return null;
-      }
+        public String[] getProtocols()
+        {
+            return null;
+        }
 
-      public byte[] readRawData(
-          ArtifactBasicMetadata bmd,
-          String classifier,
-          String type,
-          boolean exempt 
-          )
-          throws MetadataReaderException
-      {
-        return null;
-      }
+        public byte[] readMetadata( ArtifactMetadata bmd, boolean exempt )
+            throws MetadataReaderException
+        {
+            return null;
+        }
 
-      public byte[] readRawData(
-          ArtifactBasicMetadata bmd,
-          String classifier,
-          String type
-          )
-          throws MetadataReaderException
-      {
-        return null;
-      }
-      public MetadataReader getMetadataReader()
-      {
-        return null;
-      }
-      public void setMetadataReader( MetadataReader mdReader )
-      {
-      }
-    
+        public byte[] readMetadata( ArtifactMetadata bmd )
+            throws MetadataReaderException
+        {
+            return null;
+        }
+
+        public byte[] readRawData( ArtifactMetadata bmd, String classifier, String type, boolean exempt )
+            throws MetadataReaderException
+        {
+            return null;
+        }
+
+        public byte[] readRawData( ArtifactMetadata bmd, String classifier, String type )
+            throws MetadataReaderException
+        {
+            return null;
+        }
+
+        public MetadataReader getMetadataReader()
+        {
+            return null;
+        }
+
+        public void setMetadataReader( MetadataReader mdReader )
+        {
+        }
+
     };
 
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryReaderFactory.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryReaderFactory.java
index a19920c..51d4311 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryReaderFactory.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryReaderFactory.java
@@ -22,6 +22,6 @@
 
 public interface RepositoryReaderFactory
 {
-  public RepositoryReader getReader( Repository repo, DependencyProcessor mdProcessor )
-  throws RepositoryException;
+    public RepositoryReader getReader( Repository repo, DependencyProcessor mdProcessor )
+        throws RepositoryException;
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdateIntervalPolicy.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdateIntervalPolicy.java
index ffa834f..0eb0c00 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdateIntervalPolicy.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdateIntervalPolicy.java
@@ -20,6 +20,7 @@
 
 import java.text.ParseException;
 
+import org.apache.maven.mercury.artifact.Quality;
 import org.apache.maven.mercury.util.TimeUtil;
 import org.apache.maven.mercury.util.Util;
 import org.codehaus.plexus.lang.DefaultLanguage;
@@ -27,98 +28,122 @@
 
 /**
  * implements current maven update policy
- *
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class RepositoryUpdateIntervalPolicy
-implements RepositoryUpdatePolicy
+    implements RepositoryUpdatePolicy
 {
-  private static final Language _lang = new DefaultLanguage( RepositoryUpdateIntervalPolicy.class );
-  
-  public static final String UPDATE_POLICY_NAME_NEVER = "never";
+    private static final Language _lang = new DefaultLanguage( RepositoryUpdateIntervalPolicy.class );
 
-  public static final String UPDATE_POLICY_NAME_ALWAYS = "always";
+    public static final String UPDATE_POLICY_NAME_NEVER = "never";
 
-  public static final String UPDATE_POLICY_NAME_DAILY = "daily";
+    public static final String UPDATE_POLICY_NAME_ALWAYS = "always";
 
-  public static final String UPDATE_POLICY_NAME_INTERVAL = "interval";
-  private static final int UPDATE_POLICY_INTERVAL_LENGTH = UPDATE_POLICY_NAME_INTERVAL.length();
-  
-  public static final String DEFAULT_UPDATE_POLICY = UPDATE_POLICY_NAME_DAILY;
-  
-  public static final RepositoryUpdateIntervalPolicy UPDATE_POLICY_NEVER = new RepositoryUpdateIntervalPolicy(UPDATE_POLICY_NAME_NEVER);
-  public static final RepositoryUpdateIntervalPolicy UPDATE_POLICY_ALWAYS = new RepositoryUpdateIntervalPolicy(UPDATE_POLICY_NAME_ALWAYS);
+    /** same as always - do it NOW */
+    public static final String UPDATE_POLICY_NAME_NOW = "now";
 
-  private static final long NEVER = -1L;
-  
-  private static final long DAYLY = 3600000L*24L;
-  
-  protected long interval = DAYLY;
-  
-  
-  public RepositoryUpdateIntervalPolicy()
-  {
-  }
+    public static final String UPDATE_POLICY_NAME_DAILY = "daily";
 
-  public RepositoryUpdateIntervalPolicy( String policy )
-  {
-    init( policy );
-  }
-  
-  /**
-   * used mostly for testing as it's too much waiting for a minute to test expiration
-   * 
-   * @param interval
-   */
-  public RepositoryUpdateIntervalPolicy setInterval( long interval )
-  {
-    this.interval = interval;
-    return this;
-  }
+    public static final String UPDATE_POLICY_NAME_INTERVAL = "interval";
 
-  public void init( String policy )
-  {
-     if( Util.isEmpty( policy ) )
-       throw new IllegalArgumentException( _lang.getMessage( "empty.policy", policy ));
-     
-     if( policy.startsWith( UPDATE_POLICY_NAME_ALWAYS ) )
-       interval = 0L;
-     else if( policy.startsWith( UPDATE_POLICY_NAME_DAILY ) )
-       interval = DAYLY;
-     else if( policy.startsWith( UPDATE_POLICY_NAME_NEVER ) )
-       interval = NEVER;
-     else if( policy.startsWith( UPDATE_POLICY_NAME_INTERVAL ) )
-     {
-       int len = policy.length();
-       if( len <= UPDATE_POLICY_INTERVAL_LENGTH )
-         throw new IllegalArgumentException( _lang.getMessage( "bad.interval.policy", policy ));
+    private static final int UPDATE_POLICY_INTERVAL_LENGTH = UPDATE_POLICY_NAME_INTERVAL.length();
 
-       interval = Integer.parseInt( policy.substring( len-1 ) ) * 60000L;
-     }
-     else
-       throw new IllegalArgumentException( _lang.getMessage( "bad.policy", policy ));
-  }
+    public static final String DEFAULT_UPDATE_POLICY_NAME = UPDATE_POLICY_NAME_DAILY;
 
-  public boolean timestampExpired( long lastUpdateMillis )
-  {
-    if( interval == NEVER )
-      return false;
+    public static final RepositoryUpdateIntervalPolicy UPDATE_POLICY_NEVER =
+        new RepositoryUpdateIntervalPolicy( UPDATE_POLICY_NAME_NEVER );
+
+    public static final RepositoryUpdateIntervalPolicy UPDATE_POLICY_ALWAYS =
+        new RepositoryUpdateIntervalPolicy( UPDATE_POLICY_NAME_ALWAYS );
+
+    public static final RepositoryUpdateIntervalPolicy UPDATE_POLICY_DAILY =
+        new RepositoryUpdateIntervalPolicy( UPDATE_POLICY_NAME_DAILY );
+
+    /** this is the default policy - don't update unless asked */
+    public static final RepositoryUpdateIntervalPolicy DEFAULT_UPDATE_POLICY = UPDATE_POLICY_NEVER;
+
+    private static final long NEVER = -1L;
+
+    private static final long ALWAYS = 0L;
     
-    long now;
-    try
+    private static final long DAYLY = 3600000L * 24L;
+
+    protected long interval = DAYLY;
+
+    public RepositoryUpdateIntervalPolicy()
     {
-      now = TimeUtil.toMillis( TimeUtil.getUTCTimestamp() );
     }
-    catch( ParseException e )
+
+    public RepositoryUpdateIntervalPolicy( String policy )
     {
-      throw new IllegalArgumentException( e );
+        init( policy );
     }
-    
-    boolean res = ( (now - lastUpdateMillis) > interval); 
-    
-    return res;
-  }
-  
+
+    /**
+     * used mostly for testing as it's too much waiting for a minute to test expiration
+     * 
+     * @param interval
+     */
+    public RepositoryUpdateIntervalPolicy setInterval( long interval )
+    {
+        this.interval = interval;
+        return this;
+    }
+
+    public void init( String policy )
+    {
+        interval = parsePolicy( policy );
+    }
+
+    public static long parsePolicy( String policy )
+    {
+        if ( Util.isEmpty( policy ) )
+            throw new IllegalArgumentException( _lang.getMessage( "empty.policy", policy ) );
+
+        if ( policy.startsWith( UPDATE_POLICY_NAME_ALWAYS ) )
+            return ALWAYS;
+        else if ( policy.startsWith( UPDATE_POLICY_NAME_NOW ) )
+            return ALWAYS;
+        else if ( policy.startsWith( UPDATE_POLICY_NAME_DAILY ) )
+            return DAYLY;
+        else if ( policy.startsWith( UPDATE_POLICY_NAME_NEVER ) )
+            return NEVER;
+        else if ( policy.startsWith( UPDATE_POLICY_NAME_INTERVAL ) )
+        {
+            int len = policy.length();
+            if ( len <= UPDATE_POLICY_INTERVAL_LENGTH )
+                throw new IllegalArgumentException( _lang.getMessage( "bad.interval.policy", policy ) );
+
+            return Integer.parseInt( policy.substring( len - 1 ) ) * 60000L;
+        }
+        else
+            throw new IllegalArgumentException( _lang.getMessage( "bad.policy", policy ) );
+    }
+
+    public boolean timestampExpired( long lastUpdateMillis, Quality quality )
+    {
+        // save a couple of nannos 
+        if ( interval == NEVER )
+            return false;
+
+        if ( interval == ALWAYS )
+            return true;
+
+        long now;
+        try
+        {
+            now = TimeUtil.toMillis( TimeUtil.getUTCTimestamp() );
+        }
+        catch ( ParseException e )
+        {
+            throw new IllegalArgumentException( e );
+        }
+
+        boolean res = ( ( now - lastUpdateMillis ) > interval );
+
+        return res;
+    }
+
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicy.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicy.java
index edcddd1..a7d46f1 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicy.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicy.java
@@ -18,27 +18,29 @@
  */
 package org.apache.maven.mercury.repository.api;
 
+import org.apache.maven.mercury.artifact.Quality;
+
 /**
  * abstraction of a repository update policy calculator
- *
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public interface RepositoryUpdatePolicy
 {
-  /**
-   * initialize this calculator
-   * 
-   * @param policy as a string somewhere in configuration
-   */
-  void init( String policy );
+    public static final String SYSTEM_PROPERTY_UPDATE_POLICY = "mercury.repository.update.policy";
+    /**
+     * initialize this calculator
+     * 
+     * @param policy as a string somewhere in configuration
+     */
+    void init( String policy );
 
-  /**
-   * perform the calculation and decide if it's time to update
-   * 
-   * @param timestamp - UTC-based timestamp as long milliseconds
-   * @return
-   */
-  boolean timestampExpired( long timestampMillis );
+    /**
+     * perform the calculation and decide if it's time to update
+     * 
+     * @param timestamp - UTC-based timestamp as long milliseconds
+     * @return
+     */
+    boolean timestampExpired( long timestampMillis, Quality quality );
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicyFactory.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicyFactory.java
new file mode 100644
index 0000000..5c6898a
--- /dev/null
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicyFactory.java
@@ -0,0 +1,37 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.maven.mercury.repository.api;
+
+/**
+ * creates repository update policy out of strings
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class RepositoryUpdatePolicyFactory
+{
+    public static RepositoryUpdatePolicy create( String policy )
+    {
+        RepositoryUpdateIntervalPolicy up = new RepositoryUpdateIntervalPolicy( policy );
+        
+        return up;
+    }
+}
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryWriter.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryWriter.java
index edcad35..fdfa48c 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryWriter.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryWriter.java
@@ -22,64 +22,60 @@
 
 import org.apache.maven.mercury.artifact.Artifact;
 
-
 /**
- * Repository writer API to be implemented by any repo implementation that wishes 
- * to store artifacts for Maven. All operations are asynchronous and can generate
- * callback events
- *
- *
+ * Repository writer API to be implemented by any repo implementation that wishes to store artifacts for Maven. All
+ * operations are asynchronous and can generate callback events
+ * 
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public interface RepositoryWriter
-extends RepositoryOperator
+    extends RepositoryOperator
 {
-  /**
-   * write (upload) given artifact to the repository
-   * 
-   * @param artifact to upload
-   * @throws RepositoryException
-   */
-  public void writeArtifacts( Collection<Artifact> artifact )
-  throws RepositoryException;
-  
-  public void setMetadataCache( RepositoryMetadataCache mdCache );
-  public RepositoryMetadataCache getMetadataCache();
-  
-  public static final RepositoryWriter NULL_WRITER =
-  new RepositoryWriter()
-  {
-
-    public RepositoryMetadataCache getMetadataCache()
-    {
-        return null;
-    }
-
-    public void setMetadataCache( RepositoryMetadataCache mdCache )
-    {
-    }
-
+    /**
+     * write (upload) given artifact to the repository
+     * 
+     * @param artifact to upload
+     * @throws RepositoryException
+     */
     public void writeArtifacts( Collection<Artifact> artifact )
-        throws RepositoryException
-    {
-    }
+        throws RepositoryException;
 
-    public boolean canHandle( String protocol )
-    {
-        return false;
-    }
+    public void setMetadataCache( RepositoryMetadataCache mdCache );
 
-    public void close()
-    {
-    }
+    public RepositoryMetadataCache getMetadataCache();
 
-    public String[] getProtocols()
+    public static final RepositoryWriter NULL_WRITER = new RepositoryWriter()
     {
-        return null;
-    }
-      
-  };
-          
+
+        public RepositoryMetadataCache getMetadataCache()
+        {
+            return null;
+        }
+
+        public void setMetadataCache( RepositoryMetadataCache mdCache )
+        {
+        }
+
+        public void writeArtifacts( Collection<Artifact> artifact )
+            throws RepositoryException
+        {
+        }
+
+        public boolean canHandle( String protocol )
+        {
+            return false;
+        }
+
+        public void close()
+        {
+        }
+
+        public String[] getProtocols()
+        {
+            return null;
+        }
+
+    };
+
 }
diff --git a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryWriterFactory.java b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryWriterFactory.java
index a87387d..71d46df 100644
--- a/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryWriterFactory.java
+++ b/mercury-repo/mercury-repo-api/src/main/java/org/apache/maven/mercury/repository/api/RepositoryWriterFactory.java
@@ -19,16 +19,12 @@
 package org.apache.maven.mercury.repository.api;
 
 /**
- * 
- *
- *
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 
 public interface RepositoryWriterFactory
 {
-  public RepositoryWriter getWriter( Repository repo )
-  throws RepositoryException;
+    public RepositoryWriter getWriter( Repository repo )
+        throws RepositoryException;
 }
diff --git a/mercury-repo/mercury-repo-api/src/test/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicyIntervalTest.java b/mercury-repo/mercury-repo-api/src/test/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicyIntervalTest.java
index c42bd67..3e99c1d 100644
--- a/mercury-repo/mercury-repo-api/src/test/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicyIntervalTest.java
+++ b/mercury-repo/mercury-repo-api/src/test/java/org/apache/maven/mercury/repository/api/RepositoryUpdatePolicyIntervalTest.java
@@ -43,16 +43,16 @@
 
   public void testInterval()
   {
-    assertFalse( in.timestampExpired( now ) );
-    assertTrue( in.timestampExpired( now-80000L ) );
+    assertFalse( in.timestampExpired( now, null ) );
+    assertTrue( in.timestampExpired( now-80000L, null ) );
   }
 
   public void testDayly()
   {
     in = new RepositoryUpdateIntervalPolicy( RepositoryUpdateIntervalPolicy.UPDATE_POLICY_NAME_DAILY );
 
-    assertFalse( in.timestampExpired( now ) );
-    assertFalse( in.timestampExpired( now-80000L ) );
-    assertTrue( in.timestampExpired( now - 24L*3600L*1000L - 80000L ) );
+    assertFalse( in.timestampExpired( now, null ) );
+    assertFalse( in.timestampExpired( now-80000L, null ) );
+    assertTrue( in.timestampExpired( now - 24L*3600L*1000L - 80000L, null ) );
   }
 }
diff --git a/mercury-repo/mercury-repo-cache-fs/pom.xml b/mercury-repo/mercury-repo-cache-fs/pom.xml
index 0ce1702..9fc1538 100644
--- a/mercury-repo/mercury-repo-cache-fs/pom.xml
+++ b/mercury-repo/mercury-repo-cache-fs/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-repo</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <groupId>org.apache.maven.mercury</groupId>
@@ -36,9 +36,6 @@
       <plugin>
         <groupId>org.codehaus.modello</groupId>
         <artifactId>modello-maven-plugin</artifactId>
-        <!--
-        <version>1.0-alpha-17</version>
-        -->
         <configuration>
           <version>1.0.0</version>
           <models>
diff --git a/mercury-repo/mercury-repo-cache-fs/src/main/java/org/apache/maven/mercury/repository/cache/fs/Messages.properties b/mercury-repo/mercury-repo-cache-fs/src/main/java/org/apache/maven/mercury/repository/cache/fs/Messages.properties
index 96392ac..f6208ae 100644
--- a/mercury-repo/mercury-repo-cache-fs/src/main/java/org/apache/maven/mercury/repository/cache/fs/Messages.properties
+++ b/mercury-repo/mercury-repo-cache-fs/src/main/java/org/apache/maven/mercury/repository/cache/fs/Messages.properties
@@ -17,4 +17,6 @@
 #  under the License.
 #
 bad.root.file=bad root folder {0}
-no.mandatory.attribute=for element {0} mandatory attribute {1} is missing
\ No newline at end of file
+no.mandatory.attribute=for element {0} mandatory attribute {1} is missing
+
+pass.update=passed update point - cache expired
\ No newline at end of file
diff --git a/mercury-repo/mercury-repo-cache-fs/src/main/java/org/apache/maven/mercury/repository/cache/fs/MetadataCacheFs.java b/mercury-repo/mercury-repo-cache-fs/src/main/java/org/apache/maven/mercury/repository/cache/fs/MetadataCacheFs.java
index a01c5c9..fd4567d 100644
--- a/mercury-repo/mercury-repo-cache-fs/src/main/java/org/apache/maven/mercury/repository/cache/fs/MetadataCacheFs.java
+++ b/mercury-repo/mercury-repo-cache-fs/src/main/java/org/apache/maven/mercury/repository/cache/fs/MetadataCacheFs.java
@@ -24,11 +24,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactCoordinates;
-import org.apache.maven.mercury.artifact.Quality;
-import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.event.EventManager;
 import org.apache.maven.mercury.event.EventTypeEnum;
 import org.apache.maven.mercury.event.GenericEvent;
@@ -42,463 +39,498 @@
 import org.apache.maven.mercury.repository.local.m2.ArtifactLocation;
 import org.apache.maven.mercury.util.FileLockBundle;
 import org.apache.maven.mercury.util.FileUtil;
+import org.apache.maven.mercury.util.TimeUtil;
 import org.codehaus.plexus.lang.DefaultLanguage;
 import org.codehaus.plexus.lang.Language;
 
 /**
- *
- *
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class MetadataCacheFs
-implements RepositoryMetadataCache
+    implements RepositoryMetadataCache
 {
-  public static final String EVENT_FIND_GA = "find.ga";
-  public static final String EVENT_FIND_GAV = "find.gav";
-  public static final String EVENT_FIND_RAW = "find.raw";
+    public static final String EVENT_FIND_GA = "find.ga";
 
-  public static final String EVENT_UPDATE_GA = "update.ga";
-  public static final String EVENT_UPDATE_GAV = "update.gav";
-  public static final String EVENT_SAVE_RAW = "save.raw";
+    public static final String EVENT_FIND_GAV = "find.gav";
 
-  private static final Language LANG = new DefaultLanguage( RepositoryGAVMetadata.class );
-  
-  static volatile Map<String, MetadataCacheFs> fsCaches = Collections.synchronizedMap( new HashMap<String, MetadataCacheFs>(2) ); 
-  
-  // store resolved cached data in memory
-  private volatile Map<String, RepositoryGAMetadata> gaCache
-        = (Map<String, RepositoryGAMetadata>)Collections.synchronizedMap( new HashMap<String, RepositoryGAMetadata>(512) );
-  
-  private volatile Map<String, RepositoryGAVMetadata> gavCache
-        = (Map<String, RepositoryGAVMetadata>)Collections.synchronizedMap( new HashMap<String, RepositoryGAVMetadata>(1024) );
-  
-  private volatile Map<String, byte []> rawCache
-        = (Map<String, byte []>)Collections.synchronizedMap( new HashMap<String, byte []>(1024) );
-  
-  private File root;
-  
-  private EventManager _eventManager;
-  
-  /**
-   * access to all known FS caches
-   * 
-   * @param root
-   * @return
-   * @throws IOException 
-   */
-  public static MetadataCacheFs getCache( File root )
-  throws IOException
-  {
-    if( root == null 
-        || ( root.exists() && root.isFile() )
-    )
-      throw new IllegalArgumentException( LANG.getMessage( "bad.root.file", root == null ? "null" : root.getAbsolutePath() ) );
-    
-    String key = root.getCanonicalPath();
-    
-    MetadataCacheFs fsc = fsCaches.get(key);
-    
-    if( fsc == null )
+    public static final String EVENT_FIND_RAW = "find.raw";
+
+    public static final String EVENT_UPDATE_GA = "update.ga";
+
+    public static final String EVENT_UPDATE_GAV = "update.gav";
+
+    public static final String EVENT_SAVE_RAW = "save.raw";
+
+    private static final Language LANG = new DefaultLanguage( RepositoryGAVMetadata.class );
+
+    static volatile Map<String, MetadataCacheFs> fsCaches =
+        Collections.synchronizedMap( new HashMap<String, MetadataCacheFs>( 2 ) );
+
+    // store resolved cached data in memory
+    private volatile Map<String, RepositoryGAMetadata> gaCache =
+        (Map<String, RepositoryGAMetadata>) Collections.synchronizedMap( new HashMap<String, RepositoryGAMetadata>( 512 ) );
+
+    private volatile Map<String, RepositoryGAVMetadata> gavCache =
+        (Map<String, RepositoryGAVMetadata>) Collections.synchronizedMap( new HashMap<String, RepositoryGAVMetadata>(
+                                                                                                                      1024 ) );
+
+    private volatile Map<String, byte[]> rawCache =
+        (Map<String, byte[]>) Collections.synchronizedMap( new HashMap<String, byte[]>( 1024 ) );
+
+    private File root;
+
+    private EventManager _eventManager;
+
+    /**
+     * access to all known FS caches
+     * 
+     * @param root
+     * @return
+     * @throws IOException
+     */
+    public static MetadataCacheFs getCache( File root )
+        throws IOException
     {
-      fsc = new MetadataCacheFs( root );
-      fsCaches.put( key, fsc );
-    }
-    
-    return fsc;
-  }
+        if ( root == null || ( root.exists() && root.isFile() ) )
+            throw new IllegalArgumentException( LANG.getMessage( "bad.root.file", root == null ? "null"
+                            : root.getAbsolutePath() ) );
 
-  /**
-   * private as it should be obtained via a call to <code>getCache()</code>
-   */
-  private MetadataCacheFs( File root )
-  {
-    this.root = root;
-  }
+        String key = root.getCanonicalPath();
 
-  public RepositoryGAMetadata findGA( String repoGuid, RepositoryUpdatePolicy up, ArtifactCoordinates coord )
-  throws MetadataCorruptionException
-  {
-    GenericEvent event = null;
-    
-    try
-    {
-      String gaKey = getGAKey(coord);
-      
-      if( _eventManager != null )
-        event = new GenericEvent( EventTypeEnum.fsCache, EVENT_FIND_GA, gaKey );
-      
-      RepositoryGAMetadata inMem = gaCache.get( gaKey );
-      
-      if( inMem != null )
-      {
-        long lastCheckMillis = inMem.getLastCheckMillis();
-        
-        if( up.timestampExpired( lastCheckMillis ) )
+        MetadataCacheFs fsc = fsCaches.get( key );
+
+        if ( fsc == null )
         {
-          inMem.setExpired( true );
-          gaCache.put( gaKey, inMem );
+            fsc = new MetadataCacheFs( root );
+            fsCaches.put( key, fsc );
         }
-        
-        if( _eventManager != null )
-          event.setResult( "found in memory, expired is "+inMem.isExpired() );
-        
-        return inMem;
-      }
-      
-      File gaDir = getGADir(coord);
-      
-      File gamF = getGAFile( gaDir, repoGuid );
-      
-      CachedGAMetadata md = null;
-      
-      if( gamF.exists() )
-      {
-          md = new CachedGAMetadata( gamF );
-          
-          long lastCheckMillis = md.getLastCheckMillis();
-          
-          if( up != null && up.timestampExpired( lastCheckMillis ) )
-            md.setExpired( true );
 
-          gaCache.put( gaKey, md );
-          
-          if( _eventManager != null )
-            event.setResult( "found on disk, expired is "+md.isExpired() );
-      }
-      else
-      {
-        if( _eventManager != null )
-          event.setResult( "not found" );
-      }
-      
-      return md;
+        return fsc;
     }
-    catch( Exception e )
-    {
-      throw new MetadataCorruptionException( e.getMessage() );
-    }
-    finally
-    {
-      if( _eventManager != null )
-      {
-        event.stop();
-        _eventManager.fireEvent( event );
-      }
-    }
-  }
 
-  public RepositoryGAVMetadata findGAV( String repoGuid, RepositoryUpdatePolicy up, ArtifactCoordinates coord )
-  throws MetadataCorruptionException
-  {
-    FileLockBundle lock = null;
-    GenericEvent event = null;
-    
-    try
+    /**
+     * private as it should be obtained via a call to <code>getCache()</code>
+     */
+    private MetadataCacheFs( File root )
     {
-      String gavKey = getGAVKey(coord);
-      
-      if( _eventManager != null )
-        event = new GenericEvent( EventTypeEnum.fsCache, EVENT_FIND_GAV, gavKey );
-      
-      RepositoryGAVMetadata inMem = gavCache.get( gavKey );
-      
-      if( inMem != null )
-      {
-        long lastCheckMillis = inMem.getLastCheckMillis();
-        
-        if( up.timestampExpired( lastCheckMillis ) )
+        this.root = root;
+    }
+
+    public RepositoryGAMetadata findGA( String repoGuid, RepositoryUpdatePolicy up, ArtifactCoordinates coord )
+        throws MetadataCorruptionException
+    {
+        GenericEvent event = null;
+
+        try
         {
-          inMem.setExpired( true );
-          gavCache.put( gavKey, inMem );
+            String gaKey = getGAKey( coord );
+
+            if ( _eventManager != null )
+                event = new GenericEvent( EventTypeEnum.fsCache, EVENT_FIND_GA, gaKey );
+
+            RepositoryGAMetadata inMem = gaCache.get( gaKey );
+
+            if ( inMem != null )
+            {
+                // im-memory never expires!
+/*                
+                long lastCheckMillis = inMem.getLastCheckMillis();
+
+                if ( up.timestampExpired( lastCheckMillis, null ) )
+                {
+                    inMem.setExpired( true );
+                    gaCache.put( gaKey, inMem );
+                }
+*/
+                if ( _eventManager != null )
+                    event.setResult( "found in memory, expired is " + inMem.isExpired() );
+
+                return inMem;
+            }
+
+            // don't mess with cache if we are past update threshold
+            long now = TimeUtil.getUTCTimestampAsLong();
+            if ( up.timestampExpired( now, null ) )
+            {
+                if ( event != null )
+                    event.setResult( LANG.getMessage( "pass.update" ) );
+
+                return null;
+            }
+
+            File gaDir = getGADir( coord );
+
+            File gamF = getGAFile( gaDir, repoGuid );
+
+            CachedGAMetadata md = null;
+
+            if ( gamF.exists() )
+            {
+                md = new CachedGAMetadata( gamF );
+
+                long lastCheckMillis = md.getLastCheckMillis();
+
+                if ( up != null && up.timestampExpired( lastCheckMillis, null ) )
+                    md.setExpired( true );
+
+                gaCache.put( gaKey, md );
+
+                if ( _eventManager != null )
+                    event.setResult( "found on disk, expired is " + md.isExpired() );
+            }
+            else
+            {
+                if ( _eventManager != null )
+                    event.setResult( "not found" );
+            }
+
+            return md;
         }
-        
-        if( _eventManager != null )
-          event.setResult( "found in memory, expired is "+inMem.isExpired() );
-        
-        return inMem;
-      }
-      
-      File gavDir = getGAVDir( coord );
-
-      lock = FileUtil.lockDir( gavDir.getCanonicalPath(), 500L, 5L );
-      
-      File gavmF = getGAVFile( gavDir, repoGuid );
-      
-      CachedGAVMetadata md = null;
-      
-      if( gavmF.exists() )
-      {
-          md = new CachedGAVMetadata( gavmF );
-          
-          if( up != null && up.timestampExpired( md.getLastCheck() ) )
-            md.setExpired( true );
-
-          if( _eventManager != null )
-            event.setResult( "found on disk, expired is "+inMem.isExpired() );
-          
-          gavCache.put(  gavKey, md );
-      }
-      else
-        if( _eventManager != null )
-          event.setResult( "not found" );
-      
-      return md;
+        catch ( Exception e )
+        {
+            throw new MetadataCorruptionException( e.getMessage() );
+        }
+        finally
+        {
+            if ( _eventManager != null )
+            {
+                event.stop();
+                _eventManager.fireEvent( event );
+            }
+        }
     }
-    catch( Exception e )
+
+    public RepositoryGAVMetadata findGAV( String repoGuid, RepositoryUpdatePolicy up, ArtifactCoordinates coord )
+        throws MetadataCorruptionException
     {
-      throw new MetadataCorruptionException( e.getMessage() );
+        FileLockBundle lock = null;
+        GenericEvent event = null;
+
+        try
+        {
+            String gavKey = getGAVKey( coord );
+
+            if ( _eventManager != null )
+                event = new GenericEvent( EventTypeEnum.fsCache, EVENT_FIND_GAV, gavKey );
+
+            RepositoryGAVMetadata inMem = gavCache.get( gavKey );
+
+            if ( inMem != null )
+            {
+/*
+                long lastCheckMillis = inMem.getLastCheckMillis();
+
+                if ( up.timestampExpired( lastCheckMillis, null ) )
+                {
+                    inMem.setExpired( true );
+                    gavCache.put( gavKey, inMem );
+                }
+*/                
+
+                if ( _eventManager != null )
+                    event.setResult( "found in memory, expired is " + inMem.isExpired() );
+
+                return inMem;
+            }
+
+            // don't mess with cache if we are past update threshold
+            long now = TimeUtil.getUTCTimestampAsLong();
+            if ( up.timestampExpired( now, null ) )
+            {
+                if ( event != null )
+                    event.setResult( LANG.getMessage( "pass.update" ) );
+
+                return null;
+            }
+
+            File gavDir = getGAVDir( coord );
+
+            lock = FileUtil.lockDir( gavDir.getCanonicalPath(), 500L, 5L );
+
+            File gavmF = getGAVFile( gavDir, repoGuid );
+
+            CachedGAVMetadata md = null;
+
+            if ( gavmF.exists() )
+            {
+                md = new CachedGAVMetadata( gavmF );
+
+                if ( up != null && up.timestampExpired( md.getLastCheck(), null ) )
+                    md.setExpired( true );
+
+                if ( _eventManager != null )
+                    event.setResult( "found on disk, expired is " + inMem.isExpired() );
+
+                gavCache.put( gavKey, md );
+            }
+            else if ( _eventManager != null )
+                event.setResult( "not found" );
+
+            return md;
+        }
+        catch ( Exception e )
+        {
+            throw new MetadataCorruptionException( e.getMessage() );
+        }
+        finally
+        {
+            if ( lock != null )
+                lock.release();
+
+            if ( _eventManager != null )
+            {
+                event.stop();
+                _eventManager.fireEvent( event );
+            }
+        }
     }
-    finally
+
+    public void updateGA( String repoGuid, RepositoryGAMetadata gam )
+        throws MetadataCacheException
     {
-      if( lock != null )
-        lock.release();
+        FileLockBundle lock = null;
 
-      if( _eventManager != null )
-      {
-        event.stop();
-        _eventManager.fireEvent( event );
-      }
+        GenericEvent event = null;
+
+        try
+        {
+            String gaKey = getGAKey( gam.getGA() );
+
+            if ( _eventManager != null )
+                event = new GenericEvent( EventTypeEnum.fsCache, EVENT_UPDATE_GA, gaKey );
+
+            File gaDir = getGADir( gam.getGA() );
+
+            lock = FileUtil.lockDir( gaDir.getCanonicalPath(), 500L, 5L );
+
+            File gamF = getGAFile( gaDir, repoGuid );
+
+            CachedGAMetadata md = new CachedGAMetadata( gam );
+
+            md.cm.save( gamF );
+
+            gaCache.put( gaKey, md );
+        }
+        catch ( Exception e )
+        {
+            throw new MetadataCacheException( e.getMessage() );
+        }
+        finally
+        {
+            if ( lock != null )
+                lock.release();
+
+            if ( _eventManager != null )
+            {
+                event.stop();
+                _eventManager.fireEvent( event );
+            }
+        }
     }
-  }
-  
-  public void updateGA( String repoGuid, RepositoryGAMetadata gam )
-  throws MetadataCacheException
-  {
-    FileLockBundle lock = null;
 
-    GenericEvent event = null;
-    
-    try
+    public void updateGAV( String repoGuid, RepositoryGAVMetadata gavm )
+        throws MetadataCacheException
     {
-      String gaKey = getGAKey( gam.getGA() );
-      
-      if( _eventManager != null )
-        event = new GenericEvent( EventTypeEnum.fsCache, EVENT_UPDATE_GA, gaKey );
-      
-      File gaDir = getGADir( gam.getGA() );
-      
-      lock = FileUtil.lockDir( gaDir.getCanonicalPath(), 500L, 5L );
-      
-      File gamF = getGAFile( gaDir, repoGuid );
-      
-      CachedGAMetadata md = new CachedGAMetadata( gam );
-      
-      md.cm.save( gamF );
-      
-      gaCache.put( gaKey, md );
+        FileLockBundle lock = null;
+
+        GenericEvent event = null;
+
+        try
+        {
+            String gavKey = getGAKey( gavm.getGAV() );
+
+            if ( _eventManager != null )
+                event = new GenericEvent( EventTypeEnum.fsCache, EVENT_UPDATE_GA, gavKey );
+
+            File gavDir = getGAVDir( gavm.getGAV() );
+
+            lock = FileUtil.lockDir( gavDir.getCanonicalPath(), 500L, 5L );
+
+            File gavmF = getGAVFile( gavDir, repoGuid );
+
+            CachedGAVMetadata md = new CachedGAVMetadata( gavm );
+
+            md.cm.save( gavmF );
+
+            gavCache.put( gavKey, md );
+        }
+        catch ( Exception e )
+        {
+            throw new MetadataCacheException( e.getMessage() );
+        }
+        finally
+        {
+            if ( lock != null )
+                lock.release();
+
+            if ( _eventManager != null )
+            {
+                event.stop();
+                _eventManager.fireEvent( event );
+            }
+        }
     }
-    catch( Exception e )
+
+    public byte[] findRaw( ArtifactMetadata bmd )
+        throws MetadataCacheException
     {
-      throw new MetadataCacheException( e.getMessage() );
+        GenericEvent event = null;
+
+        try
+        {
+            String rawKey = bmd.getGAV();
+
+            if ( _eventManager != null )
+                event = new GenericEvent( EventTypeEnum.fsCache, EVENT_FIND_RAW, rawKey );
+
+            byte[] res = rawCache.get( rawKey );
+
+            if ( res != null )
+            {
+                if ( _eventManager != null )
+                    event.setResult( "found in memory" );
+
+                return res;
+            }
+
+            // locking is provided by underlying OS, don't waste the effort
+            File f =
+                new File( getGAVDir( bmd.getEffectiveCoordinates() ), bmd.getArtifactId() + FileUtil.DASH
+                    + bmd.getVersion() + "." + bmd.getType() );
+
+            if ( !f.exists() )
+                return null;
+
+            res = FileUtil.readRawData( f );
+
+            rawCache.put( rawKey, res );
+
+            if ( _eventManager != null )
+                event.setResult( "found on disk" );
+
+            return res;
+        }
+        catch ( IOException e )
+        {
+            throw new MetadataCacheException( e.getMessage() );
+        }
+        finally
+        {
+            if ( _eventManager != null )
+            {
+                event.stop();
+                _eventManager.fireEvent( event );
+            }
+        }
     }
-    finally
+
+    public void saveRaw( ArtifactMetadata md, byte[] rawBytes )
+        throws MetadataCacheException
     {
-      if( lock != null ) lock.release();
+        GenericEvent event = null;
 
-      if( _eventManager != null )
-      {
-        event.stop();
-        _eventManager.fireEvent( event );
-      }
+        // locking is provided by underlying OS, don't waste the effort
+        try
+        {
+            String rawKey = md.getGAV();
+
+            if ( _eventManager != null )
+                event = new GenericEvent( EventTypeEnum.fsCache, EVENT_SAVE_RAW, rawKey );
+
+            rawCache.put( rawKey, rawBytes );
+
+            File f =
+                new File( getGAVDir( md.getEffectiveCoordinates() ), md.getArtifactId() + FileUtil.DASH
+                    + md.getVersion() + "." + md.getType() );
+
+            FileUtil.writeRawData( f, rawBytes );
+        }
+        catch ( IOException e )
+        {
+            throw new MetadataCacheException( e.getMessage() );
+        }
+        finally
+        {
+            if ( _eventManager != null )
+            {
+                event.stop();
+                _eventManager.fireEvent( event );
+            }
+        }
     }
-  }
 
-  public void updateGAV( String repoGuid, RepositoryGAVMetadata gavm )
-  throws MetadataCacheException
-  {
-    FileLockBundle lock = null;
-
-    GenericEvent event = null;
-    
-    try
+    // ---------------------------------------------------------------------------------------
+    private String getGAKey( ArtifactCoordinates coord )
     {
-      String gavKey = getGAKey( gavm.getGAV() );
-
-      if( _eventManager != null )
-        event = new GenericEvent( EventTypeEnum.fsCache, EVENT_UPDATE_GA, gavKey );
-      
-      
-      File gavDir = getGAVDir( gavm.getGAV() );
-      
-      lock = FileUtil.lockDir( gavDir.getCanonicalPath(), 500L, 5L );
-
-      File gavmF = getGAVFile( gavDir, repoGuid );
-      
-      CachedGAVMetadata md = new CachedGAVMetadata( gavm );
-      
-      md.cm.save( gavmF );
-      
-      gavCache.put( gavKey, md );
+        return coord.getGroupId() + ":" + coord.getArtifactId();
     }
-    catch( Exception e )
+
+    private String getGAVKey( ArtifactCoordinates coord )
     {
-      throw new MetadataCacheException( e.getMessage() );
+        return coord.getGroupId() + ":" + coord.getArtifactId() + ":" + coord.getVersion();
     }
-    finally
+
+    private File getGADir( ArtifactCoordinates coord )
     {
-      if( lock != null ) lock.release();
+        File dir = new File( root, coord.getGroupId() + FileUtil.SEP + coord.getArtifactId() );
 
-      if( _eventManager != null )
-      {
-        event.stop();
-        _eventManager.fireEvent( event );
-      }
+        if ( !dir.exists() )
+            dir.mkdirs();
+
+        return dir;
     }
-  }
 
-  public byte[] findRaw( ArtifactBasicMetadata bmd )
-  throws MetadataCacheException
-  {
-    GenericEvent event = null;
-    
-    try
+    private File getGAFile( File gaDir, String repoGuid )
     {
-      String rawKey = bmd.getGAV();
-      
-      if( _eventManager != null )
-        event = new GenericEvent( EventTypeEnum.fsCache, EVENT_FIND_RAW, rawKey );
-      
-      byte [] res = rawCache.get( rawKey );
-      
-      if( res != null )
-      {
-        if( _eventManager != null )
-          event.setResult( "found in memory" );
-        
-        return res;
-      }
-      
-      // locking is provided by underlying OS, don't waste the effort
-      File f = new File( getGAVDir( bmd.getEffectiveCoordinates() )
-          , bmd.getArtifactId()+FileUtil.DASH+bmd.getVersion()+"."+bmd.getType()
-          );
-      
-      if( ! f.exists() )
-        return null;
-      
-      res = FileUtil.readRawData( f );
-      
-      rawCache.put( rawKey, res );
-      
-      if( _eventManager != null )
-        event.setResult( "found on disk" );
-      
-      return res; 
+        return new File( gaDir, "meta-ga-" + repoGuid + ".xml" );
     }
-    catch( IOException e )
+
+    private File getGAVDir( ArtifactCoordinates coord )
     {
-      throw new MetadataCacheException( e.getMessage() );
+        String version = ArtifactLocation.calculateVersionDir( coord.getVersion() );
+
+        File dir = new File( getGADir( coord ), coord.getArtifactId() + FileUtil.DASH + version );
+
+        if ( !dir.exists() )
+            dir.mkdirs();
+
+        return dir;
     }
-    finally
+
+    private File getGAVFile( File gavDir, String repoGuid )
     {
-      if( _eventManager != null )
-      {
-        event.stop();
-        _eventManager.fireEvent( event );
-      }
+        return new File( gavDir, "meta-gav-" + repoGuid + ".xml" );
     }
-  }
 
-  public void saveRaw( ArtifactBasicMetadata bmd, byte[] rawBytes )
-  throws MetadataCacheException
-  {
-    GenericEvent event = null;
-    
-    // locking is provided by underlying OS, don't waste the effort
-    try
+    public void register( MercuryEventListener listener )
     {
-      String rawKey = bmd.getGAV();
-      
-      if( _eventManager != null )
-        event = new GenericEvent( EventTypeEnum.fsCache, EVENT_SAVE_RAW, rawKey );
+        if ( _eventManager == null )
+            _eventManager = new EventManager();
 
-      rawCache.put( rawKey, rawBytes );
-      
-      File f = new File( getGAVDir( bmd.getEffectiveCoordinates() )
-          , bmd.getArtifactId()+FileUtil.DASH+bmd.getVersion()+"."+bmd.getType()
-          );
-      
-      FileUtil.writeRawData( f, rawBytes );
+        _eventManager.register( listener );
     }
-    catch( IOException e )
+
+    public void unRegister( MercuryEventListener listener )
     {
-      throw new MetadataCacheException( e.getMessage() );
+        if ( _eventManager != null )
+            _eventManager.unRegister( listener );
     }
-    finally
+
+    public void setEventManager( EventManager eventManager )
     {
-      if( _eventManager != null )
-      {
-        event.stop();
-        _eventManager.fireEvent( event );
-      }
+        if ( _eventManager == null )
+            _eventManager = eventManager;
+        else
+            _eventManager.getListeners().addAll( eventManager.getListeners() );
+
     }
-  }
-  //---------------------------------------------------------------------------------------
-  private String getGAKey( ArtifactCoordinates coord )
-  {
-    return coord.getGroupId()+":"+coord.getArtifactId();
-  }
 
-  private String getGAVKey( ArtifactCoordinates coord )
-  {
-    return coord.getGroupId()+":"+coord.getArtifactId()+":"+coord.getVersion();
-  }
-  
-  private File getGADir( ArtifactCoordinates coord )
-  {
-    File dir = new File( root, coord.getGroupId()+FileUtil.SEP+coord.getArtifactId() );
-    
-    if( ! dir.exists() )
-      dir.mkdirs();
-    
-    return dir;
-  }
-  
-  private File getGAFile( File gaDir, String repoGuid )
-  {
-    return new File( gaDir, "meta-ga-"+repoGuid+".xml" );
-  }
-
-  private File getGAVDir( ArtifactCoordinates coord )
-  {
-    String version = ArtifactLocation.calculateVersionDir( coord.getVersion() );
-    
-    File dir = new File( getGADir( coord ), coord.getArtifactId() + FileUtil.DASH + version );
-    
-    if( ! dir.exists() )
-      dir.mkdirs();
-    
-    return dir;
-  }
-  
-  private File getGAVFile( File gavDir, String repoGuid )
-  {
-    return new File( gavDir, "meta-gav-"+repoGuid+".xml" );
-  }
-
-
-  public void register( MercuryEventListener listener )
-  {
-    if( _eventManager == null )
-      _eventManager = new EventManager();
-      
-    _eventManager.register( listener );
-  }
-
-  public void unRegister( MercuryEventListener listener )
-  {
-    if( _eventManager != null )
-      _eventManager.unRegister( listener );
-  }
-  
-  public void setEventManager( EventManager eventManager )
-  {
-    if( _eventManager == null )
-      _eventManager = eventManager;
-    else
-      _eventManager.getListeners().addAll( eventManager.getListeners() );
-      
-  }
+    public void clearSession()
+        throws MetadataCacheException
+    {
+        rawCache.clear();
+        gaCache.clear();
+        gavCache.clear();
+    }
 }
diff --git a/mercury-repo/mercury-repo-local-flat/pom.xml b/mercury-repo/mercury-repo-local-flat/pom.xml
index 4d0dd62..72d8519 100644
--- a/mercury-repo/mercury-repo-local-flat/pom.xml
+++ b/mercury-repo/mercury-repo-local-flat/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-repo</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <groupId>org.apache.maven.mercury</groupId>
diff --git a/mercury-repo/mercury-repo-local-flat/src/main/java/org/apache/maven/mercury/repository/local/flat/ArtifactLocation.java b/mercury-repo/mercury-repo-local-flat/src/main/java/org/apache/maven/mercury/repository/local/flat/ArtifactLocation.java
index bf9e592..bb51fe8 100644
--- a/mercury-repo/mercury-repo-local-flat/src/main/java/org/apache/maven/mercury/repository/local/flat/ArtifactLocation.java
+++ b/mercury-repo/mercury-repo-local-flat/src/main/java/org/apache/maven/mercury/repository/local/flat/ArtifactLocation.java
@@ -18,7 +18,7 @@
  */
 package org.apache.maven.mercury.repository.local.flat;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
 import org.apache.maven.mercury.util.FileUtil;
 
@@ -43,9 +43,9 @@
   private String classifier;
   private String type;
   
-  private ArtifactBasicMetadata bmd;
+  private ArtifactMetadata bmd;
   
-  public ArtifactLocation( String prefix, ArtifactBasicMetadata bmd )
+  public ArtifactLocation( String prefix, ArtifactMetadata bmd )
   {
     if( prefix == null || bmd == null || bmd.getGroupId() == null || bmd.getArtifactId() == null || bmd.getVersion() == null )
       return;
diff --git a/mercury-repo/mercury-repo-local-flat/src/test/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryFlatTest.java b/mercury-repo/mercury-repo-local-flat/src/test/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryFlatTest.java
index 05cc2e1..510f477 100644
--- a/mercury-repo/mercury-repo-local-flat/src/test/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryFlatTest.java
+++ b/mercury-repo/mercury-repo-local-flat/src/test/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryFlatTest.java
@@ -26,7 +26,7 @@
 import junit.framework.TestCase;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
@@ -66,7 +66,7 @@
     
     byte [] pomBlob = "pomblob".getBytes();
     
-    a = new DefaultArtifact( new ArtifactBasicMetadata("a:a:1.0.0") );
+    a = new DefaultArtifact( new ArtifactMetadata("a:a:1.0.0") );
     
     File ant = File.createTempFile( "test-flat", "-repo" );
     ant.deleteOnExit();
@@ -75,7 +75,7 @@
     a.setFile( ant );
     a.setPomBlob( pomBlob );
     
-    b = new DefaultArtifact( new ArtifactBasicMetadata("b:b:1.0.0") );
+    b = new DefaultArtifact( new ArtifactMetadata("b:b:1.0.0") );
     
     File antlr = File.createTempFile( "test-flat", "-repo" );
     antlr.deleteOnExit();
diff --git a/mercury-repo/mercury-repo-local-m2/pom.xml b/mercury-repo/mercury-repo-local-m2/pom.xml
index 9ed7186..0341a77 100644
--- a/mercury-repo/mercury-repo-local-m2/pom.xml
+++ b/mercury-repo/mercury-repo-local-m2/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-repo</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-repo-local-m2</artifactId>
diff --git a/mercury-repo/mercury-repo-local-m2/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java b/mercury-repo/mercury-repo-local-m2/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java
index 802ce52..26ca5a5 100644
--- a/mercury-repo/mercury-repo-local-m2/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java
+++ b/mercury-repo/mercury-repo-local-m2/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java
@@ -19,7 +19,7 @@
 package org.apache.maven.mercury.repository.local.m2;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
 import org.apache.maven.mercury.util.FileUtil;
 
@@ -44,9 +44,9 @@
   private String classifier;
   private String type;
   
-  private ArtifactBasicMetadata bmd;
+  private ArtifactMetadata bmd;
   
-  public ArtifactLocation( String prefix, ArtifactBasicMetadata bmd )
+  public ArtifactLocation( String prefix, ArtifactMetadata bmd )
   {
     if( prefix == null || bmd == null || bmd.getGroupId() == null || bmd.getArtifactId() == null || bmd.getVersion() == null )
       return;
diff --git a/mercury-repo/mercury-repo-local-m2/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java b/mercury-repo/mercury-repo-local-m2/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java
index ec78e7e..3d4c4ce 100644
--- a/mercury-repo/mercury-repo-local-m2/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java
+++ b/mercury-repo/mercury-repo-local-m2/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java
@@ -19,7 +19,6 @@
 package org.apache.maven.mercury.repository.local.m2;
 
 import java.io.File;
-import java.io.FileFilter;
 import java.io.FileInputStream;
 import java.io.FilenameFilter;
 import java.io.IOException;
@@ -30,10 +29,9 @@
 import java.util.TreeSet;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
 import org.apache.maven.mercury.artifact.Quality;
-import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
 import org.apache.maven.mercury.artifact.version.VersionComparator;
 import org.apache.maven.mercury.artifact.version.VersionException;
 import org.apache.maven.mercury.artifact.version.VersionRange;
@@ -50,7 +48,7 @@
 import org.apache.maven.mercury.repository.api.AbstracRepositoryReader;
 import org.apache.maven.mercury.repository.api.AbstractRepOpResult;
 import org.apache.maven.mercury.repository.api.AbstractRepository;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.LocalRepository;
 import org.apache.maven.mercury.repository.api.Repository;
@@ -105,7 +103,7 @@
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    private static ArtifactLocation calculateLocation( String root, ArtifactBasicMetadata bmd, AbstractRepOpResult res )
+    private static ArtifactLocation calculateLocation( String root, ArtifactMetadata bmd, AbstractRepOpResult res )
     {
         ArtifactLocation loc = new ArtifactLocation( root, bmd );
 
@@ -195,7 +193,7 @@
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    public ArtifactResults readArtifacts( Collection<ArtifactBasicMetadata> query )
+    public ArtifactResults readArtifacts( Collection<ArtifactMetadata> query )
         throws RepositoryException, IllegalArgumentException
     {
         if ( query == null || query.isEmpty() )
@@ -208,11 +206,14 @@
         if ( _repo.hasServer() && _repo.getServer().hasReaderStreamVerifierFactories() )
             vFacs = _repo.getServer().getReaderStreamVerifierFactories();
 
-        for ( ArtifactBasicMetadata bmd : query )
+        for ( ArtifactMetadata md : query )
         {
-            DefaultArtifact da = bmd instanceof DefaultArtifact ? (DefaultArtifact) bmd : new DefaultArtifact( bmd );
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
 
-            ArtifactLocation loc = calculateLocation( _repoDir.getAbsolutePath(), bmd, res );
+            DefaultArtifact da = md instanceof DefaultArtifact ? (DefaultArtifact) md : new DefaultArtifact( md );
+
+            ArtifactLocation loc = calculateLocation( _repoDir.getAbsolutePath(), md, res );
 
             if ( loc == null )
                 continue;
@@ -225,7 +226,7 @@
 //                res.addError( bmd, new RepositoryException( LANG.getMessage( "binary.not.found", bmd.toString(),
 //                                                                             binary.getAbsolutePath() ) ) );
                 if( LOG.isDebugEnabled() )
-                    LOG.debug( LANG.getMessage( "binary.not.found", bmd.toString(), binary.getAbsolutePath() ) );
+                    LOG.debug( LANG.getMessage( "binary.not.found", md.toString(), binary.getAbsolutePath() ) );
 
                 continue;
             }
@@ -238,7 +239,7 @@
                     da.setTracker( this._repo );
                 }
 
-                if ( "pom".equals( bmd.getType() ) )
+                if ( "pom".equals( md.getType() ) )
                 {
                     da.setPomBlob( FileUtil.readRawData( binary ) );
                 }
@@ -251,11 +252,11 @@
                             da.setPomBlob( FileUtil.readRawData( pomFile ) );
                     }
                     else
-                        LOG.warn( LANG.getMessage( "pom.not.found", bmd.toString() ) );
+                        LOG.warn( LANG.getMessage( "pom.not.found", md.toString() ) );
                 }
 
                 da.setVersion( loc.getVersion() );
-                res.add( bmd, da );
+                res.add( md, da );
             }
             catch ( Exception e )
             {
@@ -360,20 +361,23 @@
     /**
    * 
    */
-    public ArtifactBasicResults readDependencies( Collection<ArtifactBasicMetadata> query )
+    public MetadataResults readDependencies( Collection<ArtifactMetadata> query )
         throws RepositoryException, IllegalArgumentException
     {
         if ( query == null || query.size() < 1 )
             return null;
 
-        ArtifactBasicResults ror = null;
+        MetadataResults ror = null;
 
         File pomFile = null;
-        for ( ArtifactBasicMetadata bmd : query )
+        for ( ArtifactMetadata md : query )
         {
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
+
             String pomPath =
-                bmd.getGroupId().replace( '.', '/' ) + "/" + bmd.getArtifactId() + "/" + ArtifactLocation.calculateVersionDir( bmd.getVersion() ) + "/"
-                    + bmd.getArtifactId() + '-' + bmd.getVersion() + ".pom";
+                md.getGroupId().replace( '.', '/' ) + "/" + md.getArtifactId() + "/" + ArtifactLocation.calculateVersionDir( md.getVersion() ) + "/"
+                    + md.getArtifactId() + '-' + md.getVersion() + ".pom";
 
             pomFile = new File( _repoDir, pomPath );
             if ( !pomFile.exists() )
@@ -385,19 +389,19 @@
 
             try
             {
-                List<ArtifactBasicMetadata> deps =
-                    _mdProcessor.getDependencies( bmd, _mdReader == null ? this : _mdReader, System.getenv(),
+                List<ArtifactMetadata> deps =
+                    _mdProcessor.getDependencies( md, _mdReader == null ? this : _mdReader, System.getenv(),
                                                   System.getProperties() );
 // for(ArtifactBasicMetadata d : deps )
 // {
 // System.out.println("======> "+d.getScope() );
 // }
-                ror = ArtifactBasicResults.add( ror, bmd, deps );
+                ror = MetadataResults.add( ror, md, deps );
             }
             catch ( Exception e )
             {
                 if( LOG.isDebugEnabled() )
-                    LOG.debug( "error reading " + bmd.toString() + " dependencies", e );
+                    LOG.debug( "error reading " + md.toString() + " dependencies", e );
                 continue;
             }
 
@@ -407,23 +411,30 @@
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    private static boolean findLatestSnapshot( final ArtifactBasicMetadata bmd, final ArtifactLocation loc, AbstractRepOpResult res )
+    private static boolean findLatestSnapshot( final ArtifactMetadata md, final ArtifactLocation loc, AbstractRepOpResult res )
     {
-        File binary = new File( loc.getAbsPath() );
+        File snapshotFile = new File( loc.getAbsPath() );
+        
+        boolean virtualRequested = md.isVirtual();
+        
+        final boolean virtualExists = snapshotFile.exists();
+        
+        final long  virtualLM = virtualExists ? snapshotFile.lastModified() : 0L;
 
-        if ( binary.exists() )
-            return true;
-
+        // TS exists - return it
+        if ( ! virtualRequested )
+            return snapshotFile.exists();
+        
         // no real SNAPSHOT file, let's try to find one
         File gavDir = new File( loc.getAbsGavPath() );
         
-        String classifier = Util.isEmpty( bmd.getClassifier() ) ? "" : '-'+bmd.getClassifier();
+        String classifier = Util.isEmpty( md.getClassifier() ) ? "" : '-'+md.getClassifier();
         
-        final String regEx = Artifact.SNAPSHOT_TS_REGEX + classifier + "\\."+bmd.getCheckedType();
+        final String regEx = Artifact.SNAPSHOT_TS_REGEX + classifier + "\\."+md.getCheckedType();
         
         final TreeSet<String> ts = new TreeSet<String>( new VersionComparator() );
         
-        final int pos = bmd.getArtifactId().length() + 1;
+        final int pos = md.getArtifactId().length() + 1;
         
         gavDir.listFiles( new FilenameFilter()
                             {
@@ -433,9 +444,25 @@
                                     {
                                         String ver = name.substring( pos, name.lastIndexOf( '.' ) );
                                         
-                                        ts.add( ver );
+                                        if( !virtualExists )
+                                        {
+                                            ts.add( ver );
+                                            
+                                            return true;
+                                        }
                                         
-                                        return true;
+                                        // otherwise - only add it if older'n the SNAPSHOT
+                                        long fLM = new File( dir, name ).lastModified();
+                                        
+                                        if( fLM >= virtualLM )
+                                        {
+                                            ts.add( ver );
+                                            
+                                            return true;
+                                        }
+                                        
+                                        return false;
+                                        
                                     }
     
                                     return false;
@@ -446,12 +473,18 @@
         
         if( ts.isEmpty() )
         {
+            if( virtualExists ) // none were older'n the snapshot
+            {
+                return true;
+            }
+            
             if( LOG.isErrorEnabled() )
-                LOG.error( LANG.getMessage( "snapshot.not.found", bmd.toString(), gavDir.getAbsolutePath() )  );
+                LOG.error( LANG.getMessage( "snapshot.not.found", md.toString(), gavDir.getAbsolutePath() )  );
             
             return false;
         }
         
+        // at east one is older - return it
         loc.setVersion( ts.last() );
 
         return true;
@@ -461,18 +494,21 @@
     /**
      * direct disk search, no redirects - I cannot process pom files :(
      */
-    public ArtifactBasicResults readVersions( Collection<ArtifactBasicMetadata> query )
+    public MetadataResults readVersions( Collection<ArtifactMetadata> query )
         throws RepositoryException, IllegalArgumentException
     {
         if ( query == null || query.size() < 1 )
             return null;
 
-        ArtifactBasicResults res = new ArtifactBasicResults( query.size() );
+        MetadataResults res = new MetadataResults( query.size() );
 
         File gaDir = null;
-        for ( ArtifactBasicMetadata bmd : query )
+        for ( ArtifactMetadata md : query )
         {
-            gaDir = new File( _repoDir, bmd.getGroupId().replace( '.', '/' ) + "/" + bmd.getArtifactId() );
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
+
+            gaDir = new File( _repoDir, md.getGroupId().replace( '.', '/' ) + "/" + md.getArtifactId() );
             if ( !gaDir.exists() )
                 continue;
 
@@ -481,32 +517,32 @@
             VersionRange versionQuery;
             try
             {
-                versionQuery = VersionRangeFactory.create( bmd.getVersion(), _repo.getVersionRangeQualityRange() );
+                versionQuery = VersionRangeFactory.create( md.getVersion(), _repo.getVersionRangeQualityRange() );
             }
             catch ( VersionException e )
             {
-                res = ArtifactBasicResults.add( res, bmd, new RepositoryException( e ) );
+                res = MetadataResults.add( res, md, new RepositoryException( e ) );
                 continue;
             }
 
-            Quality vq = new Quality( bmd.getVersion() );
+            Quality vq = new Quality( md.getVersion() );
 
             if ( vq.equals( Quality.FIXED_RELEASE_QUALITY ) || vq.equals( Quality.FIXED_LATEST_QUALITY )
                 || vq.equals( Quality.SNAPSHOT_QUALITY ) )
             {
-                ArtifactLocation loc = calculateLocation( _repoDir.getAbsolutePath(), bmd, res );
+                ArtifactLocation loc = calculateLocation( _repoDir.getAbsolutePath(), md, res );
 
                 if ( loc == null )
                     continue;
 
-                ArtifactBasicMetadata vmd = new ArtifactBasicMetadata();
-                vmd.setGroupId( bmd.getGroupId() );
-                vmd.setArtifactId( bmd.getArtifactId() );
-                vmd.setClassifier( bmd.getClassifier() );
-                vmd.setType( bmd.getType() );
+                ArtifactMetadata vmd = new ArtifactMetadata();
+                vmd.setGroupId( md.getGroupId() );
+                vmd.setArtifactId( md.getArtifactId() );
+                vmd.setClassifier( md.getClassifier() );
+                vmd.setType( md.getType() );
                 vmd.setVersion( loc.getVersion() );
 
-                res = ArtifactBasicResults.add( res, bmd, vmd );
+                res = MetadataResults.add( res, md, vmd );
 
                 continue;
 
@@ -526,34 +562,37 @@
                 if ( !versionQuery.includes( vf.getName() ) )
                     continue;
 
-                ArtifactBasicMetadata vmd = new ArtifactBasicMetadata();
-                vmd.setGroupId( bmd.getGroupId() );
-                vmd.setArtifactId( bmd.getArtifactId() );
-                vmd.setClassifier( bmd.getClassifier() );
-                vmd.setType( bmd.getType() );
+                ArtifactMetadata vmd = new ArtifactMetadata();
+                vmd.setGroupId( md.getGroupId() );
+                vmd.setArtifactId( md.getArtifactId() );
+                vmd.setClassifier( md.getClassifier() );
+                vmd.setType( md.getType() );
                 vmd.setVersion( vf.getName() );
 
-                res = ArtifactBasicResults.add( res, bmd, vmd );
+                res = MetadataResults.add( res, md, vmd );
             }
         }
         return res;
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type )
+    public byte[] readRawData( ArtifactMetadata md, String classifier, String type )
         throws MetadataReaderException
     {
-        return readRawData( bmd, classifier, type, false );
+        return readRawData( md, classifier, type, false );
     }
     // ---------------------------------------------------------------------------------------------------------------
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type, boolean exempt )
+    public byte[] readRawData( ArtifactMetadata md, String classifier, String type, boolean exempt )
         throws MetadataReaderException
     {
-        return readRawData( relPathOf( bmd, classifier, type ), exempt );
+        if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+            return null;
+
+        return readRawData( relPathOf( md, classifier, type ), exempt );
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    private static String relPathOf( ArtifactBasicMetadata bmd, String classifier, String type )
+    private static String relPathOf( ArtifactMetadata bmd, String classifier, String type )
     {
         String bmdPath =
             bmd.getGroupId().replace( '.', '/' ) + '/' + bmd.getArtifactId() + '/' + ArtifactLocation.calculateVersionDir( bmd.getVersion() );
diff --git a/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocationtest.java b/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocationtest.java
index df4104d..05c23ab 100644
--- a/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocationtest.java
+++ b/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocationtest.java
@@ -19,10 +19,10 @@
 
 package org.apache.maven.mercury.repository.local.m2;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
-
 import junit.framework.TestCase;
 
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
+
 /**
  *
  *
@@ -42,21 +42,21 @@
     public void testChopTS()
     throws Exception
     {
-        ArtifactLocation loc = new ArtifactLocation( "test", new ArtifactBasicMetadata("a:a:3.0-alpha-1-20080920.015600-7") );
+        ArtifactLocation loc = new ArtifactLocation( "test", new ArtifactMetadata("a:a:3.0-alpha-1-20080920.015600-7") );
         
         String chop = loc.getVersionWithoutTS();
         
         assertEquals( "3.0-alpha-1", chop );
 
         
-        loc = new ArtifactLocation( "test", new ArtifactBasicMetadata("a:a:3.0-20080920.015600-7") );
+        loc = new ArtifactLocation( "test", new ArtifactMetadata("a:a:3.0-20080920.015600-7") );
         
         chop = loc.getVersionWithoutTS();
         
         assertEquals( "3.0", chop );
 
 
-        loc = new ArtifactLocation( "test", new ArtifactBasicMetadata("a:a:3.0-20080920.0156007") );
+        loc = new ArtifactLocation( "test", new ArtifactMetadata("a:a:3.0-20080920.0156007") );
         
         chop = loc.getVersionWithoutTS();
         
diff --git a/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2Test.java b/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2Test.java
index b7bc04f..45f2e73 100644
--- a/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2Test.java
+++ b/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2Test.java
@@ -25,7 +25,7 @@
 import junit.framework.TestCase;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 
 /**
@@ -64,9 +64,9 @@
   {
     String artifactId = "a:a:4";
     
-    ArtifactBasicMetadata bmd = new ArtifactBasicMetadata(artifactId);
+    ArtifactMetadata bmd = new ArtifactMetadata(artifactId);
     
-    ArrayList<ArtifactBasicMetadata> q = new ArrayList<ArtifactBasicMetadata>();
+    ArrayList<ArtifactMetadata> q = new ArrayList<ArtifactMetadata>();
     
     q.add( bmd );
     
diff --git a/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/MetadataProcessorMock.java b/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/MetadataProcessorMock.java
index 6fe660b..82ca18f 100644
--- a/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/MetadataProcessorMock.java
+++ b/mercury-repo/mercury-repo-local-m2/src/test/java/org/apache/maven/mercury/repository/local/m2/MetadataProcessorMock.java
@@ -25,7 +25,7 @@
 import java.util.Map;
 
 import org.apache.commons.digester.Digester;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.builder.api.MetadataReader;
 import org.apache.maven.mercury.builder.api.MetadataReaderException;
@@ -43,10 +43,10 @@
 implements DependencyProcessor
 {
 
-  public List<ArtifactBasicMetadata> getDependencies( ArtifactBasicMetadata bmd, MetadataReader mdReader, Map env, Map sysProps )
+  public List<ArtifactMetadata> getDependencies( ArtifactMetadata bmd, MetadataReader mdReader, Map env, Map sysProps )
   throws MetadataReaderException
   {
-    List<ArtifactBasicMetadata> deps = null;
+    List<ArtifactMetadata> deps = null;
     
     try
     {
@@ -65,7 +65,7 @@
     }
   }
   
-  private static final List<ArtifactBasicMetadata> getDeps( byte [] pom )
+  private static final List<ArtifactMetadata> getDeps( byte [] pom )
   throws IOException, SAXException
   {
     if( pom == null )
@@ -92,11 +92,11 @@
 //==============================================================================================
 class DependencyCreator
 {
-  List<ArtifactBasicMetadata> mds = new ArrayList<ArtifactBasicMetadata>(8);
+  List<ArtifactMetadata> mds = new ArrayList<ArtifactMetadata>(8);
   
   public void addMD( String g, String a, String v, String t, String s, String o)
   {
-    ArtifactBasicMetadata md = new ArtifactBasicMetadata();
+    ArtifactMetadata md = new ArtifactMetadata();
     md.setGroupId(g);
     md.setArtifactId(a);
     md.setVersion(v);
diff --git a/mercury-repo/mercury-repo-local-map/pom.xml b/mercury-repo/mercury-repo-local-map/pom.xml
index c019913..1c2c5fe 100644
--- a/mercury-repo/mercury-repo-local-map/pom.xml
+++ b/mercury-repo/mercury-repo-local-map/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-repo</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-repo-local-map</artifactId>
diff --git a/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/DefaultStorage.java b/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/DefaultStorage.java
index 85fd14b..0751efc 100644
--- a/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/DefaultStorage.java
+++ b/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/DefaultStorage.java
@@ -6,7 +6,7 @@
 import java.util.Map;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.util.FileUtil;
 import org.apache.maven.mercury.util.Util;
 import org.codehaus.plexus.lang.DefaultLanguage;
@@ -67,7 +67,7 @@
         this( null );
     }
 
-    public void add( ArtifactBasicMetadata bmd, Artifact artifact )
+    public void add( ArtifactMetadata bmd, Artifact artifact )
     {
         if( _artifacts == null )
             _artifacts = new HashMap<String, Artifact>(32);
@@ -75,7 +75,7 @@
         _artifacts.put( bmd.toString(), artifact );
     }
 
-    public Artifact findArtifact( ArtifactBasicMetadata bmd )
+    public Artifact findArtifact( ArtifactMetadata bmd )
     {
         if( _artifacts == null )
             return null;
diff --git a/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/LocalRepositoryReaderMap.java b/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/LocalRepositoryReaderMap.java
index 9ca5928..da558af 100644
--- a/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/LocalRepositoryReaderMap.java
+++ b/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/LocalRepositoryReaderMap.java
@@ -22,7 +22,7 @@
 import java.util.List;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.builder.api.MetadataReader;
 import org.apache.maven.mercury.builder.api.MetadataReaderException;
@@ -30,7 +30,7 @@
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.repository.api.AbstracRepositoryReader;
 import org.apache.maven.mercury.repository.api.AbstractRepository;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.api.RepositoryException;
@@ -43,9 +43,9 @@
     extends AbstracRepositoryReader
     implements RepositoryReader
 {
-    private static final IMercuryLogger _log = MercuryLoggerManager.getLogger( LocalRepositoryReaderMap.class );
+    private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( LocalRepositoryReaderMap.class );
 
-    private static final Language _lang = new DefaultLanguage( LocalRepositoryReaderMap.class );
+    private static final Language LANG = new DefaultLanguage( LocalRepositoryReaderMap.class );
 
     // ---------------------------------------------------------------------------------------------------------------
     private static final String[] _protocols = new String[] { "map" };
@@ -82,7 +82,7 @@
         return _protocols;
     }
     // ---------------------------------------------------------------------------------------------------------------
-    public ArtifactResults readArtifacts( Collection<ArtifactBasicMetadata> query )
+    public ArtifactResults readArtifacts( Collection<ArtifactMetadata> query )
         throws RepositoryException
     {
         if( Util.isEmpty( query ) )
@@ -93,12 +93,12 @@
         
         ArtifactResults res = new ArtifactResults();
         
-        for( ArtifactBasicMetadata bmd : query )
+        for( ArtifactMetadata md : query )
         {
             Artifact a;
             try
             {
-                a = _repo._storage.findArtifact( bmd );
+                a = _repo._storage.findArtifact( md );
             }
             catch ( Exception e )
             {
@@ -106,7 +106,7 @@
             }
             
             if( a != null )
-                res.add( bmd, a );
+                res.add( md, a );
         }
 
         return res;
@@ -131,13 +131,13 @@
         }
     }
     // ---------------------------------------------------------------------------------------------------------------
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type )
+    public byte[] readRawData( ArtifactMetadata bmd, String classifier, String type )
         throws MetadataReaderException
     {
         return readRawData( bmd, classifier, type, false );
     }
     // ---------------------------------------------------------------------------------------------------------------
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type, boolean exempt )
+    public byte[] readRawData( ArtifactMetadata bmd, String classifier, String type, boolean exempt )
         throws MetadataReaderException
     {
         
@@ -151,7 +151,7 @@
         return readRawData( key, exempt );
     }
     // ---------------------------------------------------------------------------------------------------------------
-    public ArtifactBasicResults readDependencies( Collection<ArtifactBasicMetadata> query )
+    public MetadataResults readDependencies( Collection<ArtifactMetadata> query )
         throws RepositoryException
     {
         if( Util.isEmpty( query ) )
@@ -159,21 +159,21 @@
         
         DependencyProcessor dp = _repo.getDependencyProcessor();
         
-        ArtifactBasicResults res = new ArtifactBasicResults( query.size() );
+        MetadataResults res = new MetadataResults( query.size() );
         
-        for( ArtifactBasicMetadata bmd : query )
+        for( ArtifactMetadata bmd : query )
         {
             try
             {
                 MetadataReader mdr = _repo._mdReader == null ? this : _repo._mdReader;
                 
-                List<ArtifactBasicMetadata> deps = dp.getDependencies( bmd, mdr, System.getenv(), System.getProperties() );
+                List<ArtifactMetadata> deps = dp.getDependencies( bmd, mdr, System.getenv(), System.getProperties() );
                 
                 res.add( bmd, deps );
             }
             catch ( Exception e )
             {
-                _log.error( e.getMessage() );
+                LOG.error( e.getMessage() );
                 
                 res.addError( bmd, e );
             }
@@ -182,7 +182,7 @@
         return res;
     }
     // ---------------------------------------------------------------------------------------------------------------
-    public ArtifactBasicResults readVersions( Collection<ArtifactBasicMetadata> query )
+    public MetadataResults readVersions( Collection<ArtifactMetadata> query )
         throws RepositoryException
     {
         return null;
diff --git a/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/Storage.java b/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/Storage.java
index 713beb9..5a0d488 100644
--- a/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/Storage.java
+++ b/mercury-repo/mercury-repo-local-map/src/main/java/org/apache/maven/mercury/repository/local/map/Storage.java
@@ -3,7 +3,7 @@
 import java.io.File;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 
 /**
  * storage for the repository
@@ -20,7 +20,7 @@
      * @param bmd metadata
      * @param artifact artifact behind it
      */
-    public abstract void add( ArtifactBasicMetadata bmd, Artifact artifact );
+    public abstract void add( ArtifactMetadata bmd, Artifact artifact );
 
     /**
      * find an artifact by it's metadata
@@ -28,7 +28,7 @@
      * @param bmd
      * @return
      */
-    public abstract Artifact findArtifact( ArtifactBasicMetadata bmd );
+    public abstract Artifact findArtifact( ArtifactMetadata bmd );
 
     /**
      * find raw data in this stotage
diff --git a/mercury-repo/mercury-repo-local-map/src/test/java/org/apache/maven/mercury/repository/local/map/LocalRepositoryMapTest.java b/mercury-repo/mercury-repo-local-map/src/test/java/org/apache/maven/mercury/repository/local/map/LocalRepositoryMapTest.java
index b40f2ad..ce6a374 100644
--- a/mercury-repo/mercury-repo-local-map/src/test/java/org/apache/maven/mercury/repository/local/map/LocalRepositoryMapTest.java
+++ b/mercury-repo/mercury-repo-local-map/src/test/java/org/apache/maven/mercury/repository/local/map/LocalRepositoryMapTest.java
@@ -26,9 +26,9 @@
 
 import junit.framework.TestCase;
 
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.builder.api.DependencyProcessor;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.RepositoryReader;
 import org.apache.maven.mercury.repository.local.m2.MetadataProcessorMock;
 import org.apache.maven.mercury.util.FileUtil;
@@ -48,7 +48,7 @@
     
     RepositoryReader _rr;
     
-    ArtifactBasicMetadata bmd;
+    ArtifactMetadata bmd;
     
     File _pom;
 
@@ -56,7 +56,7 @@
     protected void setUp()
         throws Exception
     {
-        bmd = new ArtifactBasicMetadata("t:t:1.0::pom");
+        bmd = new ArtifactMetadata("t:t:1.0::pom");
         
         _pom = new File("./target/test-classes/t-1.0.pom");
 
@@ -84,11 +84,11 @@
     public void testReadMap()
         throws Exception
     {
-        Collection<ArtifactBasicMetadata> query = new ArrayList<ArtifactBasicMetadata>(1);
+        Collection<ArtifactMetadata> query = new ArrayList<ArtifactMetadata>(1);
         
         query.add( bmd );
         
-        ArtifactBasicResults res = _rr.readDependencies( query  );
+        MetadataResults res = _rr.readDependencies( query  );
         
         assertNotNull( res );
         
@@ -96,13 +96,13 @@
         
         assertTrue( res.hasResults() );
         
-        Map<ArtifactBasicMetadata, List<ArtifactBasicMetadata>>  deps = res.getResults();
+        Map<ArtifactMetadata, List<ArtifactMetadata>>  deps = res.getResults();
         
         assertNotNull( deps );
         
         assertEquals( 1, deps.size() );
         
-        List<ArtifactBasicMetadata> myDeps = deps.get( bmd );
+        List<ArtifactMetadata> myDeps = deps.get( bmd );
         
         assertNotNull( myDeps );
         
diff --git a/mercury-repo/mercury-repo-remote-m2/pom.xml b/mercury-repo/mercury-repo-remote-m2/pom.xml
index 537d508..16ff0cc 100644
--- a/mercury-repo/mercury-repo-remote-m2/pom.xml
+++ b/mercury-repo/mercury-repo-remote-m2/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-repo</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-repo-remote-m2</artifactId>
diff --git a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/Messages.properties b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/Messages.properties
index da4fd8c..804d775 100644
--- a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/Messages.properties
+++ b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/Messages.properties
@@ -46,4 +46,14 @@
 cached.metadata.reading.exception=problem {0} reading cached data for {1}, server {2}
 
 default.root=remote reader: temporary repository folder set to {0}
-read.artifact=read {1} from {0}
\ No newline at end of file
+read.artifact=read {1} from {0}
+
+null.update.policy=trying to set null update policy for repository {0}, url {1}
+
+artifact.not.qualified=The supplied metadata {0} does not have a repository reference 
+no.md.list=cannot read artifacts for a null or empty metadata list
+
+read.artifacts=read {0} artifacts as a transaction
+read.artifacts.time=reading {0} artifacts took {1} seconds
+non.qualified.artifact=internal error: an artifact without repository tracker {0} leaked into the read call
+
diff --git a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryM2.java b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryM2.java
index 8a9f691..b62cb06 100644
--- a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryM2.java
+++ b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryM2.java
@@ -38,7 +38,7 @@
     extends AbstractRepository
     implements RemoteRepository
 {
-    private static final Language _LANG = new DefaultLanguage( RemoteRepositoryReaderM2.class );
+    private static final Language LANG = new DefaultLanguage( RemoteRepositoryReaderM2.class );
 
     public static final String METADATA_FILE_NAME = "maven-metadata.xml";
 
@@ -48,7 +48,7 @@
 
     /** default update policy */
     private RepositoryUpdatePolicy _updatePolicy =
-        new RepositoryUpdateIntervalPolicy( RepositoryUpdateIntervalPolicy.DEFAULT_UPDATE_POLICY );
+        RepositoryUpdateIntervalPolicy.DEFAULT_UPDATE_POLICY;
 
     // ----------------------------------------------------------------------------------
     public RemoteRepositoryM2( String url, DependencyProcessor dependencyProcessor )
@@ -100,10 +100,9 @@
 
     // ----------------------------------------------------------------------------------
     public RepositoryWriter getWriter( String protocol )
-        throws NonExistentProtocolException
+        throws NonExistentProtocolException, RepositoryException
     {
-        // TODO Auto-generated method stub
-        return null;
+        return getWriter();
     }
 
     // ----------------------------------------------------------------------------------
@@ -145,12 +144,15 @@
     // ----------------------------------------------------------------------------------
     public RepositoryUpdatePolicy getUpdatePolicy()
     {
-        return _updatePolicy;
+        return _updatePolicy == null ? RepositoryUpdateIntervalPolicy.DEFAULT_UPDATE_POLICY : _updatePolicy;
     }
 
     // ----------------------------------------------------------------------------------
     public void setUpdatePolicy( RepositoryUpdatePolicy updatePolicy )
     {
+        if( updatePolicy == null )
+            throw new IllegalArgumentException( LANG.getMessage( "null.update.policy", getId(), _server == null ? "no URL":_server.getURL()+"" ) );
+        
         this._updatePolicy = updatePolicy;
     }
 
diff --git a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryReaderM2.java b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryReaderM2.java
index 8124b13..0f277c7 100644
--- a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryReaderM2.java
+++ b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryReaderM2.java
@@ -27,13 +27,15 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.TreeSet;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactCoordinates;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
 import org.apache.maven.mercury.artifact.Quality;
 import org.apache.maven.mercury.artifact.QualityEnum;
@@ -50,7 +52,7 @@
 import org.apache.maven.mercury.repository.api.AbstracRepositoryReader;
 import org.apache.maven.mercury.repository.api.AbstractRepOpResult;
 import org.apache.maven.mercury.repository.api.AbstractRepository;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.LocalRepository;
 import org.apache.maven.mercury.repository.api.MetadataCacheException;
@@ -77,7 +79,6 @@
 import org.apache.maven.mercury.util.Util;
 import org.codehaus.plexus.lang.DefaultLanguage;
 import org.codehaus.plexus.lang.Language;
-import org.mortbay.log.Log;
 
 /**
  * implementation of M2 remote repository reader. Actual Transport (protocol, URL) [should] come from RemoteRepository
@@ -98,9 +99,7 @@
     // TODO - replace with known Transport's protocols. Should be similar to RepositoryReader/Writer registration
     private static final String[] _protocols = new String[] { "http", "https", "dav", "webdav" };
 
-    // TODO replace with Transport
-    DefaultRetriever _transport;
-
+    private HashSet<Server> _servers;
     // ---------------------------------------------------------------------------------------------------------------
     RemoteRepository _repo;
 
@@ -143,8 +142,8 @@
             _defaultRoot.mkdirs();
             _defaultRoot.deleteOnExit();
             
-            if( LOG.isWarnEnabled() )
-                LOG.warn( LANG.getMessage( "default.root", _defaultRoot.getCanonicalPath() ) );
+            if( LOG.isDebugEnabled() )
+                LOG.debug( LANG.getMessage( "default.root", _defaultRoot.getCanonicalPath() ) );
         }
         catch ( IOException e )
         {
@@ -159,19 +158,10 @@
         else
             _localRepos = localRepos;
 
-        try
-        {
-            // TODO 2008-07-29 og: here I should analyze Server protocol
-            // and come with appropriate Transport implementation
-            _transport = new DefaultRetriever();
-            HashSet<Server> servers = new HashSet<Server>( 1 );
-            servers.add( repo.getServer() );
-            _transport.setServers( servers );
-        }
-        catch ( HttpClientException e )
-        {
-            throw new RepositoryException( e );
-        }
+        // TODO 2008-07-29 og: here I should analyze Server protocol
+        // and come with appropriate Transport implementation
+        _servers = new HashSet<Server>( 1 );
+        _servers.add( repo.getServer() );
     }
 
     // ---------------------------------------------------------------------------------------------------------------
@@ -181,15 +171,15 @@
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    private final ArtifactLocation calculateLocation( String root, ArtifactBasicMetadata bmd, AbstractRepOpResult res )
+    private final ArtifactLocation calculateLocation( String root, ArtifactMetadata md, AbstractRepOpResult res )
         throws RepositoryException, MetadataReaderException, MetadataException
     {
-        ArtifactLocation loc = new ArtifactLocation( root, bmd );
+        ArtifactLocation loc = new ArtifactLocation( root, md );
 
         Collection<String> versions = null;
         try
         {
-            versions = getCachedVersions( loc, bmd, res );
+            versions = getCachedVersions( loc, md, res );
         }
         catch ( MetadataCacheException e )
         {
@@ -213,7 +203,7 @@
                 // res.addError( bmd, new RepositoryException( LANG.getMessage( "gav.not.found", bmd.toString(),
                 // loc.getGaPath() ) ) );
                 if ( LOG.isWarnEnabled() )
-                    LOG.warn( LANG.getMessage( "gav.not.found", bmd.toString(), loc.getGaPath() ) );
+                    LOG.warn( LANG.getMessage( "gav.not.found", md.toString(), loc.getGaPath() ) );
 
                 return null;
             }
@@ -225,7 +215,7 @@
             {
                 loc.setVersionDir( loc.getVersion() );
 
-                if ( !findLatestSnapshot( bmd, loc, res ) )
+                if ( !findLatestSnapshot( md, loc, res ) )
                     return null;
             }
             else
@@ -235,7 +225,7 @@
         // regular snapshot requested
         else if ( loc.getVersion().endsWith( Artifact.SNAPSHOT_VERSION ) )
         {
-            if ( !versions.contains( loc.getVersion() ) && !findLatestSnapshot( bmd, loc, res ) )
+            if ( !versions.contains( loc.getVersion() ) && !findLatestSnapshot( md, loc, res ) )
                 return null;
         }
         // time stamped snapshot requested
@@ -248,7 +238,7 @@
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    private Collection<String> getCachedSnapshots( ArtifactBasicMetadata bmd, ArtifactLocation loc )
+    private Collection<String> getCachedSnapshots( ArtifactMetadata bmd, ArtifactLocation loc )
         throws MetadataCacheException, RepositoryException, MetadataReaderException, MetadataException
     {
         RepositoryGAVMetadata gavm = null;
@@ -305,7 +295,7 @@
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    private boolean findLatestSnapshot( ArtifactBasicMetadata bmd, ArtifactLocation loc, AbstractRepOpResult res )
+    private boolean findLatestSnapshot( ArtifactMetadata bmd, ArtifactLocation loc, AbstractRepOpResult res )
         throws MetadataReaderException, MetadataException, RemoteRepositoryM2OperationException
     {
         DefaultArtifactVersion dav = new DefaultArtifactVersion( loc.getVersion() );
@@ -354,7 +344,7 @@
     /**
      * TODO og: parallelize as soon as code stabilizes
      */
-    public ArtifactResults readArtifacts( Collection<ArtifactBasicMetadata> query )
+    public ArtifactResults readArtifacts( Collection<ArtifactMetadata> query )
         throws RepositoryException
     {
         if ( query == null || query.size() < 1 )
@@ -362,15 +352,18 @@
 
         ArtifactResults res = new ArtifactResults();
 
-        for ( ArtifactBasicMetadata bmd : query )
+        for ( ArtifactMetadata md : query )
         {
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
+            
             try
             {
-                readArtifact( bmd, res );
+                readArtifact( md, res );
             }
             catch ( Exception e )
             {
-                res.addError( bmd, e );
+                res.addError( md, e );
             }
         }
 
@@ -388,19 +381,19 @@
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    public void readArtifact( ArtifactBasicMetadata bmd, ArtifactResults res )
+    private void readArtifact( ArtifactMetadata md, ArtifactResults res )
         throws IOException, RepositoryException, MetadataReaderException, MetadataException
     {
-        DefaultArtifact da = bmd instanceof DefaultArtifact ? (DefaultArtifact) bmd : new DefaultArtifact( bmd );
+        DefaultArtifact da = md instanceof DefaultArtifact ? (DefaultArtifact) md : new DefaultArtifact( md );
 
-        ArtifactLocation loc = calculateLocation( _repo.getServer().getURL().toString(), bmd, res );
+        ArtifactLocation loc = calculateLocation( _repo.getServer().getURL().toString(), md, res );
 
         if ( loc == null )
             return;
 
         da.setVersion( loc.getVersion() );
 
-        Quality vq = new Quality( loc.getVersion() );
+        Quality vq = da.getRequestedQuality();
 
         File root = findLocalRoot( vq );
 
@@ -412,7 +405,7 @@
         Binding binBinding = new Binding( new URL( loc.getAbsPath() ), binFile );
         drr.addBinding( binBinding );
 
-        boolean isPom = "pom".equals( bmd.getType() );
+        boolean isPom = "pom".equals( md.getType() );
         if ( !isPom )
         {
             pomFile = new File( root, loc.getRelPomPath() );
@@ -420,11 +413,22 @@
             drr.addBinding( pomBinding );
         }
 
-        RetrievalResponse resp = _transport.retrieve( drr );
+        DefaultRetriever transport;
+        try
+        {
+            transport = new DefaultRetriever();
+        }
+        catch ( HttpClientException e )
+        {
+            throw new RepositoryException( e );
+        }
+        transport.setServers( _servers );
+        RetrievalResponse resp = transport.retrieve( drr );
+        transport.stop();
 
         if ( resp.hasExceptions() )
         {
-            res.addError( bmd, new RepositoryException( resp.getExceptions().toString() ) );
+            res.addError( md, new RepositoryException( resp.getExceptions().toString() ) );
         }
         else
         {
@@ -433,7 +437,121 @@
 
             da.setFile( binFile );
             da.setPomBlob( FileUtil.readRawData( isPom ? binFile : pomFile ) );
-            res.add( bmd, da );
+            res.add( md, da );
+        }
+    }
+    // ---------------------------------------------------------------------------------------------------------------
+    /**
+     * this is an extended call, specific to Remote M2 repository for now
+     */
+    public void readQualifiedArtifacts( Collection<ArtifactMetadata> mds, ArtifactResults res )
+    throws IOException, RepositoryException, MetadataReaderException, MetadataException
+    {
+        if( Util.isEmpty( mds ) )
+            throw new IllegalArgumentException( LANG.getMessage( "no.md.list" ) );
+        
+        Map<ArtifactMetadata, DefaultArtifact> artifacts = new HashMap<ArtifactMetadata, DefaultArtifact>( mds.size() );
+        
+        DefaultRetrievalRequest request = new DefaultRetrievalRequest();
+        
+        long start = 0;
+
+        if( LOG.isInfoEnabled() )
+        {
+            start = System.currentTimeMillis();
+            
+            LOG.info( LANG.getMessage( "read.artifacts", mds.size()+"" ) );
+        }
+        
+        TreeSet<Server> servers = new TreeSet<Server>(
+                        new Comparator<Server>()
+                        {
+
+                            public int compare( Server s1, Server s2 )
+                            {
+                                return s1.getId().compareTo( s2.getId() );
+                            }
+            
+                        }
+                                                     );
+        for( ArtifactMetadata md : mds )
+        {
+            DefaultArtifact da = md instanceof DefaultArtifact ? (DefaultArtifact) md : new DefaultArtifact( md );
+            
+            artifacts.put( md, da );
+            
+            Server server = ( (RemoteRepositoryReaderM2)md.getTracker() ).getRepository().getServer();
+    
+            ArtifactLocation loc = new ArtifactLocation( server.getURL().toString(), md ); //calculateLocation( server.getURL().toString(), md, res );
+            
+            servers.add( server );
+    
+            da.setVersion( loc.getVersion() );
+    
+            Quality vq = da.getRequestedQuality();
+    
+            File root = findLocalRoot( vq );
+    
+            File binFile = new File( root, loc.getRelPath() );
+            File pomFile = null;
+    
+            Binding binBinding = new Binding( new URL( loc.getAbsPath() ), binFile );
+            request.addBinding( binBinding );
+            
+            da.setFile( binFile );
+    
+            if ( !md.isPom() )
+            {
+                pomFile = new File( root, loc.getRelPomPath() );
+                Binding pomBinding = new Binding( new URL( loc.getAbsPomPath() ), pomFile );
+                request.addBinding( pomBinding );
+                
+                da.setPomFile( pomFile );
+            }
+
+            Object tracker = md.getTracker();
+            
+            if( tracker == null )
+                throw new RepositoryNonQualifiedArtifactException( LANG.getMessage( "non.qualified.artifact", md.toString() ));
+
+            servers.add( ((RemoteRepositoryReaderM2)tracker).getRepository().getServer() );
+        }
+
+        DefaultRetriever retriever;
+        try
+        {
+            retriever = new DefaultRetriever();
+        }
+        catch ( HttpClientException e )
+        {
+            throw new RepositoryException(e);
+        }
+        
+        retriever.setServers( servers );
+        
+        RetrievalResponse response = retriever.retrieve( request );
+        
+        retriever.stop();
+        
+        if ( response.hasExceptions() )
+        {
+            // record all bugs on the first artifact as jetty transport does not 
+            res.addError( (ArtifactMetadata) mds.toArray()[0], new RepositoryException( response.getExceptions().toString() ) );
+        }
+        else
+        {
+            for( Map.Entry<ArtifactMetadata, DefaultArtifact> e : artifacts.entrySet() )
+            {
+                DefaultArtifact da = e.getValue();
+                da.setPomBlob( FileUtil.readRawData( da.isPom() ? da.getFile() : da.getPomFile() ) );
+                res.add( e.getKey(), da );
+            }
+        }
+
+        if( LOG.isInfoEnabled() )
+        {
+            long diff = System.currentTimeMillis() - start;
+            LOG.info( LANG.getMessage( "read.artifacts.time", mds.size()+"", (diff/1000L)+"" ) );
         }
     }
 
@@ -441,36 +559,38 @@
     /**
    * 
    */
-    public ArtifactBasicResults readDependencies( Collection<ArtifactBasicMetadata> query )
+    public MetadataResults readDependencies( Collection<ArtifactMetadata> query )
         throws RepositoryException
     {
         if ( query == null || query.size() < 1 )
             return null;
 
-        ArtifactBasicResults ror = new ArtifactBasicResults( 16 );
+        MetadataResults ror = new MetadataResults( 16 );
 
-        for ( ArtifactBasicMetadata bmd : query )
+        for ( ArtifactMetadata md : query )
         {
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
+            
             try
             {
-                List<ArtifactBasicMetadata> deps =
-                    _mdProcessor.getDependencies( bmd, _mdReader == null ? this : _mdReader, System.getenv(),
+                List<ArtifactMetadata> deps =
+                    _mdProcessor.getDependencies( md, _mdReader == null ? this : _mdReader, System.getenv(),
                                                   System.getProperties() );
-                ror.add( bmd, deps );
+                ror.add( md, deps );
             }
             catch ( Exception e )
             {
-                LOG.warn( "error reading " + bmd.toString() + " dependencies", e );
+                LOG.warn( "error reading " + md.toString() + " dependencies", e );
                 continue;
             }
-
         }
 
         return ror;
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    private TreeSet<String> getCachedVersions( ArtifactLocation loc, ArtifactBasicMetadata bmd, AbstractRepOpResult res )
+    private TreeSet<String> getCachedVersions( ArtifactLocation loc, ArtifactMetadata bmd, AbstractRepOpResult res )
         throws MetadataException, MetadataReaderException, MetadataCacheException
     {
         RepositoryGAMetadata gam = null;
@@ -633,7 +753,7 @@
             if ( foundSnapshot )
             {
                 boolean snFound = false;
-                ArtifactBasicMetadata snMd = new ArtifactBasicMetadata( bmd.toString() );
+                ArtifactMetadata snMd = new ArtifactMetadata( bmd.toString() );
                 snMd.setVersion( v );
                 ArtifactLocation snLoc = new ArtifactLocation( loc.getPrefix(), snMd );
                 try
@@ -698,36 +818,39 @@
     /**
      * direct metadata search, no redirects, first attempt
      */
-    public ArtifactBasicResults readVersions( Collection<ArtifactBasicMetadata> query )
+    public MetadataResults readVersions( Collection<ArtifactMetadata> query )
         throws RepositoryException
     {
         if ( query == null || query.size() < 1 )
             return null;
 
-        ArtifactBasicResults res = new ArtifactBasicResults( query.size() );
+        MetadataResults res = new MetadataResults( query.size() );
 
         String root = _repo.getServer().getURL().toString();
 
-        for ( ArtifactBasicMetadata bmd : query )
+        for ( ArtifactMetadata md : query )
         {
-            ArtifactLocation loc = new ArtifactLocation( root, bmd );
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
+            
+            ArtifactLocation loc = new ArtifactLocation( root, md );
 
             TreeSet<String> versions = null;
 
             try
             {
-                versions = getCachedVersions( loc, bmd, res );
+                versions = getCachedVersions( loc, md, res );
 
                 if ( Util.isEmpty( versions ) )
                     continue;
             }
             catch ( Exception e )
             {
-                res.addError( bmd, e );
+                res.addError( md, e );
                 continue;
             }
 
-            Quality vq = new Quality( bmd.getVersion() );
+            Quality vq = new Quality( md.getVersion() );
 
             boolean lookForSnapshot = vq.equals( Quality.SNAPSHOT_QUALITY );
             boolean lookForLatest = vq.equals( Quality.FIXED_LATEST_QUALITY );
@@ -761,7 +884,7 @@
                 }
                 else
                 {
-                    String base = ArtifactLocation.stripSN( bmd.getVersion() );
+                    String base = ArtifactLocation.stripSN( md.getVersion() );
 
                     if ( base != null )
                     {
@@ -785,14 +908,16 @@
 
                 if ( found != null )
                 {
-                    ArtifactBasicMetadata vmd = new ArtifactBasicMetadata();
-                    vmd.setGroupId( bmd.getGroupId() );
-                    vmd.setArtifactId( bmd.getArtifactId() );
-                    vmd.setClassifier( bmd.getClassifier() );
-                    vmd.setType( bmd.getType() );
+                    ArtifactMetadata vmd = new ArtifactMetadata();
+                    vmd.setGroupId( md.getGroupId() );
+                    vmd.setArtifactId( md.getArtifactId() );
+                    vmd.setClassifier( md.getClassifier() );
+                    vmd.setType( md.getType() );
                     vmd.setVersion( found );
+                    
+                    vmd.setTracker( this );
 
-                    res = ArtifactBasicResults.add( res, bmd, vmd );
+                    res = MetadataResults.add( res, md, vmd );
                 }
 
                 continue;
@@ -801,11 +926,11 @@
             VersionRange versionQuery;
             try
             {
-                versionQuery = VersionRangeFactory.create( bmd.getVersion(), _repo.getVersionRangeQualityRange() );
+                versionQuery = VersionRangeFactory.create( md.getVersion(), _repo.getVersionRangeQualityRange() );
             }
             catch ( VersionException e )
             {
-                res.addError( bmd, new RepositoryException( e ) );
+                res.addError( md, new RepositoryException( e ) );
                 continue;
             }
 
@@ -819,14 +944,16 @@
                 if ( !versionQuery.includes( version ) )
                     continue;
 
-                ArtifactBasicMetadata vmd = new ArtifactBasicMetadata();
-                vmd.setGroupId( bmd.getGroupId() );
-                vmd.setArtifactId( bmd.getArtifactId() );
-                vmd.setClassifier( bmd.getClassifier() );
-                vmd.setType( bmd.getType() );
+                ArtifactMetadata vmd = new ArtifactMetadata();
+                vmd.setGroupId( md.getGroupId() );
+                vmd.setArtifactId( md.getArtifactId() );
+                vmd.setClassifier( md.getClassifier() );
+                vmd.setType( md.getType() );
                 vmd.setVersion( version );
+                
+                vmd.setTracker( this );
 
-                res = ArtifactBasicResults.add( res, bmd, vmd );
+                res = MetadataResults.add( res, md, vmd );
             }
 
         }
@@ -835,18 +962,21 @@
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type )
+    public byte[] readRawData( ArtifactMetadata md, String classifier, String type )
         throws MetadataReaderException
     {
-        return readRawData( bmd, classifier, type, false );
+        return readRawData( md, classifier, type, false );
     }
 
     // ---------------------------------------------------------------------------------------------------------------
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type, boolean exempt )
+    public byte[] readRawData( ArtifactMetadata md, String classifier, String type, boolean exempt )
         throws MetadataReaderException
     {
+        if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+            return null;
+
         byte[] res = null;
-        ArtifactBasicMetadata mod = null;
+        ArtifactMetadata mod = null;
 
         // if( _log.isDebugEnabled() )
         // _log.debug( "reading "+bmd+" from " + _repo.getId() );
@@ -854,10 +984,7 @@
         // only cache poms at the moment
         if ( _mdCache != null && "pom".equals( type ) )
         {
-            mod = new ArtifactBasicMetadata();
-            mod.setGroupId( bmd.getGroupId() );
-            mod.setArtifactId( bmd.getArtifactId() );
-            mod.setVersion( ArtifactLocation.calculateVersionDir( bmd.getVersion() ) );
+            mod = new ArtifactMetadata( md );
             mod.setClassifier( classifier );
             mod.setType( type );
 
@@ -867,33 +994,34 @@
                 if ( res != null )
                 {
                     if ( LOG.isDebugEnabled() )
-                        LOG.debug( "found " + bmd + " in the cache" );
+                        LOG.debug( "found " + md + " in the cache" );
                     return res;
                 }
             }
             catch ( MetadataCacheException e )
             {
                 // problems with the cache - move on
-                LOG.error( LANG.getMessage( "cached.data.problem", e.getMessage(), bmd.toString() ) );
+                LOG.error( LANG.getMessage( "cached.data.problem", e.getMessage(), md.toString() ) );
             }
         }
 
         mod =
-            new ArtifactBasicMetadata( bmd.getGroupId() + ":" + bmd.getArtifactId() + ":" + bmd.getVersion() + ":"
-                + ( classifier == null ? "" : classifier ) + ":" + ( type == null ? bmd.getType() : type ) );
+            new ArtifactMetadata( md.getGroupId() + ":" + md.getArtifactId() + ":" + md.getVersion() + ":"
+                + ( classifier == null ? "" : classifier ) + ":" + ( type == null ? md.getType() : type ) );
 
         // ArtifactLocation loc = new ArtifactLocation( "", mod );
 
         // String bmdPath = loc.getAbsPath();
 
-        String bmdPath =
-            bmd.getGroupId().replace( '.', '/' ) + '/' + bmd.getArtifactId() + '/'
-                + ArtifactLocation.calculateVersionDir( bmd.getVersion() ) + '/' + bmd.getBaseName( classifier ) + '.'
-                + ( type == null ? bmd.getType() : type );
-        if ( LOG.isDebugEnabled() )
-            LOG.debug( "calculated raw path as " + bmdPath );
+        String mdPath =
+            md.getGroupId().replace( '.', '/' ) + '/' + md.getArtifactId() + '/'
+                + ArtifactLocation.calculateVersionDir( md.getVersion() ) + '/' + md.getBaseName( classifier ) + '.'
+                + ( type == null ? md.getType() : type );
 
-        res = readRawData( bmdPath, exempt );
+        res = readRawData( mdPath, exempt );
+
+        if ( LOG.isDebugEnabled() )
+            LOG.debug( "POM bytes not cached, read "+ (res == null ? 0:res.length) +" bytes from " + mdPath );
 
         if ( _mdCache != null && res != null && mod != null )
         {
@@ -939,7 +1067,10 @@
             DefaultRetrievalRequest request = new DefaultRetrievalRequest();
             request.addBinding( binding );
 
-            RetrievalResponse response = _transport.retrieve( request );
+            DefaultRetriever transport = new DefaultRetriever();
+            transport.setServers( _servers );
+            RetrievalResponse response = transport.retrieve( request );
+            transport.stop();
 
             if ( response.hasExceptions() )
             {
@@ -958,6 +1089,10 @@
         {
             throw new MetadataReaderException( e );
         }
+        catch ( HttpClientException e )
+        {
+            throw new MetadataReaderException(e);
+        }
         finally
         {
             if ( fis != null )
@@ -978,12 +1113,17 @@
 
     public void close()
     {
-        // TODO Auto-generated method stub
-
+//        if( _transport != null )
+//            _transport.stop();
+        
+        if( _defaultRoot != null )
+            FileUtil.delete( _defaultRoot );
+        _defaultRoot = null;
     }
 
     public String[] getProtocols()
     {
         return _protocols;
     }
+
 }
diff --git a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryWriterM2.java b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryWriterM2.java
index e3957f1..d74fdc9 100644
--- a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryWriterM2.java
+++ b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RemoteRepositoryWriterM2.java
@@ -42,7 +42,6 @@
 import org.apache.maven.mercury.repository.api.RemoteRepository;
 import org.apache.maven.mercury.repository.api.Repository;
 import org.apache.maven.mercury.repository.api.RepositoryException;
-import org.apache.maven.mercury.repository.api.RepositoryGAMetadata;
 import org.apache.maven.mercury.repository.api.RepositoryGAVMetadata;
 import org.apache.maven.mercury.repository.api.RepositoryReader;
 import org.apache.maven.mercury.repository.api.RepositoryWriter;
@@ -127,6 +126,8 @@
   //---------------------------------------------------------------------------------------------------------------
   public void close()
   {
+      if( _transport != null )
+          _transport.stop();
   }
   //---------------------------------------------------------------------------------------------------------------
   public void writeArtifacts( Collection<Artifact> artifacts )
diff --git a/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RepositoryNonQualifiedArtifactException.java b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RepositoryNonQualifiedArtifactException.java
new file mode 100644
index 0000000..fe1f7d9
--- /dev/null
+++ b/mercury-repo/mercury-repo-remote-m2/src/main/java/org/apache/maven/mercury/repository/remote/m2/RepositoryNonQualifiedArtifactException.java
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.maven.mercury.repository.remote.m2;
+
+import org.apache.maven.mercury.repository.api.RepositoryException;
+
+
+/**
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class RepositoryNonQualifiedArtifactException
+    extends RepositoryException
+{
+    public RepositoryNonQualifiedArtifactException( String msg )
+    {
+        super( msg );
+    }
+}
diff --git a/mercury-repo/mercury-repo-virtual/pom.xml b/mercury-repo/mercury-repo-virtual/pom.xml
index e789748..f770161 100644
--- a/mercury-repo/mercury-repo-virtual/pom.xml
+++ b/mercury-repo/mercury-repo-virtual/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-repo</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-repo-virtual</artifactId>
@@ -96,7 +96,6 @@
     <dependency>
       <groupId>org.apache.maven.mercury</groupId>
       <artifactId>mercury-repo-remote-m2</artifactId>
-      <scope>test</scope>
     </dependency>
 
   </dependencies>
diff --git a/mercury-repo/mercury-repo-virtual/src/main/java/org/apache/maven/mercury/repository/virtual/VirtualRepositoryReader.java b/mercury-repo/mercury-repo-virtual/src/main/java/org/apache/maven/mercury/repository/virtual/VirtualRepositoryReader.java
index 8e428dd..dab6790 100644
--- a/mercury-repo/mercury-repo-virtual/src/main/java/org/apache/maven/mercury/repository/virtual/VirtualRepositoryReader.java
+++ b/mercury-repo/mercury-repo-virtual/src/main/java/org/apache/maven/mercury/repository/virtual/VirtualRepositoryReader.java
@@ -20,6 +20,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
@@ -29,16 +30,13 @@
 import java.util.TreeSet;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
 import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.Quality;
 import org.apache.maven.mercury.artifact.api.ArtifactListProcessor;
 import org.apache.maven.mercury.artifact.api.ArtifactListProcessorException;
 import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
 import org.apache.maven.mercury.artifact.version.MetadataVersionComparator;
-import org.apache.maven.mercury.artifact.version.VersionException;
-import org.apache.maven.mercury.artifact.version.VersionRange;
-import org.apache.maven.mercury.artifact.version.VersionRangeFactory;
+import org.apache.maven.mercury.builder.api.DependencyProcessor;
 import org.apache.maven.mercury.builder.api.MetadataReader;
 import org.apache.maven.mercury.builder.api.MetadataReaderException;
 import org.apache.maven.mercury.event.EventGenerator;
@@ -48,7 +46,7 @@
 import org.apache.maven.mercury.event.MercuryEventListener;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.LocalRepository;
 import org.apache.maven.mercury.repository.api.RemoteRepository;
@@ -58,6 +56,10 @@
 import org.apache.maven.mercury.repository.api.RepositoryReader;
 import org.apache.maven.mercury.repository.api.RepositoryWriter;
 import org.apache.maven.mercury.repository.cache.fs.MetadataCacheFs;
+import org.apache.maven.mercury.repository.metadata.MetadataException;
+import org.apache.maven.mercury.repository.remote.m2.RemoteRepositoryM2;
+import org.apache.maven.mercury.repository.remote.m2.RemoteRepositoryReaderM2;
+import org.apache.maven.mercury.transport.api.Server;
 import org.apache.maven.mercury.util.Util;
 import org.codehaus.plexus.lang.DefaultLanguage;
 import org.codehaus.plexus.lang.Language;
@@ -110,8 +112,10 @@
     private LocalRepository _localRepository;
 
     private RepositoryWriter _localRepositoryWriter;
+    
+    private RemoteRepositoryReaderM2 _idleReader;
 
-    RepositoryMetadataCache _mdCache;
+    private RepositoryMetadataCache _mdCache;
 
     private Map<String, ArtifactListProcessor> _processors;
 
@@ -266,11 +270,40 @@
 
             _repositoryReaders[i++] = rr;
         }
+        
+        try
+        {
+            _idleReader = (RemoteRepositoryReaderM2) new RemoteRepositoryM2( "http://localhost", DependencyProcessor.NULL_PROCESSOR ).getReader();
+        }
+        catch ( MalformedURLException e )
+        {
+            throw new RepositoryException( e );
+        }
+        
         _initialized = true;
     }
+    
+    /**
+     * close all readers is they are started
+     */
+    public void close()
+    {
+        if( ! _initialized )
+            return;
+        
+        try
+        {
+            for( RepositoryReader rr : _repositoryReaders )
+                rr.close();
+        }
+        finally
+        {
+            _initialized = false;
+        }
+    }
 
     // ----------------------------------------------------------------------------------------------------------------------------
-    public ArtifactBasicResults readVersions( Collection<ArtifactBasicMetadata> query )
+    public MetadataResults readVersions( Collection<ArtifactMetadata> query )
         throws IllegalArgumentException, RepositoryException
     {
         if ( query == null )
@@ -290,12 +323,12 @@
                 event = new GenericEvent( EventTypeEnum.virtualRepositoryReader, EVENT_READ_VERSIONS );
             }
 
-            ArtifactBasicResults res = null;
+            MetadataResults res = null;
             ArtifactListProcessor tp = _processors == null ? null : _processors.get( ArtifactListProcessor.FUNCTION_TP );
 
             GenericEvent eventRead = null;
 
-            List<ArtifactBasicMetadata> qList = new ArrayList<ArtifactBasicMetadata>( query.size() );
+            List<ArtifactMetadata> qList = new ArrayList<ArtifactMetadata>( query.size() );
             qList.addAll( query );
 
             for ( RepositoryReader rr : _repositoryReaders )
@@ -315,7 +348,7 @@
                                               rr.getRepository().getId() );
                     }
 
-                    ArtifactBasicResults repoRes = rr.readVersions( qList );
+                    MetadataResults repoRes = rr.readVersions( qList );
 
                     if ( repoRes != null && repoRes.hasExceptions() )
                     {
@@ -327,9 +360,9 @@
 
                     if ( repoRes != null && repoRes.hasResults() )
                     {
-                        for ( ArtifactBasicMetadata key : repoRes.getResults().keySet() )
+                        for ( ArtifactMetadata key : repoRes.getResults().keySet() )
                         {
-                            List<ArtifactBasicMetadata> rorRes = repoRes.getResult( key );
+                            List<ArtifactMetadata> rorRes = repoRes.getResult( key );
 
                             if ( tp != null )
                             {
@@ -350,14 +383,14 @@
                                 continue;
                             }
 
-                            for ( ArtifactBasicMetadata bmd : rorRes )
+                            for ( ArtifactMetadata bmd : rorRes )
                             {
                                 bmd.setTracker( rr );
                             }
 
                             if ( res == null )
                             {
-                                res = new ArtifactBasicResults( key, rorRes );
+                                res = new MetadataResults( key, rorRes );
                             }
                             else
                             {
@@ -426,32 +459,32 @@
         }
     }
 
-    private void processSingletons( ArtifactBasicResults res )
+    private void processSingletons( MetadataResults res )
     {
         if ( !res.hasResults() )
         {
             return;
         }
 
-        Map<ArtifactBasicMetadata, List<ArtifactBasicMetadata> > m = res.getResults();
+        Map<ArtifactMetadata, List<ArtifactMetadata> > m = res.getResults();
 
-        for ( ArtifactBasicMetadata key : m.keySet() )
+        for ( ArtifactMetadata key : m.keySet() )
         {
             processSingletons( key, res.getResult( key ) );
         }
     }
 
-    private void processSingletons( ArtifactBasicMetadata key, List<ArtifactBasicMetadata> res )
+    private void processSingletons( ArtifactMetadata key, List<ArtifactMetadata> res )
     {
         if ( Util.isEmpty( res ) || !DefaultArtifactVersion.isVirtual( key.getVersion() ) )
         {
             return;
         }
 
-        TreeSet<ArtifactBasicMetadata> ts = new TreeSet<ArtifactBasicMetadata>(
-                        new Comparator<ArtifactBasicMetadata>()
+        TreeSet<ArtifactMetadata> ts = new TreeSet<ArtifactMetadata>(
+                        new Comparator<ArtifactMetadata>()
                         {
-                            public int compare( ArtifactBasicMetadata o1, ArtifactBasicMetadata o2 )
+                            public int compare( ArtifactMetadata o1, ArtifactMetadata o2 )
                             {
                                   DefaultArtifactVersion av1 = new DefaultArtifactVersion( o1.getVersion() );
                                   DefaultArtifactVersion av2 = new DefaultArtifactVersion( o2.getVersion() );
@@ -463,7 +496,7 @@
                                                                               );
         ts.addAll( res );
 
-        ArtifactBasicMetadata single = ts.last();
+        ArtifactMetadata single = ts.last();
 
         res.clear();
 
@@ -471,7 +504,7 @@
     }
 
     //----------------------------------------------------------------------------------------------------------------------------
-    public ArtifactMetadata readDependencies( ArtifactBasicMetadata bmd )
+    public ArtifactMetadata readDependencies( ArtifactMetadata bmd )
         throws IllegalArgumentException, RepositoryException
     {
         if ( bmd == null )
@@ -491,7 +524,7 @@
 
             init();
 
-            List<ArtifactBasicMetadata> query = new ArrayList<ArtifactBasicMetadata>( 1 );
+            List<ArtifactMetadata> query = new ArrayList<ArtifactMetadata>( 1 );
             query.add( bmd );
 
             ArtifactMetadata md = new ArtifactMetadata( bmd );
@@ -519,7 +552,7 @@
                                               rr.getRepository().getId() );
                     }
 
-                    ArtifactBasicResults res = rr.readDependencies( query );
+                    MetadataResults res = rr.readDependencies( query );
 
                     if ( res != null )
                     {
@@ -581,13 +614,13 @@
     /**
      * split query into repository buckets
      */
-    private Map<RepositoryReader, List<ArtifactBasicMetadata>> sortByRepo( Collection<? extends ArtifactBasicMetadata> query )
+    private Map<RepositoryReader, List<ArtifactMetadata>> sortByRepo( Collection<? extends ArtifactMetadata> query )
     {
-        HashMap<RepositoryReader, List<ArtifactBasicMetadata>> res = null;
+        HashMap<RepositoryReader, List<ArtifactMetadata>> res = null;
 
-        List<ArtifactBasicMetadata> rejects = null;
+        List<ArtifactMetadata> rejects = null;
 
-        for ( ArtifactBasicMetadata bmd : query )
+        for ( ArtifactMetadata bmd : query )
         {
             Object tracker = bmd.getTracker();
 
@@ -598,14 +631,14 @@
 
                 if ( res == null )
                 {
-                    res = new HashMap<RepositoryReader, List<ArtifactBasicMetadata>>();
+                    res = new HashMap<RepositoryReader, List<ArtifactMetadata>>();
                 }
 
-                List<ArtifactBasicMetadata> rl = res.get( rr );
+                List<ArtifactMetadata> rl = res.get( rr );
 
                 if ( rl == null )
                 {
-                    rl = new ArrayList<ArtifactBasicMetadata>();
+                    rl = new ArrayList<ArtifactMetadata>();
                     res.put( rr, rl );
                 }
 
@@ -616,7 +649,7 @@
             {
                 if ( rejects == null )
                 {
-                    rejects = new ArrayList<ArtifactBasicMetadata>();
+                    rejects = new ArrayList<ArtifactMetadata>();
                 }
 
                 rejects.add( bmd );
@@ -627,7 +660,7 @@
         {
             if ( res == null )
             {
-                res = new HashMap<RepositoryReader, List<ArtifactBasicMetadata>>();
+                res = new HashMap<RepositoryReader, List<ArtifactMetadata>>();
             }
 
             res.put( RepositoryReader.NULL_READER, rejects );
@@ -637,7 +670,7 @@
     }
 
     // ----------------------------------------------------------------------------------------------------------------------------
-    public ArtifactResults readArtifacts( Collection<? extends ArtifactBasicMetadata> query )
+    public ArtifactResults readArtifactsNoBatch( Collection<? extends ArtifactMetadata> query )
         throws RepositoryException
     {
         GenericEvent event = null;
@@ -656,9 +689,9 @@
                 return res;
             }
 
-            Map<RepositoryReader, List<ArtifactBasicMetadata>> buckets = sortByRepo( query );
+            Map<RepositoryReader, List<ArtifactMetadata>> buckets = sortByRepo( query );
 
-            List<ArtifactBasicMetadata> leftovers = buckets == null ? null : buckets.get( RepositoryReader.NULL_READER );
+            List<ArtifactMetadata> leftovers = buckets == null ? null : buckets.get( RepositoryReader.NULL_READER );
 
             if ( buckets == null )
             {
@@ -690,7 +723,7 @@
                                               EVENT_READ_ARTIFACTS_FROM_REPO_QUALIFIED, repoId );
                     }
 
-                    List<ArtifactBasicMetadata> rrQuery = buckets.get( rr );
+                    List<ArtifactMetadata> rrQuery = buckets.get( rr );
 
                     ArtifactResults rrRes = rr.readArtifacts( rrQuery );
 
@@ -703,7 +736,7 @@
 
                     if ( rrRes.hasResults() )
                     {
-                        for ( ArtifactBasicMetadata bm : rrRes.getResults().keySet() )
+                        for ( ArtifactMetadata bm : rrRes.getResults().keySet() )
                         {
                             List<Artifact> al = rrRes.getResults( bm );
 
@@ -735,15 +768,15 @@
             // then process unqualified virtuals
             if ( !Util.isEmpty( leftovers ) )
             {
-                List<ArtifactBasicMetadata> virtuals = null;
+                List<ArtifactMetadata> virtuals = null;
 
-                for ( ArtifactBasicMetadata md : leftovers )
+                for ( ArtifactMetadata md : leftovers )
                 {
                     if ( DefaultArtifactVersion.isVirtual( md.getVersion() ) )
                     {
                         if ( virtuals == null )
                         {
-                            virtuals = new ArrayList<ArtifactBasicMetadata>();
+                            virtuals = new ArrayList<ArtifactMetadata>();
                         }
 
                         virtuals.add( md );
@@ -753,7 +786,7 @@
 
                 if ( virtuals != null )
                 {
-                    ArtifactBasicResults virtRes = readVersions( virtuals );
+                    MetadataResults virtRes = readVersions( virtuals );
 
                     leftovers.removeAll( virtuals );
 
@@ -763,11 +796,11 @@
                     {
                         if ( virtRes.hasResults() )
                         {
-                            Map<ArtifactBasicMetadata, ArtifactBasicMetadata> sMap = new HashMap<ArtifactBasicMetadata, ArtifactBasicMetadata>();
+                            Map<ArtifactMetadata, ArtifactMetadata> sMap = new HashMap<ArtifactMetadata, ArtifactMetadata>();
 
-                            for ( ArtifactBasicMetadata md : virtRes.getResults().keySet() )
+                            for ( ArtifactMetadata md : virtRes.getResults().keySet() )
                             {
-                                ArtifactBasicMetadata v = virtRes.getResult( md ).get( 0 );
+                                ArtifactMetadata v = virtRes.getResult( md ).get( 0 );
                                 virtuals.add( v );
                                 sMap.put( v, md );
                             }
@@ -778,10 +811,10 @@
                             {
                                 if ( ares.hasResults() )
                                 {
-                                    Map<ArtifactBasicMetadata, List<Artifact>> aresMap = ares.getResults();
+                                    Map<ArtifactMetadata, List<Artifact>> aresMap = ares.getResults();
 
                                     // remap
-                                    for ( ArtifactBasicMetadata md : aresMap.keySet() )
+                                    for ( ArtifactMetadata md : aresMap.keySet() )
                                     {
                                         res.add( sMap.get( md ), aresMap.get( md ).get( 0 ) );
                                     }
@@ -839,7 +872,255 @@
                         }
                         else if ( rrRes.hasResults() )
                         {
-                            for ( ArtifactBasicMetadata bm : rrRes.getResults().keySet() )
+                            for ( ArtifactMetadata bm : rrRes.getResults().keySet() )
+                            {
+                                List<Artifact> al = rrRes.getResults( bm );
+
+                                res.addAll( bm, al );
+
+                                leftovers.remove( bm );
+
+                                // don't write local artifacts back to the same repo
+                                if ( _localRepository != null && repoId.equals( _localRepository.getId() ) )
+                                {
+                                    continue;
+                                }
+
+                                if ( _localRepositoryWriter != null )
+                                {
+                                    _localRepositoryWriter.writeArtifacts( al );
+                                }
+
+                            }
+                        }
+                    }
+                    finally
+                    {
+                        if ( _eventManager != null )
+                        {
+                            eventRead.stop();
+                            _eventManager.fireEvent( eventRead );
+                        }
+                    }
+                }
+            }
+
+            return res;
+        }
+        finally
+        {
+            if ( _eventManager != null )
+            {
+                event.stop();
+                _eventManager.fireEvent( event );
+            }
+        }
+    }
+
+    // ----------------------------------------------------------------------------------------------------------------------------
+    public ArtifactResults readArtifacts( Collection<? extends ArtifactMetadata> query )
+        throws RepositoryException
+    {
+        GenericEvent event = null;
+
+        try
+        {
+            ArtifactResults res = null;
+
+            if ( _eventManager != null )
+            {
+                event = new GenericEvent( EventTypeEnum.virtualRepositoryReader, EVENT_READ_ARTIFACTS, "" );
+            }
+
+            if ( Util.isEmpty( query ) )
+            {
+                return res;
+            }
+            
+            int qSize = query.size();
+            
+            List<ArtifactMetadata> qualified = new ArrayList<ArtifactMetadata>( qSize );
+            
+            List<ArtifactMetadata> leftovers = new ArrayList<ArtifactMetadata>( qSize );
+            
+            for( ArtifactMetadata md : query )
+            {
+                Object tracker = md.getTracker();
+    
+                // do we know where this metadata came from ?
+                if ( tracker != null 
+                     && RemoteRepositoryReaderM2.class.isAssignableFrom( tracker.getClass() )
+                     && !md.isVirtual()
+                     && md.isSingleton()
+                )
+                    qualified.add( md );
+                else
+                    leftovers.add( md );
+            }
+
+            if ( qualified.isEmpty()  && leftovers.isEmpty() )
+            {
+                throw new RepositoryException( LANG.getMessage( "internal.error.sorting.query", query.toString() ) );
+            }
+
+            init();
+
+            res = new ArtifactResults();
+
+            // first read repository-qualified Artifacts
+            GenericEvent eventRead = null;
+
+            if( qualified.size() > 0 )
+            try
+            {
+                if ( _eventManager != null )
+                    eventRead = new GenericEvent( EventTypeEnum.virtualRepositoryReader, EVENT_READ_ARTIFACTS, ""+qualified );
+                
+                ArtifactResults rrRes = new ArtifactResults();
+                
+                _idleReader.readQualifiedArtifacts( qualified, rrRes );
+
+                if ( rrRes.hasExceptions() )
+                {
+                    throw new RepositoryException( LANG.getMessage( "error.reading.existing.artifact",
+                                                                     rrRes.getExceptions().toString(),
+                                                                     "multiple.server.internal.repo" ) );
+                }
+
+                if ( rrRes.hasResults() )
+                {
+                    for ( ArtifactMetadata bm : rrRes.getResults().keySet() )
+                    {
+                        List<Artifact> al = rrRes.getResults( bm );
+
+                        res.addAll( bm, al );
+
+                        if ( _localRepositoryWriter != null )
+                        {
+                            _localRepositoryWriter.writeArtifacts( al );
+                        }
+                    }
+                }
+            }
+            catch ( Exception e )
+            {
+                throw new RepositoryException( e );
+            }
+            finally
+            {
+                if ( _eventManager != null )
+                {
+                    eventRead.stop();
+                    _eventManager.fireEvent( eventRead );
+                }
+            }
+
+            // then process unqualified virtuals
+            if ( !Util.isEmpty( leftovers ) )
+            {
+                List<ArtifactMetadata> virtuals = null;
+
+                for ( ArtifactMetadata md : leftovers )
+                {
+                    if ( DefaultArtifactVersion.isVirtual( md.getVersion() ) )
+                    {
+                        if ( virtuals == null )
+                        {
+                            virtuals = new ArrayList<ArtifactMetadata>();
+                        }
+
+                        virtuals.add( md );
+                    }
+                }
+
+
+                if ( virtuals != null )
+                {
+                    MetadataResults virtRes = readVersions( virtuals );
+
+                    leftovers.removeAll( virtuals );
+
+                    virtuals.clear();
+
+                    if ( virtRes != null )
+                    {
+                        if ( virtRes.hasResults() )
+                        {
+                            Map<ArtifactMetadata, ArtifactMetadata> sMap = new HashMap<ArtifactMetadata, ArtifactMetadata>();
+
+                            for ( ArtifactMetadata md : virtRes.getResults().keySet() )
+                            {
+                                ArtifactMetadata v = virtRes.getResult( md ).get( 0 );
+                                virtuals.add( v );
+                                sMap.put( v, md );
+                            }
+
+                            ArtifactResults ares = readArtifactsNoBatch( virtuals );
+
+                            if ( ares != null )
+                            {
+                                if ( ares.hasResults() )
+                                {
+                                    Map<ArtifactMetadata, List<Artifact>> aresMap = ares.getResults();
+
+                                    // remap
+                                    for ( ArtifactMetadata md : aresMap.keySet() )
+                                    {
+                                        res.add( sMap.get( md ), aresMap.get( md ).get( 0 ) );
+                                    }
+                                }
+
+                                if ( ares.hasExceptions() )
+                                {
+                                    res.getExceptions().putAll( ares.getExceptions() );
+                                }
+                            }
+
+                            if ( virtRes.hasExceptions() )
+                            {
+                                res.addError( virtRes.getExceptions() );
+                            }
+                        }
+
+                        if ( virtRes.hasExceptions() )
+                        {
+                            res.addError( virtRes.getExceptions() );
+                        }
+                    }
+                }
+
+            }
+
+            // then search all repos for unqualified Artifacts
+            if ( !Util.isEmpty( leftovers ) )
+            {
+                for ( RepositoryReader rr : _repositoryReaders )
+                {
+                    if ( leftovers.isEmpty() )
+                    {
+                        break;
+                    }
+
+                    String repoId = rr.getRepository().getId();
+
+                    try
+                    {
+                        if ( _eventManager != null )
+                        {
+                            eventRead =
+                                new GenericEvent( EventTypeEnum.virtualRepositoryReader,
+                                                  EVENT_READ_ARTIFACTS_FROM_REPO_UNQUALIFIED, repoId );
+                        }
+
+                        ArtifactResults rrRes = rr.readArtifacts( leftovers );
+
+                        if ( rrRes.hasExceptions() )
+                        {
+                            res.addError( rrRes );
+                        }
+                        else if ( rrRes.hasResults() )
+                        {
+                            for ( ArtifactMetadata bm : rrRes.getResults().keySet() )
                             {
                                 List<Artifact> al = rrRes.getResults( bm );
 
@@ -887,13 +1168,13 @@
     // ----------------------------------------------------------------------------------------------------------------------------
     // MetadataReader implementation
     // ----------------------------------------------------------------------------------------------------------------------------
-    public byte[] readMetadata( ArtifactBasicMetadata bmd )
+    public byte[] readMetadata( ArtifactMetadata bmd )
         throws MetadataReaderException
     {
         return readMetadata( bmd, false );
     }
 
-    public byte[] readMetadata( ArtifactBasicMetadata bmd, boolean exempt  )
+    public byte[] readMetadata( ArtifactMetadata bmd, boolean exempt  )
         throws MetadataReaderException
     {
         if ( LOG.isDebugEnabled() )
@@ -909,13 +1190,13 @@
     // ----------------------------------------------------------------------------------------------------------------------------
     // MetadataReader implementation
     // ----------------------------------------------------------------------------------------------------------------------------
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type )
+    public byte[] readRawData( ArtifactMetadata bmd, String classifier, String type )
         throws MetadataReaderException
     {
         return readRawData( bmd, classifier, type, false );
     }
 
-    public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type, boolean exempt )
+    public byte[] readRawData( ArtifactMetadata bmd, String classifier, String type, boolean exempt )
         throws MetadataReaderException
     {
 
@@ -942,7 +1223,7 @@
                 event = new GenericEvent( EventTypeEnum.virtualRepositoryReader, EVENT_READ_RAW, eventTag );
             }
             
-            ArtifactBasicMetadata bmdQuery = bmd;
+            ArtifactMetadata bmdQuery = bmd;
 
             try
             {
@@ -963,9 +1244,9 @@
 
             if ( Quality.SNAPSHOT_QUALITY.equals( vq ) )
             {
-                List<ArtifactBasicMetadata> query = new ArrayList<ArtifactBasicMetadata>( 1 );
+                List<ArtifactMetadata> query = new ArrayList<ArtifactMetadata>( 1 );
                 
-                ArtifactBasicMetadata nBmd = new ArtifactBasicMetadata( bmd.toString() );
+                ArtifactMetadata nBmd = new ArtifactMetadata( bmd.toString() );
                 
                 if( !Util.isEmpty( type ))
                     nBmd.setType( type );
@@ -974,7 +1255,7 @@
 
                 try
                 {
-                    ArtifactBasicResults vRes = readVersions( query );
+                    MetadataResults vRes = readVersions( query );
                     if ( Util.isEmpty( vRes ) )
                     {
                         if ( LOG.isDebugEnabled() )
@@ -988,10 +1269,10 @@
 
                     if ( vRes.hasResults( nBmd ) )
                     {
-                        List<ArtifactBasicMetadata> versions = vRes.getResult( nBmd );
+                        List<ArtifactMetadata> versions = vRes.getResult( nBmd );
 
-                        TreeSet<ArtifactBasicMetadata> snapshots =
-                            new TreeSet<ArtifactBasicMetadata>( new MetadataVersionComparator() );
+                        TreeSet<ArtifactMetadata> snapshots =
+                            new TreeSet<ArtifactMetadata>( new MetadataVersionComparator() );
                         snapshots.addAll( versions );
 
                         bmdQuery = snapshots.last();
@@ -1073,7 +1354,11 @@
             }
         }
     }
-
+    // ----------------------------------------------------------------------------------------------------------------------------
+    public RepositoryMetadataCache getCache()
+    {
+        return _mdCache;
+    }
     // ----------------------------------------------------------------------------------------------------------------------------
     public void register( MercuryEventListener listener )
     {
diff --git a/mercury-repo/mercury-repo-virtual/src/test/java/org/apache/maven/mercury/repository/virtual/VirtualRepositoryReaderTest.java b/mercury-repo/mercury-repo-virtual/src/test/java/org/apache/maven/mercury/repository/virtual/VirtualRepositoryReaderTest.java
index 30849dd..9097ddf 100644
--- a/mercury-repo/mercury-repo-virtual/src/test/java/org/apache/maven/mercury/repository/virtual/VirtualRepositoryReaderTest.java
+++ b/mercury-repo/mercury-repo-virtual/src/test/java/org/apache/maven/mercury/repository/virtual/VirtualRepositoryReaderTest.java
@@ -27,12 +27,12 @@
 import junit.framework.TestCase;
 
 import org.apache.maven.mercury.artifact.Artifact;
-import org.apache.maven.mercury.artifact.ArtifactBasicMetadata;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
 import org.apache.maven.mercury.artifact.DefaultArtifact;
 import org.apache.maven.mercury.event.MercuryEvent;
 import org.apache.maven.mercury.event.MercuryEventListener;
 import org.apache.maven.mercury.event.MercuryEvent.EventMask;
-import org.apache.maven.mercury.repository.api.ArtifactBasicResults;
+import org.apache.maven.mercury.repository.api.MetadataResults;
 import org.apache.maven.mercury.repository.api.ArtifactResults;
 import org.apache.maven.mercury.repository.api.LocalRepository;
 import org.apache.maven.mercury.repository.api.RemoteRepository;
@@ -148,8 +148,8 @@
     public void testReadSnapshot()
         throws Exception
     {
-        ArtifactBasicMetadata bmd = new ArtifactBasicMetadata( _artifactCoordSn );
-        List<ArtifactBasicMetadata> q = new ArrayList<ArtifactBasicMetadata>();
+        ArtifactMetadata bmd = new ArtifactMetadata( _artifactCoordSn );
+        List<ArtifactMetadata> q = new ArrayList<ArtifactMetadata>();
         q.add( bmd );
 
         ArtifactResults res = _vr.readArtifacts( q );
@@ -162,7 +162,7 @@
 
         assertTrue( res.hasResults( bmd ) );
 
-        Map<ArtifactBasicMetadata, List<Artifact>> m = res.getResults();
+        Map<ArtifactMetadata, List<Artifact>> m = res.getResults();
 
         List<Artifact> al = m.get( bmd );
 
@@ -191,7 +191,7 @@
     public void testWrite()
         throws Exception
     {
-        Artifact a = new DefaultArtifact( new ArtifactBasicMetadata( "a:a:1.0:text:txt" ) );
+        Artifact a = new DefaultArtifact( new ArtifactMetadata( "a:a:1.0:text:txt" ) );
         File bin = File.createTempFile( "vr-", "-test.txt" );
         bin.deleteOnExit();
         FileUtil.writeRawData( bin, "test" );
@@ -213,14 +213,14 @@
     public void testReadRelease()
         throws Exception
     {
-        ArtifactBasicMetadata bmd = new ArtifactBasicMetadata( _artifactCoordRelease );
-        List<ArtifactBasicMetadata> q = new ArrayList<ArtifactBasicMetadata>();
+        ArtifactMetadata bmd = new ArtifactMetadata( _artifactCoordRelease );
+        List<ArtifactMetadata> q = new ArrayList<ArtifactMetadata>();
         q.add( bmd );
 
         Listener l = new Listener();
         _vr.register( l );
 
-        ArtifactBasicResults res = _vr.readVersions( q );
+        MetadataResults res = _vr.readVersions( q );
 
         assertNotNull( res );
 
diff --git a/mercury-repo/pom.xml b/mercury-repo/pom.xml
index 72b2f1e..0a95469 100644
--- a/mercury-repo/pom.xml
+++ b/mercury-repo/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-repo</artifactId>
diff --git a/mercury-transport/mercury-transport-api/pom.xml b/mercury-transport/mercury-transport-api/pom.xml
index 16f0e1b..02a7c54 100644
--- a/mercury-transport/mercury-transport-api/pom.xml
+++ b/mercury-transport/mercury-transport-api/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-transport</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-transport-api</artifactId>
diff --git a/mercury-transport/mercury-transport-http/pom.xml b/mercury-transport/mercury-transport-http/pom.xml
index 781d9e6..569a6e2 100644
--- a/mercury-transport/mercury-transport-http/pom.xml
+++ b/mercury-transport/mercury-transport-http/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury-transport</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-transport-http</artifactId>
diff --git a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/HandshakeExchange.java b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/HandshakeExchange.java
index 5f69074..75700bf 100644
--- a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/HandshakeExchange.java
+++ b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/HandshakeExchange.java
@@ -21,8 +21,6 @@
 
 import java.util.Map;
 
-import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
-
 import org.mortbay.io.Buffer;
 import org.mortbay.jetty.client.HttpClient;
 import org.mortbay.jetty.client.HttpExchange;
diff --git a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/DefaultDeployer.java b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/DefaultDeployer.java
index 07ea68f..3f09ead 100644
--- a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/DefaultDeployer.java
+++ b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/DefaultDeployer.java
@@ -35,6 +35,8 @@
 import org.apache.maven.mercury.crypto.api.StreamObserverException;
 import org.apache.maven.mercury.crypto.api.StreamObserverFactory;
 import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
+import org.apache.maven.mercury.logging.IMercuryLogger;
+import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.spi.http.client.DestinationRealmResolver;
 import org.apache.maven.mercury.spi.http.client.FileExchange;
 import org.apache.maven.mercury.spi.http.client.HandshakeExchange;
@@ -51,6 +53,8 @@
  */
 public class DefaultDeployer implements Deployer
 {
+    private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( DefaultDeployer.class );
+    
     private HttpClient _httpClient;
     private BatchIdGenerator _idGenerator;
     private Set<Server> _servers = new HashSet<Server>();
@@ -84,7 +88,7 @@
         _httpClient = client;
         try
         {
-            if ( _httpClient.isStarted() )
+            if ( !_httpClient.isStarted() )
             {
                 _httpClient.start();
             }
@@ -358,5 +362,24 @@
         }
         return observers;
     }
+    
+    public void stop()
+    {
+        if( _httpClient == null )
+            return;
+        
+        if( _httpClient.isStopped() || _httpClient.isStopping() )
+            return;
+        
+        try
+        {
+            _httpClient.stop();
+        }
+        catch ( Exception e )
+        {
+            LOG.error( e.getMessage() );
+        }
+            
+    }
 
 }
diff --git a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/Deployer.java b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/Deployer.java
index 2ac26ab..d296a6f 100644
--- a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/Deployer.java
+++ b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/Deployer.java
@@ -36,4 +36,10 @@
      * has occurred.
      */
     void deploy( DeployRequest request, DeployCallback callback );
+    
+    /**
+     * stop and release all resources
+     * @throws Exception 
+     */
+    void stop();
 }
diff --git a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/FilePutExchange.java b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/FilePutExchange.java
index 8a8eff7..eb116fe 100644
--- a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/FilePutExchange.java
+++ b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/deploy/FilePutExchange.java
@@ -27,13 +27,12 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
-
 import org.apache.maven.mercury.crypto.api.StreamObserver;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.spi.http.client.FileExchange;
 import org.apache.maven.mercury.spi.http.client.HttpClientException;
+import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
 import org.apache.maven.mercury.spi.http.client.ObservableInputStream;
 import org.apache.maven.mercury.transport.api.Binding;
 import org.apache.maven.mercury.transport.api.Server;
diff --git a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java
index 5a79bff..ac41b76 100644
--- a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java
+++ b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/DefaultRetriever.java
@@ -34,6 +34,8 @@
 import org.apache.maven.mercury.crypto.api.StreamObserverFactory;
 import org.apache.maven.mercury.crypto.api.StreamVerifierException;
 import org.apache.maven.mercury.crypto.api.StreamVerifierFactory;
+import org.apache.maven.mercury.logging.IMercuryLogger;
+import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.spi.http.client.DestinationRealmResolver;
 import org.apache.maven.mercury.spi.http.client.HttpClientException;
 import org.apache.maven.mercury.transport.api.Binding;
@@ -42,9 +44,10 @@
 
 public class DefaultRetriever implements Retriever
 {
+    private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( DefaultRetriever.class );
+    
     private HttpClient _httpClient;
     private Set<Server> _servers = new HashSet<Server>();
-    
 
     public DefaultRetriever()
         throws HttpClientException
@@ -55,7 +58,6 @@
         try
         {
             //TODO: What are all the reasons that the httpclient couldn't start up correctly?
-            
             _httpClient.start();
         }
         catch ( Exception e )
@@ -71,7 +73,7 @@
         _httpClient = client;
         try
         {
-            if ( _httpClient.isStarted() )
+            if ( !_httpClient.isStarted() )
             {
                 _httpClient.start();
             }
@@ -337,5 +339,24 @@
         }
         return observers;
     }
+    
+    public void stop()
+    {
+        if( _httpClient == null )
+            return;
+        
+        if( _httpClient.isStopped() || _httpClient.isStopping() )
+            return;
+        
+        try
+        {
+            _httpClient.stop();
+        }
+        catch ( Exception e )
+        {
+            LOG.error( e.getMessage() );
+        }
+            
+    }
 
 }
diff --git a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java
index 8d2ea2e..0030eed 100644
--- a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java
+++ b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/FileGetExchange.java
@@ -28,13 +28,12 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
-
 import org.apache.maven.mercury.crypto.api.StreamObserver;
 import org.apache.maven.mercury.logging.IMercuryLogger;
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.spi.http.client.FileExchange;
 import org.apache.maven.mercury.spi.http.client.HttpClientException;
+import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
 import org.apache.maven.mercury.spi.http.client.ObservableOutputStream;
 import org.apache.maven.mercury.transport.api.Binding;
 import org.apache.maven.mercury.transport.api.Server;
diff --git a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java
index a9accc5..8e3b7fe 100644
--- a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java
+++ b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/RetrievalTarget.java
@@ -30,8 +30,6 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
-
 import org.apache.maven.mercury.crypto.api.StreamObserver;
 import org.apache.maven.mercury.crypto.api.StreamVerifier;
 import org.apache.maven.mercury.crypto.api.StreamVerifierException;
@@ -39,6 +37,7 @@
 import org.apache.maven.mercury.logging.MercuryLoggerManager;
 import org.apache.maven.mercury.spi.http.client.FileExchange;
 import org.apache.maven.mercury.spi.http.client.HttpClientException;
+import org.apache.maven.mercury.spi.http.client.HttpServletResponse;
 import org.apache.maven.mercury.spi.http.client.SecureSender;
 import org.apache.maven.mercury.spi.http.validate.Validator;
 import org.apache.maven.mercury.transport.api.Binding;
diff --git a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java
index b5f6a6a..3c0e792 100644
--- a/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java
+++ b/mercury-transport/mercury-transport-http/src/main/java/org/apache/maven/mercury/spi/http/client/retrieve/Retriever.java
@@ -48,4 +48,10 @@
      * @param callback
      */
     void retrieve( RetrievalRequest request, RetrievalCallback callback );
+    
+    /**
+     * stop and release all resources
+     * @throws Exception 
+     */
+    void stop();
 }
diff --git a/mercury-transport/pom.xml b/mercury-transport/pom.xml
index 9c417d2..2594b4e 100644
--- a/mercury-transport/pom.xml
+++ b/mercury-transport/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-transport</artifactId>
diff --git a/mercury-util/pom.xml b/mercury-util/pom.xml
index 7bfbd2b..617f204 100644
--- a/mercury-util/pom.xml
+++ b/mercury-util/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-util</artifactId>
@@ -52,6 +52,8 @@
       <artifactId>bcpg-jdk15</artifactId>
       <optional>true</optional>
     </dependency>
+<!-- 
+ -->
 
     <dependency>
       <groupId>org.apache.maven.mercury</groupId>
@@ -63,20 +65,6 @@
       <artifactId>commons-cli</artifactId>
     </dependency>
 
-    <dependency>
-      <groupId>bouncycastle</groupId>
-      <artifactId>bcprov-jdk15</artifactId>
-      <scope>test</scope>
-      <optional>false</optional>
-    </dependency>
-
-    <dependency>
-      <groupId>bouncycastle</groupId>
-      <artifactId>bcpg-jdk15</artifactId>
-      <scope>test</scope>
-      <optional>false</optional>
-    </dependency>
-
   </dependencies>
 
   <build>
diff --git a/mercury-util/src/main/java/org/apache/maven/mercury/util/TimeUtil.java b/mercury-util/src/main/java/org/apache/maven/mercury/util/TimeUtil.java
index eea76aa..96ef356 100644
--- a/mercury-util/src/main/java/org/apache/maven/mercury/util/TimeUtil.java
+++ b/mercury-util/src/main/java/org/apache/maven/mercury/util/TimeUtil.java
@@ -22,83 +22,90 @@
 import java.util.Date;
 
 /**
- *
- *
  * @author Oleg Gusakov
  * @version $Id$
- *
  */
 public class TimeUtil
 {
-  public static final java.util.TimeZone TS_TZ = java.util.TimeZone.getTimeZone( "UTC" );
-  public static final java.text.DateFormat TS_FORMAT = new java.text.SimpleDateFormat( "yyyyMMddHHmmss" );
-  
-  static
-  {
-    TS_FORMAT.setTimeZone( TS_TZ );
-  }
+    public static final java.util.TimeZone TS_TZ = java.util.TimeZone.getTimeZone( "UTC" );
 
-  /**
-   * 
-   * @return current UTC timestamp by yyyyMMddHHmmss mask
-   */
-  public static String getUTCTimestamp( )
-  {
-    return getUTCTimestamp( new Date() );
-  }
+    public static final java.text.DateFormat TS_FORMAT = new java.text.SimpleDateFormat( "yyyyMMddHHmmss" );
 
-  /**
-   * 
-   * @return current UTC timestamp by yyyyMMddHHmmss mask as a long int
-   */
-  public static long getUTCTimestampAsLong( )
-  {
-    return Long.parseLong( getUTCTimestamp( new Date() ) );
-  }
+    static
+    {
+        TS_FORMAT.setTimeZone( TS_TZ );
+    }
 
-  /**
-   * 
-   * @return current UTC timestamp by yyyyMMddHHmmss mask as a long int
-   */
-  public static long getUTCTimestampAsMillis( )
-  {
-    return Long.parseLong( getUTCTimestamp( new Date() ) );
-  }
-  /**
-   * 
-   * @param date
-   * @return current date converted to UTC timestamp by yyyyMMddHHmmss mask
-   */
-  public static String getUTCTimestamp( Date date )
-  {
-      return TS_FORMAT.format( date );
-  }
+    /**
+     * @return current UTC timestamp by yyyyMMddHHmmss mask
+     */
+    public static String getUTCTimestamp()
+    {
+        return getUTCTimestamp( new Date() );
+    }
 
-  /**
-   * convert timestamp to millis
-   * 
-   * @param ts timestamp to convert. Presumed to be a long of form yyyyMMddHHmmss
-   * @return millis, corresponding to the supplied TS
-   * @throws ParseException is long does not follow the format
-   */
-  public static long toMillis( long ts )
-  throws ParseException
-  {
-    return toMillis(  ""+ts );
-  }
+    /**
+     * @return current UTC timestamp by yyyyMMddHHmmss mask as a long int
+     */
+    public static long getUTCTimestampAsLong()
+    {
+        return Long.parseLong( getUTCTimestamp( new Date() ) );
+    }
 
-  /**
-   * convert timestamp to millis
-   * 
-   * @param ts timestamp to convert. Presumed to be a string of form yyyyMMddHHmmss
-   * @return millis, corresponding to the supplied TS
-   * @throws ParseException is long does not follow the format
-   */
-  public static long toMillis( String ts )
-  throws ParseException
-  {
-    Date dts =TS_FORMAT.parse( ts );
-    
-    return dts.getTime();
-  }
+    /**
+     * @return current UTC timestamp by yyyyMMddHHmmss mask as a long int
+     */
+    public static long getUTCTimestampAsMillis()
+    {
+        return Long.parseLong( getUTCTimestamp( new Date() ) );
+    }
+
+    /**
+     * @param date
+     * @return current date converted to UTC timestamp by yyyyMMddHHmmss mask
+     */
+    public static String getUTCTimestamp( Date date )
+    {
+        return TS_FORMAT.format( date );
+    }
+
+    /**
+     * convert timestamp to millis
+     * 
+     * @param ts timestamp to convert. Presumed to be a long of form yyyyMMddHHmmss
+     * @return millis, corresponding to the supplied TS
+     * @throws ParseException is long does not follow the format
+     */
+    public static long toMillis( long ts )
+        throws ParseException
+    {
+        return toMillis( "" + ts );
+    }
+
+    /**
+     * convert timestamp to millis
+     * 
+     * @param ts timestamp to convert. Presumed to be a string of form yyyyMMddHHmmss
+     * @return millis, corresponding to the supplied TS
+     * @throws ParseException is long does not follow the format
+     */
+    public static long toMillis( String ts )
+        throws ParseException
+    {
+        Date dts = TS_FORMAT.parse( ts );
+
+        return dts.getTime();
+    }
+
+    public static void main( String[] args ) throws Exception
+    {
+        if( args == null || args.length < 0 )
+            return;
+        
+        if( "-t".equals( args[0] ) )
+        {
+            System.out.println( args[1]+" => " + new Date( toMillis( args[1] ) ) ) ;
+            return;
+        }
+    }
 }
diff --git a/mercury-util/src/main/java/org/apache/maven/mercury/util/Util.java b/mercury-util/src/main/java/org/apache/maven/mercury/util/Util.java
index 2779857..3d17604 100644
--- a/mercury-util/src/main/java/org/apache/maven/mercury/util/Util.java
+++ b/mercury-util/src/main/java/org/apache/maven/mercury/util/Util.java
@@ -20,8 +20,11 @@
 
 import java.io.File;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Map;
 
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Configurable;
+
 /**
  * general utility helpers
  *
@@ -87,4 +90,17 @@
        
        return (int)(Math.round( sz / 1024.))+" kb";
    }
+   
+   public static Map<String,Object> mapOf( Object [][] entries )
+   {
+       if( entries == null )
+           return null;
+       
+       Map<String,Object> map = new HashMap<String, Object>( entries.length );
+       
+       for( Object [] kv : entries )
+           map.put( (String)kv[0], kv[1] );
+       
+       return map;
+   }
 }
diff --git a/mercury-wagon/pom.xml b/mercury-wagon/pom.xml
index 6f874ca..2a3f3a6 100644
--- a/mercury-wagon/pom.xml
+++ b/mercury-wagon/pom.xml
@@ -23,7 +23,7 @@
   <parent>
     <groupId>org.apache.maven.mercury</groupId>
     <artifactId>mercury</artifactId>
-    <version>1.0-alpha-6-SNAPSHOT</version>
+    <version>1.0-alpha-6</version>
   </parent>
 
   <artifactId>mercury-wagon</artifactId>
@@ -61,6 +61,17 @@
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
     </dependency>
+    <dependency>
+      <groupId>bouncycastle</groupId>
+      <artifactId>bcprov-jdk15</artifactId>
+      <optional>true</optional>
+    </dependency>
+
+    <dependency>
+      <groupId>bouncycastle</groupId>
+      <artifactId>bcpg-jdk15</artifactId>
+      <optional>true</optional>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/pom.xml b/pom.xml
index 068f2a8..47a515b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
 
   <groupId>org.apache.maven.mercury</groupId>
   <artifactId>mercury</artifactId>
-  <version>1.0-alpha-6-SNAPSHOT</version>
+  <version>1.0-alpha-6</version>
   <packaging>pom</packaging>
 
   <name>Mercury</name>
@@ -65,6 +65,10 @@
     <module>mercury-logging</module>
     <module>mercury-plexus</module>
     <module>mercury-wagon</module>
+<!-- 
+    <module>mercury-it</module>
+-->
+
   </modules>
 
   <properties>
@@ -78,16 +82,18 @@
     <plexus.utils.version>1.5.5</plexus.utils.version>
     <plexus.lang.version>1.1</plexus.lang.version>
 
+    <plexus.spice.model.builder.version>1.8</plexus.spice.model.builder.version>
+
     <emma4it.plugin.version>1.0</emma4it.plugin.version>
 
     <commons.digester.version>1.8</commons.digester.version>
     <commons.cli.version>1.1</commons.cli.version>
 
-    <jetty.version>6.1.15.rc2</jetty.version>
-    <jetty.client.version>6.1.15.rc2</jetty.client.version>
+    <jetty.version>6.1.15</jetty.version>
+    <jetty.client.version>6.1.15</jetty.client.version>
     <jetty.servlet.api.version>6.1.14</jetty.servlet.api.version>
-    <jetty.util5.version>6.1.15.rc2</jetty.util5.version>
-    <jetty.servlet.tester.version>6.1.15.rc2</jetty.servlet.tester.version>
+    <jetty.util5.version>6.1.15</jetty.util5.version>
+    <jetty.servlet.tester.version>6.1.15</jetty.servlet.tester.version>
 
     <junit.version>3.8.1</junit.version>
 
@@ -95,8 +101,12 @@
     <sat4j.version>2.0.4</sat4j.version>
     <ant.version>1.7.1</ant.version>
 
-    <!-- maven version: non-modules only !! Never use in Mercury modules!! -->
+    <!-- 
+           maven version: non-modules only !!
+           Never use in Mercury modules because Mercury does not depend on Maven 
+    -->
     <maven.version>3.0-SNAPSHOT</maven.version>
+    <modello.version>1.0.1</modello.version>
 
     <!-- mercury-wagon -->
     <wagon.provider.api.version>1.0-beta-4</wagon.provider.api.version>
@@ -104,9 +114,9 @@
   </properties>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/maven/mercury/trunk/</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/mercury/trunk/</developerConnection>
-    <url>http://svn.apache.org/viewvc/maven/mercury/trunk/</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/maven/mercury/tags/mercury-1.0-alpha-6</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/mercury/tags/mercury-1.0-alpha-6</developerConnection>
+    <url>http://svn.apache.org/viewvc/maven/mercury/tags/mercury-1.0-alpha-6</url>
   </scm>
 
   <issueManagement>
@@ -265,6 +275,12 @@
         <artifactId>plexus-component-metadata</artifactId>
         <version>${plexus.component.metadata.version}</version>
       </dependency>
+      
+      <dependency>
+        <groupId>org.sonatype.spice</groupId>
+        <artifactId>model-builder</artifactId>
+        <version>${plexus.spice.model.builder.version}</version>
+      </dependency>
 
       <!-- Mercury deps -->
       <dependency>
@@ -498,6 +514,11 @@
             </execution>
           </executions>
         </plugin>
+        <plugin>
+          <groupId>org.codehaus.modello</groupId>
+          <artifactId>modello-maven-plugin</artifactId>
+          <version>1.0.1</version>
+        </plugin>
       </plugins>
     </pluginManagement>
 
diff --git a/release.notes.txt b/release.notes.txt
index e377728..4f15be0 100644
--- a/release.notes.txt
+++ b/release.notes.txt
@@ -1,3 +1,20 @@
+=================================================================================
+Release 1.0.0-alpha-6: 2009-04-07
+
+Iterative alpha release. Major fixes:
+- # of dependencies - less'n 64 were ordered correctly the rest used to be volatile
+- Mercury-ant tasks is succesfully used to bootstrap build Maven3
+- bad/missing repository metadata is worked around in most cases
+
+We solved 7 issues:
+http://jira.codehaus.org/browse/MERCURY/fixforversion/14964
+
+Staging repo:
+https://repository.apache.org/content/repositories/maven-staging-4630e65601be12/
+
+Guide to testing staged releases:
+http://maven.apache.org/guides/development/guide-testing-releases.html
+=================================================================================
 Release 1.0.0-alpha-3: 2009-01-18
 
 7 issues resolved. Main driver for this release - maven-3.0-alpha-2 prep.