This is an automated email from the ASF dual-hosted git repository. jamesbognar pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push: new c22d4ea REST refactoring. c22d4ea is described below commit c22d4ea8b3301af4a2a90f7e7302a532188c3772 Author: JamesBognar <james.bog...@salesforce.com> AuthorDate: Thu Mar 4 19:54:28 2021 -0500 REST refactoring. --- .../java/org/apache/juneau/http/HttpEntities.java | 58 +++++- .../juneau/http/entity/AbstractHttpEntity.java | 195 +++++++++++++++++++++ .../juneau/http/entity/InputStreamEntity.java | 135 ++++++++++++++ .../apache/juneau/http/entity/StringEntity.java | 131 ++++++++++++++ .../org/apache/juneau/http/header/MediaType.java | 59 ++++++- .../juneau/http/response/BasicHttpException.java | 12 +- .../juneau/http/response/BasicHttpResponse.java | 12 +- .../juneau/http/response/HttpExceptionBuilder.java | 8 +- .../juneau/http/response/HttpResponseBuilder.java | 11 +- .../java/org/apache/juneau/internal/IOUtils.java | 8 + .../org/apache/juneau/rest/client/RestClient.java | 2 - .../org/apache/juneau/rest/client/RestRequest.java | 13 +- .../rest/client/RestClient_BasicCalls_Test.java | 15 +- 13 files changed, 604 insertions(+), 55 deletions(-) diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpEntities.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpEntities.java index 43d30f6..21c588b 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpEntities.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpEntities.java @@ -12,8 +12,64 @@ // *************************************************************************************************************************** package org.apache.juneau.http; +import java.io.*; +import java.nio.charset.*; + +import org.apache.juneau.http.entity.*; +import org.apache.juneau.http.header.*; + /** - * Standard predefined HTTP headers. + * Standard predefined HTTP entities. */ public class HttpEntities { + + /** + * Creates a new {@link StringEntity} object. + * + * <p> + * Assumes {@link ContentType#TEXT_PLAIN TEXT/PLAIN} content type and <js>"UTF-8"</js> encoding. + * + * @param content The entity content. Can be <jk>null</jk>. + * @return A new {@link StringEntity} object. + */ + public static final StringEntity stringEntity(String content) { + return StringEntity.of(content); + } + + /** + * Creates a new {@link StringEntity} object. + * + * @param content The entity content. Can be <jk>null</jk>. + * @param contentType The entity content type, or {@link ContentType#TEXT_PLAIN} if not specified. + * @param charset The content character encoding, or <js>"UTF-8"</js> if not specified. + * @return A new {@link StringEntity} object. + */ + public static final StringEntity stringEntity(String content, ContentType contentType, Charset charset) { + return StringEntity.of(content, contentType, charset); + } + + /** + * Creates a new {@link InputStreamEntity} object. + * + * <p> + * Assumes no content type. + * + * @param content The entity content. Can be <jk>null<jk>. + * @return A new {@link InputStreamEntity} object. + */ + public static final InputStreamEntity streamEntity(InputStream content) { + return InputStreamEntity.of(content); + } + + /** + * Creates a new {@link InputStreamEntity} object. + * + * @param content The entity content. Can be <jk>null<jk>. + * @param contentType The entity content type, or <jk>null</jk> if not specified. + * @param length The content length, or <c>-1</c> if not known. + * @return A new {@link InputStreamEntity} object. + */ + public static final InputStreamEntity streamEntity(InputStream content, long length, ContentType contentType) { + return InputStreamEntity.of(content, length, contentType); + } } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/AbstractHttpEntity.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/AbstractHttpEntity.java new file mode 100644 index 0000000..e11ec9c --- /dev/null +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/AbstractHttpEntity.java @@ -0,0 +1,195 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you 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 org.apache.juneau.http.entity; + +import java.io.*; + +import org.apache.http.*; +import org.apache.juneau.annotation.*; +import org.apache.juneau.assertions.*; +import org.apache.juneau.http.header.*; +import org.apache.juneau.http.header.ContentType; +import org.apache.juneau.internal.*; + +/** + * An extension of {@link org.apache.http.entity.AbstractHttpEntity} with additional features. + * + * Provides the following features: + * <ul class='spaced-list'> + * <li> + * Caching. + * <li> + * Fluent setters. + * <li> + * Fluent assertions. + * </ul> + */ +@FluentSetters +@BeanIgnore +public abstract class AbstractHttpEntity extends org.apache.http.entity.AbstractHttpEntity { + + private long length = -1; + + /** + * Shortcut for calling {@link #setContentType(String)}. + * + * @param value The new <c>Content-Type</ header, or <jk>null</jk> to unset. + * @return This object (for method chaining). + */ + @FluentSetter + public AbstractHttpEntity contentType(String value) { + return contentType(ContentType.of(value)); + } + + /** + * Shortcut for calling {@link #setContentType(Header)}. + * + * @param value The new <c>Content-Type</ header, or <jk>null</jk> to unset. + * @return This object (for method chaining). + */ + @FluentSetter + public AbstractHttpEntity contentType(Header value) { + super.setContentType(value); + return this; + } + + /** + * Sets the content length of this entity. + * + * @param value The new <c>Content-Length</c> header value. + * @return This object (for method chaining). + */ + @FluentSetter + public AbstractHttpEntity contentLength(long value) { + length = value; + return this; + } + + /** + * Shortcut for calling {@link #setContentEncoding(String)}. + * + * @param value The new <c>Content-Encoding</ header, or <jk>null</jk> to unset. + * @return This object (for method chaining). + */ + @FluentSetter + public AbstractHttpEntity contentEncoding(String value) { + return contentEncoding(ContentEncoding.of(value)); + } + + /** + * Shortcut for calling {@link #setContentEncoding(Header)}. + * + * @param value The new <c>Content-Encoding</ header, or <jk>null</jk> to unset. + * @return This object (for method chaining). + */ + @FluentSetter + public AbstractHttpEntity contentEncoding(Header value) { + super.setContentEncoding(value); + return this; + } + + /** + * Shortcut for calling {@link #setChunked(boolean)} with <jk>true</jk>. + * + * <ul class='notes'> + * <li>If the {@link #getContentLength()} method returns a negative value, the HttpClient code will always + * use chunked encoding. + * </ul> + * + * @return This object (for method chaining). + */ + @FluentSetter + public AbstractHttpEntity chunked() { + return chunked(true); + } + + /** + * Shortcut for calling {@link #setChunked(boolean)}. + * + * <ul class='notes'> + * <li>If the {@link #getContentLength()} method returns a negative value, the HttpClient code will always + * use chunked encoding. + * </ul> + * + * @param value The new value for this flag. + * @return This object (for method chaining). + */ + @FluentSetter + public AbstractHttpEntity chunked(boolean value) { + super.setChunked(value); + return this; + } + + /** + * Specifies that the contents of this resource should be cached into an internal byte array so that it can + * be read multiple times. + * + * @return This object (for method chaining). + * @throws IOException If entity could not be read into memory. + */ + @FluentSetter + public AbstractHttpEntity cache() throws IOException { + return this; + } + + /** + * Converts the contents of this entity as a byte array. + * + * @return The contents of this entity as a byte array. + * @throws IOException If a problem occurred while trying to read the byte array. + */ + public String asString() throws IOException { + return IOUtils.read(getContent()); + } + + /** + * Converts the contents of this entity as a byte array. + * + * @return The contents of this entity as a byte array. + * @throws IOException If a problem occurred while trying to read the byte array. + */ + public byte[] asBytes() throws IOException { + try (InputStream o = getContent()) { + return o == null ? null : IOUtils.readBytes(o); + } + } + + /** + * Returns an assertion on the contents of this entity. + * + * @return A new fluent assertion. + * @throws IOException If a problem occurred while trying to read the byte array. + */ + public FluentStringAssertion<AbstractHttpEntity> assertString() throws IOException { + return new FluentStringAssertion<>(asString(), this); + } + + /** + * Returns an assertion on the contents of this entity. + * + * @return A new fluent assertion. + * @throws IOException If a problem occurred while trying to read the byte array. + */ + public FluentByteArrayAssertion<AbstractHttpEntity> assertBytes() throws IOException { + return new FluentByteArrayAssertion<>(asBytes(), this); + } + + @Override /* HttpEntity */ + public long getContentLength() { + return length; + } + + // <FluentSetters> + + // </FluentSetters> +} diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/InputStreamEntity.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/InputStreamEntity.java new file mode 100644 index 0000000..85b2758 --- /dev/null +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/InputStreamEntity.java @@ -0,0 +1,135 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you 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 org.apache.juneau.http.entity; + +import static org.apache.juneau.assertions.Assertions.*; + +import java.io.*; +import java.util.concurrent.atomic.*; + +import org.apache.juneau.http.header.*; +import org.apache.juneau.internal.*; + +/** + * A streamed, non-repeatable entity that obtains its content from an {@link InputStream}. + */ +public class InputStreamEntity extends AbstractHttpEntity { + + private final InputStream content; + private final long length; + private AtomicReference<byte[]> bytes = new AtomicReference<>(); + + /** + * Creates a new {@link InputStreamEntity} object. + * + * <p> + * Assumes no content type. + * + * @param content The entity content. Can be <jk>null<jk>. + * @return A new {@link InputStreamEntity} object. + */ + public static InputStreamEntity of(InputStream content) { + return new InputStreamEntity(content, -1, null); + } + + /** + * Creates a new {@link InputStreamEntity} object. + * + * @param content The entity content. Can be <jk>null<jk>. + * @param contentType The entity content type, or <jk>null</jk> if not specified. + * @param length The content length, or <c>-1</c> if not known. + * @return A new {@link InputStreamEntity} object. + */ + public static InputStreamEntity of(InputStream content, long length, ContentType contentType) { + return new InputStreamEntity(content, length, contentType); + } + + /** + * Constructor. + * + * @param content The entity content. Can be <jk>null</jk>. + * @param contentType The entity content type, or <jk>null</jk> if not specified. + * @param length The content length, or <c>-1</c> if not known. + */ + public InputStreamEntity(InputStream content, long length, ContentType contentType) { + this.content = content == null ? IOUtils.EMPTY_INPUT_STREAM : content; + this.length = length; + setContentType(contentType); + } + + @Override /* HttpEntity */ + public boolean isRepeatable() { + return false; + } + + @Override /* HttpEntity */ + public long getContentLength() { + return length; + } + + @Override /* HttpEntity */ + public InputStream getContent() throws IOException { + byte[] b = bytes.get(); + return b == null ? content : new ByteArrayInputStream(b); + } + + @Override /* AbstractHttpEntity */ + public InputStreamEntity cache() throws IOException { + byte[] b = bytes.get(); + if (b == null) { + b = IOUtils.readBytes(content); + bytes.set(b); + } + return this; + } + + /** + * Writes bytes from the {@code InputStream} this entity was constructed + * with to an {@code OutputStream}. The content length + * determines how many bytes are written. If the length is unknown ({@code -1}), the + * stream will be completely consumed (to the end of the stream). + */ + @Override + public void writeTo(OutputStream out) throws IOException { + assertArgNotNull("out", out); + InputStream is = getContent(); + try { + byte[] buffer = new byte[OUTPUT_BUFFER_SIZE]; + int readLen; + if (length < 0) { + // consume until EOF + while ((readLen = is.read(buffer)) != -1) { + out.write(buffer, 0, readLen); + } + } else { + // consume no more than length + long remaining = length; + while (remaining > 0) { + readLen = is.read(buffer, 0, (int)Math.min(OUTPUT_BUFFER_SIZE, remaining)); + if (readLen == -1) { + break; + } + out.write(buffer, 0, readLen); + remaining -= readLen; + } + } + } finally { + is.close(); + } + } + + @Override /* HttpEntity */ + public boolean isStreaming() { + return bytes.get() == null; + } +} diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/StringEntity.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/StringEntity.java new file mode 100644 index 0000000..4110cad --- /dev/null +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/StringEntity.java @@ -0,0 +1,131 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you 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 org.apache.juneau.http.entity; + +import static org.apache.juneau.assertions.Assertions.*; +import static org.apache.juneau.internal.StringUtils.*; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.concurrent.atomic.*; + +import org.apache.juneau.http.header.*; +import org.apache.juneau.internal.*; + +/** + * A self contained, repeatable entity that obtains its content from a {@link String}. + * + * Similar to {@link org.apache.http.entity.StringEntity} but delays converting to an internal byte array until + * actually used. + */ +public class StringEntity extends AbstractHttpEntity { + + private final String content; + private final Charset charset; + private AtomicReference<byte[]> bytes = new AtomicReference<>(); + + /** + * Creates a new {@link StringEntity} object. + * + * <p> + * Assumes {@link ContentType#TEXT_PLAIN TEXT/PLAIN} content type and <js>"UTF-8"</js> encoding. + * + * @param content The entity content. Can be <jk>null</jk>. + * @return A new {@link StringEntity} object. + */ + public static StringEntity of(String content) { + return new StringEntity(content, ContentType.TEXT_PLAIN, IOUtils.UTF8); + } + + /** + * Creates a new {@link StringEntity} object. + * + * @param content The entity content. Can be <jk>null</jk>. + * @param contentType The entity content type, or {@link ContentType#TEXT_PLAIN} if not specified. + * @param charset The content character encoding, or <js>"UTF-8"</js> if not specified. + * @return A new {@link StringEntity} object. + */ + public static StringEntity of(String content, ContentType contentType, Charset charset) { + return new StringEntity(content, contentType, null); + } + + /** + * Constructor. + * + * @param content The entity content. Can be <jk>null</jk>. + * @param contentType The entity content type, or {@link ContentType#TEXT_PLAIN} if not specified. + * @param charset The content character encoding, or <js>"UTF-8"</js> if not specified. + */ + public StringEntity(String content, ContentType contentType, Charset charset) { + this.content = emptyIfNull(content); + setContentType(contentType); + this.charset = charset; + } + + @Override + public byte[] asBytes() throws IOException { + cache(); + return bytes.get(); + } + + @Override /* AbstractHttpEntity */ + public StringEntity cache() { + getBytes(); + return this; + } + + @Override /* HttpEntity */ + public boolean isRepeatable() { + return true; + } + + @Override /* HttpEntity */ + public long getContentLength() { + long len = super.getContentLength(); + if (len == -1) { + len = getBytes().length; + contentLength(len); + } + return len; + } + + @Override /* HttpEntity */ + public InputStream getContent() throws IOException { + return new ByteArrayInputStream(getBytes()); + } + + @Override /* HttpEntity */ + public void writeTo(OutputStream out) throws IOException { + assertArgNotNull("out", out); + out.write(getBytes()); + out.flush(); + } + + @Override /* HttpEntity */ + public boolean isStreaming() { + return false; + } + + private byte[] getBytes() { + byte[] b = bytes.get(); + if (b == null) { + b = content.getBytes(charset == null ? IOUtils.UTF8 : charset); + bytes.set(b); + } + return b; + } +} + diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/MediaType.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/MediaType.java index 861a209..a37f226 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/MediaType.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/MediaType.java @@ -14,15 +14,14 @@ package org.apache.juneau.http.header; import static org.apache.juneau.internal.StringUtils.*; import static org.apache.juneau.internal.ObjectUtils.*; -import static org.apache.juneau.http.HttpParts.*; import static org.apache.juneau.http.header.Constants.*; +import static org.apache.juneau.http.HttpParts.*; import java.util.*; import org.apache.http.*; import org.apache.http.message.*; import org.apache.juneau.annotation.*; -import org.apache.juneau.collections.*; import org.apache.juneau.internal.*; import org.apache.juneau.json.*; @@ -104,6 +103,25 @@ public class MediaType implements Comparable<MediaType> { } /** + * Same as {@link #of(String)} but allows you to specify the parameters. + * + * + * @param value + * The media type string. + * Will be lowercased. + * Returns <jk>null</jk> if input is null or empty. + * @param parameters The media type parameters. If <jk>null</jk>, they're pulled from the media type string. + * @return A new media type object, cached if parameters were not specified. + */ + public static MediaType of(String value, NameValuePair...parameters) { + if (parameters.length == 0) + return of(value); + if (isEmpty(value)) + return null; + return new MediaType(value, parameters); + } + + /** * Same as {@link #of(String)} but allows you to construct an array of <c>MediaTypes</c> from an * array of strings. * @@ -132,18 +150,43 @@ public class MediaType implements Comparable<MediaType> { /** * Constructor. * + * @param mt The media type string. + * @param parameters The media type parameters. If <jk>null</jk>, they're pulled from the media type string. + */ + public MediaType(String mt, NameValuePair[] parameters) { + this(parse(mt), parameters); + } + + /** + * Constructor. + * * @param e The parsed media type string. */ public MediaType(HeaderElement e) { + this(e, null); + } + + /** + * Constructor. + * + * @param e The parsed media type string. + * @param parameters Optional parameters. + */ + public MediaType(HeaderElement e, NameValuePair[] parameters) { mediaType = e.getName(); - List<NameValuePair> parameters = AList.create(); - for (NameValuePair p : e.getParameters()) { - if (p.getName().equals("q")) - break; - parameters.add(stringPart(p.getName(), p.getValue())); + if (parameters == null) { + parameters = e.getParameters(); + for (int i = 0; i < parameters.length; i++) { + if (parameters[i].getName().equals("q")) { + parameters = Arrays.copyOfRange(parameters, 0, i); + break; + } + } } - this.parameters= parameters.toArray(new NameValuePair[parameters.size()]); + for (int i = 0; i < parameters.length; i++) + parameters[i] = stringPart(parameters[i].getName(), parameters[i].getValue()); + this.parameters = parameters; String x = mediaType.replace(' ', '+'); int i = x.indexOf('/'); diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpException.java index 279abdd..9bdfb15 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpException.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpException.java @@ -14,15 +14,14 @@ package org.apache.juneau.http.response; import static org.apache.juneau.assertions.Assertions.*; import static org.apache.juneau.internal.StringUtils.*; +import static org.apache.juneau.http.HttpEntities.*; -import java.io.*; import java.lang.reflect.*; import java.text.*; import java.util.*; import org.apache.http.*; import org.apache.http.Header; -import org.apache.http.entity.*; import org.apache.http.params.*; import org.apache.juneau.*; import org.apache.juneau.annotation.*; @@ -371,13 +370,8 @@ public class BasicHttpException extends BasicRuntimeException implements HttpRes @Override /* HttpMessage */ public HttpEntity getEntity() { // Constructing a StringEntity is somewhat expensive, so don't create it unless it's needed. - if (body == null) { - try { - String msg = getMessage(); - if (msg != null) - body = new StringEntity(msg); - } catch (UnsupportedEncodingException e) {} - } + if (body == null) + body = stringEntity(getMessage()); return body; } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java index 20039f3..864210b 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java @@ -13,13 +13,12 @@ package org.apache.juneau.http.response; import static org.apache.juneau.assertions.Assertions.*; +import static org.apache.juneau.http.HttpEntities.*; -import java.io.*; import java.util.*; import org.apache.http.*; import org.apache.http.Header; -import org.apache.http.entity.*; import org.apache.http.params.*; import org.apache.juneau.annotation.*; import org.apache.juneau.http.*; @@ -250,13 +249,8 @@ public class BasicHttpResponse implements HttpResponse { @Override /* HttpMessage */ public HttpEntity getEntity() { // Constructing a StringEntity is somewhat expensive, so don't create it unless it's needed. - if (body == null) { - try { - String msg = getStatusLine().getReasonPhrase(); - if (msg != null) - body = new StringEntity(msg); - } catch (UnsupportedEncodingException e) {} - } + if (body == null) + body = stringEntity(getStatusLine().getReasonPhrase()); return body; } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java index 316ba80..a907d5b 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java @@ -12,11 +12,11 @@ // *************************************************************************************************************************** package org.apache.juneau.http.response; -import java.io.*; +import static org.apache.juneau.http.HttpEntities.*; + import java.util.*; import org.apache.http.*; -import org.apache.http.entity.*; import org.apache.http.impl.*; import org.apache.juneau.*; import org.apache.juneau.http.*; @@ -392,9 +392,7 @@ public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRun * @return This object (for method chaining). */ public HttpExceptionBuilder<T> body(String value) { - try { - body(new StringEntity(value)); - } catch (UnsupportedEncodingException e) { /* Not possible */ } + body(stringEntity(value)); return this; } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java index 3c43891..055dedd 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java @@ -12,12 +12,12 @@ // *************************************************************************************************************************** package org.apache.juneau.http.response; -import java.io.*; +import static org.apache.juneau.http.HttpEntities.*; + import java.net.*; import java.util.*; import org.apache.http.*; -import org.apache.http.entity.*; import org.apache.http.impl.*; import org.apache.juneau.http.*; import org.apache.juneau.http.header.*; @@ -37,7 +37,7 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> { HeaderListBuilder headerListBuilder; HttpEntity body; boolean unmodifiable; - + private final Class<? extends BasicHttpResponse> implClass; /** @@ -424,10 +424,7 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> { * @return This object (for method chaining). */ public HttpResponseBuilder<T> body(String value) { - try { - body(new StringEntity(value)); - } catch (UnsupportedEncodingException e) { /* Not possible */ } - return this; + return body(stringEntity(value)); } /** diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/IOUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/IOUtils.java index ba58f97..f19195d 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/IOUtils.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/IOUtils.java @@ -29,6 +29,14 @@ public final class IOUtils { /** UTF-8 charset */ public static final Charset UTF8 = Charset.forName("UTF-8"); + /** Reusable empty input stream. */ + public static final InputStream EMPTY_INPUT_STREAM = new InputStream() { + @Override + public int read() { + return -1; // end of stream + } + }; + /** * Reads the contents of a file into a string. * diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java index aaca745..3183482 100644 --- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java +++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java @@ -43,8 +43,6 @@ import org.apache.http.client.entity.*; import org.apache.http.client.methods.*; import org.apache.http.client.utils.*; import org.apache.http.conn.*; -import org.apache.http.entity.*; -import org.apache.http.entity.BasicHttpEntity; import org.apache.http.impl.client.*; import org.apache.http.params.*; import org.apache.http.protocol.*; diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java index 6e4fefe..74520d3 100644 --- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java +++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java @@ -16,6 +16,7 @@ import static org.apache.juneau.internal.StringUtils.*; import static org.apache.juneau.internal.ClassUtils.*; import static org.apache.juneau.AddFlag.*; import static org.apache.juneau.httppart.HttpPartType.*; +import static org.apache.juneau.http.HttpEntities.*; import java.io.*; import java.lang.reflect.*; @@ -32,9 +33,7 @@ import org.apache.http.client.entity.*; import org.apache.http.client.methods.*; import org.apache.http.client.utils.*; import org.apache.http.concurrent.*; -import org.apache.http.entity.*; import org.apache.http.entity.BasicHttpEntity; -import org.apache.http.entity.ContentType; import org.apache.http.params.*; import org.apache.http.protocol.*; import org.apache.juneau.*; @@ -69,7 +68,7 @@ import org.apache.juneau.xml.*; */ public class RestRequest extends BeanSession implements HttpUriRequest, Configurable { - private static final ContentType TEXT_PLAIN = ContentType.create("text/plain"); + private static final ContentType TEXT_PLAIN = ContentType.TEXT_PLAIN; private final RestClient client; // The client that created this call. private final HttpRequestBase request; // The request. @@ -2906,9 +2905,9 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur else if (input2 instanceof HttpEntity) entity = (HttpEntity)input2; else if (input2 instanceof Reader) - entity = new StringEntity(IOUtils.read((Reader)input2), getRequestContentType(TEXT_PLAIN)); + entity = stringEntity(IOUtils.read((Reader)input2), getRequestContentType(TEXT_PLAIN), null); else if (input2 instanceof InputStream) - entity = new InputStreamEntity((InputStream)input2, getRequestContentType(ContentType.APPLICATION_OCTET_STREAM)); + entity = streamEntity((InputStream)input2, -1, getRequestContentType(ContentType.APPLICATION_OCTET_STREAM)); else if (serializer != null) entity = SerializedHttpEntity.of(input2, serializer).schema(requestBodySchema).contentType(contentType); else { @@ -2919,7 +2918,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur } if (input2 == null) input2 = ""; - entity = new StringEntity(BeanContext.DEFAULT.getClassMetaForObject(input2).toString(input2), getRequestContentType(TEXT_PLAIN)); + entity = stringEntity(BeanContext.DEFAULT.getClassMetaForObject(input2).toString(input2), getRequestContentType(TEXT_PLAIN), null); } request2.setEntity(entity); @@ -3465,7 +3464,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur if (h != null) { String s = h.getValue(); if (! isEmpty(s)) - return ContentType.create(s); + return ContentType.of(s); } return def; } diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_BasicCalls_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_BasicCalls_Test.java index 77a437b..9a340bd 100644 --- a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_BasicCalls_Test.java +++ b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_BasicCalls_Test.java @@ -15,6 +15,7 @@ package org.apache.juneau.rest.client; import static org.apache.juneau.assertions.Assertions.*; import static org.junit.runners.MethodSorters.*; import static org.apache.juneau.http.HttpParts.*; +import static org.apache.juneau.http.HttpEntities.*; import java.io.*; import java.net.*; @@ -23,7 +24,6 @@ import java.util.function.*; import org.apache.http.*; import org.apache.http.client.utils.*; -import org.apache.http.entity.*; import org.apache.juneau.collections.*; import org.apache.juneau.http.annotation.*; import org.apache.juneau.http.entity.*; @@ -34,6 +34,7 @@ import org.apache.juneau.rest.annotation.*; import org.apache.juneau.rest.mock.*; import org.apache.juneau.testutils.*; import org.junit.*; +import org.apache.juneau.http.header.ContentType; @FixMethodOrder(NAME_ASCENDING) public class RestClient_BasicCalls_Test { @@ -167,7 +168,7 @@ public class RestClient_BasicCalls_Test { new ByteArrayInputStream("{f:1}".getBytes()), BasicHttpResource.of("{f:1}"), bean, - new StringEntity("{f:1}"), + stringEntity("{f:1}"), parts("f",1) ); for (Object body : bodies) { @@ -210,7 +211,7 @@ public class RestClient_BasicCalls_Test { new ByteArrayInputStream("{f:1}".getBytes()), BasicHttpResource.of("{f:1}"), bean, - new StringEntity("{f:1}"), + stringEntity("{f:1}"), parts("f",1) ); for (Object body : bodies) { @@ -311,8 +312,8 @@ public class RestClient_BasicCalls_Test { /*[ 0]*/ bean, /*[ 1]*/ parts("f","1"), /*[ 2]*/ new NameValuePair[]{part("f","1")}, - /*[ 3]*/ new StringEntity("f=1",org.apache.http.entity.ContentType.APPLICATION_FORM_URLENCODED), - /*[ 4]*/ new StringEntity("f=1",(org.apache.http.entity.ContentType)null), + /*[ 3]*/ stringEntity("f=1", ContentType.APPLICATION_FORM_URLENCODED, null), + /*[ 4]*/ stringEntity("f=1", null, null), /*[ 5]*/ part("f","1"), /*[ 6]*/ BasicHttpResource.of("f=1"), /*[ 7]*/ BasicHttpResource.of("f=1"), @@ -350,7 +351,7 @@ public class RestClient_BasicCalls_Test { new ByteArrayInputStream("{f:1}".getBytes()), BasicHttpResource.of("{f:1}"), bean, - new StringEntity("{f:1}"), + stringEntity("{f:1}"), parts("f",1) ); RestClient x = client().build(); @@ -387,7 +388,7 @@ public class RestClient_BasicCalls_Test { new ByteArrayInputStream("{f:1}".getBytes()), BasicHttpResource.of("{f:1}"), bean, - new StringEntity("{f:1}"), + stringEntity("{f:1}"), parts("f",1) ); RestClient x = client().build();