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.filter;
020
021import java.io.IOException;
022import java.io.UncheckedIOException;
023import java.nio.file.Path;
024
025import org.eclipse.aether.RepositorySystemSession;
026import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter;
027import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilterSource;
028import org.eclipse.aether.util.ConfigUtils;
029import org.eclipse.aether.util.DirectoryUtils;
030
031import static java.util.Objects.requireNonNull;
032
033/**
034 * Support class for {@link RemoteRepositoryFilterSource} implementations.
035 * <p>
036 * Support class for implementing {@link RemoteRepositoryFilterSource}. It implements basic support
037 * like optional "basedir" calculation, handling of "enabled" flag.
038 * <p>
039 * The configuration keys supported:
040 * <ul>
041 *     <li><pre>aether.remoteRepositoryFilter.${id}.enabled</pre> (boolean) must be explicitly set to "true"
042 *     to become enabled</li>
043 *     <li><pre>aether.remoteRepositoryFilter.${id}.basedir</pre> (string, path) directory from where implementation
044 *     can use files. If unset, default value is ".remoteRepositoryFilters/${id}" and is resolved from local
045 *     repository basedir.</li>
046 * </ul>
047 *
048 * @since 1.9.0
049 */
050public abstract class RemoteRepositoryFilterSourceSupport implements RemoteRepositoryFilterSource {
051    private static final String CONFIG_PROP_PREFIX = "aether.remoteRepositoryFilter.";
052
053    private static final String CONF_NAME_BASEDIR = "basedir";
054
055    static final String LOCAL_REPO_PREFIX_DIR = ".remoteRepositoryFilters";
056
057    private final String name;
058
059    protected RemoteRepositoryFilterSourceSupport(String name) {
060        this.name = requireNonNull(name);
061    }
062
063    /**
064     * Utility method to create scoped configuration property key of given name.
065     */
066    protected String configPropKey(String name) {
067        return CONFIG_PROP_PREFIX + this.name + "." + name;
068    }
069
070    /**
071     * Returns {@code true} if session configuration contains this name set to {@code true}.
072     * <p>
073     * Default is {@code false}.
074     */
075    protected boolean isEnabled(RepositorySystemSession session) {
076        return ConfigUtils.getBoolean(session, false, CONFIG_PROP_PREFIX + this.name);
077    }
078
079    /**
080     * Uses common {@link DirectoryUtils#resolveDirectory(RepositorySystemSession, String, String, boolean)} to
081     * calculate (and maybe create) basedir for this implementation, never returns {@code null}. The returned
082     * {@link Path} may not exists, if invoked with {@code mayCreate} being {@code false}.
083     * <p>
084     * Default value is {@code ${LOCAL_REPOSITORY}/.checksums}.
085     *
086     * @return The {@link Path} of basedir, never {@code null}.
087     */
088    protected Path getBasedir(RepositorySystemSession session, boolean mayCreate) {
089        try {
090            return DirectoryUtils.resolveDirectory(
091                    session, LOCAL_REPO_PREFIX_DIR, configPropKey(CONF_NAME_BASEDIR), mayCreate);
092        } catch (IOException e) {
093            throw new UncheckedIOException(e);
094        }
095    }
096
097    /**
098     * Simple {@link RemoteRepositoryFilter.Result} immutable implementation.
099     */
100    protected static class SimpleResult implements RemoteRepositoryFilter.Result {
101        private final boolean accepted;
102
103        private final String reasoning;
104
105        public SimpleResult(boolean accepted, String reasoning) {
106            this.accepted = accepted;
107            this.reasoning = requireNonNull(reasoning);
108        }
109
110        @Override
111        public boolean isAccepted() {
112            return accepted;
113        }
114
115        @Override
116        public String reasoning() {
117            return reasoning;
118        }
119    }
120}