Skip to content

Commit

Permalink
Support Base64url (Azure#1238)
Browse files Browse the repository at this point in the history
  • Loading branch information
jianghaolu authored and tbombach committed Jul 11, 2016
1 parent 93de90c commit b348fdd
Show file tree
Hide file tree
Showing 18 changed files with 369 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*
*/

package com.microsoft.rest;

import com.google.common.io.BaseEncoding;

import java.util.Arrays;

/**
* Simple wrapper over Base64Url encoded byte array used during serialization/deserialization.
*/
public final class Base64Url {
/**
* The Base64Url encoded bytes.
*/
private final byte[] bytes;

/**
* Creates a new Base64Url object with the specified encoded string.
*
* @param string The encoded string.
*/
private Base64Url(String string) {
if (string == null) {
this.bytes = null;
} else {
this.bytes = string.getBytes();
}
}

/**
* Encode a byte array into Base64Url encoded bytes.
*
* @param bytes The byte array to encode.
* @return a Base64Url instance
*/
public static Base64Url encode(byte[] bytes) {
if (bytes == null) {
return new Base64Url(null);
} else {
return new Base64Url(BaseEncoding.base64Url().omitPadding().encode(bytes));
}
}

/**
* Returns the underlying encoded byte array.
*
* @return The underlying encoded byte array.
*/
public byte[] getEncodedBytes() {
return bytes;
}

/**
* Decode the bytes and return.
*
* @return The decoded byte array.
*/
public byte[] getDecodedBytes() {
if (this.bytes == null) {
return null;
}
return BaseEncoding.base64Url().decode(new String(bytes));
}

@Override
public String toString() {
return new String(bytes);
}

@Override
public int hashCode() {
return Arrays.hashCode(bytes);
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}

if (!(obj instanceof Base64Url)) {
return false;
}

Base64Url rhs = (Base64Url) obj;
return Arrays.equals(this.bytes, rhs.getEncodedBytes());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*
*/

package com.microsoft.rest.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.microsoft.rest.Base64Url;

import java.io.IOException;

/**
* Custom serializer for serializing {@link Byte[]} objects into Base64 strings.
*/
public class Base64UrlSerializer extends JsonSerializer<Base64Url> {
/**
* Gets a module wrapping this serializer as an adapter for the Jackson
* ObjectMapper.
*
* @return a simple module to be plugged onto Jackson ObjectMapper.
*/
public static SimpleModule getModule() {
SimpleModule module = new SimpleModule();
module.addSerializer(Base64Url.class, new Base64UrlSerializer());
return module;
}

@Override
public void serialize(Base64Url value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(value.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ protected void initializeObjectMapper(ObjectMapper mapper) {
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(new JodaModule())
.registerModule(ByteArraySerializer.getModule())
.registerModule(Base64UrlSerializer.getModule())
.registerModule(DateTimeSerializer.getModule())
.registerModule(DateTimeRfc1123Serializer.getModule())
.registerModule(HeadersSerializer.getModule());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -900,9 +900,9 @@ public interface Arrays {
*
* @throws ErrorException exception thrown from REST call
* @throws IOException exception thrown from serialization/deserialization
* @return the List&lt;String&gt; object wrapped in {@link ServiceResponse} if successful.
* @return the List&lt;byte[]&gt; object wrapped in {@link ServiceResponse} if successful.
*/
ServiceResponse<List<String>> getBase64Url() throws ErrorException, IOException;
ServiceResponse<List<byte[]>> getBase64Url() throws ErrorException, IOException;

/**
* Get array value ['a string that gets encoded with base64url', 'test string' 'Lorem ipsum'] with the items base64url encoded.
Expand All @@ -911,7 +911,7 @@ public interface Arrays {
* @throws IllegalArgumentException thrown if callback is null
* @return the {@link ServiceCall} object
*/
ServiceCall getBase64UrlAsync(final ServiceCallback<List<String>> serviceCallback) throws IllegalArgumentException;
ServiceCall getBase64UrlAsync(final ServiceCallback<List<byte[]>> serviceCallback) throws IllegalArgumentException;

/**
* Get array of complex type null value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import retrofit2.Retrofit;
import fixtures.bodyarray.Arrays;
import com.google.common.reflect.TypeToken;
import com.microsoft.rest.Base64Url;
import com.microsoft.rest.DateTimeRfc1123;
import com.microsoft.rest.ServiceCall;
import com.microsoft.rest.ServiceCallback;
Expand Down Expand Up @@ -2587,11 +2588,21 @@ private ServiceResponse<List<byte[]>> getByteInvalidNullDelegate(Response<Respon
*
* @throws ErrorException exception thrown from REST call
* @throws IOException exception thrown from serialization/deserialization
* @return the List&lt;String&gt; object wrapped in {@link ServiceResponse} if successful.
* @return the List&lt;byte[]&gt; object wrapped in {@link ServiceResponse} if successful.
*/
public ServiceResponse<List<String>> getBase64Url() throws ErrorException, IOException {
public ServiceResponse<List<byte[]>> getBase64Url() throws ErrorException, IOException {
Call<ResponseBody> call = service.getBase64Url();
return getBase64UrlDelegate(call.execute());
ServiceResponse<List<Base64Url>> response = getBase64UrlDelegate(call.execute());
List<byte[]> body = null;
if (response.getBody() != null) {
body = new ArrayList<byte[]>();
for (Base64Url item : response.getBody()) {
byte[] value;
value = item.getDecodedBytes();
body.add(value);
}
}
return new ServiceResponse<List<byte[]>>(body, response.getResponse());
}

/**
Expand All @@ -2601,17 +2612,27 @@ public ServiceResponse<List<String>> getBase64Url() throws ErrorException, IOExc
* @throws IllegalArgumentException thrown if callback is null
* @return the {@link Call} object
*/
public ServiceCall getBase64UrlAsync(final ServiceCallback<List<String>> serviceCallback) throws IllegalArgumentException {
public ServiceCall getBase64UrlAsync(final ServiceCallback<List<byte[]>> serviceCallback) throws IllegalArgumentException {
if (serviceCallback == null) {
throw new IllegalArgumentException("ServiceCallback is required for async calls.");
}
Call<ResponseBody> call = service.getBase64Url();
final ServiceCall serviceCall = new ServiceCall(call);
call.enqueue(new ServiceResponseCallback<List<String>>(serviceCallback) {
call.enqueue(new ServiceResponseCallback<List<byte[]>>(serviceCallback) {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
serviceCallback.success(getBase64UrlDelegate(response));
ServiceResponse<List<Base64Url>> result = getBase64UrlDelegate(response);
List<byte[]> body = null;
if (result.getBody() != null) {
body = new ArrayList<byte[]>();
for (Base64Url item : result.getBody()) {
byte[] value;
value = item.getDecodedBytes();
body.add(value);
}
}
serviceCallback.success(new ServiceResponse<List<byte[]>>(body, result.getResponse()));
} catch (ErrorException | IOException exception) {
serviceCallback.failure(exception);
}
Expand All @@ -2620,9 +2641,9 @@ public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response)
return serviceCall;
}

private ServiceResponse<List<String>> getBase64UrlDelegate(Response<ResponseBody> response) throws ErrorException, IOException {
return new ServiceResponseBuilder<List<String>, ErrorException>(this.client.mapperAdapter())
.register(200, new TypeToken<List<String>>() { }.getType())
private ServiceResponse<List<Base64Url>> getBase64UrlDelegate(Response<ResponseBody> response) throws ErrorException, IOException {
return new ServiceResponseBuilder<List<Base64Url>, ErrorException>(this.client.mapperAdapter())
.register(200, new TypeToken<List<Base64Url>>() { }.getType())
.registerError(ErrorException.class)
.build(response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -896,9 +896,9 @@ public interface Dictionarys {
*
* @throws ErrorException exception thrown from REST call
* @throws IOException exception thrown from serialization/deserialization
* @return the Map&lt;String, String&gt; object wrapped in {@link ServiceResponse} if successful.
* @return the Map&lt;String, byte[]&gt; object wrapped in {@link ServiceResponse} if successful.
*/
ServiceResponse<Map<String, String>> getBase64Url() throws ErrorException, IOException;
ServiceResponse<Map<String, byte[]>> getBase64Url() throws ErrorException, IOException;

/**
* Get base64url dictionary value {"0": "a string that gets encoded with base64url", "1": "test string", "2": "Lorem ipsum"}.
Expand All @@ -907,7 +907,7 @@ public interface Dictionarys {
* @throws IllegalArgumentException thrown if callback is null
* @return the {@link ServiceCall} object
*/
ServiceCall getBase64UrlAsync(final ServiceCallback<Map<String, String>> serviceCallback) throws IllegalArgumentException;
ServiceCall getBase64UrlAsync(final ServiceCallback<Map<String, byte[]>> serviceCallback) throws IllegalArgumentException;

/**
* Get dictionary of complex type null value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import retrofit2.Retrofit;
import fixtures.bodydictionary.Dictionarys;
import com.google.common.reflect.TypeToken;
import com.microsoft.rest.Base64Url;
import com.microsoft.rest.DateTimeRfc1123;
import com.microsoft.rest.ServiceCall;
import com.microsoft.rest.ServiceCallback;
Expand Down Expand Up @@ -2574,11 +2575,21 @@ private ServiceResponse<Map<String, byte[]>> getByteInvalidNullDelegate(Response
*
* @throws ErrorException exception thrown from REST call
* @throws IOException exception thrown from serialization/deserialization
* @return the Map&lt;String, String&gt; object wrapped in {@link ServiceResponse} if successful.
* @return the Map&lt;String, byte[]&gt; object wrapped in {@link ServiceResponse} if successful.
*/
public ServiceResponse<Map<String, String>> getBase64Url() throws ErrorException, IOException {
public ServiceResponse<Map<String, byte[]>> getBase64Url() throws ErrorException, IOException {
Call<ResponseBody> call = service.getBase64Url();
return getBase64UrlDelegate(call.execute());
ServiceResponse<Map<String, Base64Url>> response = getBase64UrlDelegate(call.execute());
Map<String, byte[]> body = null;
if (response.getBody() != null) {
body = new HashMap<String, byte[]>();
for (Map.Entry<String, Base64Url> entry : response.getBody().entrySet()) {
byte[] value;
value = entry.getValue().getDecodedBytes();
body.put(entry.getKey(), value);
}
}
return new ServiceResponse<Map<String, byte[]>>(body, response.getResponse());
}

/**
Expand All @@ -2588,17 +2599,27 @@ public ServiceResponse<Map<String, String>> getBase64Url() throws ErrorException
* @throws IllegalArgumentException thrown if callback is null
* @return the {@link Call} object
*/
public ServiceCall getBase64UrlAsync(final ServiceCallback<Map<String, String>> serviceCallback) throws IllegalArgumentException {
public ServiceCall getBase64UrlAsync(final ServiceCallback<Map<String, byte[]>> serviceCallback) throws IllegalArgumentException {
if (serviceCallback == null) {
throw new IllegalArgumentException("ServiceCallback is required for async calls.");
}
Call<ResponseBody> call = service.getBase64Url();
final ServiceCall serviceCall = new ServiceCall(call);
call.enqueue(new ServiceResponseCallback<Map<String, String>>(serviceCallback) {
call.enqueue(new ServiceResponseCallback<Map<String, byte[]>>(serviceCallback) {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
serviceCallback.success(getBase64UrlDelegate(response));
ServiceResponse<Map<String, Base64Url>> result = getBase64UrlDelegate(response);
Map<String, byte[]> body = null;
if (result.getBody() != null) {
body = new HashMap<String, byte[]>();
for (Map.Entry<String, Base64Url> entry : result.getBody().entrySet()) {
byte[] value;
value = entry.getValue().getDecodedBytes();
body.put(entry.getKey(), value);
}
}
serviceCallback.success(new ServiceResponse<Map<String, byte[]>>(body, result.getResponse()));
} catch (ErrorException | IOException exception) {
serviceCallback.failure(exception);
}
Expand All @@ -2607,9 +2628,9 @@ public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response)
return serviceCall;
}

private ServiceResponse<Map<String, String>> getBase64UrlDelegate(Response<ResponseBody> response) throws ErrorException, IOException {
return new ServiceResponseBuilder<Map<String, String>, ErrorException>(this.client.mapperAdapter())
.register(200, new TypeToken<Map<String, String>>() { }.getType())
private ServiceResponse<Map<String, Base64Url>> getBase64UrlDelegate(Response<ResponseBody> response) throws ErrorException, IOException {
return new ServiceResponseBuilder<Map<String, Base64Url>, ErrorException>(this.client.mapperAdapter())
.register(200, new TypeToken<Map<String, Base64Url>>() { }.getType())
.registerError(ErrorException.class)
.build(response);
}
Expand Down
Loading

0 comments on commit b348fdd

Please sign in to comment.