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