MRM-781 - Removal of Archiva-Webdav implementation in favor of Jackrabbit-webdav

* Adding LockManager to DavResourceFactory
* Adding locking support to DavResource
* General cleanup inside of the dav resource
* Adding DavSession attachement inside of DavSessionProvider
* Tests

NOTE: We should have a complete Class 2 locking implementation (Exclusive only) so OS X dav client should work



git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@661563 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
James William Dumay 2008-05-30 04:01:37 +00:00
parent 06b0d06fde
commit 721f552dfa
5 changed files with 340 additions and 38 deletions

View File

@ -56,23 +56,27 @@ public class ArchivaDavResource
private final String logicalResource; private final String logicalResource;
private static final String METHODS =
"OPTIONS, GET, HEAD, POST, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, PUT, DELETE, MOVE";
private static final String COMPLIANCE_CLASS = "1";
private DavPropertySet properties; private DavPropertySet properties;
private boolean propsInitialized = false; private boolean propsInitialized = false;
private LockManager lockManager;
private final DavSession session;
public ArchivaDavResource( String localResource, String logicalResource, MimeTypes mimeTypes, public ArchivaDavResource( String localResource,
ArchivaDavResourceLocator locator, DavResourceFactory factory ) String logicalResource,
MimeTypes mimeTypes,
DavSession session,
ArchivaDavResourceLocator locator,
DavResourceFactory factory )
{ {
this.mimeTypes = mimeTypes; this.mimeTypes = mimeTypes;
this.localResource = new File( localResource ); this.localResource = new File( localResource );
this.logicalResource = logicalResource; this.logicalResource = logicalResource;
this.locator = locator; this.locator = locator;
this.factory = factory; this.factory = factory;
this.session = session;
this.properties = new DavPropertySet(); this.properties = new DavPropertySet();
} }
@ -218,7 +222,7 @@ public class ArchivaDavResource
DavResourceLocator parentloc = locator.getFactory().createResourceLocator( locator.getPrefix(), parentPath ); DavResourceLocator parentloc = locator.getFactory().createResourceLocator( locator.getPrefix(), parentPath );
try try
{ {
parent = factory.createResource( parentloc, null ); parent = factory.createResource( parentloc, session );
} }
catch ( DavException e ) catch ( DavException e )
{ {
@ -285,7 +289,7 @@ public class ArchivaDavResource
String path = locator.getResourcePath() + '/' + item; String path = locator.getResourcePath() + '/' + item;
DavResourceLocator resourceLocator = DavResourceLocator resourceLocator =
locator.getFactory().createResourceLocator( locator.getPrefix(), path ); locator.getFactory().createResourceLocator( locator.getPrefix(), path );
DavResource resource = factory.createResource( resourceLocator, null ); DavResource resource = factory.createResource( resourceLocator, session );
if ( resource != null ) if ( resource != null )
list.add( resource ); list.add( resource );
} }
@ -302,20 +306,20 @@ public class ArchivaDavResource
public void removeMember( DavResource member ) public void removeMember( DavResource member )
throws DavException throws DavException
{ {
File localResource = checkDavResourceIsArchivaDavResource( member ).getLocalResource(); File resource = checkDavResourceIsArchivaDavResource( member ).getLocalResource();
if ( !localResource.exists() ) if ( !resource.exists() )
{ {
throw new DavException( HttpServletResponse.SC_NOT_FOUND, member.getResourcePath() ); throw new DavException( HttpServletResponse.SC_NOT_FOUND, member.getResourcePath() );
} }
boolean suceeded = false; boolean suceeded = false;
if ( localResource.isDirectory() ) if ( resource.isDirectory() )
{ {
try try
{ {
FileUtils.deleteDirectory( localResource ); FileUtils.deleteDirectory( resource );
suceeded = true; suceeded = true;
} }
catch ( IOException e ) catch ( IOException e )
@ -324,9 +328,9 @@ public class ArchivaDavResource
} }
} }
if ( !suceeded && localResource.isFile() ) if ( !suceeded && resource.isFile() )
{ {
suceeded = localResource.delete(); suceeded = resource.delete();
} }
if ( !suceeded ) if ( !suceeded )
@ -346,14 +350,14 @@ public class ArchivaDavResource
try try
{ {
ArchivaDavResource localResource = checkDavResourceIsArchivaDavResource( destination ); ArchivaDavResource resource = checkDavResourceIsArchivaDavResource( destination );
if ( isCollection() ) if ( isCollection() )
{ {
FileUtils.moveDirectory( getLocalResource(), localResource.getLocalResource() ); FileUtils.moveDirectory( getLocalResource(), resource.getLocalResource() );
} }
else else
{ {
FileUtils.moveFile( getLocalResource(), localResource.getLocalResource() ); FileUtils.moveFile( getLocalResource(), resource.getLocalResource() );
} }
} }
catch ( IOException e ) catch ( IOException e )
@ -377,14 +381,14 @@ public class ArchivaDavResource
try try
{ {
ArchivaDavResource localResource = checkDavResourceIsArchivaDavResource( destination ); ArchivaDavResource resource = checkDavResourceIsArchivaDavResource( destination );
if ( isCollection() ) if ( isCollection() )
{ {
FileUtils.copyDirectory( getLocalResource(), localResource.getLocalResource() ); FileUtils.copyDirectory( getLocalResource(), resource.getLocalResource() );
} }
else else
{ {
FileUtils.copyFile( getLocalResource(), localResource.getLocalResource() ); FileUtils.copyFile( getLocalResource(), resource.getLocalResource() );
} }
} }
catch ( IOException e ) catch ( IOException e )
@ -395,43 +399,82 @@ public class ArchivaDavResource
public boolean isLockable( Type type, Scope scope ) public boolean isLockable( Type type, Scope scope )
{ {
return false; return Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope);
} }
public boolean hasLock( Type type, Scope scope ) public boolean hasLock( Type type, Scope scope )
{ {
return false; return getLock(type, scope) != null;
} }
public ActiveLock getLock( Type type, Scope scope ) public ActiveLock getLock( Type type, Scope scope )
{ {
return null; ActiveLock lock = null;
if (exists() && Type.WRITE.equals(type) && Scope.EXCLUSIVE.equals(scope))
{
lock = lockManager.getLock(type, scope, this);
}
return lock;
} }
public ActiveLock[] getLocks() public ActiveLock[] getLocks()
{ {
return new ActiveLock[0]; ActiveLock writeLock = getLock(Type.WRITE, Scope.EXCLUSIVE);
return (writeLock != null) ? new ActiveLock[]{writeLock} : new ActiveLock[0];
} }
public ActiveLock lock( LockInfo reqLockInfo ) public ActiveLock lock( LockInfo lockInfo )
throws DavException throws DavException
{ {
return null; ActiveLock lock = null;
if (isLockable(lockInfo.getType(), lockInfo.getScope()))
{
lock = lockManager.createLock(lockInfo, this);
}
else
{
throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Unsupported lock type or scope.");
}
return lock;
} }
public ActiveLock refreshLock( LockInfo reqLockInfo, String lockToken ) public ActiveLock refreshLock( LockInfo lockInfo, String lockToken )
throws DavException throws DavException
{ {
return null; if (!exists()) {
throw new DavException(DavServletResponse.SC_NOT_FOUND);
}
ActiveLock lock = getLock(lockInfo.getType(), lockInfo.getScope());
if (lock == null) {
throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "No lock with the given type/scope present on resource " + getResourcePath());
}
lock = lockManager.refreshLock(lockInfo, lockToken, this);
return lock;
} }
public void unlock( String lockToken ) public void unlock( String lockToken )
throws DavException throws DavException
{ {
ActiveLock lock = getLock(Type.WRITE, Scope.EXCLUSIVE);
if (lock == null)
{
throw new DavException(HttpServletResponse.SC_PRECONDITION_FAILED);
}
else if (lock.isLockedByToken(lockToken))
{
lockManager.releaseLock(lockToken, this);
}
else
{
throw new DavException(DavServletResponse.SC_LOCKED);
}
} }
public void addLockManager( LockManager lockmgr ) public void addLockManager( LockManager lockManager )
{ {
this.lockManager = lockManager;
} }
public DavResourceFactory getFactory() public DavResourceFactory getFactory()
@ -441,7 +484,7 @@ public class ArchivaDavResource
public DavSession getSession() public DavSession getSession()
{ {
return null; return session;
} }
/** /**

View File

@ -68,6 +68,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.io.*; import java.io.*;
import org.apache.jackrabbit.webdav.lock.LockManager;
import org.apache.jackrabbit.webdav.lock.SimpleLockManager;
/** /**
* @author <a href="mailto:james@atlassian.com">James William Dumay</a> * @author <a href="mailto:james@atlassian.com">James William Dumay</a>
@ -123,6 +125,12 @@ public class ArchivaDavResourceFactory
*/ */
private HttpAuthenticator httpAuth; private HttpAuthenticator httpAuth;
/**
* Lock Manager - use simple implementation from JackRabbit
*/
private final LockManager lockManager = new SimpleLockManager();
public DavResource createResource( final DavResourceLocator locator, final DavServletRequest request, public DavResource createResource( final DavResourceLocator locator, final DavServletRequest request,
final DavServletResponse response ) final DavServletResponse response )
throws DavException throws DavException
@ -216,7 +224,7 @@ public class ArchivaDavResourceFactory
{ {
throw new BrowserRedirectException( resource.getHref() ); throw new BrowserRedirectException( resource.getHref() );
} }
resource.addLockManager(lockManager);
return resource; return resource;
} }
} }
@ -243,9 +251,10 @@ public class ArchivaDavResourceFactory
String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ); String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() );
File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource ); File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource );
resource = resource =
new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource, mimeTypes, archivaLocator, new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource, mimeTypes, davSession, archivaLocator,
this ); this );
} }
resource.addLockManager(lockManager);
return resource; return resource;
} }
@ -255,7 +264,7 @@ public class ArchivaDavResourceFactory
{ {
File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() ); File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() );
ArchivaDavResource resource = ArchivaDavResource resource =
new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, locator, this ); new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, request.getDavSession(), locator, this );
if ( !resource.isCollection() ) if ( !resource.isCollection() )
{ {
@ -289,7 +298,7 @@ public class ArchivaDavResourceFactory
resourceFile, " (proxied)" ); resourceFile, " (proxied)" );
} }
resource = resource =
new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, locator, new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, request.getDavSession(), locator,
this ); this );
if ( !resourceFile.exists() ) if ( !resourceFile.exists() )
@ -326,7 +335,7 @@ public class ArchivaDavResourceFactory
processAuditEvents( request, locator.getRepositoryId(), logicalResource.getPath(), previouslyExisted, processAuditEvents( request, locator.getRepositoryId(), logicalResource.getPath(), previouslyExisted,
resourceFile, null ); resourceFile, null );
return new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, locator, return new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), mimeTypes, request.getDavSession(), locator,
this ); this );
} }

View File

@ -46,6 +46,11 @@ public class ArchivaDavResourceLocator
this.repositoryId = repositoryId; this.repositoryId = repositoryId;
this.davLocatorFactory = davLocatorFactory; this.davLocatorFactory = davLocatorFactory;
this.resourcePath = resourcePath; this.resourcePath = resourcePath;
if (!resourcePath.startsWith("/"))
{
this.resourcePath = "/" + resourcePath;
}
String escapedPath = Text.escapePath( resourcePath ); String escapedPath = Text.escapePath( resourcePath );
String hrefPrefix = prefix; String hrefPrefix = prefix;

View File

@ -65,6 +65,9 @@ public class ArchivaDavSessionProvider
{ {
AuthenticationResult result = httpAuth.getAuthenticationResult( request, null ); AuthenticationResult result = httpAuth.getAuthenticationResult( request, null );
//Create a dav session
request.setDavSession(new ArchivaDavSession());
return servletAuth.isAuthenticated( request, result ); return servletAuth.isAuthenticated( request, result );
} }
catch ( AuthenticationException e ) catch ( AuthenticationException e )
@ -81,9 +84,13 @@ public class ArchivaDavSessionProvider
} }
} }
public void releaseSession( WebdavRequest webdavRequest ) public void releaseSession( WebdavRequest request )
{ {
//Remove DavSession
if (request.getDavSession() != null)
{
request.setDavSession(null);
}
} }
private String removeContextPath( final DavServletRequest request ) private String removeContextPath( final DavServletRequest request )

View File

@ -0,0 +1,238 @@
package org.apache.maven.archiva.webdav;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResource;
import org.apache.jackrabbit.webdav.DavServletResponse;
import org.apache.jackrabbit.webdav.DavSession;
import org.apache.jackrabbit.webdav.lock.ActiveLock;
import org.apache.jackrabbit.webdav.lock.LockInfo;
import org.apache.jackrabbit.webdav.lock.LockManager;
import org.apache.jackrabbit.webdav.lock.Scope;
import org.apache.jackrabbit.webdav.lock.SimpleLockManager;
import org.apache.jackrabbit.webdav.lock.Type;
import org.apache.maven.archiva.webdav.util.MimeTypes;
import org.codehaus.plexus.spring.PlexusInSpringTestCase;
import org.codehaus.plexus.spring.PlexusToSpringUtils;
import quicktime.std.qtcomponents.SCInfo;
public class DavResourceTest extends PlexusInSpringTestCase
{
private DavSession session;
private MimeTypes mimeTypes;
private ArchivaDavResourceLocator resourceLocator;
private ArchivaDavResourceFactory factory;
private File baseDir;
private final String REPOPATH = "/myresource.jar";
private final File myResource = new File(baseDir, REPOPATH);
private DavResource resource;
private LockManager lockManager;
@Override
protected void setUp()
throws Exception
{
super.setUp();
session = new ArchivaDavSession();
mimeTypes = (MimeTypes)getApplicationContext().getBean(PlexusToSpringUtils.buildSpringId(MimeTypes.class));
baseDir = new File("target/DavResourceTest");
baseDir.mkdirs();
myResource.createNewFile();
resourceLocator = (ArchivaDavResourceLocator)new ArchivaDavLocatorFactory().createResourceLocator("/", REPOPATH);
resource = getDavResource(REPOPATH, myResource);
lockManager = new SimpleLockManager();
resource.addLockManager(lockManager);
}
@Override
protected void tearDown()
throws Exception
{
super.tearDown();
release(mimeTypes);
FileUtils.deleteDirectory(baseDir);
}
private DavResource getDavResource(String logicalPath, File file)
{
return new ArchivaDavResource(logicalPath, file.getAbsolutePath(), mimeTypes, session, resourceLocator, null);
}
public void testIsLockable()
{
assertTrue(resource.isLockable(Type.WRITE, Scope.EXCLUSIVE));
assertFalse(resource.isLockable(Type.WRITE, Scope.SHARED));
}
public void testLock()
throws Exception
{
assertEquals(0, resource.getLocks().length);
LockInfo info = new LockInfo(Scope.EXCLUSIVE, Type.WRITE, "/", 0, false);
lockManager.createLock(info, resource);
assertEquals(1, resource.getLocks().length);
}
public void testLockIfResourceUnlockable()
throws Exception
{
assertEquals(0, resource.getLocks().length);
LockInfo info = new LockInfo(Scope.SHARED, Type.WRITE, "/", 0, false);
try
{
lockManager.createLock(info, resource);
fail("Did not throw dav exception");
}
catch (Exception e)
{
//Simple lock manager will die
}
assertEquals(0, resource.getLocks().length);
}
public void testGetLock()
throws Exception
{
LockInfo info = new LockInfo(Scope.EXCLUSIVE, Type.WRITE, "/", 0, false);
lockManager.createLock(info, resource);
assertEquals(1, resource.getLocks().length);
//Lock should exist
assertNotNull(resource.getLock(Type.WRITE, Scope.EXCLUSIVE));
//Lock should not exist
assertNull(resource.getLock(Type.WRITE, Scope.SHARED));
}
public void testRefreshLockThrowsExceptionIfNoLockIsPresent()
throws Exception
{
LockInfo info = new LockInfo(Scope.EXCLUSIVE, Type.WRITE, "/", 0, false);
assertEquals(0, resource.getLocks().length);
try
{
lockManager.refreshLock(info, "notoken", resource);
fail("Did not throw dav exception");
}
catch (DavException e)
{
assertEquals(DavServletResponse.SC_PRECONDITION_FAILED, e.getErrorCode());
}
assertEquals(0, resource.getLocks().length);
}
public void testRefreshLock()
throws Exception
{
LockInfo info = new LockInfo(Scope.EXCLUSIVE, Type.WRITE, "/", 0, false);
assertEquals(0, resource.getLocks().length);
lockManager.createLock(info, resource);
assertEquals(1, resource.getLocks().length);
ActiveLock lock = resource.getLocks()[0];
lockManager.refreshLock(info, lock.getToken(), resource);
assertEquals(1, resource.getLocks().length);
}
public void testUnlock()
throws Exception
{
LockInfo info = new LockInfo(Scope.EXCLUSIVE, Type.WRITE, "/", 0, false);
assertEquals(0, resource.getLocks().length);
lockManager.createLock(info, resource);
assertEquals(1, resource.getLocks().length);
ActiveLock lock = resource.getLocks()[0];
lockManager.releaseLock(lock.getToken(), resource);
assertEquals(0, resource.getLocks().length);
}
public void testUnlockThrowsDavExceptionIfNotLocked()
throws Exception
{
LockInfo info = new LockInfo(Scope.EXCLUSIVE, Type.WRITE, "/", 0, false);
assertEquals(0, resource.getLocks().length);
lockManager.createLock(info, resource);
assertEquals(1, resource.getLocks().length);
try
{
lockManager.releaseLock("BLAH", resource);
fail("Did not throw DavException");
}
catch (DavException e)
{
assertEquals(DavServletResponse.SC_LOCKED, e.getErrorCode());
}
assertEquals(1, resource.getLocks().length);
}
public void testUnlockThrowsDavExceptionIfResourceNotLocked()
throws Exception
{
assertEquals(0, resource.getLocks().length);
try
{
lockManager.releaseLock("BLAH", resource);
fail("Did not throw DavException");
}
catch (DavException e)
{
assertEquals(DavServletResponse.SC_PRECONDITION_FAILED, e.getErrorCode());
}
assertEquals(0, resource.getLocks().length);
}
}