This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch maven-resolver-1.9.x
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/maven-resolver-1.9.x by this
push:
new 302f64de6 [1.9.x] Better metadata locking support (#1669)
302f64de6 is described below
commit 302f64de6219aa31b713681fbc27f529ec98b0d7
Author: Tamas Cservenak <[email protected]>
AuthorDate: Mon Nov 17 20:36:56 2025 +0100
[1.9.x] Better metadata locking support (#1669)
The locking in 1.9.x was too coarse, assumed all is `maven-metadata.xml`.
This is backport from 2.x to support various `metadata.type` values for locking
(local repo is already ported back).
---
.../impl/synccontext/named/GAVNameMapper.java | 11 ++++
.../java/org/eclipse/aether/util/PathUtils.java | 75 ++++++++++++++++++++++
2 files changed, 86 insertions(+)
diff --git
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapper.java
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapper.java
index 556a9f686..b08f7867c 100644
---
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapper.java
+++
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/synccontext/named/GAVNameMapper.java
@@ -24,6 +24,7 @@ import java.util.TreeSet;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.metadata.Metadata;
+import org.eclipse.aether.util.PathUtils;
import static java.util.Objects.requireNonNull;
@@ -97,6 +98,8 @@ public class GAVNameMapper implements NameMapper {
+ artifactSuffix;
}
+ private static final String MAVEN_METADATA = "maven-metadata.xml";
+
private String getMetadataName(Metadata metadata) {
String name = metadataPrefix;
if (!metadata.getGroupId().isEmpty()) {
@@ -107,6 +110,14 @@ public class GAVNameMapper implements NameMapper {
name += fieldSeparator + metadata.getVersion();
}
}
+ if (!MAVEN_METADATA.equals(metadata.getType())) {
+ name += fieldSeparator
+ + (fileSystemFriendly ?
PathUtils.stringToPathSegment(metadata.getType()) : metadata.getType());
+ }
+ } else {
+ if (!MAVEN_METADATA.equals(metadata.getType())) {
+ name += (fileSystemFriendly ?
PathUtils.stringToPathSegment(metadata.getType()) : metadata.getType());
+ }
}
return name + metadataSuffix;
}
diff --git
a/maven-resolver-util/src/main/java/org/eclipse/aether/util/PathUtils.java
b/maven-resolver-util/src/main/java/org/eclipse/aether/util/PathUtils.java
new file mode 100644
index 000000000..e4948264a
--- /dev/null
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/PathUtils.java
@@ -0,0 +1,75 @@
+/*
+ * 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.eclipse.aether.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A reusable utility class for file paths.
+ *
+ * @since 1.9.25 (backported from 2.0.13)
+ */
+public final class PathUtils {
+ private PathUtils() {
+ // hide constructor
+ }
+
+ private static final Map<String, String> ILLEGAL_PATH_SEGMENT_REPLACEMENTS;
+
+ static {
+ HashMap<String, String> illegalPathSegmentReplacements = new
HashMap<>();
+ illegalPathSegmentReplacements.put("\\", "-BACKSLASH-");
+ illegalPathSegmentReplacements.put("/", "-SLASH-");
+ illegalPathSegmentReplacements.put(":", "-COLON-");
+ illegalPathSegmentReplacements.put("\"", "-QUOTE-");
+ illegalPathSegmentReplacements.put("<", "-LT-");
+ illegalPathSegmentReplacements.put(">", "-GT-");
+ illegalPathSegmentReplacements.put("|", "-PIPE-");
+ illegalPathSegmentReplacements.put("?", "-QMARK-");
+ illegalPathSegmentReplacements.put("*", "-ASTERISK-");
+ ILLEGAL_PATH_SEGMENT_REPLACEMENTS =
Collections.unmodifiableMap(illegalPathSegmentReplacements);
+ }
+
+ /**
+ * Method that makes sure that passed in string is valid "path segment"
string. It achieves it by potentially
+ * changing it, replacing illegal characters in it with legal ones.
+ * <p>
+ * Note: this method considers empty string as "valid path segment", it is
caller duty to ensure empty string
+ * is not used as path segment alone.
+ * <p>
+ * This method is simplistic on purpose, and if frequently used, best if
results are cached (per session)
+ */
+ public static String stringToPathSegment(String string) {
+ requireNonNull(string);
+ StringBuilder result = new StringBuilder(string);
+ for (Map.Entry<String, String> entry :
ILLEGAL_PATH_SEGMENT_REPLACEMENTS.entrySet()) {
+ String illegal = entry.getKey();
+ int pos = result.indexOf(illegal);
+ while (pos >= 0) {
+ result.replace(pos, pos + illegal.length(), entry.getValue());
+ pos = result.indexOf(illegal);
+ }
+ }
+ return result.toString();
+ }
+}