diff options
36 files changed, 976 insertions, 1542 deletions
diff --git a/archiva-cli/pom.xml b/archiva-cli/pom.xml index bc0f3f369..17019b0bd 100644 --- a/archiva-cli/pom.xml +++ b/archiva-cli/pom.xml @@ -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> diff --git a/archiva-converter/pom.xml b/archiva-converter/pom.xml index 314e25c4b..7eabccb9e 100644 --- a/archiva-converter/pom.xml +++ b/archiva-converter/pom.xml @@ -34,6 +34,10 @@ <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> </dependency> @@ -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> diff --git a/archiva-core/pom.xml b/archiva-core/pom.xml index 0844a86dd..91f0f8eca 100644 --- a/archiva-core/pom.xml +++ b/archiva-core/pom.xml @@ -51,18 +51,28 @@ </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> diff --git a/archiva-core/src/main/java/org/apache/maven/archiva/proxy/DefaultProxyManager.java b/archiva-core/src/main/java/org/apache/maven/archiva/proxy/DefaultProxyManager.java deleted file mode 100644 index 66df019de..000000000 --- a/archiva-core/src/main/java/org/apache/maven/archiva/proxy/DefaultProxyManager.java +++ /dev/null @@ -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" ); - } -} diff --git a/archiva-core/src/main/java/org/apache/maven/archiva/proxy/ProxiedRepositoryGroup.java b/archiva-core/src/main/java/org/apache/maven/archiva/proxy/ProxiedRepositoryGroup.java deleted file mode 100644 index e99f09c25..000000000 --- a/archiva-core/src/main/java/org/apache/maven/archiva/proxy/ProxiedRepositoryGroup.java +++ /dev/null @@ -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; - } -} diff --git a/archiva-core/src/main/java/org/apache/maven/archiva/proxy/ProxyManager.java b/archiva-core/src/main/java/org/apache/maven/archiva/proxy/ProxyManager.java deleted file mode 100644 index 03b3a2032..000000000 --- a/archiva-core/src/main/java/org/apache/maven/archiva/proxy/ProxyManager.java +++ /dev/null @@ -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; -} diff --git a/archiva-plexus-application/pom.xml b/archiva-plexus-application/pom.xml index c60908456..f2ece4426 100644 --- a/archiva-plexus-application/pom.xml +++ b/archiva-plexus-application/pom.xml @@ -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> diff --git a/archiva-plexus-application/src/conf/application.xml b/archiva-plexus-application/src/conf/application.xml index 53ec45b0b..37fcd4e36 100644 --- a/archiva-plexus-application/src/conf/application.xml +++ b/archiva-plexus-application/src/conf/application.xml @@ -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> diff --git a/archiva-plexus-runtime/pom.xml b/archiva-plexus-runtime/pom.xml index 8d03013e7..05f8cc5c5 100644 --- a/archiva-plexus-runtime/pom.xml +++ b/archiva-plexus-runtime/pom.xml @@ -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> diff --git a/archiva-security/pom.xml b/archiva-security/pom.xml index f2bc4443e..78cbd1282 100644 --- a/archiva-security/pom.xml +++ b/archiva-security/pom.xml @@ -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> diff --git a/archiva-webapp/pom.xml b/archiva-webapp/pom.xml index 13d1033d5..d37d0aa77 100644 --- a/archiva-webapp/pom.xml +++ b/archiva-webapp/pom.xml @@ -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> diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ProxyAction.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ProxyAction.java deleted file mode 100644 index f00fae982..000000000 --- a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ProxyAction.java +++ /dev/null @@ -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; - } -} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/AuditLog.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/AuditLog.java new file mode 100644 index 000000000..93568a2ae --- /dev/null +++ b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/AuditLog.java @@ -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 ); + } + } +} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java new file mode 100644 index 000000000..9fda5da30 --- /dev/null +++ b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java @@ -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; + } +} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/RepositoryServlet.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/RepositoryServlet.java new file mode 100644 index 000000000..3f3010f91 --- /dev/null +++ b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/RepositoryServlet.java @@ -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 ); + } + } +} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/AbstractPlexusServlet.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/AbstractPlexusServlet.java deleted file mode 100644 index e483674d2..000000000 --- a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/AbstractPlexusServlet.java +++ /dev/null @@ -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; - } -} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/PlexusComponentServlet.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/PlexusComponentServlet.java deleted file mode 100644 index 609c200a5..000000000 --- a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/PlexusComponentServlet.java +++ /dev/null @@ -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 ); - } -} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/PlexusServlet.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/PlexusServlet.java deleted file mode 100644 index 4a1c7e186..000000000 --- a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/PlexusServlet.java +++ /dev/null @@ -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; -} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryAccess.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryAccess.java deleted file mode 100644 index afe7a04fc..000000000 --- a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryAccess.java +++ /dev/null @@ -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 ); - } -} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryException.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryException.java deleted file mode 100644 index 891d3f6cb..000000000 --- a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryException.java +++ /dev/null @@ -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 ); - } -} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryMapping.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryMapping.java deleted file mode 100644 index a602cc77f..000000000 --- a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryMapping.java +++ /dev/null @@ -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() + "\"" ); - } -} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryRequest.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryRequest.java deleted file mode 100644 index 1e4e25cf2..000000000 --- a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/servlet/repository/RepositoryRequest.java +++ /dev/null @@ -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; - } - -} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/tags/GroupIdLink.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/tags/GroupIdLink.java new file mode 100644 index 000000000..02347c150 --- /dev/null +++ b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/tags/GroupIdLink.java @@ -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; + } + +} diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/tags/GroupIdLinkTag.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/tags/GroupIdLinkTag.java new file mode 100644 index 000000000..449fe9635 --- /dev/null +++ b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/tags/GroupIdLinkTag.java @@ -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; + } +} diff --git a/archiva-webapp/src/main/resources/META-INF/plexus/application.xml b/archiva-webapp/src/main/resources/META-INF/plexus/application.xml index 5ab5e01f5..756ef925c 100644 --- a/archiva-webapp/src/main/resources/META-INF/plexus/application.xml +++ b/archiva-webapp/src/main/resources/META-INF/plexus/application.xml @@ -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> diff --git a/archiva-webapp/src/main/resources/META-INF/taglib.tld b/archiva-webapp/src/main/resources/META-INF/taglib.tld new file mode 100644 index 000000000..4d38c05ee --- /dev/null +++ b/archiva-webapp/src/main/resources/META-INF/taglib.tld @@ -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>
\ No newline at end of file diff --git a/archiva-webapp/src/main/resources/xwork.xml b/archiva-webapp/src/main/resources/xwork.xml index 8484a94b1..96c9bdb21 100644 --- a/archiva-webapp/src/main/resources/xwork.xml +++ b/archiva-webapp/src/main/resources/xwork.xml @@ -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"> diff --git a/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/managedRepositories.jsp b/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/managedRepositories.jsp index 0c51db9b2..d79368bc5 100644 --- a/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/managedRepositories.jsp +++ b/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/managedRepositories.jsp @@ -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 @@ <repository> <id>${repository.id}</id> <name>${repository.name}</name> - <url>${urlbase}${repository.urlName}</url><c:if test="${repository.layout != 'default'}"> + <url>${urlbase}${repository.urlName}/</url><c:if test="${repository.layout != 'default'}"> <layout>${repository.layout}</layout></c:if> <releases> <enabled>${repository.includeSnapshots ? 'false' : 'true'}</enabled> diff --git a/archiva-webapp/src/main/webapp/WEB-INF/jsp/browseArtifact.jsp b/archiva-webapp/src/main/webapp/WEB-INF/jsp/browseArtifact.jsp index de31c5373..3dde3fca8 100644 --- a/archiva-webapp/src/main/webapp/WEB-INF/jsp/browseArtifact.jsp +++ b/archiva-webapp/src/main/webapp/WEB-INF/jsp/browseArtifact.jsp @@ -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> diff --git a/archiva-webapp/src/main/webapp/WEB-INF/jsp/browseGroup.jsp b/archiva-webapp/src/main/webapp/WEB-INF/jsp/browseGroup.jsp index 294428e73..dd7218779 100644 --- a/archiva-webapp/src/main/webapp/WEB-INF/jsp/browseGroup.jsp +++ b/archiva-webapp/src/main/webapp/WEB-INF/jsp/browseGroup.jsp @@ -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"/> diff --git a/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactInfo.jspf b/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactInfo.jspf index 2e61d2d96..7a206a351 100644 --- a/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactInfo.jspf +++ b/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactInfo.jspf @@ -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}'}"/> diff --git a/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag b/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag index 0a39338d1..53676a6ab 100644 --- a/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag +++ b/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag @@ -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="/"> diff --git a/archiva-webapp/src/main/webapp/WEB-INF/web.xml b/archiva-webapp/src/main/webapp/WEB-INF/web.xml index 7c6cb40c1..b2de4ebf3 100644 --- a/archiva-webapp/src/main/webapp/WEB-INF/web.xml +++ b/archiva-webapp/src/main/webapp/WEB-INF/web.xml @@ -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> diff --git a/archiva-webapp/src/test/java/org/apache/maven/archiva/web/servlet/repository/RepositoryAccessTest.java b/archiva-webapp/src/test/java/org/apache/maven/archiva/web/servlet/repository/RepositoryAccessTest.java deleted file mode 100644 index c893338ae..000000000 --- a/archiva-webapp/src/test/java/org/apache/maven/archiva/web/servlet/repository/RepositoryAccessTest.java +++ /dev/null @@ -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" ); - } -} @@ -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> diff --git a/src/site/apt/guides/getting-started/index.apt b/src/site/apt/guides/getting-started/index.apt index 7666dd749..0b362515e 100644 --- a/src/site/apt/guides/getting-started/index.apt +++ b/src/site/apt/guides/getting-started/index.apt @@ -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. |