You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ma...@apache.org on 2017/05/10 21:05:05 UTC

archiva git commit: Adding check path to remote repositories

Repository: archiva
Updated Branches:
  refs/heads/master 10b408249 -> 1acc6e7b8


Adding check path to remote repositories

Allow to set a check path for connection checks to the remote repositories.
This is useful for repositories that do not allow to browse the base directory.

Improved the fix for MRM-1933


Project: http://git-wip-us.apache.org/repos/asf/archiva/repo
Commit: http://git-wip-us.apache.org/repos/asf/archiva/commit/1acc6e7b
Tree: http://git-wip-us.apache.org/repos/asf/archiva/tree/1acc6e7b
Diff: http://git-wip-us.apache.org/repos/asf/archiva/diff/1acc6e7b

Branch: refs/heads/master
Commit: 1acc6e7b8439b482e611392700f2decaef54b6e6
Parents: 10b4082
Author: Martin Stockhammer <ma...@apache.org>
Authored: Sun May 7 17:26:49 2017 +0200
Committer: Martin Stockhammer <ma...@apache.org>
Committed: Wed May 10 21:39:15 2017 +0200

----------------------------------------------------------------------
 .../archiva-base/archiva-configuration/pom.xml  |   2 +-
 .../DefaultArchivaConfiguration.java            | 107 ++++++++++-
 .../src/main/mdo/configuration.mdo              |  62 ++++++-
 .../archiva/configuration/default-archiva.xml   |  14 +-
 .../configuration/ArchivaConfigurationTest.java |   1 -
 .../admin/model/beans/RemoteRepository.java     |  23 +++
 .../remote/DefaultRemoteRepositoryAdmin.java    |  17 +-
 .../DefaultRemoteRepositoriesService.java       | 182 +++++++------------
 .../org/apache/archiva/i18n/default.properties  |  10 +-
 .../admin/repository/maven2/repositories.js     |   7 +-
 .../js/templates/archiva/repositories.html      |  14 ++
 11 files changed, 312 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-base/archiva-configuration/pom.xml
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-configuration/pom.xml b/archiva-modules/archiva-base/archiva-configuration/pom.xml
index df5a1f2..df2556a 100644
--- a/archiva-modules/archiva-base/archiva-configuration/pom.xml
+++ b/archiva-modules/archiva-base/archiva-configuration/pom.xml
@@ -169,7 +169,7 @@
           </execution>
         </executions>
         <configuration>
-          <version>1.4.1</version>
+          <version>1.4.2</version>
           <models>
             <model>src/main/mdo/configuration.mdo</model>
           </models>

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java
index f37171a..44f2521 100644
--- a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java
+++ b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/DefaultArchivaConfiguration.java
@@ -162,6 +162,9 @@ public class DefaultArchivaConfiguration
 
     private static final String KEY = "org.apache.archiva";
 
+    // Section used for default only configuration
+    private static final String KEY_DEFAULT_ONLY = "org.apache.archiva_default";
+
     @Override
     public Configuration getConfiguration()
     {
@@ -183,6 +186,11 @@ public class DefaultArchivaConfiguration
         return configuration;
     }
 
+    private boolean hasConfigVersionChanged(Configuration current, Registry defaultOnlyConfiguration) {
+        return current==null || current.getVersion()==null ||
+                !current.getVersion().trim().equals(defaultOnlyConfiguration.getString("version","").trim());
+    }
+
     @SuppressWarnings("unchecked")
     private Configuration load()
     {
@@ -200,6 +208,7 @@ public class DefaultArchivaConfiguration
 
         Configuration config = new ConfigurationRegistryReader().read( subset );
 
+
         config.getRepositoryGroups();
         config.getRepositoryGroupsAsMap();
         if ( !config.getRepositories().isEmpty() )
@@ -363,9 +372,63 @@ public class DefaultArchivaConfiguration
             }
         }
 
+
+
         return config;
     }
 
+    /*
+     * Updates the checkpath list for repositories.
+     *
+     * We are replacing existing ones and adding new ones. This allows to update the list with new releases.
+     *
+     * We are also updating existing remote repositories, if they exist already.
+     *
+     * This update method should only be called, if the config version changes to avoid overwriting
+     * user repository settings all the time.
+     */
+    private void updateCheckPathDefaults(Configuration config, Registry defaultConfiguration) {
+        List<RepositoryCheckPath> existingCheckPathList = config.getArchivaDefaultConfiguration().getDefaultCheckPaths();
+        HashMap<String, RepositoryCheckPath> existingCheckPaths = new HashMap<>();
+        HashMap<String, RepositoryCheckPath> newCheckPaths = new HashMap<>();
+        for (RepositoryCheckPath path : config.getArchivaDefaultConfiguration().getDefaultCheckPaths()) {
+            existingCheckPaths.put(path.getUrl(), path);
+        }
+        List defaultCheckPathsSubsets = defaultConfiguration.getSubsetList("archivaDefaultConfiguration.defaultCheckPaths.defaultCheckPath" );
+        for ( Iterator i = defaultCheckPathsSubsets.iterator(); i.hasNext(); )
+        {
+            RepositoryCheckPath v = readRepositoryCheckPath( (Registry) i.next() );
+            if (existingCheckPaths.containsKey(v.getUrl())) {
+                existingCheckPathList.remove(existingCheckPaths.get(v.getUrl()));
+            }
+            existingCheckPathList.add(v);
+            newCheckPaths.put(v.getUrl(), v);
+        }
+        // Remote repositories update
+        for (RemoteRepositoryConfiguration remoteRepositoryConfiguration : config.getRemoteRepositories()) {
+            String url = remoteRepositoryConfiguration.getUrl().toLowerCase();
+            if (newCheckPaths.containsKey(url)) {
+                String currentPath = remoteRepositoryConfiguration.getCheckPath();
+                String newPath = newCheckPaths.get(url).getPath();
+                log.info("Updating connection check path for repository {}, from '{}' to '{}'.", remoteRepositoryConfiguration.getId(),
+                        currentPath, newPath);
+                remoteRepositoryConfiguration.setCheckPath(newPath);
+            }
+        }
+    }
+
+    private RepositoryCheckPath readRepositoryCheckPath( Registry registry )
+    {
+        RepositoryCheckPath value = new RepositoryCheckPath();
+
+        String url = registry.getString( "url", value.getUrl() );
+
+        value.setUrl( url );
+        String path = registry.getString( "path", value.getPath() );
+        value.setPath( path );
+        return value;
+    }
+
     private Policy findPolicy( String policyId )
     {
         if ( MapUtils.isEmpty( prePolicies ) )
@@ -439,6 +502,25 @@ public class DefaultArchivaConfiguration
         return registry.getSubset( KEY );
     }
 
+    /*
+     * Reads the default only configuration into a special prefix. This allows to check for changes
+     * of the default configuration.
+     */
+    private Registry readDefaultOnlyConfiguration()
+    {
+        registry.removeSubset(KEY_DEFAULT_ONLY);
+        try
+        {
+            registry.addConfigurationFromResource( "org/apache/archiva/configuration/default-archiva.xml", KEY_DEFAULT_ONLY);
+        }
+        catch ( RegistryException e )
+        {
+            throw new ConfigurationRuntimeException(
+                    "Fatal error: Unable to find the built-in default configuration and load it into the registry", e );
+        }
+        return registry.getSubset(KEY_DEFAULT_ONLY);
+    }
+
     @SuppressWarnings("unchecked")
     @Override
     public synchronized void save( Configuration configuration )
@@ -527,6 +609,9 @@ public class DefaultArchivaConfiguration
                     section.removeSubset( "repositoryScanning.invalidContentConsumers" );
                 }
             }
+            if (configuration.getArchivaRuntimeConfiguration()!=null) {
+                section.removeSubset("archivaRuntimeConfiguration.defaultCheckPaths");
+            }
 
             new ConfigurationRegistryWriter().write( configuration, section );
             section.save();
@@ -736,7 +821,7 @@ public class DefaultArchivaConfiguration
     }
 
     /**
-     * upgrade from 1.3
+     * Handle upgrade to newer version
      */
     private void handleUpgradeConfiguration()
         throws RegistryException, IndeterminateConfigurationException
@@ -781,8 +866,24 @@ public class DefaultArchivaConfiguration
             knowContentConsumers.add( "duplicate-artifacts" );
             configuration.getRepositoryScanning().setKnownContentConsumers( knowContentConsumers );
         }
-        // save ??
-        //save( configuration );
+
+        Registry defaultOnlyConfiguration = readDefaultOnlyConfiguration();
+        // Currently we check only for configuration version change, not certain version numbers.
+        if (hasConfigVersionChanged(configuration, defaultOnlyConfiguration)) {
+            updateCheckPathDefaults(configuration, defaultOnlyConfiguration);
+            String newVersion = defaultOnlyConfiguration.getString("version");
+            if (newVersion==null) {
+                throw new IndeterminateConfigurationException("The default configuration has no version information!");
+            }
+            configuration.setVersion(newVersion);
+            try {
+                save(configuration);
+            } catch (IndeterminateConfigurationException e) {
+                log.error("Error occured during configuration update to new version: {}", e.getMessage());
+            } catch (RegistryException e) {
+                log.error("Error occured during configuration update to new version: {}", e.getMessage());
+            }
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo b/archiva-modules/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo
index fc5169f..494af12 100644
--- a/archiva-modules/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo
+++ b/archiva-modules/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo
@@ -197,6 +197,15 @@
             The list of ProxyConnectorRuleConfigurations.
           </description>
         </field>
+        <field>
+          <name>archivaDefaultConfiguration</name>
+          <version>1.4.2+</version>
+          <association>
+            <type>ArchivaDefaultConfiguration</type>
+            <multiplicity>1</multiplicity>
+          </association>
+          <description>Archiva default settings.</description>
+        </field>
       </fields>
       <codeSegments>
         <codeSegment>
@@ -597,12 +606,18 @@
           <name>extraHeaders</name>
           <version>1.4.0+</version>
           <type>Map</type>
-          <description>Additionnal http headers to add to url when requesting remote repositories.</description>
+          <description>Additional http headers to add to url when requesting remote repositories.</description>
           <association xml.mapStyle="inline">
             <type>String</type>
             <multiplicity>*</multiplicity>
           </association>
         </field>
+        <field>
+          <name>checkPath</name>
+          <version>1.4.2+</version>
+          <type>String</type>
+          <description>The path to check the repository availability (relative to the repository URL). Some repositories do not allow browsing, so a certain artifact must be checked.</description>
+        </field>
       </fields>
       <codeSegments>
         <codeSegment>
@@ -877,6 +892,30 @@
         </field>
       </fields>
     </class>
+    <class>
+      <name>RepositoryCheckPath</name>
+      <version>1.4.2+</version>
+      <fields >
+        <field >
+          <name>url</name>
+          <version>1.4.2+</version>
+          <type>String</type>
+          <required>true</required>
+          <description>
+            The URL for which this path should be used
+          </description>
+        </field>
+        <field>
+          <name>path</name>
+          <version>1.4.2+</version>
+          <type>String</type>
+          <required>true</required>
+          <description>
+            The path to use for checking the repository connection.
+          </description>
+        </field>
+      </fields>
+    </class>
 
     <!--
       ____                            _
@@ -1584,6 +1623,25 @@
     </class>
 
     <class>
+    <name>ArchivaDefaultConfiguration</name>
+    <version>1.4.2+</version>
+    <description>
+      Archiva default settings.
+    </description>
+      <fields>
+        <field>
+          <name>defaultCheckPaths</name>
+          <description>The default check paths for certain remote repositories</description>
+          <version>1.4.2+</version>
+          <association>
+            <type>RepositoryCheckPath</type>
+            <multiplicity>*</multiplicity>
+          </association>
+        </field>
+      </fields>
+    </class>
+
+    <class>
       <name>LdapConfiguration</name>
       <version>1.4.0+</version>
       <description>
@@ -1670,7 +1728,7 @@
           <name>extraProperties</name>
           <version>1.4.0+</version>
           <type>Map</type>
-          <description>Additionnal properties to use for ldap connection.</description>
+          <description>Additional properties to use for ldap connection.</description>
           <association xml.mapStyle="inline">
             <type>String</type>
             <multiplicity>*</multiplicity>

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml b/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml
index a74f09c..877b6a5 100644
--- a/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml
+++ b/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
-  <version>2</version>
+  <version>3</version>
   <managedRepositories>
     <managedRepository>
       <id>internal</id>
@@ -151,5 +151,17 @@
     </rbacManagerImpls>
   </redbackRuntimeConfiguration>
 
+  <archivaDefaultConfiguration>
+    <defaultCheckPaths>
+      <defaultCheckPath>
+        <url>http://download.oracle.com/maven</url>
+        <path>com/sleepycat/je/license.txt</path>
+      </defaultCheckPath>
+      <defaultCheckPath>
+        <url>https://download.oracle.com/maven</url>
+        <path>com/sleepycat/je/license.txt</path>
+      </defaultCheckPath>
+    </defaultCheckPaths>
+  </archivaDefaultConfiguration>
 
 </configuration>

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/archiva/configuration/ArchivaConfigurationTest.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/archiva/configuration/ArchivaConfigurationTest.java b/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/archiva/configuration/ArchivaConfigurationTest.java
index 03bb489..15080d8 100644
--- a/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/archiva/configuration/ArchivaConfigurationTest.java
+++ b/archiva-modules/archiva-base/archiva-configuration/src/test/java/org/apache/archiva/configuration/ArchivaConfigurationTest.java
@@ -814,7 +814,6 @@ public class ArchivaConfigurationTest
     {
         ArchivaConfiguration archivaConfiguration = lookup( ArchivaConfiguration.class, "test-configuration" );
 
-        archivaConfiguration.reload();
         Configuration configuration = archivaConfiguration.getConfiguration();
         assertConfiguration( configuration, 2, 2, 2 );
         assertEquals( "check remote repositories", 2, configuration.getRemoteRepositories().size() );

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RemoteRepository.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RemoteRepository.java
index fdab243..fd07ce9 100644
--- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RemoteRepository.java
+++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-api/src/main/java/org/apache/archiva/admin/model/beans/RemoteRepository.java
@@ -47,6 +47,12 @@ public class RemoteRepository
     private int timeout = 60;
 
     /**
+     * @since 2.2.3
+     * The path to use for checking availability of the remote repository
+     */
+    private String checkPath;
+
+    /**
      * Activate download of remote index if remoteIndexUrl is set too.
      */
     private boolean downloadRemoteIndex = false;
@@ -316,6 +322,22 @@ public class RemoteRepository
         }
     }
 
+    public void setCheckPath(String checkPath) {
+        if (checkPath==null) {
+            this.checkPath="";
+        } else if (checkPath.startsWith("/")) {
+            this.checkPath = StringUtils.removeStart(checkPath, "/");
+            while(this.checkPath.startsWith("/")) {
+                this.checkPath = StringUtils.removeStart(checkPath, "/");
+            }
+        } else {
+            this.checkPath = checkPath;
+        }
+    }
+
+    public String getCheckPath() {
+        return checkPath;
+    }
 
     @Override
     public String toString()
@@ -335,6 +357,7 @@ public class RemoteRepository
         sb.append( ", downloadRemoteIndexOnStartup=" ).append( downloadRemoteIndexOnStartup );
         sb.append( ", extraParameters=" ).append( extraParameters );
         sb.append( ", extraHeaders=" ).append( extraHeaders );
+        sb.append( ", checkPath=").append(checkPath);
         sb.append( '}' );
         return sb.toString();
     }

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
index 9f6a20b..8f39053 100644
--- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
+++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/main/java/org/apache/archiva/admin/repository/remote/DefaultRemoteRepositoryAdmin.java
@@ -29,6 +29,7 @@ import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
 import org.apache.archiva.configuration.Configuration;
 import org.apache.archiva.configuration.ProxyConnectorConfiguration;
 import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
+import org.apache.archiva.configuration.RepositoryCheckPath;
 import org.apache.archiva.metadata.model.facets.AuditEvent;
 import org.apache.commons.lang.StringUtils;
 import org.apache.maven.index.NexusIndexer;
@@ -137,6 +138,7 @@ public class DefaultRemoteRepositoryAdmin
             remoteRepository.setDescription( repositoryConfiguration.getDescription() );
             remoteRepository.setExtraHeaders( repositoryConfiguration.getExtraHeaders() );
             remoteRepository.setExtraParameters( repositoryConfiguration.getExtraParameters() );
+            remoteRepository.setCheckPath(repositoryConfiguration.getCheckPath());
             remoteRepositories.add( remoteRepository );
         }
         return remoteRepositories;
@@ -170,7 +172,19 @@ public class DefaultRemoteRepositoryAdmin
         }
 
         //MRM-752 - url needs trimming
-        remoteRepository.setUrl( StringUtils.trim( remoteRepository.getUrl() ) );
+        //MRM-1940 - URL should not end with a slash
+        remoteRepository.setUrl( StringUtils.stripEnd(StringUtils.trim( remoteRepository.getUrl() ), "/"));
+
+        if (StringUtils.isEmpty(remoteRepository.getCheckPath())) {
+            String checkUrl = remoteRepository.getUrl().toLowerCase();
+            for (RepositoryCheckPath path : getArchivaConfiguration ().getConfiguration().getArchivaDefaultConfiguration().getDefaultCheckPaths()) {
+                log.debug("Checking path for urls: {} <-> {}", checkUrl, path.getUrl());
+                if (checkUrl.startsWith(path.getUrl())) {
+                    remoteRepository.setCheckPath(path.getPath());
+                    break;
+                }
+            }
+        }
 
         RemoteRepositoryConfiguration remoteRepositoryConfiguration =
             getRemoteRepositoryConfiguration( remoteRepository );
@@ -365,6 +379,7 @@ public class DefaultRemoteRepositoryAdmin
         remoteRepositoryConfiguration.setDescription( remoteRepository.getDescription() );
         remoteRepositoryConfiguration.setExtraHeaders( remoteRepository.getExtraHeaders() );
         remoteRepositoryConfiguration.setExtraParameters( remoteRepository.getExtraParameters() );
+        remoteRepositoryConfiguration.setCheckPath(remoteRepository.getCheckPath());
         return remoteRepositoryConfiguration;
     }
 

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRemoteRepositoriesService.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRemoteRepositoriesService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRemoteRepositoriesService.java
index a6b341a..59358dd 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRemoteRepositoriesService.java
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/DefaultRemoteRepositoriesService.java
@@ -54,8 +54,7 @@ import java.util.Map;
 @Service( "remoteRepositoriesService#rest" )
 public class DefaultRemoteRepositoriesService
     extends AbstractRestService
-    implements RemoteRepositoriesService
-{
+    implements RemoteRepositoriesService {
 
     @Inject
     private RemoteRepositoryAdmin remoteRepositoryAdmin;
@@ -70,42 +69,26 @@ public class DefaultRemoteRepositoriesService
     int checkReadTimeout = 10000;
     int checkTimeout = 9000;
 
-    // TODO: make this configurable
-    private Map<String,String> remoteConnectivityCheckPaths = new HashMap<>();
-
-    @PostConstruct
-    private void init() {
-        // default initialization for known servers
-        remoteConnectivityCheckPaths.put("http://download.oracle.com/maven","com/sleepycat/je/license.txt");
-        remoteConnectivityCheckPaths.put("https://download.oracle.com/maven","com/sleepycat/je/license.txt");
-    }
 
     @Override
     public List<RemoteRepository> getRemoteRepositories()
-        throws ArchivaRestServiceException
-    {
-        try
-        {
+            throws ArchivaRestServiceException {
+        try {
             List<RemoteRepository> remoteRepositories = remoteRepositoryAdmin.getRemoteRepositories();
             return remoteRepositories == null ? Collections.<RemoteRepository>emptyList() : remoteRepositories;
-        }
-        catch ( RepositoryAdminException e )
-        {
-            log.error( e.getMessage(), e );
-            throw new ArchivaRestServiceException( e.getMessage(), e.getFieldName(), e );
+        } catch (RepositoryAdminException e) {
+            log.error(e.getMessage(), e);
+            throw new ArchivaRestServiceException(e.getMessage(), e.getFieldName(), e);
         }
     }
 
     @Override
-    public RemoteRepository getRemoteRepository( String repositoryId )
-        throws ArchivaRestServiceException
-    {
+    public RemoteRepository getRemoteRepository(String repositoryId)
+            throws ArchivaRestServiceException {
 
         List<RemoteRepository> remoteRepositories = getRemoteRepositories();
-        for ( RemoteRepository repository : remoteRepositories )
-        {
-            if ( StringUtils.equals( repositoryId, repository.getId() ) )
-            {
+        for (RemoteRepository repository : remoteRepositories) {
+            if (StringUtils.equals(repositoryId, repository.getId())) {
                 return repository;
             }
         }
@@ -113,109 +96,91 @@ public class DefaultRemoteRepositoriesService
     }
 
     @Override
-    public Boolean deleteRemoteRepository( String repositoryId )
-        throws ArchivaRestServiceException
-    {
-        try
-        {
-            return remoteRepositoryAdmin.deleteRemoteRepository( repositoryId, getAuditInformation() );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            log.error( e.getMessage(), e );
-            throw new ArchivaRestServiceException( e.getMessage(), e.getFieldName(), e );
+    public Boolean deleteRemoteRepository(String repositoryId)
+            throws ArchivaRestServiceException {
+        try {
+            return remoteRepositoryAdmin.deleteRemoteRepository(repositoryId, getAuditInformation());
+        } catch (RepositoryAdminException e) {
+            log.error(e.getMessage(), e);
+            throw new ArchivaRestServiceException(e.getMessage(), e.getFieldName(), e);
         }
     }
 
     @Override
-    public Boolean addRemoteRepository( RemoteRepository remoteRepository )
-        throws ArchivaRestServiceException
-    {
-        try
-        {
-            return remoteRepositoryAdmin.addRemoteRepository( remoteRepository, getAuditInformation() );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            log.error( e.getMessage(), e );
-            throw new ArchivaRestServiceException( e.getMessage(), e.getFieldName(), e );
+    public Boolean addRemoteRepository(RemoteRepository remoteRepository)
+            throws ArchivaRestServiceException {
+        try {
+            return remoteRepositoryAdmin.addRemoteRepository(remoteRepository, getAuditInformation());
+        } catch (RepositoryAdminException e) {
+            log.error(e.getMessage(), e);
+            throw new ArchivaRestServiceException(e.getMessage(), e.getFieldName(), e);
         }
     }
 
     @Override
-    public Boolean updateRemoteRepository( RemoteRepository remoteRepository )
-        throws ArchivaRestServiceException
-    {
-        try
-        {
-            return remoteRepositoryAdmin.updateRemoteRepository( remoteRepository, getAuditInformation() );
-        }
-        catch ( RepositoryAdminException e )
-        {
-            log.error( e.getMessage(), e );
-            throw new ArchivaRestServiceException( e.getMessage(), e.getFieldName(), e );
+    public Boolean updateRemoteRepository(RemoteRepository remoteRepository)
+            throws ArchivaRestServiceException {
+        try {
+            return remoteRepositoryAdmin.updateRemoteRepository(remoteRepository, getAuditInformation());
+        } catch (RepositoryAdminException e) {
+            log.error(e.getMessage(), e);
+            throw new ArchivaRestServiceException(e.getMessage(), e.getFieldName(), e);
         }
     }
 
     @Override
-    public Boolean checkRemoteConnectivity( String repositoryId )
-        throws ArchivaRestServiceException
-    {
-        try
-        {
-            RemoteRepository remoteRepository = remoteRepositoryAdmin.getRemoteRepository( repositoryId );
-            if ( remoteRepository == null )
-            {
-                log.warn( "ignore scheduleDownloadRemote for repo with id {} as not exists", repositoryId );
+    public Boolean checkRemoteConnectivity(String repositoryId)
+            throws ArchivaRestServiceException {
+        try {
+            RemoteRepository remoteRepository = remoteRepositoryAdmin.getRemoteRepository(repositoryId);
+            if (remoteRepository == null) {
+                log.warn("ignore scheduleDownloadRemote for repo with id {} as not exists", repositoryId);
                 return Boolean.FALSE;
             }
             NetworkProxy networkProxy = null;
-            if ( StringUtils.isNotBlank( remoteRepository.getRemoteDownloadNetworkProxyId() ) )
-            {
-                networkProxy = networkProxyAdmin.getNetworkProxy( remoteRepository.getRemoteDownloadNetworkProxyId() );
-                if ( networkProxy == null )
-                {
+            if (StringUtils.isNotBlank(remoteRepository.getRemoteDownloadNetworkProxyId())) {
+                networkProxy = networkProxyAdmin.getNetworkProxy(remoteRepository.getRemoteDownloadNetworkProxyId());
+                if (networkProxy == null) {
                     log.warn(
-                        "your remote repository is configured to download remote index trought a proxy we cannot find id:{}",
-                        remoteRepository.getRemoteDownloadNetworkProxyId() );
+                            "your remote repository is configured to download remote index trought a proxy we cannot find id:{}",
+                            remoteRepository.getRemoteDownloadNetworkProxyId());
                 }
             }
 
-            String wagonProtocol = new URL( remoteRepository.getUrl() ).getProtocol();
+            String wagonProtocol = new URL(remoteRepository.getUrl()).getProtocol();
 
             final Wagon wagon =
-                wagonFactory.getWagon( new WagonFactoryRequest( wagonProtocol, remoteRepository.getExtraHeaders() ) //
-                                           .networkProxy( networkProxy ) );
+                    wagonFactory.getWagon(new WagonFactoryRequest(wagonProtocol, remoteRepository.getExtraHeaders()) //
+                            .networkProxy(networkProxy));
 
             // hardcoded value as it's a check of the remote repo connectivity
-            wagon.setReadTimeout( checkReadTimeout );
-            wagon.setTimeout( checkTimeout );
+            wagon.setReadTimeout(checkReadTimeout);
+            wagon.setTimeout(checkTimeout);
 
-            if ( wagon instanceof AbstractHttpClientWagon )
-            {
+            if (wagon instanceof AbstractHttpClientWagon) {
                 HttpMethodConfiguration httpMethodConfiguration = new HttpMethodConfiguration() //
-                    .setUsePreemptive( true ) //
-                    .setReadTimeout( checkReadTimeout );
-                HttpConfiguration httpConfiguration = new HttpConfiguration().setGet( httpMethodConfiguration );
-                AbstractHttpClientWagon.class.cast( wagon ).setHttpConfiguration( httpConfiguration );
+                        .setUsePreemptive(true) //
+                        .setReadTimeout(checkReadTimeout);
+                HttpConfiguration httpConfiguration = new HttpConfiguration().setGet(httpMethodConfiguration);
+                AbstractHttpClientWagon.class.cast(wagon).setHttpConfiguration(httpConfiguration);
             }
-            
+
             ProxyInfo proxyInfo = null;
-            if ( networkProxy != null )
-            {
+            if (networkProxy != null) {
                 proxyInfo = new ProxyInfo();
-                proxyInfo.setType( networkProxy.getProtocol() );
-                proxyInfo.setHost( networkProxy.getHost() );
-                proxyInfo.setPort( networkProxy.getPort() );
-                proxyInfo.setUserName( networkProxy.getUsername() );
-                proxyInfo.setPassword( networkProxy.getPassword() );
-            }            
-            String url = StringUtils.stripEnd(remoteRepository.getUrl(),"/");
-            wagon.connect( new Repository( remoteRepository.getId(), url ), proxyInfo );
+                proxyInfo.setType(networkProxy.getProtocol());
+                proxyInfo.setHost(networkProxy.getHost());
+                proxyInfo.setPort(networkProxy.getPort());
+                proxyInfo.setUserName(networkProxy.getUsername());
+                proxyInfo.setPassword(networkProxy.getPassword());
+            }
+            String url = StringUtils.stripEnd(remoteRepository.getUrl(), "/");
+            wagon.connect(new Repository(remoteRepository.getId(), url), proxyInfo);
 
             // MRM-1933, there are certain servers that do not allow browsing
-            if (remoteConnectivityCheckPaths.containsKey(url)) {
-                return wagon.resourceExists(remoteConnectivityCheckPaths.get(url));
+            if (!(StringUtils.isEmpty(remoteRepository.getCheckPath()) ||
+                    "/".equals(remoteRepository.getCheckPath()))) {
+                return wagon.resourceExists(remoteRepository.getCheckPath());
             } else {
                 // we only check connectivity as remote repo can be empty
                 // MRM-1909: Wagon implementation appends a slash already
@@ -223,14 +188,10 @@ public class DefaultRemoteRepositoriesService
             }
 
             return Boolean.TRUE;
-        }
-        catch ( TransferFailedException e )
-        {
-            log.info( "TransferFailedException :{}", e.getMessage() );
+        } catch (TransferFailedException e) {
+            log.info("TransferFailedException :{}", e.getMessage());
             return Boolean.FALSE;
-        }
-        catch ( Exception e )
-        {
+        } catch (Exception e) {
             // This service returns either true or false, Exception cannot be handled by the clients
             log.debug("Exception occured on connectivity test.", e);
             log.info("Connection exception: {}", e.getMessage());
@@ -255,11 +216,4 @@ public class DefaultRemoteRepositoriesService
         this.checkTimeout = checkTimeout;
     }
 
-    public Map<String, String> getRemoteConnectivityCheckPaths() {
-        return remoteConnectivityCheckPaths;
-    }
-
-    public void setRemoteConnectivityCheckPaths(Map<String, String> remoteConnectivityCheckPaths) {
-        this.remoteConnectivityCheckPaths = remoteConnectivityCheckPaths;
-    }
 }

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties b/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties
index e8013c5..122db4f 100644
--- a/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties
+++ b/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties
@@ -172,8 +172,9 @@ remoterepository.download.remote.full=Full download ?
 remoterepository.download.remote.scheduled=Download Remote Index of repository {0} scheduled.
 remoterepository.delete.confirm=Are you sure to delete Remote Repository {0} ?
 remoterepository.deleted=Remote repository {0}\u00c2\u00a0deleted.
-remoteRepository.extraParametersEntries=Additionnal url parameters
-remoteRepository.extraHeadersEntries=Additionnal Http Headers
+remoteRepository.extraParametersEntries=Additional url parameters
+remoteRepository.extraHeadersEntries=Additional Http Headers
+remoteRepository.checkPath=Connection Check Path
 remoteRepository.timeout.help.title=Download Timeout
 remoteRepository.timeout.help.content=Timeout in secondes for downloading files from remote repository.
 remoteRepository.userName.help.title=Username
@@ -197,6 +198,11 @@ remoteRepository.extraParametersEntries.help.content=Key/Value pair you want to
 remoteRepository.extraHeadersEntries.help.title=Extra HTTP Headers
 remoteRepository.extraHeadersEntries.help.content=Key/Value pair HTTP headers you want to add when asking the remote repository.
 remoterepository.remotecheck=Remote Check
+remoteRepository.checkPath.help.title=Connection Check Path
+remoteRepository.checkPath.help.content=Path relative to the repository URL that is used to check the connection to the \
+  remote repository. Some repositories may not allow to browse the root directory. So if this path is set, the repository is \
+  considered online if the resources exists.
+
 
 
 

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/admin/repository/maven2/repositories.js
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/admin/repository/maven2/repositories.js b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/admin/repository/maven2/repositories.js
index 3a6cb5f..abfb373 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/admin/repository/maven2/repositories.js
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/admin/repository/maven2/repositories.js
@@ -692,7 +692,7 @@ function(jquery,i18n,jqueryTmpl,bootstrap,jqueryValidate,ko) {
 
   RemoteRepository=function(id,name,layout,indexDirectory,url,userName,password,timeout,downloadRemoteIndex,remoteIndexUrl,
                             remoteDownloadNetworkProxyId,cronExpression,remoteDownloadTimeout,downloadRemoteIndexOnStartup,
-                            description,extraParametersEntries,extraHeadersEntries){
+                            description,extraParametersEntries,extraHeadersEntries,checkPath){
 
     var self=this;
 
@@ -774,6 +774,9 @@ function(jquery,i18n,jqueryTmpl,bootstrap,jqueryValidate,ko) {
       self.modified(true);
     });
 
+    this.checkPath=ko.observable(checkPath);
+    this.checkPath.subscribe(function(newValue){self.modified(true)});
+
     this.modified=ko.observable(false);
   }
 
@@ -799,7 +802,7 @@ function(jquery,i18n,jqueryTmpl,bootstrap,jqueryValidate,ko) {
     return new RemoteRepository(data.id,data.name,data.layout,data.indexDirectory,data.url,data.userName,data.password,
                                 data.timeout,data.downloadRemoteIndex,data.remoteIndexUrl,data.remoteDownloadNetworkProxyId,
                                 data.cronExpression,data.remoteDownloadTimeout,data.downloadRemoteIndexOnStartup,data.description,
-                                extraParametersEntries,extraHeadersEntries);
+                                extraParametersEntries,extraHeadersEntries,data.checkPath);
   }
 
   mapRemoteRepositories=function(data){

http://git-wip-us.apache.org/repos/asf/archiva/blob/1acc6e7b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html
index 3d16cf8..c23158e 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/repositories.html
@@ -733,6 +733,20 @@
         </div>
       </div>
 
+      <div class="control-group">
+        <label class="control-label" for="checkPath">${$.i18n.prop('remoteRepository.checkPath')}</label>
+
+        <div class="controls">
+          <input type="text" class="input-xxlarge" id="checkPath" name="checkPath"
+                 data-bind="value: remoteRepository.checkPath"/>
+          <a class="btn btn-warning btn-mini popover-doc" id="remoteRepository-checkPath-info-button"
+             data-original-title="${$.i18n.prop('remoteRepository.checkPath.help.title')}"
+             data-content="${$.i18n.prop('remoteRepository.checkPath.help.content')}">
+            <i class="icon-question-sign icon-white"></i>
+          </a>
+        </div>
+      </div>
+
       <div class="row-fluid">
         <div class="control-group span6">
           <strong>${$.i18n.prop('remoteRepository.extraParametersEntries')}</strong>