View Javadoc
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.eclipse.aether.internal.impl.synccontext.named;
20  
21  import java.util.Collection;
22  import java.util.TreeSet;
23  
24  import org.eclipse.aether.RepositorySystemSession;
25  import org.eclipse.aether.artifact.Artifact;
26  import org.eclipse.aether.metadata.Metadata;
27  
28  import static java.util.Objects.requireNonNull;
29  
30  /**
31   * Artifact GAV {@link NameMapper}, uses artifact and metadata coordinates to name their corresponding locks. Is not
32   * considering local repository, only the artifact coordinates. May use custom prefixes and sufixes and separators,
33   * hence this instance may or may not be filesystem friendly (depends on strings used).
34   */
35  public class GAVNameMapper implements NameMapper {
36      private final boolean fileSystemFriendly;
37  
38      private final String artifactPrefix;
39  
40      private final String artifactSuffix;
41  
42      private final String metadataPrefix;
43  
44      private final String metadataSuffix;
45  
46      private final String fieldSeparator;
47  
48      public GAVNameMapper(
49              boolean fileSystemFriendly,
50              String artifactPrefix,
51              String artifactSuffix,
52              String metadataPrefix,
53              String metadataSuffix,
54              String fieldSeparator) {
55          this.fileSystemFriendly = fileSystemFriendly;
56          this.artifactPrefix = requireNonNull(artifactPrefix);
57          this.artifactSuffix = requireNonNull(artifactSuffix);
58          this.metadataPrefix = requireNonNull(metadataPrefix);
59          this.metadataSuffix = requireNonNull(metadataSuffix);
60          this.fieldSeparator = requireNonNull(fieldSeparator);
61      }
62  
63      @Override
64      public boolean isFileSystemFriendly() {
65          return fileSystemFriendly;
66      }
67  
68      @Override
69      public Collection<String> nameLocks(
70              final RepositorySystemSession session,
71              final Collection<? extends Artifact> artifacts,
72              final Collection<? extends Metadata> metadatas) {
73          // Deadlock prevention: https://stackoverflow.com/a/16780988/696632
74          // We must acquire multiple locks always in the same order!
75          TreeSet<String> keys = new TreeSet<>();
76          if (artifacts != null) {
77              for (Artifact artifact : artifacts) {
78                  keys.add(getArtifactName(artifact));
79              }
80          }
81  
82          if (metadatas != null) {
83              for (Metadata metadata : metadatas) {
84                  keys.add(getMetadataName(metadata));
85              }
86          }
87          return keys;
88      }
89  
90      private String getArtifactName(Artifact artifact) {
91          return artifactPrefix
92                  + artifact.getGroupId()
93                  + fieldSeparator
94                  + artifact.getArtifactId()
95                  + fieldSeparator
96                  + artifact.getBaseVersion()
97                  + artifactSuffix;
98      }
99  
100     private String getMetadataName(Metadata metadata) {
101         String name = metadataPrefix;
102         if (!metadata.getGroupId().isEmpty()) {
103             name += metadata.getGroupId();
104             if (!metadata.getArtifactId().isEmpty()) {
105                 name += fieldSeparator + metadata.getArtifactId();
106                 if (!metadata.getVersion().isEmpty()) {
107                     name += fieldSeparator + metadata.getVersion();
108                 }
109             }
110         }
111         return name + metadataSuffix;
112     }
113 
114     public static NameMapper gav() {
115         return new GAVNameMapper(false, "artifact:", "", "metadata:", "", ":");
116     }
117 
118     public static NameMapper fileGav() {
119         return new GAVNameMapper(true, "artifact~", ".lock", "metadata~", ".lock", "~");
120     }
121 }