use of org.commonjava.maven.ext.core.state.CommonState in project pom-manipulation-ext by release-engineering.
the class DependencyManipulator method applyOverrides.
/**
* Apply a set of version overrides to a list of dependencies. Return a set of the overrides which were not applied.
*
* @param project The current Project
* @param dependencies The list of dependencies
* @param explicitOverrides Any explicitOverrides to track for ignoring
* @param overrides The map of dependency version overrides
* @return The map of overrides that were not matched in the dependencies
* @throws ManipulationException if an error occurs
*/
private Map<ArtifactRef, String> applyOverrides(final Project project, final HashMap<ArtifactRef, Dependency> dependencies, final WildcardMap<String> explicitOverrides, final Map<ArtifactRef, String> overrides) throws ManipulationException {
// Duplicate the override map so unused overrides can be easily recorded
final Map<ArtifactRef, String> unmatchedVersionOverrides = new LinkedHashMap<>();
unmatchedVersionOverrides.putAll(overrides);
if (dependencies == null || dependencies.size() == 0) {
return unmatchedVersionOverrides;
}
final CommonState commonState = session.getState(CommonState.class);
final boolean strict = commonState.getStrict();
// Apply matching overrides to dependencies
for (final ArtifactRef dependency : dependencies.keySet()) {
ProjectRef depPr = new SimpleProjectRef(dependency.getGroupId(), dependency.getArtifactId());
// will most likely happen is last-wins.
for (final Map.Entry<ArtifactRef, String> entry : overrides.entrySet()) {
ProjectRef groupIdArtifactId = entry.getKey().asProjectRef();
if (depPr.equals(groupIdArtifactId)) {
final String oldVersion = dependencies.get(dependency).getVersion();
final String overrideVersion = entry.getValue();
final String resolvedValue = dependency.getVersionString();
if (isEmpty(overrideVersion)) {
logger.warn("Unable to align with an empty override version for " + groupIdArtifactId + "; ignoring");
} else if (isEmpty(oldVersion)) {
logger.debug("Dependency is a managed version for " + groupIdArtifactId + "; ignoring");
} else // By avoiding the potential duplicate work it also avoids a possible property clash problem.
if (explicitOverrides.containsKey(depPr)) {
logger.debug("Dependency {} matches known explicit override so not performing initial override pass.", depPr);
unmatchedVersionOverrides.remove(entry.getKey());
} else // have immediate access to the original property so the closest that is feasible is verify strict matching.
if (strict && oldVersion.contains("$") && !PropertiesUtils.checkStrictValue(session, resolvedValue, overrideVersion)) {
logger.debug("Original fully resolved version {} of {} does not match override version {} -> {} so ignoring", resolvedValue, dependency, entry.getKey(), overrideVersion);
if (commonState.getFailOnStrictViolation()) {
throw new ManipulationException("For {} replacing original property version {} (fully resolved: {} ) with new version {} for {} violates the strict version-alignment rule!", depPr.toString(), dependencies.get(dependency).getVersion(), resolvedValue, entry.getKey().getVersionString(), entry.getKey().asProjectRef().toString());
} else {
logger.warn("Replacing original property version {} with new version {} for {} violates the strict version-alignment rule!", resolvedValue, overrideVersion, dependencies.get(dependency).getVersion());
}
} else {
// Too much spurious logging with project.version.
if (!oldVersion.equals("${project.version}")) {
logger.info("Updating version {} for dependency {} from {}.", overrideVersion, dependency, project.getPom());
}
if (!PropertiesUtils.cacheProperty(project, commonState, versionPropertyUpdateMap, oldVersion, overrideVersion, entry.getKey(), false)) {
if (oldVersion.equals("${project.version}")) {
logger.debug("For dependency {} ; version is built in {} so skipping inlining {}", groupIdArtifactId, oldVersion, overrideVersion);
} else if (strict && !PropertiesUtils.checkStrictValue(session, resolvedValue, overrideVersion)) {
if (commonState.getFailOnStrictViolation()) {
throw new ManipulationException("Replacing original version {} in dependency {} with new version {} violates the strict version-alignment rule!", oldVersion, groupIdArtifactId.toString(), overrideVersion);
} else {
logger.warn("Replacing original version {} in dependency {} with new version {} violates the strict version-alignment rule!", oldVersion, groupIdArtifactId, overrideVersion);
}
} else {
logger.debug("Altered dependency {} : {} -> {}", groupIdArtifactId, oldVersion, overrideVersion);
if (oldVersion.contains("${")) {
String suffix = PropertiesUtils.getSuffix(session);
String replaceVersion;
if (commonState.getStrictIgnoreSuffix() && oldVersion.contains(suffix)) {
replaceVersion = StringUtils.substringBefore(oldVersion, suffix);
replaceVersion += suffix + StringUtils.substringAfter(overrideVersion, suffix);
} else {
replaceVersion = oldVersion + StringUtils.removeStart(overrideVersion, resolvedValue);
}
logger.debug("Resolved value is {} and replacement version is {} ", resolvedValue, replaceVersion);
// In this case the previous value couldn't be cached even though it contained a property
// as it was either multiple properties or a property combined with a hardcoded value. Therefore
// just append the suffix.
dependencies.get(dependency).setVersion(replaceVersion);
} else {
dependencies.get(dependency).setVersion(overrideVersion);
}
}
}
unmatchedVersionOverrides.remove(entry.getKey());
}
}
}
}
return unmatchedVersionOverrides;
}
use of org.commonjava.maven.ext.core.state.CommonState in project pom-manipulation-ext by release-engineering.
the class PropertiesUtilsTest method testCacheProperty.
@Test
public void testCacheProperty() throws Exception {
Map<Project, Map<String, String>> propertyMap = new HashMap<>();
CommonState state = new CommonState(new Properties());
Project project = getProject();
assertFalse(PropertiesUtils.cacheProperty(project, state, propertyMap, "${foobar}${foobar2}", null, null, false));
assertFalse(PropertiesUtils.cacheProperty(project, state, propertyMap, "suffix.${foobar}", null, null, false));
assertFalse(PropertiesUtils.cacheProperty(project, state, propertyMap, null, "2.0", null, false));
assertFalse(PropertiesUtils.cacheProperty(project, state, propertyMap, "1.0", "2.0", null, false));
assertTrue(PropertiesUtils.cacheProperty(project, state, propertyMap, "${version.org.jboss}", "2.0", null, false));
assertFalse(PropertiesUtils.cacheProperty(project, state, propertyMap, "${project.version}", "2.0", null, false));
// DependencyManipulator does dependency.getVersion(). This could return e.g. ${version.scala} which can
// refer to <version.scala>${version.scala.major}.7</version.scala>. If we are attempting to change version.scala
// to e.g. 2.11.7.redhat-1 then in this case we need to ignore the version.scala.major property and append the .redhat-1.
// If the property is ${...}.foobar then we only want to append suffix to foobar to change the version
// However we don't need to change the value of the property. If the property is foobar.${....} then
// we want to append suffix to the property ... but we need to handle that part of the property is hardcoded.
assertFalse(PropertiesUtils.cacheProperty(project, state, propertyMap, "${version.scala}.7", "2.0", null, false));
assertFalse(PropertiesUtils.cacheProperty(project, state, propertyMap, "${version.foo}.${version.scala}.7", "2.0", null, false));
try {
PropertiesUtils.cacheProperty(project, state, propertyMap, "${version.scala}.7.${version.scala2}", "2.0", null, false);
} catch (ManipulationException e) {
// Pass.
}
}
use of org.commonjava.maven.ext.core.state.CommonState in project pom-manipulation-ext by release-engineering.
the class ManipulationManager method init.
/**
* Initialize {@link ManipulationSession} using the given {@link MavenSession} instance, along with any state managed by the individual
* {@link Manipulator} components.
*
* @param session the container session for manipulation.
* @throws ManipulationException if an error occurs.
*/
public void init(final ManipulationSession session) throws ManipulationException {
logger.debug("Initialising ManipulationManager with user properties {}", session.getUserProperties());
for (final ExtensionInfrastructure infra : infrastructure.values()) {
infra.init(session.getTargetDir(), session.getRemoteRepositories(), session.getLocalRepository(), session.getSettings(), session.getActiveProfiles());
}
orderedManipulators = new ArrayList<>(manipulators.values());
// The RESTState depends upon the VersionState being initialised. Therefore initialise in reverse order
// and do a final sort to run in the correct order. See the Manipulator interface for detailed discussion
// on ordered.
Collections.sort(orderedManipulators, Collections.reverseOrder(new ManipulatorPriorityComparator()));
for (final Manipulator manipulator : orderedManipulators) {
logger.debug("Initialising manipulator " + manipulator.getClass().getSimpleName());
manipulator.init(session);
}
Collections.sort(orderedManipulators, new ManipulatorPriorityComparator());
// Now init the common state
session.setState(new CommonState(session.getUserProperties()));
}
use of org.commonjava.maven.ext.core.state.CommonState in project pom-manipulation-ext by release-engineering.
the class PluginManipulator method applyOverrides.
/**
* Set the versions of any plugins which match the contents of the list of plugin overrides.
*
* Currently this method takes the remote plugin type (note that remote plugins are deprecated) and the local plugin type.
* It will ONLY apply configurations, executions and dependencies from the remote pluginMgmt to the local pluginMgmt.
* If the local pluginMgmt does not have a matching plugin then, if {@link CommonState#getOverrideTransitive()} is true
* then it will inject a new plugin into the local pluginMgmt.
* It will however apply version changes to both local pluginMgmt and local plugins.
* Note that if the deprecated injectRemotePlugins is enabled then remote plugin version, executions, dependencies and
* configurations will also be applied to the local plugins.
*
* @param project the current project
* @param remotePluginType The type of the remote plugin (mgmt or plugins)
* @param localPluginType The type of local block (mgmt or plugins). Only used to determine whether to inject configs/deps/executions.
* @param plugins The list of plugins to modify
* @param pluginVersionOverrides The list of version overrides to apply to the plugins
* @throws ManipulationException if an error occurs.
*/
private void applyOverrides(Project project, PluginType remotePluginType, final PluginType localPluginType, final HashMap<ProjectVersionRef, Plugin> plugins, final Set<Plugin> pluginVersionOverrides) throws ManipulationException {
if (plugins == null) {
throw new ManipulationException("Original plugins should not be null");
}
final PluginState pluginState = session.getState(PluginState.class);
final CommonState commonState = session.getState(CommonState.class);
final HashMap<String, ProjectVersionRef> pluginsByGA = new LinkedHashMap<>();
// Secondary map of original plugins group:artifact to pvr mapping.
for (ProjectVersionRef pvr : plugins.keySet()) {
// We should NEVER have multiple group:artifact with different versions in the same project. If we do,
// like with dependencies, the behaviour is undefined - although its most likely the last-wins.
pluginsByGA.put(pvr.asProjectRef().toString(), pvr);
}
for (final Plugin override : pluginVersionOverrides) {
Plugin plugin = null;
String newValue = override.getVersion();
// override version.
if (pluginsByGA.containsKey(override.getKey())) {
// Potential match of override group:artifact to original plugin group:artifact.
String oldValue = pluginsByGA.get(override.getKey()).getVersionString();
plugin = plugins.get(pluginsByGA.get(override.getKey()));
if (commonState.getStrict()) {
if (!PropertiesUtils.checkStrictValue(session, oldValue, newValue)) {
if (commonState.getFailOnStrictViolation()) {
throw new ManipulationException("Plugin reference {} replacement: {} of original version: {} violates the strict version-alignment rule!", plugin.getId(), newValue, oldValue);
} else {
logger.warn("Plugin reference {} replacement: {} of original version: {} violates the strict version-alignment rule!", plugin.getId(), newValue, oldValue);
// a new property either.
continue;
}
}
}
}
logger.debug("Plugin override {} and local plugin {} with remotePluginType {} / localPluginType {}", override.getId(), plugin, remotePluginType, localPluginType);
if (plugin != null) {
if (localPluginType == PluginType.LocalPM) {
if (override.getConfiguration() != null) {
logger.debug("Injecting plugin configuration" + override.getConfiguration());
if (plugin.getConfiguration() == null) {
plugin.setConfiguration(override.getConfiguration());
logger.debug("Altered plugin configuration: " + plugin.getKey() + "=" + plugin.getConfiguration());
} else if (plugin.getConfiguration() != null) {
logger.debug("Existing plugin configuration: " + plugin.getConfiguration());
if (!(plugin.getConfiguration() instanceof Xpp3Dom) || !(override.getConfiguration() instanceof Xpp3Dom)) {
throw new ManipulationException("Incorrect DOM type " + plugin.getConfiguration().getClass().getName() + " and" + override.getConfiguration().getClass().getName());
}
if (pluginState.getConfigPrecedence() == Precedence.REMOTE) {
plugin.setConfiguration(Xpp3DomUtils.mergeXpp3Dom((Xpp3Dom) override.getConfiguration(), (Xpp3Dom) plugin.getConfiguration()));
} else if (pluginState.getConfigPrecedence() == Precedence.LOCAL) {
plugin.setConfiguration(Xpp3DomUtils.mergeXpp3Dom((Xpp3Dom) plugin.getConfiguration(), (Xpp3Dom) override.getConfiguration()));
}
logger.debug("Altered plugin configuration: " + plugin.getKey() + "=" + plugin.getConfiguration());
}
} else {
logger.debug("No remote configuration to inject from " + override.toString());
}
if (override.getExecutions() != null) {
Map<String, PluginExecution> newExecutions = override.getExecutionsAsMap();
Map<String, PluginExecution> originalExecutions = plugin.getExecutionsAsMap();
for (PluginExecution pe : newExecutions.values()) {
if (originalExecutions.containsKey(pe.getId())) {
logger.warn("Unable to inject execution " + pe.getId() + " as it clashes with an existing execution");
} else {
logger.debug("Injecting execution {} ", pe);
plugin.getExecutions().add(pe);
}
}
} else {
logger.debug("No remote executions to inject from " + override.toString());
}
if (!override.getDependencies().isEmpty()) {
// TODO: ### Review this - is it still required?
logger.debug("Checking original plugin dependencies versus override");
// First, remove any Dependency from the original Plugin if the GA exists in the override.
Iterator<Dependency> originalIt = plugin.getDependencies().iterator();
while (originalIt.hasNext()) {
Dependency originalD = originalIt.next();
Iterator<Dependency> overrideIt = override.getDependencies().iterator();
while (overrideIt.hasNext()) {
Dependency newD = overrideIt.next();
if (originalD.getGroupId().equals(newD.getGroupId()) && originalD.getArtifactId().equals(newD.getArtifactId())) {
logger.debug("Removing original dependency {} in favour of {} ", originalD, newD);
originalIt.remove();
break;
}
}
}
// Now merge them together. Only inject dependencies in the management block.
logger.debug("Adding in plugin dependencies {}", override.getDependencies());
plugin.getDependencies().addAll(override.getDependencies());
}
}
// Explicitly using the original non-resolved original version.
String oldVersion = plugin.getVersion();
// will never be null.
if (!PropertiesUtils.cacheProperty(project, commonState, versionPropertyUpdateMap, oldVersion, newValue, plugin, false)) {
if (oldVersion != null && oldVersion.equals("${project.version}")) {
logger.debug("For plugin {} ; version is built in {} so skipping inlining {}", plugin, oldVersion, newValue);
} else if (oldVersion != null && oldVersion.contains("${")) {
throw new ManipulationException("NYI : Multiple embedded properties for plugins.");
} else {
plugin.setVersion(newValue);
logger.info("Altered plugin version: " + override.getKey() + "=" + newValue);
}
}
} else // get the correct config.
if (remotePluginType == PluginType.RemotePM && localPluginType == PluginType.LocalPM && commonState.getOverrideTransitive() && (override.getConfiguration() != null || override.getExecutions().size() > 0)) {
project.getModel().getBuild().getPluginManagement().getPlugins().add(override);
logger.info("Added plugin version: " + override.getKey() + "=" + newValue);
} else // TODO: Deprecated section.
if (remotePluginType == PluginType.RemoteP && localPluginType == PluginType.LocalP && pluginState.getInjectRemotePlugins() && (override.getConfiguration() != null || override.getExecutions().size() > 0)) {
project.getModel().getBuild().getPlugins().add(override);
logger.info("For non-pluginMgmt, added plugin version : " + override.getKey() + "=" + newValue);
}
}
}
use of org.commonjava.maven.ext.core.state.CommonState in project pom-manipulation-ext by release-engineering.
the class PropertiesUtils method internalUpdateProperty.
private static PropertyUpdate internalUpdateProperty(ManipulationSession session, Project p, boolean ignoreStrict, String key, String newValue, String resolvedValue, Properties props) throws ManipulationException {
final CommonState state = session.getState(CommonState.class);
final String oldValue = props.getProperty(key);
logger.info("Updating property {} / {} with {} ", key, oldValue, newValue);
PropertyUpdate found = PropertyUpdate.FOUND;
// update it with a portion of the new value.
if (oldValue != null && oldValue.startsWith("${") && oldValue.endsWith("}") && !(StringUtils.countMatches(oldValue, "${") > 1)) {
logger.debug("Recursively resolving {} ", oldValue.substring(2, oldValue.length() - 1));
if (updateProperties(session, p, ignoreStrict, oldValue.substring(2, oldValue.length() - 1), newValue) == PropertyUpdate.NOTFOUND) {
logger.error("Recursive property not found for {} with {} ", oldValue, newValue);
return PropertyUpdate.NOTFOUND;
}
} else {
if (state.getStrict() && !ignoreStrict) {
if (!checkStrictValue(session, resolvedValue, newValue)) {
if (state.getFailOnStrictViolation()) {
throw new ManipulationException("Replacing original property version {} (fully resolved: {} ) with new version {} for {} violates the strict version-alignment rule!", oldValue, resolvedValue, newValue, key);
} else {
logger.warn("Replacing original property version {} with new version {} for {} violates the strict version-alignment rule!", oldValue, newValue, key);
// a new property either.
return found;
}
}
}
// TODO: Does not handle explicit overrides.
if (oldValue != null && oldValue.contains("${") && !(oldValue.startsWith("${") && oldValue.endsWith("}")) || (StringUtils.countMatches(oldValue, "${") > 1)) {
if (ignoreStrict) {
throw new ManipulationException("NYI : handling for versions with explicit overrides (" + oldValue + ") with multiple embedded properties is NYI. ");
}
if (resolvedValue.equals(newValue)) {
logger.warn("Nothing to update as original key {} value matches new value {} ", key, newValue);
found = PropertyUpdate.IGNORE;
}
newValue = oldValue + StringUtils.removeStart(newValue, resolvedValue);
logger.info("Ignoring new value due to embedded property {} and appending {} ", oldValue, newValue);
}
props.setProperty(key, newValue);
}
return found;
}
Aggregations