package org.apache.archiva.webdav; /* * 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 junit.framework.TestCase; import org.apache.archiva.admin.model.RepositoryAdminException; import org.apache.archiva.admin.model.beans.ManagedRepository; import org.apache.archiva.admin.model.beans.RepositoryGroup; import org.apache.archiva.admin.model.remote.RemoteRepositoryAdmin; import org.apache.archiva.admin.repository.DefaultRepositoryCommonValidator; import org.apache.archiva.admin.repository.group.DefaultRepositoryGroupAdmin; import org.apache.archiva.admin.repository.managed.DefaultManagedRepositoryAdmin; import org.apache.archiva.common.plexusbridge.PlexusSisuBridge; import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException; import org.apache.archiva.configuration.ArchivaConfiguration; import org.apache.archiva.configuration.Configuration; import org.apache.archiva.configuration.RepositoryGroupConfiguration; import org.apache.archiva.proxy.DefaultRepositoryProxyConnectors; import org.apache.archiva.proxy.model.ProxyFetchResult; import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.RepositoryContentFactory; import org.apache.archiva.repository.content.maven2.ManagedDefaultRepositoryContent; import org.apache.archiva.repository.content.maven2.RepositoryRequest; import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner; import org.apache.commons.io.FileUtils; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavResourceLocator; import org.apache.jackrabbit.webdav.DavServletRequest; import org.apache.jackrabbit.webdav.DavServletResponse; import org.easymock.IMocksControl; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.context.ApplicationContext; import org.springframework.test.context.ContextConfiguration; import javax.inject.Inject; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import static org.easymock.EasyMock.*; /** * ArchivaDavResourceFactoryTest */ @RunWith( ArchivaSpringJUnit4ClassRunner.class ) @ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath*:/spring-context.xml" } ) public class ArchivaDavResourceFactoryTest extends TestCase { private static final String RELEASES_REPO = "releases"; private static final String INTERNAL_REPO = "internal"; private static final String LOCAL_MIRROR_REPO = "local-mirror"; private static final String LEGACY_REPO = "legacy-repo"; private static final String LOCAL_REPO_GROUP = "local"; private OverridingArchivaDavResourceFactory resourceFactory; private IMocksControl requestControl; private DavServletRequest request; private IMocksControl repoRequestControl; private RepositoryRequest repoRequest; private IMocksControl responseControl; private DavServletResponse response; private IMocksControl archivaConfigurationControl; private ArchivaConfiguration archivaConfiguration; private Configuration config; private IMocksControl repoContentFactoryControl; private RepositoryContentFactory repoFactory; @Inject ApplicationContext applicationContext; @Inject PlexusSisuBridge plexusSisuBridge; @Inject DefaultManagedRepositoryAdmin defaultManagedRepositoryAdmin; @Inject RemoteRepositoryAdmin remoteRepositoryAdmin; @Inject DefaultRepositoryGroupAdmin defaultRepositoryGroupAdmin; @Before @Override public void setUp() throws Exception { super.setUp(); requestControl = createControl(); request = requestControl.createMock( DavServletRequest.class ); responseControl = createControl(); response = responseControl.createMock( DavServletResponse.class ); //responseControl.setDefaultMatcher( MockControl.ALWAYS_MATCHER ); archivaConfigurationControl = createControl(); archivaConfiguration = archivaConfigurationControl.createMock( ArchivaConfiguration.class ); config = new Configuration(); expect( archivaConfiguration.getConfiguration() ).andReturn( config ).times( 5, 20 ); archivaConfiguration.save( config ); expectLastCall().times( 1, 4 ); archivaConfigurationControl.replay(); defaultManagedRepositoryAdmin.setArchivaConfiguration( archivaConfiguration ); ( (DefaultRepositoryCommonValidator) defaultManagedRepositoryAdmin.getRepositoryCommonValidator() ).setArchivaConfiguration( archivaConfiguration ); if ( defaultManagedRepositoryAdmin.getManagedRepository( RELEASES_REPO ) == null ) { defaultManagedRepositoryAdmin.addManagedRepository( createManagedRepository( RELEASES_REPO, new File( "target/test-classes/" + RELEASES_REPO ).getPath(), "default" ), false, null ); } if ( defaultManagedRepositoryAdmin.getManagedRepository( INTERNAL_REPO ) == null ) { defaultManagedRepositoryAdmin.addManagedRepository( createManagedRepository( INTERNAL_REPO, new File( "target/test-classes/" + INTERNAL_REPO ).getPath(), "default" ), false, null ); } RepositoryGroup repoGroupConfig = new RepositoryGroup(); repoGroupConfig.setId( LOCAL_REPO_GROUP ); repoGroupConfig.addRepository( RELEASES_REPO ); repoGroupConfig.addRepository( INTERNAL_REPO ); defaultRepositoryGroupAdmin.setArchivaConfiguration( archivaConfiguration ); if ( defaultManagedRepositoryAdmin.getManagedRepository( LOCAL_REPO_GROUP ) == null ) { defaultRepositoryGroupAdmin.addRepositoryGroup( repoGroupConfig, null ); } repoContentFactoryControl = createControl(); repoFactory = repoContentFactoryControl.createMock( RepositoryContentFactory.class ); repoRequestControl = createControl(); repoRequest = repoRequestControl.createMock( RepositoryRequest.class ); resourceFactory = new OverridingArchivaDavResourceFactory( applicationContext, plexusSisuBridge, archivaConfiguration ); resourceFactory.setArchivaConfiguration( archivaConfiguration ); resourceFactory.setRepositoryFactory( repoFactory ); resourceFactory.setRepositoryRequest( repoRequest ); resourceFactory.setConnectors( new OverridingRepositoryProxyConnectors() ); resourceFactory.setRemoteRepositoryAdmin( remoteRepositoryAdmin ); resourceFactory.setManagedRepositoryAdmin( defaultManagedRepositoryAdmin ); } private ManagedRepository createManagedRepository( String id, String location, String layout ) { ManagedRepository repoConfig = new ManagedRepository(); repoConfig.setId( id ); repoConfig.setName( id ); repoConfig.setLocation( location ); repoConfig.setLayout( layout ); return repoConfig; } private ManagedRepositoryContent createManagedRepositoryContent( String repoId ) throws RepositoryAdminException { ManagedRepositoryContent repoContent = new ManagedDefaultRepositoryContent(); repoContent.setRepository( defaultManagedRepositoryAdmin.getManagedRepository( repoId ) ); return repoContent; } @After @Override public void tearDown() throws Exception { super.tearDown(); } // MRM-1232 - Unable to get artifacts from repositories which requires Repository Manager role using repository group @Test public void testRepositoryGroupFirstRepositoryRequiresAuthentication() throws Exception { DavResourceLocator locator = new ArchivaDavResourceLocator( "", "/repository/" + LOCAL_REPO_GROUP + "/org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar", LOCAL_REPO_GROUP, new ArchivaDavLocatorFactory() ); ManagedRepositoryContent internalRepo = createManagedRepositoryContent( INTERNAL_REPO ); ManagedRepositoryContent releasesRepo = createManagedRepositoryContent( RELEASES_REPO ); try { archivaConfigurationControl.reset(); expect( archivaConfiguration.getConfiguration() ).andReturn( config ).times( 3 ); expect( request.getMethod() ).andReturn( "GET" ).times( 3 ); expect( request.getPathInfo() ).andReturn( "org/apache/archiva" ).times( 0, 2 ); expect( repoFactory.getManagedRepositoryContent( RELEASES_REPO ) ).andReturn( releasesRepo ); expect( request.getRemoteAddr() ).andReturn( "http://localhost:8080" ).times( 2 ); expect( request.getDavSession() ).andReturn( new ArchivaDavSession() ).times( 2 ); expect( request.getContextPath() ).andReturn( "" ).times( 2 ); expect( repoRequest.isSupportFile( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( true ); expect( repoRequest.isDefault( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( false ); expect( repoRequest.toArtifactReference( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( null ); expect( repoRequest.toNativePath( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar", internalRepo ) ).andReturn( new File( config.findManagedRepositoryById( INTERNAL_REPO ).getLocation(), "target/test-classes/internal/org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ).getPath() ); expect( repoFactory.getManagedRepositoryContent( INTERNAL_REPO ) ).andReturn( internalRepo ); expect( repoRequest.isArchetypeCatalog( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( false ); archivaConfigurationControl.replay(); requestControl.replay(); repoContentFactoryControl.replay(); repoRequestControl.replay(); resourceFactory.createResource( locator, request, response ); archivaConfigurationControl.verify(); requestControl.verify(); repoContentFactoryControl.verify(); repoRequestControl.verify(); fail( "A DavException with 401 error code should have been thrown." ); } catch ( DavException e ) { assertEquals( 401, e.getErrorCode() ); } } @Test public void testRepositoryGroupLastRepositoryRequiresAuthentication() throws Exception { DavResourceLocator locator = new ArchivaDavResourceLocator( "", "/repository/" + LOCAL_REPO_GROUP + "/org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar", LOCAL_REPO_GROUP, new ArchivaDavLocatorFactory() ); List<RepositoryGroupConfiguration> repoGroups = new ArrayList<>(); RepositoryGroupConfiguration repoGroup = new RepositoryGroupConfiguration(); repoGroup.setId( LOCAL_REPO_GROUP ); repoGroup.addRepository( INTERNAL_REPO ); repoGroup.addRepository( RELEASES_REPO ); repoGroups.add( repoGroup ); config.setRepositoryGroups( repoGroups ); ManagedRepositoryContent internalRepo = createManagedRepositoryContent( INTERNAL_REPO ); ManagedRepositoryContent releasesRepo = createManagedRepositoryContent( RELEASES_REPO ); try { archivaConfigurationControl.reset(); expect( archivaConfiguration.getConfiguration() ).andReturn( config ).times( 3 ); expect( request.getMethod() ).andReturn( "GET" ).times( 3 ); expect( request.getPathInfo() ).andReturn( "org/apache/archiva" ).times( 0, 2 ); expect( repoFactory.getManagedRepositoryContent( INTERNAL_REPO ) ).andReturn( internalRepo ); expect( repoFactory.getManagedRepositoryContent( RELEASES_REPO ) ).andReturn( releasesRepo ); expect( request.getRemoteAddr() ).andReturn( "http://localhost:8080" ).times( 2 ); expect( request.getDavSession() ).andReturn( new ArchivaDavSession() ).times( 2 ); expect( request.getContextPath() ).andReturn( "" ).times( 2 ); expect( repoRequest.isSupportFile( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( false ); expect( repoRequest.isDefault( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( false ); expect( repoRequest.toArtifactReference( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( null ); expect( repoRequest.toNativePath( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar", internalRepo ) ).andReturn( new File( config.findManagedRepositoryById( INTERNAL_REPO ).getLocation(), "target/test-classes/internal/org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ).getPath() ); expect( repoRequest.isArchetypeCatalog( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( false ); archivaConfigurationControl.replay(); requestControl.replay(); repoContentFactoryControl.replay(); repoRequestControl.replay(); resourceFactory.createResource( locator, request, response ); archivaConfigurationControl.verify(); requestControl.verify(); repoContentFactoryControl.verify(); repoRequestControl.verify(); fail( "A DavException with 401 error code should have been thrown." ); } catch ( DavException e ) { assertEquals( 401, e.getErrorCode() ); } } @Test public void testRepositoryGroupArtifactDoesNotExistInAnyOfTheReposAuthenticationDisabled() throws Exception { DavResourceLocator locator = new ArchivaDavResourceLocator( "", "/repository/" + LOCAL_REPO_GROUP + "/org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar", LOCAL_REPO_GROUP, new ArchivaDavLocatorFactory() ); defaultManagedRepositoryAdmin.addManagedRepository( createManagedRepository( LOCAL_MIRROR_REPO, new File( "target/test-classes/local-mirror" ).getPath(), "default" ), false, null ); List<RepositoryGroupConfiguration> repoGroups = new ArrayList<>(); RepositoryGroupConfiguration repoGroup = new RepositoryGroupConfiguration(); repoGroup.setId( LOCAL_REPO_GROUP ); repoGroup.addRepository( INTERNAL_REPO ); repoGroup.addRepository( LOCAL_MIRROR_REPO ); repoGroups.add( repoGroup ); config.setRepositoryGroups( repoGroups ); ManagedRepositoryContent internalRepo = createManagedRepositoryContent( INTERNAL_REPO ); ManagedRepositoryContent localMirrorRepo = createManagedRepositoryContent( LOCAL_MIRROR_REPO ); try { archivaConfigurationControl.reset(); expect( archivaConfiguration.getConfiguration() ).andReturn( config ).times( 3 ); expect( request.getMethod() ).andReturn( "GET" ).times( 5 ); expect( request.getPathInfo() ).andReturn( "org/apache/archiva" ).times( 0, 2 ); expect( repoFactory.getManagedRepositoryContent( INTERNAL_REPO ) ).andReturn( internalRepo ); expect( repoFactory.getManagedRepositoryContent( LOCAL_MIRROR_REPO ) ).andReturn( localMirrorRepo ); expect( request.getRemoteAddr() ).andReturn( "http://localhost:8080" ).times( 4 ); expect( request.getDavSession() ).andReturn( new ArchivaDavSession() ).times( 4 ); expect( request.getContextPath() ).andReturn( "" ).times( 2 ); expect( repoRequest.isSupportFile( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( false ).times( 2 ); expect( repoRequest.isDefault( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( false ).times( 2 ); expect( repoRequest.toArtifactReference( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( null ).times( 2 ); expect( repoRequest.toNativePath( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar", internalRepo ) ).andReturn( new File( config.findManagedRepositoryById( INTERNAL_REPO ).getLocation(), "target/test-classes/internal/org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ).getPath() ); expect( repoRequest.toNativePath( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar", localMirrorRepo ) ) .andReturn( new File( config.findManagedRepositoryById( LOCAL_MIRROR_REPO ).getLocation(), "target/test-classes/internal/org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ).getPath() ); expect( repoRequest.isArchetypeCatalog( "org/apache/archiva/archiva/1.2-SNAPSHOT/archiva-1.2-SNAPSHOT.jar" ) ).andReturn( false ).times( 2 ); archivaConfigurationControl.replay(); requestControl.replay(); repoContentFactoryControl.replay(); repoRequestControl.replay(); resourceFactory.createResource( locator, request, response ); archivaConfigurationControl.verify(); requestControl.verify(); repoContentFactoryControl.verify(); repoRequestControl.verify(); fail( "A DavException with 404 error code should have been thrown." ); } catch ( DavException e ) { assertEquals( 404, e.getErrorCode() ); } } // MRM-1239 @Test public void testRequestArtifactMetadataThreePartsRepoHasDefaultLayout() throws Exception { // should fetch metadata DavResourceLocator locator = new ArchivaDavResourceLocator( "", "/repository/" + INTERNAL_REPO + "/eclipse/jdtcore/maven-metadata.xml", INTERNAL_REPO, new ArchivaDavLocatorFactory() ); ManagedRepositoryContent internalRepo = createManagedRepositoryContent( INTERNAL_REPO ); // use actual object (this performs the isMetadata, isDefault and isSupportFile check!) RepositoryRequest repoRequest = new RepositoryRequest( ); resourceFactory.setRepositoryRequest( repoRequest ); try { archivaConfigurationControl.reset(); expect( archivaConfiguration.getConfiguration() ).andReturn( config ).times( 2 ); expect( repoFactory.getManagedRepositoryContent( INTERNAL_REPO ) ).andReturn( internalRepo ); expect( request.getMethod() ).andReturn( "GET" ).times( 4 ); expect( request.getRemoteAddr() ).andReturn( "http://localhost:8080" ).times( 3 ); expect( request.getContextPath() ).andReturn( "" ).times( 1 ); expect( request.getDavSession() ).andReturn( new ArchivaDavSession() ).times( 2 ); expect( request.getRequestURI() ).andReturn( "http://localhost:8080/archiva/repository/" + INTERNAL_REPO + "/eclipse/jdtcore/maven-metadata.xml" ); response.setHeader( "Pragma", "no-cache" ); expectLastCall(); response.setHeader( "Cache-Control", "no-cache" ); expectLastCall(); response.setDateHeader( eq("Last-Modified"), anyLong() ); expectLastCall(); archivaConfigurationControl.replay(); repoContentFactoryControl.replay(); requestControl.replay(); responseControl.replay(); resourceFactory.createResource( locator, request, response ); archivaConfigurationControl.verify(); repoContentFactoryControl.verify(); requestControl.verify(); responseControl.verify(); } catch ( DavException e ) { fail( "A DavException should not have been thrown!" ); } } @Test public void testRequestArtifactMetadataTwoPartsRepoHasDefaultLayout() throws Exception { // should not fetch metadata DavResourceLocator locator = new ArchivaDavResourceLocator( "", "/repository/" + INTERNAL_REPO + "/eclipse/maven-metadata.xml", INTERNAL_REPO, new ArchivaDavLocatorFactory() ); ManagedRepositoryContent internalRepo = createManagedRepositoryContent( INTERNAL_REPO ); // use actual object (this performs the isMetadata, isDefault and isSupportFile check!) RepositoryRequest repoRequest = new RepositoryRequest( ); resourceFactory.setRepositoryRequest( repoRequest ); try { archivaConfigurationControl.reset(); expect( archivaConfiguration.getConfiguration() ).andReturn( config ).times( 2 ); expect( repoFactory.getManagedRepositoryContent( INTERNAL_REPO ) ).andReturn( internalRepo ); expect( request.getMethod() ).andReturn( "GET" ).times( 3 ); expect( request.getRemoteAddr() ).andReturn( "http://localhost:8080" ).times( 3 ); expect( request.getDavSession() ).andReturn( new ArchivaDavSession() ).times( 2 ); expect( request.getContextPath() ).andReturn( "" ).times( 2 ); archivaConfigurationControl.replay(); repoContentFactoryControl.replay(); requestControl.replay(); resourceFactory.createResource( locator, request, response ); archivaConfigurationControl.verify(); repoContentFactoryControl.verify(); requestControl.verify(); fail( "A 404 error should have been thrown!" ); } catch ( DavException e ) { assertEquals( 404, e.getErrorCode() ); } } @Test public void testRequestMetadataRepoIsLegacy() throws Exception { defaultManagedRepositoryAdmin.addManagedRepository( createManagedRepository( LEGACY_REPO, new File( "target/test-classes/" + LEGACY_REPO ).getPath(), "legacy" ), false, null ); DavResourceLocator locator = new ArchivaDavResourceLocator( "", "/repository/" + LEGACY_REPO + "/eclipse/maven-metadata.xml", LEGACY_REPO, new ArchivaDavLocatorFactory() ); ManagedRepositoryContent legacyRepo = createManagedRepositoryContent( LEGACY_REPO ); // use actual object (this performs the isMetadata, isDefault and isSupportFile check!) RepositoryRequest repoRequest = new RepositoryRequest( ); resourceFactory.setRepositoryRequest( repoRequest ); try { archivaConfigurationControl.reset(); expect( archivaConfiguration.getConfiguration() ).andReturn( config ).times( 2 ); expect( repoFactory.getManagedRepositoryContent( LEGACY_REPO ) ).andReturn( legacyRepo ); expect( request.getMethod() ).andReturn( "GET" ).times( 3 ); expect( request.getRemoteAddr() ).andReturn( "http://localhost:8080" ).times( 3 ); expect( request.getDavSession() ).andReturn( new ArchivaDavSession() ).times( 2 ); expect( request.getContextPath() ).andReturn( "" ).times( 2 ); archivaConfigurationControl.replay(); repoContentFactoryControl.replay(); requestControl.replay(); resourceFactory.createResource( locator, request, response ); archivaConfigurationControl.verify(); repoContentFactoryControl.verify(); requestControl.verify(); fail( "A 404 error should have been thrown!" ); } catch ( DavException e ) { assertEquals( 404, e.getErrorCode() ); } } class OverridingArchivaDavResourceFactory extends ArchivaDavResourceFactory { OverridingArchivaDavResourceFactory( ApplicationContext applicationContext, PlexusSisuBridge plexusSisuBridge, ArchivaConfiguration archivaConfiguration ) throws PlexusSisuBridgeException { super( applicationContext, plexusSisuBridge, archivaConfiguration ); } @Override protected boolean isAuthorized( DavServletRequest request, String repositoryId ) throws DavException { if ( RELEASES_REPO.equals( repositoryId ) ) { throw new UnauthorizedDavException( repositoryId, "You are not authenticated and authorized to access any repository." ); } else { return true; } } @Override protected String getActivePrincipal( DavServletRequest request ) { return "guest"; } } class OverridingRepositoryProxyConnectors extends DefaultRepositoryProxyConnectors { @Override public ProxyFetchResult fetchMetadataFromProxies( ManagedRepositoryContent repository, String logicalPath ) { File target = new File( repository.getRepoRoot(), logicalPath ); try { FileUtils.copyFile( new File( "target/test-classes/maven-metadata.xml" ), target ); } catch ( IOException e ) { } return new ProxyFetchResult( target, true ); } } }