1 package org.apache.archiva.webdav;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import com.gargoylesoftware.htmlunit.*;
23 import junit.framework.TestCase;
24 import net.sf.ehcache.CacheManager;
25 import org.apache.archiva.configuration.ArchivaConfiguration;
26 import org.apache.archiva.configuration.Configuration;
27 import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
28 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
29 import org.apache.archiva.indexer.ArchivaIndexingContext;
30 import org.apache.archiva.repository.ManagedRepository;
31 import org.apache.archiva.repository.RepositoryRegistry;
32 import org.apache.archiva.repository.RepositoryType;
33 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
34 import org.apache.archiva.webdav.httpunit.MkColMethodWebRequest;
35 import org.apache.commons.io.FileUtils;
36 import org.apache.commons.io.IOUtils;
37 import org.apache.commons.lang3.StringUtils;
38 import org.junit.After;
39 import org.junit.Assert;
40 import org.junit.Before;
41 import org.junit.runner.RunWith;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.beans.BeansException;
45 import org.springframework.beans.factory.BeanFactory;
46 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
47 import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
48 import org.springframework.context.ApplicationContext;
49 import org.springframework.context.ApplicationEvent;
50 import org.springframework.context.MessageSourceResolvable;
51 import org.springframework.context.NoSuchMessageException;
52 import org.springframework.core.ResolvableType;
53 import org.springframework.core.env.Environment;
54 import org.springframework.core.io.Resource;
55 import org.springframework.mock.web.MockHttpServletRequest;
56 import org.springframework.mock.web.MockHttpServletResponse;
57 import org.springframework.mock.web.MockServletConfig;
58 import org.springframework.mock.web.MockServletContext;
59 import org.springframework.test.context.ContextConfiguration;
60 import org.springframework.web.context.WebApplicationContext;
62 import javax.inject.Inject;
63 import javax.servlet.Servlet;
64 import javax.servlet.ServletContext;
65 import javax.servlet.http.HttpServletRequest;
66 import javax.servlet.http.HttpServletResponse;
67 import java.io.IOException;
68 import java.io.InputStream;
69 import java.io.UnsupportedEncodingException;
70 import java.lang.annotation.Annotation;
72 import java.nio.charset.Charset;
73 import java.nio.file.Files;
74 import java.nio.file.Path;
75 import java.nio.file.Paths;
76 import java.util.Locale;
78 import java.util.concurrent.atomic.AtomicReference;
81 * AbstractRepositoryServletTestCase
83 @RunWith( ArchivaSpringJUnit4ClassRunner.class )
84 @ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath*:spring-context.xml",
85 "classpath*:/repository-servlet-simple.xml" } )
86 public abstract class AbstractRepositoryServletTestCase
89 protected static final String REPOID_INTERNAL = "internal";
91 protected Path repoRootInternal;
93 protected Path repoRootLegacy;
96 protected ArchivaConfiguration archivaConfiguration;
99 protected ApplicationContext applicationContext;
103 RepositoryRegistry repositoryRegistry;
105 protected Logger log = LoggerFactory.getLogger( getClass() );
107 private AtomicReference<Path> projectBase = new AtomicReference<>( );
108 private AtomicReference<Path> appserverBase = new AtomicReference<>( );
111 public Path getProjectBase() {
112 if (this.projectBase.get()==null) {
113 String pathVal = System.getProperty("mvn.project.base.dir");
115 if (StringUtils.isEmpty(pathVal)) {
116 baseDir= Paths.get("").toAbsolutePath();
118 baseDir = Paths.get(pathVal).toAbsolutePath();
120 this.projectBase.compareAndSet(null, baseDir);
122 return this.projectBase.get();
125 public Path getAppserverBase() {
126 if (appserverBase.get()==null)
128 String pathVal = System.getProperty( "appserver.base" );
130 if ( StringUtils.isNotEmpty( pathVal ) )
132 basePath = Paths.get( pathVal );
136 log.warn("Using relative path to working directory, appserver.base was not set!");
137 basePath = Paths.get( "target/appserver-base" );
139 appserverBase.set( basePath );
141 return appserverBase.get();
144 protected void saveConfiguration()
147 repositoryRegistry.setArchivaConfiguration(archivaConfiguration);
148 repositoryRegistry.reload();
149 saveConfiguration( archivaConfiguration );
161 System.setProperty( "appserver.base", getAppserverBase().toAbsolutePath().toString());
162 log.info("setUp appserverBase={}, projectBase={}, workingDir={}", getAppserverBase(), getProjectBase(), Paths.get("").toString());
164 repositoryRegistry.getRepositories().stream().forEach(r -> r.close());
166 org.apache.archiva.common.utils.FileUtils.deleteDirectory( getAppserverBase() );
168 Path testConf = getProjectBase().resolve( "src/test/resources/repository-archiva.xml" );
169 Path testConfDest = getAppserverBase().resolve("conf/archiva.xml" );
170 if ( Files.exists(testConfDest) )
172 org.apache.archiva.common.utils.FileUtils.deleteQuietly( testConfDest );
174 FileUtils.copyFile( testConf.toFile(), testConfDest.toFile() );
176 repoRootInternal = getAppserverBase().resolve("data/repositories/internal" );
177 repoRootLegacy = getAppserverBase().resolve( "data/repositories/legacy" );
178 Configuration config = archivaConfiguration.getConfiguration();
180 config.getManagedRepositories().clear();
182 config.addManagedRepository(
183 createManagedRepository( REPOID_INTERNAL, "Internal Test Repo", repoRootInternal, true ) );
184 config.getProxyConnectors().clear();
186 config.getRemoteRepositories().clear();
188 saveConfiguration( archivaConfiguration );
190 ArchivaIndexingContext ctx = repositoryRegistry.getManagedRepository( REPOID_INTERNAL ).getIndexingContext( );
193 if (repositoryRegistry.getIndexManager(RepositoryType.MAVEN)!=null) {
194 repositoryRegistry.getIndexManager(RepositoryType.MAVEN).pack(ctx);
201 CacheManager.getInstance().clearAll();
206 protected UnauthenticatedRepositoryServlet unauthenticatedRepositoryServlet =
207 new UnauthenticatedRepositoryServlet();
209 protected void startRepository()
213 final MockServletContext mockServletContext = new MockServletContext();
215 WebApplicationContext webApplicationContext =
216 new TestWebapplicationContext( applicationContext, mockServletContext );
218 mockServletContext.setAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
219 webApplicationContext );
221 MockServletConfig mockServletConfig = new MockServletConfig()
224 public ServletContext getServletContext()
226 return mockServletContext;
230 unauthenticatedRepositoryServlet.init( mockServletConfig );
234 protected String createVersionMetadata(String groupId, String artifactId, String version) {
235 return createVersionMetadata(groupId, artifactId, version, null, null, null);
238 protected String createVersionMetadata(String groupId, String artifactId, String version, String timestamp, String buildNumber, String lastUpdated) {
239 StringBuilder buf = new StringBuilder();
240 buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
241 buf.append("<metadata>\n");
242 buf.append(" <groupId>").append(groupId).append("</groupId>\n");
243 buf.append(" <artifactId>").append(artifactId).append("</artifactId>\n");
244 buf.append(" <version>").append(version).append("</version>\n");
245 boolean hasSnapshot = StringUtils.isNotBlank(timestamp) || StringUtils.isNotBlank(buildNumber);
246 boolean hasLastUpdated = StringUtils.isNotBlank(lastUpdated);
247 if (hasSnapshot || hasLastUpdated) {
248 buf.append(" <versioning>\n");
250 buf.append(" <snapshot>\n");
251 buf.append(" <buildNumber>").append(buildNumber).append("</buildNumber>\n");
252 buf.append(" <timestamp>").append(timestamp).append("</timestamp>\n");
253 buf.append(" </snapshot>\n");
255 if (hasLastUpdated) {
256 buf.append(" <lastUpdated>").append(lastUpdated).append("</lastUpdated>\n");
258 buf.append(" </versioning>\n");
260 buf.append("</metadata>");
261 return buf.toString();
265 public static class TestWebapplicationContext
266 implements WebApplicationContext
268 private ApplicationContext applicationContext;
270 private ServletContext servletContext;
272 TestWebapplicationContext( ApplicationContext applicationContext, ServletContext servletContext )
274 this.applicationContext = applicationContext;
278 public ServletContext getServletContext()
280 return servletContext;
284 public String getId()
286 return applicationContext.getId();
290 public String getApplicationName()
292 return applicationContext.getApplicationName();
296 public String getDisplayName()
298 return applicationContext.getDisplayName();
302 public long getStartupDate()
304 return applicationContext.getStartupDate();
308 public ApplicationContext getParent()
310 return applicationContext.getParent();
314 public AutowireCapableBeanFactory getAutowireCapableBeanFactory()
315 throws IllegalStateException
317 return applicationContext.getAutowireCapableBeanFactory();
321 public void publishEvent( ApplicationEvent applicationEvent )
323 applicationContext.publishEvent( applicationEvent );
327 public Environment getEnvironment()
329 return applicationContext.getEnvironment();
333 public BeanFactory getParentBeanFactory()
335 return applicationContext.getParentBeanFactory();
339 public boolean containsLocalBean( String s )
341 return applicationContext.containsLocalBean( s );
345 public boolean containsBeanDefinition( String s )
347 return applicationContext.containsBeanDefinition( s );
351 public int getBeanDefinitionCount()
353 return applicationContext.getBeanDefinitionCount();
357 public String[] getBeanDefinitionNames()
359 return applicationContext.getBeanDefinitionNames();
363 public String[] getBeanNamesForType( Class<?> aClass )
365 return applicationContext.getBeanNamesForType( aClass );
369 public String[] getBeanNamesForType( Class<?> aClass, boolean b, boolean b2 )
371 return applicationContext.getBeanNamesForType( aClass, b, b2 );
375 public <T> Map<String, T> getBeansOfType( Class<T> tClass )
376 throws BeansException
378 return applicationContext.getBeansOfType( tClass );
382 public <T> Map<String, T> getBeansOfType( Class<T> tClass, boolean b, boolean b2 )
383 throws BeansException
385 return applicationContext.getBeansOfType( tClass, b, b2 );
389 public String[] getBeanNamesForAnnotation( Class<? extends Annotation> aClass )
391 return applicationContext.getBeanNamesForAnnotation( aClass );
395 public Map<String, Object> getBeansWithAnnotation( Class<? extends Annotation> aClass )
396 throws BeansException
398 return applicationContext.getBeansWithAnnotation( aClass );
402 public <A extends Annotation> A findAnnotationOnBean( String s, Class<A> aClass )
403 throws NoSuchBeanDefinitionException
405 return applicationContext.findAnnotationOnBean( s, aClass );
409 public <T> T getBean( Class<T> aClass, Object... objects )
410 throws BeansException
412 return applicationContext.getBean( aClass, objects );
416 public Object getBean( String s )
417 throws BeansException
419 return applicationContext.getBean( s );
423 public <T> T getBean( String s, Class<T> tClass )
424 throws BeansException
426 return applicationContext.getBean( s, tClass );
430 public <T> T getBean( Class<T> tClass )
431 throws BeansException
433 return applicationContext.getBean( tClass );
437 public Object getBean( String s, Object... objects )
438 throws BeansException
440 return applicationContext.getBean( s, objects );
444 public boolean containsBean( String s )
446 return applicationContext.containsBean( s );
450 public boolean isSingleton( String s )
451 throws NoSuchBeanDefinitionException
453 return applicationContext.isSingleton( s );
457 public boolean isPrototype( String s )
458 throws NoSuchBeanDefinitionException
460 return applicationContext.isPrototype( s );
464 public boolean isTypeMatch( String s, Class<?> aClass )
465 throws NoSuchBeanDefinitionException
467 return applicationContext.isTypeMatch( s, aClass );
471 public Class<?> getType( String s )
472 throws NoSuchBeanDefinitionException
474 return applicationContext.getType( s );
478 public String[] getAliases( String s )
480 return applicationContext.getAliases( s );
484 public String getMessage( String s, Object[] objects, String s2, Locale locale )
486 return applicationContext.getMessage( s, objects, s2, locale );
490 public String getMessage( String s, Object[] objects, Locale locale )
491 throws NoSuchMessageException
493 return applicationContext.getMessage( s, objects, locale );
497 public String getMessage( MessageSourceResolvable messageSourceResolvable, Locale locale )
498 throws NoSuchMessageException
500 return applicationContext.getMessage( messageSourceResolvable, locale );
504 public Resource[] getResources( String s )
507 return applicationContext.getResources( s );
511 public void publishEvent( Object o )
517 public String[] getBeanNamesForType( ResolvableType resolvableType )
519 return new String[0];
523 public boolean isTypeMatch( String s, ResolvableType resolvableType )
524 throws NoSuchBeanDefinitionException
530 public Resource getResource( String s )
532 return applicationContext.getResource( s );
536 public ClassLoader getClassLoader()
538 return applicationContext.getClassLoader();
542 protected Servlet findServlet( String name )
545 return unauthenticatedRepositoryServlet;
549 protected String getSpringConfigLocation()
551 return "classpath*:/META-INF/spring-context.xml,classpath*:spring-context.xml";
555 protected static WebClient newClient()
557 final WebClient webClient = new WebClient();
558 webClient.getOptions().setJavaScriptEnabled( false );
559 webClient.getOptions().setCssEnabled( false );
560 webClient.getOptions().setAppletEnabled( false );
561 webClient.getOptions().setThrowExceptionOnFailingStatusCode( false );
562 webClient.setAjaxController( new NicelyResynchronizingAjaxController() );
567 protected WebResponse getWebResponse( String path )
570 return getWebResponse( new GetMethodWebRequest( "http://localhost" + path ) );//, false );
573 protected WebResponse getWebResponse( WebRequest webRequest ) //, boolean followRedirect )
577 MockHttpServletRequest request = new MockHttpServletRequest();
578 request.setRequestURI( webRequest.getUrl().getPath() );
579 request.addHeader( "User-Agent", "Apache Archiva unit test" );
581 request.setMethod( webRequest.getHttpMethod().name() );
583 if ( webRequest.getHttpMethod() == HttpMethod.PUT )
585 PutMethodWebRequest putRequest = PutMethodWebRequest.class.cast( webRequest );
586 request.setContentType( putRequest.contentType );
587 request.setContent( IOUtils.toByteArray( putRequest.inputStream ) );
590 if ( webRequest instanceof MkColMethodWebRequest )
592 request.setMethod( "MKCOL" );
595 final MockHttpServletResponse response = execute( request );
597 if ( response.getStatus() == HttpServletResponse.SC_MOVED_PERMANENTLY
598 || response.getStatus() == HttpServletResponse.SC_MOVED_TEMPORARILY )
600 String location = response.getHeader( "Location" );
601 log.debug( "follow redirect to {}", location );
602 return getWebResponse( new GetMethodWebRequest( location ) );
605 return new WebResponse( null, null, 1 )
608 public String getContentAsString()
612 return response.getContentAsString();
614 catch ( UnsupportedEncodingException e )
616 throw new RuntimeException( e.getMessage(), e );
621 public int getStatusCode()
623 return response.getStatus();
627 public String getResponseHeaderValue( String headerName )
629 return response.getHeader( headerName );
634 protected MockHttpServletResponse execute( HttpServletRequest request )
637 MockHttpServletResponse response = new MockHttpServletResponse()
640 public String getContentAsString()
641 throws UnsupportedEncodingException
643 String errorMessage = getErrorMessage();
644 return ( errorMessage != null ) ? errorMessage : super.getContentAsString();
647 this.unauthenticatedRepositoryServlet.service( request, response );
651 public static class GetMethodWebRequest
656 public GetMethodWebRequest( String url )
659 super( new URL( url ) );
665 public static class PutMethodWebRequest
670 InputStream inputStream;
674 public PutMethodWebRequest( String url, InputStream inputStream, String contentType )
677 super( new URL( url ), HttpMethod.PUT );
679 this.inputStream = inputStream;
680 this.contentType = contentType;
686 public static class ServletUnitClient
689 AbstractRepositoryServletTestCase abstractRepositoryServletTestCase;
691 public ServletUnitClient( AbstractRepositoryServletTestCase abstractRepositoryServletTestCase )
693 this.abstractRepositoryServletTestCase = abstractRepositoryServletTestCase;
696 public WebResponse getResponse( WebRequest request )
699 return getResponse( request, false );
702 public WebResponse getResponse( WebRequest request, boolean followRedirect )
705 // alwasy following redirect as it's normal
706 return abstractRepositoryServletTestCase.getWebResponse( request );//, followRedirect );
709 public WebResponse getResource( WebRequest request )
712 return getResponse( request );
716 public ServletUnitClient getServletUnitClient()
718 return new ServletUnitClient( this );
723 public void tearDown()
726 repositoryRegistry.getRepositories().stream().forEach(r -> r.close());
728 if ( Files.exists(repoRootInternal) )
730 org.apache.archiva.common.utils.FileUtils.deleteDirectory( repoRootInternal );
733 if ( Files.exists(repoRootLegacy) )
735 org.apache.archiva.common.utils.FileUtils.deleteDirectory( repoRootLegacy );
738 String appserverBase = System.getProperty( "appserver.base" );
739 if ( StringUtils.isNotEmpty( appserverBase ) )
741 org.apache.archiva.common.utils.FileUtils.deleteDirectory( Paths.get( appserverBase ) );
747 protected void assertFileContents( String expectedContents, Path repoRoot, String subpath )
750 String path = Paths.get(subpath).isAbsolute() ? subpath.substring( 1,subpath.length() ) : subpath;
751 Path actualFile = repoRoot.resolve( path );
752 assertTrue( "File <" + actualFile.toAbsolutePath() + "> should exist.", Files.exists(actualFile) );
753 assertTrue( "File <" + actualFile.toAbsolutePath() + "> should be a file (not a dir/link/device/etc).",
754 Files.isRegularFile( actualFile ) );
756 String actualContents = org.apache.archiva.common.utils.FileUtils.readFileToString( actualFile, Charset.defaultCharset() );
757 assertEquals( "File Contents of <" + actualFile.toAbsolutePath() + ">", expectedContents, actualContents );
760 protected void assertRepositoryValid( RepositoryServlet servlet, String repoId )
763 ManagedRepository repository = servlet.getRepository( repoId );
764 assertNotNull( "Archiva Managed Repository id:<" + repoId + "> should exist.", repository );
765 Path repoRoot = Paths.get( repository.getLocation() );
766 assertTrue( "Archiva Managed Repository id:<" + repoId + "> should have a valid location on disk.",
767 Files.exists(repoRoot) && Files.isDirectory(repoRoot) );
770 protected void assertResponseOK( WebResponse response )
772 assertNotNull( "Should have recieved a response", response );
773 Assert.assertEquals( "Should have been an OK response code", //
774 HttpServletResponse.SC_OK, //
775 response.getStatusCode() );
778 protected void assertResponseOK( WebResponse response, String path )
780 assertNotNull( "Should have recieved a response", response );
781 Assert.assertEquals( "Should have been an OK response code for path: " + path, HttpServletResponse.SC_OK,
782 response.getStatusCode() );
785 protected void assertResponseNotFound( WebResponse response )
787 assertNotNull( "Should have recieved a response", response );
788 Assert.assertEquals( "Should have been an 404/Not Found response code.", HttpServletResponse.SC_NOT_FOUND,
789 response.getStatusCode() );
792 protected void assertResponseInternalServerError( WebResponse response )
794 assertNotNull( "Should have recieved a response", response );
795 Assert.assertEquals( "Should have been an 500/Internal Server Error response code.",
796 HttpServletResponse.SC_INTERNAL_SERVER_ERROR, response.getStatusCode() );
799 protected void assertResponseConflictError( WebResponse response )
801 assertNotNull( "Should have received a response", response );
802 Assert.assertEquals( "Should have been a 409/Conflict response code.", HttpServletResponse.SC_CONFLICT,
803 response.getStatusCode() );
806 protected ManagedRepositoryConfiguration createManagedRepository( String id, String name, Path location,
807 boolean blockRedeployments )
809 ManagedRepositoryConfiguration repo = new ManagedRepositoryConfiguration();
811 repo.setName( name );
812 repo.setLocation( location.toAbsolutePath().toString() );
813 repo.setBlockRedeployments( blockRedeployments );
814 repo.setType( "MAVEN" );
815 repo.setIndexDir(".indexer");
816 repo.setPackedIndexDir(".index");
821 protected ManagedRepositoryConfiguration createManagedRepository( String id, String name, Path location,
822 String layout, boolean blockRedeployments )
824 ManagedRepositoryConfiguration repo = createManagedRepository( id, name, location, blockRedeployments );
825 repo.setLayout( layout );
829 protected RemoteRepositoryConfiguration createRemoteRepository( String id, String name, String url )
831 RemoteRepositoryConfiguration repo = new RemoteRepositoryConfiguration();
833 repo.setName( name );
838 protected void saveConfiguration( ArchivaConfiguration archivaConfiguration )
841 repositoryRegistry.setArchivaConfiguration(archivaConfiguration);
842 // repositoryRegistry.reload();
843 archivaConfiguration.save( archivaConfiguration.getConfiguration() );
848 protected void setupCleanRepo( Path repoRootDir )
851 org.apache.archiva.common.utils.FileUtils.deleteDirectory( repoRootDir );
852 if ( !Files.exists(repoRootDir) )
854 Files.createDirectories( repoRootDir );
858 protected void assertManagedFileNotExists( Path repoRootInternal, String resourcePath )
860 Path repoFile = repoRootInternal.resolve( resourcePath );
861 assertFalse( "Managed Repository File <" + repoFile.toAbsolutePath() + "> should not exist.",
862 Files.exists(repoFile) );
865 protected void setupCleanInternalRepo()
868 setupCleanRepo( repoRootInternal );
871 protected Path populateRepo( Path repoRootManaged, String path, String contents )
874 Path destFile = repoRootManaged.resolve( path );
875 Files.createDirectories( destFile.getParent() );
876 org.apache.archiva.common.utils.FileUtils.writeStringToFile( destFile, Charset.defaultCharset(), contents );