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.util.repository; 020 021import javax.net.ssl.HostnameVerifier; 022import javax.net.ssl.SSLContext; 023 024import java.util.ArrayList; 025import java.util.List; 026 027import org.eclipse.aether.repository.Authentication; 028import org.eclipse.aether.repository.AuthenticationContext; 029 030/** 031 * A utility class to build authentication info for repositories and proxies. 032 */ 033public final class AuthenticationBuilder { 034 035 private final List<Authentication> authentications; 036 037 /** 038 * Creates a new authentication builder. 039 */ 040 public AuthenticationBuilder() { 041 authentications = new ArrayList<>(); 042 } 043 044 /** 045 * Builds a new authentication object from the current data of this builder. The state of the builder itself remains 046 * unchanged. 047 * 048 * @return the authentication or {@code null} if no authentication data was supplied to the builder 049 */ 050 public Authentication build() { 051 if (authentications.isEmpty()) { 052 return null; 053 } 054 if (authentications.size() == 1) { 055 return authentications.get(0); 056 } 057 return new ChainedAuthentication(authentications); 058 } 059 060 /** 061 * Adds username data to the authentication. 062 * 063 * @param username the username, may be {@code null} 064 * @return this builder for chaining, never {@code null} 065 */ 066 public AuthenticationBuilder addUsername(String username) { 067 return addString(AuthenticationContext.USERNAME, username); 068 } 069 070 /** 071 * Adds password data to the authentication. 072 * 073 * @param password the password, may be {@code null} 074 * @return this builder for chaining, never {@code null} 075 */ 076 public AuthenticationBuilder addPassword(String password) { 077 return addSecret(AuthenticationContext.PASSWORD, password); 078 } 079 080 /** 081 * Adds password data to the authentication. The resulting authentication object uses an encrypted copy of the 082 * supplied character data and callers are advised to clear the input array soon after this method returns. 083 * 084 * @param password the password, may be {@code null} 085 * @return this builder for chaining, never {@code null} 086 */ 087 public AuthenticationBuilder addPassword(char[] password) { 088 return addSecret(AuthenticationContext.PASSWORD, password); 089 } 090 091 /** 092 * Adds NTLM data to the authentication. 093 * 094 * @param workstation the NTLM workstation name, may be {@code null} 095 * @param domain the NTLM domain name, may be {@code null} 096 * @return this builder for chaining, never {@code null} 097 */ 098 public AuthenticationBuilder addNtlm(String workstation, String domain) { 099 addString(AuthenticationContext.NTLM_WORKSTATION, workstation); 100 return addString(AuthenticationContext.NTLM_DOMAIN, domain); 101 } 102 103 /** 104 * Adds private key data to the authentication. 105 * 106 * @param pathname the (absolute) path to the private key file, may be {@code null} 107 * @param passphrase the passphrase protecting the private key, may be {@code null} 108 * @return this builder for chaining, never {@code null} 109 */ 110 public AuthenticationBuilder addPrivateKey(String pathname, String passphrase) { 111 if (pathname != null) { 112 addString(AuthenticationContext.PRIVATE_KEY_PATH, pathname); 113 addSecret(AuthenticationContext.PRIVATE_KEY_PASSPHRASE, passphrase); 114 } 115 return this; 116 } 117 118 /** 119 * Adds private key data to the authentication. The resulting authentication object uses an encrypted copy of the 120 * supplied character data and callers are advised to clear the input array soon after this method returns. 121 * 122 * @param pathname the (absolute) path to the private key file, may be {@code null} 123 * @param passphrase the passphrase protecting the private key, may be {@code null} 124 * @return this builder for chaining, never {@code null} 125 */ 126 public AuthenticationBuilder addPrivateKey(String pathname, char[] passphrase) { 127 if (pathname != null) { 128 addString(AuthenticationContext.PRIVATE_KEY_PATH, pathname); 129 addSecret(AuthenticationContext.PRIVATE_KEY_PASSPHRASE, passphrase); 130 } 131 return this; 132 } 133 134 /** 135 * Adds a hostname verifier for SSL. <strong>Note:</strong> This method assumes that all possible instances of the 136 * verifier's runtime type exhibit the exact same behavior, i.e. the behavior of the verifier depends solely on the 137 * runtime type and not on any configuration. For verifiers that do not fit this assumption, use 138 * {@link #addCustom(Authentication)} with a suitable implementation instead. 139 * 140 * @param verifier the hostname verifier, may be {@code null} 141 * @return this builder for chaining, never {@code null} 142 */ 143 public AuthenticationBuilder addHostnameVerifier(HostnameVerifier verifier) { 144 if (verifier != null) { 145 authentications.add(new ComponentAuthentication(AuthenticationContext.SSL_HOSTNAME_VERIFIER, verifier)); 146 } 147 return this; 148 } 149 150 /** 151 * Adds an SSL context for SSL/TLS connections. <strong>Note:</strong> This method assumes that all possible 152 * instances of the SSL context's runtime type exhibit the exact same behavior, i.e. the behavior of the SSL 153 * context depends solely on the runtime type and not on any configuration. For SSL contexts that do not fit 154 * this assumption, use {@link #addCustom(Authentication)} with a suitable implementation instead. 155 * 156 * @param sslContext the SSL context, may be {@code null} 157 * @return this builder for chaining, never {@code null} 158 * @see AuthenticationContext#SSL_CONTEXT 159 * @since 2.0.19 160 */ 161 public AuthenticationBuilder addSslContext(SSLContext sslContext) { 162 if (sslContext != null) { 163 authentications.add(new ComponentAuthentication(AuthenticationContext.SSL_CONTEXT, sslContext)); 164 } 165 return this; 166 } 167 168 /** 169 * Adds custom string data to the authentication. <em>Note:</em> If the string data is confidential, use 170 * {@link #addSecret(String, char[])} instead. 171 * 172 * @param key the key for the authentication data, must not be {@code null} 173 * @param value the value for the authentication data, may be {@code null} 174 * @return this builder for chaining, never {@code null} 175 */ 176 public AuthenticationBuilder addString(String key, String value) { 177 if (value != null) { 178 authentications.add(new StringAuthentication(key, value)); 179 } 180 return this; 181 } 182 183 /** 184 * Adds sensitive custom string data to the authentication. 185 * 186 * @param key the key for the authentication data, must not be {@code null} 187 * @param value the value for the authentication data, may be {@code null} 188 * @return this builder for chaining, never {@code null} 189 */ 190 public AuthenticationBuilder addSecret(String key, String value) { 191 if (value != null) { 192 authentications.add(new SecretAuthentication(key, value)); 193 } 194 return this; 195 } 196 197 /** 198 * Adds sensitive custom string data to the authentication. The resulting authentication object uses an encrypted 199 * copy of the supplied character data and callers are advised to clear the input array soon after this method 200 * returns. 201 * 202 * @param key the key for the authentication data, must not be {@code null} 203 * @param value the value for the authentication data, may be {@code null} 204 * @return this builder for chaining, never {@code null} 205 */ 206 public AuthenticationBuilder addSecret(String key, char[] value) { 207 if (value != null) { 208 authentications.add(new SecretAuthentication(key, value)); 209 } 210 return this; 211 } 212 213 /** 214 * Adds custom authentication data to the authentication. 215 * 216 * @param authentication the authentication to add, may be {@code null} 217 * @return this builder for chaining, never {@code null} 218 */ 219 public AuthenticationBuilder addCustom(Authentication authentication) { 220 if (authentication != null) { 221 authentications.add(authentication); 222 } 223 return this; 224 } 225}