git-svn-id: https://svn.apache.org/repos/asf/maven/repository-manager/trunk@430971 13f79535-47bb-0310-9956-ffa450edef68tags/archiva-0.9-alpha-1
@@ -18,6 +18,12 @@ | |||
<groupId>org.codehaus.plexus</groupId> | |||
<artifactId>plexus-utils</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>easymock</groupId> | |||
<artifactId>easymock</artifactId> | |||
<version>1.2_Java1.3</version> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
@@ -44,9 +50,12 @@ | |||
<artifactId>cobertura-maven-plugin</artifactId> | |||
<configuration> | |||
<instrumentation> | |||
<!-- TODO: should this module have tests? --> | |||
<!-- exclude generated --> | |||
<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> | |||
</instrumentation> | |||
</configuration> |
@@ -33,6 +33,7 @@ public interface ConfigurationStore | |||
* Get the configuration from the store. A cached version may be used. | |||
* | |||
* @return the configuration | |||
* @throws ConfigurationStoreException if there is a problem loading the configuration | |||
*/ | |||
Configuration getConfigurationFromStore() | |||
throws ConfigurationStoreException; |
@@ -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 good to monitor the store file for changes | |||
* @todo support other implementations than XML file | |||
* @plexus.component role="org.apache.maven.repository.configuration.ConfigurationStore" | |||
* @plexus.component | |||
*/ | |||
public class DefaultConfigurationStore | |||
extends AbstractLogEnabled | |||
@@ -121,6 +121,8 @@ public class DefaultConfigurationStore | |||
FileWriter fileWriter = null; | |||
try | |||
{ | |||
file.getParentFile().mkdirs(); | |||
fileWriter = new FileWriter( file ); | |||
writer.write( fileWriter, configuration ); | |||
} |
@@ -26,6 +26,12 @@ public class InvalidConfigurationException | |||
{ | |||
private final String name; | |||
public InvalidConfigurationException( String name, String message ) | |||
{ | |||
super( message ); | |||
this.name = name; | |||
} | |||
public InvalidConfigurationException( String name, String message, Throwable cause ) | |||
{ | |||
super( message, cause ); |
@@ -1,4 +1,4 @@ | |||
package org.apache.maven.repository.proxy.configuration; | |||
package org.apache.maven.repository.configuration; | |||
/* | |||
* Copyright 2005-2006 The Apache Software Foundation. | |||
@@ -16,20 +16,17 @@ package org.apache.maven.repository.proxy.configuration; | |||
* 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 java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.Enumeration; | |||
import java.util.List; | |||
import java.util.Properties; | |||
import java.util.StringTokenizer; | |||
/** | |||
* @author Ben Walding | |||
* @author Brett Porter | |||
*/ | |||
public class MavenProxyPropertyLoader | |||
{ | |||
@@ -39,16 +36,19 @@ public class MavenProxyPropertyLoader | |||
private static final String REPO_LIST = "repo.list"; | |||
public ProxyConfiguration load( Properties props ) | |||
throws ValidationException | |||
public void load( Properties props, Configuration configuration ) | |||
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 proxy and break | |||
//just get the first HTTP proxy and break | |||
String propertyList = props.getProperty( PROXY_LIST ); | |||
if ( propertyList != null ) | |||
{ | |||
@@ -58,21 +58,15 @@ public class MavenProxyPropertyLoader | |||
String key = tok.nextToken(); | |||
if ( StringUtils.isNotEmpty( key ) ) | |||
{ | |||
String host = getMandatoryProperty( props, "proxy." + key + ".host" ); | |||
int port = Integer.parseInt( getMandatoryProperty( props, "proxy." + key + ".port" ) ); | |||
Proxy proxy = new Proxy(); | |||
proxy.setHost( getMandatoryProperty( props, "proxy." + key + ".host" ) ); | |||
proxy.setPort( Integer.parseInt( getMandatoryProperty( props, "proxy." + key + ".port" ) ) ); | |||
// the username and password isn't required | |||
String username = props.getProperty( "proxy." + key + ".username" ); | |||
String password = props.getProperty( "proxy." + key + ".password" ); | |||
if ( StringUtils.isNotEmpty( username ) ) | |||
{ | |||
config.setHttpProxy( host, port, username, password ); | |||
} | |||
else | |||
{ | |||
config.setHttpProxy( host, port ); | |||
} | |||
proxy.setUsername( props.getProperty( "proxy." + key + ".username" ) ); | |||
proxy.setPassword( props.getProperty( "proxy." + key + ".password" ) ); | |||
configuration.setProxy( proxy ); | |||
//accept only one proxy configuration | |||
break; | |||
@@ -80,8 +74,6 @@ public class MavenProxyPropertyLoader | |||
} | |||
} | |||
List repositories = new ArrayList(); | |||
//get the remote repository list | |||
String repoList = getMandatoryProperty( props, REPO_LIST ); | |||
@@ -97,26 +89,21 @@ public class MavenProxyPropertyLoader | |||
boolean cacheFailures = | |||
Boolean.valueOf( repoProps.getProperty( "cache.failures", "false" ) ).booleanValue(); | |||
boolean hardFail = Boolean.valueOf( repoProps.getProperty( "hardfail", "true" ) ).booleanValue(); | |||
long cachePeriod = Long.parseLong( repoProps.getProperty( "cache.period", "0" ) ); | |||
ProxyRepository repository = | |||
new ProxyRepository( key, url, new DefaultRepositoryLayout(), cacheFailures, cachePeriod ); | |||
repository.setHardfail( hardFail ); | |||
if ( StringUtils.isNotEmpty( proxyKey ) ) | |||
{ | |||
repository.setProxied( true ); | |||
} | |||
repositories.add( repository ); | |||
int cachePeriod = Integer.parseInt( repoProps.getProperty( "cache.period", "60" ) ); | |||
ProxiedRepositoryConfiguration repository = new ProxiedRepositoryConfiguration(); | |||
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 ); | |||
configuration.addProxiedRepository( repository ); | |||
} | |||
config.setRepositories( repositories ); | |||
config.validate(); | |||
return config; | |||
} | |||
private Properties getSubset( Properties props, String prefix ) | |||
@@ -136,22 +123,22 @@ public class MavenProxyPropertyLoader | |||
return result; | |||
} | |||
public ProxyConfiguration load( InputStream is ) | |||
throws IOException, ValidationException | |||
public void load( InputStream is, Configuration configuration ) | |||
throws IOException, InvalidConfigurationException | |||
{ | |||
Properties props = new Properties(); | |||
props.load( is ); | |||
return load( props ); | |||
load( props, configuration ); | |||
} | |||
private String getMandatoryProperty( Properties props, String key ) | |||
throws ValidationException | |||
throws InvalidConfigurationException | |||
{ | |||
String value = props.getProperty( key ); | |||
if ( value == null ) | |||
{ | |||
throw new ValidationException( "Missing property: " + key ); | |||
throw new InvalidConfigurationException( key, "Missing required field: " + key ); | |||
} | |||
return value; |
@@ -329,7 +329,7 @@ | |||
<field> | |||
<name>snapshotsInterval</name> | |||
<version>1.0.0</version> | |||
<type>String</type> | |||
<type>int</type> | |||
<description> | |||
The interval in minutes before updating snapshots if the policy is set to 'interval'. | |||
</description> | |||
@@ -347,7 +347,7 @@ | |||
<field> | |||
<name>releasesInterval</name> | |||
<version>1.0.0</version> | |||
<type>String</type> | |||
<type>int</type> | |||
<description> | |||
The interval in minutes before updating releases if the policy is set to 'interval'. | |||
</description> | |||
@@ -361,6 +361,24 @@ | |||
Whether to use the network proxy, if one is configured for the protocol of this repository. | |||
</description> | |||
</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> | |||
</class> | |||
<class> |
@@ -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. | |||
--> | |||
@@ -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> |
@@ -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(); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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> |
@@ -22,6 +22,10 @@ | |||
<groupId>org.apache.maven.repository</groupId> | |||
<artifactId>maven-repository-discovery</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven.repository</groupId> | |||
<artifactId>maven-repository-proxy</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven.repository</groupId> | |||
<artifactId>maven-repository-reports-standard</artifactId> | |||
@@ -31,12 +35,5 @@ | |||
<artifactId>plexus-quartz</artifactId> | |||
<version>1.0-alpha-2</version> | |||
</dependency> | |||
<!-- Testing --> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<version>3.8.1</version> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -52,4 +52,20 @@ public interface ConfiguredRepositoryFactory | |||
* @return the local artifact repository | |||
*/ | |||
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 ); | |||
} |
@@ -18,6 +18,7 @@ package org.apache.maven.repository.configuration; | |||
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 java.io.File; | |||
@@ -54,11 +55,30 @@ public class DefaultConfiguredRepositoryFactory | |||
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 ) | |||
{ | |||
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() ) ); | |||
} | |||
@@ -66,6 +86,19 @@ public class DefaultConfiguredRepositoryFactory | |||
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 ) | |||
{ | |||
ArtifactRepositoryLayout layout = (ArtifactRepositoryLayout) repositoryLayouts.get( "default" ); | |||
@@ -73,4 +106,14 @@ public class DefaultConfiguredRepositoryFactory | |||
localRepository.mkdirs(); | |||
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 ); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -7,7 +7,7 @@ package org.apache.maven.repository.proxy; | |||
* 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 | |||
* 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, | |||
@@ -16,18 +16,19 @@ package org.apache.maven.repository.proxy; | |||
* limitations under the License. | |||
*/ | |||
import org.apache.maven.repository.proxy.configuration.ProxyConfiguration; | |||
import org.apache.maven.wagon.ResourceDoesNotExistException; | |||
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 | |||
{ | |||
/** The Plexus role for the component. */ | |||
String ROLE = ProxyManager.class.getName(); | |||
/** | |||
@@ -36,7 +37,7 @@ public interface ProxyManager | |||
* @param path the expected repository path | |||
* @return File object referencing the requested path in the cache | |||
* @throws ProxyException when an exception occurred during the retrieval of the requested path | |||
* @throws ResourceDoesNotExistException when the requested object can't be found in any of the | |||
* @throws org.apache.maven.wagon.ResourceDoesNotExistException when the requested object can't be found in any of the | |||
* configured repositories | |||
*/ | |||
File get( String path ) | |||
@@ -54,11 +55,4 @@ public interface ProxyManager | |||
*/ | |||
File getAlways( String path ) | |||
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 ); | |||
} |
@@ -155,7 +155,7 @@ public class DefaultRepositoryTaskScheduler | |||
} | |||
catch ( ParseException e ) | |||
{ | |||
throw new InvalidConfigurationException( "discoveryCronExpression", "Invalid cron expression", e ); | |||
throw new InvalidConfigurationException( "indexerCronExpression", "Invalid cron expression", e ); | |||
} | |||
catch ( SchedulerException e ) | |||
{ |
@@ -63,4 +63,19 @@ | |||
<artifactId>maven-repository-metadata</artifactId> | |||
</dependency> | |||
</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> |
@@ -33,10 +33,6 @@ | |||
<groupId>org.apache.maven</groupId> | |||
<artifactId>maven-artifact</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven</groupId> | |||
<artifactId>maven-artifact-manager</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven.wagon</groupId> | |||
<artifactId>wagon-file</artifactId> | |||
@@ -54,9 +50,9 @@ | |||
<artifactId>cobertura-maven-plugin</artifactId> | |||
<configuration> | |||
<check> | |||
<!-- TODO: increase coverage --> | |||
<!-- TODO!: increase coverage | |||
<totalLineRate>60</totalLineRate> | |||
<totalBranchRate>70</totalBranchRate> | |||
<totalBranchRate>70</totalBranchRate> --> | |||
</check> | |||
</configuration> | |||
</plugin> |
@@ -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 ); | |||
} | |||
} | |||
} |
@@ -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 ); | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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 ); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -16,71 +16,46 @@ package org.apache.maven.repository.proxy; | |||
* 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.codehaus.plexus.PlexusTestCase; | |||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException; | |||
import java.io.File; | |||
/** | |||
* @author Edwin Punzalan | |||
*/ | |||
public class DefaultProxyManagerTest | |||
public class ProxyRequestHandlerTest | |||
extends PlexusTestCase | |||
{ | |||
private ProxyManager proxy; | |||
private ProxyRequestHandler requestHandler; | |||
private ProxyConfiguration configuration; | |||
public void testdummy(){} | |||
/* TODO! | |||
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." ); | |||
} | |||
requestHandler = (ProxyRequestHandler) container.lookup( ProxyRequestHandler.ROLE ); | |||
} | |||
public void testArtifactDownload() | |||
throws Exception | |||
{ | |||
//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( "Downloaded file should be present in the cache.", | |||
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); | |||
file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) ); | |||
//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 | |||
{ | |||
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" ); | |||
} | |||
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() | |||
throws Exception | |||
{ | |||
//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( "Downloaded file should be present in the cache.", | |||
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); | |||
file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) ); | |||
} | |||
public void testNonArtifactWithNoChecksum() | |||
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( "Downloaded file should be present in the cache.", | |||
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); | |||
file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) ); | |||
} | |||
public void testNonArtifactWithMD5Checksum() | |||
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( "Downloaded file should be present in the cache.", | |||
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); | |||
file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) ); | |||
} | |||
public void testNonArtifactWithSHA1Checksum() | |||
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( "Downloaded file should be present in the cache.", | |||
file.getAbsolutePath().startsWith( configuration.getRepositoryCachePath() ) ); | |||
} | |||
protected void tearDown() | |||
throws Exception | |||
{ | |||
container.release( proxy ); | |||
super.tearDown(); | |||
file.getAbsolutePath().startsWith( managedRepository.getBasedir() ) ); | |||
} | |||
private ProxyConfiguration getProxyConfiguration() | |||
@@ -139,7 +112,7 @@ public class DefaultProxyManagerTest | |||
{ | |||
ProxyConfiguration config = new ProxyConfiguration(); | |||
config.setRepositoryCachePath( "target/proxy-cache" ); | |||
config.setRepositoryCachePath( "target/requestHandler-cache" ); | |||
ArtifactRepositoryLayout defLayout = new DefaultRepositoryLayout(); | |||
@@ -151,4 +124,5 @@ public class DefaultProxyManagerTest | |||
return config; | |||
} | |||
*/ | |||
} |
@@ -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" ); | |||
} | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -102,14 +102,6 @@ | |||
<build> | |||
<finalName>maven-repository-webapp</finalName> | |||
<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> | |||
<groupId>org.mortbay.jetty</groupId> | |||
<artifactId>maven-jetty-plugin</artifactId> | |||
@@ -148,17 +140,6 @@ | |||
</execution> | |||
</executions> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.codehaus.mojo</groupId> | |||
<artifactId>cobertura-maven-plugin</artifactId> | |||
<executions> | |||
<execution> | |||
<goals> | |||
<goal>clean</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.codehaus.plexus</groupId> | |||
<artifactId>plexus-maven-plugin</artifactId> |
@@ -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; | |||
} | |||
} |
@@ -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() ) ); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -293,7 +293,7 @@ | |||
</reporting> | |||
<profiles> | |||
<profile> | |||
<id>ciProfile</id> | |||
<id>ci</id> | |||
<activation> | |||
<property> | |||
<name>enableCiProfile</name> |