You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gg...@apache.org on 2017/12/09 18:46:52 UTC
[karaf] 09/19: [KARAF-5376] Generate/merge features processor
configuration from external and Maven config,
improve logging in karaf-maven-plugin:assembly
This is an automated email from the ASF dual-hosted git repository.
ggrzybek pushed a commit to branch KARAF-5376-overrides_v2
in repository https://gitbox.apache.org/repos/asf/karaf.git
commit f245b4ee418c81627e72ac8ddd941250d891121a
Author: Grzegorz Grzybek <gr...@gmail.com>
AuthorDate: Wed Nov 22 15:09:01 2017 +0100
[KARAF-5376] Generate/merge features processor configuration from external and Maven config, improve logging in karaf-maven-plugin:assembly
---
.../org/apache/karaf/features/FeaturePattern.java | 12 +++
.../org/apache/karaf/features/LocationPattern.java | 4 +
.../model/processing/FeaturesProcessing.java | 58 +++++++------
.../karaf/features/internal/service/Blacklist.java | 12 +++
.../karaf/profile/assembly/ArtifactInstaller.java | 28 ++++++
.../org/apache/karaf/profile/assembly/Builder.java | 99 ++++++++++++++--------
.../org/apache/karaf/tooling/AssemblyMojo.java | 10 +++
7 files changed, 164 insertions(+), 59 deletions(-)
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturePattern.java b/features/core/src/main/java/org/apache/karaf/features/FeaturePattern.java
index 107993b..a77c4df 100644
--- a/features/core/src/main/java/org/apache/karaf/features/FeaturePattern.java
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturePattern.java
@@ -80,6 +80,18 @@ public class FeaturePattern {
}
}
+ public String getOriginalFeatureId() {
+ return originalId;
+ }
+
+ public String getName() {
+ return nameString;
+ }
+
+ public String getVersion() {
+ return versionString;
+ }
+
/**
* Returns <code>true</code> if this feature pattern matches given feature/version
* @param featureName
diff --git a/features/core/src/main/java/org/apache/karaf/features/LocationPattern.java b/features/core/src/main/java/org/apache/karaf/features/LocationPattern.java
index 428746f..e5c96eb 100644
--- a/features/core/src/main/java/org/apache/karaf/features/LocationPattern.java
+++ b/features/core/src/main/java/org/apache/karaf/features/LocationPattern.java
@@ -108,6 +108,10 @@ public class LocationPattern {
}
}
+ public String getOriginalUri() {
+ return originalUri;
+ }
+
/**
* Converts a String with one special character (<code>*</code>) into working {@link Pattern}
* @param value
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/FeaturesProcessing.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/FeaturesProcessing.java
index 8a3c7b6..3f5050b 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/FeaturesProcessing.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/FeaturesProcessing.java
@@ -142,22 +142,49 @@ public class FeaturesProcessing {
}
/**
- * Perform <em>compilation</em> of rules declared in feature processing XML file.
+ * <p>Perform <em>compilation</em> of rules declared in feature processing XML file.</p>
+ * <p>Additional blacklist and overrides definitions will be added to this model</p>
+ *
* @param blacklist additional {@link Blacklist} definition with lower priority
* @param overrides additional overrides definition with lower priority
*/
public void postUnmarshall(Blacklist blacklist, Set<String> overrides) {
- // compile blacklisted repository URIs
- for (String repositoryURI : this.getBlacklistedRepositories()) {
+ // configure Blacklist tool
+ List<String> blacklisted = new LinkedList<>();
+
+ // compile blacklisted repository URIs (from XML and additional blacklist)
+ blacklist.getRepositoryBlacklist().stream()
+ .map(LocationPattern::getOriginalUri)
+ .forEach(uri -> getBlacklistedRepositories().add(uri));
+ for (String repositoryURI : getBlacklistedRepositories()) {
try {
blacklistedRepositoryLocationPatterns.add(new LocationPattern(repositoryURI));
+ blacklisted.add(repositoryURI + ";" + Blacklist.BLACKLIST_TYPE + "=" + Blacklist.TYPE_REPOSITORY);
} catch (MalformedURLException e) {
LOG.warn("Can't parse blacklisted repository location pattern: " + repositoryURI + ". Ignoring.");
}
}
- // verify bundle override definitions
- for (Iterator<BundleReplacements.OverrideBundle> iterator = this.bundleReplacements.getOverrideBundles().iterator(); iterator.hasNext(); ) {
+ // add external blacklisted features to this model
+ blacklist.getFeatureBlacklist()
+ .forEach(fb -> getBlacklistedFeatures().add(new BlacklistedFeature(fb.getName(), fb.getVersion())));
+ blacklisted.addAll(getBlacklistedFeatures().stream()
+ .map(bf -> bf.getName() + ";" + Blacklist.BLACKLIST_TYPE + "=" + Blacklist.TYPE_FEATURE + (bf.getVersion() == null ? "" : ";" + FeaturePattern.RANGE + "=\"" + bf.getVersion() + "\""))
+ .collect(Collectors.toList()));
+
+ // add external blacklisted bundle URIs to this model
+ blacklist.getBundleBlacklist().stream()
+ .map(LocationPattern::getOriginalUri)
+ .forEach(uri -> getBlacklistedBundles().add(uri));
+ blacklisted.addAll(getBlacklistedBundles().stream()
+ .map(bl -> bl + ";" + Blacklist.BLACKLIST_TYPE + "=" + Blacklist.TYPE_BUNDLE)
+ .collect(Collectors.toList()));
+
+ this.blacklist = new Blacklist(blacklisted);
+
+ // verify bundle override definitions (from XML and additional overrides)
+ bundleReplacements.getOverrideBundles().addAll(parseOverridesClauses(overrides));
+ for (Iterator<BundleReplacements.OverrideBundle> iterator = bundleReplacements.getOverrideBundles().iterator(); iterator.hasNext(); ) {
BundleReplacements.OverrideBundle overrideBundle = iterator.next();
if (overrideBundle.getOriginalUri() == null) {
// we have to derive it from replacement - as with etc/overrides.properties entry
@@ -180,27 +207,6 @@ public class FeaturesProcessing {
iterator.remove();
}
}
-
- // etc/blacklisted.properties
- // blacklisted bundle from XML to instruction for Blacklist class
- List<String> blacklisted = new LinkedList<>();
- for (String bl : this.getBlacklistedBundles()) {
- blacklisted.add(bl + ";" + Blacklist.BLACKLIST_TYPE + "=" + Blacklist.TYPE_BUNDLE);
- }
- // blacklisted features - XML type to String instruction for Blacklist class
- blacklisted.addAll(this.getBlacklistedFeatures().stream()
- .map(bf -> bf.getName() + ";" + Blacklist.BLACKLIST_TYPE + "=" + Blacklist.TYPE_FEATURE + (bf.getVersion() == null ? "" : ";" + FeaturePattern.RANGE + "=\"" + bf.getVersion() + "\""))
- .collect(Collectors.toList()));
- // blacklisted repositories
- for (String bl : this.getBlacklistedRepositories()) {
- blacklisted.add(bl + ";" + Blacklist.BLACKLIST_TYPE + "=" + Blacklist.TYPE_REPOSITORY);
- }
-
- this.blacklist = new Blacklist(blacklisted);
- this.blacklist.merge(blacklist);
-
- // etc/overrides.properties (mvn: URIs)
- bundleReplacements.getOverrideBundles().addAll(parseOverridesClauses(overrides));
}
/**
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
index dcc1a20..9792afa 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
@@ -243,4 +243,16 @@ public class Blacklist {
bundleBlacklist.add(locationPattern);
}
+ public List<LocationPattern> getRepositoryBlacklist() {
+ return repositoryBlacklist;
+ }
+
+ public List<FeaturePattern> getFeatureBlacklist() {
+ return featureBlacklist;
+ }
+
+ public List<LocationPattern> getBundleBlacklist() {
+ return bundleBlacklist;
+ }
+
}
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/ArtifactInstaller.java b/profile/src/main/java/org/apache/karaf/profile/assembly/ArtifactInstaller.java
index 967a979..f068f5e 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/ArtifactInstaller.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/ArtifactInstaller.java
@@ -23,6 +23,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
+import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.internal.download.Downloader;
import org.apache.karaf.features.internal.service.Blacklist;
import org.apache.karaf.util.maven.Parser;
@@ -48,6 +49,33 @@ public class ArtifactInstaller {
this.blacklist = blacklist;
}
+ public void installArtifact(BundleInfo bundle) throws Exception {
+ if (bundle.isBlacklisted()) {
+ LOGGER.info(" skipping blacklisted maven artifact: " + bundle.getLocation());
+ return;
+ }
+ if (bundle.isOverriden()) {
+ LOGGER.info(" adding overriden maven artifact: " + bundle.getLocation() + " (original location: " + bundle.getOriginalLocation() + ")");
+ } else {
+ LOGGER.info(" adding maven artifact: " + bundle.getLocation());
+ }
+ String location = bundle.getLocation().trim();
+ location = removeTrailingSlash(stripUrl(location));
+ if (!location.startsWith("mvn:")) {
+ LOGGER.warn("Ignoring non maven artifact " + location);
+ return;
+ }
+ final String finalLocation = location;
+ downloader.download(location, provider -> {
+ String uri = provider.getUrl();
+ Path path = pathFromProviderUrl(systemDirectory, finalLocation);
+ synchronized (provider) {
+ Files.createDirectories(path.getParent());
+ Files.copy(provider.getFile().toPath(), path, StandardCopyOption.REPLACE_EXISTING);
+ }
+ });
+ }
+
public void installArtifact(String location) throws Exception {
LOGGER.info(" adding maven artifact: " + location);
location = removeTrailingSlash(stripUrl(location));
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
index 960a067..aedc8eb 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
@@ -62,6 +62,7 @@ import java.util.zip.ZipInputStream;
import org.apache.felix.resolver.ResolverImpl;
import org.apache.felix.utils.manifest.Clause;
import org.apache.felix.utils.properties.Properties;
+import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.FeaturePattern;
import org.apache.karaf.features.FeaturesService;
import org.apache.karaf.features.Library;
@@ -286,6 +287,7 @@ public class Builder {
boolean ignoreDependencyFlag;
int defaultStartLevel = 50;
Path homeDirectory;
+ Path featuresProcessingLocation;
boolean offline;
String localRepository;
String mavenRepositories;
@@ -575,6 +577,20 @@ public class Builder {
}
/**
+ * <p>Configures custom location for a file with features processing instructions. Normally this file is generated
+ * by the builder if any of blacklisted options are configured.</p>
+ * <p>If custom location is provided and it's not <code>etc/org.apache.karaf.features.xml</code>, it is copied</p>
+ * <p>If custom location is provided and it's <code>etc/org.apache.karaf.features.xml</code>, it's left as is</p>
+ * <p>Any additional blacklisting/overrides configuration via Maven configuration causes overwrite of original
+ * content.</p>
+ * @param featuresProcessing
+ */
+ public Builder setFeaturesProcessing(Path featuresProcessing) {
+ this.featuresProcessingLocation = featuresProcessing;
+ return this;
+ }
+
+ /**
* Ignore the dependency attribute (dependency="[true|false]") on bundles, effectively forcing their
* installation.
*/
@@ -860,11 +876,26 @@ public class Builder {
// profiles are generated after reading features from repositories
// so for now, we can only configure blacklisting features processor
- Path existingProcessorDefinition = etcDirectory.resolve("org.apache.karaf.features.xml");
+ boolean needFeaturesProcessorFileCopy = false;
String existingProcessorDefinitionURI = null;
+ Path existingProcessorDefinition = etcDirectory.resolve("org.apache.karaf.features.xml");
if (existingProcessorDefinition.toFile().isFile()) {
existingProcessorDefinitionURI = existingProcessorDefinition.toFile().toURI().toString();
+ LOGGER.info("Found existing features processor configuration: {}", homeDirectory.relativize(existingProcessorDefinition));
+ }
+ if (featuresProcessingLocation != null && featuresProcessingLocation.toFile().isFile()
+ && !featuresProcessingLocation.equals(existingProcessorDefinition)) {
+ if (existingProcessorDefinitionURI != null) {
+ LOGGER.warn("Explicitly configured {} will be used for features processor configuration.", homeDirectory.relativize(featuresProcessingLocation));
+ } else {
+ LOGGER.info("Found features processor configuration: {}", homeDirectory.relativize(featuresProcessingLocation));
+ }
+ existingProcessorDefinitionURI = featuresProcessingLocation.toFile().toURI().toString();
+ // when there are no other (configured via Maven for example) processing instructions (e.g., blacklisting)
+ // we don't have to generate this file and may take original content
+ needFeaturesProcessorFileCopy = true;
}
+
// now we can configure blacklisting features processor which may have already defined (in XML)
// configuration for bundle replacements or feature overrides.
// we'll add overrides from profiles later.
@@ -1014,30 +1045,18 @@ public class Builder {
editor.run();
}
-// if (!blacklistedFeatures.isEmpty() || !blacklistedBundles.isEmpty()) {
-// List<String> lines = new ArrayList<>();
-// lines.add("#");
-// lines.add("# Generated by the karaf assembly builder");
-// lines.add("#");
-// if (!blacklistedFeatures.isEmpty()) {
-// lines.add("");
-// lines.add("# Features");
-// lines.addAll(blacklistedFeatures);
-// }
-// if (!blacklistedBundles.isEmpty()) {
-// lines.add("");
-// lines.add("# Bundles");
-// lines.addAll(blacklistedBundles);
-// }
-// LOGGER.info("Generating {}", homeDirectory.relativize(blacklist));
-// Files.write(blacklist, lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
-// }
-
- // TODO: download overrides, implement fuller override clauses (original->replacement)
if (processor.hasInstructions()) {
Path featuresProcessingXml = etcDirectory.resolve("org.apache.karaf.features.xml");
- try (FileOutputStream fos = new FileOutputStream(featuresProcessingXml.toFile())) {
- processor.writeInstructions(fos);
+ if (hasOwnInstructions() || overrides.size() > 0) {
+ // just generate new etc/org.apache.karaf.features.xml file (with external config + builder config)
+ try (FileOutputStream fos = new FileOutputStream(featuresProcessingXml.toFile())) {
+ LOGGER.info("Generating features processor configuration: {}", homeDirectory.relativize(featuresProcessingXml));
+ processor.writeInstructions(fos);
+ }
+ } else if (needFeaturesProcessorFileCopy) {
+ // we may simply copy configured features processor XML configuration
+ LOGGER.info("Copying features processor configuration: {} -> {}", homeDirectory.relativize(featuresProcessingLocation), homeDirectory.relativize(featuresProcessingXml));
+ Files.copy(featuresProcessingLocation, featuresProcessingXml, StandardCopyOption.REPLACE_EXISTING);
}
}
@@ -1058,6 +1077,20 @@ public class Builder {
}
/**
+ * Similar to {@link FeaturesProcessorImpl#hasInstructions()}, we check if there are any builder configuration
+ * options for blacklisted repos/features/bundles or overwrites.
+ * @return
+ */
+ private boolean hasOwnInstructions() {
+ int count = 0;
+ count += blacklistedRepositoryURIs.size();
+ count += blacklistedFeatureIdentifiers.size();
+ count += blacklistedBundleURIs.size();
+
+ return count > 0;
+ }
+
+ /**
* Checks existing (etc/overrides.properties) and configured (in profiles) overrides definitions
* @param profileOverrides
* @return
@@ -1091,7 +1124,7 @@ public class Builder {
try {
blacklist.blacklistRepository(new LocationPattern(br));
} catch (MalformedURLException e) {
- LOGGER.warn("Blacklisted features XML repository URI is invalid {}, ignoring", br);
+ LOGGER.warn("Blacklisted features XML repository URI is invalid: {}, ignoring", br);
}
}
for (String bf : blacklistedFeatureIdentifiers) {
@@ -1101,7 +1134,7 @@ public class Builder {
try {
blacklist.blacklistBundle(new LocationPattern(bb));
} catch (MalformedURLException e) {
- LOGGER.warn("Blacklisted bundle URI is invalid {}, ignoring", bb);
+ LOGGER.warn("Blacklisted bundle URI is invalid: {}, ignoring", bb);
}
}
if (existingBlacklist != null) {
@@ -1320,7 +1353,7 @@ public class Builder {
LOGGER.info(" Feature {} is defined as an installed feature", feature.getId());
for (Bundle bundle : feature.getBundle()) {
if (!ignoreDependencyFlag || !bundle.isDependency()) {
- installer.installArtifact(bundle.getLocation().trim());
+ installer.installArtifact(bundle);
}
}
// Install config files
@@ -1330,7 +1363,7 @@ public class Builder {
for (Conditional cond : feature.getConditional()) {
for (Bundle bundle : cond.getBundle()) {
if (!ignoreDependencyFlag || !bundle.isDependency()) {
- installer.installArtifact(bundle.getLocation().trim());
+ installer.installArtifact(bundle);
}
}
}
@@ -1392,16 +1425,16 @@ public class Builder {
// the feature is a startup feature, updating startup.properties file
LOGGER.info(" Feature " + feature.getId() + " is defined as a boot feature");
// add the feature in the system folder
- Set<String> locations = new HashSet<>();
+ Set<BundleInfo> bundleInfos = new HashSet<>();
for (Bundle bundle : feature.getBundle()) {
if (!ignoreDependencyFlag || !bundle.isDependency()) {
- locations.add(bundle.getLocation().trim());
+ bundleInfos.add(bundle);
}
}
for (Conditional cond : feature.getConditional()) {
for (Bundle bundle : cond.getBundle()) {
if (!ignoreDependencyFlag || !bundle.isDependency()) {
- locations.add(bundle.getLocation().trim());
+ bundleInfos.add(bundle);
}
}
}
@@ -1413,10 +1446,10 @@ public class Builder {
prereqs.put("wrap:", Collections.singletonList("wrap"));
prereqs.put("war:", Collections.singletonList("war"));
ArtifactInstaller installer = new ArtifactInstaller(systemDirectory, downloader, blacklist);
- for (String location : locations) {
- installer.installArtifact(location);
+ for (BundleInfo bundleInfo : bundleInfos) {
+ installer.installArtifact(bundleInfo);
for (Map.Entry<String, List<String>> entry : prereqs.entrySet()) {
- if (location.startsWith(entry.getKey())) {
+ if (bundleInfo.getLocation().trim().startsWith(entry.getKey())) {
for (String prereq : entry.getValue()) {
Dependency dep = generatedDep.get(prereq);
if (dep == null) {
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
index 08f41cb..2830306 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/AssemblyMojo.java
@@ -88,6 +88,13 @@ public class AssemblyMojo extends MojoSupport {
@Parameter(defaultValue = "${project.build.directory}/assembly")
protected File workDirectory;
+ /**
+ * Optional location for custom features processing XML configuration
+ * (<code>etc/org.apache.karaf.features.cfg</code>)
+ */
+ @Parameter
+ protected File featuresProcessing;
+
/*
* There are three builder stages related to maven dependency scopes:
* - Stage.Startup : scope=compile
@@ -462,6 +469,9 @@ public class AssemblyMojo extends MojoSupport {
builder.writeProfiles(writeProfiles);
builder.environment(environment);
builder.defaultStartLevel(defaultStartLevel);
+ if (featuresProcessing != null) {
+ builder.setFeaturesProcessing(featuresProcessing.toPath());
+ }
// Set up remote repositories from Maven build, to be used by pax-url-aether resolver
String remoteRepositories = MavenUtil.remoteRepositoryList(project.getRemoteProjectRepositories());
--
To stop receiving notification emails like this one, please contact
"commits@karaf.apache.org" <co...@karaf.apache.org>.