Skip to content

Commit 80ee78e

Browse files
authored
[MENFORCER-500] New rule to enforce that Maven coordinates match given patterns(#309)
Optionally allows to enforce the module directory name being equal to the module's artifactId.
1 parent 0d0d7bf commit 80ee78e

File tree

7 files changed

+365
-0
lines changed

7 files changed

+365
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.enforcer.rules;
20+
21+
import javax.inject.Inject;
22+
import javax.inject.Named;
23+
24+
import java.util.Objects;
25+
import java.util.regex.Pattern;
26+
27+
import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
28+
import org.apache.maven.project.MavenProject;
29+
30+
/**
31+
* This rule checks that the Maven coordinates (i.e. the project's {@code groupId} and {@code artifactId}) each match a given pattern.
32+
* @since 3.5.0
33+
*/
34+
@Named("requireMatchingCoordinates")
35+
public final class RequireMatchingCoordinates extends AbstractStandardEnforcerRule {
36+
37+
private Pattern groupIdPattern;
38+
39+
private Pattern artifactIdPattern;
40+
41+
private boolean moduleNameMustMatchArtifactId;
42+
43+
private final MavenProject project;
44+
45+
@Inject
46+
public RequireMatchingCoordinates(MavenProject project) {
47+
this.project = Objects.requireNonNull(project);
48+
}
49+
50+
@Override
51+
public void execute() throws EnforcerRuleException {
52+
StringBuilder msgBuilder = new StringBuilder();
53+
if (groupIdPattern != null
54+
&& !groupIdPattern.matcher(project.getGroupId()).matches()) {
55+
msgBuilder
56+
.append("Group ID must match pattern \"")
57+
.append(groupIdPattern)
58+
.append("\" but is \"")
59+
.append(project.getGroupId())
60+
.append("\"");
61+
}
62+
if (artifactIdPattern != null
63+
&& !artifactIdPattern.matcher(project.getArtifactId()).matches()) {
64+
if (msgBuilder.length() > 0) {
65+
msgBuilder.append(System.lineSeparator());
66+
}
67+
msgBuilder
68+
.append("Artifact ID must match pattern \"")
69+
.append(artifactIdPattern)
70+
.append("\" but is \"")
71+
.append(project.getArtifactId())
72+
.append("\"");
73+
}
74+
if (moduleNameMustMatchArtifactId
75+
&& !project.isExecutionRoot()
76+
&& !project.getBasedir().getName().equals(project.getArtifactId())) {
77+
if (msgBuilder.length() > 0) {
78+
msgBuilder.append(System.lineSeparator());
79+
}
80+
msgBuilder
81+
.append("Module directory name must be equal to its artifact ID \"")
82+
.append(project.getArtifactId())
83+
.append("\" but is \"")
84+
.append(project.getBasedir().getName())
85+
.append("\"");
86+
}
87+
if (msgBuilder.length() > 0) {
88+
throw new EnforcerRuleException(msgBuilder.toString());
89+
}
90+
}
91+
92+
public void setGroupIdPattern(String groupIdPattern) {
93+
this.groupIdPattern = Pattern.compile(groupIdPattern);
94+
}
95+
96+
public void setArtifactIdPattern(String artifactIdPattern) {
97+
this.artifactIdPattern = Pattern.compile(artifactIdPattern);
98+
}
99+
100+
public void setModuleNameMustMatchArtifactId(boolean moduleNameMustMatchArtifactId) {
101+
this.moduleNameMustMatchArtifactId = moduleNameMustMatchArtifactId;
102+
}
103+
104+
@Override
105+
public String toString() {
106+
return String.format(
107+
"requireMatchingCoordinates[groupIdPattern=%s, artifactIdPattern=%s, moduleNameMustMatchArtifactId=%b]",
108+
groupIdPattern, artifactIdPattern, moduleNameMustMatchArtifactId);
109+
}
110+
}

enforcer-rules/src/site/apt/index.apt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ Built-In Rules
7373

7474
* {{{./requireJavaVersion.html}requireJavaVersion}} - enforces the JDK version.
7575

76+
* {{{./requireMatchingCoordinates.html}requireMatchingCoordinates}} - enforces specific group ID and/or artifact ID patterns.
77+
7678
* {{{./requireMavenVersion.html}requireMavenVersion}} - enforces the Maven version.
7779

7880
* {{{./requireNoRepositories.html}requireNoRepositories}} - enforces to not include repositories.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
~~ Licensed to the Apache Software Foundation (ASF) under one
2+
~~ or more contributor license agreements. See the NOTICE file
3+
~~ distributed with this work for additional information
4+
~~ regarding copyright ownership. The ASF licenses this file
5+
~~ to you under the Apache License, Version 2.0 (the
6+
~~ "License"); you may not use this file except in compliance
7+
~~ with the License. You may obtain a copy of the License at
8+
~~
9+
~~ http://www.apache.org/licenses/LICENSE-2.0
10+
~~
11+
~~ Unless required by applicable law or agreed to in writing,
12+
~~ software distributed under the License is distributed on an
13+
~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
~~ KIND, either express or implied. See the License for the
15+
~~ specific language governing permissions and limitations
16+
~~ under the License.
17+
18+
------
19+
Require Matching Coordinates
20+
------
21+
Konrad Windszus
22+
------
23+
2024-03-22
24+
------
25+
26+
Require Matching Coordinates
27+
28+
This rule checks that the Maven coordinates (i.e. the project's <<<groupId>>> and <<<artifactId>>>) each match a given pattern.
29+
Optionally one can also enforce that in a multi-module build the module directory name is always equal to the module's <<<artifactId>>>.
30+
31+
The following parameters are supported by this rule:
32+
33+
* <<message>> - an optional message to the user if the rule fails. If not set a default message will be used.
34+
35+
* <<groupIdPattern>> - an optional {{{https://docs.oracle.com/javase/tutorial/essential/regex/}regular expression}}, which must match the project's <<<groupId>>>. If not set there is no check on the <<<groupId>>>.
36+
37+
* <<artifactIdPattern>> - an optional {{{https://docs.oracle.com/javase/tutorial/essential/regex/}regular expression}}, which must match the project's <<<artifactId>>>. If not set there is no check on the <<<artifactId>>>.
38+
39+
* <<moduleNameMustMatchArtifactId>> - boolean flag to enforce that the the module's directory name is always equal to the module's <<<artifactId>>>. By default <<<false>>>.
40+
41+
[]
42+
43+
44+
Sample Plugin Configuration:
45+
46+
+---+
47+
<project>
48+
[...]
49+
<build>
50+
<plugins>
51+
<plugin>
52+
<groupId>org.apache.maven.plugins</groupId>
53+
<artifactId>maven-enforcer-plugin</artifactId>
54+
<version>${project.version}</version>
55+
<executions>
56+
<execution>
57+
<id>enforce-group-id</id>
58+
<goals>
59+
<goal>enforce</goal>
60+
</goals>
61+
<configuration>
62+
<rules>
63+
<requireMatchingCoordinates>
64+
<groupIdPattern>com\.example.\namespace\..*</groupIdPattern>
65+
</requireTextFileChecksum>
66+
</rules>
67+
</configuration>
68+
</execution>
69+
</executions>
70+
</plugin>
71+
</plugins>
72+
</build>
73+
[...]
74+
</project>
75+
+---+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<!--
4+
Licensed to the Apache Software Foundation (ASF) under one
5+
or more contributor license agreements. See the NOTICE file
6+
distributed with this work for additional information
7+
regarding copyright ownership. The ASF licenses this file
8+
to you under the Apache License, Version 2.0 (the
9+
"License"); you may not use this file except in compliance
10+
with the License. You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing,
15+
software distributed under the License is distributed on an
16+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
KIND, either express or implied. See the License for the
18+
specific language governing permissions and limitations
19+
under the License.
20+
-->
21+
22+
<project>
23+
<modelVersion>4.0.0</modelVersion>
24+
25+
<parent>
26+
<groupId>org.apache.maven.its.enforcer</groupId>
27+
<artifactId>test-multimodule-project</artifactId>
28+
<version>1.0</version>
29+
</parent>
30+
31+
<artifactId>invalid-test-multimodule-mod2</artifactId>
32+
33+
<description>
34+
</description>
35+
36+
<dependencies>
37+
<dependency>
38+
<groupId>${project.groupId}</groupId>
39+
<artifactId>test-multimodule-mod1</artifactId>
40+
</dependency>
41+
</dependencies>
42+
43+
</project>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<!--
4+
Licensed to the Apache Software Foundation (ASF) under one
5+
or more contributor license agreements. See the NOTICE file
6+
distributed with this work for additional information
7+
regarding copyright ownership. The ASF licenses this file
8+
to you under the Apache License, Version 2.0 (the
9+
"License"); you may not use this file except in compliance
10+
with the License. You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing,
15+
software distributed under the License is distributed on an
16+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
KIND, either express or implied. See the License for the
18+
specific language governing permissions and limitations
19+
under the License.
20+
-->
21+
22+
<project>
23+
<modelVersion>4.0.0</modelVersion>
24+
25+
<groupId>org.apache.maven.its.enforcer</groupId>
26+
<artifactId>test-multimodule-project</artifactId>
27+
<version>1.0</version>
28+
<packaging>pom</packaging>
29+
30+
<description>
31+
</description>
32+
33+
<modules>
34+
<module>test-multimodule-mod1</module>
35+
<module>mod2</module>
36+
</modules>
37+
38+
<dependencyManagement>
39+
<dependencies>
40+
<dependency>
41+
<groupId>${project.groupId}</groupId>
42+
<artifactId>test-multimodule-mod1</artifactId>
43+
<version>${project.version}</version>
44+
</dependency>
45+
</dependencies>
46+
</dependencyManagement>
47+
48+
<build>
49+
<plugins>
50+
<plugin>
51+
<groupId>org.apache.maven.plugins</groupId>
52+
<artifactId>maven-enforcer-plugin</artifactId>
53+
<version>@project.version@</version>
54+
<executions>
55+
<execution>
56+
<id>test</id>
57+
<goals>
58+
<goal>enforce</goal>
59+
</goals>
60+
<configuration>
61+
<rules>
62+
<requireMatchingCoordinates>
63+
<groupIdPattern>org\.apache\.maven\.its\.enforcer\.somepackage</groupIdPattern>
64+
<artifactIdPattern>test-.*</artifactIdPattern>
65+
<moduleNameMustMatchArtifactId>true</moduleNameMustMatchArtifactId>
66+
</requireMatchingCoordinates>
67+
</rules>
68+
<fail>false</fail>
69+
</configuration>
70+
</execution>
71+
</executions>
72+
</plugin>
73+
</plugins>
74+
</build>
75+
</project>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<!--
4+
Licensed to the Apache Software Foundation (ASF) under one
5+
or more contributor license agreements. See the NOTICE file
6+
distributed with this work for additional information
7+
regarding copyright ownership. The ASF licenses this file
8+
to you under the Apache License, Version 2.0 (the
9+
"License"); you may not use this file except in compliance
10+
with the License. You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing,
15+
software distributed under the License is distributed on an
16+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
KIND, either express or implied. See the License for the
18+
specific language governing permissions and limitations
19+
under the License.
20+
-->
21+
22+
<project>
23+
<modelVersion>4.0.0</modelVersion>
24+
25+
<parent>
26+
<groupId>org.apache.maven.its.enforcer</groupId>
27+
<artifactId>test-multimodule-project</artifactId>
28+
<version>1.0</version>
29+
</parent>
30+
31+
<groupId>org.apache.maven.its.enforcer.somepackage</groupId>
32+
<artifactId>test-multimodule-mod1</artifactId>
33+
34+
<description>
35+
</description>
36+
37+
</project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
File buildLog = new File(basedir, 'build.log')
21+
def log = buildLog.text.normalize()
22+
assert log.contains('[WARNING] Rule 0: org.apache.maven.enforcer.rules.RequireMatchingCoordinates failed with message:\nGroup ID must match pattern "org\\.apache\\.maven\\.its\\.enforcer\\.somepackage" but is "org.apache.maven.its.enforcer"\n')
23+
assert log.contains('[WARNING] Rule 0: org.apache.maven.enforcer.rules.RequireMatchingCoordinates failed with message:\nGroup ID must match pattern "org\\.apache\\.maven\\.its\\.enforcer\\.somepackage" but is "org.apache.maven.its.enforcer"\nArtifact ID must match pattern "test-.*" but is "invalid-test-multimodule-mod2"\nModule directory name must be equal to its artifact ID "invalid-test-multimodule-mod2" but is "mod2"\n')

0 commit comments

Comments
 (0)