import org.apache.archiva.metadata.repository.MetadataResolver;
import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.metadata.repository.storage.maven2.MavenProjectFacet;
+import org.apache.archiva.model.ArchivaArtifact;
+import org.apache.archiva.repository.ManagedRepositoryContent;
+import org.apache.archiva.repository.RepositoryContentFactory;
+import org.apache.archiva.repository.RepositoryException;
+import org.apache.archiva.repository.RepositoryNotFoundException;
import org.apache.archiva.rest.api.model.Artifact;
import org.apache.archiva.rest.api.model.ArtifactContentEntry;
import org.apache.archiva.rest.api.model.BrowseResult;
import org.apache.archiva.rest.api.model.VersionsList;
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
import org.apache.archiva.rest.api.services.BrowseService;
+import org.apache.archiva.rest.services.utils.ArtifactContentEntryComparator;
import org.apache.archiva.rest.services.utils.TreeDependencyNodeVisitor;
import org.apache.archiva.security.ArchivaSecurityException;
import org.apache.commons.collections.CollectionUtils;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
+import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
/**
* @author Olivier Lamy
@Inject
private DependencyTreeBuilder dependencyTreeBuilder;
+ @Inject
+ private RepositoryContentFactory repositoryContentFactory;
+
public BrowseResult getRootGroups( String repositoryId )
throws ArchivaRestServiceException
{
}
public List<ArtifactContentEntry> getArtifactContentEntries( String groupId, String artifactId, String version,
- String path, String repositoryId )
+ String classifier, String type, String path,
+ String repositoryId )
throws ArchivaRestServiceException
{
- return null;
+ List<String> selectedRepos = getSelectedRepos( repositoryId );
+ try
+ {
+ for ( String repoId : selectedRepos )
+ {
+
+ ManagedRepositoryContent managedRepositoryContent =
+ repositoryContentFactory.getManagedRepositoryContent( repoId );
+ ArchivaArtifact archivaArtifact = new ArchivaArtifact( groupId, artifactId, version, classifier,
+ StringUtils.isEmpty( type ) ? "jar" : type,
+ repositoryId );
+ File file = managedRepositoryContent.toFile( archivaArtifact );
+ if ( file.exists() )
+ {
+ return readFileEntries( file, path );
+ }
+ }
+ }
+ catch ( IOException e )
+ {
+ log.error( e.getMessage(), e );
+ throw new ArchivaRestServiceException( e.getMessage(),
+ Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
+ }
+ catch ( RepositoryNotFoundException e )
+ {
+ log.error( e.getMessage(), e );
+ throw new ArchivaRestServiceException( e.getMessage(),
+ Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
+ }
+ catch ( RepositoryException e )
+ {
+ log.error( e.getMessage(), e );
+ throw new ArchivaRestServiceException( e.getMessage(),
+ Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() );
+ }
+ return Collections.emptyList();
}
//---------------------------
// internals
//---------------------------
+ protected List<ArtifactContentEntry> readFileEntries( File file, String filterPath )
+ throws IOException
+ {
+ Map<String, ArtifactContentEntry> artifactContentEntryMap = new HashMap<String, ArtifactContentEntry>();
+ int filterDepth = StringUtils.countMatches( filterPath, "/" );
+ if ( filterDepth == 0 )
+ {
+ filterDepth = 1;
+ }
+ JarFile jarFile = new JarFile( file );
+ try
+ {
+ Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
+ while ( jarEntryEnumeration.hasMoreElements() )
+ {
+ JarEntry entry = jarEntryEnumeration.nextElement();
+ String entryName = entry.getName();
+ String entryRootPath = getRootPath( entryName );
+ int depth = StringUtils.countMatches( entryName, "/" );
+ if ( StringUtils.isEmpty( filterPath ) && !artifactContentEntryMap.containsKey( entryRootPath ) )
+ {
+
+ artifactContentEntryMap.put( entryRootPath,
+ new ArtifactContentEntry( entryRootPath, !entry.isDirectory(),
+ depth ) );
+ }
+ else
+ {
+ if ( StringUtils.startsWith( entryName, filterPath ) && ( depth > filterDepth || (
+ !entry.isDirectory() && depth == filterDepth ) ) )
+ {
+ // remove last /
+ String cleanedEntryName = StringUtils.endsWith( entryName, "/" )
+ ? StringUtils.substringBeforeLast( entryName, "/" )
+ : entryName;
+ artifactContentEntryMap.put( cleanedEntryName,
+ new ArtifactContentEntry( cleanedEntryName, !entry.isDirectory(),
+ depth ) );
+ }
+ }
+ }
+
+ if ( StringUtils.isNotEmpty( filterPath ) )
+ {
+ // apply more filtering here
+ // search entries filterPath/blabla
+ Map<String, ArtifactContentEntry> filteredArtifactContentEntryMap =
+ new HashMap<String, ArtifactContentEntry>();
+
+ for ( Map.Entry<String, ArtifactContentEntry> entry : artifactContentEntryMap.entrySet() )
+ {
+ filteredArtifactContentEntryMap.put( entry.getKey(), entry.getValue() );
+ }
+
+ List<ArtifactContentEntry> sorted = getSmallerDepthEntries( filteredArtifactContentEntryMap );
+ if ( sorted == null )
+ {
+ return Collections.emptyList();
+ }
+ Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
+ return sorted;
+ }
+ }
+ finally
+ {
+ if ( jarFile != null )
+ {
+ jarFile.close();
+ }
+ }
+ List<ArtifactContentEntry> sorted = new ArrayList<ArtifactContentEntry>( artifactContentEntryMap.values() );
+ Collections.sort( sorted, ArtifactContentEntryComparator.INSTANCE );
+ return sorted;
+ }
+
+ private List<ArtifactContentEntry> getSmallerDepthEntries( Map<String, ArtifactContentEntry> entries )
+ {
+ int smallestDepth = Integer.MAX_VALUE;
+ Map<Integer, List<ArtifactContentEntry>> perDepthList = new HashMap<Integer, List<ArtifactContentEntry>>();
+ for ( Map.Entry<String, ArtifactContentEntry> entry : entries.entrySet() )
+ {
+
+ ArtifactContentEntry current = entry.getValue();
+
+ if ( current.getDepth() < smallestDepth )
+ {
+ smallestDepth = current.getDepth();
+ }
+
+ List<ArtifactContentEntry> currentList = perDepthList.get( current.getDepth() );
+
+ if ( currentList == null )
+ {
+ currentList = new ArrayList<ArtifactContentEntry>();
+ currentList.add( current );
+ perDepthList.put( current.getDepth(), currentList );
+ }
+ else
+ {
+ currentList.add( current );
+ }
+
+ }
+
+ return perDepthList.get( smallestDepth );
+ }
+
+ /**
+ * @param path
+ * @return org/apache -> org , org -> org
+ */
+ private String getRootPath( String path )
+ {
+ if ( StringUtils.contains( path, '/' ) )
+ {
+ return StringUtils.substringBefore( path, "/" );
+ }
+ return path;
+ }
+
private List<String> getSelectedRepos( String repositoryId )
throws ArchivaRestServiceException
{
*/
import org.apache.archiva.metadata.model.ProjectVersionMetadata;
+import org.apache.archiva.rest.api.model.ArtifactContentEntry;
import org.apache.archiva.rest.api.model.BrowseResult;
import org.apache.archiva.rest.api.model.BrowseResultEntry;
import org.apache.archiva.rest.api.model.Entry;
deleteTestRepo( testRepoId );
}
+
+ @Test
+ public void readArtifactContentEntries()
+ throws Exception
+ {
+ String testRepoId = "test-repo";
+ // force guest user creation if not exists
+ if ( getUserService( authorizationHeader ).getGuestUser() == null )
+ {
+ assertNotNull( getUserService( authorizationHeader ).createGuestUser() );
+ }
+
+ createAndIndexRepo( testRepoId, new File( getBasedir(), "src/test/repo-with-osgi" ).getAbsolutePath(), false );
+
+ BrowseService browseService = getBrowseService( authorizationHeader, true );
+
+ List<ArtifactContentEntry> artifactContentEntries =
+ browseService.getArtifactContentEntries( "commons-logging", "commons-logging", "1.1", null, null, null,
+ testRepoId );
+
+ log.info( "artifactContentEntries: {}", artifactContentEntries );
+
+ assertThat( artifactContentEntries ).isNotNull().isNotEmpty().hasSize( 2 ).contains(
+ new ArtifactContentEntry( "org", false, 1 ), new ArtifactContentEntry( "META-INF", false, 1 ) );
+ deleteTestRepo( testRepoId );
+ }
+
+ @Test
+ public void readArtifactContentEntriesRootPath()
+ throws Exception
+ {
+ String testRepoId = "test-repo";
+ // force guest user creation if not exists
+ if ( getUserService( authorizationHeader ).getGuestUser() == null )
+ {
+ assertNotNull( getUserService( authorizationHeader ).createGuestUser() );
+ }
+
+ createAndIndexRepo( testRepoId, new File( getBasedir(), "src/test/repo-with-osgi" ).getAbsolutePath(), false );
+
+ BrowseService browseService = getBrowseService( authorizationHeader, true );
+
+ List<ArtifactContentEntry> artifactContentEntries =
+ browseService.getArtifactContentEntries( "commons-logging", "commons-logging", "1.1", null, null, "org",
+ testRepoId );
+
+ log.info( "artifactContentEntries: {}", artifactContentEntries );
+
+ assertThat( artifactContentEntries ).isNotNull().isNotEmpty().hasSize( 1 ).contains(
+ new ArtifactContentEntry( "org/apache", false, 2 ) );
+ deleteTestRepo( testRepoId );
+ }
}