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