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
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.eclipse.aether.repository.Authentication;
27 import org.eclipse.aether.repository.AuthenticationContext;
28
29 /**
30 * A utility class to build authentication info for repositories and proxies.
31 */
32 public final class AuthenticationBuilder {
33
34 private final List<Authentication> authentications;
35
36 /**
37 * Creates a new authentication builder.
38 */
39 public AuthenticationBuilder() {
40 authentications = new ArrayList<>();
41 }
42
43 /**
44 * Builds a new authentication object from the current data of this builder. The state of the builder itself remains
45 * unchanged.
46 *
47 * @return the authentication or {@code null} if no authentication data was supplied to the builder
48 */
49 public Authentication build() {
50 if (authentications.isEmpty()) {
51 return null;
52 }
53 if (authentications.size() == 1) {
54 return authentications.get(0);
55 }
56 return new ChainedAuthentication(authentications);
57 }
58
59 /**
60 * Adds username data to the authentication.
61 *
62 * @param username the username, may be {@code null}
63 * @return this builder for chaining, never {@code null}
64 */
65 public AuthenticationBuilder addUsername(String username) {
66 return addString(AuthenticationContext.USERNAME, username);
67 }
68
69 /**
70 * Adds password data to the authentication.
71 *
72 * @param password the password, may be {@code null}
73 * @return this builder for chaining, never {@code null}
74 */
75 public AuthenticationBuilder addPassword(String password) {
76 return addSecret(AuthenticationContext.PASSWORD, password);
77 }
78
79 /**
80 * Adds password data to the authentication. The resulting authentication object uses an encrypted copy of the
81 * supplied character data and callers are advised to clear the input array soon after this method returns.
82 *
83 * @param password the password, may be {@code null}
84 * @return this builder for chaining, never {@code null}
85 */
86 public AuthenticationBuilder addPassword(char[] password) {
87 return addSecret(AuthenticationContext.PASSWORD, password);
88 }
89
90 /**
91 * Adds NTLM data to the authentication.
92 *
93 * @param workstation the NTLM workstation name, may be {@code null}
94 * @param domain the NTLM domain name, may be {@code null}
95 * @return this builder for chaining, never {@code null}
96 */
97 public AuthenticationBuilder addNtlm(String workstation, String domain) {
98 addString(AuthenticationContext.NTLM_WORKSTATION, workstation);
99 return addString(AuthenticationContext.NTLM_DOMAIN, domain);
100 }
101
102 /**
103 * Adds private key data to the authentication.
104 *
105 * @param pathname the (absolute) path to the private key file, may be {@code null}
106 * @param passphrase the passphrase protecting the private key, may be {@code null}
107 * @return this builder for chaining, never {@code null}
108 */
109 public AuthenticationBuilder addPrivateKey(String pathname, String passphrase) {
110 if (pathname != null) {
111 addString(AuthenticationContext.PRIVATE_KEY_PATH, pathname);
112 addSecret(AuthenticationContext.PRIVATE_KEY_PASSPHRASE, passphrase);
113 }
114 return this;
115 }
116
117 /**
118 * Adds private key data to the authentication. The resulting authentication object uses an encrypted copy of the
119 * supplied character data and callers are advised to clear the input array soon after this method returns.
120 *
121 * @param pathname the (absolute) path to the private key file, may be {@code null}
122 * @param passphrase the passphrase protecting the private key, may be {@code null}
123 * @return this builder for chaining, never {@code null}
124 */
125 public AuthenticationBuilder addPrivateKey(String pathname, char[] passphrase) {
126 if (pathname != null) {
127 addString(AuthenticationContext.PRIVATE_KEY_PATH, pathname);
128 addSecret(AuthenticationContext.PRIVATE_KEY_PASSPHRASE, passphrase);
129 }
130 return this;
131 }
132
133 /**
134 * Adds a hostname verifier for SSL. <strong>Note:</strong> This method assumes that all possible instances of the
135 * verifier's runtime type exhibit the exact same behavior, i.e. the behavior of the verifier depends solely on the
136 * runtime type and not on any configuration. For verifiers that do not fit this assumption, use
137 * {@link #addCustom(Authentication)} with a suitable implementation instead.
138 *
139 * @param verifier the hostname verifier, may be {@code null}
140 * @return this builder for chaining, never {@code null}
141 */
142 public AuthenticationBuilder addHostnameVerifier(HostnameVerifier verifier) {
143 if (verifier != null) {
144 authentications.add(new ComponentAuthentication(AuthenticationContext.SSL_HOSTNAME_VERIFIER, verifier));
145 }
146 return this;
147 }
148
149 /**
150 * Adds custom string data to the authentication. <em>Note:</em> If the string data is confidential, use
151 * {@link #addSecret(String, char[])} instead.
152 *
153 * @param key the key for the authentication data, must not be {@code null}
154 * @param value the value for the authentication data, may be {@code null}
155 * @return this builder for chaining, never {@code null}
156 */
157 public AuthenticationBuilder addString(String key, String value) {
158 if (value != null) {
159 authentications.add(new StringAuthentication(key, value));
160 }
161 return this;
162 }
163
164 /**
165 * Adds sensitive custom string data to the authentication.
166 *
167 * @param key the key for the authentication data, must not be {@code null}
168 * @param value the value for the authentication data, may be {@code null}
169 * @return this builder for chaining, never {@code null}
170 */
171 public AuthenticationBuilder addSecret(String key, String value) {
172 if (value != null) {
173 authentications.add(new SecretAuthentication(key, value));
174 }
175 return this;
176 }
177
178 /**
179 * Adds sensitive custom string data to the authentication. The resulting authentication object uses an encrypted
180 * copy of the supplied character data and callers are advised to clear the input array soon after this method
181 * returns.
182 *
183 * @param key the key for the authentication data, must not be {@code null}
184 * @param value the value for the authentication data, may be {@code null}
185 * @return this builder for chaining, never {@code null}
186 */
187 public AuthenticationBuilder addSecret(String key, char[] value) {
188 if (value != null) {
189 authentications.add(new SecretAuthentication(key, value));
190 }
191 return this;
192 }
193
194 /**
195 * Adds custom authentication data to the authentication.
196 *
197 * @param authentication the authentication to add, may be {@code null}
198 * @return this builder for chaining, never {@code null}
199 */
200 public AuthenticationBuilder addCustom(Authentication authentication) {
201 if (authentication != null) {
202 authentications.add(authentication);
203 }
204 return this;
205 }
206 }