From e0d19c4d9744caa54342eeb079b7f67ff11526c7 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 24 Oct 2007 00:16:40 +0000 Subject: [PATCH] [MRM-565] Archiva 1.0-beta-3 fails in 404 on all legacy request. Using new methods in RepositoryRequest to identify native resource path early and using it. Adding PolicingServletRequest to deal with bad formatted request paths. Beefing up RepositoryServletTest to test proxy-less (for now) requests ... * Browse * Get Checksum (default layout) * Get Checksum (legacy layout) * Get Metadata (versioned + default layout) * Get Metadata (project + default layout) * Get Artifact (default layout) Adding custom mime-types.txt to get proper "Content-Type" headers on GET requests. git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@587708 13f79535-47bb-0310-9956-ffa450edef68 --- .../repository/PolicingServletRequest.java | 69 +++++ .../web/repository/ProxiedDavServer.java | 201 ++++++++----- .../web/repository/RepositoryServlet.java | 9 + .../plexus/webdav/util/mime-types.txt | 129 +++++++++ .../web/repository/RepositoryServletTest.java | 272 ++++++++++++++++-- .../web/repository/RepositoryServletTest.xml | 51 +++- .../src/test/resources/repository-archiva.xml | 111 +++++++ 7 files changed, 736 insertions(+), 106 deletions(-) create mode 100644 archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/PolicingServletRequest.java create mode 100644 archiva-web/archiva-webapp/src/main/resources/org/codehaus/plexus/webdav/util/mime-types.txt create mode 100644 archiva-web/archiva-webapp/src/test/resources/repository-archiva.xml diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/PolicingServletRequest.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/PolicingServletRequest.java new file mode 100644 index 000000000..0076988ae --- /dev/null +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/PolicingServletRequest.java @@ -0,0 +1,69 @@ +package org.apache.maven.archiva.web.repository; + +/* + * 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.commons.lang.StringUtils; +import org.codehaus.plexus.util.FileUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +/** + * PolicingServletRequest is for policing the incoming request for naughty bits, such as a double slashes, + * or paths that include "/../" type syntax, or query string. Stripping out all things that are + * not appropriate. + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class PolicingServletRequest + extends HttpServletRequestWrapper + implements HttpServletRequest +{ + private String fixedPathInfo; + + public PolicingServletRequest( HttpServletRequest originalRequest ) + { + super( originalRequest ); + + fixedPathInfo = originalRequest.getPathInfo(); + + if ( StringUtils.isNotBlank( fixedPathInfo ) ) + { + /* Perform a simple security normalization of the requested pathinfo. + * This is to cleanup requests that use "/../" or "///" type hacks. + */ + fixedPathInfo = FileUtils.normalize( fixedPathInfo ); + } + } + + @Override + public String getPathInfo() + { + return fixedPathInfo; + } + + @Override + public String getQueryString() + { + // No query string allowed. + return null; + } +} diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java index 7dedee43b..bdf8fa97f 100644 --- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java @@ -138,29 +138,46 @@ public class ProxiedDavServer if ( isGet ) { - fetchContentFromProxies( request ); - } + // Default behaviour is to treat the resource natively. + String resource = request.getLogicalResource(); + File resourceFile = new File( managedRepository.getRepoRoot(), resource ); - if ( isPut ) - { - /* Create parent directories that don't exist when writing a file - * This actually makes this implementation not compliant to the - * WebDAV RFC - but we have enough knowledge - * about how the collection is being used to do this reasonably and - * some versions of Maven's WebDAV don't - * correctly create the collections themselves. - */ + // If this a directory resource, then we are likely browsing. + if ( resourceFile.exists() && resourceFile.isDirectory() ) + { + // TODO: [MRM-440] - If webdav URL lacks a trailing /, navigating to all links in the listing return 404. + // TODO: Issue redirect with proper pathing. + + // Process the request. + davServer.process( request, response ); + + // All done. + return; + } - File rootDirectory = getRootDirectory(); - if ( rootDirectory != null ) + // At this point the incoming request can either be in default or legacy layout format. + try { - new File( rootDirectory, request.getLogicalResource() ).getParentFile().mkdirs(); + // Perform an adjustment of the resource to the managed repository expected path. + resource = repositoryRequest.toNativePath( request.getLogicalResource(), managedRepository ); + resourceFile = new File( managedRepository.getRepoRoot(), resource ); + + // Adjust the pathInfo resource to be in the format that the dav server impl expects. + request.getRequest().setPathInfo( resource ); + + // Attempt to fetch the resource from any defined proxy. + fetchContentFromProxies( request, resource ); } - } + catch ( LayoutException e ) + { + // Invalid resource, pass it on. + respondResourceMissing( request, response, e ); - if ( isGet ) - { - if ( resourceExists( request ) ) + // All done. + return; + } + + if ( resourceFile.exists() ) { // [MRM-503] - Metadata file need Pragma:no-cache response header. if ( request.getLogicalResource().endsWith( "/maven-metadata.xml" ) ) @@ -175,17 +192,35 @@ public class ProxiedDavServer } else { - respondResourceMissing( request, response ); + respondResourceMissing( request, response, null ); } } if ( isPut ) { + /* Create parent directories that don't exist when writing a file + * This actually makes this implementation not compliant to the + * WebDAV RFC - but we have enough knowledge + * about how the collection is being used to do this reasonably and + * some versions of Maven's WebDAV don't + * correctly create the collections themselves. + */ + + File rootDirectory = getRootDirectory(); + if ( rootDirectory != null ) + { + new File( rootDirectory, request.getLogicalResource() ).getParentFile().mkdirs(); + } + + // Allow the dav server to process the put request. davServer.process( request, response ); + + // All done. + return; } } - private void respondResourceMissing( DavServerRequest request, HttpServletResponse response ) + private void respondResourceMissing( DavServerRequest request, HttpServletResponse response, Throwable t ) { response.setStatus( HttpServletResponse.SC_NOT_FOUND ); @@ -196,7 +231,6 @@ public class ProxiedDavServer missingUrl.append( request.getRequest().getServerName() ).append( ":" ); missingUrl.append( request.getRequest().getServerPort() ); missingUrl.append( request.getRequest().getServletPath() ); - // missingUrl.append( request.getRequest().getPathInfo() ); String message = "Error 404 Not Found"; @@ -217,6 +251,13 @@ public class ProxiedDavServer out.println( "\">" ); out.print( missingUrl.toString() ); out.println( "

" ); + + if ( t != null ) + { + out.println( "
" );
+                t.printStackTrace( out );
+                out.println( "
" ); + } out.println( "" ); @@ -228,74 +269,23 @@ public class ProxiedDavServer } } - private boolean resourceExists( DavServerRequest request ) - { - String resource = request.getLogicalResource(); - File resourceFile = new File( managedRepository.getRepoRoot(), resource ); - return resourceFile.exists(); - } - - private void fetchContentFromProxies( DavServerRequest request ) + private void fetchContentFromProxies( DavServerRequest request, String resource ) throws ServletException { - String resource = request.getLogicalResource(); - - // Cleanup bad requests from maven 1. - // Often seen is a double slash. - // example: http://hostname:8080/archiva/repository/internal//pmd/jars/pmd-3.0.jar - if ( resource.startsWith( "/" ) ) - { - resource = resource.substring( 1 ); - } - - if ( resource.endsWith( ".sha1" ) || resource.endsWith( ".md5" ) ) + if ( repositoryRequest.isSupportFile( resource ) ) { // Checksums are fetched with artifact / metadata. + + // Need to adjust the path for the checksum resource. return; } // Is it a Metadata resource? - if ( resource.endsWith( "/" + MetadataTools.MAVEN_METADATA ) ) + if ( repositoryRequest.isDefault( resource ) && repositoryRequest.isMetadata( resource ) ) { - ProjectReference project; - VersionedReference versioned; - - try - { - - versioned = metadataTools.toVersionedReference( resource ); - if ( versioned != null ) - { - connectors.fetchFromProxies( managedRepository, versioned ); - request.getRequest().setPathInfo( metadataTools.toPath( versioned ) ); - return; - } - } - catch ( RepositoryMetadataException e ) - { - /* eat it */ - } - catch ( ProxyException e ) + if ( fetchMetadataFromProxies( request, resource ) ) { - throw new ServletException( "Unable to fetch versioned metadata resource.", e ); - } - - try - { - project = metadataTools.toProjectReference( resource ); - if ( project != null ) - { - connectors.fetchFromProxies( managedRepository, project ); - request.getRequest().setPathInfo( metadataTools.toPath( project ) ); - } - } - catch ( RepositoryMetadataException e ) - { - /* eat it */ - } - catch ( ProxyException e ) - { - throw new ServletException( "Unable to fetch project metadata resource.", e ); + return; } } @@ -326,6 +316,52 @@ public class ProxiedDavServer } } + private boolean fetchMetadataFromProxies( DavServerRequest request, String resource ) + throws ServletException + { + ProjectReference project; + VersionedReference versioned; + + try + { + + versioned = metadataTools.toVersionedReference( resource ); + if ( versioned != null ) + { + connectors.fetchFromProxies( managedRepository, versioned ); + return true; + } + } + catch ( RepositoryMetadataException e ) + { + /* eat it */ + } + catch ( ProxyException e ) + { + throw new ServletException( "Unable to fetch versioned metadata resource.", e ); + } + + try + { + project = metadataTools.toProjectReference( resource ); + if ( project != null ) + { + connectors.fetchFromProxies( managedRepository, project ); + return true; + } + } + catch ( RepositoryMetadataException e ) + { + /* eat it */ + } + catch ( ProxyException e ) + { + throw new ServletException( "Unable to fetch project metadata resource.", e ); + } + + return false; + } + /** * A relocation capable client will request the POM prior to the artifact, * and will then read meta-data and do client side relocation. A simplier @@ -400,6 +436,13 @@ public class ProxiedDavServer // Invalid POM : ignore } } + + @Override + public void setUseIndexHtml( boolean useIndexHtml ) + { + super.setUseIndexHtml( useIndexHtml ); + davServer.setUseIndexHtml( useIndexHtml ); + } public ManagedRepositoryContent getRepository() { diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/RepositoryServlet.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/RepositoryServlet.java index 28856ef6f..9bd9596e6 100644 --- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/RepositoryServlet.java +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/RepositoryServlet.java @@ -103,9 +103,18 @@ public class RepositoryServlet DavServerComponent server = createServer( repo.getId(), repoDir, servletConfig ); + server.setUseIndexHtml( true ); server.addListener( audit ); } } + + @Override + protected void service( HttpServletRequest httpRequest, HttpServletResponse httpResponse ) + throws ServletException, IOException + { + // Wrap the incoming request to adjust paths and whatnot. + super.service( new PolicingServletRequest( httpRequest ), httpResponse ); + } public synchronized ManagedRepositoryConfiguration getRepository( String prefix ) { diff --git a/archiva-web/archiva-webapp/src/main/resources/org/codehaus/plexus/webdav/util/mime-types.txt b/archiva-web/archiva-webapp/src/main/resources/org/codehaus/plexus/webdav/util/mime-types.txt new file mode 100644 index 000000000..3c580357b --- /dev/null +++ b/archiva-web/archiva-webapp/src/main/resources/org/codehaus/plexus/webdav/util/mime-types.txt @@ -0,0 +1,129 @@ +# This is a comment. I love comments. + +# This file controls what Internet media types are sent to the client for +# given file extension(s). Sending the correct media type to the client +# is important so they know how to handle the content of the file. +# Extra types can either be added here or by using an AddType directive +# in your config files. For more information about Internet media types, +# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type +# registry is at . + +# MIME type Extensions + +application/andrew-inset ez +application/atom+xml atom +application/mac-binhex40 hqx +application/mac-compactpro cpt +application/mathml+xml mathml +application/msword doc +application/octet-stream bin dms lha lzh exe class so dll dmg +application/oda oda +application/ogg ogg +application/pdf pdf +application/pgp-encrypted pgp +application/postscript ai eps ps +application/rdf+xml rdf +application/smil smi smil +application/srgs gram +application/srgs+xml grxml +application/vnd.mif mif +application/vnd.mozilla.xul+xml xul +application/vnd.ms-excel xls +application/vnd.ms-powerpoint ppt +application/vnd.rn-realmedia rm +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/voicexml+xml vxml +application/x-bcpio bcpio +application/x-cdlink vcd +application/x-chess-pgn pgn +application/x-cpio cpio +application/x-csh csh +application/x-director dcr dir dxr +application/x-dvi dvi +application/x-futuresplash spl +application/x-gtar gtar +application/x-hdf hdf +application/x-jar jar +application/x-java-jnlp-file jnlp +application/x-javascript js +application/x-koan skp skd skt skm +application/x-latex latex +application/x-netcdf nc cdf +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-stuffit sit +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-texinfo texinfo texi +application/x-troff t tr roff +application/x-troff-man man +application/x-troff-me me +application/x-troff-ms ms +application/x-ustar ustar +application/x-wais-source src +application/xhtml+xml xhtml xht +application/xml xml xsl +application/xml-dtd dtd +application/xslt+xml xslt +application/zip zip +audio/basic au snd +audio/midi mid midi kar +audio/mpeg mpga mp2 mp3 +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-pn-realaudio ram ra +audio/x-wav wav +chemical/x-pdb pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +image/gif gif +image/ief ief +image/jp2 jp2 +image/jpeg jpeg jpg jpe +image/pict pict pic pct +image/png png +image/svg+xml svg +image/tiff tiff tif +image/vnd.djvu djvu djv +image/vnd.wap.wbmp wbmp +image/x-cmu-raster ras +image/x-icon ico +image/x-macpaint pntg pnt mac +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-quicktime qtif qti +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +model/iges igs iges +model/mesh msh mesh silo +model/vrml wrl vrml +text/calendar ics ifb +text/css css +text/html html htm +text/plain asc txt sha1 md5 +text/richtext rtx +text/rtf rtf +text/sgml sgml sgm +text/tab-separated-values tsv +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-setext etx +video/mp4 mp4 +video/mpeg mpeg mpg mpe +video/quicktime qt mov +video/vnd.mpegurl mxu m4u +video/x-dv dv dif +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletTest.java b/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletTest.java index 604e2b432..c0b24cee5 100644 --- a/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletTest.java +++ b/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletTest.java @@ -19,26 +19,36 @@ package org.apache.maven.archiva.web.repository; * under the License. */ +import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.PutMethodWebRequest; +import com.meterware.httpunit.WebLink; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; import com.meterware.servletunit.ServletRunner; import com.meterware.servletunit.ServletUnitClient; + +import org.apache.commons.io.FileUtils; import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.Configuration; -import org.apache.maven.archiva.configuration.ConfigurationEvent; -import org.apache.maven.archiva.configuration.IndeterminateConfigurationException; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration; import org.codehaus.plexus.PlexusConstants; import org.codehaus.plexus.PlexusTestCase; -import org.codehaus.plexus.registry.RegistryException; -import org.codehaus.plexus.util.FileUtils; -import org.xml.sax.SAXException; +import org.codehaus.plexus.webdav.util.MimeTypes; -import javax.servlet.ServletException; import java.io.File; import java.io.IOException; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +/** + * RepositoryServletTest + * + * @author Joakim Erdfelt + * @version $Id$ + */ public class RepositoryServletTest extends PlexusTestCase { @@ -61,61 +71,66 @@ public class RepositoryServletTest { super.setUp(); - // TODO: purely to quiet logging - shouldn't be needed String appserverBase = getTestFile( "target/appserver-base" ).getAbsolutePath(); System.setProperty( "appserver.base", appserverBase ); - configuration = (ArchivaConfiguration) lookup( ArchivaConfiguration.ROLE ); + File testConf = getTestFile( "src/test/resources/repository-archiva.xml" ); + File testConfDest = new File( appserverBase, "conf/archiva.xml" ); + FileUtils.copyFile( testConf, testConfDest ); + configuration = (ArchivaConfiguration) lookup( ArchivaConfiguration.ROLE ); repositoryLocation = new File( appserverBase, "data/repositories/internal" ); + Configuration config = configuration.getConfiguration(); + + config.addManagedRepository( createManagedRepository( "internal", "Internal Test Repo", repositoryLocation ) ); + saveConfiguration(); ServletRunner sr = new ServletRunner(); sr.registerServlet( "/repository/*", UnauthenticatedRepositoryServlet.class.getName() ); sc = sr.newClient(); - sc.getSession( true ).getServletContext().setAttribute( PlexusConstants.PLEXUS_KEY, getContainer() ); + HttpSession session = sc.getSession( true ); + ServletContext servletContext = session.getServletContext(); + servletContext.setAttribute( PlexusConstants.PLEXUS_KEY, getContainer() ); } public void testPutWithMissingParentCollection() - throws IOException, SAXException + throws Exception { FileUtils.deleteDirectory( repositoryLocation ); WebRequest request = new PutMethodWebRequest( REQUEST_PATH, getClass().getResourceAsStream( "/artifact.jar" ), "application/octet-stream" ); WebResponse response = sc.getResponse( request ); - assertNotNull( "No response received", response ); - assertEquals( "file contents", "artifact.jar\n", - FileUtils.fileRead( new File( repositoryLocation, "path/to/artifact.jar" ) ) ); + assertNotNull( "Should have received response", response ); + assertEquals( "file contents", "artifact.jar\n", FileUtils + .readFileToString( new File( repositoryLocation, "path/to/artifact.jar" ), null ) ); } public void testGetRepository() - throws IOException, ServletException + throws Exception { RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); assertNotNull( servlet ); - ManagedRepositoryConfiguration repository = servlet.getRepository( REPOSITORY_ID ); - assertNotNull( repository ); - assertEquals( "Archiva Managed Internal Repository", repository.getName() ); + assertRepositoryValid( servlet, REPOSITORY_ID ); } public void testGetRepositoryAfterDelete() - throws IOException, ServletException, RegistryException, IndeterminateConfigurationException + throws Exception { RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); assertNotNull( servlet ); Configuration c = configuration.getConfiguration(); c.removeManagedRepository( c.findManagedRepositoryById( REPOSITORY_ID ) ); - // TODO it would be better to use a mock configuration and "save" to more accurately reflect the calls made - servlet.configurationEvent( new ConfigurationEvent( ConfigurationEvent.SAVED) ); + saveConfiguration(); ManagedRepositoryConfiguration repository = servlet.getRepository( REPOSITORY_ID ); assertNull( repository ); } public void testGetRepositoryAfterAdd() - throws IOException, ServletException, RegistryException, IndeterminateConfigurationException + throws Exception { RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); assertNotNull( servlet ); @@ -131,16 +146,221 @@ public class RepositoryServletTest } repo.setLocation( repoRoot.getAbsolutePath() ); c.addManagedRepository( repo ); - // TODO it would be better to use a mock configuration and "save" to more accurately reflect the calls made - servlet.configurationEvent( new ConfigurationEvent( ConfigurationEvent.SAVED) ); + saveConfiguration(); ManagedRepositoryConfiguration repository = servlet.getRepository( NEW_REPOSITORY_ID ); assertNotNull( repository ); assertEquals( NEW_REPOSITORY_NAME, repository.getName() ); // check other is still intact - repository = servlet.getRepository( REPOSITORY_ID ); - assertNotNull( repository ); - assertEquals( "Archiva Managed Internal Repository", repository.getName() ); + assertRepositoryValid( servlet, REPOSITORY_ID ); + } + + public void testBrowse() + throws Exception + { + RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); + assertNotNull( servlet ); + assertRepositoryValid( servlet, REPOSITORY_ID ); + + new File( repositoryLocation, "org/apache/archiva" ).mkdirs(); + new File( repositoryLocation, "net/sourceforge" ).mkdirs(); + new File( repositoryLocation, "commons-lang" ).mkdirs(); + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" ); + WebResponse response = sc.getResponse( request ); + assertEquals( "Response", HttpServletResponse.SC_OK, response.getResponseCode() ); + + // dumpResponse( response ); + + WebLink links[] = response.getLinks(); + String expectedLinks[] = new String[] { "./commons-lang/", "./net/", "./org/", "./path/" }; + + assertEquals( "Links.length", expectedLinks.length, links.length ); + for ( int i = 0; i < links.length; i++ ) + { + assertEquals( "Link[" + i + "]", expectedLinks[i], links[i].getURLString() ); + } + } + + public void testGetNoProxyChecksumDefaultLayout() + throws Exception + { + RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); + assertNotNull( servlet ); + assertRepositoryValid( servlet, REPOSITORY_ID ); + + String commonsLangSha1 = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar.sha1"; + + File checksumFile = new File( repositoryLocation, commonsLangSha1 ); + checksumFile.getParentFile().mkdirs(); + + FileUtils.writeStringToFile( checksumFile, "dummy-checksum", null ); + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangSha1 ); + WebResponse response = sc.getResponse( request ); + assertEquals( "Response OK", HttpServletResponse.SC_OK, response.getResponseCode() ); + + assertEquals( "Expected file contents", "dummy-checksum", response.getText() ); + } + + public void testGetNoProxyChecksumLegacyLayout() + throws Exception + { + RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); + assertNotNull( servlet ); + assertRepositoryValid( servlet, REPOSITORY_ID ); + + String commonsLangSha1 = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar.sha1"; + + File checksumFile = new File( repositoryLocation, commonsLangSha1 ); + checksumFile.getParentFile().mkdirs(); + + FileUtils.writeStringToFile( checksumFile, "dummy-checksum", null ); + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + + "commons-lang/jars/commons-lang-2.1.jar.sha1" ); + WebResponse response = sc.getResponse( request ); + assertEquals( "Response OK", HttpServletResponse.SC_OK, response.getResponseCode() ); + + assertEquals( "Expected file contents", "dummy-checksum", response.getText() ); + } + + public void testGetNoProxyVersionedMetadataDefaultLayout() + throws Exception + { + RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); + assertNotNull( servlet ); + assertRepositoryValid( servlet, REPOSITORY_ID ); + + String commonsLangMetadata = "commons-lang/commons-lang/2.1/maven-metadata.xml"; + String expectedMetadataContents = "dummy-versioned-metadata"; + + File metadataFile = new File( repositoryLocation, commonsLangMetadata ); + metadataFile.getParentFile().mkdirs(); + + FileUtils.writeStringToFile( metadataFile, expectedMetadataContents, null ); + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangMetadata ); + WebResponse response = sc.getResponse( request ); + assertEquals( "Response OK", HttpServletResponse.SC_OK, response.getResponseCode() ); + + assertEquals( "Expected file contents", expectedMetadataContents, response.getText() ); + } + + public void testGetNoProxyProjectMetadataDefaultLayout() + throws Exception + { + RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); + assertNotNull( servlet ); + assertRepositoryValid( servlet, REPOSITORY_ID ); + + String commonsLangMetadata = "commons-lang/commons-lang/maven-metadata.xml"; + String expectedMetadataContents = "dummy-project-metadata"; + + File metadataFile = new File( repositoryLocation, commonsLangMetadata ); + metadataFile.getParentFile().mkdirs(); + + FileUtils.writeStringToFile( metadataFile, expectedMetadataContents, null ); + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangMetadata ); + WebResponse response = sc.getResponse( request ); + assertEquals( "Response OK", HttpServletResponse.SC_OK, response.getResponseCode() ); + + assertEquals( "Expected file contents", expectedMetadataContents, response.getText() ); + } + + public void testGetNoProxyArtifactDefaultLayout() + throws Exception + { + RepositoryServlet servlet = (RepositoryServlet) sc.newInvocation( REQUEST_PATH ).getServlet(); + assertNotNull( servlet ); + assertRepositoryValid( servlet, REPOSITORY_ID ); + + String commonsLangJar = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar"; + String expectedArtifactContents = "dummy-commons-lang-artifact"; + + File artifactFile = new File( repositoryLocation, commonsLangJar ); + artifactFile.getParentFile().mkdirs(); + + FileUtils.writeStringToFile( artifactFile, expectedArtifactContents, null ); + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/internal/" + commonsLangJar ); + WebResponse response = sc.getResponse( request ); + assertEquals( "Response OK", HttpServletResponse.SC_OK, response.getResponseCode() ); + + assertEquals( "Expected file contents", expectedArtifactContents, response.getText() ); + } + + public void testMimeTypesAvailable() + throws Exception + { + MimeTypes mimeTypes = (MimeTypes) lookup( MimeTypes.class ); + assertNotNull( mimeTypes ); + + // Test for some added types. + assertEquals( "sha1", "text/plain", mimeTypes.getMimeType( "foo.sha1" ) ); + assertEquals( "md5", "text/plain", mimeTypes.getMimeType( "foo.md5" ) ); + assertEquals( "pgp", "application/pgp-encrypted", mimeTypes.getMimeType( "foo.pgp" ) ); + } + + private void dumpResponse( WebResponse response ) + { + System.out.println( "---(response)---" ); + System.out.println( "" + response.getResponseCode() + " " + response.getResponseMessage() ); + + String headerNames[] = response.getHeaderFieldNames(); + for ( String headerName : headerNames ) + { + System.out.println( "[header] " + headerName + ": " + response.getHeaderField( headerName ) ); + } + + System.out.println( "---(text)---" ); + try + { + System.out.println( response.getText() ); + } + catch ( IOException e ) + { + System.err.print( "[Exception] : " ); + e.printStackTrace( System.err ); + } + } + + private void assertRepositoryValid( RepositoryServlet servlet, String repoId ) + { + ManagedRepositoryConfiguration repository = servlet.getRepository( repoId ); + assertNotNull( "Archiva Managed Repository id:<" + repoId + "> should exist.", repository ); + File repoRoot = new File( repository.getLocation() ); + assertTrue( "Archiva Managed Repository id:<" + repoId + "> should have a valid location on disk.", repoRoot + .exists() + && repoRoot.isDirectory() ); + } + + private void saveConfiguration() + throws Exception + { + configuration.save( configuration.getConfiguration() ); + // TODO it would be better to use a mock configuration and "save" to more accurately reflect the calls made + // RepositoryServlet servlet + // servlet.configurationEvent( new ConfigurationEvent( ConfigurationEvent.SAVED ) ); + } + + private ManagedRepositoryConfiguration createManagedRepository( String id, String name, File location ) + { + ManagedRepositoryConfiguration repo = new ManagedRepositoryConfiguration(); + repo.setId( id ); + repo.setName( name ); + repo.setLocation( location.getAbsolutePath() ); + return repo; + } + + private RemoteRepositoryConfiguration createRemoteRepository( String id, String name, String url ) + { + RemoteRepositoryConfiguration repo = new RemoteRepositoryConfiguration(); + repo.setId( id ); + repo.setName( name ); + repo.setUrl( url ); + return repo; } } diff --git a/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/repository/RepositoryServletTest.xml b/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/repository/RepositoryServletTest.xml index 5356abb87..beccf43c9 100644 --- a/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/repository/RepositoryServletTest.xml +++ b/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/repository/RepositoryServletTest.xml @@ -29,15 +29,64 @@ basic + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + org.apache.maven.archiva.configuration.DefaultArchivaConfiguration + + + org.codehaus.plexus.registry.Registry + configured + + + + + org.codehaus.plexus.registry.Registry + configured + org.codehaus.plexus.registry.commons.CommonsConfigurationRegistry + + + + + + + + org.codehaus.plexus.webdav.DavServerManager default org.codehaus.plexus.webdav.DefaultDavServerManager + DefaultDavServerManager proxied - + + + org.codehaus.plexus.cache.Cache + url-failures-cache + org.codehaus.plexus.cache.ehcache.EhcacheCache + URL Failure Cache + + 600 + false + ${java.io.tmpdir}/archiva/urlcache + false + 1000 + LRU + url-failures-cache + false + + 2700 + + 1800 + + + + org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers diff --git a/archiva-web/archiva-webapp/src/test/resources/repository-archiva.xml b/archiva-web/archiva-webapp/src/test/resources/repository-archiva.xml new file mode 100644 index 000000000..f642851be --- /dev/null +++ b/archiva-web/archiva-webapp/src/test/resources/repository-archiva.xml @@ -0,0 +1,111 @@ + + + + + + 2 + + + + + artifacts + + **/*.pom + **/*.jar + **/*.ear + **/*.war + **/*.car + **/*.sar + **/*.mar + **/*.rar + **/*.dtd + **/*.tld + **/*.tar.gz + **/*.tar.bz2 + **/*.zip + + + + indexable-content + + **/*.txt + **/*.TXT + **/*.block + **/*.config + **/*.pom + **/*.xml + **/*.xsd + **/*.dtd + **/*.tld + + + + auto-remove + + **/*.bak + **/*~ + **/*- + + + + ignored + + **/.htaccess + **/KEYS + **/*.rb + **/*.sh + **/.svn/** + **/.DAV/** + + + + + update-db-artifact + create-missing-checksums + update-db-repository-metadata + validate-checksum + validate-signature + index-content + auto-remove + auto-rename + + + update-db-bad-content + + + + + 0 0 * * ? + + index-artifact + update-db-project + validate-repository-metadata + index-archive-toc + update-db-bytecode-stats + index-public-methods + + + not-present-remove-db-artifact + not-present-remove-db-project + not-present-remove-indexed + + + + -- 2.39.5