From b348fddc8eb887bef441644f7a1cd27363b2c619 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Mon, 11 Jul 2016 16:00:06 -0700 Subject: [PATCH] Support Base64url (#1238) --- .../java/com/microsoft/rest/Base64Url.java | 94 ++++++++++++++++ .../rest/serializer/Base64UrlSerializer.java | 38 +++++++ .../rest/serializer/JacksonMapperAdapter.java | 1 + .../main/java/fixtures/bodyarray/Arrays.java | 6 +- .../bodyarray/implementation/ArraysImpl.java | 39 +++++-- .../fixtures/bodydictionary/Dictionarys.java | 6 +- .../implementation/DictionarysImpl.java | 39 +++++-- .../java/fixtures/bodystring/Strings.java | 26 ++--- .../implementation/StringsImpl.java | 101 ++++++++++++------ .../src/main/java/fixtures/url/Paths.java | 4 +- .../url/implementation/PathsImpl.java | 13 ++- .../java/fixtures/bodyarray/ArrayTests.java | 9 ++ .../bodydictionary/DictionaryTests.java | 8 ++ .../bodystring/StringOperationsTests.java | 24 +++++ .../test/java/fixtures/url/PathsTests.java | 6 ++ .../TypeModels/ParameterModel.cs | 22 +++- .../TypeModels/PrimaryTypeModel.cs | 11 +- .../AutoRest.Java/TypeModels/ResponseModel.cs | 4 + 18 files changed, 369 insertions(+), 82 deletions(-) create mode 100644 src/client/Java/client-runtime/src/main/java/com/microsoft/rest/Base64Url.java create mode 100644 src/client/Java/client-runtime/src/main/java/com/microsoft/rest/serializer/Base64UrlSerializer.java diff --git a/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/Base64Url.java b/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/Base64Url.java new file mode 100644 index 0000000000..61b02879fe --- /dev/null +++ b/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/Base64Url.java @@ -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()); + } +} \ No newline at end of file diff --git a/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/serializer/Base64UrlSerializer.java b/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/serializer/Base64UrlSerializer.java new file mode 100644 index 0000000000..757ab735e2 --- /dev/null +++ b/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/serializer/Base64UrlSerializer.java @@ -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 { + /** + * 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()); + } +} diff --git a/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/serializer/JacksonMapperAdapter.java b/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/serializer/JacksonMapperAdapter.java index a592472075..ea938fe50c 100644 --- a/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/serializer/JacksonMapperAdapter.java +++ b/src/client/Java/client-runtime/src/main/java/com/microsoft/rest/serializer/JacksonMapperAdapter.java @@ -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()); diff --git a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodyarray/Arrays.java b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodyarray/Arrays.java index 9a286963a3..70f3652187 100644 --- a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodyarray/Arrays.java +++ b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodyarray/Arrays.java @@ -900,9 +900,9 @@ public interface Arrays { * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the List<String> object wrapped in {@link ServiceResponse} if successful. + * @return the List<byte[]> object wrapped in {@link ServiceResponse} if successful. */ - ServiceResponse> getBase64Url() throws ErrorException, IOException; + ServiceResponse> getBase64Url() throws ErrorException, IOException; /** * Get array value ['a string that gets encoded with base64url', 'test string' 'Lorem ipsum'] with the items base64url encoded. @@ -911,7 +911,7 @@ public interface Arrays { * @throws IllegalArgumentException thrown if callback is null * @return the {@link ServiceCall} object */ - ServiceCall getBase64UrlAsync(final ServiceCallback> serviceCallback) throws IllegalArgumentException; + ServiceCall getBase64UrlAsync(final ServiceCallback> serviceCallback) throws IllegalArgumentException; /** * Get array of complex type null value. diff --git a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodyarray/implementation/ArraysImpl.java b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodyarray/implementation/ArraysImpl.java index cca1023349..ab589fb78b 100644 --- a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodyarray/implementation/ArraysImpl.java +++ b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodyarray/implementation/ArraysImpl.java @@ -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; @@ -2587,11 +2588,21 @@ private ServiceResponse> getByteInvalidNullDelegate(Response> getBase64Url() throws ErrorException, IOException { + public ServiceResponse> getBase64Url() throws ErrorException, IOException { Call call = service.getBase64Url(); - return getBase64UrlDelegate(call.execute()); + ServiceResponse> response = getBase64UrlDelegate(call.execute()); + List body = null; + if (response.getBody() != null) { + body = new ArrayList(); + for (Base64Url item : response.getBody()) { + byte[] value; + value = item.getDecodedBytes(); + body.add(value); + } + } + return new ServiceResponse>(body, response.getResponse()); } /** @@ -2601,17 +2612,27 @@ public ServiceResponse> getBase64Url() throws ErrorException, IOExc * @throws IllegalArgumentException thrown if callback is null * @return the {@link Call} object */ - public ServiceCall getBase64UrlAsync(final ServiceCallback> serviceCallback) throws IllegalArgumentException { + public ServiceCall getBase64UrlAsync(final ServiceCallback> serviceCallback) throws IllegalArgumentException { if (serviceCallback == null) { throw new IllegalArgumentException("ServiceCallback is required for async calls."); } Call call = service.getBase64Url(); final ServiceCall serviceCall = new ServiceCall(call); - call.enqueue(new ServiceResponseCallback>(serviceCallback) { + call.enqueue(new ServiceResponseCallback>(serviceCallback) { @Override public void onResponse(Call call, Response response) { try { - serviceCallback.success(getBase64UrlDelegate(response)); + ServiceResponse> result = getBase64UrlDelegate(response); + List body = null; + if (result.getBody() != null) { + body = new ArrayList(); + for (Base64Url item : result.getBody()) { + byte[] value; + value = item.getDecodedBytes(); + body.add(value); + } + } + serviceCallback.success(new ServiceResponse>(body, result.getResponse())); } catch (ErrorException | IOException exception) { serviceCallback.failure(exception); } @@ -2620,9 +2641,9 @@ public void onResponse(Call call, Response response) return serviceCall; } - private ServiceResponse> getBase64UrlDelegate(Response response) throws ErrorException, IOException { - return new ServiceResponseBuilder, ErrorException>(this.client.mapperAdapter()) - .register(200, new TypeToken>() { }.getType()) + private ServiceResponse> getBase64UrlDelegate(Response response) throws ErrorException, IOException { + return new ServiceResponseBuilder, ErrorException>(this.client.mapperAdapter()) + .register(200, new TypeToken>() { }.getType()) .registerError(ErrorException.class) .build(response); } diff --git a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodydictionary/Dictionarys.java b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodydictionary/Dictionarys.java index b71c63fc31..6fa3175f7a 100644 --- a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodydictionary/Dictionarys.java +++ b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodydictionary/Dictionarys.java @@ -896,9 +896,9 @@ public interface Dictionarys { * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the Map<String, String> object wrapped in {@link ServiceResponse} if successful. + * @return the Map<String, byte[]> object wrapped in {@link ServiceResponse} if successful. */ - ServiceResponse> getBase64Url() throws ErrorException, IOException; + ServiceResponse> getBase64Url() throws ErrorException, IOException; /** * Get base64url dictionary value {"0": "a string that gets encoded with base64url", "1": "test string", "2": "Lorem ipsum"}. @@ -907,7 +907,7 @@ public interface Dictionarys { * @throws IllegalArgumentException thrown if callback is null * @return the {@link ServiceCall} object */ - ServiceCall getBase64UrlAsync(final ServiceCallback> serviceCallback) throws IllegalArgumentException; + ServiceCall getBase64UrlAsync(final ServiceCallback> serviceCallback) throws IllegalArgumentException; /** * Get dictionary of complex type null value. diff --git a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodydictionary/implementation/DictionarysImpl.java b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodydictionary/implementation/DictionarysImpl.java index dc0b9227eb..8445f69488 100644 --- a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodydictionary/implementation/DictionarysImpl.java +++ b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodydictionary/implementation/DictionarysImpl.java @@ -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; @@ -2574,11 +2575,21 @@ private ServiceResponse> getByteInvalidNullDelegate(Response * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the Map<String, String> object wrapped in {@link ServiceResponse} if successful. + * @return the Map<String, byte[]> object wrapped in {@link ServiceResponse} if successful. */ - public ServiceResponse> getBase64Url() throws ErrorException, IOException { + public ServiceResponse> getBase64Url() throws ErrorException, IOException { Call call = service.getBase64Url(); - return getBase64UrlDelegate(call.execute()); + ServiceResponse> response = getBase64UrlDelegate(call.execute()); + Map body = null; + if (response.getBody() != null) { + body = new HashMap(); + for (Map.Entry entry : response.getBody().entrySet()) { + byte[] value; + value = entry.getValue().getDecodedBytes(); + body.put(entry.getKey(), value); + } + } + return new ServiceResponse>(body, response.getResponse()); } /** @@ -2588,17 +2599,27 @@ public ServiceResponse> getBase64Url() throws ErrorException * @throws IllegalArgumentException thrown if callback is null * @return the {@link Call} object */ - public ServiceCall getBase64UrlAsync(final ServiceCallback> serviceCallback) throws IllegalArgumentException { + public ServiceCall getBase64UrlAsync(final ServiceCallback> serviceCallback) throws IllegalArgumentException { if (serviceCallback == null) { throw new IllegalArgumentException("ServiceCallback is required for async calls."); } Call call = service.getBase64Url(); final ServiceCall serviceCall = new ServiceCall(call); - call.enqueue(new ServiceResponseCallback>(serviceCallback) { + call.enqueue(new ServiceResponseCallback>(serviceCallback) { @Override public void onResponse(Call call, Response response) { try { - serviceCallback.success(getBase64UrlDelegate(response)); + ServiceResponse> result = getBase64UrlDelegate(response); + Map body = null; + if (result.getBody() != null) { + body = new HashMap(); + for (Map.Entry entry : result.getBody().entrySet()) { + byte[] value; + value = entry.getValue().getDecodedBytes(); + body.put(entry.getKey(), value); + } + } + serviceCallback.success(new ServiceResponse>(body, result.getResponse())); } catch (ErrorException | IOException exception) { serviceCallback.failure(exception); } @@ -2607,9 +2628,9 @@ public void onResponse(Call call, Response response) return serviceCall; } - private ServiceResponse> getBase64UrlDelegate(Response response) throws ErrorException, IOException { - return new ServiceResponseBuilder, ErrorException>(this.client.mapperAdapter()) - .register(200, new TypeToken>() { }.getType()) + private ServiceResponse> getBase64UrlDelegate(Response response) throws ErrorException, IOException { + return new ServiceResponseBuilder, ErrorException>(this.client.mapperAdapter()) + .register(200, new TypeToken>() { }.getType()) .registerError(ErrorException.class) .build(response); } diff --git a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodystring/Strings.java b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodystring/Strings.java index a3d90ec9de..70f5604a5b 100644 --- a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodystring/Strings.java +++ b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodystring/Strings.java @@ -216,9 +216,9 @@ public interface Strings { * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the String object wrapped in {@link ServiceResponse} if successful. + * @return the byte[] object wrapped in {@link ServiceResponse} if successful. */ - ServiceResponse getBase64Encoded() throws ErrorException, IOException; + ServiceResponse getBase64Encoded() throws ErrorException, IOException; /** * Get value that is base64 encoded. @@ -227,16 +227,16 @@ public interface Strings { * @throws IllegalArgumentException thrown if callback is null * @return the {@link ServiceCall} object */ - ServiceCall getBase64EncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException; + ServiceCall getBase64EncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException; /** * Get value that is base64url encoded. * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the String object wrapped in {@link ServiceResponse} if successful. + * @return the byte[] object wrapped in {@link ServiceResponse} if successful. */ - ServiceResponse getBase64UrlEncoded() throws ErrorException, IOException; + ServiceResponse getBase64UrlEncoded() throws ErrorException, IOException; /** * Get value that is base64url encoded. @@ -245,37 +245,37 @@ public interface Strings { * @throws IllegalArgumentException thrown if callback is null * @return the {@link ServiceCall} object */ - ServiceCall getBase64UrlEncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException; + ServiceCall getBase64UrlEncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException; /** * Put value that is base64url encoded. * - * @param stringBody the String value + * @param stringBody the Base64Url value * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization * @throws IllegalArgumentException exception thrown from invalid parameters * @return the {@link ServiceResponse} object if successful. */ - ServiceResponse putBase64UrlEncoded(String stringBody) throws ErrorException, IOException, IllegalArgumentException; + ServiceResponse putBase64UrlEncoded(byte[] stringBody) throws ErrorException, IOException, IllegalArgumentException; /** * Put value that is base64url encoded. * - * @param stringBody the String value + * @param stringBody the Base64Url value * @param serviceCallback the async ServiceCallback to handle successful and failed responses. * @throws IllegalArgumentException thrown if callback is null * @return the {@link ServiceCall} object */ - ServiceCall putBase64UrlEncodedAsync(String stringBody, final ServiceCallback serviceCallback) throws IllegalArgumentException; + ServiceCall putBase64UrlEncodedAsync(byte[] stringBody, final ServiceCallback serviceCallback) throws IllegalArgumentException; /** * Get null value that is expected to be base64url encoded. * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the String object wrapped in {@link ServiceResponse} if successful. + * @return the byte[] object wrapped in {@link ServiceResponse} if successful. */ - ServiceResponse getNullBase64UrlEncoded() throws ErrorException, IOException; + ServiceResponse getNullBase64UrlEncoded() throws ErrorException, IOException; /** * Get null value that is expected to be base64url encoded. @@ -284,6 +284,6 @@ public interface Strings { * @throws IllegalArgumentException thrown if callback is null * @return the {@link ServiceCall} object */ - ServiceCall getNullBase64UrlEncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException; + ServiceCall getNullBase64UrlEncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException; } diff --git a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodystring/implementation/StringsImpl.java b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodystring/implementation/StringsImpl.java index 7154cd32cc..fe22df0093 100644 --- a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodystring/implementation/StringsImpl.java +++ b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/bodystring/implementation/StringsImpl.java @@ -13,6 +13,7 @@ import retrofit2.Retrofit; import fixtures.bodystring.Strings; import com.google.common.reflect.TypeToken; +import com.microsoft.rest.Base64Url; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceResponse; @@ -100,7 +101,7 @@ interface StringsService { @Headers("Content-Type: application/json; charset=utf-8") @PUT("string/base64UrlEncoding") - Call putBase64UrlEncoded(@Body String stringBody); + Call putBase64UrlEncoded(@Body Base64Url stringBody); @Headers("Content-Type: application/json; charset=utf-8") @GET("string/nullBase64UrlEncoding") @@ -590,11 +591,16 @@ private ServiceResponse getNotProvidedDelegate(Response re * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the String object wrapped in {@link ServiceResponse} if successful. + * @return the byte[] object wrapped in {@link ServiceResponse} if successful. */ - public ServiceResponse getBase64Encoded() throws ErrorException, IOException { + public ServiceResponse getBase64Encoded() throws ErrorException, IOException { Call call = service.getBase64Encoded(); - return getBase64EncodedDelegate(call.execute()); + ServiceResponse response = getBase64EncodedDelegate(call.execute()); + byte[] body = null; + if (response.getBody() != null) { + body = response.getBody().getDecodedBytes(); + } + return new ServiceResponse(body, response.getResponse()); } /** @@ -604,17 +610,22 @@ public ServiceResponse getBase64Encoded() throws ErrorException, IOExcep * @throws IllegalArgumentException thrown if callback is null * @return the {@link Call} object */ - public ServiceCall getBase64EncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException { + public ServiceCall getBase64EncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException { if (serviceCallback == null) { throw new IllegalArgumentException("ServiceCallback is required for async calls."); } Call call = service.getBase64Encoded(); final ServiceCall serviceCall = new ServiceCall(call); - call.enqueue(new ServiceResponseCallback(serviceCallback) { + call.enqueue(new ServiceResponseCallback(serviceCallback) { @Override public void onResponse(Call call, Response response) { try { - serviceCallback.success(getBase64EncodedDelegate(response)); + ServiceResponse result = getBase64EncodedDelegate(response); + byte[] body = null; + if (result.getBody() != null) { + body = result.getBody().getDecodedBytes(); + } + serviceCallback.success(new ServiceResponse(body, result.getResponse())); } catch (ErrorException | IOException exception) { serviceCallback.failure(exception); } @@ -623,9 +634,9 @@ public void onResponse(Call call, Response response) return serviceCall; } - private ServiceResponse getBase64EncodedDelegate(Response response) throws ErrorException, IOException { - return new ServiceResponseBuilder(this.client.mapperAdapter()) - .register(200, new TypeToken() { }.getType()) + private ServiceResponse getBase64EncodedDelegate(Response response) throws ErrorException, IOException { + return new ServiceResponseBuilder(this.client.mapperAdapter()) + .register(200, new TypeToken() { }.getType()) .registerError(ErrorException.class) .build(response); } @@ -635,11 +646,16 @@ private ServiceResponse getBase64EncodedDelegate(Response * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the String object wrapped in {@link ServiceResponse} if successful. + * @return the byte[] object wrapped in {@link ServiceResponse} if successful. */ - public ServiceResponse getBase64UrlEncoded() throws ErrorException, IOException { + public ServiceResponse getBase64UrlEncoded() throws ErrorException, IOException { Call call = service.getBase64UrlEncoded(); - return getBase64UrlEncodedDelegate(call.execute()); + ServiceResponse response = getBase64UrlEncodedDelegate(call.execute()); + byte[] body = null; + if (response.getBody() != null) { + body = response.getBody().getDecodedBytes(); + } + return new ServiceResponse(body, response.getResponse()); } /** @@ -649,17 +665,22 @@ public ServiceResponse getBase64UrlEncoded() throws ErrorException, IOEx * @throws IllegalArgumentException thrown if callback is null * @return the {@link Call} object */ - public ServiceCall getBase64UrlEncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException { + public ServiceCall getBase64UrlEncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException { if (serviceCallback == null) { throw new IllegalArgumentException("ServiceCallback is required for async calls."); } Call call = service.getBase64UrlEncoded(); final ServiceCall serviceCall = new ServiceCall(call); - call.enqueue(new ServiceResponseCallback(serviceCallback) { + call.enqueue(new ServiceResponseCallback(serviceCallback) { @Override public void onResponse(Call call, Response response) { try { - serviceCallback.success(getBase64UrlEncodedDelegate(response)); + ServiceResponse result = getBase64UrlEncodedDelegate(response); + byte[] body = null; + if (result.getBody() != null) { + body = result.getBody().getDecodedBytes(); + } + serviceCallback.success(new ServiceResponse(body, result.getResponse())); } catch (ErrorException | IOException exception) { serviceCallback.failure(exception); } @@ -668,9 +689,9 @@ public void onResponse(Call call, Response response) return serviceCall; } - private ServiceResponse getBase64UrlEncodedDelegate(Response response) throws ErrorException, IOException { - return new ServiceResponseBuilder(this.client.mapperAdapter()) - .register(200, new TypeToken() { }.getType()) + private ServiceResponse getBase64UrlEncodedDelegate(Response response) throws ErrorException, IOException { + return new ServiceResponseBuilder(this.client.mapperAdapter()) + .register(200, new TypeToken() { }.getType()) .registerError(ErrorException.class) .build(response); } @@ -678,29 +699,30 @@ private ServiceResponse getBase64UrlEncodedDelegate(Response putBase64UrlEncoded(String stringBody) throws ErrorException, IOException, IllegalArgumentException { + public ServiceResponse putBase64UrlEncoded(byte[] stringBody) throws ErrorException, IOException, IllegalArgumentException { if (stringBody == null) { throw new IllegalArgumentException("Parameter stringBody is required and cannot be null."); } - Call call = service.putBase64UrlEncoded(stringBody); + Base64Url stringBodyConverted = Base64Url.encode(stringBody); + Call call = service.putBase64UrlEncoded(stringBodyConverted); return putBase64UrlEncodedDelegate(call.execute()); } /** * Put value that is base64url encoded. * - * @param stringBody the String value + * @param stringBody the Base64Url value * @param serviceCallback the async ServiceCallback to handle successful and failed responses. * @throws IllegalArgumentException thrown if callback is null * @return the {@link Call} object */ - public ServiceCall putBase64UrlEncodedAsync(String stringBody, final ServiceCallback serviceCallback) throws IllegalArgumentException { + public ServiceCall putBase64UrlEncodedAsync(byte[] stringBody, final ServiceCallback serviceCallback) throws IllegalArgumentException { if (serviceCallback == null) { throw new IllegalArgumentException("ServiceCallback is required for async calls."); } @@ -708,7 +730,8 @@ public ServiceCall putBase64UrlEncodedAsync(String stringBody, final ServiceCall serviceCallback.failure(new IllegalArgumentException("Parameter stringBody is required and cannot be null.")); return null; } - Call call = service.putBase64UrlEncoded(stringBody); + Base64Url stringBodyConverted = Base64Url.encode(stringBody); + Call call = service.putBase64UrlEncoded(stringBodyConverted); final ServiceCall serviceCall = new ServiceCall(call); call.enqueue(new ServiceResponseCallback(serviceCallback) { @Override @@ -735,11 +758,16 @@ private ServiceResponse putBase64UrlEncodedDelegate(Response * * @throws ErrorException exception thrown from REST call * @throws IOException exception thrown from serialization/deserialization - * @return the String object wrapped in {@link ServiceResponse} if successful. + * @return the byte[] object wrapped in {@link ServiceResponse} if successful. */ - public ServiceResponse getNullBase64UrlEncoded() throws ErrorException, IOException { + public ServiceResponse getNullBase64UrlEncoded() throws ErrorException, IOException { Call call = service.getNullBase64UrlEncoded(); - return getNullBase64UrlEncodedDelegate(call.execute()); + ServiceResponse response = getNullBase64UrlEncodedDelegate(call.execute()); + byte[] body = null; + if (response.getBody() != null) { + body = response.getBody().getDecodedBytes(); + } + return new ServiceResponse(body, response.getResponse()); } /** @@ -749,17 +777,22 @@ public ServiceResponse getNullBase64UrlEncoded() throws ErrorException, * @throws IllegalArgumentException thrown if callback is null * @return the {@link Call} object */ - public ServiceCall getNullBase64UrlEncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException { + public ServiceCall getNullBase64UrlEncodedAsync(final ServiceCallback serviceCallback) throws IllegalArgumentException { if (serviceCallback == null) { throw new IllegalArgumentException("ServiceCallback is required for async calls."); } Call call = service.getNullBase64UrlEncoded(); final ServiceCall serviceCall = new ServiceCall(call); - call.enqueue(new ServiceResponseCallback(serviceCallback) { + call.enqueue(new ServiceResponseCallback(serviceCallback) { @Override public void onResponse(Call call, Response response) { try { - serviceCallback.success(getNullBase64UrlEncodedDelegate(response)); + ServiceResponse result = getNullBase64UrlEncodedDelegate(response); + byte[] body = null; + if (result.getBody() != null) { + body = result.getBody().getDecodedBytes(); + } + serviceCallback.success(new ServiceResponse(body, result.getResponse())); } catch (ErrorException | IOException exception) { serviceCallback.failure(exception); } @@ -768,9 +801,9 @@ public void onResponse(Call call, Response response) return serviceCall; } - private ServiceResponse getNullBase64UrlEncodedDelegate(Response response) throws ErrorException, IOException { - return new ServiceResponseBuilder(this.client.mapperAdapter()) - .register(200, new TypeToken() { }.getType()) + private ServiceResponse getNullBase64UrlEncodedDelegate(Response response) throws ErrorException, IOException { + return new ServiceResponseBuilder(this.client.mapperAdapter()) + .register(200, new TypeToken() { }.getType()) .registerError(ErrorException.class) .build(response); } diff --git a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/url/Paths.java b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/url/Paths.java index 468fd300dc..db05b0a394 100644 --- a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/url/Paths.java +++ b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/url/Paths.java @@ -469,7 +469,7 @@ public interface Paths { * @throws IllegalArgumentException exception thrown from invalid parameters * @return the {@link ServiceResponse} object if successful. */ - ServiceResponse base64Url(String base64UrlPath) throws ErrorException, IOException, IllegalArgumentException; + ServiceResponse base64Url(byte[] base64UrlPath) throws ErrorException, IOException, IllegalArgumentException; /** * Get 'lorem' encoded value as 'bG9yZW0' (base64url). @@ -479,7 +479,7 @@ public interface Paths { * @throws IllegalArgumentException thrown if callback is null * @return the {@link ServiceCall} object */ - ServiceCall base64UrlAsync(String base64UrlPath, final ServiceCallback serviceCallback) throws IllegalArgumentException; + ServiceCall base64UrlAsync(byte[] base64UrlPath, final ServiceCallback serviceCallback) throws IllegalArgumentException; /** * Get an array of string ['ArrayPath1', 'begin!*'();:@ &=+$,/?#[]end' , null, ''] using the csv-array format. diff --git a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/url/implementation/PathsImpl.java b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/url/implementation/PathsImpl.java index 6d3d307d01..3ad7b3297d 100644 --- a/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/url/implementation/PathsImpl.java +++ b/src/generator/AutoRest.Java.Tests/src/main/java/fixtures/url/implementation/PathsImpl.java @@ -13,6 +13,7 @@ import retrofit2.Retrofit; import fixtures.url.Paths; import com.google.common.reflect.TypeToken; +import com.microsoft.rest.Base64Url; import com.microsoft.rest.serializer.CollectionFormat; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; @@ -155,7 +156,7 @@ interface PathsService { @Headers("Content-Type: application/json; charset=utf-8") @GET("paths/string/bG9yZW0/{base64UrlPath}") - Call base64Url(@Path("base64UrlPath") String base64UrlPath); + Call base64Url(@Path("base64UrlPath") Base64Url base64UrlPath); @Headers("Content-Type: application/json; charset=utf-8") @GET("paths/array/ArrayPath1%2cbegin%21%2A%27%28%29%3B%3A%40%20%26%3D%2B%24%2C%2F%3F%23%5B%5Dend%2c%2c/{arrayPath:commaSeparated}") @@ -1319,11 +1320,12 @@ private ServiceResponse dateTimeNullDelegate(Response respon * @throws IllegalArgumentException exception thrown from invalid parameters * @return the {@link ServiceResponse} object if successful. */ - public ServiceResponse base64Url(String base64UrlPath) throws ErrorException, IOException, IllegalArgumentException { + public ServiceResponse base64Url(byte[] base64UrlPath) throws ErrorException, IOException, IllegalArgumentException { if (base64UrlPath == null) { throw new IllegalArgumentException("Parameter base64UrlPath is required and cannot be null."); } - Call call = service.base64Url(base64UrlPath); + Base64Url base64UrlPathConverted = Base64Url.encode(base64UrlPath); + Call call = service.base64Url(base64UrlPathConverted); return base64UrlDelegate(call.execute()); } @@ -1335,7 +1337,7 @@ public ServiceResponse base64Url(String base64UrlPath) throws ErrorExcepti * @throws IllegalArgumentException thrown if callback is null * @return the {@link Call} object */ - public ServiceCall base64UrlAsync(String base64UrlPath, final ServiceCallback serviceCallback) throws IllegalArgumentException { + public ServiceCall base64UrlAsync(byte[] base64UrlPath, final ServiceCallback serviceCallback) throws IllegalArgumentException { if (serviceCallback == null) { throw new IllegalArgumentException("ServiceCallback is required for async calls."); } @@ -1343,7 +1345,8 @@ public ServiceCall base64UrlAsync(String base64UrlPath, final ServiceCallback call = service.base64Url(base64UrlPath); + Base64Url base64UrlPathConverted = Base64Url.encode(base64UrlPath); + Call call = service.base64Url(base64UrlPathConverted); final ServiceCall serviceCall = new ServiceCall(call); call.enqueue(new ServiceResponseCallback(serviceCallback) { @Override diff --git a/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodyarray/ArrayTests.java b/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodyarray/ArrayTests.java index 2bf57357c5..ea76c41769 100644 --- a/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodyarray/ArrayTests.java +++ b/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodyarray/ArrayTests.java @@ -422,6 +422,15 @@ public void getByteInvalidNull() throws Exception { } } + @Test + public void getBase64Url() throws Exception { + List result = client.arrays().getBase64Url().getBody(); + Assert.assertEquals(3, result.size()); + Assert.assertEquals("a string that gets encoded with base64url", new String(result.get(0))); + Assert.assertEquals("test string", new String(result.get(1))); + Assert.assertEquals("Lorem ipsum", new String(result.get(2))); + } + @Test public void getComplexNull() throws Exception { try { diff --git a/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodydictionary/DictionaryTests.java b/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodydictionary/DictionaryTests.java index cf7eac68cf..b66e18ad79 100644 --- a/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodydictionary/DictionaryTests.java +++ b/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodydictionary/DictionaryTests.java @@ -433,6 +433,14 @@ public void getByteInvalidNull() throws Exception { Assert.assertNull(result.get("1")); } + @Test + public void getBase64Url() throws Exception { + Map result = client.dictionarys().getBase64Url().getBody(); + Assert.assertEquals("a string that gets encoded with base64url", new String(result.get("0"))); + Assert.assertEquals("test string", new String(result.get("1"))); + Assert.assertEquals("Lorem ipsum", new String(result.get("2"))); + } + @Test public void getComplexNull() throws Exception { Map result = client.dictionarys().getComplexNull().getBody(); diff --git a/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodystring/StringOperationsTests.java b/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodystring/StringOperationsTests.java index 7947587ed7..011e17d09d 100644 --- a/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodystring/StringOperationsTests.java +++ b/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/bodystring/StringOperationsTests.java @@ -3,6 +3,7 @@ import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceException; import com.microsoft.rest.ServiceResponse; + import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -91,4 +92,27 @@ public void getNotProvided() throws Exception { Assert.assertTrue(ex.getMessage().contains("JsonMappingException")); } } + + @Test + public void getBase64Encoded() throws Exception { + byte[] result = client.strings().getBase64Encoded().getBody(); + Assert.assertEquals("a string that gets encoded with base64", new String(result)); + } + + @Test + public void getBase64UrlEncoded() throws Exception { + byte[] result = client.strings().getBase64UrlEncoded().getBody(); + Assert.assertEquals("a string that gets encoded with base64url", new String(result)); + } + + @Test + public void getNullBase64UrlEncoded() throws Exception { + byte[] result = client.strings().getNullBase64UrlEncoded().getBody(); + Assert.assertNull(result); + } + + @Test + public void putBase64UrlEncoded() throws Exception { + client.strings().putBase64UrlEncoded("a string that gets encoded with base64url".getBytes()); + } } diff --git a/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/url/PathsTests.java b/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/url/PathsTests.java index be3c2f4954..af1ae3b2e3 100644 --- a/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/url/PathsTests.java +++ b/src/generator/AutoRest.Java.Tests/src/test/java/fixtures/url/PathsTests.java @@ -145,6 +145,12 @@ public void dateTimeNull() throws Exception { Assert.assertTrue(ex.getMessage().contains("Parameter dateTimePath is required")); } } + + @Test + public void base64Url() throws Exception { + client.paths().base64Url("lorem".getBytes()); + } + /* @Test public void arrayCsvInPath() throws Exception { diff --git a/src/generator/AutoRest.Java/TypeModels/ParameterModel.cs b/src/generator/AutoRest.Java/TypeModels/ParameterModel.cs index bde271ed77..cc1a5a685a 100644 --- a/src/generator/AutoRest.Java/TypeModels/ParameterModel.cs +++ b/src/generator/AutoRest.Java/TypeModels/ParameterModel.cs @@ -43,7 +43,7 @@ public ITypeModel WireType { return new PrimaryTypeModel(KnownPrimaryType.Stream) { Name = "RequestBody" }; } - else if (Location != ParameterLocation.Body && Location != ParameterLocation.FormData && NeedsSpecialSerialization(ClientType)) + else if (!Type.IsPrimaryType(KnownPrimaryType.Base64Url) && Location != ParameterLocation.Body && Location != ParameterLocation.FormData && NeedsSpecialSerialization(ClientType)) { return new PrimaryTypeModel(KnownPrimaryType.String); } @@ -80,7 +80,14 @@ public string ConvertToWireType(string source, string clientReference) var sequence = ClientType as SequenceTypeModel; if (primary != null && primary.IsPrimaryType(KnownPrimaryType.ByteArray)) { - return string.Format(CultureInfo.InvariantCulture, "{0} {1} = Base64.encodeBase64String({2});", WireType.Name, _wireName, source); + if (WireType.IsPrimaryType(KnownPrimaryType.String)) + { + return string.Format(CultureInfo.InvariantCulture, "{0} {1} = Base64.encodeBase64String({2});", WireType.Name, _wireName, source); + } + else + { + return string.Format(CultureInfo.InvariantCulture, "{0} {1} = Base64Url.encode({2});", WireType.Name, _wireName, source); + } } else if (sequence != null) { @@ -121,6 +128,15 @@ private string convertClientTypeToWireType(ITypeModel wireType, string source, s .AppendLine("if ({0} != null) {{", source).Indent(); } builder.AppendLine("{0}{1} = {2}.toDateTime(DateTimeZone.UTC).getMillis() / 1000;", IsRequired ? "Long " : "", target, source); + } + else if (wireType.IsPrimaryType(KnownPrimaryType.Base64Url)) + { + if (!IsRequired) + { + builder.AppendLine("Base64Url {0} = {1};", target, wireType.DefaultValue(_method)) + .AppendLine("if ({0} != null) {{", source).Indent(); + } + builder.AppendLine("{0}{1} = Base64Url.encode({2});", IsRequired ? "Base64Url " : "", target, source); if (!IsRequired) { builder.Outdent().AppendLine("}"); @@ -151,7 +167,7 @@ private string convertClientTypeToWireType(ITypeModel wireType, string source, s var elementType = sequenceType.ElementTypeModel; var itemName = string.Format(CultureInfo.InvariantCulture, "item{0}", level == 0 ? "" : level.ToString(CultureInfo.InvariantCulture)); var itemTarget = string.Format(CultureInfo.InvariantCulture, "value{0}", level == 0 ? "" : level.ToString(CultureInfo.InvariantCulture)); - builder.AppendLine("{0}{1} = new ArrayList<{2}>();", IsRequired ? wireType.Name + " " : "" ,target, elementType.Name) + builder.AppendLine("{0}{1} = new ArrayList<{2}>();", IsRequired ? wireType.Name + " " : "", target, elementType.Name) .AppendLine("for ({0} {1} : {2}) {{", elementType.ParameterVariant.Name, itemName, source) .Indent().AppendLine(convertClientTypeToWireType(elementType, itemName, itemTarget, clientReference, level + 1)) .AppendLine("{0}.add({1});", target, itemTarget) diff --git a/src/generator/AutoRest.Java/TypeModels/PrimaryTypeModel.cs b/src/generator/AutoRest.Java/TypeModels/PrimaryTypeModel.cs index 3191b2d698..2fc3571957 100644 --- a/src/generator/AutoRest.Java/TypeModels/PrimaryTypeModel.cs +++ b/src/generator/AutoRest.Java/TypeModels/PrimaryTypeModel.cs @@ -64,6 +64,10 @@ public ITypeModel ParameterVariant { return new PrimaryTypeModel(KnownPrimaryType.DateTime); } + else if (Type == KnownPrimaryType.Base64Url) + { + return new PrimaryTypeModel(KnownPrimaryType.ByteArray); + } else if (Type == KnownPrimaryType.Stream) { return new PrimaryTypeModel(KnownPrimaryType.ByteArray); @@ -87,6 +91,10 @@ public ITypeModel ResponseVariant { return new PrimaryTypeModel(KnownPrimaryType.DateTime); } + else if (Type == KnownPrimaryType.Base64Url) + { + return new PrimaryTypeModel(KnownPrimaryType.ByteArray); + } else { return this; @@ -149,7 +157,8 @@ private void Initialize(PrimaryType primaryType) } else if (primaryType.Type == KnownPrimaryType.Base64Url) { - Name = "String"; + Name = "Base64Url"; + _imports.Add("com.microsoft.rest.Base64Url"); } else if (primaryType.Type == KnownPrimaryType.Boolean) { diff --git a/src/generator/AutoRest.Java/TypeModels/ResponseModel.cs b/src/generator/AutoRest.Java/TypeModels/ResponseModel.cs index e79b35ad73..516b301478 100644 --- a/src/generator/AutoRest.Java/TypeModels/ResponseModel.cs +++ b/src/generator/AutoRest.Java/TypeModels/ResponseModel.cs @@ -283,6 +283,10 @@ private string convertToClientType(ITypeModel type, string source, string target { return target + " = new DateTime(" + source + " * 1000L, DateTimeZone.UTC);"; } + else if (type.IsPrimaryType(KnownPrimaryType.Base64Url)) + { + return target + " = " + source + ".getDecodedBytes();"; + } else { return target + " = " + source + ";";