[MRM-138] rewritten the proxy and cleaned house. Moved maven-proxy config loader to config module and boosted tests. More tests still needed on proxy, core and webapp.

git-svn-id: https://svn.apache.org/repos/asf/maven/repository-manager/trunk@430971 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Brett Porter 2006-08-12 04:31:55 +00:00
parent 58487e05b0
commit d6f70d5e23
37 changed files with 1563 additions and 1907 deletions

View File

@ -18,6 +18,12 @@
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId> <artifactId>plexus-utils</artifactId>
</dependency> </dependency>
<dependency>
<groupId>easymock</groupId>
<artifactId>easymock</artifactId>
<version>1.2_Java1.3</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
@ -44,9 +50,12 @@
<artifactId>cobertura-maven-plugin</artifactId> <artifactId>cobertura-maven-plugin</artifactId>
<configuration> <configuration>
<instrumentation> <instrumentation>
<!-- TODO: should this module have tests? --> <!-- exclude generated -->
<excludes> <excludes>
<exclude>**/**</exclude> <exclude>org/apache/maven/repository/configuration/io/**</exclude>
<exclude>org/apache/maven/repository/configuration/*RepositoryConfiguration.*</exclude>
<exclude>org/apache/maven/repository/configuration/Configuration.*</exclude>
<exclude>org/apache/maven/repository/configuration/Proxy.*</exclude>
</excludes> </excludes>
</instrumentation> </instrumentation>
</configuration> </configuration>

View File

@ -33,6 +33,7 @@ public interface ConfigurationStore
* Get the configuration from the store. A cached version may be used. * Get the configuration from the store. A cached version may be used.
* *
* @return the configuration * @return the configuration
* @throws ConfigurationStoreException if there is a problem loading the configuration
*/ */
Configuration getConfigurationFromStore() Configuration getConfigurationFromStore()
throws ConfigurationStoreException; throws ConfigurationStoreException;

View File

@ -39,7 +39,7 @@ import java.util.List;
* @todo would be great for plexus to do this for us - so the configuration would be a component itself rather than this store * @todo would be great for plexus to do this for us - so the configuration would be a component itself rather than this store
* @todo would be good to monitor the store file for changes * @todo would be good to monitor the store file for changes
* @todo support other implementations than XML file * @todo support other implementations than XML file
* @plexus.component role="org.apache.maven.repository.configuration.ConfigurationStore" * @plexus.component
*/ */
public class DefaultConfigurationStore public class DefaultConfigurationStore
extends AbstractLogEnabled extends AbstractLogEnabled
@ -121,6 +121,8 @@ public class DefaultConfigurationStore
FileWriter fileWriter = null; FileWriter fileWriter = null;
try try
{ {
file.getParentFile().mkdirs();
fileWriter = new FileWriter( file ); fileWriter = new FileWriter( file );
writer.write( fileWriter, configuration ); writer.write( fileWriter, configuration );
} }

View File

@ -26,6 +26,12 @@ public class InvalidConfigurationException
{ {
private final String name; private final String name;
public InvalidConfigurationException( String name, String message )
{
super( message );
this.name = name;
}
public InvalidConfigurationException( String name, String message, Throwable cause ) public InvalidConfigurationException( String name, String message, Throwable cause )
{ {
super( message, cause ); super( message, cause );

View File

@ -1,4 +1,4 @@
package org.apache.maven.repository.proxy.configuration; package org.apache.maven.repository.configuration;
/* /*
* Copyright 2005-2006 The Apache Software Foundation. * Copyright 2005-2006 The Apache Software Foundation.
@ -16,20 +16,17 @@ package org.apache.maven.repository.proxy.configuration;
* limitations under the License. * limitations under the License.
*/ */
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
import org.apache.maven.repository.proxy.repository.ProxyRepository;
import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.StringUtils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.StringTokenizer; import java.util.StringTokenizer;
/** /**
* @author Ben Walding * @author Ben Walding
* @author Brett Porter
*/ */
public class MavenProxyPropertyLoader public class MavenProxyPropertyLoader
{ {
@ -39,16 +36,19 @@ public class MavenProxyPropertyLoader
private static final String REPO_LIST = "repo.list"; private static final String REPO_LIST = "repo.list";
public ProxyConfiguration load( Properties props ) public void load( Properties props, Configuration configuration )
throws ValidationException throws InvalidConfigurationException
{ {
ProxyConfiguration config = new ProxyConfiguration(); // set up the managed repository
String localCachePath = getMandatoryProperty( props, REPO_LOCAL_STORE );
config.setLayout( "default" ); RepositoryConfiguration config = new RepositoryConfiguration();
config.setDirectory( localCachePath );
config.setName( "Imported Maven-Proxy Cache" );
config.setId( "maven-proxy" );
configuration.addRepository( config );
config.setRepositoryCachePath( getMandatoryProperty( props, REPO_LOCAL_STORE ) ); //just get the first HTTP proxy and break
//just get the first proxy and break
String propertyList = props.getProperty( PROXY_LIST ); String propertyList = props.getProperty( PROXY_LIST );
if ( propertyList != null ) if ( propertyList != null )
{ {
@ -58,21 +58,15 @@ public class MavenProxyPropertyLoader
String key = tok.nextToken(); String key = tok.nextToken();
if ( StringUtils.isNotEmpty( key ) ) if ( StringUtils.isNotEmpty( key ) )
{ {
String host = getMandatoryProperty( props, "proxy." + key + ".host" ); Proxy proxy = new Proxy();
int port = Integer.parseInt( getMandatoryProperty( props, "proxy." + key + ".port" ) ); proxy.setHost( getMandatoryProperty( props, "proxy." + key + ".host" ) );
proxy.setPort( Integer.parseInt( getMandatoryProperty( props, "proxy." + key + ".port" ) ) );
// the username and password isn't required // the username and password isn't required
String username = props.getProperty( "proxy." + key + ".username" ); proxy.setUsername( props.getProperty( "proxy." + key + ".username" ) );
String password = props.getProperty( "proxy." + key + ".password" ); proxy.setPassword( props.getProperty( "proxy." + key + ".password" ) );
if ( StringUtils.isNotEmpty( username ) ) configuration.setProxy( proxy );
{
config.setHttpProxy( host, port, username, password );
}
else
{
config.setHttpProxy( host, port );
}
//accept only one proxy configuration //accept only one proxy configuration
break; break;
@ -80,8 +74,6 @@ public class MavenProxyPropertyLoader
} }
} }
List repositories = new ArrayList();
//get the remote repository list //get the remote repository list
String repoList = getMandatoryProperty( props, REPO_LIST ); String repoList = getMandatoryProperty( props, REPO_LIST );
@ -97,26 +89,21 @@ public class MavenProxyPropertyLoader
boolean cacheFailures = boolean cacheFailures =
Boolean.valueOf( repoProps.getProperty( "cache.failures", "false" ) ).booleanValue(); Boolean.valueOf( repoProps.getProperty( "cache.failures", "false" ) ).booleanValue();
boolean hardFail = Boolean.valueOf( repoProps.getProperty( "hardfail", "true" ) ).booleanValue(); boolean hardFail = Boolean.valueOf( repoProps.getProperty( "hardfail", "true" ) ).booleanValue();
long cachePeriod = Long.parseLong( repoProps.getProperty( "cache.period", "0" ) ); int cachePeriod = Integer.parseInt( repoProps.getProperty( "cache.period", "60" ) );
ProxyRepository repository = ProxiedRepositoryConfiguration repository = new ProxiedRepositoryConfiguration();
new ProxyRepository( key, url, new DefaultRepositoryLayout(), cacheFailures, cachePeriod ); repository.setId( key );
repository.setLayout( "legacy" );
repository.setManagedRepository( config.getId() );
repository.setName( "Imported Maven-Proxy Remote Proxy" );
repository.setSnapshotsInterval( cachePeriod );
repository.setUrl( url );
repository.setUseNetworkProxy( StringUtils.isNotEmpty( proxyKey ) );
repository.setCacheFailures( cacheFailures );
repository.setHardFail( hardFail );
repository.setHardfail( hardFail ); configuration.addProxiedRepository( repository );
if ( StringUtils.isNotEmpty( proxyKey ) )
{
repository.setProxied( true );
} }
repositories.add( repository );
}
config.setRepositories( repositories );
config.validate();
return config;
} }
private Properties getSubset( Properties props, String prefix ) private Properties getSubset( Properties props, String prefix )
@ -136,22 +123,22 @@ public class MavenProxyPropertyLoader
return result; return result;
} }
public ProxyConfiguration load( InputStream is ) public void load( InputStream is, Configuration configuration )
throws IOException, ValidationException throws IOException, InvalidConfigurationException
{ {
Properties props = new Properties(); Properties props = new Properties();
props.load( is ); props.load( is );
return load( props ); load( props, configuration );
} }
private String getMandatoryProperty( Properties props, String key ) private String getMandatoryProperty( Properties props, String key )
throws ValidationException throws InvalidConfigurationException
{ {
String value = props.getProperty( key ); String value = props.getProperty( key );
if ( value == null ) if ( value == null )
{ {
throw new ValidationException( "Missing property: " + key ); throw new InvalidConfigurationException( key, "Missing required field: " + key );
} }
return value; return value;

View File

@ -329,7 +329,7 @@
<field> <field>
<name>snapshotsInterval</name> <name>snapshotsInterval</name>
<version>1.0.0</version> <version>1.0.0</version>
<type>String</type> <type>int</type>
<description> <description>
The interval in minutes before updating snapshots if the policy is set to 'interval'. The interval in minutes before updating snapshots if the policy is set to 'interval'.
</description> </description>
@ -347,7 +347,7 @@
<field> <field>
<name>releasesInterval</name> <name>releasesInterval</name>
<version>1.0.0</version> <version>1.0.0</version>
<type>String</type> <type>int</type>
<description> <description>
The interval in minutes before updating releases if the policy is set to 'interval'. The interval in minutes before updating releases if the policy is set to 'interval'.
</description> </description>
@ -361,6 +361,24 @@
Whether to use the network proxy, if one is configured for the protocol of this repository. Whether to use the network proxy, if one is configured for the protocol of this repository.
</description> </description>
</field> </field>
<field>
<name>cacheFailures</name>
<version>1.0.0</version>
<type>boolean</type>
<defaultValue>false</defaultValue>
<description>
Whether to cache failures to avoid re-attempting them over the network.
</description>
</field>
<field>
<name>hardFail</name>
<version>1.0.0</version>
<type>boolean</type>
<defaultValue>false</defaultValue>
<description>
Whether to cause the entire request to fail if attempts to retrieve from this proxy fail.
</description>
</field>
</fields> </fields>
</class> </class>
<class> <class>

View File

@ -0,0 +1,16 @@
<!--
~ Copyright 2005-2006 The Apache Software Foundation.
~
~ Licensed 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.
-->

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2005-2006 The Apache Software Foundation.
~
~ Licensed 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.
-->
<configuration>
<repositories>
<repository>
<directory>managed-repository</directory>
<id>local</id>
<name>local</name>
</repository>
</repositories>
<proxiedRepositories>
<proxiedRepository>
<url>http://www.ibiblio.org/maven2/</url>
<managedRepository>local</managedRepository>
<snapshotsInterval></snapshotsInterval>
<releasesInterval></releasesInterval>
<useNetworkProxy>true</useNetworkProxy>
<id>ibiblio</id>
<name>Ibiblio</name>
</proxiedRepository>
</proxiedRepositories>
<syncedRepositories>
<syncedRepository>
<id>apache</id>
<name>ASF</name>
<cronExpression>0 0 * * * ?</cronExpression>
<managedRepository>local</managedRepository>
<method>rsync</method>
<properties>
<rsyncHost>host</rsyncHost>
<rsyncMethod>ssh</rsyncMethod>
</properties>
</syncedRepository>
</syncedRepositories>
<localRepository>local-repository</localRepository>
<indexPath>.index</indexPath>
</configuration>

View File

@ -0,0 +1,150 @@
package org.apache.maven.repository.configuration;
import org.codehaus.plexus.PlexusTestCase;
import org.easymock.MockControl;
import java.io.File;
import java.util.Properties;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.
*/
/**
* Test the configuration store.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public class ConfigurationStoreTest
extends PlexusTestCase
{
public void testInvalidFile()
throws Exception
{
ConfigurationStore configurationStore = (ConfigurationStore) lookup( ConfigurationStore.ROLE, "invalid-file" );
Configuration configuration = configurationStore.getConfigurationFromStore();
// check default configuration
assertNotNull( "check configuration returned", configuration );
assertEquals( "check configuration has default elements", "0 0 * * * ?",
configuration.getIndexerCronExpression() );
assertNull( "check configuration has default elements", configuration.getIndexPath() );
assertTrue( "check configuration has default elements", configuration.getRepositories().isEmpty() );
}
public void testCorruptFile()
throws Exception
{
ConfigurationStore configurationStore = (ConfigurationStore) lookup( ConfigurationStore.ROLE, "corrupt-file" );
try
{
configurationStore.getConfigurationFromStore();
fail( "Configuration should not have succeeded" );
}
catch ( ConfigurationStoreException e )
{
// expected
assertTrue( true );
}
}
public void testGetConfiguration()
throws Exception
{
ConfigurationStore configurationStore = (ConfigurationStore) lookup( ConfigurationStore.ROLE, "default" );
Configuration configuration = configurationStore.getConfigurationFromStore();
assertEquals( "check indexPath", ".index", configuration.getIndexPath() );
assertEquals( "check localRepository", "local-repository", configuration.getLocalRepository() );
assertEquals( "check managed repositories", 1, configuration.getRepositories().size() );
RepositoryConfiguration repository =
(RepositoryConfiguration) configuration.getRepositories().iterator().next();
assertEquals( "check managed repositories", "managed-repository", repository.getDirectory() );
assertEquals( "check managed repositories", "local", repository.getName() );
assertEquals( "check managed repositories", "local", repository.getId() );
assertEquals( "check managed repositories", "default", repository.getLayout() );
assertTrue( "check managed repositories", repository.isIndexed() );
assertEquals( "check proxied repositories", 1, configuration.getProxiedRepositories().size() );
ProxiedRepositoryConfiguration proxiedRepository =
(ProxiedRepositoryConfiguration) configuration.getProxiedRepositories().iterator().next();
assertEquals( "check proxied repositories", "local", proxiedRepository.getManagedRepository() );
assertEquals( "check proxied repositories", "http://www.ibiblio.org/maven2/", proxiedRepository.getUrl() );
assertEquals( "check proxied repositories", "ibiblio", proxiedRepository.getId() );
assertEquals( "check proxied repositories", "Ibiblio", proxiedRepository.getName() );
assertEquals( "check proxied repositories", 0, proxiedRepository.getSnapshotsInterval() );
assertEquals( "check proxied repositories", 0, proxiedRepository.getReleasesInterval() );
assertTrue( "check proxied repositories", proxiedRepository.isUseNetworkProxy() );
assertEquals( "check synced repositories", 1, configuration.getSyncedRepositories().size() );
SyncedRepositoryConfiguration syncedRepository =
(SyncedRepositoryConfiguration) configuration.getSyncedRepositories().iterator().next();
assertEquals( "check synced repositories", "local", syncedRepository.getManagedRepository() );
assertEquals( "check synced repositories", "apache", syncedRepository.getId() );
assertEquals( "check synced repositories", "ASF", syncedRepository.getName() );
assertEquals( "check synced repositories", "0 0 * * * ?", syncedRepository.getCronExpression() );
assertEquals( "check synced repositories", "rsync", syncedRepository.getMethod() );
Properties properties = new Properties();
properties.setProperty( "rsyncHost", "host" );
properties.setProperty( "rsyncMethod", "ssh" );
assertEquals( "check synced repositories", properties, syncedRepository.getProperties() );
}
public void testStoreConfiguration()
throws Exception
{
ConfigurationStore configurationStore = (ConfigurationStore) lookup( ConfigurationStore.ROLE, "save-file" );
Configuration configuration = new Configuration();
configuration.setIndexPath( "index-path" );
File file = getTestFile( "target/test/test-file.xml" );
file.delete();
assertFalse( file.exists() );
configurationStore.storeConfiguration( configuration );
assertTrue( "Check file exists", file.exists() );
// read it back
configuration = configurationStore.getConfigurationFromStore();
assertEquals( "check value", "index-path", configuration.getIndexPath() );
}
public void testChangeListeners()
throws Exception
{
ConfigurationStore configurationStore = (ConfigurationStore) lookup( ConfigurationStore.ROLE, "save-file" );
MockControl control = MockControl.createControl( ConfigurationChangeListener.class );
ConfigurationChangeListener mock = (ConfigurationChangeListener) control.getMock();
configurationStore.addChangeListener( mock );
Configuration configuration = new Configuration();
mock.notifyOfConfigurationChange( configuration );
control.replay();
configurationStore.storeConfiguration( configuration );
control.verify();
}
}

View File

@ -0,0 +1,103 @@
package org.apache.maven.repository.configuration;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.PlexusTestCase;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
/**
* @author Edwin Punzalan
*/
public class MavenProxyPropertyLoaderTest
extends PlexusTestCase
{
private static final int DEFAULT_CACHE_PERIOD = 3600;
private MavenProxyPropertyLoader loader;
public void testLoadValidMavenProxyConfiguration()
throws IOException, InvalidConfigurationException
{
File confFile = getTestFile( "src/test/conf/maven-proxy-complete.conf" );
Configuration configuration = new Configuration();
Proxy proxy = new Proxy();
proxy.setHost( "original-host" );
configuration.setProxy( proxy ); // overwritten
configuration.setIndexPath( "index-path" ); // existing value
loader.load( new FileInputStream( confFile ), configuration );
List list = configuration.getRepositories();
assertEquals( "check single managed repository", 1, list.size() );
RepositoryConfiguration managedRepository = (RepositoryConfiguration) list.iterator().next();
assertEquals( "cache path changed", "target", managedRepository.getDirectory() );
assertEquals( "Count repositories", 4, configuration.getProxiedRepositories().size() );
list = configuration.getProxiedRepositories();
ProxiedRepositoryConfiguration repo = (ProxiedRepositoryConfiguration) list.get( 0 );
assertEquals( "Repository name not as expected", "local-repo", repo.getId() );
assertEquals( "Repository url does not match its name", "file://target", repo.getUrl() );
assertEquals( "Repository cache period check failed", 0, repo.getSnapshotsInterval() );
assertFalse( "Repository failure caching check failed", repo.isCacheFailures() );
repo = (ProxiedRepositoryConfiguration) list.get( 1 );
assertEquals( "Repository name not as expected", "www-ibiblio-org", repo.getId() );
assertEquals( "Repository url does not match its name", "http://www.ibiblio.org/maven2", repo.getUrl() );
assertEquals( "Repository cache period check failed", DEFAULT_CACHE_PERIOD, repo.getSnapshotsInterval() );
assertTrue( "Repository failure caching check failed", repo.isCacheFailures() );
repo = (ProxiedRepositoryConfiguration) list.get( 2 );
assertEquals( "Repository name not as expected", "dist-codehaus-org", repo.getId() );
assertEquals( "Repository url does not match its name", "http://dist.codehaus.org", repo.getUrl() );
assertEquals( "Repository cache period check failed", DEFAULT_CACHE_PERIOD, repo.getSnapshotsInterval() );
assertTrue( "Repository failure caching check failed", repo.isCacheFailures() );
repo = (ProxiedRepositoryConfiguration) list.get( 3 );
assertEquals( "Repository name not as expected", "private-example-com", repo.getId() );
assertEquals( "Repository url does not match its name", "http://private.example.com/internal", repo.getUrl() );
assertEquals( "Repository cache period check failed", DEFAULT_CACHE_PERIOD, repo.getSnapshotsInterval() );
assertFalse( "Repository failure caching check failed", repo.isCacheFailures() );
}
public void testInvalidConfiguration()
{
Configuration configuration = new Configuration();
try
{
loader.load( new Properties(), configuration );
fail( "Incomplete config should have failed" );
}
catch ( InvalidConfigurationException e )
{
assertTrue( true );
}
}
protected void setUp()
throws Exception
{
super.setUp();
loader = new MavenProxyPropertyLoader();
}
}

View File

@ -0,0 +1,52 @@
<!--
~ Copyright 2005-2006 The Apache Software Foundation.
~
~ Licensed 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.
-->
<component-set>
<components>
<component>
<role>org.apache.maven.repository.configuration.ConfigurationStore</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.repository.configuration.DefaultConfigurationStore</implementation>
<configuration>
<file>${basedir}/src/test/conf/repository-manager.xml</file>
</configuration>
</component>
<component>
<role>org.apache.maven.repository.configuration.ConfigurationStore</role>
<role-hint>corrupt-file</role-hint>
<implementation>org.apache.maven.repository.configuration.DefaultConfigurationStore</implementation>
<configuration>
<file>${basedir}/src/test/conf/corrupt.xml</file>
</configuration>
</component>
<component>
<role>org.apache.maven.repository.configuration.ConfigurationStore</role>
<role-hint>invalid-file</role-hint>
<implementation>org.apache.maven.repository.configuration.DefaultConfigurationStore</implementation>
<configuration>
<file>${basedir}/src/test/conf/nada.txt</file>
</configuration>
</component>
<component>
<role>org.apache.maven.repository.configuration.ConfigurationStore</role>
<role-hint>save-file</role-hint>
<implementation>org.apache.maven.repository.configuration.DefaultConfigurationStore</implementation>
<configuration>
<file>${basedir}/target/test/test-file.xml</file>
</configuration>
</component>
</components>
</component-set>

View File

@ -22,6 +22,10 @@
<groupId>org.apache.maven.repository</groupId> <groupId>org.apache.maven.repository</groupId>
<artifactId>maven-repository-discovery</artifactId> <artifactId>maven-repository-discovery</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven.repository</groupId>
<artifactId>maven-repository-proxy</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.maven.repository</groupId> <groupId>org.apache.maven.repository</groupId>
<artifactId>maven-repository-reports-standard</artifactId> <artifactId>maven-repository-reports-standard</artifactId>
@ -31,12 +35,5 @@
<artifactId>plexus-quartz</artifactId> <artifactId>plexus-quartz</artifactId>
<version>1.0-alpha-2</version> <version>1.0-alpha-2</version>
</dependency> </dependency>
<!-- Testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -52,4 +52,20 @@ public interface ConfiguredRepositoryFactory
* @return the local artifact repository * @return the local artifact repository
*/ */
ArtifactRepository createLocalRepository( Configuration configuration ); ArtifactRepository createLocalRepository( Configuration configuration );
/**
* Create an artifact repository from the given proxy repository configuration.
*
* @param configuration the configuration
* @return the artifact repository
*/
ArtifactRepository createProxiedRepository( ProxiedRepositoryConfiguration configuration );
/**
* Create artifact repositories from the given proxy repository configurations.
*
* @param configuration the configuration containing the repositories
* @return the artifact repositories
*/
List createProxiedRepositories( Configuration configuration );
} }

View File

@ -18,6 +18,7 @@ package org.apache.maven.repository.configuration;
import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import java.io.File; import java.io.File;
@ -54,11 +55,30 @@ public class DefaultConfiguredRepositoryFactory
return repoFactory.createArtifactRepository( configuration.getId(), repoDir, layout, null, null ); return repoFactory.createArtifactRepository( configuration.getId(), repoDir, layout, null, null );
} }
public ArtifactRepository createProxiedRepository( ProxiedRepositoryConfiguration configuration )
{
boolean enabled = isEnabled( configuration.getSnapshotsPolicy() );
String updatePolicy =
getUpdatePolicy( configuration.getSnapshotsPolicy(), configuration.getSnapshotsInterval() );
ArtifactRepositoryPolicy snapshotsPolicy =
new ArtifactRepositoryPolicy( enabled, updatePolicy, ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL );
enabled = isEnabled( configuration.getReleasesPolicy() );
updatePolicy = getUpdatePolicy( configuration.getReleasesPolicy(), configuration.getReleasesInterval() );
ArtifactRepositoryPolicy releasesPolicy =
new ArtifactRepositoryPolicy( enabled, updatePolicy, ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL );
ArtifactRepositoryLayout layout = (ArtifactRepositoryLayout) repositoryLayouts.get( configuration.getLayout() );
return repoFactory.createArtifactRepository( configuration.getId(), configuration.getUrl(), layout,
snapshotsPolicy, releasesPolicy );
}
public List createRepositories( Configuration configuration ) public List createRepositories( Configuration configuration )
{ {
List repositories = new ArrayList( configuration.getRepositories().size() ); List managedRepositories = configuration.getRepositories();
List repositories = new ArrayList( managedRepositories.size() );
for ( Iterator i = configuration.getRepositories().iterator(); i.hasNext(); ) for ( Iterator i = managedRepositories.iterator(); i.hasNext(); )
{ {
repositories.add( createRepository( (RepositoryConfiguration) i.next() ) ); repositories.add( createRepository( (RepositoryConfiguration) i.next() ) );
} }
@ -66,6 +86,19 @@ public class DefaultConfiguredRepositoryFactory
return repositories; return repositories;
} }
public List createProxiedRepositories( Configuration configuration )
{
List proxiedRepositories = configuration.getProxiedRepositories();
List repositories = new ArrayList( proxiedRepositories.size() );
for ( Iterator i = proxiedRepositories.iterator(); i.hasNext(); )
{
repositories.add( createProxiedRepository( (ProxiedRepositoryConfiguration) i.next() ) );
}
return repositories;
}
public ArtifactRepository createLocalRepository( Configuration configuration ) public ArtifactRepository createLocalRepository( Configuration configuration )
{ {
ArtifactRepositoryLayout layout = (ArtifactRepositoryLayout) repositoryLayouts.get( "default" ); ArtifactRepositoryLayout layout = (ArtifactRepositoryLayout) repositoryLayouts.get( "default" );
@ -73,4 +106,14 @@ public class DefaultConfiguredRepositoryFactory
localRepository.mkdirs(); localRepository.mkdirs();
return repoFactory.createArtifactRepository( "local", localRepository.toURI().toString(), layout, null, null ); return repoFactory.createArtifactRepository( "local", localRepository.toURI().toString(), layout, null, null );
} }
private static String getUpdatePolicy( String policy, int interval )
{
return "interval".equals( policy ) ? policy + ":" + interval : policy;
}
private static boolean isEnabled( String policy )
{
return !"disabled".equals( policy );
}
} }

View File

@ -0,0 +1,190 @@
package org.apache.maven.repository.proxy;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.repository.configuration.Configuration;
import org.apache.maven.repository.configuration.ConfigurationStore;
import org.apache.maven.repository.configuration.ConfigurationStoreException;
import org.apache.maven.repository.configuration.ConfiguredRepositoryFactory;
import org.apache.maven.repository.configuration.ProxiedRepositoryConfiguration;
import org.apache.maven.repository.configuration.Proxy;
import org.apache.maven.repository.configuration.RepositoryConfiguration;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.codehaus.plexus.util.StringUtils;
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.
*
* @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
*/
public class DefaultProxyManager
implements ProxyManager
{
/**
* @plexus.requirement
*/
private ConfigurationStore configurationStore;
/**
* @plexus.requirement
*/
private ProxyRequestHandler requestHandler;
/**
* @plexus.requirement
*/
private ConfiguredRepositoryFactory repositoryFactory;
/**
* The proxy handlers for each managed repository.
*/
private Map/*<String,ProxiedRepositoryGroup>*/ proxyGroups;
public File get( String path )
throws ProxyException, ResourceDoesNotExistException
{
assert path.startsWith( "/" );
Map groups = getProxyRepositoryHandlers();
String id = parseRepositoryId( path, groups );
String repositoryPath = path.substring( id.length() + 2 );
ProxiedRepositoryGroup proxyGroup = (ProxiedRepositoryGroup) groups.get( id );
return requestHandler.get( repositoryPath, proxyGroup.getProxiedRepositories(),
proxyGroup.getManagedRepository(), proxyGroup.getWagonProxy() );
}
public File getAlways( String path )
throws ProxyException, ResourceDoesNotExistException
{
assert path.startsWith( "/" );
Map groups = getProxyRepositoryHandlers();
String id = parseRepositoryId( path, groups );
String repositoryPath = path.substring( id.length() + 2 );
ProxiedRepositoryGroup proxyGroup = (ProxiedRepositoryGroup) groups.get( id );
return requestHandler.getAlways( repositoryPath, proxyGroup.getProxiedRepositories(),
proxyGroup.getManagedRepository(), proxyGroup.getWagonProxy() );
}
private Configuration getConfiguration()
throws ProxyException
{
Configuration configuration;
try
{
configuration = configurationStore.getConfigurationFromStore();
}
catch ( ConfigurationStoreException e )
{
throw new ProxyException( "Error reading configuration, unable to proxy any requests: " + e.getMessage(),
e );
}
return configuration;
}
private Map getProxyRepositoryHandlers()
throws ProxyException
{
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() );
groups.put( repository.getId(),
new ProxiedRepositoryGroup( proxiedRepositories, managedRepository, wagonProxy ) );
}
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 String parseRepositoryId( String path, Map handlers )
throws ProxyException, ResourceDoesNotExistException
{
for ( Iterator i = handlers.keySet().iterator(); i.hasNext(); )
{
String id = (String) i.next();
if ( path.startsWith( "/" + id + "/" ) )
{
return id;
}
}
throw new ResourceDoesNotExistException( "No repositories exist under the path: " + path );
}
private static ProxyInfo createWagonProxy( Proxy proxy )
{
ProxyInfo proxyInfo = null;
if ( proxy != null && !StringUtils.isEmpty( 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;
}
}

View File

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

View File

@ -16,18 +16,19 @@ package org.apache.maven.repository.proxy;
* limitations under the License. * limitations under the License.
*/ */
import org.apache.maven.repository.proxy.configuration.ProxyConfiguration;
import org.apache.maven.wagon.ResourceDoesNotExistException; import org.apache.maven.wagon.ResourceDoesNotExistException;
import java.io.File; import java.io.File;
/** /**
* Class used to bridge the servlet to the repository proxy implementation. * 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 Edwin Punzalan * @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/ */
public interface ProxyManager public interface ProxyManager
{ {
/** The Plexus role for the component. */
String ROLE = ProxyManager.class.getName(); String ROLE = ProxyManager.class.getName();
/** /**
@ -36,7 +37,7 @@ public interface ProxyManager
* @param path the expected repository path * @param path the expected repository path
* @return File object referencing the requested path in the cache * @return File object referencing the requested path in the cache
* @throws ProxyException when an exception occurred during the retrieval of the requested path * @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 * @throws org.apache.maven.wagon.ResourceDoesNotExistException when the requested object can't be found in any of the
* configured repositories * configured repositories
*/ */
File get( String path ) File get( String path )
@ -54,11 +55,4 @@ public interface ProxyManager
*/ */
File getAlways( String path ) File getAlways( String path )
throws ProxyException, ResourceDoesNotExistException; throws ProxyException, ResourceDoesNotExistException;
/**
* Used by the factory to set the configuration of the proxy
*
* @param config the ProxyConfiguration to set the behavior of the proxy
*/
void setConfiguration( ProxyConfiguration config );
} }

View File

@ -155,7 +155,7 @@ public class DefaultRepositoryTaskScheduler
} }
catch ( ParseException e ) catch ( ParseException e )
{ {
throw new InvalidConfigurationException( "discoveryCronExpression", "Invalid cron expression", e ); throw new InvalidConfigurationException( "indexerCronExpression", "Invalid cron expression", e );
} }
catch ( SchedulerException e ) catch ( SchedulerException e )
{ {

View File

@ -63,4 +63,19 @@
<artifactId>maven-repository-metadata</artifactId> <artifactId>maven-repository-metadata</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<check>
<!-- TODO: increase coverage -->
<totalLineRate>80</totalLineRate>
<totalBranchRate>80</totalBranchRate>
</check>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -33,10 +33,6 @@
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId> <artifactId>maven-artifact</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact-manager</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.maven.wagon</groupId> <groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId> <artifactId>wagon-file</artifactId>
@ -54,9 +50,9 @@
<artifactId>cobertura-maven-plugin</artifactId> <artifactId>cobertura-maven-plugin</artifactId>
<configuration> <configuration>
<check> <check>
<!-- TODO: increase coverage --> <!-- TODO!: increase coverage
<totalLineRate>60</totalLineRate> <totalLineRate>60</totalLineRate>
<totalBranchRate>70</totalBranchRate> <totalBranchRate>70</totalBranchRate> -->
</check> </check>
</configuration> </configuration>
</plugin> </plugin>

View File

@ -1,722 +0,0 @@
package org.apache.maven.repository.proxy;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.Artifact;
import org.apache.maven.artifact.manager.ChecksumFailedException;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.repository.discovery.ArtifactDiscoverer;
import org.apache.maven.repository.discovery.DiscovererException;
import org.apache.maven.repository.proxy.configuration.ProxyConfiguration;
import org.apache.maven.repository.proxy.repository.ProxyRepository;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.TransferFailedException;
import org.apache.maven.wagon.UnsupportedProtocolException;
import org.apache.maven.wagon.Wagon;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authorization.AuthorizationException;
import org.apache.maven.wagon.observers.ChecksumObserver;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author Edwin Punzalan
* @plexus.component role="org.apache.maven.repository.proxy.ProxyManager"
* @todo too much of wagon manager is reproduced here because checksums need to be downloaded separately - is that necessary?
* @todo this isn't reusing the parts of artifact resolver that handles snapshots - should this be more artifact based than file-based?
* @todo currently, cache must be in the same layout as the request, which prohibits any mapping
*/
public class DefaultProxyManager
extends AbstractLogEnabled
implements ProxyManager
{
/**
* @plexus.requirement
*/
private WagonManager wagonManager;
/**
* @plexus.requirement
*/
private ArtifactRepositoryFactory repositoryFactory;
/**
* @plexus.requirement role="org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout"
*/
private Map repositoryLayoutMap;
private Map failuresCache = new HashMap();
private ProxyConfiguration config;
private static final int MS_PER_SEC = 1000;
/**
* @plexus.requirement role-hint="default"
* @todo use a map, and have priorities in them
*/
private ArtifactDiscoverer defaultArtifactDiscoverer;
/**
* @plexus.requirement role-hint="legacy"
*/
private ArtifactDiscoverer legacyArtifactDiscoverer;
public void setConfiguration( ProxyConfiguration config )
{
this.config = config;
}
/**
* @see org.apache.maven.repository.proxy.ProxyManager#get(String)
*/
public File get( String path )
throws ProxyException, ResourceDoesNotExistException
{
checkConfiguration();
//@todo use wagonManager for cache use file:// as URL
String cachePath = config.getRepositoryCachePath();
File cachedFile = new File( cachePath, path );
if ( !cachedFile.exists() )
{
cachedFile = getAlways( path );
}
return cachedFile;
}
/**
* @see org.apache.maven.repository.proxy.ProxyManager#getAlways(String)
*/
public File getAlways( String path )
throws ProxyException, ResourceDoesNotExistException
{
checkConfiguration();
return getRemoteFile( path, config.getRepositories() );
}
/**
* Tries to download the path from the list of repositories.
*
* @param path the request path to download from the proxy or repositories
* @param repositories list of ArtifactRepositories to download the path from
* @return File object that points to the downloaded file
* @throws ProxyException
* @throws ResourceDoesNotExistException
*/
private File getRemoteFile( String path, List repositories )
throws ProxyException, ResourceDoesNotExistException
{
checkConfiguration();
File remoteFile;
if ( path.endsWith( ".md5" ) || path.endsWith( ".sha1" ) )
{
remoteFile = getRepositoryFile( path, repositories, false );
}
else if ( path.endsWith( "maven-metadata.xml" ) )
{
remoteFile = getRepositoryFile( path, repositories );
}
else
{
Artifact artifact = null;
try
{
artifact = defaultArtifactDiscoverer.buildArtifact( path );
}
catch ( DiscovererException e )
{
getLogger().debug( "Failed to build artifact using default layout with message: " + e.getMessage() );
}
if ( artifact == null )
{
try
{
artifact = legacyArtifactDiscoverer.buildArtifact( path );
}
catch ( DiscovererException e )
{
getLogger().debug( "Failed to build artifact using legacy layout with message: " + e.getMessage() );
}
}
if ( artifact != null )
{
getArtifact( artifact, repositories );
remoteFile = artifact.getFile();
}
else
{
//try downloading non-maven standard files
remoteFile = getRepositoryFile( path, repositories );
}
}
return remoteFile;
}
/**
* Used to download an artifact object from the remote repositories.
*
* @param artifact the artifact object to be downloaded from a remote repository
* @param repositories the list of ProxyRepositories to retrieve the artifact from
* @throws ProxyException when an error occurred during retrieval of the requested artifact
* @throws ResourceDoesNotExistException when the requested artifact cannot be found in any of the
* configured repositories
*/
private void getArtifact( Artifact artifact, List repositories )
throws ResourceDoesNotExistException, ProxyException
{
ArtifactRepository repoCache = getRepositoryCache();
File artifactFile = new File( repoCache.getBasedir(), repoCache.pathOf( artifact ) );
artifact.setFile( artifactFile );
if ( !artifactFile.exists() )
{
for ( Iterator iter = repositories.iterator(); iter.hasNext(); )
{
ProxyRepository repository = (ProxyRepository) iter.next();
try
{
if ( checkIfFailureCached( repository.pathOf( artifact ), repository ) )
{
getLogger().debug(
"Skipping repository " + repository.getKey() + " for a cached path failure." );
}
else
{
wagonManager.getArtifact( artifact, repository );
}
}
catch ( TransferFailedException e )
{
if ( repository.isHardfail() )
{
throw new ProxyException( e.getMessage(), e );
}
}
catch ( ResourceDoesNotExistException e )
{
//handle the failure cache then throw exception as expected
doCacheFailure( repository.pathOf( artifact ), repository );
throw e;
}
}
}
}
private void doCacheFailure( String path, ProxyRepository repository )
{
if ( repository.isCacheFailures() )
{
String key = repository.getKey();
if ( !failuresCache.containsKey( key ) )
{
failuresCache.put( key, new ArrayList() );
}
List failureCache = (List) failuresCache.get( key );
if ( !failureCache.contains( path ) )
{
failureCache.add( path );
}
}
}
private boolean checkIfFailureCached( String path, ProxyRepository repository )
{
boolean pathAlreadyFailed = false;
if ( repository.isCacheFailures() )
{
String key = repository.getKey();
if ( failuresCache.containsKey( key ) )
{
List failureCache = (List) failuresCache.get( key );
if ( failureCache.contains( path ) )
{
pathAlreadyFailed = true;
}
}
}
return pathAlreadyFailed;
}
private ArtifactRepositoryLayout getLayout()
throws ProxyException
{
String configLayout = config.getLayout();
if ( !repositoryLayoutMap.containsKey( configLayout ) )
{
throw new ProxyException( "Unable to find a proxy repository layout for " + configLayout );
}
return (ArtifactRepositoryLayout) repositoryLayoutMap.get( configLayout );
}
private ArtifactRepository getRepositoryCache()
throws ProxyException
{
return repositoryFactory.createArtifactRepository( "local-cache", getRepositoryCacheURL().toString(),
getLayout(), getSnapshotsPolicy(), getReleasesPolicy() );
}
private ArtifactRepositoryPolicy getReleasesPolicy()
{
return config.getCacheReleasePolicy();
}
private ArtifactRepositoryPolicy getSnapshotsPolicy()
{
return config.getCacheSnapshotPolicy();
}
public URL getRepositoryCacheURL()
throws ProxyException
{
URL url;
try
{
url = new File( config.getRepositoryCachePath() ).toURL();
}
catch ( MalformedURLException e )
{
throw new ProxyException( "Unable to create cache URL from: " + config.getRepositoryCachePath(), e );
}
return url;
}
/**
* Used to retrieve a remote file from the remote repositories. This method is used only when the requested
* path cannot be resolved into a repository object, for example, an Artifact.
*
* @param path the remote path to use to search for the requested file
* @param repositories the list of repositories to retrieve the file from
* @return File object representing the remote file in the repository cache
* @throws ResourceDoesNotExistException when the requested path cannot be found in any of the configured
* repositories.
* @throws ProxyException when an error occurred during the retrieval of the requested path
*/
private File getRepositoryFile( String path, List repositories )
throws ResourceDoesNotExistException, ProxyException
{
return getRepositoryFile( path, repositories, true );
}
/**
* Used to retrieve a remote file from the remote repositories. This method is used only when the requested
* path cannot be resolved into a repository object, for example, an Artifact.
*
* @param path the remote path to use to search for the requested file
* @param repositories the list of repositories to retrieve the file from
* @param useChecksum forces the download to whether use a checksum (if present in the remote repository) or not
* @return File object representing the remote file in the repository cache
* @throws ResourceDoesNotExistException when the requested path cannot be found in any of the configured
* repositories.
* @throws ProxyException when an error occurred during the retrieval of the requested path
*/
private File getRepositoryFile( String path, List repositories, boolean useChecksum )
throws ResourceDoesNotExistException, ProxyException
{
ArtifactRepository cache = getRepositoryCache();
File target = new File( cache.getBasedir(), path );
for ( Iterator repos = repositories.iterator(); repos.hasNext(); )
{
ProxyRepository repository = (ProxyRepository) repos.next();
if ( checkIfFailureCached( path, repository ) )
{
getLogger().debug( "Skipping repository " + repository.getKey() + " for a cached path failure." );
}
else
{
getFromRepository( target, path, repository, useChecksum );
}
}
if ( !target.exists() )
{
throw new ResourceDoesNotExistException( "Could not find " + path + " in any of the repositories." );
}
return target;
}
private void getFromRepository( File target, String path, ProxyRepository repository, boolean useChecksum )
throws ProxyException
{
boolean connected = false;
Map checksums = null;
Wagon wagon = null;
try
{
wagon = wagonManager.getWagon( repository.getProtocol() );
//@todo configure wagon (ssh settings, etc)
if ( useChecksum )
{
checksums = prepareChecksumListeners( wagon );
}
connected = connectToRepository( wagon, repository );
if ( connected )
{
File temp = new File( target.getAbsolutePath() + ".tmp" );
temp.deleteOnExit();
int tries = 0;
boolean success = true;
do
{
tries++;
getLogger().info( "Trying " + path + " from " + repository.getId() + "..." );
if ( !target.exists() )
{
wagon.get( path, temp );
}
else
{
long repoTimestamp = target.lastModified() + repository.getCachePeriod() * MS_PER_SEC;
wagon.getIfNewer( path, temp, repoTimestamp );
}
if ( useChecksum )
{
success = doChecksumCheck( checksums, path, wagon );
}
if ( tries > 1 && !success )
{
throw new ProxyException( "Checksum failures occurred while downloading " + path );
}
}
while ( !success );
disconnectWagon( wagon );
if ( temp.exists() )
{
moveTempToTarget( temp, target );
}
}
//try next repository
}
catch ( TransferFailedException e )
{
String message = "Skipping repository " + repository.getUrl() + ": " + e.getMessage();
processRepositoryFailure( repository, message, e );
}
catch ( ResourceDoesNotExistException e )
{
doCacheFailure( path, repository );
}
catch ( AuthorizationException e )
{
String message = "Skipping repository " + repository.getUrl() + ": " + e.getMessage();
processRepositoryFailure( repository, message, e );
}
catch ( UnsupportedProtocolException e )
{
String message = "Skipping repository " + repository.getUrl() + ": no wagonManager configured " +
"for protocol " + repository.getProtocol();
processRepositoryFailure( repository, message, e );
}
finally
{
if ( wagon != null && checksums != null )
{
releaseChecksumListeners( wagon, checksums );
}
if ( connected )
{
disconnectWagon( wagon );
}
}
}
/**
* Used to add checksum observers as transfer listeners to the wagonManager object
*
* @param wagon the wagonManager object to use the checksum with
* @return map of ChecksumObservers added into the wagonManager transfer listeners
*/
private Map prepareChecksumListeners( Wagon wagon )
{
Map checksums = new HashMap();
try
{
ChecksumObserver checksum = new ChecksumObserver( "SHA-1" );
wagon.addTransferListener( checksum );
checksums.put( "sha1", checksum );
checksum = new ChecksumObserver( "MD5" );
wagon.addTransferListener( checksum );
checksums.put( "md5", checksum );
}
catch ( NoSuchAlgorithmException e )
{
getLogger().info( "An error occurred while preparing checksum observers", e );
}
return checksums;
}
/**
* Used to remove the ChecksumObservers from the wagonManager object
*
* @param wagon the wagonManager object to remote the ChecksumObservers from
* @param checksumMap the map representing the list of ChecksumObservers added to the wagonManager object
*/
private void releaseChecksumListeners( Wagon wagon, Map checksumMap )
{
for ( Iterator checksums = checksumMap.values().iterator(); checksums.hasNext(); )
{
ChecksumObserver listener = (ChecksumObserver) checksums.next();
wagon.removeTransferListener( listener );
}
}
/**
* Used to request the wagonManager object to connect to a repository
*
* @param wagon the wagonManager object that will be used to connect to the repository
* @param repository the repository object to connect the wagonManager to
* @return true when the wagonManager is able to connect to the repository
*/
private boolean connectToRepository( Wagon wagon, ProxyRepository repository )
{
boolean connected = false;
try
{
if ( repository.isProxied() )
{
wagon.connect( repository, config.getHttpProxy() );
}
else
{
wagon.connect( repository );
}
connected = true;
}
catch ( ConnectionException e )
{
getLogger().info( "Could not connect to " + repository.getId() + ": " + e.getMessage() );
}
catch ( AuthenticationException e )
{
getLogger().info( "Could not connect to " + repository.getId() + ": " + e.getMessage() );
}
return connected;
}
/**
* Used to verify the checksum during a wagonManager download
*
* @param checksumMap the map of ChecksumObservers present in the wagonManager as transferlisteners
* @param path path of the remote object whose checksum is to be verified
* @param wagon the wagonManager object used to download the requested path
* @return true when the checksum succeeds and false when the checksum failed.
*/
private boolean doChecksumCheck( Map checksumMap, String path, Wagon wagon )
throws ProxyException
{
releaseChecksumListeners( wagon, checksumMap );
for ( Iterator checksums = checksumMap.keySet().iterator(); checksums.hasNext(); )
{
String checksumExt = (String) checksums.next();
ChecksumObserver checksum = (ChecksumObserver) checksumMap.get( checksumExt );
String checksumPath = path + "." + checksumExt;
File checksumFile = new File( config.getRepositoryCachePath(), checksumPath );
try
{
File tempChecksumFile = new File( checksumFile.getAbsolutePath() + ".tmp" );
wagon.get( checksumPath, tempChecksumFile );
String remoteChecksum = FileUtils.fileRead( tempChecksumFile ).trim();
if ( remoteChecksum.indexOf( ' ' ) > 0 )
{
remoteChecksum = remoteChecksum.substring( 0, remoteChecksum.indexOf( ' ' ) );
}
boolean checksumCheck = false;
if ( remoteChecksum.toUpperCase().equals( checksum.getActualChecksum().toUpperCase() ) )
{
moveTempToTarget( tempChecksumFile, checksumFile );
checksumCheck = true;
}
return checksumCheck;
}
catch ( ChecksumFailedException e )
{
return false;
}
catch ( TransferFailedException e )
{
getLogger().debug( "An error occurred during the download of " + checksumPath + ": " + e.getMessage(),
e );
// do nothing try the next checksum
}
catch ( ResourceDoesNotExistException e )
{
getLogger().debug( "An error occurred during the download of " + checksumPath + ": " + e.getMessage(),
e );
// do nothing try the next checksum
}
catch ( AuthorizationException e )
{
getLogger().debug( "An error occurred during the download of " + checksumPath + ": " + e.getMessage(),
e );
// do nothing try the next checksum
}
catch ( IOException e )
{
getLogger().debug( "An error occurred while reading the temporary checksum file.", e );
return false;
}
}
getLogger().debug( "Skipping checksum validation for " + path + ": No remote checksums available." );
return true;
}
/**
* Used to ensure that this proxy instance is running with a valid configuration instance.
*
* @throws ProxyException
*/
private void checkConfiguration()
throws ProxyException
{
if ( config == null )
{
throw new ProxyException( "No proxy configuration defined." );
}
}
/**
* Used to move the temporary file to its real destination. This is patterned from the way WagonManager handles
* its downloaded files.
*
* @param temp The completed download file
* @param target The final location of the downloaded file
* @throws ProxyException when the temp file cannot replace the target file
*/
private void moveTempToTarget( File temp, File target )
throws ProxyException
{
if ( target.exists() && !target.delete() )
{
throw new ProxyException( "Unable to overwrite existing target file: " + target.getAbsolutePath() );
}
if ( !temp.renameTo( target ) )
{
getLogger().warn( "Unable to rename tmp file to its final name... resorting to copy command." );
try
{
FileUtils.copyFile( temp, target );
}
catch ( IOException e )
{
throw new ProxyException( "Cannot copy tmp file to its final location", e );
}
finally
{
temp.delete();
}
}
}
/**
* Used to disconnect the wagonManager from its repository
*
* @param wagon the connected wagonManager object
*/
private void disconnectWagon( Wagon wagon )
{
try
{
wagon.disconnect();
}
catch ( ConnectionException e )
{
getLogger().error( "Problem disconnecting from wagonManager - ignoring: " + e.getMessage() );
}
}
/**
* Queries the configuration on how to handle a repository download failure
*
* @param repository the repository object where the failure occurred
* @param message the message/reason for the failure
* @param t the cause for the exception
* @throws ProxyException if hard failure is enabled on the repository causing the failure
*/
private void processRepositoryFailure( ProxyRepository repository, String message, Throwable t )
throws ProxyException
{
if ( repository.isHardfail() )
{
throw new ProxyException(
"An error occurred in hardfailing repository " + repository.getName() + "...\n " + message, t );
}
else
{
getLogger().debug( message, t );
}
}
}

View File

@ -0,0 +1,507 @@
package org.apache.maven.repository.proxy;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.Artifact;
import org.apache.maven.artifact.manager.ChecksumFailedException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.repository.discovery.ArtifactDiscoverer;
import org.apache.maven.repository.discovery.DiscovererException;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.TransferFailedException;
import org.apache.maven.wagon.Wagon;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authorization.AuthorizationException;
import org.apache.maven.wagon.observers.ChecksumObserver;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.repository.Repository;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.FileUtils;
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* An implementation of the proxy handler.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
* @plexus.component
* @todo this currently duplicates a lot of the wagon manager, and doesn't do things like snapshot resolution, etc.
* Should we have a more artifact based one? This will merge metadata so should behave correctly, and it is able to
* correct some limitations of the wagon manager (eg, it can retrieve newer SNAPSHOT files without metadata)
*/
public class DefaultProxyRequestHandler
extends AbstractLogEnabled
implements ProxyRequestHandler
{
/**
* @plexus.requirement role-hint="default"
* @todo use a map, and have priorities in them
*/
private ArtifactDiscoverer defaultArtifactDiscoverer;
/**
* @plexus.requirement role-hint="legacy"
*/
private ArtifactDiscoverer legacyArtifactDiscoverer;
/**
* @plexus.requirement role="org.apache.maven.wagon.Wagon"
*/
private Map/*<String,Wagon>*/ wagons;
public File get( String path, List proxiedRepositories, ArtifactRepository managedRepository )
throws ProxyException, ResourceDoesNotExistException
{
return get( path, proxiedRepositories, managedRepository, null );
}
public File get( String path, List proxiedRepositories, ArtifactRepository managedRepository, ProxyInfo wagonProxy )
throws ProxyException, ResourceDoesNotExistException
{
//@todo use wagonManager for cache use file:// as URL
File cachedFile = new File( managedRepository.getBasedir(), path );
if ( !cachedFile.exists() )
{
cachedFile = getAlways( path, proxiedRepositories, managedRepository, wagonProxy );
}
return cachedFile;
}
public File getAlways( String path, List proxiedRepositories, ArtifactRepository managedRepository )
throws ProxyException, ResourceDoesNotExistException
{
return getAlways( path, proxiedRepositories, managedRepository, null );
}
public File getAlways( String path, List proxiedRepositories, ArtifactRepository managedRepository,
ProxyInfo wagonProxy )
throws ProxyException, ResourceDoesNotExistException
{
File remoteFile = null;
for ( Iterator i = proxiedRepositories.iterator(); i.hasNext(); )
{
ProxiedArtifactRepository repository = (ProxiedArtifactRepository) i.next();
if ( repository.isCachedFailure( path ) )
{
getLogger().debug( "Skipping repository " + repository.getName() + " for a cached path failure." );
}
else
{
if ( path.endsWith( ".md5" ) || path.endsWith( ".sha1" ) )
{
// always read from the managed repository
remoteFile = new File( managedRepository.getBasedir(), path );
}
else if ( path.endsWith( "maven-metadata.xml" ) )
{
remoteFile = getFromRepository( path, repository, managedRepository.getBasedir(), wagonProxy,
repository.getRepository().getReleases() );
}
else
{
Artifact artifact = null;
try
{
artifact = defaultArtifactDiscoverer.buildArtifact( path );
}
catch ( DiscovererException e )
{
getLogger().debug(
"Failed to build artifact using default layout with message: " + e.getMessage() );
}
if ( artifact == null )
{
try
{
artifact = legacyArtifactDiscoverer.buildArtifact( path );
}
catch ( DiscovererException e )
{
getLogger().debug(
"Failed to build artifact using legacy layout with message: " + e.getMessage() );
}
}
if ( artifact != null )
{
getArtifact( artifact, repository, managedRepository, wagonProxy );
remoteFile = artifact.getFile();
}
else
{
// Some other unknown file in the repository, proxy as is
getFromRepository( path, repository, managedRepository.getBasedir(), wagonProxy, null );
}
}
if ( remoteFile != null && !remoteFile.exists() )
{
repository.addFailure( path );
throw new ResourceDoesNotExistException(
"Could not find " + path + " in any of the repositories." );
}
else
{
// in case it previously failed and we've since found it
repository.clearFailure( path );
}
}
}
return remoteFile;
}
private File getFromRepository( String path, ProxiedArtifactRepository repository, String repositoryCachePath,
ProxyInfo httpProxy, ArtifactRepositoryPolicy policy )
throws ProxyException, ResourceDoesNotExistException
{
File target = new File( repositoryCachePath, path );
if ( !target.exists() || isOutOfDate( policy, target ) )
{
boolean connected = false;
Map checksums = null;
Wagon wagon = null;
try
{
String protocol = repository.getRepository().getProtocol();
wagon = (Wagon) wagons.get( protocol );
if ( wagon == null )
{
throw new ProxyException( "Unsupported remote protocol: " + protocol );
}
//@todo configure wagon (ssh settings, etc)
checksums = prepareChecksumListeners( wagon );
connected = connectToRepository( wagon, repository, httpProxy );
if ( connected )
{
File temp = new File( target.getAbsolutePath() + ".tmp" );
temp.deleteOnExit();
int tries = 0;
boolean success;
do
{
tries++;
getLogger().info( "Trying " + path + " from " + repository.getName() + "..." );
if ( !target.exists() )
{
wagon.get( path, temp );
}
else
{
wagon.getIfNewer( path, temp, target.lastModified() );
}
success = doChecksumCheck( checksums, path, wagon, repositoryCachePath );
if ( tries > 1 && !success )
{
throw new ProxyException( "Checksum failures occurred while downloading " + path );
}
}
while ( !success );
disconnectWagon( wagon );
if ( temp.exists() )
{
moveTempToTarget( temp, target );
}
}
//try next repository
}
catch ( TransferFailedException e )
{
String message = "Skipping repository " + repository.getName() + ": " + e.getMessage();
processRepositoryFailure( repository, message, e );
}
catch ( AuthorizationException e )
{
String message = "Skipping repository " + repository.getName() + ": " + e.getMessage();
processRepositoryFailure( repository, message, e );
}
finally
{
if ( wagon != null && checksums != null )
{
releaseChecksumListeners( wagon, checksums );
}
if ( connected )
{
disconnectWagon( wagon );
}
}
}
return target;
}
private static boolean isOutOfDate( ArtifactRepositoryPolicy policy, File target )
{
return policy != null && policy.checkOutOfDate( new Date( target.lastModified() ) );
}
/**
* Used to add checksum observers as transfer listeners to the wagonManager object
*
* @param wagon the wagonManager object to use the checksum with
* @return map of ChecksumObservers added into the wagonManager transfer listeners
*/
private Map prepareChecksumListeners( Wagon wagon )
{
Map checksums = new HashMap();
try
{
ChecksumObserver checksum = new ChecksumObserver( "SHA-1" );
wagon.addTransferListener( checksum );
checksums.put( "sha1", checksum );
checksum = new ChecksumObserver( "MD5" );
wagon.addTransferListener( checksum );
checksums.put( "md5", checksum );
}
catch ( NoSuchAlgorithmException e )
{
getLogger().info( "An error occurred while preparing checksum observers", e );
}
return checksums;
}
private void releaseChecksumListeners( Wagon wagon, Map checksumMap )
{
for ( Iterator checksums = checksumMap.values().iterator(); checksums.hasNext(); )
{
ChecksumObserver listener = (ChecksumObserver) checksums.next();
wagon.removeTransferListener( listener );
}
}
private boolean connectToRepository( Wagon wagon, ProxiedArtifactRepository repository, ProxyInfo httpProxy )
{
boolean connected = false;
try
{
ArtifactRepository artifactRepository = repository.getRepository();
Repository wagonRepository = new Repository( artifactRepository.getId(), artifactRepository.getUrl() );
if ( repository.isUseNetworkProxy() && httpProxy != null )
{
wagon.connect( wagonRepository, httpProxy );
}
else
{
wagon.connect( wagonRepository );
}
connected = true;
}
catch ( ConnectionException e )
{
getLogger().info( "Could not connect to " + repository.getName() + ": " + e.getMessage() );
}
catch ( AuthenticationException e )
{
getLogger().info( "Could not connect to " + repository.getName() + ": " + e.getMessage() );
}
return connected;
}
private boolean doChecksumCheck( Map checksumMap, String path, Wagon wagon, String repositoryCachePath )
throws ProxyException
{
releaseChecksumListeners( wagon, checksumMap );
for ( Iterator checksums = checksumMap.keySet().iterator(); checksums.hasNext(); )
{
String checksumExt = (String) checksums.next();
ChecksumObserver checksum = (ChecksumObserver) checksumMap.get( checksumExt );
String checksumPath = path + "." + checksumExt;
File checksumFile = new File( repositoryCachePath, checksumPath );
try
{
File tempChecksumFile = new File( checksumFile.getAbsolutePath() + ".tmp" );
wagon.get( checksumPath, tempChecksumFile );
String remoteChecksum = FileUtils.fileRead( tempChecksumFile ).trim();
if ( remoteChecksum.indexOf( ' ' ) > 0 )
{
remoteChecksum = remoteChecksum.substring( 0, remoteChecksum.indexOf( ' ' ) );
}
boolean checksumCheck = false;
if ( remoteChecksum.toUpperCase().equals( checksum.getActualChecksum().toUpperCase() ) )
{
moveTempToTarget( tempChecksumFile, checksumFile );
checksumCheck = true;
}
return checksumCheck;
}
catch ( ChecksumFailedException e )
{
return false;
}
catch ( TransferFailedException e )
{
getLogger().debug( "An error occurred during the download of " + checksumPath + ": " + e.getMessage(),
e );
// do nothing try the next checksum
}
catch ( ResourceDoesNotExistException e )
{
getLogger().debug( "An error occurred during the download of " + checksumPath + ": " + e.getMessage(),
e );
// do nothing try the next checksum
}
catch ( AuthorizationException e )
{
getLogger().debug( "An error occurred during the download of " + checksumPath + ": " + e.getMessage(),
e );
// do nothing try the next checksum
}
catch ( IOException e )
{
getLogger().debug( "An error occurred while reading the temporary checksum file.", e );
return false;
}
}
getLogger().debug( "Skipping checksum validation for " + path + ": No remote checksums available." );
return true;
}
/**
* Used to move the temporary file to its real destination. This is patterned from the way WagonManager handles
* its downloaded files.
*
* @param temp The completed download file
* @param target The final location of the downloaded file
* @throws ProxyException when the temp file cannot replace the target file
*/
private void moveTempToTarget( File temp, File target )
throws ProxyException
{
if ( target.exists() && !target.delete() )
{
throw new ProxyException( "Unable to overwrite existing target file: " + target.getAbsolutePath() );
}
if ( !temp.renameTo( target ) )
{
getLogger().warn( "Unable to rename tmp file to its final name... resorting to copy command." );
try
{
FileUtils.copyFile( temp, target );
}
catch ( IOException e )
{
throw new ProxyException( "Cannot copy tmp file to its final location", e );
}
finally
{
temp.delete();
}
}
}
/**
* Used to disconnect the wagonManager from its repository
*
* @param wagon the connected wagonManager object
*/
private void disconnectWagon( Wagon wagon )
{
try
{
wagon.disconnect();
}
catch ( ConnectionException e )
{
getLogger().error( "Problem disconnecting from wagonManager - ignoring: " + e.getMessage() );
}
}
/**
* Queries the configuration on how to handle a repository download failure
*
* @param repository the repository object where the failure occurred
* @param message the message/reason for the failure
* @param t the cause for the exception
* @throws ProxyException if hard failure is enabled on the repository causing the failure
*/
private void processRepositoryFailure( ProxiedArtifactRepository repository, String message, Throwable t )
throws ProxyException
{
if ( repository.isHardFail() )
{
throw new ProxyException(
"An error occurred in hardfailing repository " + repository.getName() + "...\n " + message, t );
}
else
{
getLogger().error( message, t );
}
}
private void getArtifact( Artifact artifact, ProxiedArtifactRepository repository, ArtifactRepository repoCache,
ProxyInfo httpProxy )
throws ProxyException, ResourceDoesNotExistException
{
ArtifactRepository artifactRepository = repository.getRepository();
ArtifactRepositoryPolicy policy =
artifact.isSnapshot() ? artifactRepository.getSnapshots() : artifactRepository.getReleases();
if ( !policy.isEnabled() )
{
getLogger().debug( "Skipping disabled repository " + repository.getName() );
}
else
{
getLogger().debug( "Trying repository " + repository.getName() );
// Don't use releases policy, we don't want to perform updates on them (only metadata, as used above)
getFromRepository( artifactRepository.pathOf( artifact ), repository, repoCache.getBasedir(), httpProxy,
artifact.isSnapshot() ? artifactRepository.getSnapshots() : null );
getLogger().debug( " Artifact resolved" );
artifact.setResolved( true );
}
}
}

View File

@ -0,0 +1,107 @@
package org.apache.maven.repository.proxy;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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 java.util.HashSet;
import java.util.Set;
/**
* A proxied artifact repository - contains the artifact repository and additional information about
* the proxied repository.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public class ProxiedArtifactRepository
{
/**
* Whether to cache failures or not.
*/
private boolean cacheFailures;
/**
* Whether failures on this repository cause the whole group to fail.
*/
private boolean hardFail;
/**
* Whether to use the network proxy for any requests.
*/
private boolean useNetworkProxy;
/**
* The artifact repository on the other end of the proxy.
*/
private ArtifactRepository repository;
/**
* Cache of failures that have already occurred, containing paths from the repository root.
*/
private Set/*<String>*/ failureCache = new HashSet/*<String>*/();
/**
* A user friendly name for the repository.
*/
private String name;
public boolean isHardFail()
{
return hardFail;
}
public boolean isUseNetworkProxy()
{
return useNetworkProxy;
}
public boolean isCacheFailures()
{
return cacheFailures;
}
public ArtifactRepository getRepository()
{
return repository;
}
public boolean isCachedFailure( String path )
{
return cacheFailures && failureCache.contains( path );
}
public void addFailure( String path )
{
if ( cacheFailures )
{
failureCache.add( path );
}
}
public void clearFailure( String path )
{
if ( cacheFailures )
{
failureCache.remove( path );
}
}
public String getName()
{
return name;
}
}

View File

@ -0,0 +1,101 @@
package org.apache.maven.repository.proxy;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.ResourceDoesNotExistException;
import org.apache.maven.wagon.proxy.ProxyInfo;
import java.io.File;
import java.util.List;
/**
* An individual request handler for the proxy.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public interface ProxyRequestHandler
{
/**
* The Plexus role of the component.
*/
String ROLE = ProxyRequestHandler.class.getName();
/**
* Used to retrieve an artifact at a particular path, giving the cached version if it exists.
*
* @param path the expected repository path
* @param proxiedRepositories the repositories being proxied to
* @param managedRepository the locally managed repository to cache artifacts in
* @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, List proxiedRepositories, ArtifactRepository managedRepository )
throws ProxyException, ResourceDoesNotExistException;
/**
* Used to retrieve an artifact at a particular path, giving the cached version if it exists.
*
* @param path the expected repository path
* @param proxiedRepositories the repositories being proxied to
* @param managedRepository the locally managed repository to cache artifacts in
* @param wagonProxy a network proxy to use when transferring files if needed
* @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, List proxiedRepositories, ArtifactRepository managedRepository, ProxyInfo wagonProxy )
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
* @param proxiedRepositories the repositories being proxied to
* @param managedRepository the locally managed repository to cache artifacts in
* @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 getAlways( String path, List proxiedRepositories, ArtifactRepository managedRepository )
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
* @param proxiedRepositories the repositories being proxied to
* @param managedRepository the locally managed repository to cache artifacts in
* @param wagonProxy a network proxy to use when transferring files if needed
* @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 getAlways( String path, List proxiedRepositories, ArtifactRepository managedRepository, ProxyInfo wagonProxy )
throws ProxyException, ResourceDoesNotExistException;
}

View File

@ -1,221 +0,0 @@
package org.apache.maven.repository.proxy.configuration;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.ArtifactRepositoryPolicy;
import org.apache.maven.repository.proxy.repository.ProxyRepository;
import org.apache.maven.wagon.proxy.ProxyInfo;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Class to represent the configuration file for the proxy
*
* @author Edwin Punzalan
*/
public class ProxyConfiguration
{
private List repositories = new ArrayList();
private String cachePath;
private String layout;
private ProxyInfo httpProxy;
private ArtifactRepositoryPolicy cacheReleasePolicy;
private ArtifactRepositoryPolicy cacheSnapshotPolicy;
/**
* Used to set the location where the proxy should cache the configured repositories
*
* @param path
*/
public void setRepositoryCachePath( String path )
{
cachePath = new File( path ).getAbsolutePath();
}
/**
* Used to retrieved the absolute path of the repository cache
*
* @return path to the proxy cache
*/
public String getRepositoryCachePath()
{
return cachePath;
}
public void setHttpProxy( ProxyInfo httpProxy )
{
this.httpProxy = httpProxy;
}
public void setHttpProxy( String host, int port )
{
ProxyInfo proxyInfo = new ProxyInfo();
proxyInfo.setHost( host );
proxyInfo.setPort( port );
httpProxy = proxyInfo;
}
public void setHttpProxy( String host, int port, String username, String password )
{
setHttpProxy( host, port );
httpProxy.setUserName( username );
httpProxy.setPassword( password );
}
public void setHttpProxy( String host, int port, String username, String password, String ntlmHost,
String ntlmDomain )
{
setHttpProxy( host, port );
httpProxy.setUserName( username );
httpProxy.setPassword( password );
httpProxy.setNtlmHost( ntlmHost );
httpProxy.setNtlmDomain( ntlmDomain );
}
public ProxyInfo getHttpProxy()
{
return httpProxy;
}
/**
* Used to add proxied repositories.
*
* @param repository the repository to be proxied
*/
public void addRepository( ProxyRepository repository )
{
repositories.add( repository );
}
/**
* Used to retrieve an unmodifyable list of proxied repositories. They returned list determines the search sequence
* for retrieving artifacts.
*
* @return a list of ProxyRepository objects representing proxied repositories
*/
public List getRepositories()
{
return Collections.unmodifiableList( repositories );
}
/**
* Used to set the list of repositories to be proxied. This replaces any repositories already added to this
* configuraion instance. Useful for re-arranging an existing proxied list.
*
* @param repositories
*/
public void setRepositories( List repositories )
{
this.repositories = repositories;
}
public String getLayout()
{
if ( layout == null )
{
layout = "default";
}
return layout;
}
public void setLayout( String layout )
{
this.layout = layout;
}
public void validate()
throws ValidationException
{
validateRemoteRepo();
validateDirectories();
}
private void validateRemoteRepo()
throws ValidationException
{
//Verify remote repository set
//only warn if missing
if ( getRepositories().size() < 1 )
{
throw new ValidationException( "At least one remote repository must be configured." );
}
}
private void validateDirectories()
throws ValidationException
{
File f = new File( cachePath );
if ( !f.exists() )
{
throw new ValidationException( "Specified directory does not exist: " + f.getAbsolutePath() );
}
for ( Iterator repos = getRepositories().iterator(); repos.hasNext(); )
{
ProxyRepository repo = (ProxyRepository) repos.next();
if ( repo.getUrl().startsWith( "file://" ) )
{
File f2 = new File( repo.getBasedir() );
if ( !f2.exists() )
{
throw new ValidationException( "Specified directory does not exist: " + f2.getAbsolutePath() );
}
}
}
}
public ArtifactRepositoryPolicy getCacheReleasePolicy()
{
if ( cacheReleasePolicy == null )
{
cacheReleasePolicy = new ArtifactRepositoryPolicy();
}
return cacheReleasePolicy;
}
public void setCacheReleasePolicy( ArtifactRepositoryPolicy cacheReleasePolicy )
{
this.cacheReleasePolicy = cacheReleasePolicy;
}
public ArtifactRepositoryPolicy getCacheSnapshotPolicy()
{
if ( cacheSnapshotPolicy == null )
{
cacheSnapshotPolicy = new ArtifactRepositoryPolicy();
}
return cacheSnapshotPolicy;
}
public void setCacheSnapshotPolicy( ArtifactRepositoryPolicy cacheSnapshotPolicy )
{
this.cacheSnapshotPolicy = cacheSnapshotPolicy;
}
}

View File

@ -1,40 +0,0 @@
package org.apache.maven.repository.proxy.configuration;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.
*/
/**
* @author Ben Walding
*/
public class ValidationException
extends Exception
{
/**
* @param
*/
public ValidationException( String msg )
{
super( msg );
}
/**
* @param t
*/
public ValidationException( Throwable t )
{
super( t );
}
}

View File

@ -1,105 +0,0 @@
package org.apache.maven.repository.proxy.repository;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.DefaultArtifactRepository;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
/**
* Class to represent the Proxy repository. Currently does not provide additional methods from
* DefaultArtifactRepository but is expected to do so like enabled/disabled when a UI is present.
*
* @author Edwin Punzalan
*/
public class ProxyRepository
extends DefaultArtifactRepository
{
// zero caches forever
private long cachePeriod;
private boolean cacheFailures;
private boolean hardfail = true;
private boolean proxied;
public ProxyRepository( String id, String url, ArtifactRepositoryLayout layout, boolean cacheFailures,
long cachePeriod )
{
this( id, url, layout );
this.cacheFailures = cacheFailures;
this.cachePeriod = cachePeriod;
}
public ProxyRepository( String id, String url, ArtifactRepositoryLayout layout )
{
super( id, url, layout );
}
public long getCachePeriod()
{
return cachePeriod;
}
public void setCachePeriod( long cachePeriod )
{
this.cachePeriod = cachePeriod;
}
public boolean isCacheFailures()
{
return cacheFailures;
}
public void setCacheFailures( boolean cacheFailures )
{
this.cacheFailures = cacheFailures;
}
public boolean isProxied()
{
return proxied;
}
public void setProxied( boolean proxied )
{
this.proxied = proxied;
}
/**
* Checks the repository hardfail setting.
*
* @return true if the hardfail is enabled, otherwise, returns false.
*/
public boolean isHardfail()
{
return hardfail;
}
/**
* If hardfail is set to true, then any unexpected errors from retrieving files from this repository
* will cause the download to fail.
*
* @param hardfail set to true to enable hard failures
*/
public void setHardfail( boolean hardfail )
{
this.hardfail = hardfail;
}
}

View File

@ -1,154 +0,0 @@
package org.apache.maven.repository.proxy;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.layout.ArtifactRepositoryLayout;
import org.apache.maven.artifact.repository.layout.LegacyRepositoryLayout;
import org.apache.maven.repository.proxy.configuration.ProxyConfiguration;
import org.apache.maven.repository.proxy.repository.ProxyRepository;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import java.io.File;
/**
* @author Edwin Punzalan
*/
public class LegacyProxyManagerTest
extends PlexusTestCase
{
private ProxyManager proxy;
private ProxyConfiguration configuration;
protected void setUp()
throws Exception
{
super.setUp();
proxy = (ProxyManager) container.lookup( ProxyManager.ROLE );
configuration = getProxyConfiguration();
proxy.setConfiguration( configuration );
}
public void testExceptions()
{
proxy.setConfiguration( null );
try
{
proxy.get( "/invalid" );
fail( "Expected empty configuration error." );
}
catch ( ProxyException e )
{
assertEquals( "Expected Exception not thrown.", "No proxy configuration defined.", e.getMessage() );
}
catch ( ResourceDoesNotExistException e )
{
fail( "Expected Exception not thrown." );
}
}
public void testArtifactDownload()
throws Exception
{
//test download
File file = proxy.get( "/commons-logging/jars/commons-logging-1.0.jar" );
assertTrue( "File must be downloaded: " + file.getAbsolutePath(), file.exists() );
assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) );
//test cache
proxy.get( "/commons-logging/jars/commons-logging-1.0.jar" );
try
{
proxy.get( "/commons-logging/jars/commons-logging-2.0.jar" );
fail( "Expected ResourceDoesNotExistException exception not thrown" );
}
catch ( ResourceDoesNotExistException e )
{
assertTrue( true );
}
}
public void testArtifactChecksum()
throws Exception
{
//force the downlod from the remote repository, use getAlways()
File file = proxy.getAlways( "/commons-logging/jars/commons-logging-1.0.jar.md5" );
assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) );
}
public void testNonArtifactWithNoChecksum()
throws Exception
{
File file = proxy.get( "/not-standard/repository/file.txt" );
assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) );
}
public void testNonArtifactWithMD5Checksum()
throws Exception
{
File file = proxy.get( "/checksumed-md5/repository/file.txt" );
assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) );
}
public void testNonArtifactWithSHA1Checksum()
throws Exception
{
File file = proxy.get( "/checksumed-sha1/repository/file.txt" );
assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) );
}
protected void tearDown()
throws Exception
{
container.release( proxy );
super.tearDown();
}
private ProxyConfiguration getProxyConfiguration()
throws ComponentLookupException
{
ProxyConfiguration config = new ProxyConfiguration();
config.setRepositoryCachePath( getTestFile( "target/m1-proxy-cache" ).getAbsolutePath() );
ArtifactRepositoryLayout layout = new LegacyRepositoryLayout();
File repo1File = getTestFile( "src/test/m1-remote-repo" );
ProxyRepository repo1 = new ProxyRepository( "m1-test-repo", "file://" + repo1File.getAbsolutePath(), layout );
config.addRepository( repo1 );
return config;
}
}

View File

@ -16,71 +16,46 @@ package org.apache.maven.repository.proxy;
* limitations under the License. * limitations under the License.
*/ */
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
import org.apache.maven.repository.proxy.configuration.ProxyConfiguration;
import org.apache.maven.repository.proxy.repository.ProxyRepository;
import org.apache.maven.wagon.ResourceDoesNotExistException; import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.codehaus.plexus.PlexusTestCase; import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import java.io.File; import java.io.File;
/** /**
* @author Edwin Punzalan * @author Edwin Punzalan
*/ */
public class DefaultProxyManagerTest public class ProxyRequestHandlerTest
extends PlexusTestCase extends PlexusTestCase
{ {
private ProxyManager proxy; private ProxyRequestHandler requestHandler;
private ProxyConfiguration configuration; public void testdummy(){}
/* TODO!
protected void setUp() protected void setUp()
throws Exception throws Exception
{ {
super.setUp(); super.setUp();
proxy = (ProxyManager) container.lookup( ProxyManager.ROLE ); requestHandler = (ProxyRequestHandler) container.lookup( ProxyRequestHandler.ROLE );
configuration = getProxyConfiguration();
proxy.setConfiguration( configuration );
}
public void testExceptions()
{
proxy.setConfiguration( null );
try
{
proxy.get( "/invalid" );
fail( "Expected empty configuration error." );
}
catch ( ProxyException e )
{
assertEquals( "Expected Exception not thrown.", "No proxy configuration defined.", e.getMessage() );
}
catch ( ResourceDoesNotExistException e )
{
fail( "Expected Exception not thrown." );
}
} }
public void testArtifactDownload() public void testArtifactDownload()
throws Exception throws Exception
{ {
//test download //test download
File file = proxy.get( "/commons-logging/commons-logging/1.0/commons-logging-1.0.jar" ); String s = "/commons-logging/commons-logging/1.0/commons-logging-1.0.jar";
File file = get( s );
assertTrue( "File must be downloaded.", file.exists() ); assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.", assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) );
//test cache //test cache
proxy.get( "/commons-logging/commons-logging/1.0/commons-logging-1.0.jar" ); get( "/commons-logging/commons-logging/1.0/commons-logging-1.0.jar" );
try try
{ {
proxy.get( "/commons-logging/commons-logging/2.0/commons-logging-2.0.jar" ); get( "/commons-logging/commons-logging/2.0/commons-logging-2.0.jar" );
fail( "Expected ResourceDoesNotExistException exception not thrown" ); fail( "Expected ResourceDoesNotExistException exception not thrown" );
} }
catch ( ResourceDoesNotExistException e ) catch ( ResourceDoesNotExistException e )
@ -89,49 +64,47 @@ public class DefaultProxyManagerTest
} }
} }
private File get( String s )
throws ProxyException, ResourceDoesNotExistException
{
return requestHandler.get( s, proxiedRepositories, managedRepository );
}
public void testArtifactChecksum() public void testArtifactChecksum()
throws Exception throws Exception
{ {
//force the downlod from the remote repository, use getAlways() //force the downlod from the remote repository, use getAlways()
File file = proxy.getAlways( "/commons-logging/commons-logging/1.0/commons-logging-1.0.jar.md5" ); File file = requestHandler.getAlways( "/commons-logging/commons-logging/1.0/commons-logging-1.0.jar.md5" );
assertTrue( "File must be downloaded.", file.exists() ); assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.", assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) );
} }
public void testNonArtifactWithNoChecksum() public void testNonArtifactWithNoChecksum()
throws Exception throws Exception
{ {
File file = proxy.get( "/not-standard/repository/file.txt" ); File file = get( "/not-standard/repository/file.txt" );
assertTrue( "File must be downloaded.", file.exists() ); assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.", assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) );
} }
public void testNonArtifactWithMD5Checksum() public void testNonArtifactWithMD5Checksum()
throws Exception throws Exception
{ {
File file = proxy.get( "/checksumed-md5/repository/file.txt" ); File file = get( "/checksumed-md5/repository/file.txt" );
assertTrue( "File must be downloaded.", file.exists() ); assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.", assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) );
} }
public void testNonArtifactWithSHA1Checksum() public void testNonArtifactWithSHA1Checksum()
throws Exception throws Exception
{ {
File file = proxy.get( "/checksumed-sha1/repository/file.txt" ); File file = get( "/checksumed-sha1/repository/file.txt" );
assertTrue( "File must be downloaded.", file.exists() ); assertTrue( "File must be downloaded.", file.exists() );
assertTrue( "Downloaded file should be present in the cache.", assertTrue( "Downloaded file should be present in the cache.",
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) );
}
protected void tearDown()
throws Exception
{
container.release( proxy );
super.tearDown();
} }
private ProxyConfiguration getProxyConfiguration() private ProxyConfiguration getProxyConfiguration()
@ -139,7 +112,7 @@ public class DefaultProxyManagerTest
{ {
ProxyConfiguration config = new ProxyConfiguration(); ProxyConfiguration config = new ProxyConfiguration();
config.setRepositoryCachePath( "target/proxy-cache" ); config.setRepositoryCachePath( "target/requestHandler-cache" );
ArtifactRepositoryLayout defLayout = new DefaultRepositoryLayout(); ArtifactRepositoryLayout defLayout = new DefaultRepositoryLayout();
@ -151,4 +124,5 @@ public class DefaultProxyManagerTest
return config; return config;
} }
*/
} }

View File

@ -1,86 +0,0 @@
package org.apache.maven.repository.proxy.configuration;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.repository.proxy.repository.ProxyRepository;
import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.util.FileUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* @author Edwin Punzalan
*/
public class MavenProxyPropertyLoaderTest
extends PlexusTestCase
{
private static final int DEFAULT_CACHE_PERIOD = 3600;
public void testLoadValidMavenProxyConfiguration()
throws ValidationException, IOException
{
MavenProxyPropertyLoader loader = new MavenProxyPropertyLoader();
//must create the test directory bec configuration is using relative path which varies
FileUtils.mkdir( "target/remote-repo1" );
try
{
File confFile = getTestFile( "src/test/conf/maven-proxy-complete.conf" );
ProxyConfiguration config = loader.load( new FileInputStream( confFile ) );
assertTrue( "cache path changed", config.getRepositoryCachePath().endsWith( "target" ) );
assertEquals( "Count repositories", 4, config.getRepositories().size() );
ProxyRepository repo = (ProxyRepository) config.getRepositories().get( 0 );
assertEquals( "Repository name not as expected", "local-repo", repo.getKey() );
assertEquals( "Repository url does not match its name", "file://target", repo.getUrl() );
assertEquals( "Repository cache period check failed", 0, repo.getCachePeriod() );
assertFalse( "Repository failure caching check failed", repo.isCacheFailures() );
repo = (ProxyRepository) config.getRepositories().get( 1 );
assertEquals( "Repository name not as expected", "www-ibiblio-org", repo.getKey() );
assertEquals( "Repository url does not match its name", "http://www.ibiblio.org/maven2", repo.getUrl() );
assertEquals( "Repository cache period check failed", DEFAULT_CACHE_PERIOD, repo.getCachePeriod() );
assertTrue( "Repository failure caching check failed", repo.isCacheFailures() );
repo = (ProxyRepository) config.getRepositories().get( 2 );
assertEquals( "Repository name not as expected", "dist-codehaus-org", repo.getKey() );
assertEquals( "Repository url does not match its name", "http://dist.codehaus.org", repo.getUrl() );
assertEquals( "Repository cache period check failed", DEFAULT_CACHE_PERIOD, repo.getCachePeriod() );
assertTrue( "Repository failure caching check failed", repo.isCacheFailures() );
repo = (ProxyRepository) config.getRepositories().get( 3 );
assertEquals( "Repository name not as expected", "private-example-com", repo.getKey() );
assertEquals( "Repository url does not match its name", "http://private.example.com/internal",
repo.getUrl() );
assertEquals( "Repository cache period check failed", DEFAULT_CACHE_PERIOD, repo.getCachePeriod() );
assertFalse( "Repository failure caching check failed", repo.isCacheFailures() );
}
finally
{
//make sure to delete the test directory after tests
FileUtils.deleteDirectory( "target/remote-repo1" );
}
}
}

View File

@ -1,137 +0,0 @@
package org.apache.maven.repository.proxy.configuration;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.layout.ArtifactRepositoryLayout;
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
import org.apache.maven.artifact.repository.layout.LegacyRepositoryLayout;
import org.apache.maven.repository.proxy.repository.ProxyRepository;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.codehaus.plexus.PlexusTestCase;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class ProxyConfigurationTest
extends PlexusTestCase
{
private ProxyConfiguration config;
private static final int DEFAULT_CACHE_PERIOD = 3600;
private static final int DEFAULT_PORT = 80;
protected void setUp()
throws Exception
{
super.setUp();
config = new ProxyConfiguration();
}
public void testRepositoryCache()
{
File cacheFile = new File( "target/proxy-cache" );
config.setRepositoryCachePath( cacheFile.getAbsolutePath() );
assertEquals( config.getRepositoryCachePath(), cacheFile.getAbsolutePath() );
}
public void testRepositories()
{
ArtifactRepositoryLayout defLayout = new DefaultRepositoryLayout();
ProxyRepository repo1 = new ProxyRepository( "repo1", "http://www.ibiblio.org/maven2", defLayout );
repo1.setCacheFailures( true );
repo1.setCachePeriod( 0 );
repo1.setHardfail( true );
config.addRepository( repo1 );
assertEquals( 1, config.getRepositories().size() );
ArtifactRepositoryLayout legacyLayout = new LegacyRepositoryLayout();
ProxyRepository repo2 = new ProxyRepository( "repo2", "http://www.ibiblio.org/maven", legacyLayout );
repo2.setCacheFailures( false );
repo2.setCachePeriod( DEFAULT_CACHE_PERIOD );
repo2.setProxied( true );
config.setHttpProxy( "some.local.proxy", DEFAULT_PORT, "username", "password" );
config.addRepository( repo2 );
assertEquals( 2, config.getRepositories().size() );
List repositories = config.getRepositories();
ProxyRepository repo = (ProxyRepository) repositories.get( 0 );
assertEquals( "repo1", repo.getId() );
assertEquals( "http://www.ibiblio.org/maven2", repo.getUrl() );
assertTrue( repo.isCacheFailures() );
assertTrue( repo.isHardfail() );
assertEquals( 0, repo.getCachePeriod() );
assertEquals( repo1, repo );
repo = (ProxyRepository) repositories.get( 1 );
assertEquals( "repo2", repo.getId() );
assertEquals( "http://www.ibiblio.org/maven", repo.getUrl() );
assertFalse( repo.isCacheFailures() );
assertTrue( repo.isHardfail() );
assertEquals( DEFAULT_CACHE_PERIOD, repo.getCachePeriod() );
assertEquals( repo2, repo );
assertTrue( repo.isProxied() );
ProxyInfo proxyInfo = config.getHttpProxy();
assertNotNull( proxyInfo );
assertEquals( "some.local.proxy", proxyInfo.getHost() );
assertEquals( DEFAULT_PORT, proxyInfo.getPort() );
assertEquals( "username", proxyInfo.getUserName() );
assertEquals( "password", proxyInfo.getPassword() );
try
{
repositories.add( new ProxyRepository( "repo", "url", defLayout ) );
fail( "Expected UnsupportedOperationException not thrown." );
}
catch ( UnsupportedOperationException e )
{
assertTrue( true );
}
repositories = new ArrayList();
repositories.add( repo1 );
repositories.add( repo2 );
config.setRepositories( repositories );
assertEquals( repositories, config.getRepositories() );
}
public void testHttpProxy()
throws Exception
{
config.setHttpProxy( "some.local.proxy", DEFAULT_PORT, "username", "password", "ntlmHost", "ntlmDomain" );
ProxyInfo proxyInfo = config.getHttpProxy();
assertEquals( "test proxy host", proxyInfo.getHost(), "some.local.proxy" );
assertEquals( DEFAULT_PORT, proxyInfo.getPort() );
assertEquals( "username", proxyInfo.getUserName() );
assertEquals( "password", proxyInfo.getPassword() );
assertEquals( "ntlmHost", proxyInfo.getNtlmHost() );
assertEquals( "ntlmDomain", proxyInfo.getNtlmDomain() );
}
protected void tearDown()
throws Exception
{
config = null;
super.tearDown();
}
}

View File

@ -102,14 +102,6 @@
<build> <build>
<finalName>maven-repository-webapp</finalName> <finalName>maven-repository-webapp</finalName>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- TODO! temporary until tests are fixed -->
<skip>true</skip>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.mortbay.jetty</groupId> <groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId> <artifactId>maven-jetty-plugin</artifactId>
@ -148,17 +140,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-maven-plugin</artifactId> <artifactId>plexus-maven-plugin</artifactId>

View File

@ -1,154 +0,0 @@
package org.apache.maven.repository.proxy.web.action;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.xwork.Action;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.maven.repository.proxy.ProxyException;
import org.apache.maven.repository.proxy.ProxyManager;
import org.apache.maven.repository.proxy.configuration.MavenProxyPropertyLoader;
import org.apache.maven.repository.proxy.configuration.ProxyConfiguration;
import org.apache.maven.repository.proxy.configuration.ValidationException;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
/**
* This is the Action class responsible for processing artifact request,
* relies on the RestfulActionMapper to map the artifact request to this action.
*
* @plexus.component role="com.opensymphony.xwork.Action" role-hint="org.apache.maven.repository.manager.web.action.RepositoryProxyAction"
*/
public class RepositoryProxyAction
implements Action
{
/**
* logger instance
*/
protected static final Log log = LogFactory.getLog( RepositoryProxyAction.class );
public static final String NOTFOUND = "notFound";
public static final String PROXYERROR = "proxyError";
/**
* file requested by the client,
* TODO: validate the requestd file using na interceptor
*/
private String requestedFile;
/**
* main proxy logic
*
* @plexus.requirement role="org.apache.maven.repository.proxy.ProxyManager"
*/
private ProxyManager repositoryProxyManager;
/**
* configuration for the ProxyManager
*
* @plexus.requirement
*/
private ProxyConfiguration proxyConfig;
/**
* the inputstream for the artifact file
*/
private FileInputStream artifactStream;
/**
* the cached artifact file
*/
private File cachedFile;
/**
* proxy configuration file
* TODO: recode the configuration part when Configuration is finalized
* TODO: this is only temporary
*/
private String configFile;
// setters and getters
public void setProxyManager( ProxyManager manager )
{
repositoryProxyManager = manager;
}
public void setRequestedFile( String reqFile )
{
requestedFile = reqFile;
}
public String getRequestedFile()
{
return requestedFile;
}
public FileInputStream getArtifactStream()
{
return artifactStream;
}
public File getCachedFile()
{
return cachedFile;
}
public void setConfigFile( String fileName )
{
configFile = fileName;
}
/**
* entry-point
*/
public String execute()
throws MalformedURLException, IOException, ValidationException
{
try
{
MavenProxyPropertyLoader loader = new MavenProxyPropertyLoader();
proxyConfig = loader.load( new FileInputStream( configFile ) );
repositoryProxyManager.setConfiguration( proxyConfig );
cachedFile = repositoryProxyManager.get( requestedFile );
artifactStream = new FileInputStream( cachedFile );
}
catch ( ResourceDoesNotExistException ex )
{
log.info( "[not found] " + ex.getMessage() );
return NOTFOUND;
}
catch ( ProxyException ex )
{
log.info( "[proxy error] " + ex.getMessage() );
return PROXYERROR;
}
catch ( FileNotFoundException ex )
{
log.info( "[not found] " + ex.getMessage() );
return NOTFOUND;
}
return SUCCESS;
}
}

View File

@ -1,77 +0,0 @@
package org.apache.maven.repository.proxy.web.action.test;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.repository.proxy.web.action.RepositoryProxyAction;
import org.apache.maven.repository.proxy.web.action.test.stub.ProxyManagerStub;
import org.codehaus.plexus.PlexusTestCase;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;
public class RepositoryProxyActionTest
extends PlexusTestCase
{
/**
* test basic proxy operation
*
* @throws Exception
*/
public void testProxy()
throws Exception
{
String testDir = getBasedir() + "/target/test-classes/unit/proxy-test";
RepositoryProxyAction action = new RepositoryProxyAction();
ProxyManagerStub proxyManager = new ProxyManagerStub( testDir );
File cachedFile = proxyManager.get( "dummyFile" );
if ( !cachedFile.getParentFile().exists() )
{
assertTrue( "can not create test file", cachedFile.getParentFile().mkdirs() );
}
if ( !cachedFile.exists() )
{
assertTrue( "can not create test file", cachedFile.createNewFile() );
}
File tmpDir = getTestFile( "target/tmp-repo" );
tmpDir.mkdirs();
// TODO: configure manually, test the property loader elsewhere
Properties properties = new Properties();
properties.load( getClass().getResourceAsStream( "/unit/proxy-test/maven-proxy-complete.conf" ) );
properties.setProperty( "repo.local.store", tmpDir.getAbsolutePath() );
File tempFile = File.createTempFile( "test", "tmp" );
tempFile.deleteOnExit();
properties.store( new FileOutputStream( tempFile ), "" );
action.setConfigFile( tempFile.getAbsolutePath() );
action.setProxyManager( proxyManager );
String result = action.execute();
FileInputStream fileStream = action.getArtifactStream();
assertEquals( "proxy error", action.SUCCESS, result );
assertNotNull( "inputstream not set", fileStream );
assertNotNull( "cached file not set", action.getCachedFile() );
assertTrue( "proxy error", cachedFile.getPath().equals( action.getCachedFile().getPath() ) );
}
}

View File

@ -1,58 +0,0 @@
package org.apache.maven.repository.proxy.web.action.test.stub;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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.repository.proxy.ProxyManager;
import org.apache.maven.repository.proxy.configuration.ProxyConfiguration;
import java.io.File;
public class ProxyManagerStub
implements ProxyManager
{
String baseDir;
public ProxyManagerStub( String base )
{
baseDir = base;
}
public File get( String requestFile )
{
return new File( baseDir, "proxy-cache/test-0.0.jar" );
}
public File getRemoteFile( String reqFile )
{
return new File( baseDir, "proxy-chache/test-0.0.jar" );
}
public void setConfiguration( ProxyConfiguration config )
{
// do nothing
}
public ProxyConfiguration getConfiguration()
{
return null;
}
public File getAlways( String name )
{
return null;
}
}

View File

@ -293,7 +293,7 @@
</reporting> </reporting>
<profiles> <profiles>
<profile> <profile>
<id>ciProfile</id> <id>ci</id>
<activation> <activation>
<property> <property>
<name>enableCiProfile</name> <name>enableCiProfile</name>