From 7f9c76b0bb88191085f27333d27cccf7b831d63f Mon Sep 17 00:00:00 2001 From: "Maria Odea B. Ching" Date: Tue, 13 May 2008 06:35:24 +0000 Subject: [PATCH] [MRM-694] patch submitted by Napoleon Esmundo Ramirez -implement virtual repositories in archiva webdav [made some adjustments in the code because there were changes in the code after the patch was created] git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@655749 13f79535-47bb-0310-9956-ffa450edef68 --- .../RepositoryServletRepositoryGroupTest.java | 238 ++++++++++++++++++ .../webdav/ArchivaDavResourceFactory.java | 131 +++++++--- 2 files changed, 330 insertions(+), 39 deletions(-) create mode 100644 archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java diff --git a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java new file mode 100644 index 000000000..c3d98394c --- /dev/null +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java @@ -0,0 +1,238 @@ +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 java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.FileUtils; +import org.apache.maven.archiva.configuration.Configuration; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.apache.maven.archiva.configuration.RepositoryGroupConfiguration; + +import com.meterware.httpunit.GetMethodWebRequest; +import com.meterware.httpunit.PutMethodWebRequest; +import com.meterware.httpunit.WebRequest; +import com.meterware.httpunit.WebResponse; + + +/** + * RepositoryServletRepositoryGroupTest + * + * Test Case 1. Accessing a valid repository group root url (e.g. http://machine.com/repository/repository-group/) returns a Bad Request (HTTP 400) + * Test Case 2. Accessing an invalid repository group root url is forwarded to managed repository checking (this is not covered here) + * Test Case 3. Accessing an artifact in a valid repository group will iterate over the managed repositories in the repository group + * Test Case 3.a. If an invalid managed repository is encountered (managed repository doesn't exist), + * a Not Found (HTTP 404) is returned and the iteration is broken + * Test Case 3.b. If an artifact is not found in a valid managed repository (after proxying, etc.), + * a Not Found (HTTP 404) is set but not returned yet, the iteration continues to the next managed repository. + * The Not Found (HTTP 404) is returned after exhausting all valid managed repositories + * Test Case 3.c. If an artifact is found in a valid managed repository, + * the artifact is returned, the iteration is broken and any Not Found (HTTP 404) is disregarded + * Test Case 4. Accessing a valid repository group with any http write method returns a Bad Request (HTTP 400) + * + * @author + * + */ +public class RepositoryServletRepositoryGroupTest + extends AbstractRepositoryServletTestCase +{ + protected File repoRootFirst; + + protected File repoRootLast; + + protected File repoRootInvalid; + + protected static final String MANAGED_REPO_FIRST = "first"; + + protected static final String MANAGED_REPO_LAST = "last"; + + protected static final String MANAGED_REPO_INVALID = "invalid"; + + protected static final String REPO_GROUP_WITH_VALID_REPOS = "group-with-valid-repos"; + + protected static final String REPO_GROUP_WITH_INVALID_REPOS = "group-with-invalid-repos"; + + + protected void setUp() + throws Exception + { + super.setUp(); + + String appserverBase = System.getProperty( "appserver.base" ); + + Configuration configuration = archivaConfiguration.getConfiguration(); + + repoRootFirst = new File( appserverBase, "data/repositories/" + MANAGED_REPO_FIRST ); + repoRootLast = new File( appserverBase, "data/repositories/" + MANAGED_REPO_LAST ); + + configuration.addManagedRepository( createManagedRepository( MANAGED_REPO_FIRST, "First Test Repo", repoRootFirst ) ); + configuration.addManagedRepository( createManagedRepository( MANAGED_REPO_LAST, "Last Test Repo", repoRootLast ) ); + + List managedRepoIds = new ArrayList(); + managedRepoIds.add( MANAGED_REPO_FIRST ); + managedRepoIds.add( MANAGED_REPO_LAST ); + + configuration.addRepositoryGroup( createRepositoryGroup( REPO_GROUP_WITH_VALID_REPOS, managedRepoIds ) ); + + // Create the repository group with an invalid managed repository + repoRootInvalid = new File( appserverBase, "data/repositories/" + MANAGED_REPO_INVALID ); + ManagedRepositoryConfiguration managedRepositoryConfiguration = createManagedRepository( MANAGED_REPO_INVALID, "Invalid Test Repo", repoRootInvalid ); + + configuration.addManagedRepository( createManagedRepository( MANAGED_REPO_FIRST, "First Test Repo", repoRootFirst ) ); + configuration.addManagedRepository( managedRepositoryConfiguration ); + configuration.addManagedRepository( createManagedRepository( MANAGED_REPO_LAST, "Last Test Repo", repoRootLast ) ); + + List invalidManagedRepoIds = new ArrayList(); + invalidManagedRepoIds.add( MANAGED_REPO_FIRST ); + invalidManagedRepoIds.add( MANAGED_REPO_INVALID ); + invalidManagedRepoIds.add( MANAGED_REPO_LAST ); + + configuration.addRepositoryGroup( createRepositoryGroup( REPO_GROUP_WITH_INVALID_REPOS, invalidManagedRepoIds ) ); + + configuration.removeManagedRepository( managedRepositoryConfiguration ); + FileUtils.deleteDirectory( repoRootInvalid ); + + saveConfiguration( archivaConfiguration ); + } + + protected void tearDown() + throws Exception + { + setupCleanRepo( repoRootFirst ); + setupCleanRepo( repoRootLast ); + + super.tearDown(); + } + + + /* + * Test Case 1 + */ + public void testGetValidRepositoryGroupRootPathReturnBadRequest() + throws Exception + { + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS ); + WebResponse response = sc.getResponse( request ); + + assertResponseBadRequest( response ); + } + + /* + * Test Case 3.c + */ + public void testGetFromFirstManagedRepositoryReturnOk() + throws Exception + { + String resourceName = "dummy/dummy-first-resource/1.0/dummy-first-resource-1.0.txt"; + + File dummyInternalResourceFile = new File( repoRootFirst, resourceName ); + dummyInternalResourceFile.getParentFile().mkdirs(); + FileUtils.writeStringToFile( dummyInternalResourceFile, "first", null ); + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/" + resourceName ); + WebResponse response = sc.getResponse( request ); + + assertResponseOK( response ); + assertEquals( "Expected file contents", "first", response.getText() ); + } + + /* + * Test Case 3.c + */ + public void testGetFromLastManagedRepositoryReturnOk() + throws Exception + { + String resourceName = "dummy/dummy-last-resource/1.0/dummy-last-resource-1.0.txt"; + + File dummyReleasesResourceFile = new File( repoRootLast, resourceName ); + dummyReleasesResourceFile.getParentFile().mkdirs(); + FileUtils.writeStringToFile( dummyReleasesResourceFile, "last", null ); + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/" + resourceName ); + WebResponse response = sc.getResponse( request ); + + assertResponseOK( response ); + assertEquals( "Expected file contents", "last", response.getText() ); + } + + /* + * Test Case 3.b + */ + public void testGetFromValidRepositoryGroupReturnNotFound() + throws Exception + { + String resourceName = "dummy/dummy-no-resource/1.0/dummy-no-resource-1.0.txt"; + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/" + resourceName ); + WebResponse response = sc.getResponse( request ); + + assertResponseNotFound( response ); + } + + /* + * Test Case 3.a + */ + public void testGetInvalidManagedRepositoryInGroupReturnNotFound() + throws Exception + { + String resourceName = "dummy/dummy-no-resource/1.0/dummy-no-resource-1.0.txt"; + + WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_INVALID_REPOS + "/" + resourceName ); + WebResponse response = sc.getResponse( request ); + + assertResponseNotFound( response ); + } + + /* + * Test Case 4 + */ + public void testPutValidRepositoryGroupReturnBadRequest() + throws Exception + { + String resourceName = "dummy/dummy-put-resource/1.0/dummy-put-resource-1.0.txt"; + String putUrl = "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/" + resourceName; + InputStream is = getClass().getResourceAsStream( "/artifact.jar" ); + + WebRequest request = new PutMethodWebRequest( putUrl, is, "text/plain" ); + WebResponse response = sc.getResponse( request ); + + assertResponseBadRequest( response ); + } + + + protected void assertResponseBadRequest( WebResponse response ) + { + assertNotNull( "Should have recieved a response", response ); + assertEquals( "Should have been an 400/Bad Request response code.", HttpServletResponse.SC_BAD_REQUEST, response.getResponseCode() ); + } + + protected RepositoryGroupConfiguration createRepositoryGroup( String id, List repositories ) + { + RepositoryGroupConfiguration repoGroupConfiguration = new RepositoryGroupConfiguration(); + repoGroupConfiguration.setId( id ); + repoGroupConfiguration.setRepositories( repositories ); + return repoGroupConfiguration; + } +} diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java index 0bf34a0fe..4c490ab93 100644 --- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java +++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java @@ -37,6 +37,8 @@ import org.apache.maven.archiva.webdav.util.MimeTypes; import org.apache.maven.archiva.webdav.util.RepositoryPathUtil; import org.apache.maven.archiva.proxy.RepositoryProxyConnectors; import org.apache.maven.archiva.common.utils.PathUtil; +import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.RepositoryGroupConfiguration; import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.ProjectReference; import org.apache.maven.archiva.model.VersionedReference; @@ -92,53 +94,99 @@ public class ArchivaDavResourceFactory implements DavResourceFactory, Auditable * @plexus.requirement */ private MimeTypes mimeTypes; + + + /** + * @plexus.requirement + */ + private ArchivaConfiguration archivaConfiguration; public DavResource createResource(final DavResourceLocator locator, final DavServletRequest request, final DavServletResponse response) throws DavException - { + { checkLocatorIsInstanceOfRepositoryLocator(locator); ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator)locator; - - DavResource resource = null; - - if (!locator.getResourcePath().startsWith(ArchivaDavResource.HIDDEN_PATH_PREFIX)) + + RepositoryGroupConfiguration repoGroupConfig = archivaConfiguration.getConfiguration() + .getRepositoryGroupsAsMap().get( ( (RepositoryLocator) locator).getRepositoryId() ); + + List repositories = new ArrayList(); + + if ( repoGroupConfig != null ) { - final ManagedRepositoryContent managedRepository = getManagedRepository(((RepositoryLocator)locator).getRepositoryId()); - - if (managedRepository != null) - { - LogicalResource logicalResource = new LogicalResource(RepositoryPathUtil.getLogicalResource(locator.getResourcePath())); - boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() ); - boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); - - if (isGet) - { - resource = doGet(managedRepository, request, archivaLocator, logicalResource); - } - - if (isPut) - { - resource = doPut(managedRepository, request, archivaLocator, logicalResource); - } - } - else - { - throw new DavException(HttpServletResponse.SC_NOT_FOUND, "Repository does not exist"); + if ( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ).equals( "/" ) + || WebdavMethodUtil.isWriteMethod( request.getMethod() ) ) + { + throw new DavException( HttpServletResponse.SC_BAD_REQUEST, "Bad request to repository group <" + + repoGroupConfig.getId() + ">" ); } + repositories.addAll( repoGroupConfig.getRepositories() ); + } + else + { + repositories.add( ( (RepositoryLocator) locator).getRepositoryId() ); + } - if (resource == null) + DavResource resource = null; + DavException e = null; + + for ( String repositoryId : repositories ) + { + ManagedRepositoryContent managedRepository = null; + + try { - throw new DavException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not get resource for method " + request.getMethod()); + managedRepository = getManagedRepository( repositoryId ); + } + catch ( DavException de ) + { + throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid managed repository <" + repositoryId + + ">" ); } + + if (!locator.getResourcePath().startsWith(ArchivaDavResource.HIDDEN_PATH_PREFIX)) + { + if (managedRepository != null) + { + LogicalResource logicalResource = new LogicalResource(RepositoryPathUtil.getLogicalResource(locator.getResourcePath())); + + boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() ); + boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() ); - setHeaders(locator, response); + if (isGet) + { + resource = doGet(managedRepository, request, archivaLocator, logicalResource); + } - //compatibility with MRM-440 to ensure browsing the repository works ok - if (resource.isCollection() && !resource.getLocator().getResourcePath().endsWith("/")) - { - throw new BrowserRedirectException(resource.getHref()); + if (isPut) + { + resource = doPut(managedRepository, request, archivaLocator, logicalResource); + } + } + else + { + e = new DavException(HttpServletResponse.SC_NOT_FOUND, "Repository does not exist"); + } + + if (resource == null) + { + e = new DavException(HttpServletResponse.SC_NOT_FOUND, "Repository does not exist"); + } + else + { + setHeaders(locator, response); + + //compatibility with MRM-440 to ensure browsing the repository works ok + if (resource.isCollection() && !resource.getLocator().getResourcePath().endsWith("/")) + { + throw new BrowserRedirectException(resource.getHref()); + } + + return resource; + } } - } - return resource; + } + + throw e; } public DavResource createResource(final DavResourceLocator locator, final DavSession davSession) throws DavException @@ -152,7 +200,7 @@ public class ArchivaDavResourceFactory implements DavResourceFactory, Auditable ManagedRepositoryContent managedRepository = getManagedRepository(archivaLocator.getRepositoryId()); String logicalResource = RepositoryPathUtil.getLogicalResource(locator.getResourcePath()); File resourceFile = new File ( managedRepository.getRepoRoot(), logicalResource); - resource = new ArchivaDavResource(resourceFile.getAbsolutePath(), logicalResource, mimeTypes, archivaLocator, this); + resource = new ArchivaDavResource(resourceFile.getAbsolutePath(), logicalResource, mimeTypes, archivaLocator, this); } return resource; } @@ -192,6 +240,11 @@ public class ArchivaDavResourceFactory implements DavResourceFactory, Auditable processAuditEvents(request, locator.getWorkspaceName(), logicalResource.getPath(), previouslyExisted, resourceFile, " (proxied)"); } resource = new ArchivaDavResource(resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, locator, this); + + if ( !resourceFile.exists() ) + { + resource = null; + } } return resource; } @@ -476,7 +529,7 @@ public class ArchivaDavResourceFactory implements DavResourceFactory, Auditable } private ManagedRepositoryContent getManagedRepository(String respositoryId) throws DavException - { + { if (respositoryId != null) { try @@ -484,11 +537,11 @@ public class ArchivaDavResourceFactory implements DavResourceFactory, Auditable return repositoryFactory.getManagedRepositoryContent(respositoryId); } catch (RepositoryNotFoundException e) - { + { throw new DavException(HttpServletResponse.SC_NOT_FOUND, e); } catch (RepositoryException e) - { + { throw new DavException(HttpServletResponse.SC_NOT_FOUND, e); } } -- 2.39.5