Browse Source

Modifying query interface and implementing new repo content methods

pull/60/head
Martin Stockhammer 4 years ago
parent
commit
fb63a9d09d

+ 3
- 2
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java View File

@@ -186,7 +186,7 @@ public interface ManagedRepositoryContent extends RepositoryContent
* @throws ItemNotFoundException if the specified coordinates cannot be found in the repository
* @throws ContentAccessException if the access to the underlying storage failed
*/
Stream<? extends Artifact> getArtifactStream( ItemSelector selector) throws ContentAccessException;
Stream<? extends Artifact> newArtifactStream( ItemSelector selector) throws ContentAccessException;


/**
@@ -247,8 +247,9 @@ public interface ManagedRepositoryContent extends RepositoryContent
* @param item the item from where the artifacts should be returned
* @return a stream of artifacts. The stream is auto closable. You should always make sure, that the stream
* is closed after use.
* @throws ContentAccessException if the access to the underlying storage failed
*/
Stream<? extends Artifact> getArtifactStream( ContentItem item ) throws ContentAccessException;
Stream<? extends Artifact> newArtifactStream( ContentItem item ) throws ContentAccessException;


/**

+ 5
- 5
archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/content/ItemSelector.java View File

@@ -30,7 +30,7 @@ public interface ItemSelector
{

/**
* Selects the namespace to search for. You can use the {@link #searchSubNamespaces()} flag
* Selects the namespace to search for. You can use the {@link #recurse()} flag
* to decide, if only the given namespace or the namespace and all sub namespaces (if they exist) should be
* queried. If empty, the root namespace is searched.
* @return the namespace to search
@@ -96,10 +96,10 @@ public interface ItemSelector
Map<String, String> getAttributes( );

/**
* Returns <code>true</code>, if not only the given namespace but all sub namespaces
* of the given namespace should be queried too.
* Returns <code>true</code>, if the query should recurse into all sub directories for
* retrieving artifacts.
*/
boolean searchSubNamespaces();
boolean recurse();

/**
* <code>true</code>, if all files/assets should be returned that match the given selector,
@@ -107,7 +107,7 @@ public interface ItemSelector
* Related assets are e.g. hash files or signature files.
* @return <code>true</code>, if all assets should be found otherwise <code>false</code>
*/
boolean findRelatedArtifacts();
boolean includeRelatedArtifacts();

default boolean hasNamespace( )
{

+ 87
- 25
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/content/base/ArchivaItemSelector.java View File

@@ -32,17 +32,17 @@ import java.util.Map;
public class ArchivaItemSelector implements ItemSelector
{

private String projectId = null;
private String version = null;
private String artifactVersion = null;
private String artifactId = null;
private String projectId = "";
private String version = "";
private String artifactVersion = "";
private String artifactId = "";
private String namespace = "";
private String type = null;
private String classifier = null;
private String extension = null;
private String type = "";
private String classifier = "";
private String extension = "";
private Map<String, String> attributes;
private boolean searchRelatedArtifacts = false;
private boolean searchSubNamespaces = false;
private boolean includeRelatedArtifacts = false;
private boolean recurse = false;


private ArchivaItemSelector( )
@@ -61,49 +61,70 @@ public class ArchivaItemSelector implements ItemSelector

public Builder withNamespace( String namespace )
{
selector.namespace = namespace;
if (namespace!=null)
{
selector.namespace = namespace;
}
return this;
}


public Builder withProjectId( String projectId )
{
selector.projectId = projectId;
if (projectId!=null)
{
selector.projectId = projectId;
}
return this;
}


public Builder withVersion( String version )
{
selector.version = version;
if (version!=null)
{
selector.version = version;
}
return this;
}


public Builder withArtifactVersion( String artifactVersion )
{
selector.artifactVersion = artifactVersion;
if (artifactVersion!=null)
{
selector.artifactVersion = artifactVersion;
}
return this;
}


public Builder withArtifactId( String artifactId )
{
selector.artifactId = artifactId;
if (artifactId!=null)
{
selector.artifactId = artifactId;
}
return this;
}


public Builder withType( String type )
{
selector.type = type;
if (type!=null)
{
selector.type = type;
}
return this;
}


public Builder withClassifier( String classifier )
{
selector.classifier = classifier;
if (classifier != null )
{
selector.classifier = classifier;
}
return this;
}

@@ -116,17 +137,20 @@ public class ArchivaItemSelector implements ItemSelector

public Builder withExtension( String extension )
{
selector.extension = extension;
if (extension!=null)
{
selector.extension = extension;
}
return this;
}

public Builder enableSearchRelatedArtifacts() {
selector.searchRelatedArtifacts = true;
public Builder includeRelatedArtifacts() {
selector.includeRelatedArtifacts = true;
return this;
}

public Builder enableSearchSubNamespaces() {
selector.searchSubNamespaces = true;
public Builder recurse() {
selector.recurse = true;
return this;
}

@@ -221,15 +245,15 @@ public class ArchivaItemSelector implements ItemSelector
}

@Override
public boolean searchSubNamespaces( )
public boolean recurse( )
{
return searchSubNamespaces;
return recurse;
}

@Override
public boolean findRelatedArtifacts( )
public boolean includeRelatedArtifacts( )
{
return searchRelatedArtifacts;
return includeRelatedArtifacts;
}

@Override
@@ -243,4 +267,42 @@ public class ArchivaItemSelector implements ItemSelector
{
return StringUtils.isNotEmpty( extension );
}

@Override
public boolean equals( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass( ) != o.getClass( ) ) return false;

ArchivaItemSelector that = (ArchivaItemSelector) o;

if ( includeRelatedArtifacts != that.includeRelatedArtifacts ) return false;
if ( recurse != that.recurse ) return false;
if ( !projectId.equals( that.projectId ) ) return false;
if ( !version.equals( that.version ) ) return false;
if ( !artifactVersion.equals( that.artifactVersion ) ) return false;
if ( !artifactId.equals( that.artifactId ) ) return false;
if ( !namespace.equals( that.namespace ) ) return false;
if ( !type.equals( that.type ) ) return false;
if ( !classifier.equals( that.classifier ) ) return false;
if ( !extension.equals( that.extension ) ) return false;
return attributes != null ? attributes.equals( that.attributes ) : that.attributes == null;
}

@Override
public int hashCode( )
{
int result = projectId.hashCode( );
result = 31 * result + version.hashCode( );
result = 31 * result + artifactVersion.hashCode( );
result = 31 * result + artifactId.hashCode( );
result = 31 * result + namespace.hashCode( );
result = 31 * result + type.hashCode( );
result = 31 * result + classifier.hashCode( );
result = 31 * result + extension.hashCode( );
result = 31 * result + ( attributes != null ? attributes.hashCode( ) : 0 );
result = 31 * result + ( includeRelatedArtifacts ? 1 : 0 );
result = 31 * result + ( recurse ? 1 : 0 );
return result;
}
}

+ 2
- 2
archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java View File

@@ -133,7 +133,7 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
}

@Override
public Stream<? extends Artifact> getArtifactStream( ItemSelector selector ) throws ContentAccessException
public Stream<? extends Artifact> newArtifactStream( ItemSelector selector ) throws ContentAccessException
{
return null;
}
@@ -169,7 +169,7 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
}

@Override
public Stream<? extends Artifact> getArtifactStream( ContentItem item ) throws ContentAccessException
public Stream<? extends Artifact> newArtifactStream( ContentItem item ) throws ContentAccessException
{
return null;
}

+ 2
- 2
archiva-modules/archiva-base/archiva-repository-scanner/src/test/java/org/apache/archiva/repository/scanner/mock/ManagedRepositoryContentMock.java View File

@@ -134,7 +134,7 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
}

@Override
public Stream<? extends Artifact> getArtifactStream( ItemSelector selector ) throws ContentAccessException
public Stream<? extends Artifact> newArtifactStream( ItemSelector selector ) throws ContentAccessException
{
return null;
}
@@ -170,7 +170,7 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
}

@Override
public Stream<? extends Artifact> getArtifactStream( ContentItem item ) throws ContentAccessException
public Stream<? extends Artifact> newArtifactStream( ContentItem item ) throws ContentAccessException
{
return null;
}

+ 2
- 2
archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java View File

@@ -138,7 +138,7 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
}

@Override
public Stream<? extends Artifact> getArtifactStream( ItemSelector selector ) throws ContentAccessException
public Stream<? extends Artifact> newArtifactStream( ItemSelector selector ) throws ContentAccessException
{
return null;
}
@@ -174,7 +174,7 @@ public class ManagedRepositoryContentMock implements ManagedRepositoryContent
}

@Override
public Stream<? extends Artifact> getArtifactStream( ContentItem item ) throws ContentAccessException
public Stream<? extends Artifact> newArtifactStream( ContentItem item ) throws ContentAccessException
{
return null;
}

+ 194
- 64
archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven/content/ManagedDefaultRepositoryContent.java View File

@@ -24,8 +24,6 @@ import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.configuration.FileTypes;
import org.apache.archiva.metadata.maven.MavenMetadataReader;
import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
import org.apache.archiva.repository.maven.metadata.storage.ArtifactMappingProvider;
import org.apache.archiva.repository.maven.metadata.storage.DefaultArtifactMappingProvider;
import org.apache.archiva.model.ArchivaArtifact;
import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.model.ProjectReference;
@@ -43,10 +41,13 @@ import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.repository.content.Namespace;
import org.apache.archiva.repository.content.Project;
import org.apache.archiva.repository.content.Version;
import org.apache.archiva.repository.content.base.ArchivaItemSelector;
import org.apache.archiva.repository.content.base.ArchivaNamespace;
import org.apache.archiva.repository.content.base.ArchivaProject;
import org.apache.archiva.repository.content.base.ArchivaVersion;
import org.apache.archiva.repository.content.base.builder.ArtifactOptBuilder;
import org.apache.archiva.repository.maven.metadata.storage.ArtifactMappingProvider;
import org.apache.archiva.repository.maven.metadata.storage.DefaultArtifactMappingProvider;
import org.apache.archiva.repository.storage.RepositoryStorage;
import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.archiva.repository.storage.util.StorageUtil;
@@ -55,6 +56,7 @@ import org.apache.commons.lang3.StringUtils;

import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.Name;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
@@ -70,6 +72,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
* ManagedDefaultRepositoryContent
@@ -511,48 +514,6 @@ public class ManagedDefaultRepositoryContent
return getStorage( ).getAsset( path.toString( ) );
}

/*
* File filter to select certain artifacts using the selector data.
*/
private Predicate<StorageAsset> getFileFilterFromSelector(final ItemSelector selector) {
Predicate<StorageAsset> p = a -> a.isLeaf( );
StringBuilder fileNamePattern = new StringBuilder("^" );
if (selector.hasArtifactId()) {
fileNamePattern.append( Pattern.quote(selector.getArtifactId( )) ).append("-");
} else {
fileNamePattern.append("[A-Za-z0-9_\\-.]+-");
}
if (selector.hasArtifactVersion()) {
fileNamePattern.append( Pattern.quote(selector.getArtifactVersion( )) );
} else {
fileNamePattern.append( "[A-Za-z0-9_\\-.]+" );
}
String classifier = selector.hasClassifier( ) ? selector.getClassifier( ) :
( selector.hasType( ) ? MavenContentHelper.getClassifierFromType( selector.getType( ) ) : null );
if (classifier != null)
{
if ( "*".equals( classifier ) )
{
fileNamePattern.append( "-[A-Za-z0-9]+\\." );
}
else
{
fileNamePattern.append("-").append( Pattern.quote( classifier ) ).append( "\\." );
}
} else {
fileNamePattern.append( "\\." );
}
String extension = selector.hasExtension( ) ? selector.getExtension( ) :
( selector.hasType( ) ? MavenContentHelper.getArtifactExtension( selector ) : null );
if (extension != null) {
fileNamePattern.append( Pattern.quote( extension ) );
} else {
fileNamePattern.append( ".*" );
}
final Pattern pattern = Pattern.compile( fileNamePattern.toString() );
return p.and( a -> pattern.matcher( a.getName( ) ).matches());
}


/**
* Returns all the subdirectories of the given namespace directory as project.
@@ -620,41 +581,210 @@ public class ManagedDefaultRepositoryContent
}


/*
TBD
*/
/**
* See {@link #newArtifactStream(ItemSelector)}. This method collects the stream into a list.
*
* @param selector the selector for the artifacts
* @return the list of artifacts
* @throws ContentAccessException if the access to the underlying filesystem failed
*/
@Override
public List<? extends Artifact> getArtifacts( ItemSelector selector ) throws ContentAccessException
{
return null;
try(Stream<? extends Artifact> stream = newArtifactStream( selector )) {
return stream.collect( Collectors.toList());
}
}


/*
TBD
* File filter to select certain artifacts using the selector data.
*/
private Predicate<StorageAsset> getFileFilterFromSelector(final ItemSelector selector) {
Predicate<StorageAsset> p = a -> a.isLeaf( );
StringBuilder fileNamePattern = new StringBuilder("^" );
if (selector.hasArtifactId()) {
fileNamePattern.append( Pattern.quote(selector.getArtifactId( )) ).append("-");
} else {
fileNamePattern.append("[A-Za-z0-9_\\-.]+-");
}
if (selector.hasArtifactVersion()) {
fileNamePattern.append( Pattern.quote(selector.getArtifactVersion( )) );
} else {
fileNamePattern.append( "[A-Za-z0-9_\\-.]+" );
}
String classifier = selector.hasClassifier( ) ? selector.getClassifier( ) :
( selector.hasType( ) ? MavenContentHelper.getClassifierFromType( selector.getType( ) ) : null );
if (classifier != null)
{
if ( "*".equals( classifier ) )
{
fileNamePattern.append( "-[A-Za-z0-9]+\\." );
}
else
{
fileNamePattern.append("-").append( Pattern.quote( classifier ) ).append( "\\." );
}
} else {
fileNamePattern.append( "\\." );
}
String extension = selector.hasExtension( ) ? selector.getExtension( ) :
( selector.hasType( ) ? MavenContentHelper.getArtifactExtension( selector ) : null );
if (extension != null) {
if (selector.includeRelatedArtifacts())
{
fileNamePattern.append( Pattern.quote( extension ) ).append("(\\.[A-Za-z0-9]+)?");
} else {
fileNamePattern.append( Pattern.quote( extension ) );
}
} else {
fileNamePattern.append( "[A-Za-z0-9]+" );
}
final Pattern pattern = Pattern.compile( fileNamePattern.toString() );
return p.and( a -> pattern.matcher( a.getName( ) ).matches());
}


/**
* Returns the artifacts. The number of artifacts returned depend on the selector.
* If the selector sets the flag {@link ItemSelector#includeRelatedArtifacts()} to <code>true</code>,
* additional to the matching artifacts, related artifacts like hash values or signatures are included in the artifact
* stream.
* If the selector sets the flag {@link ItemSelector#recurse()} to <code>true</code>, artifacts of the given
* namespace and from all sub namespaces that start with the given namespace are returned.
* <ul>
* <li>If only a namespace is given, all artifacts with the given namespace or starting with the given
* namespace (see {@link ItemSelector#recurse()} are returned.</li>
* <li>If a namespace and a project id, or artifact id is given, the artifacts of all versions of the given
* namespace and project are returned.</li>
* <li>If a namespace and a project id or artifact id and a version is given, the artifacts of the given
* version are returned</li>
* </ul>
*
* There is no determinate order of the elements in the stream.
*
* Returned streams are auto closable and should be used in a try-with-resources statement.
*
* @param selector the item selector
* @throws ContentAccessException if the access to the underlying filesystem failed
*/
@Override
public Stream<? extends Artifact> getArtifactStream( ItemSelector selector ) throws ContentAccessException
public Stream<? extends Artifact> newArtifactStream( ItemSelector selector ) throws ContentAccessException
{
return null;
String projectId = selector.hasProjectId( ) ? selector.getProjectId( ) : ( selector.hasArtifactId( ) ? selector.getArtifactId( )
: null );
final Predicate<StorageAsset> filter = getFileFilterFromSelector( selector );
if (projectId!=null && selector.hasVersion()) {
return getAsset( selector.getNamespace( ), projectId, selector.getVersion( ) )
.list( ).stream( ).filter( filter )
.map( this::getArtifactFromPath );
} else if (projectId!=null) {
final StorageAsset projDir = getAsset( selector.getNamespace( ), projectId );
return projDir.list( ).stream( ).filter( StorageAsset::isContainer )
.map( StorageAsset::list )
.flatMap( List::stream )
.filter( filter )
.map( this::getArtifactFromPath );
} else
{
StorageAsset namespaceDir = getAsset( selector.getNamespace( ) );
if (selector.recurse())
{
return StorageUtil.newAssetStream( namespaceDir, true )
.filter( filter )
.map( this::getArtifactFromPath );

} else {
return namespaceDir.list( ).stream( )
.filter( StorageAsset::isContainer )
.map( StorageAsset::list )
.flatMap( List::stream )
.filter( StorageAsset::isContainer )
.map( StorageAsset::list )
.flatMap( List::stream )
.filter( filter )
.map(this::getArtifactFromPath);
}
}
}

/*
TBD
*/
/**
* Same as {@link #newArtifactStream(ContentItem)} but returns the collected stream as list.
*
* @param item the item the parent item
* @return the list of artifacts or a empty list of no artifacts where found
*/
@Override
public List<? extends Artifact> getArtifacts( ContentItem item )
{
return null;
try(Stream<? extends Artifact> stream = newArtifactStream( item )) {
return stream.collect( Collectors.toList());
}
}

/**
* Returns all artifacts
* @param item
* @return
* @throws ContentAccessException
*/
public Stream<? extends Artifact> newArtifactStream( Namespace item ) throws ContentAccessException
{
return newArtifactStream( ArchivaItemSelector.builder( ).withNamespace( item.getNamespace( ) ).build( ) );
}

/*
TBD
public Stream<? extends Artifact> newArtifactStream( Project item ) throws ContentAccessException
{
return newArtifactStream( ArchivaItemSelector.builder( ).withNamespace( item.getNamespace( ).getNamespace() )
.withProjectId( item.getId() ).build( ) );
}

public Stream<? extends Artifact> newArtifactStream( Version item ) throws ContentAccessException
{
return newArtifactStream( ArchivaItemSelector.builder( ).withNamespace( item.getProject().getNamespace( ).getNamespace() )
.withProjectId( item.getProject().getId() )
.withVersion( item.getVersion() ).build( ) );
}

/**
* Returns all related artifacts that match the given artifact. That means all artifacts that have
* the same filename plus an additional extension, e.g. ${fileName}.sha2
* @param item the artifact
* @return the stream of artifacts
* @throws ContentAccessException
*/
public Stream<? extends Artifact> newArtifactStream( Artifact item ) throws ContentAccessException
{
final Version v = item.getVersion( );
final String fileName = item.getFileName( );
final Predicate<StorageAsset> filter = ( StorageAsset a ) ->
a.getName( ).startsWith( fileName + "." );
return v.getAsset( ).list( ).stream( ).filter( filter )
.map( a -> getArtifactFromPath( a ) );
}
/**
* Returns the stream of artifacts that are children of the given item.
*
* @param item the item from where the artifacts should be returned
* @return
* @throws ContentAccessException
*/
@Override
public Stream<? extends Artifact> getArtifactStream( ContentItem item )
public Stream<? extends Artifact> newArtifactStream( ContentItem item ) throws ContentAccessException
{
return null;
if (item instanceof Namespace) {
return newArtifactStream( ( (Namespace) item ) );
} else if (item instanceof Project) {
return newArtifactStream( (Project) item );
} else if (item instanceof Version) {
return newArtifactStream( (Version) item );
} else if (item instanceof Artifact) {
return newArtifactStream( (Artifact) item );
} else
{
log.warn( "newArtifactStream for unsupported item requested: {}", item.getClass( ).getName( ) );
return Stream.empty( );
}
}

/**
@@ -1092,7 +1222,7 @@ public class ManagedDefaultRepositoryContent
public Set<String> getVersions( VersionedReference reference )
throws ContentNotFoundException, ContentAccessException, LayoutException
{
try(Stream<ArtifactReference> stream = getArtifactStream( reference ))
try(Stream<ArtifactReference> stream = newArtifactStream( reference ))
{
return stream.filter( Objects::nonNull )
.map( ar -> ar.getVersion( ) )
@@ -1230,7 +1360,7 @@ public class ManagedDefaultRepositoryContent
private ArtifactReference getFirstArtifact( VersionedReference reference )
throws ContentNotFoundException, LayoutException, IOException
{
try(Stream<ArtifactReference> stream = getArtifactStream( reference ))
try(Stream<ArtifactReference> stream = newArtifactStream( reference ))
{
return stream.findFirst( ).orElse( null );
} catch (RuntimeException e) {
@@ -1238,7 +1368,7 @@ public class ManagedDefaultRepositoryContent
}
}

private Stream<ArtifactReference> getArtifactStream(VersionedReference reference) throws ContentNotFoundException, LayoutException, IOException {
private Stream<ArtifactReference> newArtifactStream( VersionedReference reference) throws ContentNotFoundException, LayoutException, IOException {
final Path repoBase = getRepoDir( );
String path = toMetadataPath( reference );
Path versionDir = repoBase.resolve( path ).getParent();
@@ -1262,7 +1392,7 @@ public class ManagedDefaultRepositoryContent

public List<ArtifactReference> getArtifacts(VersionedReference reference) throws ContentNotFoundException, LayoutException, ContentAccessException
{
try (Stream<ArtifactReference> stream = getArtifactStream( reference ))
try (Stream<ArtifactReference> stream = newArtifactStream( reference ))
{
return stream.collect( Collectors.toList( ) );
} catch ( IOException e )
@@ -1277,7 +1407,7 @@ public class ManagedDefaultRepositoryContent
private boolean hasArtifact( VersionedReference reference )

{
try(Stream<ArtifactReference> stream = getArtifactStream( reference ))
try(Stream<ArtifactReference> stream = newArtifactStream( reference ))
{
return stream.anyMatch( e -> true );
} catch (ContentNotFoundException e) {

Loading…
Cancel
Save