You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by og...@apache.org on 2009/04/23 00:57:04 UTC

svn commit: r767705 [9/31] - in /maven/mercury/trunk/mercury-core: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/maven/ src/main/java/org/apache/maven/mercury/ src/main/java/org/apache/maven/merc...

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlat.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlat.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlat.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlat.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,340 @@
+/**
+ *  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.local.flat;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+
+import org.apache.maven.mercury.artifact.Artifact;
+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.repository.api.AbstractRepository;
+import org.apache.maven.mercury.repository.api.AbstractRepositoryWriter;
+import org.apache.maven.mercury.repository.api.LocalRepository;
+import org.apache.maven.mercury.repository.api.Repository;
+import org.apache.maven.mercury.repository.api.RepositoryException;
+import org.apache.maven.mercury.repository.api.RepositoryWriter;
+import org.apache.maven.mercury.transport.api.Server;
+import org.apache.maven.mercury.util.FileLockBundle;
+import org.apache.maven.mercury.util.FileUtil;
+import org.apache.maven.mercury.util.Util;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+public class LocalRepositoryWriterFlat
+extends AbstractRepositoryWriter
+implements RepositoryWriter
+{
+  public static final String SYSTEM_PROPERTY_PARALLEL_WORKERS = "mercury.local.repo.workers";
+  public static final int  PARALLEL_WORKERS = Integer.parseInt( System.getProperty( SYSTEM_PROPERTY_PARALLEL_WORKERS, "4" ) );
+  
+  public static final long SLEEP_FOR_WORKERS_TICK = 20l;
+
+  public static final String SYSTEM_PROPERTY_SLEEP_FOR_LOCK = "mercury.local.lock.wait.millis";
+  public static final long SLEEP_FOR_LOCK = Long.parseLong(  System.getProperty( SYSTEM_PROPERTY_SLEEP_FOR_LOCK, "5000" ) );
+  
+  public static final long SLEEP_FOR_LOCK_TICK = 5l;
+
+  private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( LocalRepositoryWriterFlat.class ); 
+  private static final Language LANG = new DefaultLanguage( LocalRepositoryWriterFlat.class );
+  //---------------------------------------------------------------------------------------------------------------
+  private static final String [] _protocols = new String [] { "file" };
+  
+  private final LocalRepository _repo;
+  private final File _repoDir;
+  private final ArtifactQueue _aq;
+
+  private static final ArifactWriteData LAST_ARTIFACT = new ArifactWriteData( null, null );
+  
+  //---------------------------------------------------------------------------------------------------------------
+  public LocalRepositoryWriterFlat( LocalRepository repo )
+  {
+    if( repo == null )
+      throw new IllegalArgumentException("localRepo cannot be null");
+    
+    _repoDir = repo.getDirectory();
+    if( _repoDir == null )
+      throw new IllegalArgumentException("localRepo directory cannot be null");
+    
+    if( !_repoDir.exists() )
+      throw new IllegalArgumentException("localRepo directory \""+_repoDir.getAbsolutePath()+"\" should exist");
+
+    _repo = repo;
+    _aq = null;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  private LocalRepositoryWriterFlat( LocalRepository repo, File repoDir, ArtifactQueue aq )
+  {
+    _repo = repo;
+    _repoDir = repoDir;
+    _aq = aq;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public Repository getRepository()
+  {
+    return _repo;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public boolean canHandle( String protocol )
+  {
+    return AbstractRepository.DEFAULT_LOCAL_READ_PROTOCOL.equals( protocol );
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public String[] getProtocols()
+  {
+    return _protocols;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public void close()
+  {
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public void writeArtifacts( Collection<Artifact> artifacts )
+  throws RepositoryException
+  {
+    if( artifacts == null || artifacts.size() < 1 )
+      return;
+    
+    int nWorkers = PARALLEL_WORKERS;
+    if( artifacts.size() < nWorkers )
+      nWorkers = artifacts.size();
+    
+    ArtifactQueue aq = new ArtifactQueue();
+    LocalRepositoryWriterFlat [] workers = new LocalRepositoryWriterFlat[ nWorkers ];
+    
+    for( int i=0; i<nWorkers; i++ )
+      workers[ i ] = new LocalRepositoryWriterFlat( _repo, _repoDir, aq );
+    
+    for( Artifact artifact : artifacts )
+    {
+      Set<StreamVerifierFactory> vFacs = null;
+      Server server = _repo.getServer();
+      if( server != null && server.hasWriterStreamVerifierFactories() )
+        vFacs = server.getWriterStreamVerifierFactories();
+      
+      if( vFacs == null ) // let it be empty, but not null
+        vFacs = new HashSet<StreamVerifierFactory>(1);
+
+      aq.addArtifact( new ArifactWriteData( artifact, vFacs ) );
+    }
+    aq.addArtifact( LAST_ARTIFACT );
+
+    for( int i=0; i<nWorkers; i++ )
+      workers[ i ].start();
+    
+    boolean alive = true;
+    while( alive )
+    {
+      alive = false;
+      for( int i=0; i<nWorkers; i++ )
+        if( workers[ i ].isAlive() )
+        {
+          alive = true;
+          try { sleep( SLEEP_FOR_WORKERS_TICK ); } catch( InterruptedException ie ) {}
+        }
+    }
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  /* (non-Javadoc)
+   * @see java.lang.Thread#run()
+   */
+  @Override
+  public void run()
+  {
+    try
+    {
+      for(;;)
+      {
+        ArifactWriteData awd = _aq.getArtifact();
+
+        if( awd == null || awd.artifact == null )
+            break;
+        
+        writeArtifact( awd.artifact, awd.vFacs );
+      }
+    }
+    catch (InterruptedException e)
+    {
+    }
+    catch( RepositoryException e )
+    {
+      throw new RuntimeException(e);
+    }
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public void writeArtifact( final Artifact artifact, final Set<StreamVerifierFactory> vFacs )
+      throws RepositoryException
+  {
+    if( artifact == null )
+      return;
+    
+    boolean isPom = "pom".equals( artifact.getType() );
+    
+    byte [] pomBlob = artifact.getPomBlob();
+    boolean hasPomBlob = pomBlob != null && pomBlob.length > 0;
+    
+    InputStream in = artifact.getStream();
+    if( in == null )
+    {
+      File aFile = artifact.getFile();
+      if( aFile == null && !isPom )
+      {
+        throw new RepositoryException( LANG.getMessage( "artifact.no.stream", artifact.toString() ) );
+      }
+
+      try
+      {
+        in = new FileInputStream( aFile );
+      }
+      catch( FileNotFoundException e )
+      {
+        if( !isPom )
+          throw new RepositoryException( e );
+      }
+    }
+
+    String relGroupPath = ((LocalRepositoryFlat)_repo).isCreateGroupFolders() ? artifact.getGroupId() : "";
+    String versionPath = _repoDir.getAbsolutePath() + (Util.isEmpty( relGroupPath ) ? "" : "/"+relGroupPath);
+    
+    String lockDir = null;
+    FileLockBundle fLock = null;
+
+    try
+    {
+      
+      if( isPom )
+      {
+        if( in == null && !hasPomBlob )
+          throw new RepositoryException( LANG.getMessage( "pom.artifact.no.stream", artifact.toString() ) );
+        
+        if( in != null )
+        {
+          byte [] pomBlobBytes = FileUtil.readRawData( in );
+          hasPomBlob = pomBlobBytes != null && pomBlobBytes.length > 0;
+          if( hasPomBlob )
+            pomBlob = pomBlobBytes;
+        }
+      }
+
+      // create folders
+      lockDir = versionPath;
+
+      File gav = new File( lockDir );
+      gav.mkdirs();
+
+      fLock = FileUtil.lockDir( lockDir, SLEEP_FOR_LOCK, SLEEP_FOR_LOCK_TICK );
+      if( fLock == null )
+        throw new RepositoryException( LANG.getMessage( "cannot.lock.gav", lockDir, ""+SLEEP_FOR_LOCK ) );
+
+      String fName = versionPath+'/'+artifact.getBaseName()+'.'+artifact.getType();
+      
+      if( !isPom ) // first - take care of the binary
+        FileUtil.writeAndSign( fName, in, vFacs );
+
+      // if classier - nothing else to do :)
+      if( artifact.hasClassifier() )
+        return;
+      
+      if( ((LocalRepositoryFlat)_repo).isCreatePoms() && hasPomBlob )
+      {
+        FileUtil.writeAndSign( versionPath
+                              +'/'+artifact.getArtifactId()+'-'+artifact.getVersion()+".pom", pomBlob, vFacs
+                              );
+      }
+        
+    }
+    catch( Exception e )
+    {
+      throw new RepositoryException( e );
+    }
+    finally
+    {
+      if( fLock != null )
+        fLock.release();
+            if ( in != null )
+            {
+                try
+                {
+                    in.close();
+                }
+                catch ( IOException e )
+                {
+                    // ignore, tried our best to clean up
+                }
+            }
+    }
+    
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  //---------------------------------------------------------------------------------------------------------------
+}
+//=================================================================================================================
+class ArifactWriteData
+{
+  Artifact artifact;
+  Set<StreamVerifierFactory> vFacs;
+  
+  public ArifactWriteData(Artifact artifact, Set<StreamVerifierFactory> vFacs)
+  {
+    this.artifact = artifact;
+    this.vFacs = vFacs;
+  }
+}
+//=================================================================================================================
+class ArtifactQueue
+{
+  LinkedList<ArifactWriteData> queue = new LinkedList<ArifactWriteData>();
+  boolean empty = false;
+  
+  public synchronized void addArtifact( ArifactWriteData awd )
+  {
+    queue.addLast( awd );
+    empty = false;
+    notify();
+  }
+
+  public synchronized ArifactWriteData getArtifact()
+  throws InterruptedException
+  {
+    if( empty )
+      return null;
+
+    while( queue.isEmpty() )
+      wait();
+    
+    ArifactWriteData res = queue.removeFirst();
+    
+    if( res.artifact == null )
+    {
+      empty = true;
+      return null;
+    }
+
+    return res;
+  }
+}
+//=================================================================================================================

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlat.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlat.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlatFactory.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlatFactory.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlatFactory.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlatFactory.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,50 @@
+/**
+ *  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.local.flat;
+
+import org.apache.maven.mercury.repository.api.AbstractRepository;
+import org.apache.maven.mercury.repository.api.LocalRepository;
+import org.apache.maven.mercury.repository.api.Repository;
+import org.apache.maven.mercury.repository.api.RepositoryException;
+import org.apache.maven.mercury.repository.api.RepositoryWriter;
+import org.apache.maven.mercury.repository.api.RepositoryWriterFactory;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+public class LocalRepositoryWriterFlatFactory
+implements RepositoryWriterFactory
+{
+  private static final Language LANG = new DefaultLanguage( LocalRepositoryWriterFlatFactory.class );
+  private static final LocalRepositoryWriterFlatFactory FACTORY = new LocalRepositoryWriterFlatFactory();
+  
+  static 
+  {
+    AbstractRepository.register( LocalRepositoryFlat.FLAT_REPOSITORY_TYPE, FACTORY  );
+  }
+  
+  public RepositoryWriter getWriter( Repository repo )
+  throws RepositoryException
+  {
+    if( repo == null || !(repo instanceof LocalRepository) )
+      throw new RepositoryException( LANG.getMessage( "bad.repository.type", repo == null ? "null" : repo.getClass().getName() ) );
+    
+    return new LocalRepositoryWriterFlat( (LocalRepository)repo );
+  }
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlatFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/LocalRepositoryWriterFlatFactory.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/Messages.properties
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/Messages.properties?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/Messages.properties (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/Messages.properties Wed Apr 22 22:56:48 2009
@@ -0,0 +1,33 @@
+#
+#  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.
+#
+bad.repository.type=repository should implement LocalRepository, instead got {0}
+empty.query=received empty query - {0}
+binary.not.found=Artifact {0} binary at not found {1} 
+ga.not.found=Artifact {0} version group not found at {1} 
+gav.not.found=No artifact version for {0} found in {1}
+snapshot.not.found=No snapshot version for {0} found in {1}
+gavdir.not.found=No directory {1} for artifact {0} 
+pom.not.found=Artifact {0} - binary exists, but POM not found in the repository 
+artifact.no.stream=Cannot find either input stream or file, associated with artifact {0}
+pom.artifact.no.stream=Cannot find either pom blob, input stream or file, associated with artifact {0}
+no.signature.file=Verifier for {0} is mandatory, but file {1} does not exist
+signature.failed=Signature "{0}": verification failed for file {1}
+cannot.read.signature.file=Cannot read signature file {0}, error: {1}
+cannot.lock.gav=Cannot lock GAV folder {0} in {1} millis
+file.is.empty=File {0} exists, but is empty. Data corruption somewhere - please repair metadata.
\ No newline at end of file

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/Messages.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/flat/Messages.properties
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,285 @@
+/**
+ *  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.local.m2;
+
+import org.apache.maven.mercury.artifact.Artifact;
+import org.apache.maven.mercury.artifact.ArtifactMetadata;
+import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
+import org.apache.maven.mercury.util.FileUtil;
+
+/**
+ * artifact relative location data object - used by repositories to hold on to intermediate path calculations 
+ *
+ *
+ * @author Oleg Gusakov
+ * @version $Id$
+ *
+ */
+public class ArtifactLocation
+{
+  public static final String POM_EXT = ".pom";
+
+  private String prefix;
+  
+  private String gaPath;
+  private String versionDir;
+  private String baseName;
+  private String version;
+  private String classifier;
+  private String type;
+  
+  private ArtifactMetadata bmd;
+  
+  public ArtifactLocation( String prefix, ArtifactMetadata bmd )
+  {
+    if( prefix == null || bmd == null || bmd.getGroupId() == null || bmd.getArtifactId() == null || bmd.getVersion() == null )
+      return;
+    
+    this.bmd = bmd;
+
+    this.prefix     = prefix;
+    this.gaPath     = bmd.getGroupId().replace( '.', FileUtil.SEP_CHAR ) + FileUtil.SEP + bmd.getArtifactId();
+    this.version    = bmd.getVersion();
+    this.baseName   = bmd.getArtifactId();
+    this.versionDir = this.version;
+    this.classifier = bmd.getClassifier();
+    this.type       = bmd.getType();
+  }
+  
+  public String getRelPath()
+  {
+    return gaPath+FileUtil.SEP+calculateVersionDir( version )+FileUtil.SEP+baseName+FileUtil.DASH+version+getDashedClassifier()+'.'+type;
+  }
+  
+  public String getRelPomPath()
+  {
+    return gaPath+FileUtil.SEP+calculateVersionDir( version )+FileUtil.SEP+baseName+FileUtil.DASH+version+POM_EXT;
+  }
+  
+  public String getAbsPath()
+  {
+    if( prefix == null )
+      return null;
+
+    return getSeparatedPrefix() + getRelPath();
+  }
+  
+  public String getAbsPomPath()
+  {
+    if( prefix == null )
+      return null;
+
+    return getSeparatedPrefix() + getRelPomPath();
+  }
+  
+  public String getAbsGavPath()
+  {
+      if( prefix == null )
+          return null;
+
+    return getSeparatedPrefix() + getGavPath();
+  }
+  
+  public String getGavPath()
+  {
+    return getGaPath() + FileUtil.SEP + calculateVersionDir( version );
+  }
+  
+  public String getBaseVersion()
+  {
+    if( version == null )
+      return null;
+    
+    DefaultArtifactVersion dav = new DefaultArtifactVersion( version );
+    return dav.getBase();
+  }
+  
+  public String getVersionWithoutTS(  )
+  {
+    if( version == null )
+      return null;
+    
+    int li = version.lastIndexOf( '-' );
+    
+    if( li < 1 )
+        return version;
+    
+    int li2 = version.substring( 0, li ).lastIndexOf( '-' );
+    
+    if( li2 > 0 )
+        return version.substring( 0, li2 );
+    
+    return version;
+  }
+  
+  public static String stripTS( String ver  )
+  {
+    if( ver == null )
+      return null;
+    
+    int li = ver.lastIndexOf( '-' );
+    
+    if( li < 1 )
+        return ver;
+    
+    int li2 = ver.substring( 0, li ).lastIndexOf( '-' );
+    
+    if( li2 > 0 )
+        return ver.substring( 0, li2 );
+    
+    return ver;
+  }
+  
+  public static String stripSN( String ver  )
+  {
+    if( ver == null )
+      return null;
+    
+    int li = ver.lastIndexOf( '-' );
+    
+    if( li < 1 )
+        return ver;
+    
+    return ver.substring( 0, li );
+  }
+  
+  public static String getTS( String ver  )
+  {
+    if( ver == null )
+      return null;
+    
+    int li = ver.lastIndexOf( '-' );
+    
+    if( li < 1 )
+        return ver;
+    
+    int li2 = ver.substring( 0, li ).lastIndexOf( '-' );
+    
+    if( li2 > 0 )
+        return ver.substring( li2+1 );
+    
+    return ver;
+  }
+  
+  public static String getFileTS( String name  )
+  {
+      if( name == null )
+          return null;
+      
+      int lastDash = name.lastIndexOf( '-' );
+      if( lastDash < 2 )
+          return null;
+      
+      int firstDash = name.lastIndexOf( '-', lastDash-1 );
+      if( firstDash < 1 )
+          return null;
+      
+      String fTS = name.substring( firstDash+1, lastDash );
+      
+      return fTS;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public static String calculateVersionDir( String ver )
+  {
+      if( ver == null )
+          return ver;
+      
+      if( ver.matches( Artifact.SNAPSHOT_TS_REGEX ) )
+          return stripTS( ver )+FileUtil.DASH+Artifact.SNAPSHOT_VERSION;
+      
+      return ver;
+  }
+  
+  //---------------------------------------------------------
+  public String getGaPath()
+  {
+    return gaPath;
+  }
+  public void setGaPath( String gaPath )
+  {
+    this.gaPath = gaPath;
+  }
+  public String getVersionDir()
+  {
+    return versionDir;
+  }
+  public void setVersionDir( String versionDir )
+  {
+    this.versionDir = versionDir;
+  }
+  public String getBaseName()
+  {
+    return baseName;
+  }
+  public void setBaseName( String baseName )
+  {
+    this.baseName = baseName;
+  }
+  public String getVersion()
+  {
+    return version;
+  }
+  public void setVersion( String version )
+  {
+    this.version = version;
+  }
+  public String getClassifier()
+  {
+    return classifier;
+  }
+  public String getDashedClassifier()
+  {
+    return (classifier == null||classifier.length()<1) ? "" : FileUtil.DASH+classifier;
+  }
+  public void setClassifier( String classifier )
+  {
+    this.classifier = classifier;
+  }
+  public String getType()
+  {
+    return type;
+  }
+  public void setType( String type )
+  {
+    this.type = type;
+  }
+  public String getPrefix()
+  {
+    return prefix;
+  }
+  public String getSeparatedPrefix()
+  {
+    if( prefix == null )
+      return null;
+
+    return prefix+(prefix.endsWith( FileUtil.SEP ) ? "" : FileUtil.SEP);
+  }
+
+  public void setPrefix( String prefix )
+  {
+    this.prefix = prefix;
+  }
+
+  @Override
+  public String toString()
+  {
+    return bmd == null ? "no ArtifactBasicMetadata" : bmd.toString();
+  }
+  
+}
\ No newline at end of file

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/ArtifactLocation.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,166 @@
+/**
+ *  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.local.m2;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import org.apache.maven.mercury.builder.api.DependencyProcessor;
+import org.apache.maven.mercury.repository.api.AbstractRepository;
+import org.apache.maven.mercury.repository.api.LocalRepository;
+import org.apache.maven.mercury.repository.api.NonExistentProtocolException;
+import org.apache.maven.mercury.repository.api.RepositoryReader;
+import org.apache.maven.mercury.repository.api.RepositoryWriter;
+import org.apache.maven.mercury.transport.api.Server;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+public class LocalRepositoryM2
+extends AbstractRepository
+implements LocalRepository
+{
+    private static final Language LANG = new DefaultLanguage( LocalRepositoryM2.class );
+
+    private File directory;
+    
+    public static final String METADATA_FILE_NAME = "maven-metadata-local.xml";
+    
+    /** indicates that if a-1.0-SNAPSHOT.jar exists, it wins despite any timestamps
+     *  required for Maven comatibility 
+     **/
+    private boolean _snapshotAlwaysWins = false;
+
+    //----------------------------------------------------------------------------------
+    private void setDirectory( File directory )
+    {
+      if( directory == null )
+        throw new IllegalArgumentException( LANG.getMessage( "null.directory" ) );
+      
+      if( !directory.exists() )
+        directory.mkdirs();
+
+      if( !directory.isDirectory() )
+          throw new IllegalArgumentException( LANG.getMessage( "file.directory", directory.getAbsolutePath() ) );
+        
+      this.directory = directory;
+    }
+    //----------------------------------------------------------------------------------
+    public LocalRepositoryM2( Server server, DependencyProcessor dependencyProcessor )
+    {
+        super( server.getId(), DEFAULT_REPOSITORY_TYPE );
+        setDirectory( new File( server.getURL().getFile() ) );
+        this.server = server;
+        
+        setDependencyProcessor( dependencyProcessor );
+    }
+    //----------------------------------------------------------------------------------
+    public LocalRepositoryM2( File directory, DependencyProcessor dependencyProcessor )
+    throws IOException
+    {
+        this( directory.getCanonicalPath(), directory, DEFAULT_REPOSITORY_TYPE, dependencyProcessor );
+    }
+    //----------------------------------------------------------------------------------
+    public LocalRepositoryM2( String id, File directory, DependencyProcessor dependencyProcessor )
+    {
+        this( id, directory, DEFAULT_REPOSITORY_TYPE, dependencyProcessor );
+    }
+    //----------------------------------------------------------------------------------
+    public LocalRepositoryM2( String id, File directory, String type, DependencyProcessor dependencyProcessor )
+    {
+        super( id, type );
+
+        setDirectory( directory );
+        
+        setDependencyProcessor( dependencyProcessor );
+        
+        try
+        {
+            this.server = new Server( getId(), directory.toURL() );
+        }
+        catch ( MalformedURLException e )
+        {
+            throw new IllegalArgumentException(e);
+        }
+    }
+    //----------------------------------------------------------------------------------
+    public File getDirectory()
+    {
+        return directory;
+    }
+    //----------------------------------------------------------------------------------
+    public RepositoryReader getReader() 
+    {
+      return new LocalRepositoryReaderM2( this, getDependencyProcessor() );
+    }
+    //----------------------------------------------------------------------------------
+    public RepositoryReader getReader( String protocol )
+    {
+       return getReader();
+    }
+    //----------------------------------------------------------------------------------
+    public RepositoryWriter getWriter()
+    {
+      return new LocalRepositoryWriterM2(this);
+    }
+    //----------------------------------------------------------------------------------
+    public RepositoryWriter getWriter( String protocol )
+        throws NonExistentProtocolException
+    {
+      return getWriter();
+    }
+    //----------------------------------------------------------------------------------
+    public boolean isLocal()
+    {
+      return true;
+    }
+    //----------------------------------------------------------------------------------
+    public boolean isReadable()
+    {
+      return true;
+    }
+    //----------------------------------------------------------------------------------
+    public boolean isWriteable()
+    {
+      return true;
+    }
+
+    public void setSnapshotAlwaysWins( boolean alwaysWins )
+    {
+        _snapshotAlwaysWins = alwaysWins;
+    }
+
+    public boolean getSnapshotAlwaysWins()
+    {
+        return _snapshotAlwaysWins;
+    }
+    
+    //----------------------------------------------------------------------------------
+    public String getType()
+    {
+      return DEFAULT_REPOSITORY_TYPE;
+    }
+    //----------------------------------------------------------------------------------
+    public String getMetadataName()
+    {
+      return METADATA_FILE_NAME;
+    }
+    //----------------------------------------------------------------------------------
+    //----------------------------------------------------------------------------------
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryM2.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,687 @@
+/**
+ *  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.local.m2;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.maven.mercury.artifact.Artifact;
+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.VersionComparator;
+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.crypto.api.StreamObserverException;
+import org.apache.maven.mercury.crypto.api.StreamVerifier;
+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.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.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;
+import org.apache.maven.mercury.repository.api.RepositoryException;
+import org.apache.maven.mercury.repository.api.RepositoryReader;
+import org.apache.maven.mercury.util.FileUtil;
+import org.apache.maven.mercury.util.TimeUtil;
+import org.apache.maven.mercury.util.Util;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+public class LocalRepositoryReaderM2
+    extends AbstracRepositoryReader
+    implements RepositoryReader, MetadataReader
+{
+    private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( LocalRepositoryReaderM2.class );
+
+    private static final Language LANG = new DefaultLanguage( LocalRepositoryReaderM2.class );
+
+    // ---------------------------------------------------------------------------------------------------------------
+    private static final String[] _protocols = new String[] { "file" };
+
+    LocalRepository _repo;
+
+    File _repoDir;
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public LocalRepositoryReaderM2( LocalRepository repo, DependencyProcessor mdProcessor )
+    {
+        if ( repo == null )
+            throw new IllegalArgumentException( "localRepo cannot be null" );
+
+        _repoDir = repo.getDirectory();
+        if ( _repoDir == null )
+            throw new IllegalArgumentException( "localRepo directory cannot be null" );
+
+        if ( !_repoDir.exists() )
+            throw new IllegalArgumentException( "localRepo directory \"" + _repoDir.getAbsolutePath()
+                + "\" should exist" );
+
+        _repo = repo;
+
+        if ( mdProcessor == null )
+            throw new IllegalArgumentException( "MetadataProcessor cannot be null " );
+
+        setDependencyProcessor( mdProcessor );
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public Repository getRepository()
+    {
+        return _repo;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    private ArtifactLocation calculateLocation( String root, ArtifactMetadata bmd, AbstractRepOpResult res )
+    {
+        ArtifactLocation loc = new ArtifactLocation( root, bmd );
+
+        File gaDir = new File( root, loc.getGaPath() );
+
+        if ( !gaDir.exists() )
+        {
+            if ( LOG.isDebugEnabled() )
+                LOG.debug( LANG.getMessage( "ga.not.found", bmd.toString(), loc.getGaPath() ) );
+            return null;
+        }
+
+        Quality vq = new Quality( loc.getVersion() );
+
+        // RELEASE = LATEST - SNAPSHOTs
+        if ( Artifact.RELEASE_VERSION.equals( loc.getVersion() ) || Artifact.LATEST_VERSION.equals( loc.getVersion() ) )
+        {
+            final boolean noSnapshots = Artifact.RELEASE_VERSION.equals( loc.getVersion() );
+            loc.setVersion( null );
+            
+            final TreeSet<String> ts = new TreeSet<String>( new VersionComparator() );
+
+            gaDir.listFiles(
+                     new FilenameFilter()
+                     {
+                        public boolean accept( File dir, String name )
+                        {   
+                            if( new File(dir,name).isDirectory() )
+                            {
+                                if( noSnapshots && name.endsWith( Artifact.SNAPSHOT_VERSION ) )
+                                    return false;
+                                
+                                ts.add( name );
+                                return true;
+                            }
+                            return false;
+                        }
+                         
+                     }
+                           );
+            
+            if( !ts.isEmpty() )
+                loc.setVersion( ts.last() );
+            else
+            {
+                if( LOG.isDebugEnabled() )
+                    LOG.debug( LANG.getMessage( "gav.not.found", bmd.toString(), loc.getGaPath() ) );
+                return null;
+            }
+
+            // LATEST is a SNAPSHOT :(
+            if ( loc.getVersion().endsWith( Artifact.SNAPSHOT_VERSION ) )
+            {
+                loc.setVersionDir( loc.getVersion() );
+
+                if ( !findLatestSnapshot( bmd, loc, res ) )
+                    return null;
+            }
+            else
+                // R or L found and actual captured in loc.version
+                loc.setVersionDir( loc.getVersion() );
+        }
+        // regular snapshot requested
+        else if ( loc.getVersion().endsWith( Artifact.SNAPSHOT_VERSION ) )
+        {
+            File gavDir = new File( gaDir, loc.getVersion() );
+            if ( !gavDir.exists() )
+            {
+//                res.addError( bmd, new RepositoryException( LANG.getMessage( "gavdir.not.found", bmd.toString(),
+//                                                                             gavDir.getAbsolutePath() ) ) );
+                if( LOG.isDebugEnabled() )
+                    LOG.debug( LANG.getMessage( "gavdir.not.found", bmd.toString(), gavDir.getAbsolutePath() ) );
+                
+                return null;
+            }
+
+            if ( !findLatestSnapshot( bmd, loc, res ) )
+                return null;
+
+        }
+        // time stamped snapshot requested
+        else if ( vq.equals( Quality.SNAPSHOT_TS_QUALITY ) )
+        {
+            loc.setVersionDir( loc.getVersionWithoutTS() + FileUtil.DASH + Artifact.SNAPSHOT_VERSION );
+        }
+
+        return loc;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public ArtifactResults readArtifacts( Collection<ArtifactMetadata> query )
+        throws RepositoryException, IllegalArgumentException
+    {
+        if ( query == null || query.isEmpty() )
+            throw new IllegalArgumentException( LANG.getMessage( "empty.query", query == null ? "null" : "empty" ) );
+
+        ArtifactResults res = new ArtifactResults();
+
+        Set<StreamVerifierFactory> vFacs = null;
+
+        if ( _repo.hasServer() && _repo.getServer().hasReaderStreamVerifierFactories() )
+            vFacs = _repo.getServer().getReaderStreamVerifierFactories();
+
+        for ( ArtifactMetadata md : query )
+        {
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
+
+            DefaultArtifact da = md instanceof DefaultArtifact ? (DefaultArtifact) md : new DefaultArtifact( md );
+
+            ArtifactLocation loc = calculateLocation( _repoDir.getAbsolutePath(), md, res );
+
+            if ( loc == null )
+                continue;
+
+            File binary = new File( loc.getAbsPath() );
+
+            // binary calculated
+            if ( !binary.exists() )
+            {
+//                res.addError( bmd, new RepositoryException( LANG.getMessage( "binary.not.found", bmd.toString(),
+//                                                                             binary.getAbsolutePath() ) ) );
+                if( LOG.isDebugEnabled() )
+                    LOG.debug( LANG.getMessage( "binary.not.found", md.toString(), binary.getAbsolutePath() ) );
+
+                continue;
+            }
+
+            try // reading pom if one exists
+            {
+                if ( checkFile( binary, vFacs ) )
+                {
+                    da.setFile( binary );
+                    da.setTracker( this._repo );
+                }
+
+                if ( "pom".equals( md.getType() ) )
+                {
+                    da.setPomBlob( FileUtil.readRawData( binary ) );
+                }
+                else
+                {
+                    File pomFile = new File( loc.getAbsPomPath() );
+                    if ( pomFile.exists() )
+                    {
+                        if ( checkFile( pomFile, vFacs ) )
+                            da.setPomBlob( FileUtil.readRawData( pomFile ) );
+                    }
+                    else
+                        LOG.warn( LANG.getMessage( "pom.not.found", md.toString() ) );
+                }
+
+                da.setVersion( loc.getVersion() );
+                res.add( md, da );
+            }
+            catch ( Exception e )
+            {
+                throw new RepositoryException( e );
+            }
+        }
+        return res;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    private static boolean checkFile( File f, Set<StreamVerifierFactory> vFacs )
+        throws RepositoryException, StreamVerifierException
+    {
+        if ( vFacs != null )
+        {
+            String fileName = f.getAbsolutePath();
+
+            HashSet<StreamVerifier> vs = new HashSet<StreamVerifier>( vFacs.size() );
+
+            for ( StreamVerifierFactory svf : vFacs )
+            {
+                StreamVerifier sv = svf.newInstance();
+                String ext = sv.getAttributes().getExtension();
+                String sigFileName = fileName + ( ext.startsWith( "." ) ? "" : "." ) + ext;
+                File sigFile = new File( sigFileName );
+                if ( sigFile.exists() )
+                {
+                    try
+                    {
+                        sv.initSignature( FileUtil.readRawDataAsString( sigFile ) );
+                    }
+                    catch ( IOException e )
+                    {
+                        throw new RepositoryException( LANG.getMessage( "cannot.read.signature.file", sigFileName,
+                                                                        e.getMessage() ) );
+                    }
+                    vs.add( sv );
+                }
+                else if ( !sv.getAttributes().isLenient() )
+                {
+                    throw new RepositoryException( LANG.getMessage( "no.signature.file", ext, sigFileName ) );
+                }
+                // otherwise ignore absence of signature file, if verifier is lenient
+            }
+
+            FileInputStream fin = null;
+            try
+            {
+                fin = new FileInputStream( f );
+                byte[] buf = new byte[1024];
+                int n = -1;
+                while ( ( n = fin.read( buf ) ) != -1 )
+                {
+                    for ( StreamVerifier sv : vs )
+                        try
+                        {
+                            sv.bytesReady( buf, 0, n );
+                        }
+                        catch ( StreamObserverException e )
+                        {
+                            if ( !sv.getAttributes().isLenient() )
+                                throw new RepositoryException( e );
+                        }
+                }
+
+                for ( StreamVerifier sv : vs )
+                {
+                    if ( sv.verifySignature() )
+                    {
+                        if ( sv.getAttributes().isSufficient() )
+                            break;
+                    }
+                    else
+                    {
+                        if ( !sv.getAttributes().isLenient() )
+                            throw new RepositoryException(
+                                                           LANG.getMessage( "signature.failed",
+                                                                            sv.getAttributes().getExtension(), fileName ) );
+                    }
+                }
+            }
+            catch ( IOException e )
+            {
+                throw new RepositoryException( e );
+            }
+            finally
+            {
+                if ( fin != null )
+                    try
+                    {
+                        fin.close();
+                    }
+                    catch ( Exception any )
+                    {
+                    }
+            }
+        }
+        return true;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    /**
+   * 
+   */
+    public MetadataResults readDependencies( Collection<ArtifactMetadata> query )
+        throws RepositoryException, IllegalArgumentException
+    {
+        if ( query == null || query.size() < 1 )
+            return null;
+
+        MetadataResults ror = null;
+
+        File pomFile = null;
+        for ( ArtifactMetadata md : query )
+        {
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
+
+            String pomPath =
+                md.getGroupId().replace( '.', '/' ) + "/" + md.getArtifactId() + "/" + ArtifactLocation.calculateVersionDir( md.getVersion() ) + "/"
+                    + md.getArtifactId() + '-' + md.getVersion() + ".pom";
+
+            pomFile = new File( _repoDir, pomPath );
+            if ( !pomFile.exists() )
+            {
+                if( LOG.isDebugEnabled() )
+                    LOG.debug( "file \"" + pomPath + "\" does not exist in local repo" );
+                continue;
+            }
+
+            try
+            {
+                List<ArtifactMetadata> deps =
+                    _mdProcessor.getDependencies( md, _mdReader == null ? this : _mdReader, System.getenv(),
+                                                  System.getProperties() );
+// for(ArtifactBasicMetadata d : deps )
+// {
+// System.out.println("======> "+d.getScope() );
+// }
+                ror = MetadataResults.add( ror, md, deps );
+            }
+            catch ( Exception e )
+            {
+                if( LOG.isDebugEnabled() )
+                    LOG.debug( "error reading " + md.toString() + " dependencies", e );
+                continue;
+            }
+
+        }
+
+        return ror;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    private boolean findLatestSnapshot( final ArtifactMetadata md, final ArtifactLocation loc, AbstractRepOpResult res )
+    {
+        File snapshotFile = new File( loc.getAbsPath() );
+        
+        boolean virtualRequested = md.isVirtual();
+        
+        final boolean virtualExists = snapshotFile.exists();
+        
+        final long  virtualLM = virtualExists ? snapshotFile.lastModified() : 0L;
+        final String virtualTS = virtualExists ? TimeUtil.defaultToSnTs( virtualLM ) : "00000000.000000";
+
+        // TS exists - return it
+        if ( ! virtualRequested )
+            return snapshotFile.exists();
+
+        if( virtualExists &&  ((LocalRepositoryM2)_repo).getSnapshotAlwaysWins() )
+            return true;
+        
+        // no real SNAPSHOT file, let's try to find one
+        File gavDir = new File( loc.getAbsGavPath() );
+        
+        String classifier = Util.isEmpty( md.getClassifier() ) ? "" : '-'+md.getClassifier();
+        
+        final String regEx = Artifact.SNAPSHOT_TS_REGEX + classifier + "\\."+md.getCheckedType();
+        
+        final TreeSet<String> ts = new TreeSet<String>( new VersionComparator() );
+        
+        final int pos = md.getArtifactId().length() + 1;
+        
+        gavDir.listFiles( new FilenameFilter()
+                            {
+                                public boolean accept( File dir, String name )
+                                {
+                                    if( name.matches( regEx ) )
+                                    {
+                                        String ver = name.substring( pos, name.lastIndexOf( '.' ) );
+                                        
+                                        if( !virtualExists )
+                                        {
+                                            ts.add( ver );
+                                            
+                                            return true;
+                                        }
+                                        
+                                        // otherwise - only add it if older'n the SNAPSHOT
+                                        String fTS = ArtifactLocation.getFileTS( name );
+                                        
+                                        if( fTS.compareTo( virtualTS ) >= 0 )
+                                        {
+                                            ts.add( ver );
+                                            
+                                            return true;
+                                        }
+                                        
+                                        return false;
+                                        
+                                    }
+    
+                                    return false;
+                                }
+                                
+                            }
+                          );
+        
+        if( ts.isEmpty() )
+        {
+            if( virtualExists ) // none were older'n the snapshot
+            {
+                md.setTimeStamp( virtualTS );
+                return true;
+            }
+            
+            if( LOG.isErrorEnabled() )
+                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;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    /**
+     * direct disk search, no redirects - I cannot process pom files :(
+     */
+    public MetadataResults readVersions( Collection<ArtifactMetadata> query )
+        throws RepositoryException, IllegalArgumentException
+    {
+        if ( query == null || query.size() < 1 )
+            return null;
+
+        MetadataResults res = new MetadataResults( query.size() );
+
+        File gaDir = null;
+        for ( ArtifactMetadata md : query )
+        {
+            if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+                continue;
+
+            gaDir = new File( _repoDir, md.getGroupId().replace( '.', '/' ) + "/" + md.getArtifactId() );
+            if ( !gaDir.exists() )
+                continue;
+
+            File[] versionFiles = gaDir.listFiles();
+
+            VersionRange versionQuery;
+            try
+            {
+                versionQuery = VersionRangeFactory.create( md.getVersion(), _repo.getVersionRangeQualityRange() );
+            }
+            catch ( VersionException e )
+            {
+                res = MetadataResults.add( res, md, new RepositoryException( e ) );
+                continue;
+            }
+
+            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(), md, res );
+
+                if ( loc == null )
+                    continue;
+
+                ArtifactMetadata vmd = new ArtifactMetadata();
+                vmd.setGroupId( md.getGroupId() );
+                vmd.setArtifactId( md.getArtifactId() );
+                vmd.setClassifier( md.getClassifier() );
+                vmd.setType( md.getType() );
+                vmd.setVersion( loc.getVersion() );
+                vmd.setTimeStamp( md.getTimeStamp() );
+
+                res = MetadataResults.add( res, md, vmd );
+
+                continue;
+
+            }
+
+            for ( File vf : versionFiles )
+            {
+                if ( !vf.isDirectory() )
+                    continue;
+
+                String version = vf.getName();
+
+                Quality q = new Quality( version );
+                if ( !_repo.isAcceptedQuality( q ) )
+                    continue;
+
+                if ( !versionQuery.includes( vf.getName() ) )
+                    continue;
+
+                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 = MetadataResults.add( res, md, vmd );
+            }
+        }
+        return res;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public byte[] readRawData( ArtifactMetadata md, String classifier, String type )
+        throws MetadataReaderException
+    {
+        return readRawData( md, classifier, type, false );
+    }
+    // ---------------------------------------------------------------------------------------------------------------
+    public byte[] readRawData( ArtifactMetadata md, String classifier, String type, boolean exempt )
+        throws MetadataReaderException
+    {
+        if( ! _repo.getRepositoryQualityRange().isAcceptedQuality( md.getRequestedQuality() ) )
+            return null;
+
+        return readRawData( relPathOf( md, classifier, type ), exempt );
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    private static String relPathOf( ArtifactMetadata bmd, String classifier, String type )
+    {
+        String bmdPath =
+            bmd.getGroupId().replace( '.', '/' ) + '/' + bmd.getArtifactId() + '/' + ArtifactLocation.calculateVersionDir( bmd.getVersion() );
+
+        String path = bmdPath + '/' + bmd.getBaseName( classifier ) + '.' + ( type == null ? bmd.getType() : type );
+        
+        if( LOG.isDebugEnabled() )
+            LOG.debug( bmd.toString()+" path is "+ path);
+
+        return path;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public byte[] readRawData( String path )
+    throws MetadataReaderException
+    {
+        return readRawData( path, false );
+    }
+    // ---------------------------------------------------------------------------------------------------------------
+    public byte[] readRawData( String path, boolean exempt )
+    throws MetadataReaderException
+    {
+        File file = new File( _repoDir, path );
+
+        if ( !file.exists() )
+            return null;
+
+        FileInputStream fis = null;
+
+        try
+        {
+            fis = new FileInputStream( file );
+            int len = (int) file.length();
+            byte[] pom = new byte[len];
+            fis.read( pom );
+            return pom;
+        }
+        catch ( IOException e )
+        {
+            throw new MetadataReaderException( e );
+        }
+        finally
+        {
+            if ( fis != null )
+                try
+                {
+                    fis.close();
+                }
+                catch ( Exception any )
+                {
+                }
+        }
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public String readStringData( String path )
+        throws MetadataReaderException
+    {
+        byte[] data = readRawData( path, false );
+        if ( data == null )
+            return null;
+
+        return new String( data );
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public boolean canHandle( String protocol )
+    {
+        return AbstractRepository.DEFAULT_LOCAL_READ_PROTOCOL.equals( protocol );
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public String[] getProtocols()
+    {
+        return _protocols;
+    }
+
+    // ---------------------------------------------------------------------------------------------------------------
+    public void close()
+    {
+    }
+    // ---------------------------------------------------------------------------------------------------------------
+    
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2Factory.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2Factory.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2Factory.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2Factory.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,51 @@
+/**
+ *  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.local.m2;
+
+import org.apache.maven.mercury.builder.api.DependencyProcessor;
+import org.apache.maven.mercury.repository.api.AbstractRepository;
+import org.apache.maven.mercury.repository.api.LocalRepository;
+import org.apache.maven.mercury.repository.api.Repository;
+import org.apache.maven.mercury.repository.api.RepositoryException;
+import org.apache.maven.mercury.repository.api.RepositoryReader;
+import org.apache.maven.mercury.repository.api.RepositoryReaderFactory;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+public class LocalRepositoryReaderM2Factory
+implements RepositoryReaderFactory
+{
+  private static final Language LANG = new DefaultLanguage( LocalRepositoryReaderM2Factory.class );
+  private static final LocalRepositoryReaderM2Factory FACTORY = new LocalRepositoryReaderM2Factory();
+  
+  static 
+  {
+    AbstractRepository.register( AbstractRepository.DEFAULT_REPOSITORY_TYPE, FACTORY  );
+  }
+  
+  public RepositoryReader getReader( Repository repo, DependencyProcessor mdProcessor)
+  throws RepositoryException
+  {
+    if( repo == null || !(repo instanceof LocalRepository) )
+      throw new RepositoryException( LANG.getMessage( "bad.repository.type", repo == null ? "null" : repo.getClass().getName() ) );
+    
+    return new LocalRepositoryReaderM2( (LocalRepository)repo, mdProcessor );
+  }
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2Factory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryReaderM2Factory.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,449 @@
+/**
+ *  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.local.m2;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.maven.mercury.artifact.Artifact;
+import org.apache.maven.mercury.artifact.Quality;
+import org.apache.maven.mercury.artifact.version.DefaultArtifactVersion;
+import org.apache.maven.mercury.crypto.api.StreamObserverException;
+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.repository.api.AbstractRepository;
+import org.apache.maven.mercury.repository.api.AbstractRepositoryWriter;
+import org.apache.maven.mercury.repository.api.LocalRepository;
+import org.apache.maven.mercury.repository.api.Repository;
+import org.apache.maven.mercury.repository.api.RepositoryException;
+import org.apache.maven.mercury.repository.api.RepositoryWriter;
+import org.apache.maven.mercury.repository.metadata.AddVersionOperation;
+import org.apache.maven.mercury.repository.metadata.Metadata;
+import org.apache.maven.mercury.repository.metadata.MetadataBuilder;
+import org.apache.maven.mercury.repository.metadata.MetadataException;
+import org.apache.maven.mercury.repository.metadata.MetadataOperation;
+import org.apache.maven.mercury.repository.metadata.SetSnapshotOperation;
+import org.apache.maven.mercury.repository.metadata.Snapshot;
+import org.apache.maven.mercury.repository.metadata.SnapshotOperand;
+import org.apache.maven.mercury.repository.metadata.StringOperand;
+import org.apache.maven.mercury.transport.api.Server;
+import org.apache.maven.mercury.util.FileLockBundle;
+import org.apache.maven.mercury.util.FileUtil;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+public class LocalRepositoryWriterM2
+extends AbstractRepositoryWriter
+implements RepositoryWriter
+{
+  public static final String SYSTEM_PROPERTY_PARALLEL_WORKERS = "mercury.local.repo.workers";
+  public static final int  PARALLEL_WORKERS = Integer.parseInt( System.getProperty( SYSTEM_PROPERTY_PARALLEL_WORKERS, "4" ) );
+  
+  public static final long SLEEP_FOR_WORKERS_TICK = 20l;
+
+  public static final String SYSTEM_PROPERTY_SLEEP_FOR_LOCK = "mercury.local.lock.wait.millis";
+  public static final long SLEEP_FOR_LOCK = Long.parseLong(  System.getProperty( SYSTEM_PROPERTY_SLEEP_FOR_LOCK, "5000" ) );
+  
+  public static final long SLEEP_FOR_LOCK_TICK = 5l;
+
+  private static final IMercuryLogger LOG = MercuryLoggerManager.getLogger( LocalRepositoryWriterM2.class ); 
+  private static final Language LANG = new DefaultLanguage( LocalRepositoryWriterM2.class );
+  //---------------------------------------------------------------------------------------------------------------
+  private static final String [] _protocols = new String [] { "file" };
+  
+  private final LocalRepository _repo;
+  private final File _repoDir;
+  private final ArtifactQueue _aq;
+
+  private static final ArifactWriteData LAST_ARTIFACT = new ArifactWriteData( null, null );
+  //---------------------------------------------------------------------------------------------------------------
+  public LocalRepositoryWriterM2( LocalRepository repo )
+  {
+    if( repo == null )
+      throw new IllegalArgumentException("localRepo cannot be null");
+    
+    _repoDir = repo.getDirectory();
+    if( _repoDir == null )
+      throw new IllegalArgumentException("localRepo directory cannot be null");
+    
+    if( !_repoDir.exists() )
+      throw new IllegalArgumentException("localRepo directory \""+_repoDir.getAbsolutePath()+"\" should exist");
+
+    _repo = repo;
+    _aq = null;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  private LocalRepositoryWriterM2( LocalRepository repo, File repoDir, ArtifactQueue aq )
+  {
+    _repo = repo;
+    _repoDir = repoDir;
+    _aq = aq;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public Repository getRepository()
+  {
+    return _repo;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public boolean canHandle( String protocol )
+  {
+    return AbstractRepository.DEFAULT_LOCAL_READ_PROTOCOL.equals( protocol );
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public String[] getProtocols()
+  {
+    return _protocols;
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public void close()
+  {
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public void writeArtifacts( Collection<Artifact> artifacts )
+      throws RepositoryException
+  {
+    if( artifacts == null || artifacts.size() < 1 )
+      return;
+    
+    int nWorkers = PARALLEL_WORKERS;
+    if( artifacts.size() < nWorkers )
+      nWorkers = artifacts.size();
+    
+    ArtifactQueue aq = new ArtifactQueue();
+    LocalRepositoryWriterM2 [] workers = new LocalRepositoryWriterM2[ nWorkers ];
+    
+    for( int i=0; i<nWorkers; i++ )
+      workers[ i ] = new LocalRepositoryWriterM2( _repo, _repoDir, aq );
+    
+    for( Artifact artifact : artifacts )
+    {
+      Set<StreamVerifierFactory> vFacs = null;
+      Server server = _repo.getServer();
+      if( server != null && server.hasWriterStreamVerifierFactories() )
+        vFacs = server.getWriterStreamVerifierFactories();
+      
+      if( vFacs == null ) // let it be empty, but not null
+        vFacs = new HashSet<StreamVerifierFactory>(1);
+
+      aq.addArtifact( new ArifactWriteData( artifact, vFacs ) );
+    }
+    aq.addArtifact( LAST_ARTIFACT );
+    
+    for( int i=0; i<nWorkers; i++ )
+      workers[ i ].start();
+    
+    boolean alive = true;
+    while( alive )
+    {
+      alive = false;
+      for( int i=0; i<nWorkers; i++ )
+        if( workers[ i ].isAlive() )
+        {
+          alive = true;
+          try { sleep( SLEEP_FOR_WORKERS_TICK ); } catch( InterruptedException ie ) {}
+        }
+    }
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  /* (non-Javadoc)
+   * @see java.lang.Thread#run()
+   */
+  @Override
+  public void run()
+  {
+    try
+    {
+      for(;;)
+      {
+        ArifactWriteData awd = _aq.getArtifact();
+
+        if( awd == null || awd.artifact == null )
+            break;
+        
+        writeArtifact( awd.artifact, awd.vFacs );
+      }
+    }
+    catch (InterruptedException e)
+    {
+    }
+    catch( RepositoryException e )
+    {
+      throw new RuntimeException(e);
+    }
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  public void writeArtifact( final Artifact artifact, final Set<StreamVerifierFactory> vFacs )
+      throws RepositoryException
+  {
+    if( artifact == null )
+      return;
+    
+    boolean isPom = "pom".equals( artifact.getType() );
+    
+    byte [] pomBlob = artifact.getPomBlob();
+    boolean hasPomBlob = pomBlob != null && pomBlob.length > 0;
+    
+    InputStream in = artifact.getStream();
+    if( in == null )
+    {
+      File aFile = artifact.getFile();
+      if( aFile == null && !isPom )
+      {
+        throw new RepositoryException( LANG.getMessage( "artifact.no.stream", artifact.toString() ) );
+      }
+
+      try
+      {
+        in = new FileInputStream( aFile );
+      }
+      catch( FileNotFoundException e )
+      {
+        if( !isPom )
+          throw new RepositoryException( e );
+      }
+    }
+    DefaultArtifactVersion dav = new DefaultArtifactVersion( artifact.getVersion() );
+    Quality aq = dav.getQuality();
+    boolean isSnapshot = aq.equals( Quality.SNAPSHOT_QUALITY ) || aq.equals( Quality.SNAPSHOT_TS_QUALITY );
+
+    String relGroupPath = artifact.getGroupId().replace( '.', '/' )+"/"+artifact.getArtifactId();
+    String versionDirName = isSnapshot ? (dav.getBase()+'-'+Artifact.SNAPSHOT_VERSION) : artifact.getVersion();
+    String relVersionPath = relGroupPath + '/' + versionDirName;
+    
+    String lockDir = null;
+    FileLockBundle fLock = null;
+
+    try
+    {
+
+      if( isPom )
+      {
+        if( in == null && !hasPomBlob )
+          throw new RepositoryException( LANG.getMessage( "pom.artifact.no.stream", artifact.toString() ) );
+        
+        if( in != null )
+        {
+          byte [] pomBlobBytes = FileUtil.readRawData( in );
+          hasPomBlob = pomBlobBytes != null && pomBlobBytes.length > 0;
+          if( hasPomBlob )
+            pomBlob = pomBlobBytes;
+        }
+      }
+
+      // create folders
+      lockDir = _repoDir.getAbsolutePath()+'/'+relGroupPath;
+
+      File gav = new File( lockDir );
+      gav.mkdirs();
+
+//    haveLock = FileUtil.lockDir( lockDir, SLEEP_FOR_LOCK, SLEEP_FOR_LOCK_TICK );
+//    if( !haveLock )
+//      throw new RepositoryException( _lang.getMessage( "cannot.lock.gav", lockDir, ""+SLEEP_FOR_LOCK ) );
+      fLock = FileUtil.lockDir( lockDir, SLEEP_FOR_LOCK, SLEEP_FOR_LOCK_TICK );
+      if( fLock == null )
+        throw new RepositoryException( LANG.getMessage( "cannot.lock.gav", lockDir, ""+SLEEP_FOR_LOCK ) );
+
+      String fName = _repoDir.getAbsolutePath()+'/'+relVersionPath+'/'+artifact.getBaseName()+'.'+artifact.getType();
+      
+      if( !isPom ) // first - take care of the binary
+      {
+        FileUtil.writeAndSign( fName, in, vFacs );
+        artifact.setFile( new File(fName) );
+      }
+
+      // GA metadata
+      File mdFile = new File( _repoDir, relGroupPath+'/'+_repo.getMetadataName() );
+      updateGAMetadata( mdFile, artifact, versionDirName, aq, vFacs );
+
+      // now - GAV metadata
+      mdFile = new File( _repoDir, relVersionPath+'/'+_repo.getMetadataName() );
+      updateGAVMetadata( mdFile, artifact, aq, vFacs );
+
+      // if classier - nothing else to do :)
+      if( artifact.hasClassifier() )
+        return;
+      
+      if( hasPomBlob )
+      {
+        FileUtil.writeAndSign( _repoDir.getAbsolutePath()+'/'+relVersionPath
+                              +'/'+artifact.getArtifactId()+'-'+artifact.getVersion()+".pom", pomBlob, vFacs
+                              );
+      }
+        
+    }
+    catch( Exception e )
+    {
+      throw new RepositoryException( e );
+    }
+    finally
+    {
+      if( fLock != null )
+        fLock.release();
+            if ( in != null )
+            {
+                try
+                {
+                    in.close();
+                }
+                catch ( IOException e )
+                {
+                    // ignore, tried our best to clean up
+                }
+            }
+    }
+    
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  private void updateGAMetadata(  final File mdFile
+                                , final Artifact artifact
+                                , final String version
+                                , final Quality aq
+                                , final Set<StreamVerifierFactory> vFacs
+                              )
+  throws MetadataException, IOException, StreamObserverException
+  {
+    Metadata md = null;
+    
+    if( mdFile.exists() )
+    {
+      try
+      {
+        byte [] mdBytes = FileUtil.readRawData( mdFile );
+        
+        if( mdBytes == null )
+          throw new MetadataException( LANG.getMessage( "file.is.empty", mdFile.getAbsolutePath() ));
+        
+        md = MetadataBuilder.read( new ByteArrayInputStream(mdBytes) );
+      }
+      catch( MetadataException e )
+      {
+        throw e;
+      }
+    }
+    else
+    {
+      md = new Metadata();
+      md.setGroupId( artifact.getGroupId() );
+      md.setArtifactId( artifact.getArtifactId() );
+    }
+    
+    MetadataOperation mdOp = new AddVersionOperation( new StringOperand( version ) ); 
+    
+    byte [] resBytes = MetadataBuilder.changeMetadata( md, mdOp );
+
+    FileUtil.writeAndSign( mdFile.getAbsolutePath(), resBytes, vFacs );
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  private void updateGAVMetadata( final File mdFile
+                                , final Artifact artifact
+                                , final Quality aq
+                                , final Set<StreamVerifierFactory> vFacs
+                              )
+  throws MetadataException, IOException, StreamObserverException
+  {
+    Metadata md = null;
+    
+    if( mdFile.exists() )
+    {
+      byte [] mdBytes = FileUtil.readRawData( mdFile );
+      md = MetadataBuilder.read( new ByteArrayInputStream(mdBytes) );
+    }
+    else
+    {
+      md = new Metadata();
+      md.setGroupId( artifact.getGroupId() );
+      md.setArtifactId( artifact.getArtifactId() );
+      md.setVersion( artifact.getVersion() );
+    }
+    List<MetadataOperation> mdOps = new ArrayList<MetadataOperation>(2);
+    
+    if( aq.equals( Quality.SNAPSHOT_TS_QUALITY ) )
+    {
+      Snapshot sn = MetadataBuilder.createSnapshot( artifact.getVersion() );
+      sn.setLocalCopy( true );
+      mdOps.add( new SetSnapshotOperation( new SnapshotOperand(sn) ) );
+    }
+    
+    mdOps.add( new AddVersionOperation( new StringOperand(artifact.getVersion()) ) ); 
+ 
+//System.out.println("added "+artifact.getVersion());
+//System.out.flush();
+    byte [] resBytes = MetadataBuilder.changeMetadata( md, mdOps );
+    FileUtil.writeAndSign( mdFile.getAbsolutePath(), resBytes, vFacs );
+  }
+  //---------------------------------------------------------------------------------------------------------------
+  //---------------------------------------------------------------------------------------------------------------
+}
+//=================================================================================================================
+class ArifactWriteData
+{
+  Artifact artifact;
+  Set<StreamVerifierFactory> vFacs;
+  
+  public ArifactWriteData(Artifact artifact, Set<StreamVerifierFactory> vFacs)
+  {
+    this.artifact = artifact;
+    this.vFacs = vFacs;
+  }
+}
+//=================================================================================================================
+class ArtifactQueue
+{
+  LinkedList<ArifactWriteData> queue = new LinkedList<ArifactWriteData>();
+  boolean empty = false;
+  
+  public synchronized void addArtifact( ArifactWriteData awd )
+  {
+    queue.addLast( awd );
+    empty = false;
+    notify();
+  }
+
+  public synchronized ArifactWriteData getArtifact()
+  throws InterruptedException
+  {
+    if( empty )
+      return null;
+
+    while( queue.isEmpty() )
+      wait();
+    
+    ArifactWriteData res = queue.removeFirst();
+    
+    if( res.artifact == null )
+    {
+      empty = true;
+      return null;
+    }
+
+    return res;
+  }
+}
+//=================================================================================================================

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2Factory.java
URL: http://svn.apache.org/viewvc/maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2Factory.java?rev=767705&view=auto
==============================================================================
--- maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2Factory.java (added)
+++ maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2Factory.java Wed Apr 22 22:56:48 2009
@@ -0,0 +1,50 @@
+/**
+ *  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.local.m2;
+
+import org.apache.maven.mercury.repository.api.AbstractRepository;
+import org.apache.maven.mercury.repository.api.LocalRepository;
+import org.apache.maven.mercury.repository.api.Repository;
+import org.apache.maven.mercury.repository.api.RepositoryException;
+import org.apache.maven.mercury.repository.api.RepositoryWriter;
+import org.apache.maven.mercury.repository.api.RepositoryWriterFactory;
+import org.codehaus.plexus.lang.DefaultLanguage;
+import org.codehaus.plexus.lang.Language;
+
+public class LocalRepositoryWriterM2Factory
+implements RepositoryWriterFactory
+{
+  private static final Language LANG = new DefaultLanguage( LocalRepositoryWriterM2Factory.class );
+  private static final LocalRepositoryWriterM2Factory FACTORY = new LocalRepositoryWriterM2Factory();
+  
+  static 
+  {
+    AbstractRepository.register( AbstractRepository.DEFAULT_REPOSITORY_TYPE, FACTORY );
+  }
+  
+  public RepositoryWriter getWriter( Repository repo )
+  throws RepositoryException
+  {
+    if( repo == null || !(repo instanceof LocalRepository) )
+      throw new RepositoryException( LANG.getMessage( "bad.repository.type", repo == null ? "null" : repo.getClass().getName() ) );
+    
+    return new LocalRepositoryWriterM2( (LocalRepository)repo );
+  }
+
+}

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2Factory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/mercury/trunk/mercury-core/src/main/java/org/apache/maven/mercury/repository/local/m2/LocalRepositoryWriterM2Factory.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision