2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.odlparent;
12 import java.io.FileInputStream;
13 import java.io.FileNotFoundException;
14 import java.net.MalformedURLException;
16 import java.util.ArrayList;
17 import java.util.LinkedHashSet;
18 import java.util.List;
20 import org.apache.karaf.features.internal.model.Bundle;
21 import org.apache.karaf.features.internal.model.ConfigFile;
22 import org.apache.karaf.features.internal.model.Feature;
23 import org.apache.karaf.features.internal.model.Features;
24 import org.apache.karaf.features.internal.model.JaxbUtil;
25 import org.eclipse.aether.artifact.Artifact;
26 import org.eclipse.aether.resolution.ArtifactResolutionException;
27 import org.ops4j.pax.url.mvn.internal.Parser;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 public final class FeatureUtil {
32 private static final Logger LOG = LoggerFactory.getLogger(FeatureUtil.class);
34 private FeatureUtil() {
35 throw new UnsupportedOperationException();
39 * Converts the given list of URLs to artifact coordinates.
41 * @param urls The URLs.
42 * @return The corresponding artifact coordinates.
43 * @throws MalformedURLException if a URL is malformed.
45 public static List<String> toCoord(List<URL> urls) throws MalformedURLException {
46 List<String> result = new ArrayList<>();
47 for (URL url : urls) {
48 result.add(toCoord(url));
50 LOG.trace("toCoord({}) returns {}", urls, result);
55 * Converts the given URL to artifact coordinates.
58 * @return The corresponding artifact coordinates.
59 * @throws MalformedURLException if the URL is malformed.
61 public static String toCoord(URL url) throws MalformedURLException {
62 String repository = url.toString();
63 String unwrappedRepo = repository.replaceFirst("wrap:", "");
64 Parser parser = new Parser(unwrappedRepo);
65 String coord = parser.getGroup().replace("mvn:", "") + ":" + parser.getArtifact();
66 if (parser.getType() != null) {
67 coord = coord + ":" + parser.getType();
69 if (parser.getClassifier() != null) {
70 coord = coord + ":" + parser.getClassifier();
72 coord = coord + ":" + parser.getVersion().replaceAll("\\$.*$", "");
73 LOG.trace("toCoord({}) returns {}", url, coord);
78 * Parses the given repository as URLs and converts them to artifact coordinates.
80 * @param repository The repository (list of URLs).
81 * @return The corresponding artifact coordinates.
82 * @throws MalformedURLException if a URL is malformed.
84 public static Set<String> mvnUrlsToCoord(List<String> repository) throws MalformedURLException {
85 Set<String> result = new LinkedHashSet<>();
86 for (String url : repository) {
87 result.add(toCoord(new URL(url)));
89 LOG.trace("mvnUrlsToCoord({}) returns {}", repository, result);
94 * Converts the given features' repository to artifact coordinates.
96 * @param features The features.
97 * @return The corresponding artifact coordinates.
98 * @throws MalformedURLException if a URL is malformed.
100 public static Set<String> featuresRepositoryToCoords(Features features) throws MalformedURLException {
101 return mvnUrlsToCoord(features.getRepository());
105 * Converts all the given features' repositories to artifact coordinates.
107 * @param features The features.
108 * @return The corresponding artifact coordinates.
109 * @throws MalformedURLException if a URL is malformed.
111 public static Set<String> featuresRepositoryToCoords(Set<Features> features) throws MalformedURLException {
112 Set<String> result = new LinkedHashSet<>();
113 for (Features feature : features) {
114 result.addAll(featuresRepositoryToCoords(feature));
116 LOG.trace("featuresRepositoryToCoords({}) returns {}", features, result);
121 * Lists the artifact coordinates of the given feature's bundles and configuration files.
123 * @param feature The feature.
124 * @return The corresponding coordinates.
125 * @throws MalformedURLException if a URL is malformed.
127 public static Set<String> featureToCoords(Feature feature) throws MalformedURLException {
128 Set<String> result = new LinkedHashSet<>();
129 if (feature.getBundle() != null) {
130 result.addAll(bundlesToCoords(feature.getBundle()));
132 if (feature.getConfigfile() != null) {
133 result.addAll(configFilesToCoords(feature.getConfigfile()));
135 LOG.trace("featureToCoords({}) returns {}", feature.getName(), result);
140 * Lists the artifact coordinates of the given configuration files.
142 * @param configfiles The configuration files.
143 * @return The corresponding coordinates.
144 * @throws MalformedURLException if a URL is malformed.
146 public static Set<String> configFilesToCoords(List<ConfigFile> configfiles) throws MalformedURLException {
147 Set<String> result = new LinkedHashSet<>();
148 for (ConfigFile configFile : configfiles) {
149 result.add(toCoord(new URL(configFile.getLocation())));
151 LOG.trace("configFilesToCoords({}) returns {}", configfiles, result);
156 * Lists the artifact coordinates of the given bundles.
158 * @param bundles The bundles.
159 * @return The corresponding coordinates.
160 * @throws MalformedURLException if a URL is malformed.
162 public static Set<String> bundlesToCoords(List<Bundle> bundles) throws MalformedURLException {
163 Set<String> result = new LinkedHashSet<>();
164 for (Bundle bundle : bundles) {
165 result.add(toCoord(new URL(bundle.getLocation())));
167 LOG.trace("bundlesToCoords({}) returns {}", bundles, result);
172 * Extracts all the artifact coordinates for the given features (repositories, bundles, configuration files).
174 * @param features The feature.
175 * @return The artifact coordinates.
176 * @throws MalformedURLException if a URL is malformed.
178 public static Set<String> featuresToCoords(Features features) throws MalformedURLException {
179 Set<String> result = new LinkedHashSet<>();
180 if (features.getRepository() != null) {
181 result.addAll(featuresRepositoryToCoords(features));
183 if (features.getFeature() != null) {
184 for (Feature feature : features.getFeature()) {
185 result.addAll(featureToCoords(feature));
188 LOG.trace("featuresToCoords({}) returns {}", features.getName(), result);
193 * Extracts all the artifact coordinates for the given set of features (repositories, bundles, configuration
196 * @param features The features.
197 * @return The artifact coordinates.
198 * @throws MalformedURLException if a URL is malformed.
200 public static Set<String> featuresToCoords(Set<Features> features) throws MalformedURLException {
201 Set<String> result = new LinkedHashSet<>();
202 for (Features feature : features) {
203 result.addAll(featuresToCoords(feature));
205 LOG.trace("featuresToCoords({}) returns {}", features, result);
210 * Unmarshal all the features in the given artifacts.
212 * @param featureArtifacts The artifacts.
213 * @return The features.
214 * @throws FileNotFoundException if a file is missing.
216 public static Set<Features> readFeatures(Set<Artifact> featureArtifacts) throws FileNotFoundException {
217 Set<Features> result = new LinkedHashSet<>();
218 for (Artifact artifact : featureArtifacts) {
219 result.add(readFeature(artifact));
221 LOG.trace("readFeatures({}) returns {}", featureArtifacts, result);
226 * Unmarshal the features in the given artifact.
228 * @param artifact The artifact.
229 * @return The features.
230 * @throws FileNotFoundException if a file is missing.
232 public static Features readFeature(Artifact artifact) throws FileNotFoundException {
233 File file = artifact.getFile();
234 FileInputStream stream = new FileInputStream(file);
235 Features result = JaxbUtil.unmarshal(stream, false);
236 LOG.trace("readFeature({}) returns {} without resolving first", artifact, result.getName());
241 * Unmarshal the features matching the given artifact coordinates.
243 * @param aetherUtil The Aether resolver.
244 * @param coords The artifact coordinates.
245 * @return The features.
246 * @throws ArtifactResolutionException if the coordinates can't be resolved.
247 * @throws FileNotFoundException if a file is missing.
249 public static Features readFeature(AetherUtil aetherUtil, String coords)
250 throws ArtifactResolutionException, FileNotFoundException {
251 Artifact artifact = aetherUtil.resolveArtifact(coords);
252 Features result = readFeature(artifact);
253 LOG.trace("readFeature({}) returns {} after resolving first", coords, result.getName());
258 * Unmarshals all the features starting from the given feature.
260 * @param aetherUtil The Aether resolver.
261 * @param features The starting features.
262 * @param existingCoords The artifact coordinates which have already been unmarshalled.
263 * @return The features.
264 * @throws MalformedURLException if a URL is malformed.
265 * @throws FileNotFoundException if a file is missing.
266 * @throws ArtifactResolutionException if artifact coordinates can't be resolved.
268 public static Set<Features> findAllFeaturesRecursively(
269 AetherUtil aetherUtil, Features features, Set<String> existingCoords)
270 throws MalformedURLException, FileNotFoundException, ArtifactResolutionException {
271 LOG.debug("findAllFeaturesRecursively({}) starts", features.getName());
272 LOG.trace("findAllFeaturesRecursively knows about these coords: {}", existingCoords);
273 Set<Features> result = new LinkedHashSet<>();
274 Set<String> coords = FeatureUtil.featuresRepositoryToCoords(features);
275 for (String coord : coords) {
276 if (!existingCoords.contains(coord)) {
277 LOG.trace("findAllFeaturesRecursively() going to add {}", coord);
278 existingCoords.add(coord);
279 Features feature = FeatureUtil.readFeature(aetherUtil, coord);
281 LOG.debug("findAllFeaturesRecursively() added {}", coord);
282 result.addAll(findAllFeaturesRecursively(aetherUtil, FeatureUtil.readFeature(aetherUtil, coord),
285 LOG.trace("findAllFeaturesRecursively() skips known {}", coord);
292 * Unmarshals all the features starting from the given features.
294 * @param aetherUtil The Aether resolver.
295 * @param features The starting features.
296 * @param existingCoords The artifact coordinates which have already been unmarshalled.
297 * @return The features.
298 * @throws MalformedURLException if a URL is malformed.
299 * @throws FileNotFoundException if a file is missing.
300 * @throws ArtifactResolutionException if artifact coordinates can't be resolved.
302 public static Set<Features> findAllFeaturesRecursively(
303 AetherUtil aetherUtil, Set<Features> features, Set<String> existingCoords)
304 throws MalformedURLException, FileNotFoundException, ArtifactResolutionException {
305 Set<Features> result = new LinkedHashSet<>();
306 for (Features feature : features) {
307 result.addAll(findAllFeaturesRecursively(aetherUtil, feature, existingCoords));
313 * Unmarshals all the features (including known ones) starting from the given features.
315 * @param aetherUtil The Aether resolver.
316 * @param features The starting features.
317 * @return The features.
318 * @throws MalformedURLException if a URL is malformed.
319 * @throws FileNotFoundException if a file is missing.
320 * @throws ArtifactResolutionException if artifact coordinates can't be resolved.
322 public static Set<Features> findAllFeaturesRecursively(AetherUtil aetherUtil, Set<Features> features)
323 throws MalformedURLException, FileNotFoundException, ArtifactResolutionException {
324 return findAllFeaturesRecursively(aetherUtil, features, new LinkedHashSet<String>());