* Upgraded webdav server to use new plexus-webdav with ability to override logic and correct flaws found in webdav servers.

* Added ProxiedDavServer component (used by plexus-webdav) to make /repository/ access proxied.
* Upgraded plexus, used [MRM-264] as baseline, but many more changes were needed.
* Plexus upgrade broken JSTL's <c:forTokens> taglib everywhere, corrected by moving away from that taglib.
* Created GroupIdLink tag following webwork guidelines for UI component.
* Fixed AuditLog.



git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@497563 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Joakim Erdfelt 2007-01-18 20:39:19 +00:00
parent 74d27bf44f
commit 79cc18ce70
36 changed files with 976 additions and 1542 deletions

View File

@ -37,7 +37,7 @@
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-cli</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>

View File

@ -33,6 +33,10 @@
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
@ -54,5 +58,11 @@
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!-- Needed for PlexusTestCase -->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -49,20 +49,30 @@
<groupId>org.apache.maven.archiva</groupId>
<artifactId>archiva-reports-standard</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-quartz</artifactId>
<version>1.0-alpha-2</version>
<version>1.0-alpha-4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-taskqueue</artifactId>
<version>1.0-alpha-4</version>
<version>1.0-alpha-6-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
<!-- needed for PlexusTestCase -->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -1,257 +0,0 @@
package org.apache.maven.archiva.proxy;
/*
* 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.apache.maven.archiva.configuration.Configuration;
import org.apache.maven.archiva.configuration.ConfigurationChangeException;
import org.apache.maven.archiva.configuration.ConfigurationChangeListener;
import org.apache.maven.archiva.configuration.ConfigurationStore;
import org.apache.maven.archiva.configuration.ConfigurationStoreException;
import org.apache.maven.archiva.configuration.ConfiguredRepositoryFactory;
import org.apache.maven.archiva.configuration.InvalidConfigurationException;
import org.apache.maven.archiva.configuration.ProxiedRepositoryConfiguration;
import org.apache.maven.archiva.configuration.Proxy;
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Default implementation of the proxy manager that bridges the repository configuration classes to the proxy API. This
* class is not thread safe (due to the request handler being a non-thread safe requirement).
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
* @todo we should be able to configure "views" that sit in front of this (ie, prefix = /legacy, appears as layout maven-1.x, path gets translated before being passed on)
* @plexus.component instantiation-strategy="per-lookup"
*/
public class DefaultProxyManager
extends AbstractLogEnabled
implements ProxyManager, ConfigurationChangeListener
{
/**
* @plexus.requirement
*/
private ConfigurationStore configurationStore;
/**
* @plexus.requirement role="org.apache.maven.archiva.proxy.ProxyRequestHandler"
* @todo seems to be a bug in qdox that the role above is required
*/
private ProxyRequestHandler requestHandler;
/**
* @plexus.requirement
*/
private ConfiguredRepositoryFactory repositoryFactory;
/**
* The proxy groups for each managed repository.
*/
private static Map/*<String,ProxiedRepositoryGroup>*/ proxyGroups;
/**
* The default proxy group/managed repository.
*/
private static ProxiedRepositoryGroup defaultProxyGroup;
public File get( String path )
throws ProxyException, ResourceDoesNotExistException
{
assert path.startsWith( "/" );
Map groups = getProxyGroups();
ProxiedRepositoryGroup proxyGroup = parseRepositoryId( path, groups );
String repositoryPath = path;
if ( proxyGroup == null )
{
if ( defaultProxyGroup != null )
{
proxyGroup = defaultProxyGroup;
}
else
{
throw new ResourceDoesNotExistException( "No repositories exist under the path: " + path );
}
}
else
{
String id = proxyGroup.getManagedRepository().getId();
getLogger().debug( "requesting " + repositoryPath + " from repository '" + id + "'" );
repositoryPath = repositoryPath.substring( id.length() + 2 );
}
return requestHandler.get( repositoryPath, proxyGroup.getProxiedRepositories(),
proxyGroup.getManagedRepository(), proxyGroup.getWagonProxy() );
}
public File getAlways( String path )
throws ProxyException, ResourceDoesNotExistException
{
assert path.startsWith( "/" );
Map groups = getProxyGroups();
ProxiedRepositoryGroup proxyGroup = parseRepositoryId( path, groups );
String repositoryPath = path;
if ( proxyGroup == null )
{
if ( defaultProxyGroup != null )
{
proxyGroup = defaultProxyGroup;
}
else
{
throw new ResourceDoesNotExistException( "No repositories exist under the path: " + path );
}
}
else
{
repositoryPath = repositoryPath.substring( proxyGroup.getManagedRepository().getId().length() + 2 );
}
return requestHandler.getAlways( repositoryPath, proxyGroup.getProxiedRepositories(),
proxyGroup.getManagedRepository(), proxyGroup.getWagonProxy() );
}
private Configuration getConfiguration()
throws ProxyException
{
Configuration configuration;
try
{
configuration = configurationStore.getConfigurationFromStore();
configurationStore.addChangeListener( this );
}
catch ( ConfigurationStoreException e )
{
throw new ProxyException( "Error reading configuration, unable to proxy any requests: " + e.getMessage(),
e );
}
return configuration;
}
private Map getProxyGroups()
throws ProxyException, ResourceDoesNotExistException
{
if ( proxyGroups == null )
{
Map groups = new HashMap();
Configuration configuration = getConfiguration();
ProxyInfo wagonProxy = createWagonProxy( configuration.getProxy() );
for ( Iterator i = configuration.getRepositories().iterator(); i.hasNext(); )
{
RepositoryConfiguration repository = (RepositoryConfiguration) i.next();
ArtifactRepository managedRepository = repositoryFactory.createRepository( repository );
List proxiedRepositories = getProxiedRepositoriesForManagedRepository(
configuration.getProxiedRepositories(), repository.getId() );
if ( !proxiedRepositories.isEmpty() )
{
groups.put( repository.getId(),
new ProxiedRepositoryGroup( proxiedRepositories, managedRepository, wagonProxy ) );
}
}
// TODO: ability to configure default proxy separately!
if ( groups.size() == 1 )
{
defaultProxyGroup = (ProxiedRepositoryGroup) groups.values().iterator().next();
}
proxyGroups = groups;
}
return proxyGroups;
}
private List getProxiedRepositoriesForManagedRepository( List proxiedRepositories, String id )
{
List repositories = new ArrayList();
for ( Iterator i = proxiedRepositories.iterator(); i.hasNext(); )
{
ProxiedRepositoryConfiguration config = (ProxiedRepositoryConfiguration) i.next();
if ( config.getManagedRepository().equals( id ) )
{
repositories.add( repositoryFactory.createProxiedRepository( config ) );
}
}
return repositories;
}
private static ProxiedRepositoryGroup parseRepositoryId( String path, Map groups )
throws ProxyException, ResourceDoesNotExistException
{
ProxiedRepositoryGroup group = null;
for ( Iterator i = groups.entrySet().iterator(); i.hasNext() && group == null; )
{
Map.Entry entry = (Map.Entry) i.next();
if ( path.startsWith( "/" + entry.getKey() + "/" ) )
{
group = (ProxiedRepositoryGroup) entry.getValue();
}
}
return group;
}
private static ProxyInfo createWagonProxy( Proxy proxy )
{
ProxyInfo proxyInfo = null;
if ( proxy != null && StringUtils.isNotEmpty( proxy.getHost() ) )
{
proxyInfo = new ProxyInfo();
proxyInfo.setHost( proxy.getHost() );
proxyInfo.setPort( proxy.getPort() );
proxyInfo.setUserName( proxy.getUsername() );
proxyInfo.setPassword( proxy.getPassword() );
proxyInfo.setNonProxyHosts( proxy.getNonProxyHosts() );
proxyInfo.setType( proxy.getProtocol() );
}
return proxyInfo;
}
public void notifyOfConfigurationChange( Configuration configuration )
throws InvalidConfigurationException, ConfigurationChangeException
{
// reinit
proxyGroups = null;
defaultProxyGroup = null;
getLogger().debug( "Re-initialising proxy configuration" );
}
}

View File

@ -1,93 +0,0 @@
package org.apache.maven.archiva.proxy;
/*
* 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.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.wagon.proxy.ProxyInfo;
import java.util.List;
/**
* A set of information to store for a group of proxies.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public class ProxiedRepositoryGroup
{
/**
* The locally managed repository that caches proxied artifacts.
*/
private ArtifactRepository managedRepository;
/**
* The remote repositories that are being proxied.
*/
private List/*<ArtifactRepository>*/ proxiedRepositories;
/**
* A wagon proxy to communicate to the proxy repository over a proxy (eg, http proxy)... TerminologyOverflowException
*/
private final ProxyInfo wagonProxy;
/**
* Constructor.
*
* @param proxiedRepositories the proxied repository
* @param managedRepository the locally managed repository
* @param wagonProxy the network proxy to use
*/
public ProxiedRepositoryGroup( List/*<ArtifactRepository>*/ proxiedRepositories,
ArtifactRepository managedRepository, ProxyInfo wagonProxy )
{
this.proxiedRepositories = proxiedRepositories;
this.managedRepository = managedRepository;
this.wagonProxy = wagonProxy;
}
/**
* Constructor.
*
* @param proxiedRepositories the proxied repository
* @param managedRepository the locally managed repository
*/
public ProxiedRepositoryGroup( List/*<ArtifactRepository>*/ proxiedRepositories,
ArtifactRepository managedRepository )
{
this( proxiedRepositories, managedRepository, null );
}
public ArtifactRepository getManagedRepository()
{
return managedRepository;
}
public List getProxiedRepositories()
{
return proxiedRepositories;
}
public ProxyInfo getWagonProxy()
{
return wagonProxy;
}
}

View File

@ -1,64 +0,0 @@
package org.apache.maven.archiva.proxy;
/*
* 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.maven.wagon.ResourceDoesNotExistException;
import java.io.File;
/**
* Repository proxying component. This component will take requests for a given path within a managed repository
* and if it is not found or expired, will look in the specified proxy repositories.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public interface ProxyManager
{
/**
* The Plexus role for the component.
*/
String ROLE = ProxyManager.class.getName();
/**
* Used to retrieve a cached path or retrieve one if the cache does not contain it yet.
*
* @param path the expected repository path
* @return File object referencing the requested path in the cache
* @throws ProxyException when an exception occurred during the retrieval of the requested path
* @throws org.apache.maven.wagon.ResourceDoesNotExistException
* when the requested object can't be found in any of the
* configured repositories
*/
File get( String path )
throws ProxyException, ResourceDoesNotExistException;
/**
* Used to force remote download of the requested path from any the configured repositories. This method will
* only bypass the cache for searching but the requested path will still be cached.
*
* @param path the expected repository path
* @return File object referencing the requested path in the cache
* @throws ProxyException when an exception occurred during the retrieval of the requested path
* @throws ResourceDoesNotExistException when the requested object can't be found in any of the
* configured repositories
*/
File getAlways( String path )
throws ProxyException, ResourceDoesNotExistException;
}

View File

@ -34,7 +34,7 @@
<plugin>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-appserver-maven-plugin</artifactId>
<version>2.0-alpha-5</version>
<version>2.0-alpha-7-SNAPSHOT</version>
<extensions>true</extensions>
<configuration>
<applicationConfiguration>src/conf/application.xml</applicationConfiguration>

View File

@ -27,7 +27,7 @@
<webapps>
<webapp>
<file>${plexus.home}/lib/archiva-webapp-@archivaVersion@.war</file>
<context>/</context>
<context>/archiva</context>
<extraction-path>${plexus.home}/webapp</extraction-path>
<standardWebappClassloader>true</standardWebappClassloader>
<listeners>

View File

@ -40,13 +40,13 @@
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-appserver-host</artifactId>
<version>2.0-alpha-5</version>
<version>2.0-alpha-7-SNAPSHOT</version>
</dependency>
<!-- Services -->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-appserver-service-jetty</artifactId>
<version>2.0-alpha-5</version>
<version>2.0-alpha-7-SNAPSHOT</version>
<type>plexus-service</type>
</dependency>
<!-- Plexus applications -->
@ -92,7 +92,7 @@
<plugin>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-appserver-maven-plugin</artifactId>
<version>2.0-alpha-5</version>
<version>2.0-alpha-7-SNAPSHOT</version>
<extensions>true</extensions>
<executions>
<execution>

View File

@ -37,5 +37,9 @@
<groupId>org.codehaus.plexus.security</groupId>
<artifactId>plexus-security-system</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -33,7 +33,13 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@ -140,6 +146,17 @@
<groupId>org.codehaus.plexus.security</groupId>
<artifactId>plexus-security-ui-web-taglib</artifactId>
</dependency>
<!-- Other dependencies -->
<dependency>
<groupId>org.codehaus.plexus.webdav</groupId>
<artifactId>plexus-webdav-simple</artifactId>
<version>1.0-alpha-1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-xwork-integration</artifactId>
<version>1.0-alpha-5-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
@ -149,11 +166,6 @@
<artifactId>derby</artifactId>
<version>10.1.3.1</version>
</dependency>
<dependency>
<groupId>it.could</groupId>
<artifactId>webdav</artifactId>
<version>0.4</version>
</dependency>
</dependencies>
<build>
<plugins>
@ -221,7 +233,7 @@
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.0</version>
<version>6.1.1</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<contextPath>/</contextPath>
@ -241,6 +253,10 @@
<name>derby.system.home</name>
<value>${project.build.directory}/appserver-base/logs</value>
</systemProperty>
<systemProperty>
<name>configuration.store.file</name>
<value>archiva-configuration.xml</value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>

View File

@ -1,130 +0,0 @@
package org.apache.maven.archiva.web.action;
/*
* 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 com.opensymphony.webwork.interceptor.ServletResponseAware;
import org.apache.maven.archiva.proxy.ProxyException;
import org.apache.maven.archiva.proxy.ProxyManager;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.codehaus.plexus.xwork.action.PlexusActionSupport;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* Proxy functionality.
*
* @plexus.component role="com.opensymphony.xwork.Action" role-hint="proxyAction"
*/
public class ProxyAction
extends PlexusActionSupport
implements ServletResponseAware
{
/**
* @plexus.requirement
*/
private ProxyManager proxyManager;
private String path;
private String filename;
private String contentType;
private static final String NOT_FOUND = "notFound";
private InputStream artifactStream;
private long contentLength;
private HttpServletResponse httpServletResponse;
public String execute()
throws ProxyException
{
try
{
File file = proxyManager.get( path );
artifactStream = new FileInputStream( file );
// TODO: set the correct content type and other headers!
contentType = "application/octet-stream";
filename = file.getName();
contentLength = file.length();
httpServletResponse.addDateHeader( "Last-Modified", file.lastModified() );
}
catch ( ResourceDoesNotExistException e )
{
getLogger().debug( "Requested proxy path not found: " + e.getMessage() );
// TODO: set message?
return NOT_FOUND;
}
catch ( FileNotFoundException e )
{
getLogger().debug( "Requested proxy file not found: " + e.getMessage() );
// TODO: set message?
return NOT_FOUND;
}
return SUCCESS;
}
public String getPath()
{
return path;
}
public void setPath( String path )
{
this.path = path;
}
public String getFilename()
{
return filename;
}
public String getContentType()
{
return contentType;
}
public long getContentLength()
{
return contentLength;
}
public InputStream getArtifactStream()
{
return artifactStream;
}
public void setServletResponse( HttpServletResponse httpServletResponse )
{
this.httpServletResponse = httpServletResponse;
}
}

View File

@ -0,0 +1,137 @@
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.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.webdav.DavServerComponent;
import org.codehaus.plexus.webdav.DavServerListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* AuditLog - Audit Log.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*
* @plexus.component role="org.apache.maven.archiva.web.repository.AuditLog"
*/
public class AuditLog
implements DavServerListener, Initializable
{
public static final String ROLE = AuditLog.class.getName();
/**
* @plexus.configuration default-value="${appserver.base}/logs/audit.log"
*/
private File logFile;
/**
* @plexus.configuration default-value="yyyy-MM-dd HH:mm:ss"
*/
private String timestampFormat;
private PrintWriter writer;
private SimpleDateFormat timestamp;
private String getServerId( DavServerComponent server )
{
return "[" + server.getPrefix() + "]";
}
public void serverCollectionCreated( DavServerComponent server, String resource )
{
log( getServerId( server ) + " Created Directory \"" + resource + "\"" );
}
public void serverCollectionRemoved( DavServerComponent server, String resource )
{
log( getServerId( server ) + " Removed Directory \"" + resource + "\"" );
}
public void serverResourceCreated( DavServerComponent server, String resource )
{
log( getServerId( server ) + " Created File \"" + resource + "\"" );
}
public void serverResourceModified( DavServerComponent server, String resource )
{
log( getServerId( server ) + " Modified Existing File \"" + resource + "\"" );
}
public void serverResourceRemoved( DavServerComponent server, String resource )
{
log( getServerId( server ) + " Removed File \"" + resource + "\"" );
}
/**
* Log the message to the file.
*
* @param msg the message.
*/
public void log( String msg )
{
// Synchronize to prevent threading issues.
synchronized ( writer )
{
writer.println( timestamp.format( new Date() ) + " - " + msg );
// Manually flush buffer to ensure data is written to disk.
writer.flush();
}
}
public void initialize()
throws InitializationException
{
File parentDir = logFile.getParentFile();
if ( parentDir != null )
{
if ( !parentDir.exists() )
{
parentDir.mkdirs();
}
}
if ( StringUtils.isBlank( timestampFormat ) )
{
timestampFormat = "yyyy-MM-dd HH:mm:ss";
}
timestamp = new SimpleDateFormat( timestampFormat );
try
{
writer = new PrintWriter( new FileWriter( logFile ) );
log( "Logging Initialized." );
}
catch ( IOException e )
{
throw new InitializationException( "Unable to initialize log file writer: " + logFile.getAbsolutePath(), e );
}
}
}

View File

@ -0,0 +1,198 @@
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.apache.maven.archiva.configuration.Configuration;
import org.apache.maven.archiva.configuration.ConfigurationStore;
import org.apache.maven.archiva.configuration.ConfigurationStoreException;
import org.apache.maven.archiva.configuration.ConfiguredRepositoryFactory;
import org.apache.maven.archiva.configuration.ProxiedRepositoryConfiguration;
import org.apache.maven.archiva.configuration.Proxy;
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
import org.apache.maven.archiva.proxy.ProxyException;
import org.apache.maven.archiva.proxy.ProxyRequestHandler;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.codehaus.plexus.webdav.AbstractDavServerComponent;
import org.codehaus.plexus.webdav.DavServerComponent;
import org.codehaus.plexus.webdav.DavServerException;
import org.codehaus.plexus.webdav.servlet.DavServerRequest;
import org.codehaus.plexus.webdav.util.WebdavMethodUtil;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
/**
* ProxiedDavServer
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*
* @plexus.component role="org.codehaus.plexus.webdav.DavServerComponent"
* role-hint="proxied"
* instantiation-strategy="per-lookup"
*/
public class ProxiedDavServer
extends AbstractDavServerComponent
{
/**
* @plexus.requirement role-hint="simple"
*/
private DavServerComponent davServer;
/**
* @plexus.requirement
*/
private ConfigurationStore configurationStore;
/**
* @plexus.requirement role="org.apache.maven.archiva.proxy.ProxyRequestHandler"
* @todo seems to be a bug in qdox that the role above is required
*/
private ProxyRequestHandler proxyRequestHandler;
/**
* @plexus.requirement
*/
private ConfiguredRepositoryFactory repositoryFactory;
private RepositoryConfiguration repositoryConfiguration;
private ArtifactRepository managedRepository;
private List/*<ArtifactRepository>*/ proxiedRepositories;
private ProxyInfo wagonProxy;
public String getPrefix()
{
return davServer.getPrefix();
}
public File getRootDirectory()
{
return davServer.getRootDirectory();
}
public void setPrefix( String prefix )
{
davServer.setPrefix( prefix );
}
public void setRootDirectory( File rootDirectory )
{
davServer.setRootDirectory( rootDirectory );
}
public void init( ServletConfig servletConfig )
throws DavServerException
{
davServer.init( servletConfig );
proxiedRepositories = new ArrayList();
try
{
Configuration config = configurationStore.getConfigurationFromStore();
wagonProxy = createWagonProxy( config.getProxy() );
repositoryConfiguration = config.getRepositoryByUrlName( getPrefix() );
managedRepository = repositoryFactory.createRepository( repositoryConfiguration );
for ( Iterator i = config.getProxiedRepositories().iterator(); i.hasNext(); )
{
ProxiedRepositoryConfiguration proxiedRepoConfig = (ProxiedRepositoryConfiguration) i.next();
if ( proxiedRepoConfig.getManagedRepository().equals( repositoryConfiguration.getId() ) )
{
proxiedRepositories.add( repositoryFactory.createProxiedRepository( proxiedRepoConfig ) );
}
}
}
catch ( ConfigurationStoreException e )
{
throw new DavServerException( "Unable to obtain configuration.", e );
}
}
public void process( DavServerRequest request, HttpServletResponse response )
throws DavServerException, ServletException, IOException
{
if ( WebdavMethodUtil.isReadMethod( request.getRequest().getMethod() ) )
{
if ( !hasResource( request.getLogicalResource() ) )
{
fetchContentFromProxies( request );
}
}
davServer.process( request, response );
}
private void fetchContentFromProxies( DavServerRequest request )
throws ServletException
{
try
{
proxyRequestHandler.get( request.getLogicalResource(), this.proxiedRepositories, this.managedRepository,
this.wagonProxy );
}
catch ( ResourceDoesNotExistException e )
{
throw new ServletException( "Unable to fetch resource, it does not exist.", e );
}
catch ( ProxyException e )
{
throw new ServletException( "Unable to fetch resource.", e );
}
}
private ProxyInfo createWagonProxy( Proxy proxy )
{
ProxyInfo proxyInfo = null;
if ( proxy != null && StringUtils.isNotEmpty( proxy.getHost() ) )
{
proxyInfo = new ProxyInfo();
proxyInfo.setHost( proxy.getHost() );
proxyInfo.setPort( proxy.getPort() );
proxyInfo.setUserName( proxy.getUsername() );
proxyInfo.setPassword( proxy.getPassword() );
proxyInfo.setNonProxyHosts( proxy.getNonProxyHosts() );
proxyInfo.setType( proxy.getProtocol() );
}
return proxyInfo;
}
public RepositoryConfiguration getRepositoryConfiguration()
{
return repositoryConfiguration;
}
}

View File

@ -0,0 +1,234 @@
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.maven.archiva.configuration.Configuration;
import org.apache.maven.archiva.configuration.ConfigurationChangeException;
import org.apache.maven.archiva.configuration.ConfigurationChangeListener;
import org.apache.maven.archiva.configuration.ConfigurationStore;
import org.apache.maven.archiva.configuration.ConfigurationStoreException;
import org.apache.maven.archiva.configuration.InvalidConfigurationException;
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
import org.apache.maven.archiva.security.ArchivaRoleConstants;
import org.codehaus.plexus.security.authentication.AuthenticationException;
import org.codehaus.plexus.security.authentication.AuthenticationResult;
import org.codehaus.plexus.security.authorization.AuthorizationException;
import org.codehaus.plexus.security.authorization.AuthorizationResult;
import org.codehaus.plexus.security.policy.AccountLockedException;
import org.codehaus.plexus.security.policy.MustChangePasswordException;
import org.codehaus.plexus.security.system.SecuritySession;
import org.codehaus.plexus.security.system.SecuritySystem;
import org.codehaus.plexus.security.ui.web.filter.authentication.HttpAuthenticator;
import org.codehaus.plexus.webdav.DavServerComponent;
import org.codehaus.plexus.webdav.DavServerException;
import org.codehaus.plexus.webdav.servlet.DavServerRequest;
import org.codehaus.plexus.webdav.servlet.multiplexed.MultiplexedWebDavServlet;
import org.codehaus.plexus.webdav.util.WebdavMethodUtil;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* RepositoryServlet
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class RepositoryServlet
extends MultiplexedWebDavServlet
implements ConfigurationChangeListener
{
/**
* @plexus.requirement
*/
private SecuritySystem securitySystem;
/**
* @plexus.requirement role-hint="basic"
*/
private HttpAuthenticator httpAuth;
/**
* @plexus.requirement
*/
private AuditLog audit;
private Configuration config;
public void initComponents()
throws ServletException
{
super.initComponents();
ConfigurationStore configurationStore;
configurationStore = (ConfigurationStore) lookup( ConfigurationStore.ROLE );
securitySystem = (SecuritySystem) lookup( SecuritySystem.ROLE );
httpAuth = (HttpAuthenticator) lookup( HttpAuthenticator.ROLE, "basic" );
audit = (AuditLog) lookup( AuditLog.ROLE );
try
{
config = configurationStore.getConfigurationFromStore();
configurationStore.addChangeListener( this );
}
catch ( ConfigurationStoreException e )
{
throw new ServletException( "Unable to obtain configuration.", e );
}
}
public void initServers( ServletConfig servletConfig )
throws DavServerException
{
List repositories = config.getRepositories();
Iterator itrepos = repositories.iterator();
while ( itrepos.hasNext() )
{
RepositoryConfiguration repoConfig = (RepositoryConfiguration) itrepos.next();
DavServerComponent server = createServer( repoConfig.getUrlName(), new File( repoConfig.getDirectory() ),
servletConfig );
server.addListener( audit );
}
}
public RepositoryConfiguration getRepositoryConfiguration( DavServerRequest request )
{
return config.getRepositoryByUrlName( request.getPrefix() );
}
public String getRepositoryName( DavServerRequest request )
{
RepositoryConfiguration repoConfig = getRepositoryConfiguration( request );
if ( repoConfig == null )
{
return "Unknown";
}
return repoConfig.getName();
}
public boolean isAuthenticated( DavServerRequest davRequest, HttpServletResponse response )
throws ServletException, IOException
{
HttpServletRequest request = davRequest.getRequest();
// Authentication Tests.
try
{
AuthenticationResult result = httpAuth.getAuthenticationResult( request, response );
if ( ( result != null ) && !result.isAuthenticated() )
{
// Must Authenticate.
httpAuth.challenge( request, response, "Repository " + getRepositoryName( davRequest ),
new AuthenticationException( "User Credentials Invalid" ) );
return false;
}
}
catch ( AuthenticationException e )
{
log( "Fatal Http Authentication Error.", e );
throw new ServletException( "Fatal Http Authentication Error.", e );
}
catch ( AccountLockedException e )
{
httpAuth.challenge( request, response, "Repository " + getRepositoryName( davRequest ),
new AuthenticationException( "User account is locked" ) );
}
catch ( MustChangePasswordException e )
{
httpAuth.challenge( request, response, "Repository " + getRepositoryName( davRequest ),
new AuthenticationException( "You must change your password." ) );
}
return true;
}
public boolean isAuthorized( DavServerRequest davRequest, HttpServletResponse response )
throws ServletException, IOException
{
// Authorization Tests.
HttpServletRequest request = davRequest.getRequest();
boolean isWriteRequest = WebdavMethodUtil.isWriteMethod( request.getMethod() );
SecuritySession securitySession = httpAuth.getSecuritySession();
try
{
String permission = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS;
if ( isWriteRequest )
{
permission = ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD;
}
AuthorizationResult authzResult = securitySystem.authorize( securitySession, permission,
getRepositoryConfiguration( davRequest )
.getId() );
if ( !authzResult.isAuthorized() )
{
if ( authzResult.getException() != null )
{
log( "Authorization Denied [ip=" + request.getRemoteAddr() + ",isWriteRequest=" + isWriteRequest
+ ",permission=" + permission + "] : " + authzResult.getException().getMessage() );
}
// Issue HTTP Challenge.
httpAuth.challenge( request, response, "Repository " + getRepositoryName( davRequest ),
new AuthenticationException( "Authorization Denied." ) );
return false;
}
}
catch ( AuthorizationException e )
{
throw new ServletException( "Fatal Authorization Subsystem Error." );
}
return true;
}
public void notifyOfConfigurationChange( Configuration newConfiguration )
throws InvalidConfigurationException, ConfigurationChangeException
{
config = newConfiguration;
getDavManager().removeAllServers();
try
{
initServers( getServletConfig() );
}
catch ( DavServerException e )
{
throw new ConfigurationChangeException( "Unable to process configuration change.", e );
}
}
}

View File

@ -1,67 +0,0 @@
package org.apache.maven.archiva.web.servlet;
/*
* 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.codehaus.plexus.logging.AbstractLogEnabled;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
/**
* AbstractPlexusServlet
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public abstract class AbstractPlexusServlet
extends AbstractLogEnabled
implements PlexusServlet
{
private ServletConfig servletConfig;
private ServletContext servletContext;
public ServletConfig getServletConfig()
{
return servletConfig;
}
public ServletContext getServletContext()
{
return servletContext;
}
public void servletDestroy()
{
// Do Nothing Here.
}
public void setServletConfig( ServletConfig config )
throws ServletException
{
servletConfig = config;
}
public void setServletContext( ServletContext servletContext )
{
this.servletContext = servletContext;
}
}

View File

@ -1,131 +0,0 @@
package org.apache.maven.archiva.web.servlet;
/*
* 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.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.xwork.PlexusLifecycleListener;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* PlexusComponentServlet - This is merely a servlet facade against a loaded
* plexus component called foo
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class PlexusComponentServlet
implements Servlet
{
private PlexusContainer plexus;
private PlexusServlet servletProxy;
private boolean isInitialized = false;
public void destroy()
{
if ( isInitialized )
{
servletProxy.servletDestroy();
}
}
public ServletConfig getServletConfig()
{
if ( isInitialized )
{
return servletProxy.getServletConfig();
}
return null;
}
public String getServletInfo()
{
if ( isInitialized )
{
return servletProxy.getServletInfo();
}
return null;
}
public void init( ServletConfig config )
throws ServletException
{
isInitialized = false;
plexus = (PlexusContainer) config.getServletContext().getAttribute( PlexusLifecycleListener.KEY );
String componentKey = config.getInitParameter( "key" );
try
{
Object obj = plexus.lookup( PlexusServlet.ROLE, componentKey );
if ( !( obj instanceof PlexusServlet ) )
{
throw new ServletException(
"Class " + obj.getClass().getName() + " does not implement " + PlexusServlet.class.getName() );
}
servletProxy = (PlexusServlet) obj;
servletProxy.setServletConfig( config );
isInitialized = true;
}
catch ( ComponentLookupException e )
{
throw new ServletException( "Unable to initialize PlexusComponentServlet.", e );
}
}
public void service( ServletRequest req, ServletResponse res )
throws ServletException, IOException
{
if ( !isInitialized )
{
throw new ServletException( "PlexusComponentServlet is not initialized correctly!" );
}
if ( !( req instanceof HttpServletRequest ) )
{
throw new ServletException( "PlexusComponentServlet can only handle HttpServletRequests." );
}
if ( !( res instanceof HttpServletResponse ) )
{
throw new ServletException( "PlexusComponentServlet can only handle HttpServletResponse." );
}
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
servletProxy.servletRequest( request, response );
}
}

View File

@ -1,49 +0,0 @@
package org.apache.maven.archiva.web.servlet;
/*
* 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 javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* PlexusServlet - a component that handles HTTP Servlet Requests for {@link PlexusComponentServlet}.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public interface PlexusServlet
{
public static final String ROLE = PlexusServlet.class.getName();
public void servletDestroy();
public ServletConfig getServletConfig();
public String getServletInfo();
public void setServletConfig( ServletConfig config )
throws ServletException;
public void servletRequest( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException;
}

View File

@ -1,303 +0,0 @@
package org.apache.maven.archiva.web.servlet.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 it.could.webdav.DAVTransaction;
import it.could.webdav.DAVUtilities;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.configuration.Configuration;
import org.apache.maven.archiva.configuration.ConfigurationStore;
import org.apache.maven.archiva.configuration.ConfigurationStoreException;
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
import org.apache.maven.archiva.security.ArchivaRoleConstants;
import org.apache.maven.archiva.web.servlet.AbstractPlexusServlet;
import org.codehaus.plexus.security.authentication.AuthenticationException;
import org.codehaus.plexus.security.authentication.AuthenticationResult;
import org.codehaus.plexus.security.authorization.AuthorizationException;
import org.codehaus.plexus.security.authorization.AuthorizationResult;
import org.codehaus.plexus.security.policy.AccountLockedException;
import org.codehaus.plexus.security.policy.MustChangePasswordException;
import org.codehaus.plexus.security.system.SecuritySession;
import org.codehaus.plexus.security.system.SecuritySystem;
import org.codehaus.plexus.security.ui.web.filter.authentication.HttpAuthenticator;
import org.codehaus.plexus.util.FileUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* RepositoryAccess - access read/write to the repository.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
* @plexus.component role="org.apache.maven.archiva.web.servlet.PlexusServlet"
* role-hint="repositoryAccess"
* @todo CACHE REPOSITORY LIST
*/
public class RepositoryAccess
extends AbstractPlexusServlet
{
/**
* @plexus.requirement
*/
private ConfigurationStore configurationStore;
/**
* @plexus.requirement
*/
private SecuritySystem securitySystem;
/**
* @plexus.requirement role-hint="basic"
*/
private HttpAuthenticator httpAuth;
/**
* List of request methods that fall into the category of 'access' or 'read' of a repository.
* All other method requests are to be considered 'write' or 'upload' requests.
*/
private static final List ACCESS_METHODS;
static
{
ACCESS_METHODS = new ArrayList();
ACCESS_METHODS.add( "HEAD" );
ACCESS_METHODS.add( "GET" );
ACCESS_METHODS.add( "PROPFIND" );
ACCESS_METHODS.add( "OPTIONS" );
ACCESS_METHODS.add( "REPORT" );
}
public class RequestPath
{
String repoName;
String path;
}
private Map davRepositoryMap = new HashMap();
public String getServletInfo()
{
// TODO: We could produce information about # of repositories being tracked, etc...
return "Archiva Repository Access Servlet";
}
public void servletRequest( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException
{
Configuration config;
try
{
config = configurationStore.getConfigurationFromStore();
}
catch ( ConfigurationStoreException e )
{
// TODO: should be a more pretty error to user. ;-)
// TODO: can we determine if the incoming request is a real user, or just maven-wagon?
throw new ServletException( "Unable to obtain configuration.", e );
}
RequestPath reqpath = getRepositoryPath( request.getPathInfo() );
if ( reqpath == null )
{
routeToErrorPage( response, "Invalid Repository URL." );
return;
}
RepositoryConfiguration repoconfig = config.getRepositoryByUrlName( reqpath.repoName );
if ( repoconfig == null )
{
routeToErrorPage( response, "Invalid Repository URL." );
return;
}
// Authentication Tests.
try
{
AuthenticationResult result = httpAuth.getAuthenticationResult( request, response );
if ( ( result != null ) && !result.isAuthenticated() )
{
// Must Authenticate.
httpAuth.challenge( request, response, "Repository " + repoconfig.getName(),
new AuthenticationException( "User Credentials Invalid" ) );
return;
}
}
catch ( AuthenticationException e )
{
getLogger().error( "Fatal Http Authentication Error.", e );
throw new ServletException( "Fatal Http Authentication Error.", e );
}
catch ( AccountLockedException e )
{
httpAuth.challenge( request, response, "Repository " + repoconfig.getName(),
new AuthenticationException( "User account is locked" ) );
}
catch ( MustChangePasswordException e )
{
httpAuth.challenge( request, response, "Repository " + repoconfig.getName(), new AuthenticationException(
"You must change your password before you can attempt this again." ) );
}
// Authorization Tests.
boolean isWriteRequest = !ACCESS_METHODS.contains( request.getMethod().toUpperCase() );
SecuritySession securitySession = httpAuth.getSecuritySession();
try
{
String permission = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS;
if ( isWriteRequest )
{
permission = ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD;
}
AuthorizationResult authzResult = securitySystem
.authorize( securitySession, permission, repoconfig.getId() );
if ( !authzResult.isAuthorized() )
{
if ( authzResult.getException() != null )
{
getLogger().warn( "Authorization Denied [ip=" + request.getRemoteAddr() + ",isWriteRequest=" +
isWriteRequest + ",permission=" + permission + "] : " +
authzResult.getException().getMessage() );
}
// Issue HTTP Challenge.
httpAuth.challenge( request, response, "Repository " + repoconfig.getName(),
new AuthenticationException( "Authorization Denied." ) );
return;
}
}
catch ( AuthorizationException e )
{
throw new ServletException( "Fatal Authorization Subsystem Error." );
}
// Allow DAV To Handle Request.
RepositoryMapping repo = getRepositoryMapping( repoconfig );
String serverInfo = "";
if ( getServletContext() != null )
{
if ( StringUtils.isNotEmpty( getServletContext().getServerInfo() ) )
{
serverInfo = getServletContext().getServerInfo();
}
}
response.setHeader( "Server", serverInfo + " Archiva : " + DAVUtilities.SERVLET_SIGNATURE );
DAVTransaction transaction =
new DAVTransaction( new RepositoryRequest( request, repoconfig.getUrlName() ), response );
try
{
repo.getDavProcessor().process( transaction );
}
catch ( RuntimeException exception )
{
final String header = request.getMethod() + ' ' + request.getRequestURI() + ' ' + request.getProtocol();
getLogger().error( "Error processing: " + header );
getLogger().error( "Exception processing DAV transaction", exception );
throw exception;
}
}
public RepositoryMapping getRepositoryMapping( RepositoryConfiguration repoconfig )
throws IOException
{
RepositoryMapping repo = (RepositoryMapping) davRepositoryMap.get( repoconfig.getDirectory() );
if ( repo == null )
{
repo = new RepositoryMapping( repoconfig );
davRepositoryMap.put( repoconfig.getDirectory(), repo );
}
return repo;
}
public RequestPath getRepositoryPath( String requestPathInfo )
{
if ( StringUtils.isEmpty( requestPathInfo ) || StringUtils.equals( "/", requestPathInfo ) )
{
// Got root url. Can't do anything with this.
return null;
}
RequestPath ret = new RequestPath();
// Find the first 'path' of the pathInfo.
// Default: "/pathid" -> "pathid"
ret.repoName = requestPathInfo.substring( 1 );
ret.path = "/";
// Find first element, if slash exists.
int slash = requestPathInfo.indexOf( '/', 1 );
if ( slash > 0 )
{
// Filtered: "/central/org/apache/maven/" -> "central"
ret.repoName = requestPathInfo.substring( 1, slash );
String repoPath = requestPathInfo.substring( slash );
if ( repoPath.endsWith( "/.." ) )
{
repoPath += "/";
}
String path = FileUtils.normalize( repoPath );
if ( path == null )
{
ret.path = "/";
}
else
{
ret.path = path;
}
}
return ret;
}
public void routeToErrorPage( HttpServletResponse response, String message )
throws IOException
{
response.resetBuffer();
/* Since the primary user of this servlet will be Maven Wagon.
* Always return 404 on error to force the wagon to stop retrying.
*/
response.sendError( HttpServletResponse.SC_NOT_FOUND, message );
}
}

View File

@ -1,51 +0,0 @@
package org.apache.maven.archiva.web.servlet.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.
*/
/**
* RepositoryException
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class RepositoryException
extends Exception
{
public RepositoryException()
{
super();
}
public RepositoryException( String message, Throwable cause )
{
super( message, cause );
}
public RepositoryException( String message )
{
super( message );
}
public RepositoryException( Throwable cause )
{
super( cause );
}
}

View File

@ -1,92 +0,0 @@
package org.apache.maven.archiva.web.servlet.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 it.could.webdav.DAVListener;
import it.could.webdav.DAVProcessor;
import it.could.webdav.DAVRepository;
import it.could.webdav.DAVResource;
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
import org.codehaus.plexus.logging.Logger;
import java.io.File;
import java.io.IOException;
/**
* RepositoryMapping
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class RepositoryMapping
implements DAVListener
{
private RepositoryConfiguration repositoryConfiguration;
private DAVProcessor davProcessor;
private DAVRepository davRepository;
private Logger logger;
public RepositoryMapping( RepositoryConfiguration repoConfig )
throws IOException
{
this.repositoryConfiguration = repoConfig;
File repoDir = new File( repositoryConfiguration.getDirectory() );
this.davRepository = new DAVRepository( repoDir );
this.davProcessor = new DAVProcessor( this.davRepository );
this.davRepository.addListener( this );
}
public DAVProcessor getDavProcessor()
{
return davProcessor;
}
/**
* <p>Receive notification of an event occurred in a specific
* {@link DAVRepository}.</p>
*/
public void notify( DAVResource resource, int event )
{
String message = "Unknown event";
switch ( event )
{
case DAVListener.COLLECTION_CREATED:
message = "Collection created";
break;
case DAVListener.COLLECTION_REMOVED:
message = "Collection removed";
break;
case DAVListener.RESOURCE_CREATED:
message = "Resource created";
break;
case DAVListener.RESOURCE_REMOVED:
message = "Resource removed";
break;
case DAVListener.RESOURCE_MODIFIED:
message = "Resource modified";
break;
}
logger.info(
message + ": " + this.repositoryConfiguration.getId() + " : \"" + resource.getRelativePath() + "\"" );
}
}

View File

@ -1,80 +0,0 @@
package org.apache.maven.archiva.web.servlet.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 it.could.webdav.DAVTransaction;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* RepositoryRequest
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class RepositoryRequest
extends HttpServletRequestWrapper
{
private String repoUrlName;
public RepositoryRequest( HttpServletRequest request, String repoUrlName )
{
super( request );
this.repoUrlName = "";
if ( repoUrlName != null )
{
this.repoUrlName = repoUrlName;
}
}
/**
* Adjust the path info value to remove reference to repoUrlName.
* This is done to satisfy the needs of {@link DAVTransaction}
*/
public String getPathInfo()
{
String pathInfo = super.getPathInfo();
if ( pathInfo == null )
{
return "";
}
if ( ( pathInfo.length() > 1 ) && ( pathInfo.charAt( 0 ) == '/' ) )
{
pathInfo = pathInfo.substring( 1 );
}
if ( pathInfo.startsWith( repoUrlName ) )
{
pathInfo = pathInfo.substring( repoUrlName.length() );
}
return pathInfo;
}
public String getServletPath()
{
return super.getServletPath() + "/" + this.repoUrlName;
}
}

View File

@ -0,0 +1,148 @@
package org.apache.maven.archiva.web.tags;
/*
* 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 com.opensymphony.webwork.WebWorkException;
import com.opensymphony.webwork.components.Component;
import com.opensymphony.xwork.util.OgnlValueStack;
import java.io.IOException;
import java.io.Writer;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* GroupIdLink
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class GroupIdLink
extends Component
{
private static final String ACTION = "browseGroup";
private static final String NAMESPACE = "/";
private static final boolean includeContext = false;
private static final boolean encode = true;
private static final String method = null;
private HttpServletRequest req;
private HttpServletResponse res;
private String groupId;
private boolean includeTop = false;
public GroupIdLink( OgnlValueStack stack, HttpServletRequest req, HttpServletResponse res )
{
super( stack );
this.req = req;
this.res = res;
}
public boolean end( Writer writer, String body )
{
StringBuffer sb = new StringBuffer();
sb.append( "<span class=\"groupId\">" );
if ( includeTop )
{
sb.append( "<a href=\"" );
sb.append( determineBrowseActionUrl() );
sb.append( "\">[top]</a> / " ); // TODO: i18n
}
StringTokenizer tok = new StringTokenizer( groupId, "." );
String cumulativeGroup = null;
while ( tok.hasMoreTokens() )
{
String token = tok.nextToken();
if ( cumulativeGroup == null )
{
cumulativeGroup = token;
}
else
{
cumulativeGroup += "." + token;
}
sb.append( "<a href=\"" );
sb.append( determineBrowseGroupActionUrl( cumulativeGroup ) );
sb.append( "\">" ).append( token ).append( "</a> / " );
}
sb.append( "</span>" );
try
{
writer.write( sb.toString() );
}
catch ( IOException e )
{
throw new WebWorkException( "IOError: " + e.getMessage(), e );
}
return super.end( writer, body );
}
private String determineBrowseActionUrl()
{
return determineActionURL( "browse", NAMESPACE, method, req, res, parameters, req.getScheme(), includeContext,
encode );
}
private String determineBrowseGroupActionUrl( String gid )
{
parameters.put( "groupId", gid );
return determineActionURL( ACTION, NAMESPACE, method, req, res, parameters, req.getScheme(), includeContext,
encode );
}
public String getGroupId()
{
return groupId;
}
public void setGroupId( String groupId )
{
this.groupId = groupId;
}
public boolean isIncludeTop()
{
return includeTop;
}
public void setIncludeTop( boolean includeTop )
{
this.includeTop = includeTop;
}
}

View File

@ -0,0 +1,100 @@
package org.apache.maven.archiva.web.tags;
/*
* 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 com.opensymphony.webwork.views.jsp.TagUtils;
import org.apache.taglibs.standard.tag.common.core.NullAttributeException;
import org.apache.taglibs.standard.tag.el.core.ExpressionUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
/**
* GroupIdLink
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class GroupIdLinkTag
extends TagSupport
{
private String var_; // stores EL-based property
private Object var; // stores the evaluated object.
private boolean includeTop = false;
public void release()
{
var_ = null;
var = null;
includeTop = false;
super.release();
}
public int doEndTag()
throws JspException
{
evaluateExpressions();
GroupIdLink gidlink = new GroupIdLink( TagUtils.getStack( pageContext ), (HttpServletRequest) pageContext
.getRequest(), (HttpServletResponse) pageContext.getResponse() );
gidlink.setGroupId( var.toString() );
gidlink.setIncludeTop( includeTop );
gidlink.end( pageContext.getOut(), "" );
return super.doEndTag();
}
private void evaluateExpressions()
throws JspException
{
try
{
var = ExpressionUtil.evalNotNull( "groupIdLink", "var", var_, String.class, this, pageContext );
}
catch ( NullAttributeException e )
{
log( "groupIdLink var is null!", e );
var = "";
}
}
public void setVar( String value )
{
this.var_ = value;
}
private void log( String msg, Throwable t )
{
pageContext.getServletContext().log( msg, t );
}
public void setIncludeTop( boolean includeTop )
{
this.includeTop = includeTop;
}
}

View File

@ -40,6 +40,16 @@
<jndiSessionName>java:comp/env/mail/Session</jndiSessionName>
</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.jdo.JdoFactory</role>
@ -130,36 +140,9 @@
</property>
</properties>
</appender>
<appender>
<id>audit</id>
<threshold>DEBUG</threshold>
<type>org.apache.log4j.DailyRollingFileAppender</type>
<conversion-pattern>%-4r [%t] %-5p %c %x - %m%n</conversion-pattern>
<properties>
<property>
<name>file</name>
<value>${appserver.base}/logs/audit.log</value>
</property>
<property>
<name>append</name>
<value>true</value>
</property>
<property>
<name>datePattern</name>
<value>'.'yyyy-MM-dd</value>
</property>
</properties>
</appender>
</appenders>
<levels>
<level>
<hierarchy>org.apache.maven.archiva.web.servlet.repository.RepositoryMapping</hierarchy>
<level>DEBUG, audit</level>
</level>
<!-- Help identify bugs during testing -->
<level>
<hierarchy>org.apache.maven</hierarchy>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>2.2.3</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>Archiva Taglib</short-name>
<uri>http://maven.apache.org/archiva</uri>
<display-name>Archiva Taglib</display-name>
<description><![CDATA[Archiva JSP Taglib]]></description>
<tag>
<name>groupIdLink</name>
<tag-class>org.apache.maven.archiva.web.tags.GroupIdLinkTag</tag-class>
<body-content>empty</body-content>
<description><![CDATA[Render a groupId as a set of Links]]></description>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[The GroupID String]]></description>
</attribute>
<attribute>
<name>includeTop</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<description><![CDATA[Boolean indicating if 'top' link should be created or not.]]></description>
</attribute>
</tag>
</taglib>

View File

@ -181,16 +181,6 @@
<result>/WEB-INF/jsp/showArtifact.jsp</result>
</action>
<action name="proxy" class="proxyAction">
<result type="stream">
<param name="contentType">${contentType}</param>
<param name="contentDisposition">filename="${filename}"</param>
<param name="inputName">artifactStream</param>
<param name="bufferSize">1024</param>
<param name="contentLength">${contentLength}</param>
</result>
<result name="notFound" type="httpheader">404</result>
</action>
</package>
<package name="components" namespace="/components" extends="default">

View File

@ -79,7 +79,7 @@
</tr>
<tr>
<th>WebDAV URL</th>
<td><a href="${urlbase}${repository.urlName}">${urlbase}${repository.urlName}</a></td>
<td><a href="${urlbase}${repository.urlName}/">${urlbase}${repository.urlName}/</a></td>
</tr>
<tr>
<th>Type</th>
@ -121,7 +121,7 @@
&lt;repository>
&lt;id>${repository.id}&lt;/id>
&lt;name>${repository.name}&lt;/name>
&lt;url>${urlbase}${repository.urlName}&lt;/url><c:if test="${repository.layout != 'default'}">
&lt;url>${urlbase}${repository.urlName}/&lt;/url><c:if test="${repository.layout != 'default'}">
&lt;layout>${repository.layout}&lt;/layout></c:if>
&lt;releases>
&lt;enabled>${repository.includeSnapshots ? 'false' : 'true'}&lt;/enabled>

View File

@ -19,6 +19,7 @@
<%@ taglib prefix="ww" uri="/webwork" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="archiva" uri="http://maven.apache.org/archiva" %>
<html>
<head>
@ -33,23 +34,7 @@
<div id="contentArea">
<div id="nameColumn">
<p>
<c:set var="cumulativeGroup" value=""/>
<c:forTokens items="${groupId}" delims="./" var="part">
<c:choose>
<c:when test="${empty(cumulativeGroup)}">
<c:set var="cumulativeGroup" value="${part}"/>
</c:when>
<c:otherwise>
<c:set var="cumulativeGroup" value="${cumulativeGroup}.${part}"/>
</c:otherwise>
</c:choose>
<c:set var="url">
<ww:url action="browseGroup" namespace="/">
<ww:param name="groupId" value="%{'${cumulativeGroup}'}"/>
</ww:url>
</c:set>
<a href="${url}">${part}</a> /
</c:forTokens>
<archiva:groupIdLink var="${groupId}" includeTop="true" />
<strong>${artifactId}</strong>
</p>

View File

@ -19,6 +19,7 @@
<%@ taglib prefix="ww" uri="/webwork" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="archiva" uri="http://maven.apache.org/archiva" %>
<html>
<head>
@ -33,30 +34,7 @@
<div id="contentArea">
<div id="nameColumn">
<p>
<c:set var="cumulativeGroup" value=""/>
<c:forTokens items="${groupId}" delims="." var="part" varStatus="status">
<c:choose>
<c:when test="${empty(cumulativeGroup)}">
<c:set var="cumulativeGroup" value="${part}"/>
</c:when>
<c:otherwise>
<c:set var="cumulativeGroup" value="${cumulativeGroup}.${part}"/>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${status.last}">
<strong>${part}</strong>
</c:when>
<c:otherwise>
<c:set var="url">
<ww:url action="browseGroup" namespace="/">
<ww:param name="groupId" value="%{'${cumulativeGroup}'}"/>
</ww:url>
</c:set>
<a href="${url}">${part}</a> /
</c:otherwise>
</c:choose>
</c:forTokens>
<archiva:groupIdLink var="${groupId}" includeTop="true" />
</p>
<ww:set name="groups" value="groups"/>

View File

@ -19,25 +19,11 @@
<%@ taglib prefix="ww" uri="/webwork" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="archiva" uri="http://maven.apache.org/archiva" %>
<p>
<c:set var="cumulativeGroup" value=""/>
<c:forTokens items="${model.groupId}" delims="." var="part">
<c:choose>
<c:when test="${empty(cumulativeGroup)}">
<c:set var="cumulativeGroup" value="${part}"/>
</c:when>
<c:otherwise>
<c:set var="cumulativeGroup" value="${cumulativeGroup}.${part}"/>
</c:otherwise>
</c:choose>
<c:set var="url">
<ww:url action="browseGroup" namespace="/">
<ww:param name="groupId" value="%{'${cumulativeGroup}'}"/>
</ww:url>
</c:set>
<a href="${url}">${part}</a> /
</c:forTokens>
<archiva:groupIdLink var="${model.groupId}" includeTop="true" />
<c:set var="url">
<ww:url action="browseArtifact" namespace="/">
<ww:param name="groupId" value="%{'${model.groupId}'}"/>

View File

@ -19,6 +19,7 @@
<%@ taglib prefix="ww" uri="/webwork" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="archiva" uri="http://maven.apache.org/archiva" %>
<%@ attribute name="groupId" required="true" %>
<%@ attribute name="artifactId" %>
<%@ attribute name="version" %>
@ -27,26 +28,8 @@
<%@ attribute name="versions" type="java.util.List" %>
<span class="artifact-link">
<c:set var="cumulativeGroup" value=""/>
<c:forTokens items="${groupId}" delims="." var="part" varStatus="i">
<c:choose>
<c:when test="${empty(cumulativeGroup)}">
<c:set var="cumulativeGroup" value="${part}"/>
</c:when>
<c:otherwise>
<c:set var="cumulativeGroup" value="${cumulativeGroup}.${part}"/>
</c:otherwise>
</c:choose>
<c:set var="url">
<ww:url action="browseGroup" namespace="/">
<ww:param name="groupId" value="%{'${cumulativeGroup}'}"/>
</ww:url>
</c:set>
<a href="${url}">${part}</a>
<c:if test="${!i.last}">
/
</c:if>
</c:forTokens>
<archiva:groupIdLink var="${model.groupId}" includeTop="true" />
<c:if test="${!empty(artifactId)}">
<c:set var="url">
<ww:url action="browseArtifact" namespace="/">

View File

@ -60,16 +60,12 @@
</listener>
<servlet>
<servlet-name>RepositoryAccessServlet</servlet-name>
<servlet-class>org.apache.maven.archiva.web.servlet.PlexusComponentServlet</servlet-class>
<init-param>
<param-name>key</param-name>
<param-value>repositoryAccess</param-value>
</init-param>
<servlet-name>RepositoryServlet</servlet-name>
<servlet-class>org.apache.maven.archiva.web.repository.RepositoryServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RepositoryAccessServlet</servlet-name>
<servlet-name>RepositoryServlet</servlet-name>
<url-pattern>/repository/*</url-pattern>
</servlet-mapping>

View File

@ -1,83 +0,0 @@
package org.apache.maven.archiva.web.servlet.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.maven.archiva.web.servlet.PlexusServlet;
import org.codehaus.plexus.PlexusTestCase;
/**
* RepositoryAccessTest
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class RepositoryAccessTest
extends PlexusTestCase
{
private void assertRequestPath( String expectedId, String expectedPath, String rawpath )
throws Exception
{
RepositoryAccess repoaccess = (RepositoryAccess) lookup( PlexusServlet.ROLE, "repositoryAccess" );
RepositoryAccess.RequestPath requestPath = repoaccess.getRepositoryPath( rawpath );
if ( expectedId == null )
{
// special case, should be null.
assertNull( requestPath );
return;
}
assertNotNull( requestPath );
assertEquals( expectedId, requestPath.repoName );
assertEquals( expectedPath, requestPath.path );
}
public void testGetRepoPath()
throws Exception
{
// Test for paths with no id.
assertRequestPath( null, null, null );
assertRequestPath( null, null, "" );
assertRequestPath( null, null, "/" );
// Test for paths with root browse
assertRequestPath( "central", "/", "/central" );
assertRequestPath( "central", "/", "/central/" );
assertRequestPath( "snapshots", "/", "/snapshots/" );
// Test for paths deep within repository.
assertRequestPath( "central", "/org/apache/maven/", "/central/org/apache/maven/" );
assertRequestPath( "snapshots", "/org/codehaus/mojo", "/snapshots/org/codehaus/mojo" );
assertRequestPath( "central", "/org/apache/maven/archiva/metadata.xml",
"/central/org/apache/maven/archiva/metadata.xml" );
assertRequestPath( "sandbox", "/org/company/experiment/1.0/experiment-1.0.jar.pom",
"/sandbox/org/company/experiment/1.0/experiment-1.0.jar.pom" );
// Test for paths with "/../" nastyness
assertRequestPath( "central", "/", "/central/.." );
assertRequestPath( "central", "/", "/central/../../../" );
assertRequestPath( "central", "/", "/central/org/../../etc/passwd" );
assertRequestPath( "central", "/etc/passwd", "/central//etc/passwd" );
assertRequestPath( "central", "/org/codehaus/mojo", "/central/org/apache/../codehaus/mojo" );
}
}

40
pom.xml
View File

@ -154,15 +154,44 @@
<artifactId>maven-app-configuration-web</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--
Rejected Plexus Container / Component Versions:
1.0-alpha-11
2007-01-17 11:40:40.371::WARN: Failed startup of context org.mortbay.jetty.webapp.WebAppContext@553763
{/,/home/joakim/code/maven/trunks/archiva/archiva-webapp/src/main/webapp}
java.lang.NullPointerException
at org.codehaus.plexus.classworlds.strategy.DefaultStrategy.getResource(DefaultStrategy.java:99)
at org.codehaus.plexus.classworlds.strategy.ForeignStrategy.getResource(ForeignStrategy.java:54)
at org.codehaus.plexus.classworlds.strategy.DefaultStrategy.getResourceAsStream(DefaultStrategy.java:107)
at org.codehaus.plexus.classworlds.realm.ClassRealm.getResourceAsStream(ClassRealm.java:207)
at org.codehaus.plexus.DefaultPlexusContainer.<init>(DefaultPlexusContainer.java:244)
1.0-alpha-12
1.0-alpha-13
1.0-alpha-14
Caused by: org.codehaus.plexus.PlexusContainerException: The specified user configuration
'file:/home/joakim/code/maven/trunks/archiva/archiva-webapp/src/main/webapp/WEB-INF/classes/META-INF/plexus/application.xml' is null.
1.0-alpha-15
The resolution of ${configuration.store.file} is never attempted.
1.0-alpha-16-SNAPSHOT
Incompatible with plexus-xwork-integration
-->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
<version>1.0-alpha-10</version>
<version>1.0-alpha-16-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-api</artifactId>
<version>1.0-alpha-16-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.3</version>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
@ -188,6 +217,12 @@
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>${maven.version}</version>
<exclusions>
<exclusion>
<groupId>plexus</groupId>
<artifactId>plexus-container-default</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
@ -400,6 +435,7 @@
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<source>1.4</source>
<aggregate>true</aggregate>
</configuration>
</plugin>

View File

@ -94,7 +94,7 @@ To deploy Archiva on Plexus
Setting up your Archiva instance
* Goto {{http://localhost:9091/}} if on the embedded Jetty, {{http://localhost:8080/archiva/}} if on Tomcat or {{http://localhost:8080/}} if on Plexus.
* Goto {{http://localhost:9091/}} if on the embedded Jetty, {{http://localhost:8080/archiva/}} if on Tomcat or {{http://localhost:8080/archiva/}} if on Plexus.
* On the first page - setup your administration user. The password requires a numerical character and must not be longer than 8 chars. You'll then need to log in. User 'admin' as the username and the password you've entered.