blob: 1135c07ba6c8de9307368db03b5dfa8ae406f4c4 [file] [log] [blame]
package org.apache.maven.repository;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.settings.Mirror;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.util.StringUtils;
/**
* DefaultMirrorSelector
*/
@Component( role = MirrorSelector.class )
public class DefaultMirrorSelector
implements MirrorSelector
{
private static final String WILDCARD = "*";
private static final String EXTERNAL_WILDCARD = "external:*";
public Mirror getMirror( ArtifactRepository repository, List<Mirror> mirrors )
{
String repoId = repository.getId();
if ( repoId != null && mirrors != null )
{
for ( Mirror mirror : mirrors )
{
if ( repoId.equals( mirror.getMirrorOf() ) && matchesLayout( repository, mirror ) )
{
return mirror;
}
}
for ( Mirror mirror : mirrors )
{
if ( matchPattern( repository, mirror.getMirrorOf() ) && matchesLayout( repository, mirror ) )
{
return mirror;
}
}
}
return null;
}
/**
* This method checks if the pattern matches the originalRepository. Valid patterns:
* <ul>
* <li>{@code *} = everything,</li>
* <li>{@code external:*} = everything not on the localhost and not file based,</li>
* <li>{@code repo,repo1} = {@code repo} or {@code repo1},</li>
* <li>{@code *,!repo1} = everything except {@code repo1}.</li>
* </ul>
*
* @param originalRepository to compare for a match.
* @param pattern used for match.
* @return true if the repository is a match to this pattern.
*/
static boolean matchPattern( ArtifactRepository originalRepository, String pattern )
{
boolean result = false;
String originalId = originalRepository.getId();
// simple checks first to short circuit processing below.
if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
{
result = true;
}
else
{
// process the list
String[] repos = pattern.split( "," );
for ( String repo : repos )
{
repo = repo.trim();
// see if this is a negative match
if ( repo.length() > 1 && repo.startsWith( "!" ) )
{
if ( repo.substring( 1 ).equals( originalId ) )
{
// explicitly exclude. Set result and stop processing.
result = false;
break;
}
}
// check for exact match
else if ( repo.equals( originalId ) )
{
result = true;
break;
}
// check for external:*
else if ( EXTERNAL_WILDCARD.equals( repo ) && isExternalRepo( originalRepository ) )
{
result = true;
// don't stop processing in case a future segment explicitly excludes this repo
}
else if ( WILDCARD.equals( repo ) )
{
result = true;
// don't stop processing in case a future segment explicitly excludes this repo
}
}
}
return result;
}
/**
* Checks the URL to see if this repository refers to an external repository
*
* @param originalRepository
* @return true if external.
*/
static boolean isExternalRepo( ArtifactRepository originalRepository )
{
try
{
URL url = new URL( originalRepository.getUrl() );
return !( url.getHost().equals( "localhost" ) || url.getHost().equals( "127.0.0.1" )
|| url.getProtocol().equals( "file" ) );
}
catch ( MalformedURLException e )
{
// bad url just skip it here. It should have been validated already, but the wagon lookup will deal with it
return false;
}
}
static boolean matchesLayout( ArtifactRepository repository, Mirror mirror )
{
return matchesLayout( RepositoryUtils.getLayout( repository ), mirror.getMirrorOfLayouts() );
}
/**
* Checks whether the layouts configured for a mirror match with the layout of the repository.
*
* @param repoLayout The layout of the repository, may be {@code null}.
* @param mirrorLayout The layouts supported by the mirror, may be {@code null}.
* @return {@code true} if the layouts associated with the mirror match the layout of the original repository,
* {@code false} otherwise.
*/
static boolean matchesLayout( String repoLayout, String mirrorLayout )
{
boolean result = false;
// simple checks first to short circuit processing below.
if ( StringUtils.isEmpty( mirrorLayout ) || WILDCARD.equals( mirrorLayout ) )
{
result = true;
}
else if ( mirrorLayout.equals( repoLayout ) )
{
result = true;
}
else
{
// process the list
String[] layouts = mirrorLayout.split( "," );
for ( String layout : layouts )
{
// see if this is a negative match
if ( layout.length() > 1 && layout.startsWith( "!" ) )
{
if ( layout.substring( 1 ).equals( repoLayout ) )
{
// explicitly exclude. Set result and stop processing.
result = false;
break;
}
}
// check for exact match
else if ( layout.equals( repoLayout ) )
{
result = true;
break;
}
else if ( WILDCARD.equals( layout ) )
{
result = true;
// don't stop processing in case a future segment explicitly excludes this repo
}
}
}
return result;
}
}