| /** |
| * 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.IOException; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.apache.maven.mercury.artifact.Artifact; |
| import org.apache.maven.mercury.artifact.ArtifactBasicMetadata; |
| 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.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.ArtifactBasicResults; |
| 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.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 static ArtifactLocation calculateLocation( String root, ArtifactBasicMetadata bmd, AbstractRepOpResult res ) |
| { |
| ArtifactLocation loc = new ArtifactLocation( root, bmd ); |
| |
| File gaDir = new File( root, loc.getGaPath() ); |
| |
| if( !gaDir.exists() ) |
| { |
| res.addError( bmd, new RepositoryException( _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() ) |
| ) |
| { |
| boolean noSnapshots = Artifact.RELEASE_VERSION.equals( loc.getVersion() ); |
| loc.setVersion( null ); |
| DefaultArtifactVersion tempDav = null; |
| DefaultArtifactVersion tempDav2 = null; |
| |
| File [] files = gaDir.listFiles(); |
| |
| // find latest |
| for( File vf : files ) |
| { |
| if( vf.isFile() ) |
| continue; |
| |
| String vn = vf.getName(); |
| |
| // RELEASE? |
| if( noSnapshots && vn.endsWith( Artifact.SNAPSHOT_VERSION )) |
| continue; |
| |
| if( loc.getVersion() == null ) |
| { |
| loc.setVersion( vn ); |
| tempDav = new DefaultArtifactVersion( vn ); |
| continue; |
| } |
| |
| tempDav2 = new DefaultArtifactVersion( vn ); |
| if( tempDav2.compareTo( tempDav ) > 0 ) |
| { |
| loc.setVersion( vn ); |
| tempDav = tempDav2; |
| } |
| |
| } |
| |
| if( loc.getVersion() == null ) |
| { |
| res.addError( bmd, new RepositoryException( _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() ) ) ); |
| return null; |
| } |
| |
| if( !findLatestSnapshot( bmd, loc, res ) ) |
| return null; |
| |
| } |
| // time stamped snapshot requested |
| else if( vq.equals( Quality.SNAPSHOT_TS_QUALITY )) |
| { |
| loc.setVersionDir( loc.getBaseVersion()+FileUtil.DASH+Artifact.SNAPSHOT_VERSION ); |
| } |
| |
| return loc; |
| } |
| //--------------------------------------------------------------------------------------------------------------- |
| public ArtifactResults readArtifacts( Collection<ArtifactBasicMetadata> 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( ArtifactBasicMetadata bmd : query ) |
| { |
| DefaultArtifact da = bmd instanceof DefaultArtifact ? (DefaultArtifact)bmd : new DefaultArtifact( bmd ); |
| |
| ArtifactLocation loc = calculateLocation( _repoDir.getAbsolutePath(), bmd, 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() ) ) ); |
| continue; |
| } |
| |
| try // reading pom if one exists |
| { |
| if( checkFile( binary, vFacs ) ) |
| { |
| da.setFile( binary ); |
| da.setTracker( this._repo ); |
| } |
| |
| |
| if( "pom".equals( bmd.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", bmd.toString()) ); |
| } |
| |
| da.setVersion( loc.getVersion() ); |
| res.add( bmd, 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 ArtifactBasicResults readDependencies( Collection<ArtifactBasicMetadata> query ) |
| throws RepositoryException, |
| IllegalArgumentException |
| { |
| if( query == null || query.size() < 1 ) |
| return null; |
| |
| ArtifactBasicResults ror = null; |
| |
| File pomFile = null; |
| for( ArtifactBasicMetadata bmd : query ) |
| { |
| String pomPath = bmd.getGroupId().replace( '.', '/' ) |
| + "/" + bmd.getArtifactId() |
| + "/" + bmd.getVersion() |
| + "/" + bmd.getArtifactId()+'-'+bmd.getVersion() |
| + ".pom" |
| ; |
| |
| pomFile = new File( _repoDir, pomPath ); |
| if( ! pomFile.exists() ) |
| { |
| _log.warn( "file \""+pomPath+"\" does not exist in local repo" ); |
| continue; |
| } |
| |
| // TODO HIGH og: delegate POM processing to maven-project |
| // for testing purpose - I plug in my test processor |
| try |
| { |
| List<ArtifactBasicMetadata> deps = _mdProcessor.getDependencies( bmd, _mdReader == null ? this : _mdReader |
| , System.getenv() |
| , System.getProperties() |
| ); |
| //for(ArtifactBasicMetadata d : deps ) |
| //{ |
| // System.out.println("======> "+d.getScope() ); |
| //} |
| ror = ArtifactBasicResults.add( ror, bmd, deps ); |
| } |
| catch( Exception e ) |
| { |
| _log.warn( "error reading "+bmd.toString()+" dependencies", e ); |
| continue; |
| } |
| |
| } |
| |
| return ror; |
| } |
| //--------------------------------------------------------------------------------------------------------------- |
| private static boolean findLatestSnapshot( ArtifactBasicMetadata bmd, ArtifactLocation loc, AbstractRepOpResult res ) |
| { |
| File binary = new File( loc.getAbsPath() ); |
| |
| if( binary.exists() ) |
| return true; |
| |
| // no real SNAPSHOT file, let's try to find one |
| File gavDir = new File( loc.getGavPath() ); |
| File [] files = gavDir.listFiles(); |
| loc.setVersion( null ); |
| DefaultArtifactVersion tempDav = null; |
| DefaultArtifactVersion tempDav2 = null; |
| |
| int aLen = loc.getBaseName().length(); |
| |
| // find latest |
| for( File vf : files ) |
| { |
| if( vf.isFile() ) |
| continue; |
| |
| String vn = vf.getName().substring( aLen+1 ); |
| |
| // no snapshots |
| if( vn.endsWith( Artifact.SNAPSHOT_VERSION )) |
| continue; |
| |
| if( loc.getVersion() == null ) |
| { |
| loc.setVersion( vn ); |
| tempDav = new DefaultArtifactVersion( vn ); |
| continue; |
| } |
| |
| tempDav2 = new DefaultArtifactVersion( vn ); |
| if( tempDav2.compareTo( tempDav ) > 0 ) |
| { |
| loc.setVersion( vn ); |
| tempDav = tempDav2; |
| } |
| |
| } |
| |
| if( loc.getVersion() == null ) |
| { |
| res.addError( bmd, new RepositoryException( _lang.getMessage( "snapshot.not.found", bmd.toString(), gavDir.getAbsolutePath() ) ) ); |
| return false; |
| } |
| |
| return true; |
| } |
| //--------------------------------------------------------------------------------------------------------------- |
| /** |
| * direct disk search, no redirects - I cannot process pom files :( |
| */ |
| public ArtifactBasicResults readVersions( Collection<ArtifactBasicMetadata> query ) |
| throws RepositoryException, IllegalArgumentException |
| { |
| if( query == null || query.size() < 1 ) |
| return null; |
| |
| ArtifactBasicResults res = new ArtifactBasicResults( query.size() ); |
| |
| File gaDir = null; |
| for( ArtifactBasicMetadata bmd : query ) |
| { |
| gaDir = new File( _repoDir, bmd.getGroupId().replace( '.', '/' )+"/"+bmd.getArtifactId() ); |
| if( ! gaDir.exists() ) |
| continue; |
| |
| File [] versionFiles = gaDir.listFiles(); |
| |
| VersionRange versionQuery; |
| try |
| { |
| versionQuery = VersionRangeFactory.create( bmd.getVersion(), _repo.getVersionRangeQualityRange() ); |
| } |
| catch( VersionException e ) |
| { |
| res = ArtifactBasicResults.add( res, bmd, new RepositoryException(e) ); |
| continue; |
| } |
| |
| Quality vq = new Quality( bmd.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 ); |
| |
| if( loc == null ) |
| continue; |
| |
| ArtifactBasicMetadata vmd = new ArtifactBasicMetadata(); |
| vmd.setGroupId( bmd.getGroupId() ); |
| vmd.setArtifactId( bmd.getArtifactId() ); |
| vmd.setClassifier( bmd.getClassifier() ); |
| vmd.setType( bmd.getType() ); |
| vmd.setVersion( loc.getVersion() ); |
| |
| res = ArtifactBasicResults.add( res, bmd, 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; |
| |
| ArtifactBasicMetadata vmd = new ArtifactBasicMetadata(); |
| vmd.setGroupId( bmd.getGroupId() ); |
| vmd.setArtifactId( bmd.getArtifactId() ); |
| vmd.setClassifier( bmd.getClassifier() ); |
| vmd.setType( bmd.getType() ); |
| vmd.setVersion( vf.getName() ); |
| |
| res = ArtifactBasicResults.add( res, bmd, vmd ); |
| } |
| } |
| return res; |
| } |
| //--------------------------------------------------------------------------------------------------------------- |
| public byte[] readRawData( ArtifactBasicMetadata bmd, String classifier, String type ) |
| throws MetadataReaderException |
| { |
| return readRawData( relPathOf(bmd, classifier, type, null ) ); |
| } |
| //--------------------------------------------------------------------------------------------------------------- |
| private static String relPathOf( ArtifactBasicMetadata bmd, String classifier, String type, DefaultArtifactVersion inDav ) |
| { |
| DefaultArtifactVersion dav = inDav; |
| if( inDav == null ) |
| dav = new DefaultArtifactVersion( bmd.getVersion() ); |
| Quality aq = dav.getQuality(); |
| boolean isSnapshot = aq.equals( Quality.SNAPSHOT_QUALITY ) || aq.equals( Quality.SNAPSHOT_TS_QUALITY ); |
| |
| String bmdPath = bmd.getGroupId().replace( '.', '/' )+'/'+bmd.getArtifactId() |
| +'/' + ( isSnapshot ? dav.getBase()+'-'+Artifact.SNAPSHOT_VERSION : bmd.getVersion() ); |
| |
| String path = bmdPath+'/'+bmd.getBaseName(classifier)+'.' + (type == null ? bmd.getType() : type ); |
| |
| return path ; |
| } |
| //--------------------------------------------------------------------------------------------------------------- |
| public byte[] readRawData( String path ) |
| 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 ); |
| 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() |
| { |
| } |
| //--------------------------------------------------------------------------------------------------------------- |
| } |