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.filter;
20  
21  import java.io.IOException;
22  import java.io.UncheckedIOException;
23  import java.nio.file.Path;
24  
25  import org.eclipse.aether.ConfigurationProperties;
26  import org.eclipse.aether.RepositorySystemSession;
27  import org.eclipse.aether.internal.impl.checksum.FileTrustedChecksumsSourceSupport;
28  import org.eclipse.aether.repository.RemoteRepository;
29  import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter;
30  import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilterSource;
31  import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory;
32  import org.eclipse.aether.util.DirectoryUtils;
33  
34  import static java.util.Objects.requireNonNull;
35  
36  /**
37   * Support class for {@link RemoteRepositoryFilterSource} implementations.
38   * <p>
39   * Support class for implementing {@link RemoteRepositoryFilterSource}. It implements basic support
40   * like optional "basedir" calculation, handling of "enabled" flag.
41   * <p>
42   * The configuration keys supported:
43   * <ul>
44   *     <li><pre>aether.remoteRepositoryFilter.${id}.enabled</pre> (boolean) must be explicitly set to "true"
45   *     to become enabled</li>
46   *     <li><pre>aether.remoteRepositoryFilter.${id}.basedir</pre> (string, path) directory from where implementation
47   *     can use files. If unset, default value is ".remoteRepositoryFilters/${id}" and is resolved from local
48   *     repository basedir.</li>
49   * </ul>
50   *
51   * @since 1.9.0
52   */
53  public abstract class RemoteRepositoryFilterSourceSupport implements RemoteRepositoryFilterSource {
54      protected static final String CONFIG_PROPS_PREFIX =
55              ConfigurationProperties.PREFIX_AETHER + "remoteRepositoryFilter.";
56  
57      /**
58       * <b>Experimental:</b> Configuration for "repository key" function.
59       * Note: repository key functions other than "nid" produce repository keys will be <em>way different
60       * that those produced with previous versions or without this option enabled</em>. Filter uses this key function to
61       * lay down and look up files to use in filtering.
62       *
63       * @since 2.0.14
64       * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
65       * @configurationType {@link java.lang.String}
66       * @configurationDefaultValue {@link #DEFAULT_REPOSITORY_KEY_FUNCTION}
67       */
68      public static final String CONFIG_PROP_REPOSITORY_KEY_FUNCTION = CONFIG_PROPS_PREFIX + "repositoryKeyFunction";
69  
70      public static final String DEFAULT_REPOSITORY_KEY_FUNCTION = "nid";
71  
72      private final RepositoryKeyFunctionFactory repositoryKeyFunctionFactory;
73  
74      protected RemoteRepositoryFilterSourceSupport(RepositoryKeyFunctionFactory repositoryKeyFunctionFactory) {
75          this.repositoryKeyFunctionFactory = requireNonNull(repositoryKeyFunctionFactory);
76      }
77  
78      /**
79       * Returns {@code true} if session configuration contains this name set to {@code true}.
80       * <p>
81       * Default is {@code true}.
82       */
83      protected abstract boolean isEnabled(RepositorySystemSession session);
84  
85      /**
86       * Uses common {@link DirectoryUtils#resolveDirectory(RepositorySystemSession, String, String, boolean)} to
87       * calculate (and maybe create) basedir for this implementation, never returns {@code null}. The returned
88       * {@link Path} may not exists, if invoked with {@code mayCreate} being {@code false}.
89       * <p>
90       * Default value is {@code ${LOCAL_REPOSITORY}/.checksums}.
91       *
92       * @return The {@link Path} of basedir, never {@code null}.
93       */
94      protected Path getBasedir(
95              RepositorySystemSession session, String defaultValue, String configPropKey, boolean mayCreate) {
96          try {
97              return DirectoryUtils.resolveDirectory(session, defaultValue, configPropKey, mayCreate);
98          } catch (IOException e) {
99              throw new UncheckedIOException(e);
100         }
101     }
102 
103     /**
104      * We use remote repositories as keys, so normalize them.
105      *
106      * @since 2.0.14
107      * @see RemoteRepository#toBareRemoteRepository()
108      */
109     protected RemoteRepository normalizeRemoteRepository(
110             RepositorySystemSession session, RemoteRepository remoteRepository) {
111         return remoteRepository.toBareRemoteRepository();
112     }
113 
114     /**
115      * Returns repository key to be used on file system layout.
116      *
117      * @since 2.0.14
118      */
119     protected String repositoryKey(RepositorySystemSession session, RemoteRepository repository) {
120         return repositoryKeyFunctionFactory
121                 .repositoryKeyFunction(
122                         FileTrustedChecksumsSourceSupport.class,
123                         session,
124                         DEFAULT_REPOSITORY_KEY_FUNCTION,
125                         CONFIG_PROP_REPOSITORY_KEY_FUNCTION)
126                 .apply(repository, null);
127     }
128 
129     /**
130      * Simple {@link RemoteRepositoryFilter.Result} immutable implementation.
131      */
132     private static class SimpleResult implements RemoteRepositoryFilter.Result {
133         private final boolean accepted;
134 
135         private final String reasoning;
136 
137         private SimpleResult(boolean accepted, String reasoning) {
138             this.accepted = accepted;
139             this.reasoning = requireNonNull(reasoning);
140         }
141 
142         @Override
143         public boolean isAccepted() {
144             return accepted;
145         }
146 
147         @Override
148         public String reasoning() {
149             return reasoning;
150         }
151     }
152 
153     /**
154      * Visible for testing.
155      */
156     static RemoteRepositoryFilter.Result result(boolean accepted, String name, String message) {
157         return new SimpleResult(accepted, name + ": " + message);
158     }
159 }