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.ConfigurationProperties; 026import org.eclipse.aether.RepositorySystemSession; 027import org.eclipse.aether.repository.RemoteRepository; 028import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter; 029import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilterSource; 030import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory; 031import org.eclipse.aether.util.DirectoryUtils; 032 033import static java.util.Objects.requireNonNull; 034 035/** 036 * Support class for {@link RemoteRepositoryFilterSource} implementations. 037 * <p> 038 * Support class for implementing {@link RemoteRepositoryFilterSource}. It implements basic support 039 * like optional "basedir" calculation, handling of "enabled" flag. 040 * <p> 041 * The configuration keys supported: 042 * <ul> 043 * <li><pre>aether.remoteRepositoryFilter.${id}.enabled</pre> (boolean) must be explicitly set to "true" 044 * to become enabled</li> 045 * <li><pre>aether.remoteRepositoryFilter.${id}.basedir</pre> (string, path) directory from where implementation 046 * can use files. If unset, default value is ".remoteRepositoryFilters/${id}" and is resolved from local 047 * repository basedir.</li> 048 * </ul> 049 * 050 * @since 1.9.0 051 */ 052public abstract class RemoteRepositoryFilterSourceSupport implements RemoteRepositoryFilterSource { 053 protected static final String CONFIG_PROPS_PREFIX = 054 ConfigurationProperties.PREFIX_AETHER + "remoteRepositoryFilter."; 055 056 /** 057 * <b>Experimental:</b> Configuration for "repository key" function. 058 * Note: repository key functions other than "nid" produce repository keys will be <em>way different 059 * that those produced with previous versions or without this option enabled</em>. Filter uses this key function to 060 * lay down and look up files to use in filtering. 061 * 062 * @since 2.0.14 063 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 064 * @configurationType {@link java.lang.String} 065 * @configurationDefaultValue {@link #DEFAULT_REPOSITORY_KEY_FUNCTION} 066 */ 067 public static final String CONFIG_PROP_REPOSITORY_KEY_FUNCTION = CONFIG_PROPS_PREFIX + "repositoryKeyFunction"; 068 069 public static final String DEFAULT_REPOSITORY_KEY_FUNCTION = "nid"; 070 071 private final RepositoryKeyFunctionFactory repositoryKeyFunctionFactory; 072 073 protected RemoteRepositoryFilterSourceSupport(RepositoryKeyFunctionFactory repositoryKeyFunctionFactory) { 074 this.repositoryKeyFunctionFactory = requireNonNull(repositoryKeyFunctionFactory); 075 } 076 077 /** 078 * Returns {@code true} if session configuration contains this name set to {@code true}. 079 * <p> 080 * Default is {@code true}. 081 */ 082 protected abstract boolean isEnabled(RepositorySystemSession session); 083 084 /** 085 * Uses common {@link DirectoryUtils#resolveDirectory(RepositorySystemSession, String, String, boolean)} to 086 * calculate (and maybe create) basedir for this implementation, never returns {@code null}. The returned 087 * {@link Path} may not exists, if invoked with {@code mayCreate} being {@code false}. 088 * <p> 089 * Default value is {@code ${LOCAL_REPOSITORY}/.checksums}. 090 * 091 * @return The {@link Path} of basedir, never {@code null}. 092 */ 093 protected Path getBasedir( 094 RepositorySystemSession session, String defaultValue, String configPropKey, boolean mayCreate) { 095 try { 096 return DirectoryUtils.resolveDirectory(session, defaultValue, configPropKey, mayCreate); 097 } catch (IOException e) { 098 throw new UncheckedIOException(e); 099 } 100 } 101 102 /** 103 * We use remote repositories as keys, so normalize them. 104 * 105 * @since 2.0.14 106 * @see RemoteRepository#toBareRemoteRepository() 107 */ 108 protected RemoteRepository normalizeRemoteRepository( 109 RepositorySystemSession session, RemoteRepository remoteRepository) { 110 return remoteRepository.toBareRemoteRepository(); 111 } 112 113 /** 114 * Returns repository key to be used on file system layout. 115 * 116 * @since 2.0.14 117 */ 118 protected String repositoryKey(RepositorySystemSession session, RemoteRepository repository) { 119 return repositoryKeyFunctionFactory 120 .repositoryKeyFunction( 121 RemoteRepositoryFilterSourceSupport.class, 122 session, 123 DEFAULT_REPOSITORY_KEY_FUNCTION, 124 CONFIG_PROP_REPOSITORY_KEY_FUNCTION) 125 .apply(repository, null); 126 } 127 128 /** 129 * Simple {@link RemoteRepositoryFilter.Result} immutable implementation. 130 */ 131 private static class SimpleResult implements RemoteRepositoryFilter.Result { 132 private final boolean accepted; 133 134 private final String reasoning; 135 136 private SimpleResult(boolean accepted, String reasoning) { 137 this.accepted = accepted; 138 this.reasoning = requireNonNull(reasoning); 139 } 140 141 @Override 142 public boolean isAccepted() { 143 return accepted; 144 } 145 146 @Override 147 public String reasoning() { 148 return reasoning; 149 } 150 } 151 152 /** 153 * Visible for testing. 154 */ 155 static RemoteRepositoryFilter.Result result(boolean accepted, String name, String message) { 156 return new SimpleResult(accepted, name + ": " + message); 157 } 158}