遗留的问题: 重要,这是我看源码的动机
远程仓库和镜像之间的映射关系?
此处故意逆向查找,其实在常用类中很容易猜出来repos的来源
找到最终repos出现的位置
org.eclipse.aether.internal.impl.DefaultArtifactResolver#resolve
List<RemoteRepository> repos = request.getRepositories();
来自这个属性: org.eclipse.aether.resolution.ArtifactRequest#repositories
通过断点反查到原始传递的类
其实requests是一个实例
org.eclipse.aether.internal.impl.DefaultArtifactResolver#resolveArtifact
public ArtifactResult resolveArtifact( RepositorySystemSession session, ArtifactRequest request )
throws ArtifactResolutionException {
return resolveArtifacts( session, Collections.singleton( request ) ).get( 0 );
}
对象在org.apache.maven.project.ProjectModelResolver#resolveModel创建
public ModelSource resolveModel(String groupId, String artifactId, String version)
throws UnresolvableModelException {
File pomFile = null;
if (modelPool != null) {
pomFile = modelPool.get(groupId, artifactId, version);
}
if (pomFile == null) {
Artifact pomArtifact = new DefaultArtifact(groupId, artifactId, "", "pom", version);
try {
// repositories出现,并且已经有了值
ArtifactRequest request = new ArtifactRequest(pomArtifact, repositories, context);
request.setTrace(trace);
pomArtifact = resolver.resolveArtifact(session, request).getArtifact();
} catch (ArtifactResolutionException e) {}
pomFile = pomArtifact.getFile();
}
return new FileModelSource(pomFile);
}
说明在ProjectModelResolver声明中期中赋值,所以重点是看这个对象的创建时期
org.apache.maven.model.building.DefaultModelBuilder#readParentExternally
ModelResolver modelResolver = request.getModelResolver(); // 来自request
org.apache.maven.project.DefaultProjectBuilder#build
ModelBuildingRequest request = getModelBuildingRequest( config ); // repositories来自 config
private ModelBuildingRequest getModelBuildingRequest( InternalConfig config ) {
ProjectBuildingRequest configuration = config.request;
ModelBuildingRequest request = new DefaultModelBuildingRequest(); // request
RequestTrace trace = RequestTrace.newChild( null, configuration ).newChild( request );
ModelResolver resolver =new ProjectModelResolver( config.session, trace, repoSystem, repositoryManager, config.repositories, configuration.getRepositoryMerging(), config.modelPool ); // repositories
request.setValidationLevel( configuration.getValidationLevel() );
request.setProcessPlugins( configuration.isProcessPlugins() );
request.setProfiles( configuration.getProfiles() );
request.setActiveProfileIds( configuration.getActiveProfileIds() );
request.setInactiveProfileIds( configuration.getInactiveProfileIds() );
request.setSystemProperties( configuration.getSystemProperties() );
request.setUserProperties( configuration.getUserProperties() );
request.setBuildStartTime( configuration.getBuildStartTime() );
request.setModelResolver( resolver ); // ModelResolver 赋值
request.setModelCache( config.modelCache );
return request;
}
org.apache.maven.project.DefaultProjectBuilder#build
InternalConfig config = new InternalConfig( request, modelPool,useGlobalModelCache() ? getModelCache() : new ReactorModelCache() ); // 来自 request
InternalConfig(ProjectBuildingRequest request, ReactorModelPool modelPool, ReactorModelCache modelCache) {
this.request = request;
this.modelPool = modelPool;
this.modelCache = modelCache;
session = LegacyLocalRepositoryManager.overlay(request.getLocalRepository(), equest.getRepositorySession(), repoSystem);
repositories = RepositoryUtils.toRepos(request.getRemoteRepositories()); // 做了类型不让人
// ArtifactRepository -> RemoteRepository
}
org.apache.maven.graph.DefaultGraphBuilder#collectProjects
private void collectProjects(List<MavenProject> projects, List<File> files, MavenExecutionRequest request)
throws ProjectBuildingException {
ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest(); // 对象转换了下
List<ProjectBuildingResult> results = projectBuilder.build(files, request.isRecursive(),
projectBuildingRequest);
}
public ProjectBuildingRequest getProjectBuildingRequest() {
if (projectBuildingRequest == null) {
projectBuildingRequest = new DefaultProjectBuildingRequest();
projectBuildingRequest.setLocalRepository(getLocalRepository());
projectBuildingRequest.setSystemProperties(getSystemProperties());
projectBuildingRequest.setUserProperties(getUserProperties());
projectBuildingRequest.setRemoteRepositories(getRemoteRepositories()); // 远程仓库复制
projectBuildingRequest.setPluginArtifactRepositories(getPluginArtifactRepositories());
projectBuildingRequest.setActiveProfileIds(getActiveProfiles());
projectBuildingRequest.setInactiveProfileIds(getInactiveProfiles());
projectBuildingRequest.setProfiles(getProfiles());
projectBuildingRequest.setProcessPlugins(true);
projectBuildingRequest.setBuildStartTime(getStartTime());
}
return projectBuildingRequest;
}
org.apache.maven.graph.DefaultGraphBuilder#getProjectsForMavenReactor
private List<MavenProject> getProjectsForMavenReactor(MavenSession session) throws ProjectBuildingException {
MavenExecutionRequest request = session.getRequest(); // 从session中获取到
}
org.apache.maven.DefaultMaven#doExecute(org.apache.maven.execution.MavenExecutionRequest)
MavenSession session = new MavenSession(container, repoSession, request, result);
public MavenSession(PlexusContainer container, RepositorySystemSession repositorySession,
MavenExecutionRequest request, MavenExecutionResult result) {
this.container = container;
this.request = request; // 是这个request
this.result = result;
this.settings = new SettingsAdapter(request);
this.repositorySession = repositorySession;
}
org.apache.maven.cli.MavenCli#execute
这是一个重要时机,因为执行填充前后远程仓库数量变化了
cliRequest.request; // 执行前只有profile的repository没有镜像
执行后多了一个默认的中央仓库,也没有镜像
MavenExecutionRequest request = executionRequestPopulator.populateDefaults(cliRequest.request); // 做了一次属性填充
public MavenExecutionRequest populateDefaults(MavenExecutionRequest request)
throws MavenExecutionRequestPopulationException {
baseDirectory(request); // 设置base目录
localRepository(request); // 本地仓库
populateDefaultPluginGroups(request); // 填充默认插件组
injectDefaultRepositories(request); // 注入默认仓库
injectDefaultPluginRepositories(request); // 注入默认插件仓库
return request; // 封住后返回
}
那么核心问题来了, 镜像何时将远程仓库替换掉了: 即mirrorOf配置规则何时生效的
记得List repos = request.getRepositories();执行时候是有一部分仓库被镜像掉了,如下结果
remoteRepository: http://dg.artifact.huawei.com/artifactory/maven-group/
remoteRepository: http://cmc.centralrepo.rnd.huawei.com/maven/
mirroredRepository: http://dg.artifact.huawei.com/artifactory/maven-local-group/ : 被镜像了的一个
remoteRepository: http://dg.artifact.huawei.com/artifactory/maven-group/
mirroredRepository: https://repo.maven.apache.org/maven2 : 被镜像掉的默认中央仓库
经过寻找在org.apache.maven.model.building.DefaultModelBuilder#configureResolver找到
org.apache.maven.model.building.DefaultModelBuilder#configureResolver
private void configureResolver(ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems,
boolean replaceRepositories) {
if (modelResolver == null) {
return;
}
problems.setSource(model);
List<Repository> repositories = model.getRepositories(); // 这个就是从setting中解析到的两个仓库
for (Repository repository : repositories) {
try { // 遍历添加到modelResolver中
modelResolver.addRepository(repository, replaceRepositories); // TODO : 核心 添加仓库
} catch (InvalidRepositoryException e) {
problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE).setMessage(
"Invalid repository " + repository.getId() + ": " + e.getMessage())
.setLocation(repository.getLocation(""))
.setException(e));
}
}
}
public void addRepository(final Repository repository, boolean replace) throws InvalidRepositoryException {
if (!repositoryIds.add(repository.getId())) { // ID存在
if (!replace) {
return; // 不替换就return
}
// Remove any previous repository with this Id
removeMatchingRepository(repositories, repository.getId());
removeMatchingRepository(pomRepositories, repository.getId()); // 如果替换就移除继续执行
}
List<RemoteRepository> newRepositories = Collections.singletonList(
ArtifactDescriptorUtils.toRemoteRepository(repository)); // 转换成集合
if (ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT.equals(repositoryMerging)) { // 合并
repositories = remoteRepositoryManager.aggregateRepositories(session, repositories, newRepositories, true);
} else {
pomRepositories = remoteRepositoryManager.aggregateRepositories(session, pomRepositories, newRepositories,
true); // 代码相同, recessiveIsRaw 标记不同, 将结果作为主导仓库,传入下面的方法
repositories = remoteRepositoryManager.aggregateRepositories(session, pomRepositories, externalRepositories,
false); // 第二次还有个重要的不同参数externalRepositories
}
}
public List<RemoteRepository> aggregateRepositories( RepositorySystemSession session,
List<RemoteRepository> dominantRepositories,
List<RemoteRepository> recessiveRepositories,
boolean recessiveIsRaw ){
if ( recessiveRepositories.isEmpty() ){ // 隐性的仓库如果没有, 就直接返回主导仓库,因为就是要判断它需不需要被镜像
return dominantRepositories;
}
MirrorSelector mirrorSelector = session.getMirrorSelector(); // 镜像选择器,包含了可选的镜像
AuthenticationSelector authSelector = session.getAuthenticationSelector(); // 用户认证选择器
ProxySelector proxySelector = session.getProxySelector(); // 代理选择器
// 第一次肯定没有值,但是隐性仓库的结果会作为主导仓库参数,第二次以recessiveIsRaw = false方式进行第二次调用
List<RemoteRepository> result = new ArrayList<>( dominantRepositories );
next: for ( RemoteRepository recessiveRepository : recessiveRepositories ){
RemoteRepository repository = recessiveRepository; // 可能被镜像的仓库
if ( recessiveIsRaw ){ // 隐性仓库是原生的
RemoteRepository mirrorRepository = mirrorSelector.getMirror( recessiveRepository ); // 根据mirrorOf获取被镜像的仓库
if ( mirrorRepository != null )
{
logMirror( session, recessiveRepository, mirrorRepository );
repository = mirrorRepository;
}
}
String key = getKey( repository );
// recessiveIsRaw == true时候,一定 不会进入
for ( ListIterator<RemoteRepository> it = result.listIterator(); it.hasNext(); ){
}
}
}
return result;
}
// 好像找错位置了
externalRepositories什么时候赋值的(什么时候解析出仓库被镜像的结果列表)
org.apache.maven.project.DefaultProjectBuilder#getModelBuildingRequest
private ModelBuildingRequest getModelBuildingRequest(InternalConfig config) {
ProjectBuildingRequest configuration = config.request;
ModelBuildingRequest request = new DefaultModelBuildingRequest();
RequestTrace trace = RequestTrace.newChild(null, configuration).newChild(request);
ModelResolver resolver = new ProjectModelResolver(config.session, trace, repoSystem, repositoryManager,
config.repositories, configuration.getRepositoryMerging(), config.modelPool);
}
public ProjectModelResolver(RepositorySystemSession session, RequestTrace trace, RepositorySystem resolver,
RemoteRepositoryManager remoteRepositoryManager, List<RemoteRepository> repositories,
ProjectBuildingRequest.RepositoryMerging repositoryMerging, ReactorModelPool modelPool) {
this.session = session;
this.trace = trace;
this.resolver = resolver;
this.remoteRepositoryManager = remoteRepositoryManager;
this.pomRepositories = new ArrayList<>();
this.externalRepositories = Collections.unmodifiableList(new ArrayList<>(repositories)); // 外部仓库赋值
this.repositories = new ArrayList<>();
this.repositories.addAll(externalRepositories);
this.repositoryMerging = repositoryMerging;
this.repositoryIds = new HashSet<>();
this.modelPool = modelPool;
}
此时的仓库已经是
[dg-maven-group (http://dg.artifact.huawei.com/artifactory/maven-group/, default, releases+snapshots),
mirror-artifactory-maven-group (http://cmc.centralrepo.rnd.huawei.com/maven/, default, releases+snapshots),
mirror-maven-group (http://dg.artifact.huawei.com/artifactory/maven-group/, default, releases)]
// mirror开头的是镜像仓库