blob: 0b63cd18fd2aed4665e29e1ac5307882ee5c9c59 [file] [log] [blame]
/*
* 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.
*/
/**
* A script for sorting child modules and dependencyManagement dependencies in pom.xml files.
* Only elements will be sorted that occur after a comment containing the {@code a..z} marker string.
*/
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.Files
import java.util.regex.Matcher
import java.util.regex.Pattern
@groovy.transform.Field
final Path baseDir = basedir.toPath()
final String[] sortDepManagementPaths = properties['sortDependencyManagementPaths'].split(',')
sortDependencyManagement(sortDepManagementPaths)
final String[] sortModulesPaths = properties['sortModulesPaths'].split(',')
sortModules(sortModulesPaths)
void sortDependencyManagement(String[] pomPaths) {
for (pomPath in pomPaths) {
final Path pomXmlPath = baseDir.resolve(pomPath.trim())
final String xmlSource = new String(Files.readAllBytes(pomXmlPath), 'UTF-8')
final Pattern sortSpanPattern = Pattern.compile('(a\\.\\.z[^>]*>)(.*)</dependencies>(\\r?\\n)([ ]*)</dependencyManagement>', Pattern.DOTALL)
final Pattern groupIdPattern = Pattern.compile('<groupId>([^<]+)</groupId>')
final Matcher matcher = sortSpanPattern.matcher(xmlSource)
if (matcher.find()) {
String dependenciesString = matcher.group(2)
final String eol = matcher.group(3)
final String indent = matcher.group(4)
dependenciesString = dependenciesString.replaceAll('<!--\\$[^>]*\\$-->', '')
final String[] dependenciesArray = dependenciesString.split('</dependency>')
/* Sort by adding to a TreeMap */
final Map<String, Map<String, String>> sortedDeps = new TreeMap<>();
for (dep in dependenciesArray) {
dep = dep.trim()
if (!dep.isEmpty()) {
String key = dep
.replaceAll('>[ \n\r\t]+', '>')
.replaceAll('[ \n\r\t]+<', '<')
final Matcher gMatcher = groupIdPattern.matcher(key)
gMatcher.find()
final String groupId = gMatcher.group(1)
key = key.replaceAll('<[^>]+>', ' ').replaceAll(' +', ' ')
Map<String, String> groupMap = sortedDeps.get(groupId)
if (groupMap == null) {
groupMap = new TreeMap<String, String>()
sortedDeps.put(groupId, groupMap)
}
groupMap.put(key, dep);
}
}
final StringBuilder result = new StringBuilder(xmlSource)
result.setLength(matcher.end(1))
final Appender appender = new Appender(eol, indent, sortedDeps, result)
appender.appendGroup('org.apache.camel', true)
appender.appendGroup('org.apache.camel.quarkus', true)
appender.appendOther()
appender.result().append(eol).append(indent).append(indent).append(xmlSource.substring(matcher.end(2)))
Files.write(pomXmlPath, result.toString().getBytes('UTF-8'));
} else {
throw new RuntimeException('Could not match ' + sortSpanPattern + ' in ' + pomXmlPath)
}
}
}
class Appender {
private final Set<String> processedGroupIds = new HashSet<>()
private final String eol
private final String indent
private final Map<String, Map<String, String>> sortedDeps
private final StringBuilder result
public Appender(String eol, String indent, Map<String, Map<String, String>> sortedDeps, StringBuilder result) {
this.eol = eol
this.indent = indent
this.sortedDeps = sortedDeps
this.result = result
}
public void comment(String comment) {
result.append(eol).append(eol)
.append(indent).append(indent).append(indent).append('<!--$ '+ comment +' $-->')
}
public void appendGroup(String groupId, boolean isComment) {
final Map<String, String> deps = sortedDeps.get(groupId)
if (deps == null || processedGroupIds.contains(groupId)) {
return
}
processedGroupIds.add(groupId)
if (isComment) {
comment(groupId)
}
for (dep in deps.values()) {
result.append(eol)
.append(indent).append(indent).append(indent).append(dep)
.append(eol).append(indent).append(indent).append(indent).append('</dependency>')
}
}
public void appendOther() {
if (processedGroupIds.size() < sortedDeps.size()) {
comment('Other third party dependencies')
for (group in sortedDeps.entrySet()) {
appendGroup(group.getKey(), false)
}
}
}
public StringBuilder result() {
return result
}
}
void sortModules(String[] sortModulesPaths) {
for (pomPath in sortModulesPaths) {
final Path pomXmlPath = basedir.toPath().resolve(pomPath.trim())
final String xmlSource = new String(Files.readAllBytes(pomXmlPath), 'UTF-8')
final Pattern sortSpanPattern = Pattern.compile('(a\\.\\.z[^>]*>)(.*)(\\r?\\n)([ ]*)</modules>', Pattern.DOTALL)
final Matcher matcher = sortSpanPattern.matcher(xmlSource)
if (matcher.find()) {
final String modulesString = matcher.group(2)
final String eol = matcher.group(3)
final String indent = matcher.group(4)
final String[] modulesArray = modulesString.split('[\r\n]+ *')
final Map<String, String> sortedModules = new TreeMap<String, String>()
for (module in modulesArray) {
module = module.trim()
if (!module.isEmpty()) {
String key = module
.replaceAll('>[ \n\r\t]+', '>')
.replaceAll('[ \n\r\t]+<', '<')
key = key.replaceAll('<[^>]+>', '')
if (!key.isEmpty()) {
sortedModules.put(key, module);
}
}
}
final StringBuilder result = new StringBuilder(xmlSource)
result.setLength(matcher.end(1))
for (module in sortedModules.values()) {
result.append(eol).append(indent).append(indent).append(module)
}
result.append(eol).append(indent).append(xmlSource.substring(matcher.end(4)))
Files.write(pomXmlPath, result.toString().getBytes('UTF-8'));
} else {
throw new RuntimeException('Could not match ' + sortSpanPattern + ' in ' + pomXmlPath)
}
}
}