001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.eclipse.aether.internal.impl;
020
021import org.eclipse.aether.RepositorySystemSession;
022import org.eclipse.aether.artifact.Artifact;
023import org.eclipse.aether.metadata.Metadata;
024import org.eclipse.aether.repository.RemoteRepository;
025import org.eclipse.aether.repository.RepositoryKeyFunction;
026import org.eclipse.aether.util.ConfigUtils;
027
028/**
029 * Support class for {@link LocalPathPrefixComposerFactory} implementations: it predefines and makes re-usable
030 * common configuration getters, and defines a support class for {@link LocalPathPrefixComposer} carrying same
031 * configuration and providing default implementation for all methods.
032 * <p>
033 * Implementors should extend this class to implement custom split strategies. If one needs to alter default
034 * configuration, they should override any configuration getter from this class.
035 *
036 * @see DefaultLocalPathPrefixComposerFactory
037 * @since 1.8.1
038 */
039public abstract class LocalPathPrefixComposerFactorySupport implements LocalPathPrefixComposerFactory {
040
041    /**
042     * Whether LRM should split local and remote artifacts.
043     *
044     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
045     * @configurationType {@link java.lang.Boolean}
046     * @configurationDefaultValue {@link #DEFAULT_SPLIT}
047     */
048    public static final String CONFIG_PROP_SPLIT = EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "split";
049
050    public static final boolean DEFAULT_SPLIT = false;
051
052    /**
053     * The prefix to use for locally installed artifacts.
054     *
055     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
056     * @configurationType {@link java.lang.String}
057     * @configurationDefaultValue {@link #DEFAULT_LOCAL_PREFIX}
058     */
059    public static final String CONFIG_PROP_LOCAL_PREFIX =
060            EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "localPrefix";
061
062    public static final String DEFAULT_LOCAL_PREFIX = "installed";
063
064    /**
065     * Whether locally installed artifacts should be split by version (release/snapshot).
066     *
067     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
068     * @configurationType {@link java.lang.Boolean}
069     * @configurationDefaultValue {@link #DEFAULT_SPLIT_LOCAL}
070     */
071    public static final String CONFIG_PROP_SPLIT_LOCAL =
072            EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "splitLocal";
073
074    public static final boolean DEFAULT_SPLIT_LOCAL = false;
075
076    /**
077     * The prefix to use for remotely cached artifacts.
078     *
079     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
080     * @configurationType {@link java.lang.String}
081     * @configurationDefaultValue {@link #DEFAULT_REMOTE_PREFIX}
082     */
083    public static final String CONFIG_PROP_REMOTE_PREFIX =
084            EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "remotePrefix";
085
086    public static final String DEFAULT_REMOTE_PREFIX = "cached";
087
088    /**
089     * Whether cached artifacts should be split by version (release/snapshot).
090     *
091     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
092     * @configurationType {@link java.lang.Boolean}
093     * @configurationDefaultValue {@link #DEFAULT_SPLIT_REMOTE}
094     */
095    public static final String CONFIG_PROP_SPLIT_REMOTE =
096            EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "splitRemote";
097
098    public static final boolean DEFAULT_SPLIT_REMOTE = false;
099
100    /**
101     * Whether cached artifacts should be split by origin repository (repository ID).
102     *
103     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
104     * @configurationType {@link java.lang.Boolean}
105     * @configurationDefaultValue {@link #DEFAULT_SPLIT_REMOTE_REPOSITORY}
106     */
107    public static final String CONFIG_PROP_SPLIT_REMOTE_REPOSITORY =
108            EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "splitRemoteRepository";
109
110    public static final boolean DEFAULT_SPLIT_REMOTE_REPOSITORY = false;
111
112    /**
113     * For cached artifacts, if both splitRemote and splitRemoteRepository are set to true sets the splitting order:
114     * by default it is repositoryId/version (false) or version/repositoryId (true)
115     *
116     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
117     * @configurationType {@link java.lang.Boolean}
118     * @configurationDefaultValue {@link #DEFAULT_SPLIT_REMOTE_REPOSITORY_LAST}
119     */
120    public static final String CONFIG_PROP_SPLIT_REMOTE_REPOSITORY_LAST =
121            EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "splitRemoteRepositoryLast";
122
123    public static final boolean DEFAULT_SPLIT_REMOTE_REPOSITORY_LAST = false;
124
125    /**
126     * The prefix to use for release artifacts.
127     *
128     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
129     * @configurationType {@link java.lang.String}
130     * @configurationDefaultValue {@link #DEFAULT_RELEASES_PREFIX}
131     */
132    public static final String CONFIG_PROP_RELEASES_PREFIX =
133            EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "releasesPrefix";
134
135    public static final String DEFAULT_RELEASES_PREFIX = "releases";
136
137    /**
138     * The prefix to use for snapshot artifacts.
139     *
140     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
141     * @configurationType {@link java.lang.String}
142     * @configurationDefaultValue {@link #DEFAULT_SNAPSHOTS_PREFIX}
143     */
144    public static final String CONFIG_PROP_SNAPSHOTS_PREFIX =
145            EnhancedLocalRepositoryManagerFactory.CONFIG_PROPS_PREFIX + "snapshotsPrefix";
146
147    public static final String DEFAULT_SNAPSHOTS_PREFIX = "snapshots";
148
149    // Legacy support: properties were renamed in Resolver 2.0.x, but we should support 1.9.x properties as well
150    // These below are Resolver 1.9.x properties, are undocumented and shall be removed with Resolver 2.1.x (or later).
151
152    private static final String R1_CONF_PROP_SPLIT = "aether.enhancedLocalRepository.split";
153
154    private static final String R1_CONF_PROP_LOCAL_PREFIX = "aether.enhancedLocalRepository.localPrefix";
155
156    private static final String R1_CONF_PROP_SPLIT_LOCAL = "aether.enhancedLocalRepository.splitLocal";
157
158    private static final String R1_CONF_PROP_REMOTE_PREFIX = "aether.enhancedLocalRepository.remotePrefix";
159
160    private static final String R1_CONF_PROP_SPLIT_REMOTE = "aether.enhancedLocalRepository.splitRemote";
161
162    private static final String R1_CONF_PROP_SPLIT_REMOTE_REPOSITORY =
163            "aether.enhancedLocalRepository.splitRemoteRepository";
164
165    private static final String R1_CONF_PROP_SPLIT_REMOTE_REPOSITORY_LAST =
166            "aether.enhancedLocalRepository.splitRemoteRepositoryLast";
167
168    private static final String R1_CONF_PROP_RELEASES_PREFIX = "aether.enhancedLocalRepository.releasesPrefix";
169
170    private static final String R1_CONF_PROP_SNAPSHOTS_PREFIX = "aether.enhancedLocalRepository.snapshotsPrefix";
171
172    protected boolean isSplit(RepositorySystemSession session) {
173        return ConfigUtils.getBoolean(session, DEFAULT_SPLIT, CONFIG_PROP_SPLIT, R1_CONF_PROP_SPLIT);
174    }
175
176    protected String getLocalPrefix(RepositorySystemSession session) {
177        return ConfigUtils.getString(
178                session, DEFAULT_LOCAL_PREFIX, CONFIG_PROP_LOCAL_PREFIX, R1_CONF_PROP_LOCAL_PREFIX);
179    }
180
181    protected boolean isSplitLocal(RepositorySystemSession session) {
182        return ConfigUtils.getBoolean(session, DEFAULT_SPLIT_LOCAL, CONFIG_PROP_SPLIT_LOCAL, R1_CONF_PROP_SPLIT_LOCAL);
183    }
184
185    protected String getRemotePrefix(RepositorySystemSession session) {
186        return ConfigUtils.getString(
187                session, DEFAULT_REMOTE_PREFIX, CONFIG_PROP_REMOTE_PREFIX, R1_CONF_PROP_REMOTE_PREFIX);
188    }
189
190    protected boolean isSplitRemote(RepositorySystemSession session) {
191        return ConfigUtils.getBoolean(
192                session, DEFAULT_SPLIT_REMOTE, CONFIG_PROP_SPLIT_REMOTE, R1_CONF_PROP_SPLIT_REMOTE);
193    }
194
195    protected boolean isSplitRemoteRepository(RepositorySystemSession session) {
196        return ConfigUtils.getBoolean(
197                session,
198                DEFAULT_SPLIT_REMOTE_REPOSITORY,
199                CONFIG_PROP_SPLIT_REMOTE_REPOSITORY,
200                R1_CONF_PROP_SPLIT_REMOTE_REPOSITORY);
201    }
202
203    protected boolean isSplitRemoteRepositoryLast(RepositorySystemSession session) {
204        return ConfigUtils.getBoolean(
205                session,
206                DEFAULT_SPLIT_REMOTE_REPOSITORY_LAST,
207                CONFIG_PROP_SPLIT_REMOTE_REPOSITORY_LAST,
208                R1_CONF_PROP_SPLIT_REMOTE_REPOSITORY_LAST);
209    }
210
211    protected String getReleasesPrefix(RepositorySystemSession session) {
212        return ConfigUtils.getString(
213                session, DEFAULT_RELEASES_PREFIX, CONFIG_PROP_RELEASES_PREFIX, R1_CONF_PROP_RELEASES_PREFIX);
214    }
215
216    protected String getSnapshotsPrefix(RepositorySystemSession session) {
217        return ConfigUtils.getString(
218                session, DEFAULT_SNAPSHOTS_PREFIX, CONFIG_PROP_SNAPSHOTS_PREFIX, R1_CONF_PROP_SNAPSHOTS_PREFIX);
219    }
220
221    /**
222     * Support class for composers: it defines protected members for all the predefined configuration values and
223     * provides default implementation for methods. Implementors may change it's behaviour by overriding methods.
224     */
225    @SuppressWarnings("checkstyle:parameternumber")
226    protected abstract static class LocalPathPrefixComposerSupport implements LocalPathPrefixComposer {
227        protected final boolean split;
228
229        protected final String localPrefix;
230
231        protected final boolean splitLocal;
232
233        protected final String remotePrefix;
234
235        protected final boolean splitRemote;
236
237        protected final boolean splitRemoteRepository;
238
239        protected final boolean splitRemoteRepositoryLast;
240
241        protected final String releasesPrefix;
242
243        protected final String snapshotsPrefix;
244
245        protected final RepositoryKeyFunction repositoryKeyFunction;
246
247        protected LocalPathPrefixComposerSupport(
248                boolean split,
249                String localPrefix,
250                boolean splitLocal,
251                String remotePrefix,
252                boolean splitRemote,
253                boolean splitRemoteRepository,
254                boolean splitRemoteRepositoryLast,
255                String releasesPrefix,
256                String snapshotsPrefix,
257                RepositoryKeyFunction repositoryKeyFunction) {
258            this.split = split;
259            this.localPrefix = localPrefix;
260            this.splitLocal = splitLocal;
261            this.remotePrefix = remotePrefix;
262            this.splitRemote = splitRemote;
263            this.splitRemoteRepository = splitRemoteRepository;
264            this.splitRemoteRepositoryLast = splitRemoteRepositoryLast;
265            this.releasesPrefix = releasesPrefix;
266            this.snapshotsPrefix = snapshotsPrefix;
267            this.repositoryKeyFunction = repositoryKeyFunction;
268        }
269
270        @Override
271        public String getPathPrefixForLocalArtifact(Artifact artifact) {
272            if (!split) {
273                return null;
274            }
275            String result = localPrefix;
276            if (splitLocal) {
277                result += "/" + (artifact.isSnapshot() ? snapshotsPrefix : releasesPrefix);
278            }
279            return result;
280        }
281
282        @Override
283        public String getPathPrefixForRemoteArtifact(Artifact artifact, RemoteRepository repository) {
284            if (!split) {
285                return null;
286            }
287            String result = remotePrefix;
288            if (!splitRemoteRepositoryLast && splitRemoteRepository) {
289                result += "/" + repositoryKeyFunction.apply(repository, null);
290            }
291            if (splitRemote) {
292                result += "/" + (artifact.isSnapshot() ? snapshotsPrefix : releasesPrefix);
293            }
294            if (splitRemoteRepositoryLast && splitRemoteRepository) {
295                result += "/" + repositoryKeyFunction.apply(repository, null);
296            }
297            return result;
298        }
299
300        @Override
301        public String getPathPrefixForLocalMetadata(Metadata metadata) {
302            if (!split) {
303                return null;
304            }
305            String result = localPrefix;
306            if (splitLocal) {
307                result += "/" + (isSnapshot(metadata) ? snapshotsPrefix : releasesPrefix);
308            }
309            return result;
310        }
311
312        @Override
313        public String getPathPrefixForRemoteMetadata(Metadata metadata, RemoteRepository repository) {
314            if (!split) {
315                return null;
316            }
317            String result = remotePrefix;
318            if (!splitRemoteRepositoryLast && splitRemoteRepository) {
319                result += "/" + repositoryKeyFunction.apply(repository, null);
320            }
321            if (splitRemote) {
322                result += "/" + (isSnapshot(metadata) ? snapshotsPrefix : releasesPrefix);
323            }
324            if (splitRemoteRepositoryLast && splitRemoteRepository) {
325                result += "/" + repositoryKeyFunction.apply(repository, null);
326            }
327            return result;
328        }
329
330        protected boolean isSnapshot(Metadata metadata) {
331            return !metadata.getVersion().isEmpty() && metadata.getVersion().endsWith("-SNAPSHOT");
332        }
333    }
334}