Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MNG-8222] Extend PropertyContributor #1679

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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.
*/
package org.apache.maven.api;
gnodet marked this conversation as resolved.
Show resolved Hide resolved

import java.nio.file.Path;
import java.time.Instant;
import java.util.Map;

import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.ThreadSafe;

/**
* The proto session, material used to create {@link Session}.
*
* @since 4.0.0
*/
@Experimental
@ThreadSafe
public interface ProtoSession {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should give access to CLI commands / arguments I think, this may be needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just a List<String> to not expose commons-cli.

/**
* The Maven version, never {@code null}.
*/
@Nonnull
Version getMavenVersion();

/**
* The instant when session creation started, never {@code null}.
*/
@Nonnull
Instant getStartTime();

/**
* User properties as immutable map, never {@code null}.
*/
@Nonnull
Map<String, String> getUserProperties();

/**
* System properties as immutable map, never {@code null}.
*/
@Nonnull
Map<String, String> getSystemProperties();

/**
* Gets the directory of the topmost project being built, usually the current directory or the
* directory pointed at by the {@code -f/--file} command line argument, never {@code null}.
*/
@Nonnull
Path getTopDirectory();

/**
* Gets the root directory of the session, which is the root directory for the top directory project, never {@code null}.
*
* @throws IllegalStateException if the root directory could not be found
* @see #getTopDirectory()
* @see Project#getRootDirectory()
*/
@Nonnull
Path getRootDirectory();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package org.apache.maven.api;

import java.nio.file.Path;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.Map;
Expand All @@ -45,7 +44,7 @@
*/
@Experimental
@ThreadSafe
public interface Session {
public interface Session extends ProtoSession {

@Nonnull
Settings getSettings();
Expand All @@ -59,25 +58,6 @@ public interface Session {
@Nonnull
SessionData getData();

/**
* Returns immutable user properties to use for interpolation. The user properties have been configured directly
* by the user, e.g. via the {@code -Dkey=value} parameter on the command line.
*
* @return the user properties, never {@code null}
*/
@Nonnull
Map<String, String> getUserProperties();

/**
* Returns immutable system properties to use for interpolation. The system properties are collected from the
* runtime environment such as {@link System#getProperties()} and environment variables
* (prefixed with {@code env.}).
*
* @return the system properties, never {@code null}
*/
@Nonnull
Map<String, String> getSystemProperties();

/**
* Each invocation computes a new map of effective properties. To be used in interpolation.
* <p>
Expand All @@ -100,35 +80,8 @@ public interface Session {
@Nonnull
Map<String, String> getEffectiveProperties(@Nullable Project project);

/**
* Returns the current maven version
* @return the maven version, never {@code null}
*/
@Nonnull
Version getMavenVersion();

int getDegreeOfConcurrency();

@Nonnull
Instant getStartTime();

/**
* Gets the directory of the topmost project being built, usually the current directory or the
* directory pointed at by the {@code -f/--file} command line argument.
*/
@Nonnull
Path getTopDirectory();

/**
* Gets the root directory of the session, which is the root directory for the top directory project.
*
* @throws IllegalStateException if the root directory could not be found
* @see #getTopDirectory()
* @see Project#getRootDirectory()
*/
@Nonnull
Path getRootDirectory();

@Nonnull
List<Project> getProjects();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.util.Map;

import org.apache.maven.api.ProtoSession;
import org.apache.maven.api.annotations.Consumer;
import org.apache.maven.api.annotations.Experimental;

Expand All @@ -33,9 +34,9 @@
@Consumer
public interface PropertyContributor extends SpiService {
/**
* Invoked just before session is created with a mutable map that carries collected user properties so far.
* Invoked just before session is created.
*
* @param userProperties The mutable user properties, never {@code null}.
* @param protoSession the proto-session, never {@code null}.
*/
void contribute(Map<String, String> userProperties);
Map<String, String> contribute(ProtoSession protoSession);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* 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.
*/
package org.apache.maven.internal.impl;

import java.nio.file.Path;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

import org.apache.maven.api.ProtoSession;
import org.apache.maven.api.Version;

import static java.util.Objects.requireNonNull;

public class DefaultProtoSession implements ProtoSession {
private final Version mavenVersion;
private final Instant startTime;
private final Map<String, String> systemProperties;
private final Map<String, String> userProperties;
private final Path topDirectory;
private final Path rootDirectory;

private DefaultProtoSession(
Version mavenVersion,
Instant startTime,
Map<String, String> systemProperties,
Map<String, String> userProperties,
Path topDirectory,
Path rootDirectory) {
this.mavenVersion = requireNonNull(mavenVersion);
this.startTime = requireNonNull(startTime);
this.systemProperties = Map.copyOf(requireNonNull(systemProperties));
this.userProperties = Map.copyOf(requireNonNull(userProperties));
this.topDirectory = requireNonNull(topDirectory);
this.rootDirectory = requireNonNull(rootDirectory);
}

@Override
public Version getMavenVersion() {
return mavenVersion;
}

@Override
public Instant getStartTime() {
return startTime;
}

@Override
public Map<String, String> getUserProperties() {
return userProperties;
}

@Override
public Map<String, String> getSystemProperties() {
return systemProperties;
}

@Override
public Path getTopDirectory() {
return topDirectory;
}

@Override
public Path getRootDirectory() {
return rootDirectory;
}

public Builder toBuilder() {
return new Builder(mavenVersion, startTime, systemProperties, userProperties, topDirectory, rootDirectory);
}

public static class Builder {
private Version mavenVersion;
private Instant startTime;
private Map<String, String> systemProperties;
private Map<String, String> userProperties;
private Path topDirectory;
private Path rootDirectory;

public Builder() {
this(null, Instant.now(), new HashMap<>(), new HashMap<>(), null, null);
}

public Builder(
Version mavenVersion,
Instant startTime,
Map<String, String> systemProperties,
Map<String, String> userProperties,
Path topDirectory,
Path rootDirectory) {
this.mavenVersion = mavenVersion;
this.startTime = startTime;
this.systemProperties = systemProperties;
this.userProperties = userProperties;
this.topDirectory = topDirectory;
this.rootDirectory = rootDirectory;
}

public Builder withMavenVersion(Version mavenVersion) {
this.mavenVersion = mavenVersion;
return this;
}

public Builder withStartTime(Instant startTime) {
this.startTime = startTime;
return this;
}

public Builder withSystemProperties(Map<String, String> systemProperties) {
this.systemProperties = systemProperties;
return this;
}

public Builder withUserProperties(Map<String, String> userProperties) {
this.userProperties = userProperties;
return this;
}

public Builder putAllUserProperties(Map<String, String> userProperties) {
requireNonNull(userProperties);
this.userProperties = new HashMap<>(this.userProperties);
this.userProperties.putAll(userProperties);
return this;
}

public Builder withTopDirectory(Path topDirectory) {
this.topDirectory = topDirectory;
return this;
}

public Builder withRootDirectory(Path rootDirectory) {
this.rootDirectory = rootDirectory;
return this;
}

public DefaultProtoSession build() {
return new DefaultProtoSession(
mavenVersion, startTime, systemProperties, userProperties, topDirectory, rootDirectory);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@
import javax.inject.Named;
import javax.inject.Singleton;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.maven.api.services.Lookup;
import org.apache.maven.api.spi.PropertyContributor;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.internal.impl.DefaultProtoSession;
import org.apache.maven.internal.impl.DefaultProtoSessionFactory;

/**
* Extender that manages {@link PropertyContributor}.
Expand All @@ -39,24 +40,36 @@
@Singleton
class PropertyContributorExtender implements MavenExecutionRequestExtender {
private final Lookup lookup;
private final DefaultProtoSessionFactory protoSessionFactory;

@Inject
PropertyContributorExtender(Lookup lookup) {
PropertyContributorExtender(Lookup lookup, DefaultProtoSessionFactory protoSessionFactory) {
this.lookup = lookup;
this.protoSessionFactory = protoSessionFactory;
}

@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void extend(MavenExecutionRequest mavenExecutionRequest) {
Map<String, PropertyContributor> effectivePropertyContributors = lookup.lookupMap(PropertyContributor.class);
if (!effectivePropertyContributors.isEmpty()) {
HashMap<String, String> userPropertiesMap = new HashMap<>((Map) mavenExecutionRequest.getUserProperties());
DefaultProtoSession protoSession = protoSessionFactory.from(mavenExecutionRequest);

int contributedProperties = 0;
for (PropertyContributor contributor : effectivePropertyContributors.values()) {
contributor.contribute(userPropertiesMap);
Map<String, String> contribution = contributor.contribute(protoSession);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A given contributor won't see properties added by previous contributors, is that what we want ?

if (contribution != null && !contribution.isEmpty()) {
contributedProperties += contribution.size();
protoSession = protoSession.toBuilder()
.putAllUserProperties(contribution)
.build();
}
}

if (contributedProperties > 0) {
Properties userProperties = new Properties();
userProperties.putAll(protoSession.getUserProperties());
mavenExecutionRequest.setUserProperties(userProperties);
}
Properties newProperties = new Properties();
newProperties.putAll(userPropertiesMap);
mavenExecutionRequest.setUserProperties(newProperties);
}
}
}
Loading