Implementation is thread-safe, and sub-classes must be thread-safe. For maximum efficiency, - * applications should use a single globally-shared instance of the JSON factory. - * - * @since 1.3 - * @author Yaniv Inbar - * @deprecated As of release 1.28, please use Jackson2 and google-http-client-jackson2. - */ -@Deprecated -public final class JacksonFactory extends JsonFactory { - - /** JSON factory. */ - private final org.codehaus.jackson.JsonFactory factory = new org.codehaus.jackson.JsonFactory(); - - { - // don't auto-close JSON content in order to ensure consistent behavior across JSON factories - // TODO(rmistry): Should we disable the JsonGenerator.Feature.AUTO_CLOSE_TARGET feature? - factory.configure(org.codehaus.jackson.JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false); - } - - @Override - public JsonGenerator createJsonGenerator(OutputStream out, Charset enc) throws IOException { - return new JacksonGenerator( - this, factory.createJsonGenerator(out, org.codehaus.jackson.JsonEncoding.UTF8)); - } - - @Override - public JsonGenerator createJsonGenerator(Writer writer) throws IOException { - return new JacksonGenerator(this, factory.createJsonGenerator(writer)); - } - - @Override - public JsonParser createJsonParser(Reader reader) throws IOException { - Preconditions.checkNotNull(reader); - return new JacksonParser(this, factory.createJsonParser(reader)); - } - - @Override - public JsonParser createJsonParser(InputStream in) throws IOException { - Preconditions.checkNotNull(in); - return new JacksonParser(this, factory.createJsonParser(in)); - } - - @Override - public JsonParser createJsonParser(InputStream in, Charset charset) throws IOException { - Preconditions.checkNotNull(in); - return new JacksonParser(this, factory.createJsonParser(in)); - } - - @Override - public JsonParser createJsonParser(String value) throws IOException { - Preconditions.checkNotNull(value); - return new JacksonParser(this, factory.createJsonParser(value)); - } - - static JsonToken convert(org.codehaus.jackson.JsonToken token) { - if (token == null) { - return null; - } - switch (token) { - case END_ARRAY: - return JsonToken.END_ARRAY; - case START_ARRAY: - return JsonToken.START_ARRAY; - case END_OBJECT: - return JsonToken.END_OBJECT; - case START_OBJECT: - return JsonToken.START_OBJECT; - case VALUE_FALSE: - return JsonToken.VALUE_FALSE; - case VALUE_TRUE: - return JsonToken.VALUE_TRUE; - case VALUE_NULL: - return JsonToken.VALUE_NULL; - case VALUE_STRING: - return JsonToken.VALUE_STRING; - case VALUE_NUMBER_FLOAT: - return JsonToken.VALUE_NUMBER_FLOAT; - case VALUE_NUMBER_INT: - return JsonToken.VALUE_NUMBER_INT; - case FIELD_NAME: - return JsonToken.FIELD_NAME; - default: - return JsonToken.NOT_AVAILABLE; - } - } -} diff --git a/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/JacksonGenerator.java b/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/JacksonGenerator.java deleted file mode 100644 index 096b892ac..000000000 --- a/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/JacksonGenerator.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2010 Google Inc. - * - * 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.google.api.client.json.jackson; - -import com.google.api.client.json.JsonGenerator; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; - -/** - * Low-level JSON serializer implementation based on Jackson. - * - *
Implementation is not thread-safe. - * - * @author Yaniv Inbar - * @deprecated As of release 1.28, please use Jackson2 and google-http-client-jackson2. - */ -@Deprecated -final class JacksonGenerator extends JsonGenerator { - private final org.codehaus.jackson.JsonGenerator generator; - private final JacksonFactory factory; - - @Override - public JacksonFactory getFactory() { - return factory; - } - - JacksonGenerator(JacksonFactory factory, org.codehaus.jackson.JsonGenerator generator) { - this.factory = factory; - this.generator = generator; - } - - @Override - public void flush() throws IOException { - generator.flush(); - } - - @Override - public void close() throws IOException { - generator.close(); - } - - @Override - public void writeBoolean(boolean state) throws IOException { - generator.writeBoolean(state); - } - - @Override - public void writeEndArray() throws IOException { - generator.writeEndArray(); - } - - @Override - public void writeEndObject() throws IOException { - generator.writeEndObject(); - } - - @Override - public void writeFieldName(String name) throws IOException { - generator.writeFieldName(name); - } - - @Override - public void writeNull() throws IOException { - generator.writeNull(); - } - - @Override - public void writeNumber(int v) throws IOException { - generator.writeNumber(v); - } - - @Override - public void writeNumber(long v) throws IOException { - generator.writeNumber(v); - } - - @Override - public void writeNumber(BigInteger v) throws IOException { - generator.writeNumber(v); - } - - @Override - public void writeNumber(double v) throws IOException { - generator.writeNumber(v); - } - - @Override - public void writeNumber(float v) throws IOException { - generator.writeNumber(v); - } - - @Override - public void writeNumber(BigDecimal v) throws IOException { - generator.writeNumber(v); - } - - @Override - public void writeNumber(String encodedValue) throws IOException { - generator.writeNumber(encodedValue); - } - - @Override - public void writeStartArray() throws IOException { - generator.writeStartArray(); - } - - @Override - public void writeStartObject() throws IOException { - generator.writeStartObject(); - } - - @Override - public void writeString(String value) throws IOException { - generator.writeString(value); - } - - @Override - public void enablePrettyPrint() throws IOException { - generator.useDefaultPrettyPrinter(); - } -} diff --git a/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/JacksonParser.java b/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/JacksonParser.java deleted file mode 100644 index 529582075..000000000 --- a/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/JacksonParser.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2010 Google Inc. - * - * 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.google.api.client.json.jackson; - -import com.google.api.client.json.JsonParser; -import com.google.api.client.json.JsonToken; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; - -/** - * Low-level JSON serializer implementation based on Jackson. - * - *
Implementation is not thread-safe.
- *
- * @author Yaniv Inbar
- * @deprecated As of release 1.28, please use Jackson2 and google-http-client-jackson2.
- */
-@Deprecated
-final class JacksonParser extends JsonParser {
-
- private final org.codehaus.jackson.JsonParser parser;
- private final JacksonFactory factory;
-
- @Override
- public JacksonFactory getFactory() {
- return factory;
- }
-
- JacksonParser(JacksonFactory factory, org.codehaus.jackson.JsonParser parser) {
- this.factory = factory;
- this.parser = parser;
- }
-
- @Override
- public void close() throws IOException {
- parser.close();
- }
-
- @Override
- public JsonToken nextToken() throws IOException {
- return JacksonFactory.convert(parser.nextToken());
- }
-
- @Override
- public String getCurrentName() throws IOException {
- return parser.getCurrentName();
- }
-
- @Override
- public JsonToken getCurrentToken() {
- return JacksonFactory.convert(parser.getCurrentToken());
- }
-
- @Override
- public JsonParser skipChildren() throws IOException {
- parser.skipChildren();
- return this;
- }
-
- @Override
- public String getText() throws IOException {
- return parser.getText();
- }
-
- @Override
- public byte getByteValue() throws IOException {
- return parser.getByteValue();
- }
-
- @Override
- public float getFloatValue() throws IOException {
- return parser.getFloatValue();
- }
-
- @Override
- public int getIntValue() throws IOException {
- return parser.getIntValue();
- }
-
- @Override
- public short getShortValue() throws IOException {
- return parser.getShortValue();
- }
-
- @Override
- public BigInteger getBigIntegerValue() throws IOException {
- return parser.getBigIntegerValue();
- }
-
- @Override
- public BigDecimal getDecimalValue() throws IOException {
- return parser.getDecimalValue();
- }
-
- @Override
- public double getDoubleValue() throws IOException {
- return parser.getDoubleValue();
- }
-
- @Override
- public long getLongValue() throws IOException {
- return parser.getLongValue();
- }
-}
diff --git a/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/package-info.java b/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/package-info.java
deleted file mode 100644
index eabec34a6..000000000
--- a/google-http-client-jackson/src/main/java/com/google/api/client/json/jackson/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2010 Google Inc.
- *
- * 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.
- */
-
-/**
- * Low-level implementation of the JSON parser library based on the Jackson JSON library.
- *
- * @since 1.3
- * @author Yaniv Inbar
- * @deprecated As of release 1.28, please use Jackson2 and google-http-client-jackson2.
- */
-package com.google.api.client.json.jackson;
diff --git a/google-http-client-jackson/src/test/java/com/google/api/client/json/jackson/JacksonFactoryTest.java b/google-http-client-jackson/src/test/java/com/google/api/client/json/jackson/JacksonFactoryTest.java
deleted file mode 100644
index 892d5b3b6..000000000
--- a/google-http-client-jackson/src/test/java/com/google/api/client/json/jackson/JacksonFactoryTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2010 Google Inc.
- *
- * 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.google.api.client.json.jackson;
-
-import com.google.api.client.json.JsonFactory;
-import com.google.api.client.json.JsonParser;
-import com.google.api.client.test.json.AbstractJsonFactoryTest;
-import com.google.api.client.util.StringUtils;
-import com.google.common.base.Charsets;
-import java.io.ByteArrayInputStream;
-import java.util.ArrayList;
-
-/**
- * Tests {@link JacksonFactory}.
- *
- * @author Yaniv Inbar
- */
-public class JacksonFactoryTest extends AbstractJsonFactoryTest {
-
- private static final String JSON_ENTRY_PRETTY =
- "{" + StringUtils.LINE_SEPARATOR + " \"title\" : \"foo\"" + StringUtils.LINE_SEPARATOR + "}";
- private static final String JSON_FEED_PRETTY =
- "{"
- + StringUtils.LINE_SEPARATOR
- + " \"entries\" : [ {"
- + StringUtils.LINE_SEPARATOR
- + " \"title\" : \"foo\""
- + StringUtils.LINE_SEPARATOR
- + " }, {"
- + StringUtils.LINE_SEPARATOR
- + " \"title\" : \"bar\""
- + StringUtils.LINE_SEPARATOR
- + " } ]"
- + StringUtils.LINE_SEPARATOR
- + "}";
-
- public JacksonFactoryTest(String name) {
- super(name);
- }
-
- @Override
- protected JsonFactory newFactory() {
- return new JacksonFactory();
- }
-
- public final void testToPrettyString_entry() throws Exception {
- Entry entry = new Entry();
- entry.title = "foo";
- assertEquals(JSON_ENTRY_PRETTY, newFactory().toPrettyString(entry));
- }
-
- public final void testToPrettyString_Feed() throws Exception {
- Feed feed = new Feed();
- Entry entryFoo = new Entry();
- entryFoo.title = "foo";
- Entry entryBar = new Entry();
- entryBar.title = "bar";
- feed.entries = new ArrayList Requires the the current event be {@link XmlPullParser#START_TAG} (skipping any initial
+ * Requires the current event be {@link XmlPullParser#START_TAG} (skipping any initial
* {@link XmlPullParser#START_DOCUMENT}) of the element being parsed. At normal parsing
* completion, the current event will either be {@link XmlPullParser#END_TAG} of the element being
* parsed, or the {@link XmlPullParser#START_TAG} of the requested {@code atom:entry}.
diff --git a/google-http-client-xml/src/main/java/com/google/api/client/xml/XmlNamespaceDictionary.java b/google-http-client-xml/src/main/java/com/google/api/client/xml/XmlNamespaceDictionary.java
index c500e2f83..6c04ef00f 100644
--- a/google-http-client-xml/src/main/java/com/google/api/client/xml/XmlNamespaceDictionary.java
+++ b/google-http-client-xml/src/main/java/com/google/api/client/xml/XmlNamespaceDictionary.java
@@ -283,7 +283,7 @@ private void computeAliases(Object element, SortedSet Implementations must not close the output stream, and instead should flush the output
- * stream. Some callers may assume that the the output stream has not been closed, and will fail
- * to work if it has been closed.
+ * stream. Some callers may assume that the output stream has not been closed, and will fail to
+ * work if it has been closed.
*
* @param content streaming content
* @param out output stream
diff --git a/google-http-client/src/main/java/com/google/api/client/http/HttpHeaders.java b/google-http-client/src/main/java/com/google/api/client/http/HttpHeaders.java
index caa88c99e..e43f09b0f 100644
--- a/google-http-client/src/main/java/com/google/api/client/http/HttpHeaders.java
+++ b/google-http-client/src/main/java/com/google/api/client/http/HttpHeaders.java
@@ -893,21 +893,6 @@ static void serializeHeaders(
serializeHeaders(headers, logbuf, curlbuf, logger, lowLevelHttpRequest, null);
}
- /**
- * Serializes headers to an {@link Writer} for Multi-part requests.
- *
- * @param headers HTTP headers
- * @param logbuf log buffer or {@code null} for none
- * @param logger logger or {@code null} for none. Logger must be specified if log buffer is
- * specified
- * @param writer Writer where HTTP headers will be serialized to or {@code null} for none
- * @since 1.9
- */
- public static void serializeHeadersForMultipartRequests(
- HttpHeaders headers, StringBuilder logbuf, Logger logger, Writer writer) throws IOException {
- serializeHeaders(headers, logbuf, null, logger, null, writer);
- }
-
static void serializeHeaders(
HttpHeaders headers,
StringBuilder logbuf,
@@ -947,6 +932,21 @@ static void serializeHeaders(
}
}
+ /**
+ * Serializes headers to an {@link Writer} for Multi-part requests.
+ *
+ * @param headers HTTP headers
+ * @param logbuf log buffer or {@code null} for none
+ * @param logger logger or {@code null} for none. Logger must be specified if log buffer is
+ * specified
+ * @param writer Writer where HTTP headers will be serialized to or {@code null} for none
+ * @since 1.9
+ */
+ public static void serializeHeadersForMultipartRequests(
+ HttpHeaders headers, StringBuilder logbuf, Logger logger, Writer writer) throws IOException {
+ serializeHeaders(headers, logbuf, null, logger, null, writer);
+ }
+
/**
* Puts all headers of the {@link LowLevelHttpResponse} into this {@link HttpHeaders} object.
*
diff --git a/google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java b/google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java
index 05d6cc906..399ed8bac 100644
--- a/google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java
+++ b/google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java
@@ -15,7 +15,7 @@
package com.google.api.client.http;
import com.google.api.client.util.Beta;
-import com.google.api.client.util.IOUtils;
+import com.google.api.client.util.CachingByteArrayOutputStream;
import com.google.api.client.util.LoggingStreamingContent;
import com.google.api.client.util.ObjectParser;
import com.google.api.client.util.Preconditions;
@@ -932,7 +932,14 @@ public HttpResponse execute() throws IOException {
} else {
contentEncoding = encoding.getName();
streamingContent = new HttpEncodingStreamingContent(streamingContent, encoding);
- contentLength = contentRetrySupported ? IOUtils.computeLength(streamingContent) : -1;
+ if (contentRetrySupported) {
+ CachingByteArrayOutputStream outputStream = new CachingByteArrayOutputStream();
+ streamingContent.writeTo(outputStream);
+ contentLength = outputStream.getContentLength();
+ streamingContent = new ByteArrayContent(contentType, outputStream.getBuffer());
+ } else {
+ contentLength = -1;
+ }
}
// append content headers to log buffer
if (loggable) {
diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java
index e497f882c..aa0d8e3e4 100644
--- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java
+++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java
@@ -115,7 +115,7 @@ LowLevelHttpResponse execute(final OutputWriter outputWriter) throws IOException
} catch (IOException e) {
// If we've gotten a response back, continue on and try to parse the response. Otherwise,
// re-throw the IOException
- if (!hasReponse(connection)) {
+ if (!hasResponse(connection)) {
throw e;
}
} finally {
@@ -151,7 +151,7 @@ LowLevelHttpResponse execute(final OutputWriter outputWriter) throws IOException
}
}
- private boolean hasReponse(HttpURLConnection connection) {
+ private boolean hasResponse(HttpURLConnection connection) {
try {
return connection.getResponseCode() > 0;
} catch (IOException e) {
diff --git a/google-http-client/src/main/java/com/google/api/client/util/Base64.java b/google-http-client/src/main/java/com/google/api/client/util/Base64.java
index 305ab688c..038156390 100644
--- a/google-http-client/src/main/java/com/google/api/client/util/Base64.java
+++ b/google-http-client/src/main/java/com/google/api/client/util/Base64.java
@@ -43,6 +43,9 @@ public static byte[] encodeBase64(byte[] binaryData) {
* @return String containing Base64 characters or {@code null} for {@code null} input
*/
public static String encodeBase64String(byte[] binaryData) {
+ if (binaryData == null) {
+ return null;
+ }
return BaseEncoding.base64().encode(binaryData);
}
@@ -66,6 +69,9 @@ public static byte[] encodeBase64URLSafe(byte[] binaryData) {
* @return String containing Base64 characters or {@code null} for {@code null} input
*/
public static String encodeBase64URLSafeString(byte[] binaryData) {
+ if (binaryData == null) {
+ return null;
+ }
return BaseEncoding.base64Url().omitPadding().encode(binaryData);
}
@@ -88,11 +94,14 @@ public static byte[] decodeBase64(byte[] base64Data) {
* @return Array containing decoded data or {@code null} for {@code null} input
*/
public static byte[] decodeBase64(String base64String) {
+ if (base64String == null) {
+ return null;
+ }
try {
return BaseEncoding.base64().decode(base64String);
} catch (IllegalArgumentException e) {
if (e.getCause() instanceof DecodingException) {
- return BaseEncoding.base64Url().decode(base64String);
+ return BaseEncoding.base64Url().decode(base64String.trim());
}
throw e;
}
diff --git a/google-http-client/src/main/java/com/google/api/client/util/CachingByteArrayOutputStream.java b/google-http-client/src/main/java/com/google/api/client/util/CachingByteArrayOutputStream.java
new file mode 100644
index 000000000..73119a644
--- /dev/null
+++ b/google-http-client/src/main/java/com/google/api/client/util/CachingByteArrayOutputStream.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * 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.google.api.client.util;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Output stream that extends the built-in {@link ByteArrayOutputStream} to return the internal
+ * byte buffer rather than creating a copy.
+ */
+public class CachingByteArrayOutputStream extends ByteArrayOutputStream {
+
+ /**
+ * Returns the content length of the buffer.
+ *
+ * @return tthe content length of the buffer.
+ */
+ public int getContentLength() {
+ return count;
+ }
+
+ /**
+ * Returns the buffer where the byte data is stored.
+ *
+ * @return the buffer where the byte data is stored.
+ */
+ public byte[] getBuffer() {
+ return buf;
+ }
+
+}
diff --git a/google-http-client/src/main/java/com/google/api/client/util/Key.java b/google-http-client/src/main/java/com/google/api/client/util/Key.java
index dfc0dd454..40094065c 100644
--- a/google-http-client/src/main/java/com/google/api/client/util/Key.java
+++ b/google-http-client/src/main/java/com/google/api/client/util/Key.java
@@ -34,7 +34,7 @@
*
* // uses data key name of "some_other_name"
* @Key("some_other_name")
- * private String dataKeyNameIsOverriden;
+ * private String dataKeyNameIsOverridden;
*
* // not a data key
* private String notADataKey;
diff --git a/google-http-client/src/main/java/com/google/api/client/util/Objects.java b/google-http-client/src/main/java/com/google/api/client/util/Objects.java
index ab980d948..08da55d0b 100644
--- a/google-http-client/src/main/java/com/google/api/client/util/Objects.java
+++ b/google-http-client/src/main/java/com/google/api/client/util/Objects.java
@@ -88,7 +88,7 @@ public static final class ToStringHelper {
private ValueHolder holderTail = holderHead;
private boolean omitNullValues;
- /** @param wrapped wrapped object */
+ /** @param className wrapped object */
ToStringHelper(String className) {
this.className = className;
}
diff --git a/google-http-client/src/main/java/com/google/api/client/util/StreamingContent.java b/google-http-client/src/main/java/com/google/api/client/util/StreamingContent.java
index a2a9f600d..8ae55bbf6 100644
--- a/google-http-client/src/main/java/com/google/api/client/util/StreamingContent.java
+++ b/google-http-client/src/main/java/com/google/api/client/util/StreamingContent.java
@@ -31,8 +31,8 @@ public interface StreamingContent {
* Writes the byte content to the given output stream.
*
* Implementations must not close the output stream, and instead should flush the output
- * stream. Some callers may assume that the the output stream has not been closed, and will fail
- * to work if it has been closed.
+ * stream. Some callers may assume that the output stream has not been closed, and will fail to
+ * work if it has been closed.
*
* @param out output stream
*/
diff --git a/google-http-client/src/main/java/com/google/api/client/util/StringUtils.java b/google-http-client/src/main/java/com/google/api/client/util/StringUtils.java
index dc57990ef..0efb24674 100644
--- a/google-http-client/src/main/java/com/google/api/client/util/StringUtils.java
+++ b/google-http-client/src/main/java/com/google/api/client/util/StringUtils.java
@@ -39,7 +39,7 @@ public class StringUtils {
* @param string the String to encode, may be null
* @return encoded bytes, or null if the input string was null
* @throws IllegalStateException Thrown when the charset is missing, which should be never
- * according the the Java specification.
+ * according the Java specification.
* @see Standard charsets
* @since 1.8
diff --git a/google-http-client/src/test/java/com/google/api/client/http/HttpRequestTest.java b/google-http-client/src/test/java/com/google/api/client/http/HttpRequestTest.java
index 946f5961f..543dd1644 100644
--- a/google-http-client/src/test/java/com/google/api/client/http/HttpRequestTest.java
+++ b/google-http-client/src/test/java/com/google/api/client/http/HttpRequestTest.java
@@ -25,6 +25,7 @@
import com.google.api.client.util.BackOff;
import com.google.api.client.util.Key;
import com.google.api.client.util.LoggingStreamingContent;
+import com.google.api.client.util.StreamingContent;
import com.google.api.client.util.StringUtils;
import com.google.api.client.util.Value;
import com.google.common.base.Charsets;
@@ -33,6 +34,7 @@
import com.google.common.collect.Lists;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
@@ -984,7 +986,6 @@ public LowLevelHttpRequest buildRequest(String method, String url) throws IOExce
@Override
public LowLevelHttpResponse execute() throws IOException {
if (expectGZip) {
- assertEquals(HttpEncodingStreamingContent.class, getStreamingContent().getClass());
assertEquals("gzip", getContentEncoding());
assertEquals(25, getContentLength());
} else {
@@ -1264,4 +1265,56 @@ public void testExecute_curlLoggerWithContentEncoding() throws Exception {
}
assertTrue(found);
}
+
+ public void testExecute_shouldEncodeContentOnce() throws IOException {
+ class TestEncoding implements HttpEncoding {
+
+ private int encodingCount = 0;
+
+ @Override
+ public String getName() {
+ return "test-encoding";
+ }
+
+ @Override
+ public void encode(StreamingContent content, OutputStream out) throws IOException {
+ encodingCount++;
+ return;
+ }
+
+ public int getEncodingCount() {
+ return encodingCount;
+ }
+ }
+
+ class NullOutputStream extends OutputStream {
+ @Override
+ public void write(int b) throws IOException {
+ }
+ }
+ final LowLevelHttpRequest lowLevelHttpRequest =
+ new MockLowLevelHttpRequest() {
+ @Override
+ public LowLevelHttpResponse execute() throws IOException {
+ // LowLevelRequest implementations will use writeTo for the request body
+ getStreamingContent().writeTo(new NullOutputStream());
+ return super.execute();
+ }
+ };
+ HttpTransport transport =
+ new MockHttpTransport() {
+ @Override
+ public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
+ return lowLevelHttpRequest;
+ }
+ };
+ HttpContent content = new EmptyContent();
+ TestEncoding encoding = new TestEncoding();
+ HttpRequest request =
+ transport.createRequestFactory().buildPostRequest(HttpTesting.SIMPLE_GENERIC_URL, content);
+ request.setEncoding(encoding);
+ request.execute();
+
+ assertEquals(1, encoding.getEncodingCount());
+ }
}
diff --git a/google-http-client/src/test/java/com/google/api/client/util/Base64Test.java b/google-http-client/src/test/java/com/google/api/client/util/Base64Test.java
new file mode 100644
index 000000000..0ee174f9f
--- /dev/null
+++ b/google-http-client/src/test/java/com/google/api/client/util/Base64Test.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * 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.google.api.client.util;
+
+import java.nio.charset.StandardCharsets;
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link Base64}.
+ *
+ * @author Jeff Ching
+ */
+public class Base64Test extends TestCase {
+
+ public void test_decodeBase64_withPadding() {
+ String encoded = "Zm9vOmJhcg==";
+ assertEquals("foo:bar", new String(Base64.decodeBase64(encoded), StandardCharsets.UTF_8));
+ }
+
+ public void test_decodeBase64_withoutPadding() {
+ String encoded = "Zm9vOmJhcg";
+ assertEquals("foo:bar", new String(Base64.decodeBase64(encoded), StandardCharsets.UTF_8));
+ }
+
+ public void test_decodeBase64_withTrailingWhitespace() {
+ // Some internal use cases append extra space characters that apache-commons base64 decoding
+ // previously handled.
+ String encoded = "Zm9vOmJhcg==\r\n";
+ assertEquals("foo:bar", new String(Base64.decodeBase64(encoded), StandardCharsets.UTF_8));
+ }
+
+ public void test_decodeBase64_withNullBytes_shouldReturnNull() {
+ byte[] encoded = null;
+ assertNull(Base64.decodeBase64(encoded));
+ }
+
+ public void test_decodeBase64_withNull_shouldReturnNull() {
+ String encoded = null;
+ assertNull(Base64.decodeBase64(encoded));
+ }
+
+ public void test_encodeBase64URLSafeString_withNull_shouldReturnNull() {
+ assertNull(Base64.encodeBase64URLSafeString(null));
+ }
+
+ public void test_encodeBase64URLSafe_withNull_shouldReturnNull() {
+ assertNull(Base64.encodeBase64URLSafe(null));
+ }
+
+ public void test_encodeBase64_withNull_shouldReturnNull() {
+ assertNull(Base64.encodeBase64(null));
+ }
+}
diff --git a/pom.xml b/pom.xml
index b1d4d0bb6..6872e5cc4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,7 +60,6 @@