Skip to content

Commit

Permalink
Remove usage of commons-lang3
Browse files Browse the repository at this point in the history
We have had a request to minimize the external dependencies of the
library. This patch removes all our usage of commons-lang3.
  • Loading branch information
elreydetodo committed Feb 19, 2019
1 parent 7254410 commit 8519fe0
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 124 deletions.
4 changes: 0 additions & 4 deletions edgegrid-signer-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@
import com.akamai.edgegrid.signer.exceptions.NoMatchingCredentialException;
import com.akamai.edgegrid.signer.exceptions.RequestSigningException;

import org.apache.commons.lang3.Validate;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;

/**
* <p> This is an abstract base class for implementing EdgeGrid request signing in a
Expand Down Expand Up @@ -92,8 +91,7 @@ public void sign(RequestT request, MutableRequestT requestToUpdate) throws Reque
throw new NoMatchingCredentialException();
}
String newHost = credential.getHost();
URI originalUri = requestUri(request);
Validate.notNull(originalUri, "Request-URI cannot be null");
URI originalUri = Objects.requireNonNull(requestUri(request), "Request-URI cannot be null");
URI newUri = withNewHost(originalUri, newHost);
setHost(requestToUpdate, newHost, newUri);
String authorization = edgeGridSigner.getSignature(req, credential);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,11 @@

package com.akamai.edgegrid.signer;

import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.Builder;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
* 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
Expand All @@ -39,6 +34,12 @@ public class ClientCredential implements Comparable<ClientCredential> {
/** 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<Integer> integerComparator = new NullSafeComparator<>();

/** A {@link String} {@link Comparator}. */
private static Comparator<String> stringComparator = new NullSafeComparator<>();

private String accessToken;
private String clientSecret;
private String clientToken;
Expand Down Expand Up @@ -67,13 +68,24 @@ public static ClientCredentialBuilder builder() {

@Override
public int compareTo(ClientCredential that) {
return new CompareToBuilder()
.append(this.accessToken, that.accessToken)
.append(this.clientSecret, that.clientSecret)
.append(this.clientToken, that.clientToken)
.append(this.host, that.host)
.append(this.maxBodySize, that.maxBodySize)
.build();
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
Expand Down Expand Up @@ -118,17 +130,18 @@ public int hashCode() {

@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)
.append("accessToken", accessToken)
.append("clientSecret", clientSecret)
.append("clientToken", clientToken)
.append("headersToSign", headersToSign)
.append("host", host)
.append("maxBodySize", getMaxBodySize()) // note: intentionally using accessor here.
.build();
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();
}

public static class ClientCredentialBuilder implements Builder<ClientCredential> {
public static class ClientCredentialBuilder {
private String accessToken;
private String clientSecret;
private String clientToken;
Expand All @@ -151,7 +164,9 @@ public ClientCredentialBuilder() {
* @return reference back to this builder instance
*/
public ClientCredentialBuilder clientToken(String clientToken) {
Validate.notBlank(clientToken, "clientToken cannot be blank");
if (Objects.isNull(clientToken) || "".equals(clientToken)) {
throw new IllegalArgumentException("clientToken cannot be empty");
}
this.clientToken = clientToken;
return this;
}
Expand All @@ -164,7 +179,9 @@ public ClientCredentialBuilder clientToken(String clientToken) {
* @return reference back to this builder instance
*/
public ClientCredentialBuilder clientSecret(String clientSecret) {
Validate.notBlank(clientSecret, "clientSecret cannot be blank");
if (Objects.isNull(clientSecret) || "".equals(clientSecret)) {
throw new IllegalArgumentException("clientSecret cannot be empty");
}
this.clientSecret = clientSecret;
return this;
}
Expand All @@ -176,7 +193,9 @@ public ClientCredentialBuilder clientSecret(String clientSecret) {
* @return reference back to this builder instance
*/
public ClientCredentialBuilder accessToken(String accessToken) {
Validate.notBlank(accessToken, "accessToken cannot be blank");
if (Objects.isNull(accessToken) || "".equals(accessToken)) {
throw new IllegalArgumentException("accessToken cannot be empty");
}
this.accessToken = accessToken;
return this;
}
Expand Down Expand Up @@ -218,8 +237,9 @@ public ClientCredentialBuilder headersToSign(Set<String> headersToSign) {
* @return reference back to this builder instance
*/
public ClientCredentialBuilder headerToSign(String headerName) {
Validate.notBlank(headerName, "headerName cannot be blank");

if (Objects.isNull(headerName) || "".equals(headerName)) {
throw new IllegalArgumentException("headerName cannot be empty");
}
this.headersToSign.add(headerName.toLowerCase());
return this;
}
Expand All @@ -231,7 +251,9 @@ public ClientCredentialBuilder headerToSign(String headerName) {
* @return reference back to this builder instance
*/
public ClientCredentialBuilder host(String host) {
Validate.notBlank(host, "host cannot be blank");
if (Objects.isNull(host) || "".equals(host)) {
throw new IllegalArgumentException("host cannot be empty");
}
this.host = host;
return this;
}
Expand All @@ -252,12 +274,11 @@ public ClientCredentialBuilder maxBodySize(int maxBodySize) {
*
* @return reference back to this builder instance
*/
@Override
public ClientCredential build() {
Validate.notBlank(accessToken, "accessToken cannot be blank");
Validate.notBlank(clientSecret, "clientSecret cannot be blank");
Validate.notBlank(clientToken, "clientToken cannot be blank");
Validate.notBlank(host, "host cannot be blank");
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package com.akamai.edgegrid.signer;

import org.apache.commons.lang3.Validate;
import java.util.Objects;

/**
* This is a basic implementation of {@link ClientCredentialProvider} that returns the same
Expand All @@ -29,7 +29,7 @@ public class DefaultClientCredentialProvider implements ClientCredentialProvider
private ClientCredential clientCredential;

public DefaultClientCredentialProvider(ClientCredential clientCredential) {
this.clientCredential = Validate.notNull(clientCredential, "clientCredential cannot be null");
this.clientCredential = Objects.requireNonNull(clientCredential, "clientCredential cannot be null");
}
@Override
public ClientCredential getClientCredential(Request request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,16 @@
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -63,7 +61,7 @@
* The main entry point to produce a signature is
* {@link #getSignature(Request, ClientCredential)}. This method's two arguments are
* immutable representations of exactly what they sound like: an API request and your client
* credentials. They should be built with their {@link Builder} classes ({@link RequestBuilder} and
* credentials. They should be built with their builder classes ({@link RequestBuilder} and
* {@link ClientCredentialBuilder} respectively).
* </p>
*
Expand Down Expand Up @@ -158,7 +156,7 @@ private static String formatTimeStamp(long time) {
}

private static String canonicalizeUri(String uri) {
if (StringUtils.isEmpty(uri)) {
if (uri == null || "".equals(uri)) {
return "/";
}

Expand All @@ -171,8 +169,8 @@ private static String canonicalizeUri(String uri) {

String getSignature(Request request, ClientCredential credential, long timestamp, String nonce)
throws RequestSigningException {
Validate.notNull(credential, "credential cannot be null");
Validate.notNull(request, "request cannot be null");
Objects.requireNonNull(credential, "credential cannot be null");
Objects.requireNonNull(request, "request cannot be null");

String timeStamp = formatTimeStamp(timestamp);
String authData = getAuthData(credential, timeStamp, nonce);
Expand All @@ -186,9 +184,9 @@ private String getSignature(Request request, ClientCredential credential, String
String authData) throws RequestSigningException {
String signingKey = getSigningKey(timeStamp, credential.getClientSecret());
String canonicalizedRequest = getCanonicalizedRequest(request, credential);
log.debug("Canonicalized request: {}", StringEscapeUtils.escapeJava(canonicalizedRequest));
log.trace("Canonicalized request: {}", canonicalizedRequest);
String dataToSign = getDataToSign(canonicalizedRequest, authData);
log.debug("Data to sign: {}", StringEscapeUtils.escapeJava(dataToSign));
log.trace("Data to sign: {}", dataToSign);

return signAndEncode(dataToSign, signingKey);
}
Expand Down Expand Up @@ -275,21 +273,20 @@ private byte[] getHash(byte[] requestBody, int offset, int len) throws RequestSi
}

private String canonicalizeHeaders(Map<String, String> requestHeaders, ClientCredential credential) {
List<String> headers = new ArrayList<>();
// NOTE: Headers are expected to be in order. ClientCredential#headersToSign is a TreeSet.
for (String headerName : credential.getHeadersToSign()) {
String headerValue = requestHeaders.get(headerName);
if (StringUtils.isBlank(headerValue)) {
continue;
}
headers.add(headerName.toLowerCase() + ":" + canonicalizeHeaderValue(headerValue));
}
return StringUtils.join(headers, "\t");
return requestHeaders.entrySet().stream()
.filter(entry -> credential.getHeadersToSign().contains(entry.getKey()))
.filter(entry -> entry.getValue() != null)
.filter(entry -> !"".equals(entry.getValue()))
.map(entry -> {
return entry.getKey().toLowerCase() + ":" + canonicalizeHeaderValue(entry.getValue());
})
.collect(Collectors.joining("\t"));
}

private String canonicalizeHeaderValue(String headerValue) {
headerValue = headerValue.trim();
if (StringUtils.isNotBlank(headerValue)) {
if (headerValue != null && !"".equals(headerValue)) {
Matcher matcher = PATTERN_SPACES.matcher(headerValue);
headerValue = matcher.replaceAll(" ");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2019 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;

/**
* This is a null-safe {@link Comparator} implementation to make the classes {@link Comparable}
* implementation simpler.
*
* @param <T> any type that implements {@link Comparable}
*/
public class NullSafeComparator<T extends Comparable<T>> implements Comparator<T> {

@Override
public int compare(final T o1, final T o2) {
if (o1 == null && o2 == null) {
return 0;
}
if (o1 == null) {
return -1;
}
if (o2 == null) {
return 1;
}
return o1.compareTo(o2);
}

}
Loading

0 comments on commit 8519fe0

Please sign in to comment.