Author: oching
Date: Tue May 20 07:34:48 2008
New Revision: 658261
URL: http://svn.apache.org/viewvc?rev=658261&view=rev
Log:
[MRM-694]
-handle virtual repos in webdav browse
-add new DavResource for virtual repos
Added:
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java
Modified:
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/IndexWriter.java
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtil.java
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtilTest.java
Modified:
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java
URL:
http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java?rev=658261&r1=658260&r2=658261&view=diff
==============================================================================
---
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java
(original)
+++
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/repository/RepositoryServletRepositoryGroupTest.java
Tue May 20 07:34:48 2008
@@ -125,20 +125,7 @@
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
*/
@@ -217,11 +204,20 @@
WebRequest request = new PutMethodWebRequest( putUrl, is, "text/plain"
);
WebResponse response = sc.getResponse( request );
-
+
assertResponseBadRequest( response );
}
-
+ public void testBrowseRepositoryGroup()
+ throws Exception
+ {
+ WebRequest request = new GetMethodWebRequest(
"http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS );
+ WebResponse response = sc.getResponse( request );
+
+ assertNotNull( "Should have received a response", response );
+ assertResponseOK( response );
+ }
+
protected void assertResponseBadRequest( WebResponse response )
{
assertNotNull( "Should have recieved a response", response );
Modified:
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
URL:
http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java?rev=658261&r1=658260&r2=658261&view=diff
==============================================================================
---
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
(original)
+++
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
Tue May 20 07:34:48 2008
@@ -123,7 +123,7 @@
public DavResource createResource( final DavResourceLocator locator, final
DavServletRequest request,
final DavServletResponse response )
throws DavException
- {
+ {
checkLocatorIsInstanceOfRepositoryLocator( locator );
ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator)
locator;
@@ -134,23 +134,21 @@
boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() );
boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
-
+
if ( repoGroupConfig != null )
- {
- if ( RepositoryPathUtil.getLogicalResource(
locator.getResourcePath() ).equals( "/" ) ||
- WebdavMethodUtil.isWriteMethod( request.getMethod() ) )
+ {
+ if( WebdavMethodUtil.isWriteMethod( request.getMethod() ) )
{
throw new DavException( HttpServletResponse.SC_BAD_REQUEST,
"Bad request to repository group <" +
repoGroupConfig.getId() + ">" );
}
repositories.addAll( repoGroupConfig.getRepositories() );
- // do not allow write request for repo groups
- if( isPut )
- {
- throw new DavException( HttpServletResponse.SC_FORBIDDEN,
"Write request is not allowed for <" +
- repoGroupConfig.getId() + ">" );
- }
+ // handle browse requests for virtual repos
+ if ( RepositoryPathUtil.getLogicalResource(
locator.getResourcePath() ).endsWith( "/" ) )
+ {
+ return getResource( repositories, archivaLocator );
+ }
}
else
{
@@ -231,7 +229,7 @@
public DavResource createResource( final DavResourceLocator locator, final
DavSession davSession )
throws DavException
- {
+ {
checkLocatorIsInstanceOfRepositoryLocator( locator );
ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator)
locator;
@@ -666,4 +664,44 @@
}
}
+ private DavResource getResource( List<String> repositories,
ArchivaDavResourceLocator locator )
+ throws DavException
+ {
+ List<File> mergedRepositoryContents = new ArrayList<File>();
+ LogicalResource logicalResource =
+ new LogicalResource( RepositoryPathUtil.getLogicalResource(
locator.getResourcePath() ) );
+
+ for( String repository : repositories )
+ {
+ ManagedRepositoryContent managedRepository = null;
+
+ try
+ {
+ managedRepository = getManagedRepository( repository );
+ }
+ catch ( DavException de )
+ {
+ throw new DavException( HttpServletResponse.SC_NOT_FOUND,
"Invalid managed repository <" +
+ repository + ">" );
+ }
+
+ if ( !locator.getResourcePath().startsWith(
ArchivaVirtualDavResource.HIDDEN_PATH_PREFIX ) )
+ {
+ if( managedRepository != null )
+ {
+ File resourceFile = new File(
managedRepository.getRepoRoot(), logicalResource.getPath() );
+ if( resourceFile.exists() )
+ {
+ mergedRepositoryContents.add( resourceFile );
+ }
+ }
+ }
+ }
+
+ ArchivaVirtualDavResource resource =
+ new ArchivaVirtualDavResource( mergedRepositoryContents,
logicalResource.getPath(), mimeTypes, locator, this );
+
+ return resource;
+ }
+
}
Added:
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java
URL:
http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java?rev=658261&view=auto
==============================================================================
---
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java
(added)
+++
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaVirtualDavResource.java
Tue May 20 07:34:48 2008
@@ -0,0 +1,348 @@
+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 java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavResourceIterator;
+import org.apache.jackrabbit.webdav.DavResourceLocator;
+import org.apache.jackrabbit.webdav.DavSession;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.io.InputContext;
+import org.apache.jackrabbit.webdav.io.OutputContext;
+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.Type;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
+import org.apache.jackrabbit.webdav.property.ResourceType;
+import org.apache.maven.archiva.webdav.util.IndexWriter;
+import org.apache.maven.archiva.webdav.util.MimeTypes;
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
+
+/**
+ * DavResource for virtual repositories
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Maria Odea Ching</a>
+ */
+public class ArchivaVirtualDavResource
+ implements DavResource
+{
+ public static final String HIDDEN_PATH_PREFIX = ".";
+
+ private static final String COMPLIANCE_CLASS = "1";
+
+ private MimeTypes mimeTypes;
+
+ private ArchivaDavResourceLocator locator;
+
+ private DavResourceFactory factory;
+
+ private String logicalResource;
+
+ private DavPropertySet properties;
+
+ private boolean propsInitialized = false;
+
+ private static final String METHODS = "OPTIONS, GET, HEAD, POST, TRACE,
PROPFIND, PROPPATCH, MKCOL";
+
+ private final List<File> localResources;
+
+ public ArchivaVirtualDavResource( List<File> localResources, String
logicalResource, MimeTypes mimeTypes,
+ ArchivaDavResourceLocator locator,
DavResourceFactory factory )
+ {
+ this.localResources = localResources;
+ this.logicalResource = logicalResource;
+ this.mimeTypes = mimeTypes;
+ this.locator = locator;
+ this.factory = factory;
+ this.properties = new DavPropertySet();
+ }
+
+ public void spool( OutputContext outputContext )
+ throws IOException
+ {
+ Collections.sort( localResources );
+ List<File> localResourceFiles = new ArrayList<File>();
+
+ for ( File resourceFile : localResources )
+ {
+ if ( resourceFile.exists() )
+ {
+ localResourceFiles.add( resourceFile );
+ }
+ }
+
+ IndexWriter writer = new IndexWriter( this, localResourceFiles,
logicalResource );
+ writer.write( outputContext );
+ }
+
+ public void addLockManager( LockManager arg0 )
+ {
+
+ }
+
+ public void addMember( DavResource arg0, InputContext arg1 )
+ throws DavException
+ {
+
+ }
+
+ public MultiStatusResponse alterProperties( List arg0 )
+ throws DavException
+ {
+ return null;
+ }
+
+ public MultiStatusResponse alterProperties( DavPropertySet arg0,
DavPropertyNameSet arg1 )
+ throws DavException
+ {
+ return null;
+ }
+
+ public void copy( DavResource arg0, boolean arg1 )
+ throws DavException
+ {
+
+ }
+
+ public boolean exists()
+ {
+ // localResources are already filtered (all files in the list are
already existing)
+ return true;
+ }
+
+ public ActiveLock getLock( Type arg0, Scope arg1 )
+ {
+ return null;
+ }
+
+ public ActiveLock[] getLocks()
+ {
+ return null;
+ }
+
+ public DavResourceIterator getMembers()
+ {
+ return null;
+ }
+
+ public String getSupportedMethods()
+ {
+ return METHODS;
+ }
+
+ public long getModificationTime()
+ {
+ return 0;
+ }
+
+ public boolean hasLock( Type arg0, Scope arg1 )
+ {
+ return false;
+ }
+
+ public boolean isCollection()
+ {
+ return true;
+ }
+
+ public boolean isLockable( Type arg0, Scope arg1 )
+ {
+ return false;
+ }
+
+ public ActiveLock lock( LockInfo arg0 )
+ throws DavException
+ {
+ return null;
+ }
+
+ public void move( DavResource arg0 )
+ throws DavException
+ {
+
+ }
+
+ public ActiveLock refreshLock( LockInfo arg0, String arg1 )
+ throws DavException
+ {
+ return null;
+ }
+
+ public void removeMember( DavResource arg0 )
+ throws DavException
+ {
+
+ }
+
+ public void unlock( String arg0 )
+ throws DavException
+ {
+
+ }
+
+ public String getComplianceClass()
+ {
+ return COMPLIANCE_CLASS;
+ }
+
+ public DavResourceLocator getLocator()
+ {
+ return locator;
+ }
+
+ public String getResourcePath()
+ {
+ return locator.getResourcePath();
+ }
+
+ public String getHref()
+ {
+ return locator.getHref( isCollection() );
+ }
+
+ public DavResourceFactory getFactory()
+ {
+ return factory;
+ }
+
+ public String getDisplayName()
+ {
+ String resPath = getResourcePath();
+
+ return ( resPath != null ) ? Text.getName( resPath ) : resPath;
+ }
+
+ public DavSession getSession()
+ {
+ return null;
+ }
+
+ public DavPropertyName[] getPropertyNames()
+ {
+ return getProperties().getPropertyNames();
+ }
+
+ public DavProperty getProperty( DavPropertyName name )
+ {
+ initProperties();
+ return properties.get( name );
+ }
+
+ public DavPropertySet getProperties()
+ {
+ initProperties();
+ return properties;
+ }
+
+ public void setProperty( DavProperty property )
+ throws DavException
+ {
+ }
+
+ public void removeProperty( DavPropertyName propertyName )
+ throws DavException
+ {
+ }
+
+ public DavResource getCollection()
+ {
+ DavResource parent = null;
+ if ( getResourcePath() != null && !getResourcePath().equals( "/" ) )
+ {
+ String parentPath = Text.getRelativeParent( getResourcePath(), 1 );
+ if ( parentPath.equals( "" ) )
+ {
+ parentPath = "/";
+ }
+ DavResourceLocator parentloc =
locator.getFactory().createResourceLocator( locator.getPrefix(), parentPath );
+ try
+ {
+ // go back to ArchivaDavResourceFactory!
+ parent = factory.createResource( parentloc, null );
+ }
+ catch ( DavException e )
+ {
+ // should not occur
+ }
+ }
+ return parent;
+ }
+
+ /**
+ * Fill the set of properties
+ */
+ protected void initProperties()
+ {
+ if ( !exists() || propsInitialized )
+ {
+ return;
+ }
+
+ // set (or reset) fundamental properties
+ if ( getDisplayName() != null )
+ {
+ properties.add( new DefaultDavProperty(
DavPropertyName.DISPLAYNAME, getDisplayName() ) );
+ }
+ if ( isCollection() )
+ {
+ properties.add( new ResourceType( ResourceType.COLLECTION ) );
+ // Windows XP support
+ properties.add( new DefaultDavProperty(
DavPropertyName.ISCOLLECTION, "1" ) );
+ }
+ else
+ {
+ properties.add( new ResourceType( ResourceType.DEFAULT_RESOURCE )
);
+
+ // Windows XP support
+ properties.add( new DefaultDavProperty(
DavPropertyName.ISCOLLECTION, "0" ) );
+ }
+
+ // Need to get the ISO8601 date for properties
+ DateTime dt = new DateTime( 0 );
+ DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
+ String modifiedDate = fmt.print( dt );
+
+ properties.add( new DefaultDavProperty(
DavPropertyName.GETLASTMODIFIED, modifiedDate ) );
+
+ properties.add( new DefaultDavProperty( DavPropertyName.CREATIONDATE,
modifiedDate ) );
+
+ properties.add( new DefaultDavProperty(
DavPropertyName.GETCONTENTLENGTH, 0 ) );
+
+ propsInitialized = true;
+ }
+
+}
Modified:
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/IndexWriter.java
URL:
http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/IndexWriter.java?rev=658261&r1=658260&r2=658261&view=diff
==============================================================================
---
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/IndexWriter.java
(original)
+++
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/IndexWriter.java
Tue May 20 07:34:48 2008
@@ -26,7 +26,9 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.io.PrintWriter;
import java.io.File;
@@ -37,19 +39,31 @@
{
private final DavResource resource;
- private final File localResource;
-
private final String logicalResource;
-
+
+ private final List<File> localResources;
+
+ private final boolean isVirtual;
+
public IndexWriter(DavResource resource, File localResource, String
logicalResource)
{
this.resource = resource;
- this.localResource = localResource;
+ this.localResources = new ArrayList<File>();
+ this.localResources.add( localResource );
+ this.logicalResource = logicalResource;
+ this.isVirtual = false;
+ }
+
+ public IndexWriter( DavResource resource, List<File> localResources,
String logicalResource )
+ {
+ this.resource = resource;
this.logicalResource = logicalResource;
+ this.localResources = localResources;
+ this.isVirtual = true;
}
public void write(OutputContext outputContext)
- {
+ {
outputContext.setModificationTime(new Date().getTime());
outputContext.setContentType("text/html");
outputContext.setETag("");
@@ -94,18 +108,50 @@
}
private void writeHyperlinks(PrintWriter writer)
- {
- List<File> files = new ArrayList<File>( Arrays.asList(
localResource.listFiles() ) );
- Collections.sort( files );
-
- for ( File file : files )
+ {
+ if( !isVirtual )
{
- writeHyperlink(writer, file.getName(), file.isDirectory());
+ for( File localResource : localResources )
+ {
+ List<File> files = new ArrayList<File>( Arrays.asList(
localResource.listFiles() ) );
+ Collections.sort( files );
+
+ for ( File file : files )
+ {
+ writeHyperlink( writer, file.getName(),
file.isDirectory(), false );
+ }
+ }
+ }
+ else
+ {
+ // virtual repository - filter unique directories
+ Map<String, File> uniqueChildFiles = new HashMap<String, File>();
+ for( File resource : localResources )
+ {
+ List<File> files = new ArrayList<File>( Arrays.asList(
resource.listFiles() ) );
+ Collections.sort( files );
+
+ for ( File file : files )
+ {
+ if( uniqueChildFiles.get( file.getName() ) == null )
+ {
+ uniqueChildFiles.put( file.getName(), file );
+ }
+ }
+ }
+
+ List<File> uniqueChildFilesInList = new ArrayList<File>();
+ uniqueChildFilesInList.addAll( uniqueChildFiles.values() );
+
+ for ( File file : uniqueChildFilesInList )
+ {
+ writeHyperlink( writer, file.getName(), file.isDirectory(),
true );
+ }
}
}
- private void writeHyperlink(PrintWriter writer, String resourceName,
boolean directory)
- {
+ private void writeHyperlink(PrintWriter writer, String resourceName,
boolean directory, boolean isBrowse )
+ {
if (directory)
{
writer.println("<li><a href=\"./" + resourceName + "/\">" +
resourceName + "</a></li>");
@@ -114,5 +160,5 @@
{
writer.println("<li><a href=\"./" + resourceName + "\">" +
resourceName + "</a></li>");
}
- }
+ }
}
Modified:
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtil.java
URL:
http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtil.java?rev=658261&r1=658260&r2=658261&view=diff
==============================================================================
---
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtil.java
(original)
+++
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtil.java
Tue May 20 07:34:48 2008
@@ -21,7 +21,6 @@
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.ArrayUtils;
-import org.apache.commons.io.FilenameUtils;
/**
* @author <a href="mailto:[EMAIL PROTECTED]">James William Dumay</a>
@@ -44,19 +43,19 @@
int slash = requestPathInfo.indexOf( '/' );
if ( slash > 0 )
- {
+ {
logicalResource = requestPathInfo.substring( slash );
-
+
if (logicalResource.endsWith( "/.." ) )
{
logicalResource += "/";
}
-
+
if ( logicalResource != null && logicalResource.startsWith( "//" )
)
{
logicalResource = logicalResource.substring( 1 );
}
-
+
if ( logicalResource == null )
{
logicalResource = "/";
@@ -100,6 +99,13 @@
{
return "/";
}
- return StringUtils.join(parts, '/');
+
+ String joinedString = StringUtils.join(parts, '/');
+ if( href.endsWith( "/" ) )
+ {
+ joinedString = joinedString + "/";
+ }
+
+ return joinedString;
}
}
Modified:
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtilTest.java
URL:
http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtilTest.java?rev=658261&r1=658260&r2=658261&view=diff
==============================================================================
---
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtilTest.java
(original)
+++
archiva/trunk/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/util/RepositoryPathUtilTest.java
Tue May 20 07:34:48 2008
@@ -45,5 +45,8 @@
href = "repository/internal/org/apache/maven/someartifact.jar";
assertEquals("/org/apache/maven/someartifact.jar",
RepositoryPathUtil.getLogicalResource(href));
+
+ href = "repository/internal/org/apache/maven/";
+ assertEquals( "/org/apache/maven/",
RepositoryPathUtil.getLogicalResource( href ) );
}
}