mirror of
https://github.com/apache/maven-mvnd.git
synced 2025-09-21 19:35:08 +00:00
Provide distributions for both maven 3.9.x and 4.0.x (#796)
This commit is contained in:
50
daemon-m39/pom.xml
Normal file
50
daemon-m39/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright 2019 the original author or authors.
|
||||
|
||||
Licensed 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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd</artifactId>
|
||||
<version>1.0.0-m5-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mvnd-daemon-m39</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
<name>Maven Daemon - Daemon 3.9.x specifics</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-core</artifactId>
|
||||
<version>${maven3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-embedder</artifactId>
|
||||
<version>${maven3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-daemon</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
1419
daemon-m39/src/main/java/org/apache/maven/cli/DaemonMavenCli.java
Normal file
1419
daemon-m39/src/main/java/org/apache/maven/cli/DaemonMavenCli.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.project;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.maven.model.building.ModelCache;
|
||||
|
||||
public class SnapshotModelCache implements ModelCache {
|
||||
|
||||
private final ModelCache globalCache;
|
||||
private final ModelCache reactorCache;
|
||||
|
||||
public SnapshotModelCache(ModelCache globalCache, ModelCache reactorCache) {
|
||||
this.globalCache = Objects.requireNonNull(globalCache);
|
||||
this.reactorCache = Objects.requireNonNull(reactorCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String groupId, String artifactId, String version, String tag, Object data) {
|
||||
getDelegate(version).put(groupId, artifactId, version, tag, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String groupId, String artifactId, String version, String tag) {
|
||||
return getDelegate(version).get(groupId, artifactId, version, tag);
|
||||
}
|
||||
|
||||
private ModelCache getDelegate(String version) {
|
||||
return version.contains("SNAPSHOT") || version.contains("${") ? reactorCache : globalCache;
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.project;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.maven.model.building.ModelCache;
|
||||
import org.apache.maven.repository.internal.DefaultModelCacheFactory;
|
||||
import org.apache.maven.repository.internal.ModelCacheFactory;
|
||||
import org.eclipse.aether.DefaultRepositoryCache;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.sisu.Priority;
|
||||
|
||||
@Singleton
|
||||
@Named
|
||||
@Priority(10)
|
||||
public class SnapshotModelCacheFactory implements ModelCacheFactory {
|
||||
|
||||
private final ModelCacheFactory factory;
|
||||
private final ModelCache globalCache;
|
||||
|
||||
@Inject
|
||||
public SnapshotModelCacheFactory(DefaultModelCacheFactory factory) {
|
||||
this.factory = factory;
|
||||
DefaultRepositorySystemSession session = new DefaultRepositorySystemSession();
|
||||
session.setCache(new DefaultRepositoryCache());
|
||||
this.globalCache = factory.createCache(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelCache createCache(RepositorySystemSession session) {
|
||||
return new SnapshotModelCache(globalCache, factory.createCache(session));
|
||||
}
|
||||
}
|
125
daemon-m39/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingPluginRealmCache.java
vendored
Normal file
125
daemon-m39/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingPluginRealmCache.java
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.cache.invalidating;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.plugin.DefaultPluginRealmCache;
|
||||
import org.apache.maven.plugin.PluginContainerException;
|
||||
import org.apache.maven.plugin.PluginResolutionException;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.codehaus.plexus.classworlds.realm.ClassRealm;
|
||||
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
|
||||
import org.eclipse.sisu.Priority;
|
||||
import org.mvndaemon.mvnd.cache.Cache;
|
||||
import org.mvndaemon.mvnd.cache.CacheFactory;
|
||||
|
||||
@Singleton
|
||||
@Named
|
||||
@Priority(10)
|
||||
public class InvalidatingPluginRealmCache extends DefaultPluginRealmCache {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PluginRealmSupplier {
|
||||
CacheRecord load() throws PluginResolutionException, PluginContainerException;
|
||||
}
|
||||
|
||||
protected static class Record implements org.mvndaemon.mvnd.cache.CacheRecord {
|
||||
|
||||
final CacheRecord record;
|
||||
|
||||
public Record(CacheRecord record) {
|
||||
this.record = record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Path> getDependencyPaths() {
|
||||
return record.getArtifacts().stream()
|
||||
.map(artifact -> artifact.getFile().toPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
ClassRealm realm = record.getRealm();
|
||||
try {
|
||||
realm.getWorld().disposeRealm(realm.getId());
|
||||
} catch (NoSuchRealmException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Cache<Key, Record> cache;
|
||||
|
||||
@Inject
|
||||
public InvalidatingPluginRealmCache(CacheFactory cacheFactory) {
|
||||
cache = cacheFactory.newCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheRecord get(Key key) {
|
||||
Record r = cache.get(key);
|
||||
return r != null ? r.record : null;
|
||||
}
|
||||
|
||||
public CacheRecord get(Key key, PluginRealmSupplier supplier)
|
||||
throws PluginResolutionException, PluginContainerException {
|
||||
try {
|
||||
Record r = cache.computeIfAbsent(key, k -> {
|
||||
try {
|
||||
return new Record(supplier.load());
|
||||
} catch (PluginResolutionException | PluginContainerException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
return r.record;
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getCause() instanceof PluginResolutionException) {
|
||||
throw (PluginResolutionException) e.getCause();
|
||||
}
|
||||
if (e.getCause() instanceof PluginContainerException) {
|
||||
throw (PluginContainerException) e.getCause();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheRecord put(Key key, ClassRealm pluginRealm, List<Artifact> pluginArtifacts) {
|
||||
CacheRecord record = super.put(key, pluginRealm, pluginArtifacts);
|
||||
super.cache.remove(key);
|
||||
cache.put(key, new Record(record));
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(MavenProject project, Key key, CacheRecord record) {}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.execution;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.maven.execution.MavenExecutionResult;
|
||||
|
||||
/**
|
||||
* Instances of this class are responsible for determining whether it makes sense to "resume" a build (i.e., using
|
||||
* the {@code --resume} flag.
|
||||
*/
|
||||
public interface BuildResumptionAnalyzer {
|
||||
/**
|
||||
* Construct an instance of {@link BuildResumptionData} based on the outcome of the current Maven build.
|
||||
*
|
||||
* @param result Outcome of the current Maven build.
|
||||
* @return A {@link BuildResumptionData} instance or {@link Optional#empty()} if resuming the build is not
|
||||
* possible.
|
||||
*/
|
||||
Optional<BuildResumptionData> determineBuildResumptionData(final MavenExecutionResult result);
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.execution;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class holds the information required to enable resuming a Maven build with {@code --resume}.
|
||||
*/
|
||||
public class BuildResumptionData {
|
||||
/**
|
||||
* The list of projects that remain to be built.
|
||||
*/
|
||||
private final List<String> remainingProjects;
|
||||
|
||||
public BuildResumptionData(final List<String> remainingProjects) {
|
||||
this.remainingProjects = remainingProjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the projects that still need to be built when resuming.
|
||||
*
|
||||
* @return A list containing the group and artifact id of the projects.
|
||||
*/
|
||||
public List<String> getRemainingProjects() {
|
||||
return this.remainingProjects;
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.execution;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
|
||||
/**
|
||||
* Instances of this interface retrieve and store data for the --resume / -r feature. This data is used to ensure newer
|
||||
* builds of the same project, that have the -r command-line flag, skip successfully built projects during earlier
|
||||
* invocations of Maven.
|
||||
*/
|
||||
public interface BuildResumptionDataRepository {
|
||||
/**
|
||||
* Persists any data needed to resume the build at a later point in time, using a new Maven invocation. This method
|
||||
* may also decide it is not needed or meaningful to persist such data, and return <code>false</code> to indicate
|
||||
* so.
|
||||
*
|
||||
* @param rootProject The root project that is being built.
|
||||
* @param buildResumptionData Information needed to resume the build.
|
||||
* @throws BuildResumptionPersistenceException When an error occurs while persisting data.
|
||||
*/
|
||||
void persistResumptionData(final MavenProject rootProject, final BuildResumptionData buildResumptionData)
|
||||
throws BuildResumptionPersistenceException;
|
||||
|
||||
/**
|
||||
* Uses previously stored resumption data to enrich an existing execution request.
|
||||
*
|
||||
* @param request The execution request that will be enriched.
|
||||
* @param rootProject The root project that is being built.
|
||||
*/
|
||||
void applyResumptionData(final MavenExecutionRequest request, final MavenProject rootProject);
|
||||
|
||||
/**
|
||||
* Removes previously stored resumption data.
|
||||
*
|
||||
* @param rootProject The root project that is being built.
|
||||
*/
|
||||
void removeResumptionData(final MavenProject rootProject);
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.execution;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This exception will be thrown when something fails while persisting build resumption data.
|
||||
*
|
||||
* @see BuildResumptionDataRepository#persistResumptionData
|
||||
*/
|
||||
public class BuildResumptionPersistenceException extends Exception {
|
||||
public BuildResumptionPersistenceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.execution;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.execution.BuildFailure;
|
||||
import org.apache.maven.execution.BuildSuccess;
|
||||
import org.apache.maven.execution.MavenExecutionResult;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link BuildResumptionAnalyzer}.
|
||||
*/
|
||||
@Named
|
||||
@Singleton
|
||||
public class DefaultBuildResumptionAnalyzer implements BuildResumptionAnalyzer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultBuildResumptionAnalyzer.class);
|
||||
|
||||
@Override
|
||||
public Optional<BuildResumptionData> determineBuildResumptionData(final MavenExecutionResult result) {
|
||||
if (!result.hasExceptions()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
List<MavenProject> sortedProjects = result.getTopologicallySortedProjects();
|
||||
|
||||
boolean hasNoSuccess =
|
||||
sortedProjects.stream().noneMatch(project -> result.getBuildSummary(project) instanceof BuildSuccess);
|
||||
|
||||
if (hasNoSuccess) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
List<String> remainingProjects = sortedProjects.stream()
|
||||
.filter(project -> result.getBuildSummary(project) == null
|
||||
|| result.getBuildSummary(project) instanceof BuildFailure)
|
||||
.map(project -> project.getGroupId() + ":" + project.getArtifactId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (remainingProjects.isEmpty()) {
|
||||
LOGGER.info("No remaining projects found, resuming the build would not make sense.");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(new BuildResumptionData(remainingProjects));
|
||||
}
|
||||
}
|
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.execution;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This implementation of {@link BuildResumptionDataRepository} persists information in a properties file. The file is
|
||||
* stored in the build output directory under the Maven execution root.
|
||||
*/
|
||||
@Named
|
||||
@Singleton
|
||||
public class DefaultBuildResumptionDataRepository implements BuildResumptionDataRepository {
|
||||
private static final String RESUME_PROPERTIES_FILENAME = "resume.properties";
|
||||
private static final String REMAINING_PROJECTS = "remainingProjects";
|
||||
private static final String PROPERTY_DELIMITER = ", ";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultBuildResumptionDataRepository.class);
|
||||
|
||||
@Override
|
||||
public void persistResumptionData(MavenProject rootProject, BuildResumptionData buildResumptionData)
|
||||
throws BuildResumptionPersistenceException {
|
||||
Path directory = Paths.get(rootProject.getBuild().getDirectory());
|
||||
persistResumptionData(directory, buildResumptionData);
|
||||
}
|
||||
|
||||
public void persistResumptionData(Path directory, BuildResumptionData buildResumptionData)
|
||||
throws BuildResumptionPersistenceException {
|
||||
Properties properties = convertToProperties(buildResumptionData);
|
||||
|
||||
Path resumeProperties = directory.resolve(RESUME_PROPERTIES_FILENAME);
|
||||
try {
|
||||
Files.createDirectories(resumeProperties.getParent());
|
||||
try (Writer writer = Files.newBufferedWriter(resumeProperties)) {
|
||||
properties.store(writer, null);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
String message = "Could not create " + RESUME_PROPERTIES_FILENAME + " file.";
|
||||
throw new BuildResumptionPersistenceException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Properties convertToProperties(final BuildResumptionData buildResumptionData) {
|
||||
Properties properties = new Properties();
|
||||
|
||||
String value = String.join(PROPERTY_DELIMITER, buildResumptionData.getRemainingProjects());
|
||||
properties.setProperty(REMAINING_PROJECTS, value);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyResumptionData(MavenExecutionRequest request, MavenProject rootProject) {
|
||||
Path directory = Paths.get(rootProject.getBuild().getDirectory());
|
||||
applyResumptionData(request, directory);
|
||||
}
|
||||
|
||||
public void applyResumptionData(MavenExecutionRequest request, Path directory) {
|
||||
Properties properties = loadResumptionFile(directory);
|
||||
applyResumptionProperties(request, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeResumptionData(MavenProject rootProject) {
|
||||
Path directory = Paths.get(rootProject.getBuild().getDirectory());
|
||||
removeResumptionData(directory);
|
||||
}
|
||||
|
||||
public void removeResumptionData(Path directory) {
|
||||
Path resumeProperties = directory.resolve(RESUME_PROPERTIES_FILENAME);
|
||||
try {
|
||||
Files.deleteIfExists(resumeProperties);
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn("Could not delete {} file. ", RESUME_PROPERTIES_FILENAME, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Properties loadResumptionFile(Path rootBuildDirectory) {
|
||||
Properties properties = new Properties();
|
||||
Path path = rootBuildDirectory.resolve(RESUME_PROPERTIES_FILENAME);
|
||||
if (!Files.exists(path)) {
|
||||
LOGGER.warn("The {} file does not exist. The --resume / -r feature will not work.", path);
|
||||
return properties;
|
||||
}
|
||||
|
||||
try (Reader reader = Files.newBufferedReader(path)) {
|
||||
properties.load(reader);
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn("Unable to read {}. The --resume / -r feature will not work.", path);
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
// This method is made package-private for testing purposes
|
||||
void applyResumptionProperties(MavenExecutionRequest request, Properties properties) {
|
||||
if (properties.containsKey(REMAINING_PROJECTS) && StringUtils.isEmpty(request.getResumeFrom())) {
|
||||
String propertyValue = properties.getProperty(REMAINING_PROJECTS);
|
||||
Stream.of(propertyValue.split(PROPERTY_DELIMITER))
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.forEach(request.getSelectedProjects()::add);
|
||||
LOGGER.info("Resuming from {} due to the --resume / -r feature.", propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.plugin;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.plugin.version.PluginVersionRequest;
|
||||
import org.apache.maven.plugin.version.PluginVersionResolutionException;
|
||||
import org.apache.maven.plugin.version.PluginVersionResolver;
|
||||
import org.apache.maven.plugin.version.PluginVersionResult;
|
||||
import org.apache.maven.plugin.version.internal.DefaultPluginVersionResolver;
|
||||
import org.eclipse.aether.SessionData;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
import org.eclipse.sisu.Priority;
|
||||
import org.eclipse.sisu.Typed;
|
||||
|
||||
@Named
|
||||
@Singleton
|
||||
@Priority(10)
|
||||
@Typed(PluginVersionResolver.class)
|
||||
public class CachingPluginVersionResolver extends DefaultPluginVersionResolver {
|
||||
|
||||
private static final Object CACHE_KEY = new Object();
|
||||
|
||||
@Override
|
||||
public PluginVersionResult resolve(PluginVersionRequest request) throws PluginVersionResolutionException {
|
||||
Map<String, PluginVersionResult> cache =
|
||||
getCache(request.getRepositorySession().getData());
|
||||
String key = getKey(request);
|
||||
PluginVersionResult result = cache.get(key);
|
||||
if (result == null) {
|
||||
result = super.resolve(request);
|
||||
cache.putIfAbsent(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, PluginVersionResult> getCache(SessionData data) {
|
||||
Map<String, PluginVersionResult> cache = (Map<String, PluginVersionResult>) data.get(CACHE_KEY);
|
||||
while (cache == null) {
|
||||
cache = new ConcurrentHashMap<>(256);
|
||||
if (data.set(CACHE_KEY, null, cache)) {
|
||||
break;
|
||||
}
|
||||
cache = (Map<String, PluginVersionResult>) data.get(CACHE_KEY);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
private static String getKey(PluginVersionRequest request) {
|
||||
return Stream.concat(
|
||||
Stream.of(request.getGroupId(), request.getArtifactId()),
|
||||
request.getRepositories().stream().map(RemoteRepository::getId))
|
||||
.collect(Collectors.joining(":"));
|
||||
}
|
||||
}
|
@@ -0,0 +1,779 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.plugin;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.apache.maven.RepositoryUtils;
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.classrealm.ClassRealmManager;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule;
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.monitor.logging.DefaultLog;
|
||||
import org.apache.maven.plugin.*;
|
||||
import org.apache.maven.plugin.descriptor.MojoDescriptor;
|
||||
import org.apache.maven.plugin.descriptor.Parameter;
|
||||
import org.apache.maven.plugin.descriptor.PluginDescriptor;
|
||||
import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
|
||||
import org.apache.maven.plugin.internal.PluginDependenciesResolver;
|
||||
import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
|
||||
import org.apache.maven.plugin.version.PluginVersionRequest;
|
||||
import org.apache.maven.plugin.version.PluginVersionResolutionException;
|
||||
import org.apache.maven.plugin.version.PluginVersionResolver;
|
||||
import org.apache.maven.project.ExtensionDescriptor;
|
||||
import org.apache.maven.project.ExtensionDescriptorBuilder;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.rtinfo.RuntimeInformation;
|
||||
import org.apache.maven.session.scope.internal.SessionScopeModule;
|
||||
import org.codehaus.plexus.DefaultPlexusContainer;
|
||||
import org.codehaus.plexus.PlexusContainer;
|
||||
import org.codehaus.plexus.classworlds.realm.ClassRealm;
|
||||
import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException;
|
||||
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
|
||||
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
|
||||
import org.codehaus.plexus.component.configurator.ConfigurationListener;
|
||||
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
|
||||
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
|
||||
import org.codehaus.plexus.component.repository.ComponentDescriptor;
|
||||
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
|
||||
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
|
||||
import org.codehaus.plexus.configuration.PlexusConfiguration;
|
||||
import org.codehaus.plexus.configuration.PlexusConfigurationException;
|
||||
import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
|
||||
import org.codehaus.plexus.logging.Logger;
|
||||
import org.codehaus.plexus.logging.LoggerManager;
|
||||
import org.codehaus.plexus.util.ReaderFactory;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.codehaus.plexus.util.xml.Xpp3Dom;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.aether.graph.DependencyFilter;
|
||||
import org.eclipse.aether.graph.DependencyNode;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
import org.eclipse.aether.util.filter.AndDependencyFilter;
|
||||
import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator;
|
||||
import org.eclipse.sisu.Priority;
|
||||
import org.eclipse.sisu.Typed;
|
||||
import org.mvndaemon.mvnd.cache.invalidating.InvalidatingPluginDescriptorCache;
|
||||
import org.mvndaemon.mvnd.cache.invalidating.InvalidatingPluginRealmCache;
|
||||
|
||||
/*
|
||||
* gnodet: This file is based on maven DefaultMavenPluginManager and changed in order
|
||||
* to better support parallel builds. See https://github.com/apache/maven-mvnd/issues/310
|
||||
*/
|
||||
/**
|
||||
* Provides basic services to manage Maven plugins and their mojos. This component is kept general in its design such
|
||||
* that the plugins/mojos can be used in arbitrary contexts. In particular, the mojos can be used for ordinary build
|
||||
* plugins as well as special purpose plugins like reports.
|
||||
*
|
||||
* @author Benjamin Bentmann
|
||||
* @since 3.0
|
||||
*/
|
||||
@Singleton
|
||||
@Named
|
||||
@Priority(10)
|
||||
@Typed(MavenPluginManager.class)
|
||||
public class CliMavenPluginManager implements MavenPluginManager {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* PluginId => ExtensionRealmCache.CacheRecord map MavenProject context value key. The map is used to ensure the
|
||||
* same class realm is used to load build extensions and load mojos for extensions=true plugins.
|
||||
* </p>
|
||||
* <strong>Note:</strong> This is part of internal implementation and may be changed or removed without notice
|
||||
*
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public static final String KEY_EXTENSIONS_REALMS = CliMavenPluginManager.class.getName() + "/extensionsRealms";
|
||||
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@Inject
|
||||
private LoggerManager loggerManager;
|
||||
|
||||
@Inject
|
||||
private PlexusContainer container;
|
||||
|
||||
@Inject
|
||||
private ClassRealmManager classRealmManager;
|
||||
|
||||
@Inject
|
||||
private InvalidatingPluginDescriptorCache pluginDescriptorCache;
|
||||
|
||||
@Inject
|
||||
private InvalidatingPluginRealmCache pluginRealmCache;
|
||||
|
||||
@Inject
|
||||
private PluginDependenciesResolver pluginDependenciesResolver;
|
||||
|
||||
@Inject
|
||||
private RuntimeInformation runtimeInformation;
|
||||
|
||||
@Inject
|
||||
private ExtensionRealmCache extensionRealmCache;
|
||||
|
||||
@Inject
|
||||
private PluginVersionResolver pluginVersionResolver;
|
||||
|
||||
@Inject
|
||||
private PluginArtifactsCache pluginArtifactsCache;
|
||||
|
||||
private ExtensionDescriptorBuilder extensionDescriptorBuilder = new ExtensionDescriptorBuilder();
|
||||
|
||||
private PluginDescriptorBuilder builder = new PluginDescriptorBuilder();
|
||||
|
||||
public PluginDescriptor getPluginDescriptor(
|
||||
Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session)
|
||||
throws PluginResolutionException, PluginDescriptorParsingException, InvalidPluginDescriptorException {
|
||||
PluginDescriptorCache.Key cacheKey = pluginDescriptorCache.createKey(plugin, repositories, session);
|
||||
|
||||
PluginDescriptor pluginDescriptor = pluginDescriptorCache.get(cacheKey, () -> {
|
||||
org.eclipse.aether.artifact.Artifact artifact =
|
||||
pluginDependenciesResolver.resolve(plugin, repositories, session);
|
||||
|
||||
Artifact pluginArtifact = RepositoryUtils.toArtifact(artifact);
|
||||
|
||||
PluginDescriptor descriptor = extractPluginDescriptor(pluginArtifact, plugin);
|
||||
|
||||
descriptor.setRequiredMavenVersion(artifact.getProperty("requiredMavenVersion", null));
|
||||
|
||||
return descriptor;
|
||||
});
|
||||
|
||||
pluginDescriptor.setPlugin(plugin);
|
||||
|
||||
return pluginDescriptor;
|
||||
}
|
||||
|
||||
private PluginDescriptor extractPluginDescriptor(Artifact pluginArtifact, Plugin plugin)
|
||||
throws PluginDescriptorParsingException, InvalidPluginDescriptorException {
|
||||
PluginDescriptor pluginDescriptor = null;
|
||||
|
||||
File pluginFile = pluginArtifact.getFile();
|
||||
|
||||
try {
|
||||
if (pluginFile.isFile()) {
|
||||
try (JarFile pluginJar = new JarFile(pluginFile, false)) {
|
||||
ZipEntry pluginDescriptorEntry = pluginJar.getEntry(getPluginDescriptorLocation());
|
||||
|
||||
if (pluginDescriptorEntry != null) {
|
||||
InputStream is = pluginJar.getInputStream(pluginDescriptorEntry);
|
||||
|
||||
pluginDescriptor = parsePluginDescriptor(is, plugin, pluginFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
File pluginXml = new File(pluginFile, getPluginDescriptorLocation());
|
||||
|
||||
if (pluginXml.isFile()) {
|
||||
try (InputStream is = new BufferedInputStream(new FileInputStream(pluginXml))) {
|
||||
pluginDescriptor = parsePluginDescriptor(is, plugin, pluginXml.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginDescriptor == null) {
|
||||
throw new IOException("No plugin descriptor found at " + getPluginDescriptorLocation());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new PluginDescriptorParsingException(plugin, pluginFile.getAbsolutePath(), e);
|
||||
}
|
||||
|
||||
MavenPluginValidator validator = new MavenPluginValidator(pluginArtifact);
|
||||
|
||||
validator.validate(pluginDescriptor);
|
||||
|
||||
if (validator.hasErrors()) {
|
||||
throw new InvalidPluginDescriptorException(
|
||||
"Invalid plugin descriptor for " + plugin.getId() + " (" + pluginFile + ")", validator.getErrors());
|
||||
}
|
||||
|
||||
pluginDescriptor.setPluginArtifact(pluginArtifact);
|
||||
|
||||
return pluginDescriptor;
|
||||
}
|
||||
|
||||
private String getPluginDescriptorLocation() {
|
||||
return "META-INF/maven/plugin.xml";
|
||||
}
|
||||
|
||||
private PluginDescriptor parsePluginDescriptor(InputStream is, Plugin plugin, String descriptorLocation)
|
||||
throws PluginDescriptorParsingException {
|
||||
try {
|
||||
Reader reader = ReaderFactory.newXmlReader(is);
|
||||
|
||||
PluginDescriptor pluginDescriptor = builder.build(reader, descriptorLocation);
|
||||
|
||||
return pluginDescriptor;
|
||||
} catch (IOException | PlexusConfigurationException e) {
|
||||
throw new PluginDescriptorParsingException(plugin, descriptorLocation, e);
|
||||
}
|
||||
}
|
||||
|
||||
public MojoDescriptor getMojoDescriptor(
|
||||
Plugin plugin, String goal, List<RemoteRepository> repositories, RepositorySystemSession session)
|
||||
throws MojoNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
|
||||
InvalidPluginDescriptorException {
|
||||
PluginDescriptor pluginDescriptor = getPluginDescriptor(plugin, repositories, session);
|
||||
|
||||
MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo(goal);
|
||||
|
||||
if (mojoDescriptor == null) {
|
||||
throw new MojoNotFoundException(goal, pluginDescriptor);
|
||||
}
|
||||
|
||||
return mojoDescriptor;
|
||||
}
|
||||
|
||||
public void checkRequiredMavenVersion(PluginDescriptor pluginDescriptor) throws PluginIncompatibleException {
|
||||
String requiredMavenVersion = pluginDescriptor.getRequiredMavenVersion();
|
||||
if (StringUtils.isNotBlank(requiredMavenVersion)) {
|
||||
try {
|
||||
if (!runtimeInformation.isMavenVersion(requiredMavenVersion)) {
|
||||
throw new PluginIncompatibleException(
|
||||
pluginDescriptor.getPlugin(),
|
||||
"The plugin " + pluginDescriptor.getId() + " requires Maven version "
|
||||
+ requiredMavenVersion);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
logger.warn("Could not verify plugin's Maven prerequisite: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setupPluginRealm(
|
||||
PluginDescriptor pluginDescriptor,
|
||||
MavenSession session,
|
||||
ClassLoader parent,
|
||||
List<String> imports,
|
||||
DependencyFilter filter)
|
||||
throws PluginResolutionException, PluginContainerException {
|
||||
Plugin plugin = pluginDescriptor.getPlugin();
|
||||
MavenProject project = session.getCurrentProject();
|
||||
|
||||
if (plugin.isExtensions()) {
|
||||
ExtensionRealmCache.CacheRecord extensionRecord;
|
||||
try {
|
||||
RepositorySystemSession repositorySession = session.getRepositorySession();
|
||||
extensionRecord = setupExtensionsRealm(project, plugin, repositorySession);
|
||||
} catch (PluginManagerException e) {
|
||||
// extensions realm is expected to be fully setup at this point
|
||||
// any exception means a problem in maven code, not a user error
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
ClassRealm pluginRealm = extensionRecord.getRealm();
|
||||
List<Artifact> pluginArtifacts = extensionRecord.getArtifacts();
|
||||
|
||||
for (ComponentDescriptor<?> componentDescriptor : pluginDescriptor.getComponents()) {
|
||||
componentDescriptor.setRealm(pluginRealm);
|
||||
}
|
||||
|
||||
pluginDescriptor.setClassRealm(pluginRealm);
|
||||
pluginDescriptor.setArtifacts(pluginArtifacts);
|
||||
} else {
|
||||
Map<String, ClassLoader> foreignImports = calcImports(project, parent, imports);
|
||||
|
||||
PluginRealmCache.Key cacheKey = pluginRealmCache.createKey(
|
||||
plugin,
|
||||
parent,
|
||||
foreignImports,
|
||||
filter,
|
||||
project.getRemotePluginRepositories(),
|
||||
session.getRepositorySession());
|
||||
|
||||
PluginRealmCache.CacheRecord cacheRecord = pluginRealmCache.get(cacheKey, () -> {
|
||||
createPluginRealm(pluginDescriptor, session, parent, foreignImports, filter);
|
||||
return new PluginRealmCache.CacheRecord(
|
||||
pluginDescriptor.getClassRealm(), pluginDescriptor.getArtifacts());
|
||||
});
|
||||
|
||||
if (cacheRecord != null) {
|
||||
pluginDescriptor.setClassRealm(cacheRecord.getRealm());
|
||||
pluginDescriptor.setArtifacts(new ArrayList<>(cacheRecord.getArtifacts()));
|
||||
for (ComponentDescriptor<?> componentDescriptor : pluginDescriptor.getComponents()) {
|
||||
componentDescriptor.setRealm(cacheRecord.getRealm());
|
||||
}
|
||||
}
|
||||
|
||||
pluginRealmCache.register(project, cacheKey, cacheRecord);
|
||||
}
|
||||
}
|
||||
|
||||
private void createPluginRealm(
|
||||
PluginDescriptor pluginDescriptor,
|
||||
MavenSession session,
|
||||
ClassLoader parent,
|
||||
Map<String, ClassLoader> foreignImports,
|
||||
DependencyFilter filter)
|
||||
throws PluginResolutionException, PluginContainerException {
|
||||
Plugin plugin = Objects.requireNonNull(pluginDescriptor.getPlugin(), "pluginDescriptor.plugin cannot be null");
|
||||
|
||||
Artifact pluginArtifact = Objects.requireNonNull(
|
||||
pluginDescriptor.getPluginArtifact(), "pluginDescriptor.pluginArtifact cannot be null");
|
||||
|
||||
MavenProject project = session.getCurrentProject();
|
||||
|
||||
final ClassRealm pluginRealm;
|
||||
final List<Artifact> pluginArtifacts;
|
||||
|
||||
RepositorySystemSession repositorySession = session.getRepositorySession();
|
||||
DependencyFilter dependencyFilter = project.getExtensionDependencyFilter();
|
||||
dependencyFilter = AndDependencyFilter.newInstance(dependencyFilter, filter);
|
||||
|
||||
DependencyNode root = pluginDependenciesResolver.resolve(
|
||||
plugin,
|
||||
RepositoryUtils.toArtifact(pluginArtifact),
|
||||
dependencyFilter,
|
||||
project.getRemotePluginRepositories(),
|
||||
repositorySession);
|
||||
|
||||
PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
|
||||
root.accept(nlg);
|
||||
|
||||
pluginArtifacts = toMavenArtifacts(root, nlg);
|
||||
|
||||
if (parent == null) {
|
||||
parent = new URLClassLoader(new URL[0]);
|
||||
}
|
||||
pluginRealm = classRealmManager.createPluginRealm(
|
||||
plugin, parent, null, foreignImports, toAetherArtifacts(pluginArtifacts));
|
||||
|
||||
discoverPluginComponents(pluginRealm, plugin, pluginDescriptor);
|
||||
|
||||
pluginDescriptor.setClassRealm(pluginRealm);
|
||||
pluginDescriptor.setArtifacts(pluginArtifacts);
|
||||
}
|
||||
|
||||
private void discoverPluginComponents(
|
||||
final ClassRealm pluginRealm, Plugin plugin, PluginDescriptor pluginDescriptor)
|
||||
throws PluginContainerException {
|
||||
try {
|
||||
if (pluginDescriptor != null) {
|
||||
for (ComponentDescriptor<?> componentDescriptor : pluginDescriptor.getComponents()) {
|
||||
componentDescriptor.setRealm(pluginRealm);
|
||||
container.addComponentDescriptor(componentDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
((DefaultPlexusContainer) container)
|
||||
.discoverComponents(
|
||||
pluginRealm, new SessionScopeModule(container), new MojoExecutionScopeModule(container));
|
||||
} catch (ComponentLookupException | CycleDetectedInComponentGraphException e) {
|
||||
throw new PluginContainerException(
|
||||
plugin,
|
||||
pluginRealm,
|
||||
"Error in component graph of plugin " + plugin.getId() + ": " + e.getMessage(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<org.eclipse.aether.artifact.Artifact> toAetherArtifacts(final List<Artifact> pluginArtifacts) {
|
||||
return new ArrayList<>(RepositoryUtils.toArtifacts(pluginArtifacts));
|
||||
}
|
||||
|
||||
private List<Artifact> toMavenArtifacts(DependencyNode root, PreorderNodeListGenerator nlg) {
|
||||
List<Artifact> artifacts = new ArrayList<>(nlg.getNodes().size());
|
||||
RepositoryUtils.toArtifacts(artifacts, Collections.singleton(root), Collections.<String>emptyList(), null);
|
||||
for (Iterator<Artifact> it = artifacts.iterator(); it.hasNext(); ) {
|
||||
Artifact artifact = it.next();
|
||||
if (artifact.getFile() == null) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(artifacts);
|
||||
}
|
||||
|
||||
private Map<String, ClassLoader> calcImports(MavenProject project, ClassLoader parent, List<String> imports) {
|
||||
Map<String, ClassLoader> foreignImports = new HashMap<>();
|
||||
|
||||
ClassLoader projectRealm = project.getClassRealm();
|
||||
if (projectRealm != null) {
|
||||
foreignImports.put("", projectRealm);
|
||||
} else {
|
||||
foreignImports.put("", classRealmManager.getMavenApiRealm());
|
||||
}
|
||||
|
||||
if (parent != null && imports != null) {
|
||||
for (String parentImport : imports) {
|
||||
foreignImports.put(parentImport, parent);
|
||||
}
|
||||
}
|
||||
|
||||
return foreignImports;
|
||||
}
|
||||
|
||||
public <T> T getConfiguredMojo(Class<T> mojoInterface, MavenSession session, MojoExecution mojoExecution)
|
||||
throws PluginConfigurationException, PluginContainerException {
|
||||
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
|
||||
|
||||
PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
|
||||
|
||||
ClassRealm pluginRealm = pluginDescriptor.getClassRealm();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Configuring mojo " + mojoDescriptor.getId() + " from plugin realm " + pluginRealm);
|
||||
}
|
||||
|
||||
// We are forcing the use of the plugin realm for all lookups that might occur during
|
||||
// the lifecycle that is part of the lookup. Here we are specifically trying to keep
|
||||
// lookups that occur in contextualize calls in line with the right realm.
|
||||
ClassRealm oldLookupRealm = container.setLookupRealm(pluginRealm);
|
||||
|
||||
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(pluginRealm);
|
||||
|
||||
try {
|
||||
T mojo;
|
||||
|
||||
try {
|
||||
mojo = container.lookup(mojoInterface, mojoDescriptor.getRoleHint());
|
||||
} catch (ComponentLookupException e) {
|
||||
Throwable cause = e.getCause();
|
||||
while (cause != null
|
||||
&& !(cause instanceof LinkageError)
|
||||
&& !(cause instanceof ClassNotFoundException)) {
|
||||
cause = cause.getCause();
|
||||
}
|
||||
|
||||
if ((cause instanceof NoClassDefFoundError) || (cause instanceof ClassNotFoundException)) {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
|
||||
PrintStream ps = new PrintStream(os);
|
||||
ps.println("Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '"
|
||||
+ pluginDescriptor.getId() + "'. A required class is missing: "
|
||||
+ cause.getMessage());
|
||||
pluginRealm.display(ps);
|
||||
|
||||
throw new PluginContainerException(mojoDescriptor, pluginRealm, os.toString(), cause);
|
||||
} else if (cause instanceof LinkageError) {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
|
||||
PrintStream ps = new PrintStream(os);
|
||||
ps.println("Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '"
|
||||
+ pluginDescriptor.getId() + "' due to an API incompatibility: "
|
||||
+ e.getClass().getName() + ": " + cause.getMessage());
|
||||
pluginRealm.display(ps);
|
||||
|
||||
throw new PluginContainerException(mojoDescriptor, pluginRealm, os.toString(), cause);
|
||||
}
|
||||
|
||||
throw new PluginContainerException(
|
||||
mojoDescriptor,
|
||||
pluginRealm,
|
||||
"Unable to load the mojo '" + mojoDescriptor.getGoal()
|
||||
+ "' (or one of its required components) from the plugin '"
|
||||
+ pluginDescriptor.getId() + "'",
|
||||
e);
|
||||
}
|
||||
|
||||
if (mojo instanceof ContextEnabled) {
|
||||
MavenProject project = session.getCurrentProject();
|
||||
|
||||
Map<String, Object> pluginContext = session.getPluginContext(pluginDescriptor, project);
|
||||
|
||||
if (pluginContext != null) {
|
||||
pluginContext.put("project", project);
|
||||
|
||||
pluginContext.put("pluginDescriptor", pluginDescriptor);
|
||||
|
||||
((ContextEnabled) mojo).setPluginContext(pluginContext);
|
||||
}
|
||||
}
|
||||
|
||||
if (mojo instanceof Mojo) {
|
||||
Logger mojoLogger = loggerManager.getLoggerForComponent(mojoDescriptor.getImplementation());
|
||||
((Mojo) mojo).setLog(new DefaultLog(mojoLogger));
|
||||
}
|
||||
|
||||
Xpp3Dom dom = mojoExecution.getConfiguration();
|
||||
|
||||
PlexusConfiguration pomConfiguration;
|
||||
|
||||
if (dom == null) {
|
||||
pomConfiguration = new XmlPlexusConfiguration("configuration");
|
||||
} else {
|
||||
pomConfiguration = new XmlPlexusConfiguration(dom);
|
||||
}
|
||||
|
||||
ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator(session, mojoExecution);
|
||||
|
||||
populatePluginFields(mojo, mojoDescriptor, pluginRealm, pomConfiguration, expressionEvaluator);
|
||||
|
||||
return mojo;
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(oldClassLoader);
|
||||
container.setLookupRealm(oldLookupRealm);
|
||||
}
|
||||
}
|
||||
|
||||
private void populatePluginFields(
|
||||
Object mojo,
|
||||
MojoDescriptor mojoDescriptor,
|
||||
ClassRealm pluginRealm,
|
||||
PlexusConfiguration configuration,
|
||||
ExpressionEvaluator expressionEvaluator)
|
||||
throws PluginConfigurationException {
|
||||
ComponentConfigurator configurator = null;
|
||||
|
||||
String configuratorId = mojoDescriptor.getComponentConfigurator();
|
||||
|
||||
if (StringUtils.isEmpty(configuratorId)) {
|
||||
configuratorId = "basic";
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO could the configuration be passed to lookup and the configurator known to plexus via the descriptor
|
||||
// so that this method could entirely be handled by a plexus lookup?
|
||||
configurator = container.lookup(ComponentConfigurator.class, configuratorId);
|
||||
|
||||
ConfigurationListener listener = new DebugConfigurationListener(logger);
|
||||
|
||||
ValidatingConfigurationListener validator =
|
||||
new ValidatingConfigurationListener(mojo, mojoDescriptor, listener);
|
||||
|
||||
logger.debug(
|
||||
"Configuring mojo '" + mojoDescriptor.getId() + "' with " + configuratorId + " configurator -->");
|
||||
|
||||
configurator.configureComponent(mojo, configuration, expressionEvaluator, pluginRealm, validator);
|
||||
|
||||
logger.debug("-- end configuration --");
|
||||
|
||||
Collection<Parameter> missingParameters = validator.getMissingParameters();
|
||||
if (!missingParameters.isEmpty()) {
|
||||
if ("basic".equals(configuratorId)) {
|
||||
throw new PluginParameterException(mojoDescriptor, new ArrayList<>(missingParameters));
|
||||
} else {
|
||||
/*
|
||||
* NOTE: Other configurators like the map-oriented one don't call into the listener, so do it the
|
||||
* hard way.
|
||||
*/
|
||||
validateParameters(mojoDescriptor, configuration, expressionEvaluator);
|
||||
}
|
||||
}
|
||||
} catch (ComponentConfigurationException e) {
|
||||
String message = "Unable to parse configuration of mojo " + mojoDescriptor.getId();
|
||||
if (e.getFailedConfiguration() != null) {
|
||||
message += " for parameter " + e.getFailedConfiguration().getName();
|
||||
}
|
||||
message += ": " + e.getMessage();
|
||||
|
||||
throw new PluginConfigurationException(mojoDescriptor.getPluginDescriptor(), message, e);
|
||||
} catch (ComponentLookupException e) {
|
||||
throw new PluginConfigurationException(
|
||||
mojoDescriptor.getPluginDescriptor(),
|
||||
"Unable to retrieve component configurator " + configuratorId + " for configuration of mojo "
|
||||
+ mojoDescriptor.getId(),
|
||||
e);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
|
||||
PrintStream ps = new PrintStream(os);
|
||||
ps.println("A required class was missing during configuration of mojo " + mojoDescriptor.getId() + ": "
|
||||
+ e.getMessage());
|
||||
pluginRealm.display(ps);
|
||||
|
||||
throw new PluginConfigurationException(mojoDescriptor.getPluginDescriptor(), os.toString(), e);
|
||||
} catch (LinkageError e) {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
|
||||
PrintStream ps = new PrintStream(os);
|
||||
ps.println("An API incompatibility was encountered during configuration of mojo " + mojoDescriptor.getId()
|
||||
+ ": " + e.getClass().getName() + ": " + e.getMessage());
|
||||
pluginRealm.display(ps);
|
||||
|
||||
throw new PluginConfigurationException(mojoDescriptor.getPluginDescriptor(), os.toString(), e);
|
||||
} finally {
|
||||
if (configurator != null) {
|
||||
try {
|
||||
container.release(configurator);
|
||||
} catch (ComponentLifecycleException e) {
|
||||
logger.debug("Failed to release mojo configurator - ignoring.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateParameters(
|
||||
MojoDescriptor mojoDescriptor, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator)
|
||||
throws ComponentConfigurationException, PluginParameterException {
|
||||
if (mojoDescriptor.getParameters() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Parameter> invalidParameters = new ArrayList<>();
|
||||
|
||||
for (Parameter parameter : mojoDescriptor.getParameters()) {
|
||||
if (!parameter.isRequired()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object value = null;
|
||||
|
||||
PlexusConfiguration config = configuration.getChild(parameter.getName(), false);
|
||||
if (config != null) {
|
||||
String expression = config.getValue(null);
|
||||
|
||||
try {
|
||||
value = expressionEvaluator.evaluate(expression);
|
||||
|
||||
if (value == null) {
|
||||
value = config.getAttribute("default-value", null);
|
||||
}
|
||||
} catch (ExpressionEvaluationException e) {
|
||||
String msg = "Error evaluating the expression '" + expression + "' for configuration value '"
|
||||
+ configuration.getName() + "'";
|
||||
throw new ComponentConfigurationException(configuration, msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (value == null && (config == null || config.getChildCount() <= 0)) {
|
||||
invalidParameters.add(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
if (!invalidParameters.isEmpty()) {
|
||||
throw new PluginParameterException(mojoDescriptor, invalidParameters);
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseMojo(Object mojo, MojoExecution mojoExecution) {
|
||||
if (mojo != null) {
|
||||
try {
|
||||
container.release(mojo);
|
||||
} catch (ComponentLifecycleException e) {
|
||||
String goalExecId = mojoExecution.getGoal();
|
||||
|
||||
if (mojoExecution.getExecutionId() != null) {
|
||||
goalExecId += " {execution: " + mojoExecution.getExecutionId() + "}";
|
||||
}
|
||||
|
||||
logger.debug("Error releasing mojo for " + goalExecId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ExtensionRealmCache.CacheRecord setupExtensionsRealm(
|
||||
MavenProject project, Plugin plugin, RepositorySystemSession session) throws PluginManagerException {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, ExtensionRealmCache.CacheRecord> pluginRealms =
|
||||
(Map<String, ExtensionRealmCache.CacheRecord>) project.getContextValue(KEY_EXTENSIONS_REALMS);
|
||||
if (pluginRealms == null) {
|
||||
pluginRealms = new HashMap<>();
|
||||
project.setContextValue(KEY_EXTENSIONS_REALMS, pluginRealms);
|
||||
}
|
||||
|
||||
final String pluginKey = plugin.getId();
|
||||
|
||||
ExtensionRealmCache.CacheRecord extensionRecord = pluginRealms.get(pluginKey);
|
||||
if (extensionRecord != null) {
|
||||
return extensionRecord;
|
||||
}
|
||||
|
||||
final List<RemoteRepository> repositories = project.getRemotePluginRepositories();
|
||||
|
||||
// resolve plugin version as necessary
|
||||
if (plugin.getVersion() == null) {
|
||||
PluginVersionRequest versionRequest = new DefaultPluginVersionRequest(plugin, session, repositories);
|
||||
try {
|
||||
plugin.setVersion(pluginVersionResolver.resolve(versionRequest).getVersion());
|
||||
} catch (PluginVersionResolutionException e) {
|
||||
throw new PluginManagerException(plugin, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// resolve plugin artifacts
|
||||
List<Artifact> artifacts;
|
||||
PluginArtifactsCache.Key cacheKey = pluginArtifactsCache.createKey(plugin, null, repositories, session);
|
||||
PluginArtifactsCache.CacheRecord recordArtifacts;
|
||||
try {
|
||||
recordArtifacts = pluginArtifactsCache.get(cacheKey);
|
||||
} catch (PluginResolutionException e) {
|
||||
throw new PluginManagerException(plugin, e.getMessage(), e);
|
||||
}
|
||||
if (recordArtifacts != null) {
|
||||
artifacts = recordArtifacts.getArtifacts();
|
||||
} else {
|
||||
try {
|
||||
artifacts = resolveExtensionArtifacts(plugin, repositories, session);
|
||||
recordArtifacts = pluginArtifactsCache.put(cacheKey, artifacts);
|
||||
} catch (PluginResolutionException e) {
|
||||
pluginArtifactsCache.put(cacheKey, e);
|
||||
pluginArtifactsCache.register(project, cacheKey, recordArtifacts);
|
||||
throw new PluginManagerException(plugin, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
pluginArtifactsCache.register(project, cacheKey, recordArtifacts);
|
||||
|
||||
// create and cache extensions realms
|
||||
final ExtensionRealmCache.Key extensionKey = extensionRealmCache.createKey(artifacts);
|
||||
extensionRecord = extensionRealmCache.get(extensionKey);
|
||||
if (extensionRecord == null) {
|
||||
ClassRealm extensionRealm = classRealmManager.createExtensionRealm(plugin, toAetherArtifacts(artifacts));
|
||||
|
||||
// TODO figure out how to use the same PluginDescriptor when running mojos
|
||||
|
||||
PluginDescriptor pluginDescriptor = null;
|
||||
if (plugin.isExtensions() && !artifacts.isEmpty()) {
|
||||
// ignore plugin descriptor parsing errors at this point
|
||||
// these errors will reported during calculation of project build execution plan
|
||||
try {
|
||||
pluginDescriptor = extractPluginDescriptor(artifacts.get(0), plugin);
|
||||
} catch (PluginDescriptorParsingException | InvalidPluginDescriptorException e) {
|
||||
// ignore, see above
|
||||
}
|
||||
}
|
||||
|
||||
discoverPluginComponents(extensionRealm, plugin, pluginDescriptor);
|
||||
|
||||
ExtensionDescriptor extensionDescriptor = null;
|
||||
Artifact extensionArtifact = artifacts.get(0);
|
||||
try {
|
||||
extensionDescriptor = extensionDescriptorBuilder.build(extensionArtifact.getFile());
|
||||
} catch (IOException e) {
|
||||
String message = "Invalid extension descriptor for " + plugin.getId() + ": " + e.getMessage();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.error(message, e);
|
||||
} else {
|
||||
logger.error(message);
|
||||
}
|
||||
}
|
||||
extensionRecord = extensionRealmCache.put(extensionKey, extensionRealm, extensionDescriptor, artifacts);
|
||||
}
|
||||
extensionRealmCache.register(project, extensionKey, extensionRecord);
|
||||
pluginRealms.put(pluginKey, extensionRecord);
|
||||
|
||||
return extensionRecord;
|
||||
}
|
||||
|
||||
private List<Artifact> resolveExtensionArtifacts(
|
||||
Plugin extensionPlugin, List<RemoteRepository> repositories, RepositorySystemSession session)
|
||||
throws PluginResolutionException {
|
||||
DependencyNode root = pluginDependenciesResolver.resolve(extensionPlugin, null, null, repositories, session);
|
||||
PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
|
||||
root.accept(nlg);
|
||||
return toMavenArtifacts(root, nlg);
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.plugin;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.plugin.descriptor.MojoDescriptor;
|
||||
import org.apache.maven.plugin.descriptor.Parameter;
|
||||
import org.codehaus.plexus.component.configurator.ConfigurationListener;
|
||||
|
||||
/**
|
||||
* A configuration listener to help validate the plugin configuration. For instance, check for required but missing
|
||||
* parameters.
|
||||
*
|
||||
* @author Benjamin Bentmann
|
||||
*/
|
||||
class ValidatingConfigurationListener implements ConfigurationListener {
|
||||
|
||||
private final Object mojo;
|
||||
|
||||
private final ConfigurationListener delegate;
|
||||
|
||||
private final Map<String, Parameter> missingParameters;
|
||||
|
||||
ValidatingConfigurationListener(Object mojo, MojoDescriptor mojoDescriptor, ConfigurationListener delegate) {
|
||||
this.mojo = mojo;
|
||||
this.delegate = delegate;
|
||||
this.missingParameters = new HashMap<>();
|
||||
|
||||
if (mojoDescriptor.getParameters() != null) {
|
||||
for (Parameter param : mojoDescriptor.getParameters()) {
|
||||
if (param.isRequired()) {
|
||||
missingParameters.put(param.getName(), param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Parameter> getMissingParameters() {
|
||||
return missingParameters.values();
|
||||
}
|
||||
|
||||
public void notifyFieldChangeUsingSetter(String fieldName, Object value, Object target) {
|
||||
delegate.notifyFieldChangeUsingSetter(fieldName, value, target);
|
||||
|
||||
if (mojo == target) {
|
||||
notify(fieldName, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyFieldChangeUsingReflection(String fieldName, Object value, Object target) {
|
||||
delegate.notifyFieldChangeUsingReflection(fieldName, value, target);
|
||||
|
||||
if (mojo == target) {
|
||||
notify(fieldName, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void notify(String fieldName, Object value) {
|
||||
if (value != null) {
|
||||
missingParameters.remove(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
50
daemon-m40/pom.xml
Normal file
50
daemon-m40/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright 2019 the original author or authors.
|
||||
|
||||
Licensed 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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd</artifactId>
|
||||
<version>1.0.0-m5-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mvnd-daemon-m40</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
<name>Maven Daemon - Daemon 4.0.x specifics</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-core</artifactId>
|
||||
<version>${maven4.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-embedder</artifactId>
|
||||
<version>${maven4.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-daemon</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -70,8 +70,6 @@ import org.apache.maven.lifecycle.LifecycleExecutionException;
|
||||
import org.apache.maven.model.building.ModelProcessor;
|
||||
import org.apache.maven.plugin.ExtensionRealmCache;
|
||||
import org.apache.maven.plugin.PluginArtifactsCache;
|
||||
import org.apache.maven.plugin.PluginRealmCache;
|
||||
import org.apache.maven.plugin.version.PluginVersionResolver;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.artifact.ProjectArtifactsCache;
|
||||
import org.apache.maven.properties.internal.SystemProperties;
|
||||
@@ -93,7 +91,6 @@ import org.codehaus.plexus.util.StringUtils;
|
||||
import org.eclipse.aether.transfer.TransferListener;
|
||||
import org.mvndaemon.mvnd.cache.invalidating.InvalidatingExtensionRealmCache;
|
||||
import org.mvndaemon.mvnd.cache.invalidating.InvalidatingPluginArtifactsCache;
|
||||
import org.mvndaemon.mvnd.cache.invalidating.InvalidatingPluginRealmCache;
|
||||
import org.mvndaemon.mvnd.cache.invalidating.InvalidatingProjectArtifactsCache;
|
||||
import org.mvndaemon.mvnd.cli.EnvHelper;
|
||||
import org.mvndaemon.mvnd.common.Environment;
|
||||
@@ -102,7 +99,6 @@ import org.mvndaemon.mvnd.logging.internal.Slf4jLoggerManager;
|
||||
import org.mvndaemon.mvnd.logging.smart.BuildEventListener;
|
||||
import org.mvndaemon.mvnd.logging.smart.LoggingExecutionListener;
|
||||
import org.mvndaemon.mvnd.logging.smart.LoggingOutputStream;
|
||||
import org.mvndaemon.mvnd.plugin.CachingPluginVersionResolver;
|
||||
import org.mvndaemon.mvnd.transfer.DaemonMavenTransferListener;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
@@ -119,7 +115,7 @@ import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
|
||||
*
|
||||
* @author Jason van Zyl
|
||||
*/
|
||||
public class DaemonMavenCli {
|
||||
public class DaemonMavenCli implements DaemonCli {
|
||||
public static final String LOCAL_REPO_PROPERTY = "maven.repo.local";
|
||||
|
||||
public static final String MULTIMODULE_PROJECT_DIRECTORY = "maven.multiModuleProjectDirectory";
|
||||
@@ -522,9 +518,9 @@ public class DaemonMavenCli {
|
||||
bind(CoreExportsProvider.class).toInstance(new CoreExportsProvider(exports));
|
||||
bind(ExtensionRealmCache.class).to(InvalidatingExtensionRealmCache.class);
|
||||
bind(PluginArtifactsCache.class).to(InvalidatingPluginArtifactsCache.class);
|
||||
bind(PluginRealmCache.class).to(InvalidatingPluginRealmCache.class);
|
||||
// bind(PluginRealmCache.class).to(InvalidatingPluginRealmCache.class);
|
||||
bind(ProjectArtifactsCache.class).to(InvalidatingProjectArtifactsCache.class);
|
||||
bind(PluginVersionResolver.class).to(CachingPluginVersionResolver.class);
|
||||
// bind(PluginVersionResolver.class).to(CachingPluginVersionResolver.class);
|
||||
}
|
||||
});
|
||||
|
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.apache.maven.project;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.maven.building.Source;
|
||||
import org.apache.maven.model.building.ModelCache;
|
||||
|
||||
@@ -27,8 +29,8 @@ public class SnapshotModelCache implements ModelCache {
|
||||
private final ModelCache reactorCache;
|
||||
|
||||
public SnapshotModelCache(ModelCache globalCache, ModelCache reactorCache) {
|
||||
this.globalCache = globalCache;
|
||||
this.reactorCache = reactorCache;
|
||||
this.globalCache = Objects.requireNonNull(globalCache);
|
||||
this.reactorCache = Objects.requireNonNull(reactorCache);
|
||||
}
|
||||
|
||||
public Object get(Source path, String tag) {
|
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.cache.invalidating;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.plugin.DefaultPluginDescriptorCache;
|
||||
import org.apache.maven.plugin.InvalidPluginDescriptorException;
|
||||
import org.apache.maven.plugin.PluginDescriptorParsingException;
|
||||
import org.apache.maven.plugin.PluginResolutionException;
|
||||
import org.apache.maven.plugin.descriptor.PluginDescriptor;
|
||||
import org.codehaus.plexus.classworlds.realm.ClassRealm;
|
||||
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
|
||||
import org.eclipse.aether.RepositorySystemSession;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
import org.eclipse.sisu.Priority;
|
||||
import org.mvndaemon.mvnd.cache.Cache;
|
||||
import org.mvndaemon.mvnd.cache.CacheFactory;
|
||||
import org.mvndaemon.mvnd.cache.CacheRecord;
|
||||
|
||||
@Singleton
|
||||
@Named
|
||||
@Priority(10)
|
||||
public class InvalidatingPluginDescriptorCache extends DefaultPluginDescriptorCache {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PluginDescriptorSupplier {
|
||||
PluginDescriptor load()
|
||||
throws PluginResolutionException, PluginDescriptorParsingException, InvalidPluginDescriptorException;
|
||||
}
|
||||
|
||||
protected static class Record implements CacheRecord {
|
||||
|
||||
private final PluginDescriptor descriptor;
|
||||
|
||||
public Record(PluginDescriptor descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Path> getDependencyPaths() {
|
||||
return Optional.ofNullable(descriptor.getArtifacts()).orElse(Collections.emptyList()).stream()
|
||||
.map(artifact -> artifact.getFile().toPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
ClassRealm realm = descriptor.getClassRealm();
|
||||
try {
|
||||
realm.getWorld().disposeRealm(realm.getId());
|
||||
} catch (NoSuchRealmException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Cache<Key, Record> cache;
|
||||
|
||||
@Inject
|
||||
public InvalidatingPluginDescriptorCache(CacheFactory cacheFactory) {
|
||||
this.cache = cacheFactory.newCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key createKey(Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session) {
|
||||
return super.createKey(plugin, repositories, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginDescriptor get(Key key) {
|
||||
Record r = cache.get(key);
|
||||
return r != null ? clone(r.descriptor) : null;
|
||||
}
|
||||
|
||||
public PluginDescriptor get(Key key, PluginDescriptorSupplier supplier)
|
||||
throws PluginDescriptorParsingException, PluginResolutionException, InvalidPluginDescriptorException {
|
||||
try {
|
||||
Record r = cache.computeIfAbsent(key, k -> {
|
||||
try {
|
||||
return new Record(clone(supplier.load()));
|
||||
} catch (PluginDescriptorParsingException
|
||||
| PluginResolutionException
|
||||
| InvalidPluginDescriptorException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
return clone(r.descriptor);
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getCause() instanceof PluginDescriptorParsingException) {
|
||||
throw (PluginDescriptorParsingException) e.getCause();
|
||||
}
|
||||
if (e.getCause() instanceof PluginResolutionException) {
|
||||
throw (PluginResolutionException) e.getCause();
|
||||
}
|
||||
if (e.getCause() instanceof InvalidPluginDescriptorException) {
|
||||
throw (InvalidPluginDescriptorException) e.getCause();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Key key, PluginDescriptor descriptor) {
|
||||
cache.put(key, new Record(clone(descriptor)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
190
daemon-m40/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingRealmCacheEventSpy.java
vendored
Normal file
190
daemon-m40/src/main/java/org/mvndaemon/mvnd/cache/invalidating/InvalidatingRealmCacheEventSpy.java
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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.mvndaemon.mvnd.cache.invalidating;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.eventspy.AbstractEventSpy;
|
||||
import org.apache.maven.eventspy.EventSpy;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.execution.MavenExecutionResult;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.eclipse.sisu.Typed;
|
||||
import org.mvndaemon.mvnd.common.Environment;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Named
|
||||
@Singleton
|
||||
@Typed(EventSpy.class)
|
||||
public class InvalidatingRealmCacheEventSpy extends AbstractEventSpy {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(InvalidatingRealmCacheEventSpy.class);
|
||||
|
||||
private final InvalidatingPluginRealmCache pluginCache;
|
||||
private final InvalidatingExtensionRealmCache extensionCache;
|
||||
private final InvalidatingProjectArtifactsCache projectArtifactsCache;
|
||||
private Path multiModuleProjectDirectory;
|
||||
private String pattern;
|
||||
private PathMatcher matcher;
|
||||
|
||||
@Inject
|
||||
public InvalidatingRealmCacheEventSpy(
|
||||
InvalidatingPluginRealmCache cache,
|
||||
InvalidatingExtensionRealmCache extensionCache,
|
||||
InvalidatingProjectArtifactsCache projectArtifactsCache) {
|
||||
this.pluginCache = cache;
|
||||
this.extensionCache = extensionCache;
|
||||
this.projectArtifactsCache = projectArtifactsCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Object event) throws Exception {
|
||||
try {
|
||||
if (event instanceof MavenExecutionRequest) {
|
||||
/* Store the multiModuleProjectDirectory path */
|
||||
multiModuleProjectDirectory = ((MavenExecutionRequest) event)
|
||||
.getMultiModuleProjectDirectory()
|
||||
.toPath();
|
||||
pattern = Environment.MVND_PLUGIN_REALM_EVICT_PATTERN
|
||||
.asOptional()
|
||||
.orElse(Environment.MVND_PLUGIN_REALM_EVICT_PATTERN.getDefault());
|
||||
if (!pattern.isEmpty()) {
|
||||
String[] patterns = pattern.split(",");
|
||||
List<PathMatcher> matchers = new ArrayList<>();
|
||||
for (String pattern : patterns) {
|
||||
if (pattern.startsWith("mvn:")) {
|
||||
String[] parts = pattern.substring("mvn:".length()).split(":");
|
||||
String groupId, artifactId, version;
|
||||
if (parts.length >= 3) {
|
||||
version = parts[2];
|
||||
} else {
|
||||
version = "*";
|
||||
}
|
||||
if (parts.length >= 2) {
|
||||
groupId = parts[0];
|
||||
artifactId = parts[1];
|
||||
} else {
|
||||
groupId = "*";
|
||||
artifactId = parts[0];
|
||||
}
|
||||
pattern = "glob:**/" + ("*".equals(groupId) ? "" : groupId.replace('.', '/') + "/")
|
||||
+ artifactId + "/" + ("*".equals(version) ? "**" : version + "/**");
|
||||
}
|
||||
matchers.add(getPathMatcher(pattern));
|
||||
}
|
||||
if (matchers.size() == 1) {
|
||||
matcher = matchers.iterator().next();
|
||||
} else {
|
||||
matcher = path -> matchers.stream().anyMatch(f -> f.matches(path));
|
||||
}
|
||||
}
|
||||
} else if (event instanceof MavenExecutionResult) {
|
||||
/* Evict the entries referring to jars under multiModuleProjectDirectory */
|
||||
pluginCache.cache.removeIf(this::shouldEvict);
|
||||
extensionCache.cache.removeIf(this::shouldEvict);
|
||||
MavenExecutionResult mer = (MavenExecutionResult) event;
|
||||
List<MavenProject> projects = mer.getTopologicallySortedProjects();
|
||||
projectArtifactsCache.cache.removeIf(
|
||||
(k, r) -> shouldEvict(projects, (InvalidatingProjectArtifactsCache.CacheKey) k, r));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Could not notify CliPluginRealmCache", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldEvict(
|
||||
List<MavenProject> projects,
|
||||
InvalidatingProjectArtifactsCache.CacheKey k,
|
||||
InvalidatingProjectArtifactsCache.Record v) {
|
||||
return projects.stream().anyMatch(p -> k.matches(p.getGroupId(), p.getArtifactId(), p.getVersion()));
|
||||
}
|
||||
|
||||
private boolean shouldEvict(InvalidatingPluginRealmCache.Key k, InvalidatingPluginRealmCache.Record v) {
|
||||
try {
|
||||
for (URL url : v.record.getRealm().getURLs()) {
|
||||
if (url.getProtocol().equals("file")) {
|
||||
final Path path = Paths.get(url.toURI());
|
||||
if (path.startsWith(multiModuleProjectDirectory)) {
|
||||
LOG.debug(
|
||||
"Removing PluginRealmCache entry {} because it refers to an artifact in the build tree {}",
|
||||
k,
|
||||
path);
|
||||
return true;
|
||||
} else if (matcher != null && matcher.matches(path)) {
|
||||
LOG.debug(
|
||||
"Removing PluginRealmCache entry {} because its components {} matches the eviction pattern '{}'",
|
||||
k,
|
||||
path,
|
||||
pattern);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (URISyntaxException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldEvict(InvalidatingExtensionRealmCache.Key k, InvalidatingExtensionRealmCache.Record v) {
|
||||
try {
|
||||
for (URL url : v.record.getRealm().getURLs()) {
|
||||
if (url.getProtocol().equals("file")) {
|
||||
final Path path = Paths.get(url.toURI());
|
||||
if (path.startsWith(multiModuleProjectDirectory)) {
|
||||
LOG.debug(
|
||||
"Removing ExtensionRealmCache entry {} because it refers to an artifact in the build tree {}",
|
||||
k,
|
||||
path);
|
||||
return true;
|
||||
} else if (matcher != null && matcher.matches(path)) {
|
||||
LOG.debug(
|
||||
"Removing ExtensionRealmCache entry {} because its components {} matches the eviction pattern '{}'",
|
||||
k,
|
||||
path,
|
||||
pattern);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (URISyntaxException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static PathMatcher getPathMatcher(String pattern) {
|
||||
if (!pattern.startsWith("glob:") && !pattern.startsWith("regex:")) {
|
||||
pattern = "glob:" + pattern;
|
||||
}
|
||||
return FileSystems.getDefault().getPathMatcher(pattern);
|
||||
}
|
||||
}
|
@@ -28,7 +28,7 @@
|
||||
<artifactId>mvnd-daemon</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
<name>Maven Daemon</name>
|
||||
<name>Maven Daemon - Daemon</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
37
daemon/src/main/java/org/apache/maven/cli/DaemonCli.java
Normal file
37
daemon/src/main/java/org/apache/maven/cli/DaemonCli.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.cli;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mvndaemon.mvnd.logging.smart.BuildEventListener;
|
||||
|
||||
/**
|
||||
* Simple interface to bridge maven 3.9.x and 4.0.x CLI
|
||||
*/
|
||||
public interface DaemonCli {
|
||||
int main(
|
||||
List<String> args,
|
||||
String workingDir,
|
||||
String projectDir,
|
||||
Map<String, String> env,
|
||||
BuildEventListener buildEventListener)
|
||||
throws Exception;
|
||||
}
|
@@ -50,7 +50,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.maven.cli.DaemonMavenCli;
|
||||
import org.apache.maven.cli.DaemonCli;
|
||||
import org.mvndaemon.mvnd.builder.SmartBuilder;
|
||||
import org.mvndaemon.mvnd.common.DaemonConnection;
|
||||
import org.mvndaemon.mvnd.common.DaemonException;
|
||||
@@ -87,7 +87,7 @@ public class Server implements AutoCloseable, Runnable {
|
||||
private final String daemonId;
|
||||
private final boolean noDaemon;
|
||||
private final ServerSocketChannel socket;
|
||||
private final DaemonMavenCli cli;
|
||||
private final DaemonCli cli;
|
||||
private volatile DaemonInfo info;
|
||||
private final DaemonRegistry registry;
|
||||
|
||||
@@ -129,7 +129,11 @@ public class Server implements AutoCloseable, Runnable {
|
||||
.orElse(SocketFamily.inet);
|
||||
|
||||
try {
|
||||
cli = new DaemonMavenCli();
|
||||
cli = (DaemonCli) getClass()
|
||||
.getClassLoader()
|
||||
.loadClass("org.apache.maven.cli.DaemonMavenCli")
|
||||
.getDeclaredConstructor()
|
||||
.newInstance();
|
||||
registry = new DaemonRegistry(Environment.MVND_REGISTRY.asPath());
|
||||
socket = socketFamily.openServerSocket();
|
||||
executor = Executors.newScheduledThreadPool(1);
|
||||
|
@@ -25,10 +25,10 @@
|
||||
<version>1.0.0-m5-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mvnd-dist</artifactId>
|
||||
<artifactId>mvnd-dist-m39</artifactId>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<name>Maven Daemon - Distribution</name>
|
||||
<name>Maven Daemon - Distribution for 3.9.x</name>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
@@ -52,6 +52,10 @@
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-daemon</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-daemon-m39</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -67,7 +71,7 @@
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/maven-mvnd-${project.version}-${os.detected.name}-${os.detected.arch}</outputDirectory>
|
||||
<outputDirectory>${project.build.directory}/maven-${project.version}-mvnd-m39-${os.detected.name}-${os.detected.arch}</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
93
dist-m39/src/main/provisio/maven-distro.xml
Normal file
93
dist-m39/src/main/provisio/maven-distro.xml
Normal file
@@ -0,0 +1,93 @@
|
||||
<!--
|
||||
|
||||
Copyright 2019-2021 the original author or authors.
|
||||
|
||||
Licensed 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.
|
||||
|
||||
-->
|
||||
<assembly>
|
||||
|
||||
<artifactSet to="/">
|
||||
<artifact id="org.apache.maven:apache-maven:tar.gz:bin:${maven3.version}">
|
||||
<unpack useRoot="false"
|
||||
excludes="conf/logging/*,lib/maven-slf4j-provider*" />
|
||||
</artifact>
|
||||
</artifactSet>
|
||||
|
||||
<artifactSet to="/lib">
|
||||
<artifact id="ch.qos.logback:logback-classic">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="ch.qos.logback:logback-core">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
</artifactSet>
|
||||
|
||||
<artifactSet to="/lib/ext">
|
||||
<artifact id="org.apache.maven.daemon:mvnd-daemon:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.apache.maven.daemon:mvnd-daemon-m39:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.apache.maven.daemon:mvnd-client:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.apache.maven.daemon:mvnd-common:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.apache.maven.daemon:mvnd-agent:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.apache.maven.daemon:mvnd-helper-agent:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.apache.maven.daemon:mvnd-native:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.codehaus.plexus:plexus-interactivity-api">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.jline:jline-terminal">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.jline:jline-terminal-jansi">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
</artifactSet>
|
||||
|
||||
<fileSet to="/">
|
||||
<directory path="${basedir}/../dist/src/main/distro"/>
|
||||
<directory path="${basedir}/..">
|
||||
<include>NOTICE.txt</include>
|
||||
<include>LICENSE.txt</include>
|
||||
<include>README.adoc</include>
|
||||
</directory>
|
||||
</fileSet>
|
||||
<fileSet to="/bin">
|
||||
<directory path="${basedir}/../client/target">
|
||||
<include>mvnd</include>
|
||||
<include>mvnd.exe</include>
|
||||
</directory>
|
||||
<directory path="${basedir}/../dist/src/main/resources">
|
||||
<include>platform-${os.detected.name}-${os.detected.arch}</include>
|
||||
</directory>
|
||||
</fileSet>
|
||||
|
||||
<archive name="maven-${project.version}-mvnd-mvn39-${os.detected.name}-${os.detected.arch}.zip"
|
||||
executable="**/bin/mvnd"/>
|
||||
|
||||
<archive name="maven-${project.version}-mvnd-mvn39-${os.detected.name}-${os.detected.arch}.tar.gz"
|
||||
executable="**/bin/mvnd"/>
|
||||
|
||||
</assembly>
|
82
dist-m40/pom.xml
Normal file
82
dist-m40/pom.xml
Normal file
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright 2019-2021 the original author or authors.
|
||||
|
||||
Licensed 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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd</artifactId>
|
||||
<version>1.0.0-m5-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mvnd-dist-m40</artifactId>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<name>Maven Daemon - Distribution for 4.0.x</name>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-agent</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-helper-agent</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-daemon</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-daemon-m40</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>ca.vanzyl.provisio.maven.plugins</groupId>
|
||||
<artifactId>provisio-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>maven-distro</id>
|
||||
<goals>
|
||||
<goal>provision</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/maven-${project.version}-mvnd-m40-${os.detected.name}-${os.detected.arch}</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@@ -18,7 +18,7 @@
|
||||
<assembly>
|
||||
|
||||
<artifactSet to="/">
|
||||
<artifact id="org.apache.maven:apache-maven:tar.gz:bin">
|
||||
<artifact id="org.apache.maven:apache-maven:tar.gz:bin:${maven4.version}">
|
||||
<unpack useRoot="false"
|
||||
excludes="conf/logging/*,lib/maven-slf4j-provider*,lib/plexus-utils-3.*" />
|
||||
</artifact>
|
||||
@@ -37,6 +37,9 @@
|
||||
<artifact id="org.apache.maven.daemon:mvnd-daemon:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.apache.maven.daemon:mvnd-daemon-m40:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
<artifact id="org.apache.maven.daemon:mvnd-client:${project.version}">
|
||||
<exclusion id="*:*"/>
|
||||
</artifact>
|
||||
@@ -64,7 +67,7 @@
|
||||
</artifactSet>
|
||||
|
||||
<fileSet to="/">
|
||||
<directory path="${basedir}/src/main/distro"/>
|
||||
<directory path="${basedir}/../dist/src/main/distro"/>
|
||||
<directory path="${basedir}/..">
|
||||
<include>NOTICE.txt</include>
|
||||
<include>LICENSE.txt</include>
|
||||
@@ -76,13 +79,15 @@
|
||||
<include>mvnd</include>
|
||||
<include>mvnd.exe</include>
|
||||
</directory>
|
||||
<file touch="platform-${os.detected.name}-${os.detected.arch}"/>
|
||||
<directory path="${basedir}/../dist/src/main/resources">
|
||||
<include>platform-${os.detected.name}-${os.detected.arch}</include>
|
||||
</directory>
|
||||
</fileSet>
|
||||
|
||||
<archive name="maven-mvnd-${project.version}-${os.detected.name}-${os.detected.arch}.zip"
|
||||
<archive name="maven-${project.version}-mvnd-40-${os.detected.name}-${os.detected.arch}.zip"
|
||||
executable="**/bin/mvnd"/>
|
||||
|
||||
<archive name="maven-mvnd-${project.version}-${os.detected.name}-${os.detected.arch}.tar.gz"
|
||||
<archive name="maven-${project.version}-mvnd-40-${os.detected.name}-${os.detected.arch}.tar.gz"
|
||||
executable="**/bin/mvnd"/>
|
||||
|
||||
</assembly>
|
13
dist/src/main/resources/platform-darwin-aarch64
vendored
Normal file
13
dist/src/main/resources/platform-darwin-aarch64
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2019-2021 the original author or authors.
|
||||
|
||||
Licensed 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.
|
13
dist/src/main/resources/platform-darwin-amd64
vendored
Normal file
13
dist/src/main/resources/platform-darwin-amd64
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2019-2021 the original author or authors.
|
||||
|
||||
Licensed 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.
|
13
dist/src/main/resources/platform-linux-amd64
vendored
Normal file
13
dist/src/main/resources/platform-linux-amd64
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2019-2021 the original author or authors.
|
||||
|
||||
Licensed 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.
|
13
dist/src/main/resources/platform-windows-amd64
vendored
Normal file
13
dist/src/main/resources/platform-windows-amd64
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Copyright 2019-2021 the original author or authors.
|
||||
|
||||
Licensed 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.
|
@@ -32,7 +32,8 @@
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<mvnd.home>${project.basedir}/../dist/target/maven-mvnd-${project.version}-${os.detected.name}-${os.detected.arch}</mvnd.home>
|
||||
<mvnd.m39.home>${project.basedir}/../dist-m39/target/maven-${project.version}-mvnd-m39-${os.detected.name}-${os.detected.arch}</mvnd.m39.home>
|
||||
<mvnd.m40.home>${project.basedir}/../dist-m40/target/maven-${project.version}-mvnd-m40-${os.detected.name}-${os.detected.arch}</mvnd.m40.home>
|
||||
<preinstall.artifacts>org/apache/maven/surefire/surefire-providers/${surefire.version}
|
||||
org/apache/maven/surefire/surefire-junit-platform/${surefire.version}
|
||||
org/junit/platform/junit-platform-launcher/${junit-platform-launcher.version}
|
||||
@@ -56,7 +57,19 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-dist</artifactId>
|
||||
<artifactId>mvnd-dist-m39</artifactId>
|
||||
<type>pom</type>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-dist-m40</artifactId>
|
||||
<type>pom</type>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
@@ -88,18 +101,51 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<rerunFailingTestsCount>4</rerunFailingTestsCount>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-test</id>
|
||||
<phase>none</phase>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>mvn-39</id>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<phase>test</phase>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<mvnd.home>${mvnd.m39.home}</mvnd.home>
|
||||
<project.version>${project.version}</project.version>
|
||||
<mvnd.home>${mvnd.home}</mvnd.home>
|
||||
<mrm.repository.url>${mrm.repository.url}</mrm.repository.url>
|
||||
<os.detected.name>${os.detected.name}</os.detected.name>
|
||||
<os.detected.arch>${os.detected.arch}</os.detected.arch>
|
||||
<mvnd.test.hostLocalMavenRepo>${settings.localRepository}</mvnd.test.hostLocalMavenRepo>
|
||||
<preinstall.artifacts>${preinstall.artifacts}</preinstall.artifacts>
|
||||
</systemPropertyVariables>
|
||||
<rerunFailingTestsCount>2</rerunFailingTestsCount>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>mvn-40</id>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<phase>test</phase>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<mvnd.home>${mvnd.m40.home}</mvnd.home>
|
||||
<project.version>${project.version}</project.version>
|
||||
<mrm.repository.url>${mrm.repository.url}</mrm.repository.url>
|
||||
<os.detected.name>${os.detected.name}</os.detected.name>
|
||||
<os.detected.arch>${os.detected.arch}</os.detected.arch>
|
||||
<mvnd.test.hostLocalMavenRepo>${settings.localRepository}</mvnd.test.hostLocalMavenRepo>
|
||||
<preinstall.artifacts>${preinstall.artifacts}</preinstall.artifacts>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -168,6 +214,7 @@
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>native-39</id>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
@@ -175,7 +222,25 @@
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<project.version>${project.version}</project.version>
|
||||
<mvnd.home>${mvnd.home}</mvnd.home>
|
||||
<mvnd.home>${mvnd.m39.home}</mvnd.home>
|
||||
<mrm.repository.url>${mrm.repository.url}</mrm.repository.url>
|
||||
<os.detected.name>${os.detected.name}</os.detected.name>
|
||||
<os.detected.arch>${os.detected.arch}</os.detected.arch>
|
||||
<mvnd.test.hostLocalMavenRepo>${settings.localRepository}</mvnd.test.hostLocalMavenRepo>
|
||||
<preinstall.artifacts>${preinstall.artifacts}</preinstall.artifacts>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>native-40</id>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<project.version>${project.version}</project.version>
|
||||
<mvnd.home>${mvnd.m40.home}</mvnd.home>
|
||||
<mrm.repository.url>${mrm.repository.url}</mrm.repository.url>
|
||||
<os.detected.name>${os.detected.name}</os.detected.name>
|
||||
<os.detected.arch>${os.detected.arch}</os.detected.arch>
|
||||
|
25
pom.xml
25
pom.xml
@@ -51,7 +51,10 @@
|
||||
<module>common</module>
|
||||
<module>client</module>
|
||||
<module>daemon</module>
|
||||
<module>dist</module>
|
||||
<module>daemon-m39</module>
|
||||
<module>daemon-m40</module>
|
||||
<module>dist-m39</module>
|
||||
<module>dist-m40</module>
|
||||
<module>integration-tests</module>
|
||||
</modules>
|
||||
|
||||
@@ -85,6 +88,8 @@
|
||||
<junit.jupiter.version>5.9.2</junit.jupiter.version>
|
||||
<logback.version>1.2.11</logback.version>
|
||||
<maven.version>4.0.0-alpha-4</maven.version>
|
||||
<maven3.version>3.9.0</maven3.version>
|
||||
<maven4.version>${maven.version}</maven4.version>
|
||||
<!-- Keep in sync with Maven -->
|
||||
<maven.resolver.version>1.9.4</maven.resolver.version>
|
||||
<slf4j.version>1.7.36</slf4j.version>
|
||||
@@ -251,7 +256,13 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-dist</artifactId>
|
||||
<artifactId>mvnd-dist-m39</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-dist-m40</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
@@ -260,6 +271,16 @@
|
||||
<artifactId>mvnd-daemon</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-daemon-m39</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-daemon-m40</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.daemon</groupId>
|
||||
<artifactId>mvnd-helper-agent</artifactId>
|
||||
|
Reference in New Issue
Block a user