1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.eclipse.aether.util.repository;
20
21 import javax.net.ssl.HostnameVerifier;
22 import javax.net.ssl.SSLContext;
23
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.eclipse.aether.repository.Authentication;
28 import org.eclipse.aether.repository.AuthenticationContext;
29
30 /**
31 * A utility class to build authentication info for repositories and proxies.
32 */
33 public final class AuthenticationBuilder {
34
35 private final List<Authentication> authentications;
36
37 /**
38 * Creates a new authentication builder.
39 */
40 public AuthenticationBuilder() {
41 authentications = new ArrayList<>();
42 }
43
44 /**
45 * Builds a new authentication object from the current data of this builder. The state of the builder itself remains
46 * unchanged.
47 *
48 * @return the authentication or {@code null} if no authentication data was supplied to the builder
49 */
50 public Authentication build() {
51 if (authentications.isEmpty()) {
52 return null;
53 }
54 if (authentications.size() == 1) {
55 return authentications.get(0);
56 }
57 return new ChainedAuthentication(authentications);
58 }
59
60 /**
61 * Adds username data to the authentication.
62 *
63 * @param username the username, may be {@code null}
64 * @return this builder for chaining, never {@code null}
65 */
66 public AuthenticationBuilder addUsername(String username) {
67 return addString(AuthenticationContext.USERNAME, username);
68 }
69
70 /**
71 * Adds password data to the authentication.
72 *
73 * @param password the password, may be {@code null}
74 * @return this builder for chaining, never {@code null}
75 */
76 public AuthenticationBuilder addPassword(String password) {
77 return addSecret(AuthenticationContext.PASSWORD, password);
78 }
79
80 /**
81 * Adds password data to the authentication. The resulting authentication object uses an encrypted copy of the
82 * supplied character data and callers are advised to clear the input array soon after this method returns.
83 *
84 * @param password the password, may be {@code null}
85 * @return this builder for chaining, never {@code null}
86 */
87 public AuthenticationBuilder addPassword(char[] password) {
88 return addSecret(AuthenticationContext.PASSWORD, password);
89 }
90
91 /**
92 * Adds NTLM data to the authentication.
93 *
94 * @param workstation the NTLM workstation name, may be {@code null}
95 * @param domain the NTLM domain name, may be {@code null}
96 * @return this builder for chaining, never {@code null}
97 */
98 public AuthenticationBuilder addNtlm(String workstation, String domain) {
99 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 }