2 * Copyright 2001-2005 The Apache Software Foundation.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.opendaylight.odlparent;
20 import java.io.FileInputStream;
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
24 import java.net.URISyntaxException;
26 import java.util.Enumeration;
27 import java.util.HashMap;
28 import java.util.LinkedHashSet;
29 import java.util.List;
31 import java.util.Properties;
33 import org.apache.karaf.features.internal.model.Features;
34 import org.apache.maven.plugin.AbstractMojo;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.plugin.MojoFailureException;
37 import org.apache.maven.project.MavenProject;
38 import org.eclipse.aether.RepositorySystem;
39 import org.eclipse.aether.RepositorySystemSession;
40 import org.eclipse.aether.artifact.Artifact;
41 import org.eclipse.aether.repository.RemoteRepository;
42 import org.opendaylight.odlparent.karafutil.CustomBundleUrlStreamHandlerFactory;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 // TODO: Use org.apache.maven.plugin.annotations.* to allow more flexibility for non-ODL consumers.
49 * Mojo populating the local repository by delegating to Aether.
51 * @goal populate-local-repo
52 * @phase prepare-package
54 // URL.setURLStreamHandlerFactory throws an Error directly, so we can’t do any better than this...
55 @SuppressWarnings("checkstyle:IllegalCatch")
56 public class PopulateLocalRepoMojo
57 extends AbstractMojo {
58 private static final Logger LOG = LoggerFactory.getLogger(PopulateLocalRepoMojo.class);
61 // Static initialization, as we may be invoked multiple times
62 // karaf-maven-plugin defines its own URLStreamHandlerFactory for install-kars, so we may find a factory
63 // already defined (but it handles "mvn:" and "wrap:mvn:" so we should be OK)
65 URL.setURLStreamHandlerFactory(new CustomBundleUrlStreamHandlerFactory());
67 LOG.warn("populate-local-repo: URL factory is already defined");
72 * The Maven project being built.
78 private MavenProject project;
81 * The entry point to Aether, i.e. the component doing all the work.
85 private RepositorySystem repoSystem;
88 * The current repository/network configuration of Maven.
90 * @parameter default-value="${repositorySystemSession}"
93 private RepositorySystemSession repoSession;
96 * The project's remote repositories to use for the resolution of plugins and their dependencies.
98 * @parameter default-value="${project.remoteProjectRepositories}"
101 private List<RemoteRepository> remoteRepos;
104 * The local repository to use for the resolution of plugins and their dependencies.
108 private File localRepo;
110 private AetherUtil aetherUtil;
113 public void execute() throws MojoExecutionException, MojoFailureException {
115 aetherUtil = new AetherUtil(repoSystem, repoSession, remoteRepos, localRepo);
117 Set<Artifact> startupArtifacts = readStartupProperties();
118 aetherUtil.installArtifacts(startupArtifacts);
119 Set<Artifact> featureArtifacts = new LinkedHashSet<>();
120 Set<Features> features = new LinkedHashSet<>();
121 readFeatureCfg(featureArtifacts, features);
122 featureArtifacts.addAll(
123 aetherUtil.resolveDependencies(MvnToAetherMapper.toAether(project.getDependencies()),
124 new KarafFeaturesDependencyFilter()));
125 features.addAll(FeatureUtil.readFeatures(featureArtifacts));
126 // Do not provide FeatureUtil.featuresRepositoryToCoords(features)) as existingCoords
127 // to findAllFeaturesRecursively, as those coords are not resolved yet, and it would lead to Bug 6187.
128 features.addAll(FeatureUtil.findAllFeaturesRecursively(aetherUtil, features));
129 for (Features feature : features) {
130 LOG.info("Feature repository discovered recursively: {}", feature.getName());
132 Set<Artifact> artifacts = aetherUtil.resolveArtifacts(FeatureUtil.featuresToCoords(features));
133 artifacts.addAll(featureArtifacts);
135 Map<Gace, String> gaceVersions = new HashMap<>();
136 for (Artifact artifact : artifacts) {
137 LOG.debug("Artifact to be installed: {}", artifact.toString());
138 Gace gace = new Gace(artifact);
139 String duplicate = gaceVersions.putIfAbsent(gace, artifact.getVersion());
140 if (duplicate != null && !duplicate.equals(artifact.getVersion())) {
141 LOG.warn("Duplicate versions for {}, {} and {}", gace, duplicate, artifact.getVersion());
144 if (localRepo != null) {
145 aetherUtil.installArtifacts(artifacts);
147 } catch (Exception e) {
148 throw new MojoExecutionException("Failed to execute", e);
152 private void readFeatureCfg(Set<Artifact> artifacts, Set<Features> features) {
153 String karafHome = localRepo.getParent();
154 File file = new File(karafHome + "/etc/org.apache.karaf.features.cfg");
155 Properties prop = new Properties();
157 prop.load(new FileInputStream(file));
158 String featuresRepositories = prop.getProperty("featuresRepositories");
159 for (String mvnUrl : featuresRepositories.split(",")) {
160 String fixedUrl = mvnUrl.replace("${karaf.home}", karafHome);
161 if (fixedUrl.startsWith("file:")) {
163 // Local feature file
164 features.add(FeatureUtil.readFeature(new File(new URI(fixedUrl))));
165 } catch (URISyntaxException e) {
166 LOG.info("Could not resolve URI: {}", fixedUrl, e);
169 artifacts.add(aetherUtil.resolveArtifact(FeatureUtil.toCoord(new URL(fixedUrl))));
172 } catch (FileNotFoundException e) {
173 LOG.info("Could not find properties file: {}", file.getAbsolutePath(), e);
174 } catch (IOException e) {
175 LOG.info("Could not read properties file: {}", file.getAbsolutePath(), e);
179 private Set<Artifact> readStartupProperties() {
180 Set<Artifact> artifacts = new LinkedHashSet<>();
181 File file = new File(localRepo.getParentFile().toString() + "/etc/startup.properties");
182 Properties prop = new Properties();
184 prop.load(new FileInputStream(file));
185 Enumeration<Object> mvnUrls = prop.keys();
186 while (mvnUrls.hasMoreElements()) {
187 String mvnUrl = (String) mvnUrls.nextElement();
188 Artifact artifact = aetherUtil.resolveArtifact(FeatureUtil.toCoord(new URL(mvnUrl)));
189 artifacts.add(artifact);
191 } catch (FileNotFoundException e) {
192 LOG.info("Could not find properties file: {}", file.getAbsolutePath(), e);
193 } catch (IOException e) {
194 LOG.info("Could not read properties file: {}", file.getAbsolutePath(), e);