moved code from org.ecplise to org.apache.maven Project: http://git-wip-us.apache.org/repos/asf/maven-aether/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-aether/commit/261b17db Tree: http://git-wip-us.apache.org/repos/asf/maven-aether/tree/261b17db Diff: http://git-wip-us.apache.org/repos/asf/maven-aether/diff/261b17db
Branch: refs/heads/ant-tasks Commit: 261b17db32bcc3e7573a63b0217e64d135579b17 Parents: 222122a Author: Hervé Boutemy <hbout...@apache.org> Authored: Sat May 7 18:47:40 2016 +0200 Committer: Hervé Boutemy <hbout...@apache.org> Committed: Sat May 7 18:47:40 2016 +0200 ---------------------------------------------------------------------- README.md | 4 +- build.xml | 4 +- pom.xml | 12 +- .../maven/aether/internal/ant/AetherUtils.java | 83 ++ .../maven/aether/internal/ant/AntLogger.java | 68 ++ .../aether/internal/ant/AntModelResolver.java | 157 ++++ .../maven/aether/internal/ant/AntRepoSys.java | 825 +++++++++++++++++++ .../internal/ant/AntRepositoryListener.java | 123 +++ .../aether/internal/ant/AntSecDispatcher.java | 45 + .../ant/AntServiceLocatorErrorHandler.java | 50 ++ .../ant/AntSettingsDecryptorFactory.java | 51 ++ .../internal/ant/AntTransferListener.java | 91 ++ .../aether/internal/ant/ConverterUtils.java | 227 +++++ .../apache/maven/aether/internal/ant/Names.java | 44 + .../internal/ant/ProjectWorkspaceReader.java | 144 ++++ .../aether/internal/ant/SettingsUtils.java | 182 ++++ .../internal/ant/tasks/AbstractDistTask.java | 180 ++++ .../ant/tasks/AbstractResolvingTask.java | 108 +++ .../ant/tasks/DependencyGraphLogger.java | 85 ++ .../maven/aether/internal/ant/tasks/Deploy.java | 105 +++ .../aether/internal/ant/tasks/Install.java | 60 ++ .../maven/aether/internal/ant/tasks/Layout.java | 131 +++ .../aether/internal/ant/tasks/RefTask.java | 98 +++ .../aether/internal/ant/tasks/Resolve.java | 585 +++++++++++++ .../aether/internal/ant/types/Artifact.java | 181 ++++ .../internal/ant/types/ArtifactContainer.java | 35 + .../aether/internal/ant/types/Artifacts.java | 97 +++ .../internal/ant/types/Authentication.java | 152 ++++ .../aether/internal/ant/types/Dependencies.java | 197 +++++ .../aether/internal/ant/types/Dependency.java | 329 ++++++++ .../internal/ant/types/DependencyContainer.java | 31 + .../aether/internal/ant/types/Exclusion.java | 190 +++++ .../internal/ant/types/LocalRepository.java | 90 ++ .../maven/aether/internal/ant/types/Mirror.java | 155 ++++ .../internal/ant/types/ModelValueExtractor.java | 99 +++ .../maven/aether/internal/ant/types/Pom.java | 352 ++++++++ .../ant/types/PomPropertyEvaluator.java | 62 ++ .../internal/ant/types/PomPropertyHelper.java | 65 ++ .../maven/aether/internal/ant/types/Proxy.java | 164 ++++ .../internal/ant/types/RemoteRepositories.java | 97 +++ .../internal/ant/types/RemoteRepository.java | 351 ++++++++ .../ant/types/RemoteRepositoryContainer.java | 35 + .../aether/internal/ant/types/Settings.java | 86 ++ .../aether/internal/ant/AetherUtils.java | 83 -- .../eclipse/aether/internal/ant/AntLogger.java | 68 -- .../aether/internal/ant/AntModelResolver.java | 157 ---- .../eclipse/aether/internal/ant/AntRepoSys.java | 825 ------------------- .../internal/ant/AntRepositoryListener.java | 123 --- .../aether/internal/ant/AntSecDispatcher.java | 45 - .../ant/AntServiceLocatorErrorHandler.java | 50 -- .../ant/AntSettingsDecryptorFactory.java | 51 -- .../internal/ant/AntTransferListener.java | 91 -- .../aether/internal/ant/ConverterUtils.java | 227 ----- .../org/eclipse/aether/internal/ant/Names.java | 44 - .../internal/ant/ProjectWorkspaceReader.java | 144 ---- .../aether/internal/ant/SettingsUtils.java | 182 ---- .../internal/ant/tasks/AbstractDistTask.java | 180 ---- .../ant/tasks/AbstractResolvingTask.java | 107 --- .../ant/tasks/DependencyGraphLogger.java | 85 -- .../aether/internal/ant/tasks/Deploy.java | 104 --- .../aether/internal/ant/tasks/Install.java | 40 - .../aether/internal/ant/tasks/Layout.java | 131 --- .../aether/internal/ant/tasks/RefTask.java | 98 --- .../aether/internal/ant/tasks/Resolve.java | 585 ------------- .../aether/internal/ant/types/Artifact.java | 181 ---- .../internal/ant/types/ArtifactContainer.java | 35 - .../aether/internal/ant/types/Artifacts.java | 97 --- .../internal/ant/types/Authentication.java | 152 ---- .../aether/internal/ant/types/Dependencies.java | 197 ----- .../aether/internal/ant/types/Dependency.java | 329 -------- .../internal/ant/types/DependencyContainer.java | 31 - .../aether/internal/ant/types/Exclusion.java | 190 ----- .../internal/ant/types/LocalRepository.java | 90 -- .../aether/internal/ant/types/Mirror.java | 154 ---- .../internal/ant/types/ModelValueExtractor.java | 99 --- .../eclipse/aether/internal/ant/types/Pom.java | 352 -------- .../ant/types/PomPropertyEvaluator.java | 62 -- .../internal/ant/types/PomPropertyHelper.java | 65 -- .../aether/internal/ant/types/Proxy.java | 163 ---- .../internal/ant/types/RemoteRepositories.java | 97 --- .../internal/ant/types/RemoteRepository.java | 351 -------- .../ant/types/RemoteRepositoryContainer.java | 35 - .../aether/internal/ant/types/Settings.java | 86 -- .../org/apache/maven/aether/ant/antlib.xml | 41 + .../resources/org/eclipse/aether/ant/antlib.xml | 41 - .../aether/internal/ant/AntBuildsTest.java | 123 +++ .../maven/aether/internal/ant/DeployTest.java | 91 ++ .../maven/aether/internal/ant/InstallTest.java | 98 +++ .../ant/ProjectWorkspaceReaderTest.java | 123 +++ .../maven/aether/internal/ant/ReactorTest.java | 99 +++ .../maven/aether/internal/ant/ResolveTest.java | 150 ++++ .../maven/aether/internal/ant/SettingsTest.java | 63 ++ .../aether/internal/ant/tasks/LayoutTest.java | 54 ++ .../internal/ant/types/DependencyTest.java | 87 ++ .../internal/ant/types/ExclusionTest.java | 87 ++ .../aether/internal/ant/types/PomTest.java | 42 + .../aether/internal/ant/AntBuildsTest.java | 124 --- .../eclipse/aether/internal/ant/DeployTest.java | 91 -- .../aether/internal/ant/InstallTest.java | 98 --- .../ant/ProjectWorkspaceReaderTest.java | 124 --- .../aether/internal/ant/ReactorTest.java | 100 --- .../aether/internal/ant/ResolveTest.java | 150 ---- .../aether/internal/ant/SettingsTest.java | 65 -- .../aether/internal/ant/tasks/LayoutTest.java | 55 -- .../internal/ant/types/DependencyTest.java | 88 -- .../internal/ant/types/ExclusionTest.java | 88 -- .../aether/internal/ant/types/PomTest.java | 43 - src/test/resources/ant/Deploy/ant.xml | 2 +- src/test/resources/ant/Install/ant.xml | 2 +- src/test/resources/ant/Reactor/ant.xml | 2 +- src/test/resources/ant/Resolve/ant.xml | 2 +- src/test/resources/ant/Settings/ant.xml | 2 +- src/test/resources/ant/common.xml | 2 +- 113 files changed, 7284 insertions(+), 7269 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/README.md ---------------------------------------------------------------------- diff --git a/README.md b/README.md index b696aae..ee213a4 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ and install and deploy locally built artifacts. To integrate the tasks into your build file, copy the JAR into your project's lib directory and use the following snippet to load it: - <project xmlns:aether="antlib:org.eclipse.aether.ant" ...> - <taskdef uri="antlib:org.eclipse.aether.ant" resource="org/eclipse/aether/ant/antlib.xml"> + <project xmlns:aether="antlib:org.apache.maven.aether.ant" ...> + <taskdef uri="antlib:org.apache.maven.aether.ant" resource="org/apache/maven/aether/ant/antlib.xml"> <classpath> <fileset dir="lib" includes="aether-ant-tasks-*.jar"/> </classpath> http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/build.xml ---------------------------------------------------------------------- diff --git a/build.xml b/build.xml index b73eca7..aa5bcf6 100644 --- a/build.xml +++ b/build.xml @@ -19,7 +19,7 @@ under the License. --> -<project xmlns:aether="antlib:org.eclipse.aether.ant" default="deploy"> +<project xmlns:aether="antlib:org.apache.maven.aether.ant" default="deploy"> <!-- This is an example Ant build file using the Aether Ant Tasks to compile, test, install and deploy the @@ -27,7 +27,7 @@ aether-ant-task.jar which this build file will load below. --> - <taskdef uri="antlib:org.eclipse.aether.ant" resource="org/eclipse/aether/ant/antlib.xml"> + <taskdef uri="antlib:org.apache.maven.aether.ant" resource="org/apache/maven/aether/ant/antlib.xml"> <classpath> <fileset dir="target" includes="aether-ant-tasks-*uber.jar"/> </classpath> http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index b5dda58..dc45f6e 100644 --- a/pom.xml +++ b/pom.xml @@ -290,30 +290,30 @@ <relocations> <relocation> <pattern>org.eclipse.aether</pattern> - <shadedPattern>org.eclipse.aether.internal.ant.org.eclipse.aether</shadedPattern> + <shadedPattern>org.apache.maven.aether.internal.ant.org.eclipse.aether</shadedPattern> <excludes> <exclude>org.eclipse.aether.ant.**</exclude> - <exclude>org.eclipse.aether.internal.ant.**</exclude> </excludes> </relocation> <relocation> <pattern>org.sonatype.plexus</pattern> - <shadedPattern>org.eclipse.aether.internal.ant.org.sonatype.plexus</shadedPattern> + <shadedPattern>org.apache.maven.aether.internal.ant.org.sonatype.plexus</shadedPattern> </relocation> <relocation> <pattern>org.apache</pattern> - <shadedPattern>org.eclipse.aether.internal.ant.org.apache</shadedPattern> + <shadedPattern>org.apache.maven.aether.internal.ant.org.apache</shadedPattern> <excludes> <exclude>org.apache.tools.**</exclude> + <exclude>org.apache.maven.aether.**</exclude> </excludes> </relocation> <relocation> <pattern>org.codehaus</pattern> - <shadedPattern>org.eclipse.aether.internal.ant.org.codehaus</shadedPattern> + <shadedPattern>org.apache.maven.aether.internal.ant.org.codehaus</shadedPattern> </relocation> <relocation> <pattern>org.slf4j</pattern> - <shadedPattern>org.eclipse.aether.internal.ant.org.slf4j</shadedPattern> + <shadedPattern>org.apache.maven.aether.internal.ant.org.slf4j</shadedPattern> </relocation> </relocations> </configuration> http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AetherUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AetherUtils.java b/src/main/java/org/apache/maven/aether/internal/ant/AetherUtils.java new file mode 100644 index 0000000..9e2bbb0 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AetherUtils.java @@ -0,0 +1,83 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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.io.File; + +import org.apache.maven.aether.internal.ant.types.RemoteRepositories; +import org.apache.tools.ant.Project; + +class AetherUtils +{ + + public static File findGlobalSettings( Project project ) + { + File file = new File( new File( project.getProperty( "ant.home" ), "etc" ), Names.SETTINGS_XML ); + if ( file.isFile() ) + { + return file; + } + else + { + String mavenHome = getMavenHome( project ); + if ( mavenHome != null ) + { + return new File( new File( mavenHome, "conf" ), Names.SETTINGS_XML ); + } + } + + return null; + } + + public static String getMavenHome( Project project ) + { + String mavenHome = project.getProperty( "maven.home" ); + if ( mavenHome != null ) + { + return mavenHome; + } + return System.getenv( "M2_HOME" ); + } + + public static File findUserSettings( Project project ) + { + File userHome = new File( project.getProperty( "user.home" ) ); + File file = new File( new File( userHome, ".ant" ), Names.SETTINGS_XML ); + if ( file.isFile() ) + { + return file; + } + else + { + return new File( new File( userHome, ".m2" ), Names.SETTINGS_XML ); + } + } + + public static RemoteRepositories getDefaultRepositories( Project project ) + { + Object obj = project.getReference( Names.ID_DEFAULT_REPOS ); + if ( obj instanceof RemoteRepositories ) + { + return (RemoteRepositories) obj; + } + return null; + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AntLogger.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AntLogger.java b/src/main/java/org/apache/maven/aether/internal/ant/AntLogger.java new file mode 100644 index 0000000..d70f8a0 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AntLogger.java @@ -0,0 +1,68 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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 org.apache.tools.ant.Project; +import org.eclipse.aether.spi.log.Logger; + +/** + */ +class AntLogger + implements Logger +{ + + private Project project; + + public AntLogger( Project project ) + { + this.project = project; + } + + public void debug( String msg ) + { + project.log( msg, Project.MSG_DEBUG ); + } + + public void debug( String msg, Throwable error ) + { + project.log( msg, error, Project.MSG_DEBUG ); + } + + public boolean isDebugEnabled() + { + return true; + } + + public boolean isWarnEnabled() + { + return true; + } + + public void warn( String msg ) + { + project.log( msg, Project.MSG_WARN ); + } + + public void warn( String msg, Throwable error ) + { + project.log( msg, error, Project.MSG_WARN ); + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AntModelResolver.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AntModelResolver.java b/src/main/java/org/apache/maven/aether/internal/ant/AntModelResolver.java new file mode 100644 index 0000000..72b9802 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AntModelResolver.java @@ -0,0 +1,157 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.maven.model.Repository; +import org.apache.maven.model.building.FileModelSource; +import org.apache.maven.model.building.ModelSource; +import org.apache.maven.model.resolution.InvalidRepositoryException; +import org.apache.maven.model.resolution.ModelResolver; +import org.apache.maven.model.resolution.UnresolvableModelException; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.impl.RemoteRepositoryManager; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.repository.RepositoryPolicy; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; + +/** + * A model resolver to assist building of dependency POMs. This resolver gives priority to those repositories that have + * been initially specified and repositories discovered in dependency POMs are recessively merged into the search chain. + * + */ +class AntModelResolver + implements ModelResolver +{ + + private final RepositorySystemSession session; + + private final String context; + + private List<org.eclipse.aether.repository.RemoteRepository> repositories; + + private final RepositorySystem repoSys; + + private final RemoteRepositoryManager remoteRepositoryManager; + + private final Set<String> repositoryIds; + + public AntModelResolver( RepositorySystemSession session, String context, RepositorySystem repoSys, + RemoteRepositoryManager remoteRepositoryManager, List<RemoteRepository> repositories ) + { + this.session = session; + this.context = context; + this.repoSys = repoSys; + this.remoteRepositoryManager = remoteRepositoryManager; + this.repositories = repositories; + this.repositoryIds = new HashSet<String>(); + } + + private AntModelResolver( AntModelResolver original ) + { + this.session = original.session; + this.context = original.context; + this.repoSys = original.repoSys; + this.remoteRepositoryManager = original.remoteRepositoryManager; + this.repositories = original.repositories; + this.repositoryIds = new HashSet<String>( original.repositoryIds ); + } + + public void addRepository( Repository repository ) + throws InvalidRepositoryException + { + if ( !repositoryIds.add( repository.getId() ) ) + { + return; + } + + List<RemoteRepository> newRepositories = Collections.singletonList( convert( repository ) ); + + this.repositories = + remoteRepositoryManager.aggregateRepositories( session, repositories, newRepositories, true ); + } + + static RemoteRepository convert( Repository repository ) + { + RemoteRepository.Builder builder = + new RemoteRepository.Builder( repository.getId(), repository.getLayout(), repository.getUrl() ); + builder.setSnapshotPolicy( convert( repository.getSnapshots() ) ); + builder.setReleasePolicy( convert( repository.getReleases() ) ); + return builder.build(); + } + + private static RepositoryPolicy convert( org.apache.maven.model.RepositoryPolicy policy ) + { + boolean enabled = true; + String checksums = RepositoryPolicy.CHECKSUM_POLICY_WARN; + String updates = RepositoryPolicy.UPDATE_POLICY_DAILY; + + if ( policy != null ) + { + enabled = policy.isEnabled(); + if ( policy.getUpdatePolicy() != null ) + { + updates = policy.getUpdatePolicy(); + } + if ( policy.getChecksumPolicy() != null ) + { + checksums = policy.getChecksumPolicy(); + } + } + + return new RepositoryPolicy( enabled, updates, checksums ); + } + + public ModelResolver newCopy() + { + return new AntModelResolver( this ); + } + + public ModelSource resolveModel( String groupId, String artifactId, String version ) + throws UnresolvableModelException + { + Artifact pomArtifact = new DefaultArtifact( groupId, artifactId, "", "pom", version ); + + try + { + ArtifactRequest request = new ArtifactRequest( pomArtifact, repositories, context ); + pomArtifact = repoSys.resolveArtifact( session, request ).getArtifact(); + } + catch ( ArtifactResolutionException e ) + { + throw new UnresolvableModelException( "Failed to resolve POM for " + groupId + ":" + artifactId + ":" + + version + " due to " + e.getMessage(), groupId, artifactId, version, e ); + } + + File pomFile = pomArtifact.getFile(); + + return new FileModelSource( pomFile ); + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AntRepoSys.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AntRepoSys.java b/src/main/java/org/apache/maven/aether/internal/ant/AntRepoSys.java new file mode 100644 index 0000000..b19e346 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AntRepoSys.java @@ -0,0 +1,825 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.maven.aether.internal.ant.types.Artifact; +import org.apache.maven.aether.internal.ant.types.Artifacts; +import org.apache.maven.aether.internal.ant.types.Authentication; +import org.apache.maven.aether.internal.ant.types.Dependencies; +import org.apache.maven.aether.internal.ant.types.Dependency; +import org.apache.maven.aether.internal.ant.types.DependencyContainer; +import org.apache.maven.aether.internal.ant.types.Exclusion; +import org.apache.maven.aether.internal.ant.types.LocalRepository; +import org.apache.maven.aether.internal.ant.types.Mirror; +import org.apache.maven.aether.internal.ant.types.Pom; +import org.apache.maven.aether.internal.ant.types.Proxy; +import org.apache.maven.aether.internal.ant.types.RemoteRepositories; +import org.apache.maven.aether.internal.ant.types.RemoteRepository; +import org.apache.maven.model.Model; +import org.apache.maven.model.building.DefaultModelBuilderFactory; +import org.apache.maven.model.building.DefaultModelBuildingRequest; +import org.apache.maven.model.building.FileModelSource; +import org.apache.maven.model.building.ModelBuilder; +import org.apache.maven.model.building.ModelBuildingException; +import org.apache.maven.model.building.ModelBuildingRequest; +import org.apache.maven.model.resolution.ModelResolver; +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; +import org.apache.maven.settings.building.DefaultSettingsBuilderFactory; +import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; +import org.apache.maven.settings.building.SettingsBuilder; +import org.apache.maven.settings.building.SettingsBuildingException; +import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; +import org.apache.maven.settings.crypto.SettingsDecrypter; +import org.apache.maven.settings.crypto.SettingsDecryptionResult; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.condition.Os; +import org.apache.tools.ant.types.Reference; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.eclipse.aether.ConfigurationProperties; +import org.eclipse.aether.DefaultRepositoryCache; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.collection.CollectResult; +import org.eclipse.aether.collection.DependencyCollectionException; +import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; +import org.eclipse.aether.deployment.DeployRequest; +import org.eclipse.aether.deployment.DeploymentException; +import org.eclipse.aether.impl.DefaultServiceLocator; +import org.eclipse.aether.impl.RemoteRepositoryManager; +import org.eclipse.aether.installation.InstallRequest; +import org.eclipse.aether.installation.InstallationException; +import org.eclipse.aether.repository.AuthenticationSelector; +import org.eclipse.aether.repository.LocalRepositoryManager; +import org.eclipse.aether.repository.MirrorSelector; +import org.eclipse.aether.repository.ProxySelector; +import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; +import org.eclipse.aether.spi.connector.transport.TransporterFactory; +import org.eclipse.aether.spi.log.Logger; +import org.eclipse.aether.transport.classpath.ClasspathTransporterFactory; +import org.eclipse.aether.transport.file.FileTransporterFactory; +import org.eclipse.aether.transport.http.HttpTransporterFactory; +import org.eclipse.aether.util.repository.AuthenticationBuilder; +import org.eclipse.aether.util.repository.ConservativeAuthenticationSelector; +import org.eclipse.aether.util.repository.DefaultAuthenticationSelector; +import org.eclipse.aether.util.repository.DefaultMirrorSelector; +import org.eclipse.aether.util.repository.DefaultProxySelector; + +/** + */ +public class AntRepoSys +{ + + private static final boolean OS_WINDOWS = Os.isFamily( "windows" ); + + private static final ModelBuilder MODEL_BUILDER = new DefaultModelBuilderFactory().newInstance(); + + private static final SettingsBuilder SETTINGS_BUILDER = new DefaultSettingsBuilderFactory().newInstance(); + + private static final SettingsDecrypter SETTINGS_DECRYPTER = new AntSettingsDecryptorFactory().newInstance(); + + private final Project project; + + private final DefaultServiceLocator locator; + + private RepositorySystem repoSys; + + private RemoteRepositoryManager remoteRepoMan; + + private File userSettings; + + private File globalSettings; + + private Settings settings; + + private final List<Mirror> mirrors = new CopyOnWriteArrayList<Mirror>(); + + private final List<Proxy> proxies = new CopyOnWriteArrayList<Proxy>(); + + private final List<Authentication> authentications = new CopyOnWriteArrayList<Authentication>(); + + private LocalRepository localRepository; + + private Pom defaultPom; + + private static <T> boolean eq( T o1, T o2 ) + { + return ( o1 == null ) ? o2 == null : o1.equals( o2 ); + } + + public static synchronized AntRepoSys getInstance( Project project ) + { + Object obj = project.getReference( Names.ID ); + if ( obj instanceof AntRepoSys ) + { + return (AntRepoSys) obj; + } + AntRepoSys instance = new AntRepoSys( project ); + project.addReference( Names.ID, instance ); + instance.initDefaults(); + return instance; + } + + private AntRepoSys( Project project ) + { + this.project = project; + + locator = MavenRepositorySystemUtils.newServiceLocator(); + locator.setErrorHandler( new AntServiceLocatorErrorHandler( project ) ); + locator.setServices( Logger.class, new AntLogger( project ) ); + locator.setServices( ModelBuilder.class, MODEL_BUILDER ); + locator.addService( RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class ); + locator.addService( TransporterFactory.class, FileTransporterFactory.class ); + locator.addService( TransporterFactory.class, HttpTransporterFactory.class ); + locator.addService( TransporterFactory.class, ClasspathTransporterFactory.class ); + } + + private void initDefaults() + { + RemoteRepository repo = new RemoteRepository(); + repo.setProject( project ); + repo.setId( "central" ); + repo.setUrl( "http://repo1.maven.org/maven2/" ); + project.addReference( Names.ID_CENTRAL, repo ); + + repo = new RemoteRepository(); + repo.setProject( project ); + repo.setRefid( new Reference( project, Names.ID_CENTRAL ) ); + RemoteRepositories repos = new RemoteRepositories(); + repos.setProject( project ); + repos.addRemoterepo( repo ); + project.addReference( Names.ID_DEFAULT_REPOS, repos ); + } + + public synchronized RepositorySystem getSystem() + { + if ( repoSys == null ) + { + repoSys = locator.getService( RepositorySystem.class ); + if ( repoSys == null ) + { + throw new BuildException( "The repository system could not be initialized" ); + } + } + return repoSys; + } + + private synchronized RemoteRepositoryManager getRemoteRepoMan() + { + if ( remoteRepoMan == null ) + { + remoteRepoMan = locator.getService( RemoteRepositoryManager.class ); + if ( remoteRepoMan == null ) + { + throw new BuildException( "The repository system could not be initialized" ); + } + } + return remoteRepoMan; + } + + public RepositorySystemSession getSession( Task task, LocalRepository localRepo ) + { + DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); + + Map<Object, Object> configProps = new LinkedHashMap<Object, Object>(); + configProps.put( ConfigurationProperties.USER_AGENT, getUserAgent() ); + configProps.putAll( (Map<?, ?>) project.getProperties() ); + processServerConfiguration( configProps ); + session.setConfigProperties( configProps ); + + session.setOffline( isOffline() ); + session.setUserProperties( project.getUserProperties() ); + + session.setProxySelector( getProxySelector() ); + session.setMirrorSelector( getMirrorSelector() ); + session.setAuthenticationSelector( getAuthSelector() ); + + session.setCache( new DefaultRepositoryCache() ); + + session.setRepositoryListener( new AntRepositoryListener( task ) ); + session.setTransferListener( new AntTransferListener( task ) ); + + session.setLocalRepositoryManager( getLocalRepoMan( session, localRepo ) ); + + session.setWorkspaceReader( ProjectWorkspaceReader.getInstance() ); + + return session; + } + + private String getUserAgent() + { + StringBuilder buffer = new StringBuilder( 128 ); + + buffer.append( "Apache-Ant/" ).append( project.getProperty( "ant.version" ) ); + buffer.append( " (" ); + buffer.append( "Java " ).append( System.getProperty( "java.version" ) ); + buffer.append( "; " ); + buffer.append( System.getProperty( "os.name" ) ).append( " " ).append( System.getProperty( "os.version" ) ); + buffer.append( ")" ); + buffer.append( " Aether" ); + + return buffer.toString(); + } + + private boolean isOffline() + { + String prop = project.getProperty( Names.PROPERTY_OFFLINE ); + if ( prop != null ) + { + return Boolean.parseBoolean( prop ); + } + return getSettings().isOffline(); + } + + private void processServerConfiguration( Map<Object, Object> configProps ) + { + Settings settings = getSettings(); + for ( Server server : settings.getServers() ) + { + if ( server.getConfiguration() != null ) + { + Xpp3Dom dom = (Xpp3Dom) server.getConfiguration(); + for ( int i = dom.getChildCount() - 1; i >= 0; i-- ) + { + Xpp3Dom child = dom.getChild( i ); + if ( "wagonProvider".equals( child.getName() ) ) + { + dom.removeChild( i ); + } + else if ( "httpHeaders".equals( child.getName() ) ) + { + configProps.put( ConfigurationProperties.HTTP_HEADERS + "." + server.getId(), + getHttpHeaders( child ) ); + } + } + + configProps.put( "aether.connector.wagon.config." + server.getId(), dom ); + } + + configProps.put( "aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions() ); + configProps.put( "aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions() ); + } + } + + private Map<String, String> getHttpHeaders( Xpp3Dom dom ) + { + Map<String, String> headers = new HashMap<String, String>(); + for ( int i = 0; i < dom.getChildCount(); i++ ) + { + Xpp3Dom child = dom.getChild( i ); + Xpp3Dom name = child.getChild( "name" ); + Xpp3Dom value = child.getChild( "value" ); + if ( name != null && name.getValue() != null ) + { + headers.put( name.getValue(), ( value != null ) ? value.getValue() : null ); + } + } + return Collections.unmodifiableMap( headers ); + } + + private File getDefaultLocalRepoDir() + { + String dir = project.getProperty( "maven.repo.local" ); + if ( dir != null ) + { + return project.resolveFile( dir ); + } + + Settings settings = getSettings(); + if ( settings.getLocalRepository() != null ) + { + return new File( settings.getLocalRepository() ); + } + + return new File( new File( project.getProperty( "user.home" ), ".m2" ), "repository" ); + } + + private LocalRepositoryManager getLocalRepoMan( RepositorySystemSession session, LocalRepository localRepo ) + { + if ( localRepo == null ) + { + localRepo = localRepository; + } + + File repoDir; + if ( localRepo != null && localRepo.getDir() != null ) + { + repoDir = localRepo.getDir(); + } + else + { + repoDir = getDefaultLocalRepoDir(); + } + + org.eclipse.aether.repository.LocalRepository repo = + new org.eclipse.aether.repository.LocalRepository( repoDir ); + + return getSystem().newLocalRepositoryManager( session, repo ); + } + + private synchronized Settings getSettings() + { + if ( settings == null ) + { + DefaultSettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); + request.setUserSettingsFile( getUserSettings() ); + request.setGlobalSettingsFile( getGlobalSettings() ); + request.setSystemProperties( getSystemProperties() ); + request.setUserProperties( getUserProperties() ); + + try + { + settings = SETTINGS_BUILDER.build( request ).getEffectiveSettings(); + } + catch ( SettingsBuildingException e ) + { + project.log( "Could not process settings.xml: " + e.getMessage(), e, Project.MSG_WARN ); + } + + SettingsDecryptionResult result = + SETTINGS_DECRYPTER.decrypt( new DefaultSettingsDecryptionRequest( settings ) ); + settings.setServers( result.getServers() ); + settings.setProxies( result.getProxies() ); + } + return settings; + } + + private ProxySelector getProxySelector() + { + DefaultProxySelector selector = new DefaultProxySelector(); + + for ( Proxy proxy : proxies ) + { + selector.add( ConverterUtils.toProxy( proxy ), proxy.getNonProxyHosts() ); + } + + Settings settings = getSettings(); + for ( org.apache.maven.settings.Proxy proxy : settings.getProxies() ) + { + AuthenticationBuilder auth = new AuthenticationBuilder(); + auth.addUsername( proxy.getUsername() ).addPassword( proxy.getPassword() ); + selector.add( new org.eclipse.aether.repository.Proxy( proxy.getProtocol(), proxy.getHost(), + proxy.getPort(), auth.build() ), + proxy.getNonProxyHosts() ); + } + + return selector; + } + + private MirrorSelector getMirrorSelector() + { + DefaultMirrorSelector selector = new DefaultMirrorSelector(); + + for ( Mirror mirror : mirrors ) + { + selector.add( mirror.getId(), mirror.getUrl(), mirror.getType(), false, mirror.getMirrorOf(), null ); + } + + Settings settings = getSettings(); + for ( org.apache.maven.settings.Mirror mirror : settings.getMirrors() ) + { + selector.add( String.valueOf( mirror.getId() ), mirror.getUrl(), mirror.getLayout(), false, + mirror.getMirrorOf(), mirror.getMirrorOfLayouts() ); + } + + return selector; + } + + private AuthenticationSelector getAuthSelector() + { + DefaultAuthenticationSelector selector = new DefaultAuthenticationSelector(); + + Collection<String> ids = new HashSet<String>(); + for ( Authentication auth : authentications ) + { + List<String> servers = auth.getServers(); + if ( !servers.isEmpty() ) + { + org.eclipse.aether.repository.Authentication a = ConverterUtils.toAuthentication( auth ); + for ( String server : servers ) + { + if ( ids.add( server ) ) + { + selector.add( server, a ); + } + } + } + } + + Settings settings = getSettings(); + for ( Server server : settings.getServers() ) + { + AuthenticationBuilder auth = new AuthenticationBuilder(); + auth.addUsername( server.getUsername() ).addPassword( server.getPassword() ); + auth.addPrivateKey( server.getPrivateKey(), server.getPassphrase() ); + selector.add( server.getId(), auth.build() ); + } + + return new ConservativeAuthenticationSelector( selector ); + } + + public synchronized void setUserSettings( File file ) + { + if ( !eq( this.userSettings, file ) ) + { + settings = null; + } + this.userSettings = file; + } + + /* UT */File getUserSettings() + { + if ( userSettings == null ) + { + userSettings = AetherUtils.findUserSettings( project ); + } + return userSettings; + } + + public void setGlobalSettings( File file ) + { + if ( !eq( this.globalSettings, file ) ) + { + settings = null; + } + this.globalSettings = file; + } + + /* UT */File getGlobalSettings() + { + if ( globalSettings == null ) + { + globalSettings = AetherUtils.findGlobalSettings( project ); + } + return globalSettings; + } + + public void addProxy( Proxy proxy ) + { + proxies.add( proxy ); + } + + public void addMirror( Mirror mirror ) + { + mirrors.add( mirror ); + } + + public void addAuthentication( Authentication authentication ) + { + authentications.add( authentication ); + } + + public void setLocalRepository( LocalRepository localRepository ) + { + this.localRepository = localRepository; + } + + public Model loadModel( Task task, File pomFile, boolean local, RemoteRepositories remoteRepositories ) + { + RepositorySystemSession session = getSession( task, null ); + + remoteRepositories = + remoteRepositories == null ? AetherUtils.getDefaultRepositories( project ) : remoteRepositories; + + List<org.eclipse.aether.repository.RemoteRepository> repositories = + ConverterUtils.toRepositories( task.getProject(), session, remoteRepositories, getRemoteRepoMan() ); + + ModelResolver modelResolver = + new AntModelResolver( session, "project", getSystem(), getRemoteRepoMan(), repositories ); + + Settings settings = getSettings(); + + try + { + DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); + request.setLocationTracking( true ); + request.setProcessPlugins( false ); + if ( local ) + { + request.setPomFile( pomFile ); + request.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_STRICT ); + } + else + { + request.setModelSource( new FileModelSource( pomFile ) ); + request.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL ); + } + request.setSystemProperties( getSystemProperties() ); + request.setUserProperties( getUserProperties() ); + request.setProfiles( SettingsUtils.convert( settings.getProfiles() ) ); + request.setActiveProfileIds( settings.getActiveProfiles() ); + request.setModelResolver( modelResolver ); + return MODEL_BUILDER.build( request ).getEffectiveModel(); + } + catch ( ModelBuildingException e ) + { + throw new BuildException( "Could not load POM " + pomFile + ": " + e.getMessage(), e ); + } + } + + private Properties getSystemProperties() + { + Properties props = new Properties(); + getEnvProperties( props ); + props.putAll( System.getProperties() ); + ConverterUtils.addProperties( props, project.getProperties() ); + return props; + } + + private Properties getEnvProperties( Properties props ) + { + if ( props == null ) + { + props = new Properties(); + } + boolean envCaseInsensitive = OS_WINDOWS; + for ( Map.Entry<String, String> entry : System.getenv().entrySet() ) + { + String key = entry.getKey(); + if ( envCaseInsensitive ) + { + key = key.toUpperCase( Locale.ENGLISH ); + } + key = "env." + key; + props.put( key, entry.getValue() ); + } + return props; + } + + private Properties getUserProperties() + { + return ConverterUtils.addProperties( null, project.getUserProperties() ); + } + + /** + * Sets the default POM. + */ + public void setDefaultPom( Pom pom ) + { + this.defaultPom = pom; + } + + /** + * Returns the current default POM. + */ + public Pom getDefaultPom() + { + return defaultPom; + } + + public CollectResult collectDependencies( Task task, Dependencies dependencies, LocalRepository localRepository, + RemoteRepositories remoteRepositories ) + { + RepositorySystemSession session = getSession( task, localRepository ); + + remoteRepositories = + remoteRepositories == null ? AetherUtils.getDefaultRepositories( project ) : remoteRepositories; + + List<org.eclipse.aether.repository.RemoteRepository> repos = + ConverterUtils.toRepositories( project, session, remoteRepositories, getRemoteRepoMan() ); + + CollectRequest collectRequest = new CollectRequest(); + collectRequest.setRequestContext( "project" ); + + for ( org.eclipse.aether.repository.RemoteRepository repo : repos ) + { + task.getProject().log( "Using remote repository " + repo, Project.MSG_VERBOSE ); + collectRequest.addRepository( repo ); + } + + if ( dependencies != null ) + { + populateCollectRequest( collectRequest, task, session, dependencies, Collections.<Exclusion>emptyList() ); + } + + task.getProject().log( "Collecting dependencies", Project.MSG_VERBOSE ); + + CollectResult result; + try + { + result = getSystem().collectDependencies( session, collectRequest ); + } + catch ( DependencyCollectionException e ) + { + throw new BuildException( "Could not collect dependencies: " + e.getMessage(), e ); + } + + return result; + } + + private void populateCollectRequest( CollectRequest collectRequest, Task task, RepositorySystemSession session, + Dependencies dependencies, List<Exclusion> exclusions ) + { + List<Exclusion> globalExclusions = exclusions; + if ( !dependencies.getExclusions().isEmpty() ) + { + globalExclusions = new ArrayList<Exclusion>( exclusions ); + globalExclusions.addAll( dependencies.getExclusions() ); + } + + Collection<String> ids = new HashSet<String>(); + + for ( DependencyContainer container : dependencies.getDependencyContainers() ) + { + if ( container instanceof Dependency ) + { + Dependency dep = (Dependency) container; + ids.add( dep.getVersionlessKey() ); + collectRequest.addDependency( ConverterUtils.toDependency( dep, globalExclusions, session ) ); + } + else + { + populateCollectRequest( collectRequest, task, session, (Dependencies) container, globalExclusions ); + } + } + + if ( dependencies.getPom() != null ) + { + Model model = dependencies.getPom().getModel( task ); + for ( org.apache.maven.model.Dependency dep : model.getDependencies() ) + { + Dependency dependency = new Dependency(); + dependency.setArtifactId( dep.getArtifactId() ); + dependency.setClassifier( dep.getClassifier() ); + dependency.setGroupId( dep.getGroupId() ); + dependency.setScope( dep.getScope() ); + dependency.setType( dep.getType() ); + dependency.setVersion( dep.getVersion() ); + if ( ids.contains( dependency.getVersionlessKey() ) ) + { + project.log( "Ignoring dependency " + dependency.getVersionlessKey() + " from " + model.getId() + + ", already declared locally", Project.MSG_VERBOSE ); + continue; + } + if ( dep.getSystemPath() != null && dep.getSystemPath().length() > 0 ) + { + dependency.setSystemPath( task.getProject().resolveFile( dep.getSystemPath() ) ); + } + for ( org.apache.maven.model.Exclusion exc : dep.getExclusions() ) + { + Exclusion exclusion = new Exclusion(); + exclusion.setGroupId( exc.getGroupId() ); + exclusion.setArtifactId( exc.getArtifactId() ); + exclusion.setClassifier( "*" ); + exclusion.setExtension( "*" ); + dependency.addExclusion( exclusion ); + } + collectRequest.addDependency( ConverterUtils.toDependency( dependency, globalExclusions, session ) ); + } + } + + if ( dependencies.getFile() != null ) + { + List<Dependency> deps = readDependencies( dependencies.getFile() ); + for ( Dependency dependency : deps ) + { + if ( ids.contains( dependency.getVersionlessKey() ) ) + { + project.log( "Ignoring dependency " + dependency.getVersionlessKey() + " from " + + dependencies.getFile() + ", already declared locally", Project.MSG_VERBOSE ); + continue; + } + collectRequest.addDependency( ConverterUtils.toDependency( dependency, globalExclusions, session ) ); + } + } + } + + private List<Dependency> readDependencies( File file ) + { + List<Dependency> dependencies = new ArrayList<Dependency>(); + try + { + BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream( file ), "UTF-8" ) ); + try + { + for ( String line = reader.readLine(); line != null; line = reader.readLine() ) + { + int comment = line.indexOf( '#' ); + if ( comment >= 0 ) + { + line = line.substring( 0, comment ); + } + line = line.trim(); + if ( line.length() <= 0 ) + { + continue; + } + Dependency dependency = new Dependency(); + dependency.setCoords( line ); + dependencies.add( dependency ); + } + } + finally + { + reader.close(); + } + } + catch ( IOException e ) + { + throw new BuildException( "Cannot read " + file, e ); + } + return dependencies; + } + + public void install( Task task, Pom pom, Artifacts artifacts ) + { + RepositorySystemSession session = getSession( task, null ); + + InstallRequest request = new InstallRequest(); + request.setArtifacts( toArtifacts( task, session, pom, artifacts ) ); + + try + { + getSystem().install( session, request ); + } + catch ( InstallationException e ) + { + throw new BuildException( "Could not install artifacts: " + e.getMessage(), e ); + } + } + + public void deploy( Task task, Pom pom, Artifacts artifacts, RemoteRepository releaseRepository, + RemoteRepository snapshotRepository ) + { + RepositorySystemSession session = getSession( task, null ); + + DeployRequest request = new DeployRequest(); + request.setArtifacts( toArtifacts( task, session, pom, artifacts ) ); + boolean snapshot = request.getArtifacts().iterator().next().isSnapshot(); + RemoteRepository distRepo = ( snapshot && snapshotRepository != null ) ? snapshotRepository : releaseRepository; + request.setRepository( ConverterUtils.toDistRepository( distRepo, session ) ); + + try + { + getSystem().deploy( session, request ); + } + catch ( DeploymentException e ) + { + throw new BuildException( "Could not deploy artifacts: " + e.getMessage(), e ); + } + } + + private List<org.eclipse.aether.artifact.Artifact> toArtifacts( Task task, RepositorySystemSession session, + Pom pom, Artifacts artifacts ) + { + Model model = pom.getModel( task ); + File pomFile = pom.getFile(); + + List<org.eclipse.aether.artifact.Artifact> results = new ArrayList<org.eclipse.aether.artifact.Artifact>(); + + org.eclipse.aether.artifact.Artifact pomArtifact = + new DefaultArtifact( model.getGroupId(), model.getArtifactId(), "pom", model.getVersion() ).setFile( pomFile ); + results.add( pomArtifact ); + + for ( Artifact artifact : artifacts.getArtifacts() ) + { + org.eclipse.aether.artifact.Artifact buildArtifact = + new DefaultArtifact( model.getGroupId(), model.getArtifactId(), artifact.getClassifier(), + artifact.getType(), model.getVersion() ).setFile( artifact.getFile() ); + results.add( buildArtifact ); + } + + return results; + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AntRepositoryListener.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AntRepositoryListener.java b/src/main/java/org/apache/maven/aether/internal/ant/AntRepositoryListener.java new file mode 100644 index 0000000..6a7f325 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AntRepositoryListener.java @@ -0,0 +1,123 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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.io.FileNotFoundException; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.eclipse.aether.AbstractRepositoryListener; +import org.eclipse.aether.RepositoryEvent; +import org.eclipse.aether.transfer.MetadataNotFoundException; + +/** + * Logs repository events like installed and unresolved artifacts and metadata. + */ +class AntRepositoryListener + extends AbstractRepositoryListener +{ + + private Task task; + + public AntRepositoryListener( Task task ) + { + this.task = task; + } + + @Override + public void artifactInstalling( RepositoryEvent event ) + { + task.log( "Installing " + event.getArtifact().getFile() + " to " + event.getFile() ); + } + + @Override + public void metadataInstalling( RepositoryEvent event ) + { + task.log( "Installing " + event.getMetadata() + " to " + event.getFile() ); + } + + @Override + public void metadataResolved( RepositoryEvent event ) + { + Exception e = event.getException(); + if ( e != null ) + { + if ( e instanceof MetadataNotFoundException ) + { + task.log( e.getMessage(), Project.MSG_DEBUG ); + } + else + { + task.log( e.getMessage(), e, Project.MSG_WARN ); + } + } + } + + @Override + public void metadataInvalid( RepositoryEvent event ) + { + Exception exception = event.getException(); + + StringBuilder buffer = new StringBuilder( 256 ); + buffer.append( "The metadata " ); + if ( event.getMetadata().getFile() != null ) + { + buffer.append( event.getMetadata().getFile() ); + } + else + { + buffer.append( event.getMetadata() ); + } + + if ( exception instanceof FileNotFoundException ) + { + buffer.append( " is inaccessible" ); + } + else + { + buffer.append( " is invalid" ); + } + + if ( exception != null ) + { + buffer.append( ": " ); + buffer.append( exception.getMessage() ); + } + + task.log( buffer.toString(), exception, Project.MSG_WARN ); + } + + @Override + public void artifactDescriptorInvalid( RepositoryEvent event ) + { + task.log( "The POM for " + event.getArtifact() + " is invalid" + + ", transitive dependencies (if any) will not be available: " + + event.getException().getMessage(), + event.getException(), Project.MSG_WARN ); + }; + + @Override + public void artifactDescriptorMissing( RepositoryEvent event ) + { + task.log( "The POM for " + event.getArtifact() + " is missing, no dependency information available", + Project.MSG_WARN ); + }; + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AntSecDispatcher.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AntSecDispatcher.java b/src/main/java/org/apache/maven/aether/internal/ant/AntSecDispatcher.java new file mode 100644 index 0000000..07de15c --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AntSecDispatcher.java @@ -0,0 +1,45 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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 org.sonatype.plexus.components.cipher.DefaultPlexusCipher; +import org.sonatype.plexus.components.cipher.PlexusCipherException; +import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; + +/** + */ +class AntSecDispatcher + extends DefaultSecDispatcher +{ + + public AntSecDispatcher() + { + _configurationFile = "~/.m2/settings-security.xml"; + try + { + _cipher = new DefaultPlexusCipher(); + } + catch ( PlexusCipherException e ) + { + e.printStackTrace(); + } + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AntServiceLocatorErrorHandler.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AntServiceLocatorErrorHandler.java b/src/main/java/org/apache/maven/aether/internal/ant/AntServiceLocatorErrorHandler.java new file mode 100644 index 0000000..5816cf7 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AntServiceLocatorErrorHandler.java @@ -0,0 +1,50 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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 org.apache.tools.ant.Project; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.impl.DefaultServiceLocator; + +/** + */ +class AntServiceLocatorErrorHandler + extends DefaultServiceLocator.ErrorHandler +{ + + private Project project; + + public AntServiceLocatorErrorHandler( Project project ) + { + this.project = project; + } + + public void serviceCreationFailed( Class<?> type, Class<?> impl, Throwable exception ) + { + String msg = "Could not initialize repository system"; + if ( !RepositorySystem.class.equals( type ) ) + { + msg += ", service " + type.getName() + " (" + impl.getName() + ") failed to initialize"; + } + msg += ": " + exception.getMessage(); + project.log( msg, exception, Project.MSG_ERR ); + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AntSettingsDecryptorFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AntSettingsDecryptorFactory.java b/src/main/java/org/apache/maven/aether/internal/ant/AntSettingsDecryptorFactory.java new file mode 100644 index 0000000..b22d20e --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AntSettingsDecryptorFactory.java @@ -0,0 +1,51 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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.lang.reflect.Field; + +import org.apache.maven.settings.crypto.DefaultSettingsDecrypter; + +/** + */ +class AntSettingsDecryptorFactory +{ + + public DefaultSettingsDecrypter newInstance() + { + AntSecDispatcher secDispatcher = new AntSecDispatcher(); + + DefaultSettingsDecrypter decrypter = new DefaultSettingsDecrypter(); + + try + { + Field field = decrypter.getClass().getDeclaredField( "securityDispatcher" ); + field.setAccessible( true ); + field.set( decrypter, secDispatcher ); + } + catch ( Exception e ) + { + throw new IllegalStateException( e ); + } + + return decrypter; + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/AntTransferListener.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/AntTransferListener.java b/src/main/java/org/apache/maven/aether/internal/ant/AntTransferListener.java new file mode 100644 index 0000000..d4faea4 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/AntTransferListener.java @@ -0,0 +1,91 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.Locale; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.eclipse.aether.transfer.AbstractTransferListener; +import org.eclipse.aether.transfer.TransferCancelledException; +import org.eclipse.aether.transfer.TransferEvent; +import org.eclipse.aether.transfer.TransferResource; + +/** + * Logs up- and downloads. + */ +class AntTransferListener + extends AbstractTransferListener +{ + + private Task task; + + public AntTransferListener( Task task ) + { + this.task = task; + } + + @Override + public void transferInitiated( TransferEvent event ) + throws TransferCancelledException + { + String msg = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading"; + msg += " " + event.getResource().getRepositoryUrl() + event.getResource().getResourceName(); + task.log( msg ); + } + + @Override + public void transferCorrupted( TransferEvent event ) + throws TransferCancelledException + { + TransferResource resource = event.getResource(); + + task.log( event.getException().getMessage() + " for " + resource.getRepositoryUrl() + + resource.getResourceName(), Project.MSG_WARN ); + } + + @Override + public void transferSucceeded( TransferEvent event ) + { + String msg = event.getRequestType() == TransferEvent.RequestType.PUT ? "Uploaded" : "Downloaded"; + msg += " " + event.getResource().getRepositoryUrl() + event.getResource().getResourceName(); + + long contentLength = event.getTransferredBytes(); + if ( contentLength >= 0 ) + { + String len = contentLength >= 1024 ? ( ( contentLength + 1023 ) / 1024 ) + " KB" : contentLength + " B"; + + String throughput = ""; + long duration = System.currentTimeMillis() - event.getResource().getTransferStartTime(); + if ( duration > 0 ) + { + DecimalFormat format = new DecimalFormat( "0.0", new DecimalFormatSymbols( Locale.ENGLISH ) ); + double kbPerSec = ( contentLength / 1024.0 ) / ( duration / 1000.0 ); + throughput = " at " + format.format( kbPerSec ) + " KB/sec"; + } + + msg += " (" + len + throughput + ")"; + } + task.log( msg ); + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/ConverterUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/ConverterUtils.java b/src/main/java/org/apache/maven/aether/internal/ant/ConverterUtils.java new file mode 100644 index 0000000..d6ff28f --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/ConverterUtils.java @@ -0,0 +1,227 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.maven.aether.internal.ant.types.Authentication; +import org.apache.maven.aether.internal.ant.types.Dependency; +import org.apache.maven.aether.internal.ant.types.Exclusion; +import org.apache.maven.aether.internal.ant.types.Proxy; +import org.apache.maven.aether.internal.ant.types.RemoteRepositories; +import org.apache.maven.aether.internal.ant.types.RemoteRepository; +import org.apache.tools.ant.Project; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.ArtifactProperties; +import org.eclipse.aether.artifact.ArtifactType; +import org.eclipse.aether.artifact.ArtifactTypeRegistry; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.artifact.DefaultArtifactType; +import org.eclipse.aether.impl.RemoteRepositoryManager; +import org.eclipse.aether.repository.RepositoryPolicy; +import org.eclipse.aether.util.repository.AuthenticationBuilder; + +/** + * Utility methods to convert between Aether and Ant objects. + */ +class ConverterUtils +{ + + private static org.eclipse.aether.artifact.Artifact toArtifact( Dependency dependency, ArtifactTypeRegistry types ) + { + ArtifactType type = types.get( dependency.getType() ); + if ( type == null ) + { + type = new DefaultArtifactType( dependency.getType() ); + } + + Map<String, String> props = null; + if ( "system".equals( dependency.getScope() ) && dependency.getSystemPath() != null ) + { + props = Collections.singletonMap( ArtifactProperties.LOCAL_PATH, dependency.getSystemPath().getPath() ); + } + + Artifact artifact = + new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), dependency.getClassifier(), null, + dependency.getVersion(), props, type ); + + return artifact; + } + + public static org.eclipse.aether.repository.Authentication toAuthentication( Authentication auth ) + { + if ( auth == null ) + { + return null; + } + AuthenticationBuilder authBuilder = new AuthenticationBuilder(); + authBuilder.addUsername( auth.getUsername() ).addPassword( auth.getPassword() ); + authBuilder.addPrivateKey( auth.getPrivateKeyFile(), auth.getPassphrase() ); + return authBuilder.build(); + } + + public static org.eclipse.aether.graph.Dependency toDependency( Dependency dependency, List<Exclusion> exclusions, + RepositorySystemSession session ) + { + return new org.eclipse.aether.graph.Dependency( toArtifact( dependency, session.getArtifactTypeRegistry() ), + dependency.getScope(), false, + toExclusions( dependency.getExclusions(), exclusions ) ); + } + + /** + * Converts the given ant repository type to an Aether repository instance with authentication and proxy filled in + * via the sessions' selectors. + */ + public static org.eclipse.aether.repository.RemoteRepository toDistRepository( RemoteRepository repo, + RepositorySystemSession session ) + { + org.eclipse.aether.repository.RemoteRepository result = toRepository( repo ); + org.eclipse.aether.repository.RemoteRepository.Builder builder = + new org.eclipse.aether.repository.RemoteRepository.Builder( result ); + builder.setAuthentication( session.getAuthenticationSelector().getAuthentication( result ) ); + builder.setProxy( session.getProxySelector().getProxy( result ) ); + return builder.build(); + } + + private static org.eclipse.aether.graph.Exclusion toExclusion( Exclusion exclusion ) + { + return new org.eclipse.aether.graph.Exclusion( exclusion.getGroupId(), exclusion.getArtifactId(), + exclusion.getClassifier(), exclusion.getExtension() ); + } + + private static Collection<org.eclipse.aether.graph.Exclusion> toExclusions( Collection<Exclusion> exclusions1, + Collection<Exclusion> exclusions2 ) + { + Collection<org.eclipse.aether.graph.Exclusion> results = + new LinkedHashSet<org.eclipse.aether.graph.Exclusion>(); + if ( exclusions1 != null ) + { + for ( Exclusion exclusion : exclusions1 ) + { + results.add( toExclusion( exclusion ) ); + } + } + if ( exclusions2 != null ) + { + for ( Exclusion exclusion : exclusions2 ) + { + results.add( toExclusion( exclusion ) ); + } + } + return results; + } + + private static RepositoryPolicy toPolicy( RemoteRepository.Policy policy, boolean enabled, String updates, + String checksums ) + { + if ( policy != null ) + { + enabled = policy.isEnabled(); + if ( policy.getChecksums() != null ) + { + checksums = policy.getChecksums(); + } + if ( policy.getUpdates() != null ) + { + updates = policy.getUpdates(); + } + } + return new RepositoryPolicy( enabled, updates, checksums ); + } + + /** + * Adds every <String, String>-entry in the map as a property to the given Properties. + */ + public static Properties addProperties( Properties props, Map<?, ?> map ) + { + if ( props == null ) + { + props = new Properties(); + } + for ( Map.Entry<?, ?> entry : map.entrySet() ) + { + if ( entry.getKey() instanceof String && entry.getValue() instanceof String ) + { + props.put( entry.getKey(), entry.getValue() ); + } + } + return props; + } + + public static org.eclipse.aether.repository.Proxy toProxy( Proxy proxy ) + { + if ( proxy == null ) + { + return null; + } + return new org.eclipse.aether.repository.Proxy( proxy.getType(), proxy.getHost(), proxy.getPort(), + toAuthentication( proxy.getAuthentication() ) ); + } + + private static org.eclipse.aether.repository.RemoteRepository toRepository( RemoteRepository repo ) + { + org.eclipse.aether.repository.RemoteRepository.Builder builder = + new org.eclipse.aether.repository.RemoteRepository.Builder( repo.getId(), repo.getType(), repo.getUrl() ); + builder.setSnapshotPolicy( toPolicy( repo.getSnapshotPolicy(), repo.isSnapshots(), repo.getUpdates(), + repo.getChecksums() ) ); + builder.setReleasePolicy( toPolicy( repo.getReleasePolicy(), repo.isReleases(), repo.getUpdates(), + repo.getChecksums() ) ); + builder.setAuthentication( toAuthentication( repo.getAuthentication() ) ); + return builder.build(); + } + + public static List<org.eclipse.aether.repository.RemoteRepository> toRepositories( Project project, + RepositorySystemSession session, + RemoteRepositories repos, RemoteRepositoryManager remoteRepositoryManager ) + { + List<RemoteRepository> repositories; + + if ( repos != null ) + { + repositories = repos.getRepositories(); + } + else + { + repositories = new ArrayList<RemoteRepository>(); + } + + List<org.eclipse.aether.repository.RemoteRepository> results = + new ArrayList<org.eclipse.aether.repository.RemoteRepository>(); + for ( RemoteRepository repo : repositories ) + { + results.add( toRepository( repo ) ); + } + + results = + remoteRepositoryManager.aggregateRepositories( session, + Collections.<org.eclipse.aether.repository.RemoteRepository>emptyList(), + results, true ); + + return results; + } + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/Names.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/Names.java b/src/main/java/org/apache/maven/aether/internal/ant/Names.java new file mode 100644 index 0000000..5ce8427 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/Names.java @@ -0,0 +1,44 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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. + */ + +/** + */ +public final class Names +{ + + private Names() + { + // hide constructor + } + + public static final String ID = "aether"; + + public static final String ID_DEFAULT_REPOS = ID + ".repositories"; + + public static final String ID_DEFAULT_POM = ID + ".pom"; + + public static final String ID_CENTRAL = "central"; + + public static final String PROPERTY_OFFLINE = "aether.offline"; + + public static final String SETTINGS_XML = "settings.xml"; + +} http://git-wip-us.apache.org/repos/asf/maven-aether/blob/261b17db/src/main/java/org/apache/maven/aether/internal/ant/ProjectWorkspaceReader.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/maven/aether/internal/ant/ProjectWorkspaceReader.java b/src/main/java/org/apache/maven/aether/internal/ant/ProjectWorkspaceReader.java new file mode 100644 index 0000000..7c77fc8 --- /dev/null +++ b/src/main/java/org/apache/maven/aether/internal/ant/ProjectWorkspaceReader.java @@ -0,0 +1,144 @@ +package org.apache.maven.aether.internal.ant; + +/* + * 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.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.maven.aether.internal.ant.types.Pom; +import org.apache.maven.model.Model; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.repository.WorkspaceReader; +import org.eclipse.aether.repository.WorkspaceRepository; +import org.eclipse.aether.util.artifact.ArtifactIdUtils; + +/** + * Workspace reader caching available POMs and artifacts for ant builds. + * <p/> + * <pom> elements are cached if they are defined by the 'file'-attribute, as they reference a backing pom.xml file that + * can be used for resolution with Aether. <artifact> elements are cached if they directly define a 'pom'-attribute + * or child. The POM may be file-based or in-memory. + */ +public class ProjectWorkspaceReader + implements WorkspaceReader +{ + + private static volatile ProjectWorkspaceReader instance; + + private static final Object LOCK = new Object(); + + private Map<String, Artifact> artifacts = new ConcurrentHashMap<String, Artifact>(); + + public void addPom( Pom pom ) + { + if ( pom.getFile() != null ) + { + Model model = pom.getModel( pom ); + Artifact aetherArtifact = + new DefaultArtifact( model.getGroupId(), model.getArtifactId(), null, "pom", model.getVersion() ); + aetherArtifact = aetherArtifact.setFile( pom.getFile() ); + String coords = coords( aetherArtifact ); + artifacts.put( coords, aetherArtifact ); + } + } + + public void addArtifact( org.apache.maven.aether.internal.ant.types.Artifact artifact ) + { + if ( artifact.getPom() != null ) + { + Pom pom = artifact.getPom(); + Artifact aetherArtifact; + if ( pom.getFile() != null ) + { + Model model = pom.getModel( pom ); + aetherArtifact = + new DefaultArtifact( model.getGroupId(), model.getArtifactId(), artifact.getClassifier(), + artifact.getType(), model.getVersion() ); + } + else + { + aetherArtifact = + new DefaultArtifact( pom.getGroupId(), pom.getArtifactId(), artifact.getClassifier(), + artifact.getType(), pom.getVersion() ); + } + aetherArtifact = aetherArtifact.setFile( artifact.getFile() ); + + String coords = coords( aetherArtifact ); + artifacts.put( coords, aetherArtifact ); + } + } + + private String coords( Artifact artifact ) + { + return ArtifactIdUtils.toId( artifact ); + } + + public WorkspaceRepository getRepository() + { + return new WorkspaceRepository( "ant" ); + } + + public File findArtifact( Artifact artifact ) + { + artifact = artifacts.get( coords( artifact ) ); + return ( artifact != null ) ? artifact.getFile() : null; + } + + public List<String> findVersions( Artifact artifact ) + { + List<String> versions = new ArrayList<String>(); + for ( Artifact art : artifacts.values() ) + { + if ( ArtifactIdUtils.equalsVersionlessId( artifact, art ) ) + { + versions.add( art.getVersion() ); + } + } + return versions; + } + + ProjectWorkspaceReader() + { + } + + public static ProjectWorkspaceReader getInstance() + { + if ( instance == null ) + { + synchronized ( LOCK ) + { + if ( instance == null ) + { + instance = new ProjectWorkspaceReader(); + } + } + } + return instance; + } + + static void dropInstance() + { + instance = null; + } +}