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.checksum; 020 021import java.io.IOException; 022import java.io.UncheckedIOException; 023import java.nio.file.Path; 024import java.util.List; 025import java.util.Map; 026 027import org.eclipse.aether.ConfigurationProperties; 028import org.eclipse.aether.RepositorySystemSession; 029import org.eclipse.aether.artifact.Artifact; 030import org.eclipse.aether.repository.ArtifactRepository; 031import org.eclipse.aether.repository.RemoteRepository; 032import org.eclipse.aether.spi.checksums.TrustedChecksumsSource; 033import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory; 034import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory; 035import org.eclipse.aether.util.DirectoryUtils; 036 037import static java.util.Objects.requireNonNull; 038 039/** 040 * Support class for implementing {@link TrustedChecksumsSource} backed by local filesystem. It implements basic support 041 * like basedir calculation, "enabled" flag and "originAware" flag. 042 * <p> 043 * The configuration keys supported: 044 * <ul> 045 * <li><pre>aether.trustedChecksumsSource.${name}</pre> (boolean) must be explicitly set to "true" 046 * to become enabled</li> 047 * <li><pre>aether.trustedChecksumsSource.${name}.basedir</pre> (string, path) directory from where implementation 048 * can use files. May be relative path (then is resolved against local repository basedir) or absolute. If unset, 049 * default value is ".checksums" and is resolved against local repository basedir.</li> 050 * <li><pre>aether.trustedChecksumsSource.${name}.originAware</pre> (boolean) whether to make implementation 051 * "originAware", to factor in origin repository ID as well or not.</li> 052 * </ul> 053 * <p> 054 * This implementation ensures that implementations have "name" property, used in configuration properties above. 055 * 056 * @since 1.9.0 057 */ 058public abstract class FileTrustedChecksumsSourceSupport implements TrustedChecksumsSource { 059 protected static final String CONFIG_PROPS_PREFIX = 060 ConfigurationProperties.PREFIX_AETHER + "trustedChecksumsSource."; 061 062 /** 063 * <b>Experimental:</b> Configuration for "repository key" function. 064 * Note: repository key functions other than "nid" produce repository keys will be <em>way different 065 * that those produced with previous versions or without this option enabled</em>. Checksum source uses this key 066 * function to lay down and look up files to use in sources. 067 * 068 * @since 2.0.14 069 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 070 * @configurationType {@link java.lang.String} 071 * @configurationDefaultValue {@link #DEFAULT_REPOSITORY_KEY_FUNCTION} 072 */ 073 public static final String CONFIG_PROP_REPOSITORY_KEY_FUNCTION = CONFIG_PROPS_PREFIX + "repositoryKeyFunction"; 074 075 public static final String DEFAULT_REPOSITORY_KEY_FUNCTION = "nid"; 076 077 private final RepositoryKeyFunctionFactory repositoryKeyFunctionFactory; 078 079 protected FileTrustedChecksumsSourceSupport(RepositoryKeyFunctionFactory repositoryKeyFunctionFactory) { 080 this.repositoryKeyFunctionFactory = requireNonNull(repositoryKeyFunctionFactory); 081 } 082 083 /** 084 * This implementation will call into underlying code only if enabled, and will enforce non-{@code null} return 085 * value. In worst case, empty map should be returned, meaning "no trusted checksums available". 086 */ 087 @Override 088 public Map<String, String> getTrustedArtifactChecksums( 089 RepositorySystemSession session, 090 Artifact artifact, 091 ArtifactRepository artifactRepository, 092 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories) { 093 requireNonNull(session, "session is null"); 094 requireNonNull(artifact, "artifact is null"); 095 requireNonNull(artifactRepository, "artifactRepository is null"); 096 requireNonNull(checksumAlgorithmFactories, "checksumAlgorithmFactories is null"); 097 if (isEnabled(session)) { 098 return requireNonNull( 099 doGetTrustedArtifactChecksums(session, artifact, artifactRepository, checksumAlgorithmFactories)); 100 } 101 return null; 102 } 103 104 /** 105 * This implementation will call into underlying code only if enabled. Underlying implementation may still choose 106 * to return {@code null}. 107 */ 108 @Override 109 public Writer getTrustedArtifactChecksumsWriter(RepositorySystemSession session) { 110 requireNonNull(session, "session is null"); 111 if (isEnabled(session)) { 112 return doGetTrustedArtifactChecksumsWriter(session); 113 } 114 return null; 115 } 116 117 /** 118 * Implementors MUST NOT return {@code null} at this point, as this source is enabled. 119 */ 120 protected abstract Map<String, String> doGetTrustedArtifactChecksums( 121 RepositorySystemSession session, 122 Artifact artifact, 123 ArtifactRepository artifactRepository, 124 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories); 125 126 /** 127 * Implementors may override this method and return {@link Writer} instance. 128 */ 129 protected Writer doGetTrustedArtifactChecksumsWriter(RepositorySystemSession session) { 130 return null; 131 } 132 133 /** 134 * Returns {@code true} if session configuration marks this instance as enabled. 135 * <p> 136 * Default value is {@code false}. 137 */ 138 protected abstract boolean isEnabled(RepositorySystemSession session); 139 140 /** 141 * Uses utility {@link DirectoryUtils#resolveDirectory(RepositorySystemSession, String, String, boolean)} to 142 * calculate (and maybe create) basedir for this implementation, never returns {@code null}. The returned 143 * {@link Path} may not exist, if invoked with {@code mayCreate} being {@code false}. 144 * <p> 145 * Default value is {@code ${LOCAL_REPOSITORY}/.checksums}. 146 * 147 * @return The {@link Path} of basedir, never {@code null}. 148 */ 149 protected Path getBasedir( 150 RepositorySystemSession session, String defaultValue, String configPropKey, boolean mayCreate) { 151 try { 152 return DirectoryUtils.resolveDirectory(session, defaultValue, configPropKey, mayCreate); 153 } catch (IOException e) { 154 throw new UncheckedIOException(e); 155 } 156 } 157 158 /** 159 * Returns repository key to be used on file system layout. 160 * 161 * @since 2.0.14 162 */ 163 protected String repositoryKey(RepositorySystemSession session, ArtifactRepository artifactRepository) { 164 if (artifactRepository instanceof RemoteRepository) { 165 return repositoryKeyFunctionFactory 166 .repositoryKeyFunction( 167 FileTrustedChecksumsSourceSupport.class, 168 session, 169 DEFAULT_REPOSITORY_KEY_FUNCTION, 170 CONFIG_PROP_REPOSITORY_KEY_FUNCTION) 171 .apply((RemoteRepository) artifactRepository, null); 172 } else { 173 return artifactRepository.getId(); 174 } 175 } 176}