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.checksum;
20  
21  import java.io.IOException;
22  import java.io.UncheckedIOException;
23  import java.nio.file.Path;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.eclipse.aether.ConfigurationProperties;
28  import org.eclipse.aether.RepositorySystemSession;
29  import org.eclipse.aether.artifact.Artifact;
30  import org.eclipse.aether.repository.ArtifactRepository;
31  import org.eclipse.aether.repository.RemoteRepository;
32  import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
33  import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
34  import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory;
35  import org.eclipse.aether.util.DirectoryUtils;
36  
37  import static java.util.Objects.requireNonNull;
38  
39  /**
40   * Support class for implementing {@link TrustedChecksumsSource} backed by local filesystem. It implements basic support
41   * like basedir calculation, "enabled" flag and "originAware" flag.
42   * <p>
43   * The configuration keys supported:
44   * <ul>
45   *     <li><pre>aether.trustedChecksumsSource.${name}</pre> (boolean) must be explicitly set to "true"
46   *     to become enabled</li>
47   *     <li><pre>aether.trustedChecksumsSource.${name}.basedir</pre> (string, path) directory from where implementation
48   *     can use files. May be relative path (then is resolved against local repository basedir) or absolute. If unset,
49   *     default value is ".checksums" and is resolved against local repository basedir.</li>
50   *     <li><pre>aether.trustedChecksumsSource.${name}.originAware</pre> (boolean) whether to make implementation
51   *     "originAware", to factor in origin repository ID as well or not.</li>
52   * </ul>
53   * <p>
54   * This implementation ensures that implementations have "name" property, used in configuration properties above.
55   *
56   * @since 1.9.0
57   */
58  public abstract class FileTrustedChecksumsSourceSupport implements TrustedChecksumsSource {
59      protected static final String CONFIG_PROPS_PREFIX =
60              ConfigurationProperties.PREFIX_AETHER + "trustedChecksumsSource.";
61  
62      /**
63       * <b>Experimental:</b> Configuration for "repository key" function.
64       * Note: repository key functions other than "nid" produce repository keys will be <em>way different
65       * that those produced with previous versions or without this option enabled</em>. Checksum source uses this key
66       * function to lay down and look up files to use in sources.
67       *
68       * @since 2.0.14
69       * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
70       * @configurationType {@link java.lang.String}
71       * @configurationDefaultValue {@link #DEFAULT_REPOSITORY_KEY_FUNCTION}
72       */
73      public static final String CONFIG_PROP_REPOSITORY_KEY_FUNCTION = CONFIG_PROPS_PREFIX + "repositoryKeyFunction";
74  
75      public static final String DEFAULT_REPOSITORY_KEY_FUNCTION = "nid";
76  
77      private final RepositoryKeyFunctionFactory repositoryKeyFunctionFactory;
78  
79      protected FileTrustedChecksumsSourceSupport(RepositoryKeyFunctionFactory repositoryKeyFunctionFactory) {
80          this.repositoryKeyFunctionFactory = requireNonNull(repositoryKeyFunctionFactory);
81      }
82  
83      /**
84       * This implementation will call into underlying code only if enabled, and will enforce non-{@code null} return
85       * value. In worst case, empty map should be returned, meaning "no trusted checksums available".
86       */
87      @Override
88      public Map<String, String> getTrustedArtifactChecksums(
89              RepositorySystemSession session,
90              Artifact artifact,
91              ArtifactRepository artifactRepository,
92              List<ChecksumAlgorithmFactory> checksumAlgorithmFactories) {
93          requireNonNull(session, "session is null");
94          requireNonNull(artifact, "artifact is null");
95          requireNonNull(artifactRepository, "artifactRepository is null");
96          requireNonNull(checksumAlgorithmFactories, "checksumAlgorithmFactories is null");
97          if (isEnabled(session)) {
98              return requireNonNull(
99                      doGetTrustedArtifactChecksums(session, artifact, artifactRepository, checksumAlgorithmFactories));
100         }
101         return null;
102     }
103 
104     /**
105      * This implementation will call into underlying code only if enabled. Underlying implementation may still choose
106      * to return {@code null}.
107      */
108     @Override
109     public Writer getTrustedArtifactChecksumsWriter(RepositorySystemSession session) {
110         requireNonNull(session, "session is null");
111         if (isEnabled(session)) {
112             return doGetTrustedArtifactChecksumsWriter(session);
113         }
114         return null;
115     }
116 
117     /**
118      * Implementors MUST NOT return {@code null} at this point, as this source is enabled.
119      */
120     protected abstract Map<String, String> doGetTrustedArtifactChecksums(
121             RepositorySystemSession session,
122             Artifact artifact,
123             ArtifactRepository artifactRepository,
124             List<ChecksumAlgorithmFactory> checksumAlgorithmFactories);
125 
126     /**
127      * Implementors may override this method and return {@link Writer} instance.
128      */
129     protected Writer doGetTrustedArtifactChecksumsWriter(RepositorySystemSession session) {
130         return null;
131     }
132 
133     /**
134      * Returns {@code true} if session configuration marks this instance as enabled.
135      * <p>
136      * Default value is {@code false}.
137      */
138     protected abstract boolean isEnabled(RepositorySystemSession session);
139 
140     /**
141      * Uses utility {@link DirectoryUtils#resolveDirectory(RepositorySystemSession, String, String, boolean)} to
142      * calculate (and maybe create) basedir for this implementation, never returns {@code null}. The returned
143      * {@link Path} may not exist, if invoked with {@code mayCreate} being {@code false}.
144      * <p>
145      * Default value is {@code ${LOCAL_REPOSITORY}/.checksums}.
146      *
147      * @return The {@link Path} of basedir, never {@code null}.
148      */
149     protected Path getBasedir(
150             RepositorySystemSession session, String defaultValue, String configPropKey, boolean mayCreate) {
151         try {
152             return DirectoryUtils.resolveDirectory(session, defaultValue, configPropKey, mayCreate);
153         } catch (IOException e) {
154             throw new UncheckedIOException(e);
155         }
156     }
157 
158     /**
159      * Returns repository key to be used on file system layout.
160      *
161      * @since 2.0.14
162      */
163     protected String repositoryKey(RepositorySystemSession session, ArtifactRepository artifactRepository) {
164         if (artifactRepository instanceof RemoteRepository) {
165             return repositoryKeyFunctionFactory
166                     .repositoryKeyFunction(
167                             FileTrustedChecksumsSourceSupport.class,
168                             session,
169                             DEFAULT_REPOSITORY_KEY_FUNCTION,
170                             CONFIG_PROP_REPOSITORY_KEY_FUNCTION)
171                     .apply((RemoteRepository) artifactRepository, null);
172         } else {
173             return artifactRepository.getId();
174         }
175     }
176 }