Adding maven repo implementation and unit test

This commit is contained in:
Martin Stockhammer 2017-10-13 22:23:08 +02:00
parent 267b6a702b
commit 5121735795
14 changed files with 304 additions and 106 deletions

View File

@ -20,7 +20,10 @@ package org.apache.archiva.repository;
*/
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
/**
* Simple implementation of a managed repository.
@ -29,6 +32,8 @@ public abstract class AbstractManagedRepository extends AbstractRepository imple
{
private boolean blocksRedeployment = false;
private ManagedRepositoryContent content;
private Set<ReleaseScheme> activeReleaseSchemes = new HashSet<>( );
private Set<ReleaseScheme> uActiveReleaseSchemes = Collections.unmodifiableSet( activeReleaseSchemes );
public AbstractManagedRepository( RepositoryType type, String id, String name )
{
@ -62,4 +67,28 @@ public abstract class AbstractManagedRepository extends AbstractRepository imple
{
return blocksRedeployment;
}
@Override
public Set<ReleaseScheme> getActiveReleaseSchemes( )
{
return uActiveReleaseSchemes;
}
@Override
public void addActiveReleaseScheme( ReleaseScheme scheme )
{
this.activeReleaseSchemes.add(scheme);
}
@Override
public void removeActiveReleaseScheme( ReleaseScheme scheme )
{
this.activeReleaseSchemes.remove(scheme);
}
@Override
public void clearActiveReleaseSchemes( )
{
this.activeReleaseSchemes.clear();
}
}

View File

@ -26,11 +26,9 @@ import com.cronutils.parser.CronParser;
import org.apache.archiva.repository.features.RepositoryFeature;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@ -54,11 +52,8 @@ public abstract class AbstractRepository implements EditableRepository
private Set<URI> uFailoverLocations = Collections.unmodifiableSet( failoverLocations );
private boolean scanned = true;
String schedulingDefinition = "0 0 02 * *";
private boolean index;
private URI indexPath;
private boolean index = true;
private String layout;
private Set<ReleaseScheme> activeReleaseSchemes = new HashSet<>( );
private Set<ReleaseScheme> uActiveReleaseSchemes = Collections.unmodifiableSet( activeReleaseSchemes );
public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
public AbstractRepository(RepositoryType type, String id, String name) {
@ -144,24 +139,12 @@ public abstract class AbstractRepository implements EditableRepository
return index;
}
@Override
public URI getIndexPath( )
{
return indexPath;
}
@Override
public String getLayout( )
{
return layout;
}
@Override
public Set<ReleaseScheme> getActiveReleaseSchemes( )
{
return uActiveReleaseSchemes;
}
@Override
public abstract RepositoryCapabilities getCapabilities( );
@ -231,36 +214,12 @@ public abstract class AbstractRepository implements EditableRepository
this.index = hasIndex;
}
@Override
public void setIndexPath( URI indexPath )
{
this.indexPath = indexPath;
}
@Override
public void setLayout( String layout )
{
this.layout = layout;
}
@Override
public void addActiveReleaseScheme( ReleaseScheme scheme )
{
this.activeReleaseSchemes.add(scheme);
}
@Override
public void removeActiveReleaseScheme( ReleaseScheme scheme )
{
this.activeReleaseSchemes.remove(scheme);
}
@Override
public void clearActiveReleaseSchemes( )
{
this.activeReleaseSchemes.clear();
}
@Override
public void setSchedulingDefinition(String cronExpression) {
CronParser parser = new CronParser(CRON_DEFINITION);

View File

@ -35,4 +35,22 @@ public interface EditableManagedRepository extends EditableRepository, ManagedRe
* @param content
*/
void setContent(ManagedRepositoryContent content);
/**
* Adds an active release scheme. Release schemes may be combined.
* @param scheme the scheme to add.
*/
void addActiveReleaseScheme(ReleaseScheme scheme);
/**
* Removes an active release scheme from the set.
* @param scheme the scheme to remove.
*/
void removeActiveReleaseScheme(ReleaseScheme scheme);
/**
* Clears all active release schemes.
*/
void clearActiveReleaseSchemes();
}

View File

@ -113,34 +113,11 @@ public interface EditableRepository extends Repository
*/
void setIndex(boolean hasIndex);
/**
* Sets the path to the index directory. May be a relative or absolute URI.
* @param indexPath the path
*/
void setIndexPath(URI indexPath);
/**
* Sets the layout string.
* @param layout
*/
void setLayout(String layout);
/**
* Adds an active release scheme. Release schemes may be combined.
* @param scheme the scheme to add.
*/
void addActiveReleaseScheme(ReleaseScheme scheme);
/**
* Removes an active release scheme from the set.
* @param scheme the scheme to remove.
*/
void removeActiveReleaseScheme(ReleaseScheme scheme);
/**
* Clears all active release schemes.
*/
void clearActiveReleaseSchemes();
}

View File

@ -20,6 +20,8 @@ package org.apache.archiva.repository;
*/
import java.util.Set;
/**
* Represents a managed repository, that is readable and writable.
*/
@ -37,4 +39,11 @@ public interface ManagedRepository extends Repository {
* @return
*/
boolean blocksRedeployments();
/**
* Returns the release schemes that are active by this repository. E.g. for maven repositories
* this may either be a release repository, a snapshot repository or a combined repository.
* @return
*/
Set<ReleaseScheme> getActiveReleaseSchemes();
}

View File

@ -113,12 +113,6 @@ public interface Repository {
*/
boolean hasIndex();
/**
* Returns the path to the index parent folder. May be a HTTP URL or a file path.
* @return
*/
URI getIndexPath();
/**
* Returns a layout definition. The returned string may be implementation specific and is not
* standardized.
@ -127,13 +121,6 @@ public interface Repository {
*/
String getLayout();
/**
* Returns the release schemes that are active by this repository. E.g. for maven repositories
* this may either be a release repository, a snapshot repository or a combined repository.
* @return
*/
Set<ReleaseScheme> getActiveReleaseSchemes();
/**
* Returns the capabilities of the repository implementation.

View File

@ -34,7 +34,7 @@ public interface RepositoryProvider
{
Set<RepositoryType> provides();
ManagedRepository createManagedInstance( ManagedRepositoryConfiguration configuration);
ManagedRepository createManagedInstance( ManagedRepositoryConfiguration configuration) throws RepositoryException;
RemoteRepository createRemoteInstance( RemoteRepositoryConfiguration configuration);
RemoteRepository createRemoteInstance( RemoteRepositoryConfiguration configuration) throws RepositoryException;
}

View File

@ -100,7 +100,7 @@ public class RepositoryRegistry
ManagedRepository repo = createNewManagedRepository( providerMap.get( repositoryType ), repoConfig );
managedRepos.put(repo.getId(), repo);
} catch (Exception e) {
log.error("Could not create managed repository "+repoConfig.getId(), e);
log.error("Could not create managed repository {}: {}", repoConfig.getId(), e.getMessage(), e);
}
}
}
@ -142,8 +142,15 @@ public class RepositoryRegistry
{
RepositoryType repositoryType = RepositoryType.valueOf( repoConfig.getType( ) );
if (providerMap.containsKey( repositoryType )) {
try
{
remoteRepos.put(repoConfig.getId(), providerMap.get(repositoryType).createRemoteInstance( repoConfig ));
}
catch ( Exception e )
{
log.error("Could not create repository {} from config: {}", repoConfig.getId(), e.getMessage(), e);
}
}
}
return remoteRepos;

View File

@ -20,6 +20,8 @@ package org.apache.archiva.repository.features;
*/
import java.net.URI;
/**
*
* This feature provides some information about index creation.
@ -29,6 +31,8 @@ public class IndexCreationFeature implements RepositoryFeature<IndexCreationFeat
private boolean skipPackedIndexCreation = false;
private URI indexPath;
public IndexCreationFeature() {
}
@ -58,4 +62,24 @@ public class IndexCreationFeature implements RepositoryFeature<IndexCreationFeat
public void setSkipPackedIndexCreation(boolean skipPackedIndexCreation) {
this.skipPackedIndexCreation = skipPackedIndexCreation;
}
/**
* Returns the path that is used to store the index.
* @return the uri (may be relative or absolute)
*/
public URI getIndexPath( )
{
return indexPath;
}
/**
* Sets the path that is used to store the index.
* @param indexPath the uri to the index path (may be relative)
*/
public void setIndexPath( URI indexPath )
{
this.indexPath = indexPath;
}
}

View File

@ -289,6 +289,15 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<appserver.base>${project.build.directory}/test-repository</appserver.base>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>

View File

@ -30,7 +30,10 @@ import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.repository.features.RepositoryFeature;
import org.apache.archiva.repository.features.StagingRepositoryFeature;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
/**
* Maven2 managed repository implementation.
@ -97,4 +100,8 @@ public class MavenManagedRepository extends AbstractManagedRepository
}
return false;
}
}

View File

@ -46,8 +46,7 @@ public class MavenRemoteRepository extends AbstractRemoteRepository
new ReleaseScheme[] { ReleaseScheme.RELEASE, ReleaseScheme.SNAPSHOT },
new String[] { MavenManagedRepository.DEFAULT_LAYOUT, MavenManagedRepository.LEGACY_LAYOUT},
new String[] {},
new String[] {ArtifactCleanupFeature.class.getName(), IndexCreationFeature.class.getName(),
StagingRepositoryFeature.class.getName(), RemoteIndexFeature.class.getName()},
new String[] {RemoteIndexFeature.class.getName()},
true,
true,
true,

View File

@ -27,7 +27,7 @@ import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.PasswordCredentials;
import org.apache.archiva.repository.ReleaseScheme;
import org.apache.archiva.repository.RemoteRepository;
import org.apache.archiva.repository.Repository;
import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryProvider;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.features.ArtifactCleanupFeature;
@ -46,6 +46,7 @@ import java.time.Period;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Provider for the maven2 repository implementations
@ -53,6 +54,7 @@ import java.util.Set;
@Service("mavenRepositoryProvider")
public class MavenRepositoryProvider implements RepositoryProvider
{
private static final Logger log = LoggerFactory.getLogger( MavenRepositoryProvider.class );
static final Set<RepositoryType> TYPES = new HashSet<>( );
@ -66,22 +68,37 @@ public class MavenRepositoryProvider implements RepositoryProvider
return TYPES;
}
@Override
public ManagedRepository createManagedInstance( ManagedRepositoryConfiguration cfg )
{
MavenManagedRepository repo = new MavenManagedRepository(cfg.getId() ,cfg.getName());
private URI getURIFromConfig(String config) throws RepositoryException {
URI uri;
try {
uri = new URI(config);
if (uri.getScheme()==null) {
uri = new URI("file://"+config);
}
if (!"file".equals(uri.getScheme())) {
log.error("Bad URI scheme found: {}, URI={}", uri.getScheme(), uri);
throw new RepositoryException("The uri "+config+" is not valid. Only file:// URI is allowed for maven.");
}
} catch (URISyntaxException e) {
String newCfg = "file://"+config;
try
{
if (cfg.getLocation().startsWith("file:")) {
repo.setLocation( new URI(cfg.getLocation()) );
} else {
repo.setLocation( new URI("file://"+cfg.getLocation()) );
uri = new URI(newCfg);
}
}
catch ( URISyntaxException e )
catch ( URISyntaxException e1 )
{
log.error("Could not set repository uri "+cfg.getLocation());
log.error("Could not create URI from {} -> ", config, newCfg);
throw new RepositoryException( "The config entry "+config+" cannot be converted to URI." );
}
}
return uri;
}
@Override
public ManagedRepository createManagedInstance( ManagedRepositoryConfiguration cfg ) throws RepositoryException
{
MavenManagedRepository repo = new MavenManagedRepository(cfg.getId() ,cfg.getName());
repo.setLocation( getURIFromConfig( cfg.getLocation() ) );
setBaseConfig( repo, cfg );
repo.setSchedulingDefinition(cfg.getRefreshCronExpression());
repo.setBlocksRedeployment( cfg.isBlockRedeployments() );
@ -101,6 +118,7 @@ public class MavenRepositoryProvider implements RepositoryProvider
IndexCreationFeature indexCreationFeature = repo.getFeature( IndexCreationFeature.class ).get( );
indexCreationFeature.setSkipPackedIndexCreation( cfg.isSkipPackedIndexCreation() );
indexCreationFeature.setIndexPath( getURIFromConfig( cfg.getIndexDir() ) );
ArtifactCleanupFeature artifactCleanupFeature = repo.getFeature( ArtifactCleanupFeature.class ).get();
@ -111,6 +129,8 @@ public class MavenRepositoryProvider implements RepositoryProvider
return repo;
}
@Override
public RemoteRepository createRemoteInstance( RemoteRepositoryConfiguration cfg )
{
@ -147,9 +167,14 @@ public class MavenRepositoryProvider implements RepositoryProvider
repo.setExtraHeaders( cfg.getExtraHeaders() );
repo.setExtraParameters( cfg.getExtraParameters() );
PasswordCredentials credentials = new PasswordCredentials();
if (cfg.getPassword()!=null && cfg.getUsername()!=null)
{
credentials.setPassword( cfg.getPassword( ).toCharArray( ) );
credentials.setUsername( cfg.getUsername() );
repo.setCredentials( credentials );
} else {
credentials.setPassword( new char[0] );
}
return repo;
}
@ -161,20 +186,19 @@ public class MavenRepositoryProvider implements RepositoryProvider
{
if ( StringUtils.isEmpty( indexDir )) {
repo.setIndex( false );
repo.setIndexPath( null );
} else
{
if ( indexDir.startsWith( "file://" ) )
{
repo.setIndexPath( new URI( indexDir ) );
//repo.setIndexPath( new URI( indexDir ) );
}
else
{
repo.setIndexPath( new URI( "file://" + indexDir ) );
//repo.setIndexPath( new URI( "file://" + indexDir ) );
}
}
}
catch ( URISyntaxException e )
catch ( Exception e )
{
log.error("Could not set index path "+cfg.getIndexDir());
repo.setIndex(false);

View File

@ -0,0 +1,149 @@
package org.apache.archiva.repository.maven2;
/*
* 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.
*/
import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.ReleaseScheme;
import org.apache.archiva.repository.RemoteRepository;
import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.UnsupportedFeatureException;
import org.apache.archiva.repository.features.ArtifactCleanupFeature;
import org.apache.archiva.repository.features.IndexCreationFeature;
import org.apache.archiva.repository.features.RemoteIndexFeature;
import org.apache.archiva.repository.features.StagingRepositoryFeature;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import javax.inject.Inject;
import javax.inject.Named;
import java.time.Period;
import static org.junit.Assert.*;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@RunWith( ArchivaSpringJUnit4ClassRunner.class )
@ContextConfiguration( { "classpath*:/META-INF/spring-context.xml", "classpath:/spring-context-no-mock-conf.xml" } )
public class MavenRepositoryProviderTest
{
@Inject
@Named( "archivaConfiguration#default" )
ArchivaConfiguration archivaConfiguration;
MavenRepositoryProvider provider;
@Before
public void setUp()
throws Exception
{
provider = new MavenRepositoryProvider();
}
@Test
public void provides( ) throws Exception
{
assertEquals(1, provider.provides().size());
assertEquals( RepositoryType.MAVEN, provider.provides().iterator().next());
}
@Test
public void createManagedInstance( ) throws Exception
{
assertNotNull(archivaConfiguration);
assertNotNull(archivaConfiguration.getConfiguration());
ManagedRepositoryConfiguration repo = archivaConfiguration.getConfiguration().getManagedRepositories().get(0);
ManagedRepository mr = provider.createManagedInstance( repo );
assertNotNull(mr.getLocation());
assertTrue(mr.getLocation().toString().endsWith( "/repositories/internal" ));
assertEquals("Archiva Managed Internal Repository", mr.getName());
assertEquals(1, mr.getActiveReleaseSchemes().size());
assertEquals( ReleaseScheme.RELEASE, mr.getActiveReleaseSchemes().iterator().next());
assertEquals("internal", mr.getId());
assertTrue(mr.blocksRedeployments());
assertEquals("0 0 * * * ?", mr.getSchedulingDefinition());
assertTrue(mr.isScanned());
ArtifactCleanupFeature artifactCleanupFeature = mr.getFeature( ArtifactCleanupFeature.class ).get();
assertEquals( Period.ofDays( 30), artifactCleanupFeature.getRetentionTime());
assertFalse(artifactCleanupFeature.isDeleteReleasedSnapshots());
assertEquals(2, artifactCleanupFeature.getRetentionCount());
IndexCreationFeature indexCreationFeature = mr.getFeature( IndexCreationFeature.class ).get();
assertNotNull(indexCreationFeature.getIndexPath());
assertTrue(indexCreationFeature.getIndexPath().toString().endsWith("/repositories/internal/.indexer"));
assertTrue(indexCreationFeature.getIndexPath().isAbsolute());
assertFalse(indexCreationFeature.isSkipPackedIndexCreation());
StagingRepositoryFeature stagingRepositoryFeature = mr.getFeature( StagingRepositoryFeature.class ).get();
assertFalse(stagingRepositoryFeature.isStageRepoNeeded());
assertNull(stagingRepositoryFeature.getStagingRepository());
}
@Test
public void createRemoteInstance( ) throws Exception
{
assertNotNull(archivaConfiguration);
assertNotNull(archivaConfiguration.getConfiguration());
RemoteRepositoryConfiguration repo = archivaConfiguration.getConfiguration().getRemoteRepositories().get(0);
RemoteRepository mr = provider.createRemoteInstance( repo );
assertNotNull(mr.getLocation());
assertEquals("https://repo.maven.apache.org/maven2", mr.getLocation().toString());
assertEquals("Central Repository", mr.getName());
assertEquals("central", mr.getId());
assertEquals("0 0 08 ? * SUN", mr.getSchedulingDefinition());
assertTrue(mr.isScanned());
assertNull(mr.getLoginCredentials());
try
{
ArtifactCleanupFeature artifactCleanupFeature = mr.getFeature( ArtifactCleanupFeature.class ).get( );
throw new Exception("artifactCleanupFeature should not be available");
} catch ( UnsupportedFeatureException e ) {
// correct
}
try
{
IndexCreationFeature indexCreationFeature = mr.getFeature( IndexCreationFeature.class ).get( );
throw new Exception("indexCreationFeature should not be available");
} catch (UnsupportedFeatureException e) {
// correct
}
try
{
StagingRepositoryFeature stagingRepositoryFeature = mr.getFeature( StagingRepositoryFeature.class ).get( );
throw new Exception("stagingRepositoryFeature should not be available");
} catch (UnsupportedFeatureException e) {
// correct
}
RemoteIndexFeature remoteIndexFeature = mr.getFeature( RemoteIndexFeature.class ).get();
assertNull(remoteIndexFeature.getProxyId());
}
}