Browse Source

[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
tags/archiva-1.0-beta-3
Joakim Erdfelt 16 years ago
parent
commit
e0d19c4d97

+ 69
- 0
archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/PolicingServletRequest.java View File

@@ -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 <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
* @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;
}
}

+ 122
- 79
archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java View File

@@ -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( "</a></p>" );
if ( t != null )
{
out.println( "<pre>" );
t.printStackTrace( out );
out.println( "</pre>" );
}

out.println( "</body></html>" );

@@ -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()
{

+ 9
- 0
archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/RepositoryServlet.java View File

@@ -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 )
{

+ 129
- 0
archiva-web/archiva-webapp/src/main/resources/org/codehaus/plexus/webdav/util/mime-types.txt View File

@@ -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 <http://www.iana.org/assignments/media-types/>.

# 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

+ 246
- 26
archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletTest.java View File

@@ -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 <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
* @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;
}
}

+ 50
- 1
archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/repository/RepositoryServletTest.xml View File

@@ -29,15 +29,64 @@
<lifecycle-handler>basic</lifecycle-handler>
</component>

<!--
| Configuration
-->
<component>
<role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
<implementation>org.apache.maven.archiva.configuration.DefaultArchivaConfiguration</implementation>
<requirements>
<requirement>
<role>org.codehaus.plexus.registry.Registry</role>
<role-hint>configured</role-hint>
</requirement>
</requirements>
</component>
<component>
<role>org.codehaus.plexus.registry.Registry</role>
<role-hint>configured</role-hint>
<implementation>org.codehaus.plexus.registry.commons.CommonsConfigurationRegistry</implementation>
<configuration>
<properties>
<system/>
<xml fileName="${appserver.base}/conf/archiva.xml"
config-name="org.apache.maven.archiva.base" config-at="org.apache.maven.archiva"/>
</properties>
</configuration>
</component>
<component>
<role>org.codehaus.plexus.webdav.DavServerManager</role>
<role-hint>default</role-hint>
<implementation>org.codehaus.plexus.webdav.DefaultDavServerManager</implementation>
<description>DefaultDavServerManager</description>
<configuration>
<provider-hint>proxied</provider-hint>
</configuration>
</component>

<component>
<role>org.codehaus.plexus.cache.Cache</role>
<role-hint>url-failures-cache</role-hint>
<implementation>org.codehaus.plexus.cache.ehcache.EhcacheCache</implementation>
<description>URL Failure Cache</description>
<configuration>
<disk-expiry-thread-interval-seconds>600</disk-expiry-thread-interval-seconds>
<disk-persistent>false</disk-persistent> <!--disabling disk persistence for unit testing. -->
<disk-store-path>${java.io.tmpdir}/archiva/urlcache</disk-store-path>
<eternal>false</eternal>
<max-elements-in-memory>1000</max-elements-in-memory>
<memory-eviction-policy>LRU</memory-eviction-policy>
<name>url-failures-cache</name>
<overflow-to-disk>false</overflow-to-disk>
<!-- 45 minutes = 2700 seconds -->
<time-to-idle-seconds>2700</time-to-idle-seconds>
<!-- 30 minutes = 1800 seconds -->
<time-to-live-seconds>1800</time-to-live-seconds>
</configuration>
</component>
<!-- Don't drag in the world just to test this -->
<component>
<role>org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers</role>

+ 111
- 0
archiva-web/archiva-webapp/src/test/resources/repository-archiva.xml View File

@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ 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.
-->

<configuration>

<version>2</version>
<repositoryScanning>
<fileTypes>
<fileType>
<id>artifacts</id>
<patterns>
<pattern>**/*.pom</pattern>
<pattern>**/*.jar</pattern>
<pattern>**/*.ear</pattern>
<pattern>**/*.war</pattern>
<pattern>**/*.car</pattern>
<pattern>**/*.sar</pattern>
<pattern>**/*.mar</pattern>
<pattern>**/*.rar</pattern>
<pattern>**/*.dtd</pattern>
<pattern>**/*.tld</pattern>
<pattern>**/*.tar.gz</pattern>
<pattern>**/*.tar.bz2</pattern>
<pattern>**/*.zip</pattern>
</patterns>
</fileType>
<fileType>
<id>indexable-content</id>
<patterns>
<pattern>**/*.txt</pattern>
<pattern>**/*.TXT</pattern>
<pattern>**/*.block</pattern>
<pattern>**/*.config</pattern>
<pattern>**/*.pom</pattern>
<pattern>**/*.xml</pattern>
<pattern>**/*.xsd</pattern>
<pattern>**/*.dtd</pattern>
<pattern>**/*.tld</pattern>
</patterns>
</fileType>
<fileType>
<id>auto-remove</id>
<patterns>
<pattern>**/*.bak</pattern>
<pattern>**/*~</pattern>
<pattern>**/*-</pattern>
</patterns>
</fileType>
<fileType>
<id>ignored</id>
<patterns>
<pattern>**/.htaccess</pattern>
<pattern>**/KEYS</pattern>
<pattern>**/*.rb</pattern>
<pattern>**/*.sh</pattern>
<pattern>**/.svn/**</pattern>
<pattern>**/.DAV/**</pattern>
</patterns>
</fileType>
</fileTypes>
<knownContentConsumers>
<knownContentConsumer>update-db-artifact</knownContentConsumer>
<knownContentConsumer>create-missing-checksums</knownContentConsumer>
<knownContentConsumer>update-db-repository-metadata</knownContentConsumer>
<knownContentConsumer>validate-checksum</knownContentConsumer>
<knownContentConsumer>validate-signature</knownContentConsumer>
<knownContentConsumer>index-content</knownContentConsumer>
<knownContentConsumer>auto-remove</knownContentConsumer>
<knownContentConsumer>auto-rename</knownContentConsumer>
</knownContentConsumers>
<invalidContentConsumers>
<invalidContentConsumer>update-db-bad-content</invalidContentConsumer>
</invalidContentConsumers>
</repositoryScanning>

<databaseScanning>
<cronExpression>0 0 * * ?</cronExpression>
<unprocessedConsumers>
<unprocessedConsumer>index-artifact</unprocessedConsumer>
<unprocessedConsumer>update-db-project</unprocessedConsumer>
<unprocessedConsumer>validate-repository-metadata</unprocessedConsumer>
<unprocessedConsumer>index-archive-toc</unprocessedConsumer>
<unprocessedConsumer>update-db-bytecode-stats</unprocessedConsumer>
<unprocessedConsumer>index-public-methods</unprocessedConsumer>
</unprocessedConsumers>
<cleanupConsumers>
<cleanupConsumer>not-present-remove-db-artifact</cleanupConsumer>
<cleanupConsumer>not-present-remove-db-project</cleanupConsumer>
<cleanupConsumer>not-present-remove-indexed</cleanupConsumer>
</cleanupConsumers>
</databaseScanning>

</configuration>

Loading…
Cancel
Save