com.akamai.edgegrid.signer.ClientCredential Maven / Gradle / Ivy
/*
* Copyright 2018 Akamai Technologies, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.akamai.edgegrid.signer;
import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
/**
* This is a representation of client credential used to sign an EdgeGrid request. This object is
* immutable, so you probably want to build an instance using {@link ClientCredentialBuilder} or one
* of the static methods that reads from an EdgeRc file.
*
* @author [email protected]
* @author [email protected]
*/
public class ClientCredential implements Comparable {
/** This is the default {@code maxBodySize} to apply if not explicitly set in a credential. */
public static final int DEFAULT_MAX_BODY_SIZE_IN_BYTES = 131072;
/** An {@link Integer} {@link Comparator}. */
private static Comparator integerComparator = new NullSafeComparator<>();
/** A {@link String} {@link Comparator}. */
private static Comparator stringComparator = new NullSafeComparator<>();
private String accessToken;
private String clientSecret;
private String clientToken;
private TreeSet headersToSign;
private String host;
private Integer maxBodySize;
ClientCredential(ClientCredentialBuilder b) {
this.accessToken = b.accessToken;
this.clientSecret = b.clientSecret;
this.clientToken = b.clientToken;
this.headersToSign = b.headersToSign;
this.host = b.host;
this.maxBodySize = b.maxBodySize;
}
/**
* Returns a new builder. The returned builder is equivalent to the builder
* generated by {@link ClientCredentialBuilder}.
*
* @return a fresh {@link ClientCredentialBuilder}
*/
public static ClientCredentialBuilder builder() {
return new ClientCredentialBuilder();
}
@Override
public int compareTo(ClientCredential that) {
if (that == null) {
return 1;
}
int comparison = 0;
comparison = stringComparator.compare(this.accessToken, that.accessToken);
if (comparison == 0) {
comparison = stringComparator.compare(this.clientSecret, that.clientSecret);
}
if (comparison == 0) {
comparison = stringComparator.compare(this.clientToken, that.clientToken);
}
if (comparison == 0) {
comparison = stringComparator.compare(this.host, that.host);
}
if (comparison == 0) {
comparison = integerComparator.compare(this.maxBodySize, that.maxBodySize);
}
return comparison;
}
@Override
public boolean equals(Object o) {
if (o == null) return false;
if (getClass() != o.getClass()) return false;
final ClientCredential that = (ClientCredential) o;
return compareTo(that) == 0;
}
/**
* Retrieves access token.
*
* @return accessToken
*
*/
public String getAccessToken() {
return accessToken;
}
/**
* Retrieves client secret.
*
* @return clientSecret
*
*/
public String getClientSecret() {
return clientSecret;
}
/**
* Retrieves client token.
*
* @return clientToken
*
*/
public String getClientToken() {
return clientToken;
}
/**
* Retrieves set of headers for signing.
*
* @return headersToSign
*
*/
public Set getHeadersToSign() {
return headersToSign;
}
/**
* Retrieves host.
*
* @return host
*
*/
public String getHost() {
return host;
}
/**
* Defines maximum body size defined in bytes.
*
* @return maxBodySize
*
*/
public int getMaxBodySize() {
if (maxBodySize == null) {
return DEFAULT_MAX_BODY_SIZE_IN_BYTES;
}
return maxBodySize;
}
@Override
public int hashCode() {
return Objects.hash(accessToken, clientSecret, clientToken, headersToSign, host, maxBodySize);
}
@Override
public String toString() {
return new StringBuilder("[ ")
.append("accessToken: ").append(accessToken).append("; ")
.append("clientSecret: ").append(clientSecret).append("; ")
.append("clientToken: ").append(clientToken).append("; ")
.append("headersToSign: ").append(headersToSign).append("; ")
.append("host: ").append(host).append("; ")
.append("maxBodySize: ").append(getMaxBodySize()) // note: intentionally using accessor here.
.append(" ]")
.toString();
}
/**
* Defines {@link ClientCredentialBuilder} which is used to build instance of {@link ClientCredential}.
*
*/
public static class ClientCredentialBuilder {
private String accessToken;
private String clientSecret;
private String clientToken;
// NOTE: Headers are expected to be in order, so we pre-sort them here by using TreeSet.
private TreeSet headersToSign = new TreeSet<>();
private String host;
private Integer maxBodySize;
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ClientCredential#builder}.
*/
public ClientCredentialBuilder() {
}
/**
* Sets a token representing an OPEN API service client.
*
* @param clientToken a client token
* @return reference back to this builder instance
*/
public ClientCredentialBuilder clientToken(String clientToken) {
if (Objects.isNull(clientToken) || "".equals(clientToken)) {
throw new IllegalArgumentException("clientToken cannot be empty");
}
this.clientToken = clientToken;
return this;
}
/**
* Sets a secret associated with a client token.
*
* @param clientSecret a client secret
* @return reference back to this builder instance
*/
public ClientCredentialBuilder clientSecret(String clientSecret) {
if (Objects.isNull(clientSecret) || "".equals(clientSecret)) {
throw new IllegalArgumentException("clientSecret cannot be empty");
}
this.clientSecret = clientSecret;
return this;
}
/**
* Sets an access token representing authorizations a client has for OPEN API service.
*
* @param accessToken an access token
* @return reference back to this builder instance
*/
public ClientCredentialBuilder accessToken(String accessToken) {
if (Objects.isNull(accessToken) || "".equals(accessToken)) {
throw new IllegalArgumentException("accessToken cannot be empty");
}
this.accessToken = accessToken;
return this;
}
/**
*
* Adds all of {@code headersToSign} into the builder's internal collection. This can be
* called multiple times to continue adding them. The set passed in is not stored directly,
* a copy is made instead.
*
*
* NOTE: All header names are lower-cased for storage. In HTTP, header names are
* case-insensitive anyway, and EdgeGrid does not support multiple headers with the same
* name. Forcing to lowercase here improves our chance of detecting bad requests early.
*
*
* @param headersToSign a {@link Set} of header names
* @return reference back to this builder instance
*/
public ClientCredentialBuilder headersToSign(Set headersToSign) {
for (String headerName : headersToSign) {
headerToSign(headerName);
}
return this;
}
/**
*
* Adds {@code headerName} into the builder's internal collection. This can be called
* multiple times to continue adding them.
*
*
* NOTE: All header names are lower-cased for storage. In HTTP, header names are
* case-insensitive anyway, and EdgeGrid does not support multiple headers with the same
* name. Forcing to lowercase here improves our chance of detecting bad requests early.
*
*
* @param headerName a header name
* @return reference back to this builder instance
*/
public ClientCredentialBuilder headerToSign(String headerName) {
if (Objects.isNull(headerName) || "".equals(headerName)) {
throw new IllegalArgumentException("headerName cannot be empty");
}
this.headersToSign.add(headerName.toLowerCase());
return this;
}
/**
* Sets a hostname to be used when making OPEN API requests with this credential.
*
* @param host a host name
* @return reference back to this builder instance
*/
public ClientCredentialBuilder host(String host) {
if (Objects.isNull(host) || "".equals(host)) {
throw new IllegalArgumentException("host cannot be empty");
}
this.host = host;
return this;
}
/**
* Sets the maximum body size that will be used for producing request signatures.
*
* @param maxBodySize a number of bytes
* @return reference back to this builder instance
*/
public ClientCredentialBuilder maxBodySize(int maxBodySize) {
this.maxBodySize = maxBodySize;
return this;
}
/**
* Returns a newly-created immutable client credential.
*
* @return reference back to this builder instance
*/
public ClientCredential build() {
Objects.requireNonNull(accessToken, "accessToken cannot be empty");
Objects.requireNonNull(clientSecret, "clientSecret cannot be empty");
Objects.requireNonNull(clientToken, "clientToken cannot be empty");
Objects.requireNonNull(host, "host cannot be empty");
return new ClientCredential(this);
}
}
}