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 d0eaf21f4d TODO-274: CRTP-convert the classic BasicResource hierarchy
(10.0.0 breaking change)
d0eaf21f4d is described below
commit d0eaf21f4daa8ad5fc45aebe3cd4d9030ec0177b
Author: James Bognar <[email protected]>
AuthorDate: Tue Jul 21 10:36:51 2026 -0400
TODO-274: CRTP-convert the classic BasicResource hierarchy (10.0.0 breaking
change)
Generify BasicResource into an abstract self-typed (CRTP) root
BasicResource<SELF extends BasicResource<SELF>> implements HttpResource,
mirroring
the already-shipped BasicHttpEntity<SELF> precedent. Each of the 5 leaves
(ByteArrayResource, FileResource, ReaderResource, StreamResource,
StringResource)
drops its 15 covariant narrowing-setter overrides (~75 total deleted) and
inherits
leaf-typed fluent setters for free.
Generifying makes the root effectively abstract, so ResponseContent now
materializes
HttpResource/BasicResource response bodies as a concrete StreamResource
(which IS-A
BasicResource), and StreamResource gained an HttpResponse constructor for
this. This
keeps the breaking surface narrow: .as(BasicResource.class) and @Remote
methods
declared to return BasicResource/HttpResource still work; only
direct/reflective
new BasicResource(...) instantiation breaks. BasicResource_Test's
direct-instantiation
sites were rebased onto concrete leaves.
Co-authored-by: Cursor <[email protected]>
---
.../rest/client/classic/ResponseContent.java | 8 +-
.../http/classic/resource/BasicResource.java | 136 +++++++++------------
.../http/classic/resource/ByteArrayResource.java | 98 +--------------
.../juneau/http/classic/resource/FileResource.java | 97 +--------------
.../http/classic/resource/ReaderResource.java | 97 +--------------
.../http/classic/resource/StreamResource.java | 105 ++--------------
.../http/classic/resource/StringResource.java | 98 +--------------
.../http/classic/resource/BasicResource_Test.java | 59 +++++----
8 files changed, 114 insertions(+), 584 deletions(-)
diff --git
a/juneau-rest/juneau-rest-client-classic/src/main/java/org/apache/juneau/rest/client/classic/ResponseContent.java
b/juneau-rest/juneau-rest-client-classic/src/main/java/org/apache/juneau/rest/client/classic/ResponseContent.java
index b6be172e19..41f3d19432 100644
---
a/juneau-rest/juneau-rest-client-classic/src/main/java/org/apache/juneau/rest/client/classic/ResponseContent.java
+++
b/juneau-rest/juneau-rest-client-classic/src/main/java/org/apache/juneau/rest/client/classic/ResponseContent.java
@@ -162,7 +162,7 @@ public class ResponseContent implements HttpEntity {
* <li>{@link ResponseContent}/{@link HttpEntity}
- Returns access to this object.
* <li>{@link Reader} - Returns access to the raw
reader of the response.
* <li>{@link InputStream} - Returns access to the
raw input stream of the response.
- * <li>{@link HttpResource} - Response will be
converted to an {@link BasicResource}.
+ * <li>{@link HttpResource} - Response will be
converted to a {@link StreamResource}.
* <li>Any type that takes in an {@link
HttpResponse} object.
* </ul>
* <li class='note'>
@@ -254,8 +254,8 @@ public class ResponseContent implements HttpEntity {
if (type.is(HttpResponse.class))
return (T)response;
- if (type.is(HttpResource.class))
- type =
(ClassMeta<T>)getClassMeta(BasicResource.class);
+ if (type.is(HttpResource.class) ||
type.is(BasicResource.class))
+ type =
(ClassMeta<T>)getClassMeta(StreamResource.class);
var result = type.getPublicConstructor(x ->
x.hasParameterTypes(HttpResponse.class)).map(ci -> safe(() ->
(T)ci.newInstance(response)));
if (result.isPresent())
@@ -429,7 +429,7 @@ public class ResponseContent implements HttpEntity {
* <li>{@link ResponseContent}/{@link HttpEntity}
- Returns access to this object.
* <li>{@link Reader} - Returns access to the raw
reader of the response.
* <li>{@link InputStream} - Returns access to the
raw input stream of the response.
- * <li>{@link HttpResource} - Response will be
converted to an {@link BasicResource}.
+ * <li>{@link HttpResource} - Response will be
converted to a {@link StreamResource}.
* <li>Any type that takes in an {@link
HttpResponse} object.
* </ul>
* <li class='note'>
diff --git
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/BasicResource.java
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/BasicResource.java
index 284a5e0a57..07adaa327e 100644
---
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/BasicResource.java
+++
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/BasicResource.java
@@ -44,16 +44,23 @@ import org.apache.juneau.test.assertions.*;
* Externally-supplied/dynamic content.
* </ul>
*
+ * <p>
+ * This is a self-typed (CRTP) root: a leaf declares <c>class StringResource
<jk>extends</jk> BasicResource<StringResource></c>
+ * and inherits leaf-typed fluent setters with no covariant overrides.
+ *
* <h5 class='section'>See Also:</h5><ul>
* <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common
Basics</a>
* </ul>
+ *
+ * @param <SELF> The self type for fluent setters.
*/
@BeanIgnore /* Use toString() to serialize */
@SuppressWarnings({
"resource", // Depends on entity (streams); value equality not practical
"java:S1206", // equals/hashCode not overridden; value equality not
practical for this class
+ "java:S119", // 'SELF' (CRTP self-type) is intentional and clearer than
a single-letter name.
})
-public class BasicResource implements HttpResource {
+public abstract class BasicResource<SELF extends BasicResource<SELF>>
implements HttpResource {
BasicHttpEntity<?> entity;
HeaderList headers = HeaderList.create();
@@ -71,7 +78,7 @@ public class BasicResource implements HttpResource {
*
* @param copyFrom The bean being copied. Must not be <jk>null</jk>.
*/
- public BasicResource(BasicResource copyFrom) {
+ public BasicResource(BasicResource<?> copyFrom) {
this.entity = copyFrom.entity.copy();
this.headers = copyFrom.headers.copy();
}
@@ -100,10 +107,10 @@ public class BasicResource implements HttpResource {
* @param value The header value.
* @return This object.
*/
- public BasicResource addHeader(String name, String value) {
+ public SELF addHeader(String name, String value) {
if (nn(name) && nn(value))
headers.append(name, value);
- return this;
+ return self();
}
/**
@@ -112,7 +119,7 @@ public class BasicResource implements HttpResource {
* @param values The headers to set. <jk>null</jk> headers and headers
with <jk>null</jk> names or values are ignored.
* @return This object.
*/
- public BasicResource addHeaders(Header...values) {
+ public SELF addHeaders(Header...values) {
for (var h : values) {
if (nn(h)) {
var n = h.getName();
@@ -129,7 +136,7 @@ public class BasicResource implements HttpResource {
}
}
}
- return this;
+ return self();
}
/**
@@ -154,7 +161,7 @@ public class BasicResource implements HttpResource {
* @return A new fluent assertion.
* @throws IOException If a problem occurred while trying to read the
byte array.
*/
- public FluentByteArrayAssertion<BasicResource> assertBytes() throws
IOException {
+ public FluentByteArrayAssertion<BasicResource<?>> assertBytes() throws
IOException {
return new FluentByteArrayAssertion<>(asBytes(), this);
}
@@ -167,7 +174,7 @@ public class BasicResource implements HttpResource {
* @return A new fluent assertion.
* @throws IOException If a problem occurred while trying to read the
byte array.
*/
- public FluentStringAssertion<BasicResource> assertString() throws
IOException {
+ public FluentStringAssertion<BasicResource<?>> assertString() throws
IOException {
return new FluentStringAssertion<>(asString(), this);
}
@@ -197,9 +204,7 @@ public class BasicResource implements HttpResource {
*
* @return A new builder bean.
*/
- public BasicResource copy() {
- return new BasicResource(this);
- }
+ public abstract SELF copy();
/**
* Copies the contents of the specified HTTP response to this builder.
@@ -208,11 +213,11 @@ public class BasicResource implements HttpResource {
* @return This object.
* @throws IOException If content could not be retrieved.
*/
- public BasicResource copyFrom(HttpResponse response) throws IOException
{
+ public SELF copyFrom(HttpResponse response) throws IOException {
assertArgNotNull("response", response);
addHeaders(response.getAllHeaders());
setContent(response.getEntity().getContent());
- return this;
+ return self();
}
@Override /* Overridden from HttpEntity */
@@ -260,9 +265,9 @@ public class BasicResource implements HttpResource {
* @return This object.
* @throws IOException If entity could not be read into memory.
*/
- public BasicResource setCached() throws IOException {
+ public SELF setCached() throws IOException {
entity.setCached();
- return this;
+ return self();
}
/**
@@ -275,9 +280,9 @@ public class BasicResource implements HttpResource {
*
* @return This object.
*/
- public BasicResource setChunked() {
+ public SELF setChunked() {
entity.setChunked();
- return this;
+ return self();
}
/**
@@ -291,9 +296,9 @@ public class BasicResource implements HttpResource {
* @param value The new value for this flag.
* @return This object.
*/
- public BasicResource setChunked(boolean value) {
+ public SELF setChunked(boolean value) {
entity.setChunked(value);
- return this;
+ return self();
}
/**
@@ -302,9 +307,9 @@ public class BasicResource implements HttpResource {
* @param value The entity content, can be <jk>null</jk>.
* @return This object.
*/
- public BasicResource setContent(Object value) {
+ public SELF setContent(Object value) {
entity.setContent(value);
- return this;
+ return self();
}
/**
@@ -317,9 +322,9 @@ public class BasicResource implements HttpResource {
* @param value The entity content, can be <jk>null</jk>.
* @return This object.
*/
- public BasicResource setContent(Supplier<?> value) {
+ public SELF setContent(Supplier<?> value) {
entity.setContent(value);
- return this;
+ return self();
}
/**
@@ -328,9 +333,9 @@ public class BasicResource implements HttpResource {
* @param value The new <c>Content-Encoding</c> header, or
<jk>null</jk> to unset.
* @return This object.
*/
- public BasicResource setContentEncoding(ContentEncoding value) {
+ public SELF setContentEncoding(ContentEncoding value) {
entity.setContentEncoding(value);
- return this;
+ return self();
}
/**
@@ -339,9 +344,9 @@ public class BasicResource implements HttpResource {
* @param value The new <c>Content-Encoding</c> header, or
<jk>null</jk> to unset.
* @return This object.
*/
- public BasicResource setContentEncoding(String value) {
+ public SELF setContentEncoding(String value) {
entity.setContentEncoding(value);
- return this;
+ return self();
}
/**
@@ -350,9 +355,9 @@ public class BasicResource implements HttpResource {
* @param value The new <c>Content-Length</c> header value, or
<c>-1</c> to unset.
* @return This object.
*/
- public BasicResource setContentLength(long value) {
+ public SELF setContentLength(long value) {
entity.setContentLength(value);
- return this;
+ return self();
}
/**
@@ -361,9 +366,9 @@ public class BasicResource implements HttpResource {
* @param value The new <c>Content-Type</c> header, or <jk>null</jk> to
unset.
* @return This object.
*/
- public BasicResource setContentType(ContentType value) {
+ public SELF setContentType(ContentType value) {
entity.setContentType(value);
- return this;
+ return self();
}
/**
@@ -372,9 +377,9 @@ public class BasicResource implements HttpResource {
* @param value The new <c>Content-Type</c> header, or <jk>null</jk> to
unset.
* @return This object.
*/
- public BasicResource setContentType(String value) {
+ public SELF setContentType(String value) {
entity.setContentType(value);
- return this;
+ return self();
}
/**
@@ -387,10 +392,10 @@ public class BasicResource implements HttpResource {
* @param value The header value.
* @return This object.
*/
- public BasicResource setHeader(String name, String value) {
+ public SELF setHeader(String name, String value) {
if (nn(name) && nn(value))
headers.set(name, value);
- return this;
+ return self();
}
/**
@@ -399,7 +404,7 @@ public class BasicResource implements HttpResource {
* @param values The headers to add. <jk>null</jk> values are ignored.
* @return This object.
*/
- public BasicResource setHeaders(Header...values) {
+ public SELF setHeaders(Header...values) {
for (var h : values) {
if (nn(h)) {
var n = h.getName();
@@ -416,7 +421,7 @@ public class BasicResource implements HttpResource {
}
}
}
- return this;
+ return self();
}
/**
@@ -425,7 +430,7 @@ public class BasicResource implements HttpResource {
* @param value The new value. Must not be <jk>null</jk>.
* @return This object.
*/
- public BasicResource setHeaders(HeaderList value) {
+ public SELF setHeaders(HeaderList value) {
return modify(() -> headers = value.copy());
}
@@ -437,33 +442,41 @@ public class BasicResource implements HttpResource {
*
* @return An unmodifiable snapshot of this bean, or this bean if it is
already unmodifiable.
*/
- public BasicResource unmodifiable() {
- return this instanceof UnmodifiableBean ? this : new
Unmodifiable(this);
- }
+ public abstract SELF unmodifiable();
@Override /* Overridden from HttpEntity */
public void writeTo(OutputStream outStream) throws IOException {
entity.writeTo(outStream);
}
+ /**
+ * Returns this object cast to the self type.
+ *
+ * @return This object.
+ */
+ @SuppressWarnings({
+ "unchecked" // CRTP self-type cast is safe: SELF is bound to
the concrete leaf type.
+ })
+ protected final SELF self() { return (SELF) this; }
+
/**
* Single mutation funnel for direct-field state changes on this bean.
*
* <p>
- * The nested {@link Unmodifiable} snapshot overrides this method to
throw. Mutators that delegate to the entity or
- * header sub-beans are frozen by the {@link #freeze()} deep-freeze of
those sub-beans; this funnel additionally
- * covers the direct-field {@link #setHeaders(HeaderList)} reassignment.
+ * Each leaf's nested {@code Unmodifiable} snapshot overrides this
method to throw. Mutators that delegate to the
+ * entity or header sub-beans are frozen by the {@link #freeze()}
deep-freeze of those sub-beans; this funnel
+ * additionally covers the direct-field {@link #setHeaders(HeaderList)}
reassignment.
*
* @param mutation The state change to apply.
* @return This object.
*/
- protected BasicResource modify(Runnable mutation) {
+ protected SELF modify(Runnable mutation) {
mutation.run();
- return this;
+ return self();
}
/**
- * Deep-freeze hook invoked from the nested {@link Unmodifiable}
constructor after the snapshot copy completes.
+ * Deep-freeze hook invoked from a leaf's nested {@code Unmodifiable}
constructor after the snapshot copy completes.
*
* <p>
* The mutable sub-beans are frozen here by <b>direct field
assignment</b> (never via a setter, which would route
@@ -473,33 +486,4 @@ public class BasicResource implements HttpResource {
entity = entity.unmodifiable(); // DIRECT field write —
snapshot the copied entity.
headers = headers.unmodifiable(); // DIRECT field write —
snapshot the copied HeaderList.
}
-
- /**
- * An unmodifiable snapshot of a {@link BasicResource}.
- *
- * <p>
- * Its behavioral override is a throwing {@link #modify(Runnable)}, and
its constructor deep-freezes the entity and
- * header sub-beans via {@link #freeze()}. Together these freeze the
entire mutation surface: direct-field mutators
- * throw through {@code modify(...)}, and sub-bean-delegating mutators
throw through the frozen entity/headers.
- */
- public static class Unmodifiable extends BasicResource implements
UnmodifiableBean {
-
- /**
- * Constructor.
- *
- * @param copyFrom The bean to snapshot-copy. Must not be
<jk>null</jk>.
- */
- @SuppressWarnings({
- "java:S1699" // Paradigm intentionally calls the
overridable freeze() from the ctor to deep-freeze sub-beans.
- })
- protected Unmodifiable(BasicResource copyFrom) {
- super(copyFrom);
- freeze();
- }
-
- @Override /* Overridden from BasicResource */
- protected BasicResource modify(Runnable mutation) {
- throw uoex("Bean is unmodifiable.");
- }
- }
}
\ No newline at end of file
diff --git
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/ByteArrayResource.java
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/ByteArrayResource.java
index 238b69e63c..b5c8935569 100644
---
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/ByteArrayResource.java
+++
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/ByteArrayResource.java
@@ -18,10 +18,6 @@ package org.apache.juneau.http.classic.resource;
import static org.apache.juneau.commons.utils.Shorts.*;
-import java.io.*;
-import java.util.function.*;
-
-import org.apache.http.*;
import org.apache.juneau.http.UnmodifiableBean;
import org.apache.juneau.http.classic.entity.*;
import org.apache.juneau.http.classic.header.*;
@@ -33,7 +29,7 @@ import org.apache.juneau.http.classic.header.*;
* <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common
Basics</a>
* </ul>
*/
-public class ByteArrayResource extends BasicResource {
+public class ByteArrayResource extends BasicResource<ByteArrayResource> {
/**
* Constructor.
@@ -62,100 +58,10 @@ public class ByteArrayResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- public ByteArrayResource addHeader(String name, String value) {
- super.addHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource addHeaders(Header...values) {
- super.addHeaders(values);
- return this;
- }
-
- @Override
public ByteArrayResource copy() {
return new ByteArrayResource(this);
}
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setCached() throws IOException {
- super.setCached();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setChunked() {
- super.setChunked();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setChunked(boolean value) {
- super.setChunked(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setContent(Object value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setContent(Supplier<?> value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setContentEncoding(ContentEncoding value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setContentEncoding(String value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setContentLength(long value) {
- super.setContentLength(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setContentType(ContentType value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setContentType(String value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setHeader(String name, String value) {
- super.setHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setHeaders(Header...values) {
- super.setHeaders(values);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ByteArrayResource setHeaders(HeaderList value) {
- super.setHeaders(value);
- return this;
- }
-
@Override /* Overridden from BasicResource */
public ByteArrayResource unmodifiable() {
return this instanceof UnmodifiableBean ? this : new
Unmodifiable(this);
@@ -180,7 +86,7 @@ public class ByteArrayResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- protected BasicResource modify(Runnable mutation) {
+ protected ByteArrayResource modify(Runnable mutation) {
throw uoex("Bean is unmodifiable.");
}
}
diff --git
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/FileResource.java
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/FileResource.java
index c4eb9d9ddd..7920b55fe4 100644
---
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/FileResource.java
+++
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/FileResource.java
@@ -19,9 +19,6 @@ package org.apache.juneau.http.classic.resource;
import static org.apache.juneau.commons.utils.Shorts.*;
import java.io.*;
-import java.util.function.*;
-
-import org.apache.http.*;
import org.apache.juneau.http.UnmodifiableBean;
import org.apache.juneau.http.classic.entity.*;
import org.apache.juneau.http.classic.header.*;
@@ -33,7 +30,7 @@ import org.apache.juneau.http.classic.header.*;
* <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common
Basics</a>
* </ul>
*/
-public class FileResource extends BasicResource {
+public class FileResource extends BasicResource<FileResource> {
/**
* Constructor.
@@ -62,100 +59,10 @@ public class FileResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- public FileResource addHeader(String name, String value) {
- super.addHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource addHeaders(Header...values) {
- super.addHeaders(values);
- return this;
- }
-
- @Override
public FileResource copy() {
return new FileResource(this);
}
- @Override /* Overridden from BasicResource */
- public FileResource setCached() throws IOException {
- super.setCached();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setChunked() {
- super.setChunked();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setChunked(boolean value) {
- super.setChunked(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setContent(Object value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setContent(Supplier<?> value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setContentEncoding(ContentEncoding value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setContentEncoding(String value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setContentLength(long value) {
- super.setContentLength(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setContentType(ContentType value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setContentType(String value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setHeader(String name, String value) {
- super.setHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setHeaders(Header...values) {
- super.setHeaders(values);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public FileResource setHeaders(HeaderList value) {
- super.setHeaders(value);
- return this;
- }
-
@Override /* Overridden from BasicResource */
public FileResource unmodifiable() {
return this instanceof UnmodifiableBean ? this : new
Unmodifiable(this);
@@ -180,7 +87,7 @@ public class FileResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- protected BasicResource modify(Runnable mutation) {
+ protected FileResource modify(Runnable mutation) {
throw uoex("Bean is unmodifiable.");
}
}
diff --git
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/ReaderResource.java
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/ReaderResource.java
index 1fdf757d55..a474eb2b71 100644
---
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/ReaderResource.java
+++
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/ReaderResource.java
@@ -19,9 +19,6 @@ package org.apache.juneau.http.classic.resource;
import static org.apache.juneau.commons.utils.Shorts.*;
import java.io.*;
-import java.util.function.*;
-
-import org.apache.http.*;
import org.apache.juneau.http.UnmodifiableBean;
import org.apache.juneau.http.classic.entity.*;
import org.apache.juneau.http.classic.header.*;
@@ -33,7 +30,7 @@ import org.apache.juneau.http.classic.header.*;
* <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common
Basics</a>
* </ul>
*/
-public class ReaderResource extends BasicResource {
+public class ReaderResource extends BasicResource<ReaderResource> {
/**
* Constructor.
@@ -62,100 +59,10 @@ public class ReaderResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- public ReaderResource addHeader(String name, String value) {
- super.addHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource addHeaders(Header...values) {
- super.addHeaders(values);
- return this;
- }
-
- @Override
public ReaderResource copy() {
return new ReaderResource(this);
}
- @Override /* Overridden from BasicResource */
- public ReaderResource setCached() throws IOException {
- super.setCached();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setChunked() {
- super.setChunked();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setChunked(boolean value) {
- super.setChunked(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setContent(Object value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setContent(Supplier<?> value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setContentEncoding(ContentEncoding value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setContentEncoding(String value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setContentLength(long value) {
- super.setContentLength(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setContentType(ContentType value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setContentType(String value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setHeader(String name, String value) {
- super.setHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setHeaders(Header...values) {
- super.setHeaders(values);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public ReaderResource setHeaders(HeaderList value) {
- super.setHeaders(value);
- return this;
- }
-
@Override /* Overridden from BasicResource */
public ReaderResource unmodifiable() {
return this instanceof UnmodifiableBean ? this : new
Unmodifiable(this);
@@ -180,7 +87,7 @@ public class ReaderResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- protected BasicResource modify(Runnable mutation) {
+ protected ReaderResource modify(Runnable mutation) {
throw uoex("Bean is unmodifiable.");
}
}
diff --git
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/StreamResource.java
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/StreamResource.java
index b100855bd1..96375ee4d4 100644
---
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/StreamResource.java
+++
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/StreamResource.java
@@ -19,8 +19,6 @@ package org.apache.juneau.http.classic.resource;
import static org.apache.juneau.commons.utils.Shorts.*;
import java.io.*;
-import java.util.function.*;
-
import org.apache.http.*;
import org.apache.juneau.http.UnmodifiableBean;
import org.apache.juneau.http.classic.entity.*;
@@ -33,7 +31,7 @@ import org.apache.juneau.http.classic.header.*;
* <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common
Basics</a>
* </ul>
*/
-public class StreamResource extends BasicResource {
+public class StreamResource extends BasicResource<StreamResource> {
/**
* Constructor.
@@ -61,101 +59,24 @@ public class StreamResource extends BasicResource {
super(copyFrom);
}
- @Override /* Overridden from BasicResource */
- public StreamResource addHeader(String name, String value) {
- super.addHeader(name, value);
- return this;
+ /**
+ * Constructor.
+ *
+ * <p>
+ * This is the constructor used when converting an HTTP response into a
resource.
+ *
+ * @param response The HTTP response to copy from. Must not be
<jk>null</jk>.
+ * @throws IOException Rethrown from {@link HttpEntity#getContent()}.
+ */
+ public StreamResource(HttpResponse response) throws IOException {
+ super(response);
}
@Override /* Overridden from BasicResource */
- public StreamResource addHeaders(Header...values) {
- super.addHeaders(values);
- return this;
- }
-
- @Override
public StreamResource copy() {
return new StreamResource(this);
}
- @Override /* Overridden from BasicResource */
- public StreamResource setCached() throws IOException {
- super.setCached();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setChunked() {
- super.setChunked();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setChunked(boolean value) {
- super.setChunked(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setContent(Object value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setContent(Supplier<?> value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setContentEncoding(ContentEncoding value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setContentEncoding(String value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setContentLength(long value) {
- super.setContentLength(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setContentType(ContentType value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setContentType(String value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setHeader(String name, String value) {
- super.setHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setHeaders(Header...values) {
- super.setHeaders(values);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StreamResource setHeaders(HeaderList value) {
- super.setHeaders(value);
- return this;
- }
-
@Override /* Overridden from BasicResource */
public StreamResource unmodifiable() {
return this instanceof UnmodifiableBean ? this : new
Unmodifiable(this);
@@ -180,7 +101,7 @@ public class StreamResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- protected BasicResource modify(Runnable mutation) {
+ protected StreamResource modify(Runnable mutation) {
throw uoex("Bean is unmodifiable.");
}
}
diff --git
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/StringResource.java
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/StringResource.java
index 93dff6340f..7504238683 100644
---
a/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/StringResource.java
+++
b/juneau-rest/juneau-rest-common-classic/src/main/java/org/apache/juneau/http/classic/resource/StringResource.java
@@ -18,10 +18,6 @@ package org.apache.juneau.http.classic.resource;
import static org.apache.juneau.commons.utils.Shorts.*;
-import java.io.*;
-import java.util.function.*;
-
-import org.apache.http.*;
import org.apache.juneau.http.UnmodifiableBean;
import org.apache.juneau.http.classic.entity.*;
import org.apache.juneau.http.classic.header.*;
@@ -33,7 +29,7 @@ import org.apache.juneau.http.classic.header.*;
* <li class='link'><a class="doclink"
href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common
Basics</a>
* </ul>
*/
-public class StringResource extends BasicResource {
+public class StringResource extends BasicResource<StringResource> {
/**
* Constructor.
@@ -62,100 +58,10 @@ public class StringResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- public StringResource addHeader(String name, String value) {
- super.addHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource addHeaders(Header...values) {
- super.addHeaders(values);
- return this;
- }
-
- @Override
public StringResource copy() {
return new StringResource(this);
}
- @Override /* Overridden from BasicResource */
- public StringResource setCached() throws IOException {
- super.setCached();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setChunked() {
- super.setChunked();
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setChunked(boolean value) {
- super.setChunked(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setContent(Object value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setContent(Supplier<?> value) {
- super.setContent(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setContentEncoding(ContentEncoding value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setContentEncoding(String value) {
- super.setContentEncoding(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setContentLength(long value) {
- super.setContentLength(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setContentType(ContentType value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setContentType(String value) {
- super.setContentType(value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setHeader(String name, String value) {
- super.setHeader(name, value);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setHeaders(Header...values) {
- super.setHeaders(values);
- return this;
- }
-
- @Override /* Overridden from BasicResource */
- public StringResource setHeaders(HeaderList value) {
- super.setHeaders(value);
- return this;
- }
-
@Override /* Overridden from BasicResource */
public StringResource unmodifiable() {
return this instanceof UnmodifiableBean ? this : new
Unmodifiable(this);
@@ -180,7 +86,7 @@ public class StringResource extends BasicResource {
}
@Override /* Overridden from BasicResource */
- protected BasicResource modify(Runnable mutation) {
+ protected StringResource modify(Runnable mutation) {
throw uoex("Bean is unmodifiable.");
}
}
diff --git
a/juneau-rest/juneau-rest-common-classic/src/test/java/org/apache/juneau/http/classic/resource/BasicResource_Test.java
b/juneau-rest/juneau-rest-common-classic/src/test/java/org/apache/juneau/http/classic/resource/BasicResource_Test.java
index f153ef7fc8..0ed9b7b153 100644
---
a/juneau-rest/juneau-rest-common-classic/src/test/java/org/apache/juneau/http/classic/resource/BasicResource_Test.java
+++
b/juneau-rest/juneau-rest-common-classic/src/test/java/org/apache/juneau/http/classic/resource/BasicResource_Test.java
@@ -25,7 +25,6 @@ import java.io.*;
import org.apache.http.*;
import org.apache.http.message.*;
import org.apache.juneau.*;
-import org.apache.juneau.http.classic.entity.*;
import org.apache.juneau.http.classic.header.*;
import org.junit.jupiter.api.*;
@@ -40,7 +39,7 @@ class BasicResource_Test extends TestBase {
//------------------------------------------------------------------------------------------------------------------
@Test void a01_constructor_entity() throws Exception {
- var x = new BasicResource(new
StringEntity(contentType("text/plain"), "foo"));
+ var x = new StringResource(contentType("text/plain"), "foo");
assertEquals("foo", toUtf8(x.getContent()));
assertEquals("text/plain", x.getContentType().getValue());
assertNotNull(x.getEntity());
@@ -48,9 +47,9 @@ class BasicResource_Test extends TestBase {
}
@Test void a02_constructor_copy() throws Exception {
- var src = new BasicResource(new
StringEntity(contentType("text/plain"), "foo"))
+ var src = new StringResource(contentType("text/plain"), "foo")
.setHeader("Foo", "bar");
- var x = new BasicResource(src);
+ var x = new StringResource(src);
assertNotSame(src, x);
assertEquals("foo", toUtf8(x.getContent()));
assertEquals("text/plain", x.getContentType().getValue());
@@ -64,7 +63,7 @@ class BasicResource_Test extends TestBase {
resp.addHeader("Content-Type", "text/plain");
resp.addHeader("Content-Encoding", "identity");
resp.addHeader("Content-Length", "5");
- var x = new BasicResource(resp);
+ var x = new StreamResource(resp);
assertEquals("hello", toUtf8(x.getContent()));
assertEquals("bar",
x.getHeaders().getFirst("X-Foo").get().getValue());
assertEquals("text/plain", x.getContentType().getValue());
@@ -77,7 +76,7 @@ class BasicResource_Test extends TestBase {
//------------------------------------------------------------------------------------------------------------------
@Test void b01_addHeader_basic() {
- var x = new BasicResource(new StringEntity(null, "foo"))
+ var x = new StringResource(null, "foo")
.addHeader("Foo", "bar")
.addHeader("Foo", "baz")
.setHeader("Qux", "quux");
@@ -88,7 +87,7 @@ class BasicResource_Test extends TestBase {
}
@Test void b02_addHeader_nullSafe() {
- var x = new BasicResource(new StringEntity(null, "foo"))
+ var x = new StringResource(null, "foo")
.addHeader(null, "bar")
.addHeader("Foo", null)
.setHeader(null, "x")
@@ -97,7 +96,7 @@ class BasicResource_Test extends TestBase {
}
@Test void b03_addHeaders_specialHeaders() {
- var x = new BasicResource(new StringEntity(null, "foo"))
+ var x = new StringResource(null, "foo")
.addHeaders(
header("Content-Type", "text/plain"),
header("Content-Encoding", "identity"),
@@ -113,7 +112,7 @@ class BasicResource_Test extends TestBase {
}
@Test void b04_setHeaders_specialHeaders() {
- var x = new BasicResource(new StringEntity(null, "foo"))
+ var x = new StringResource(null, "foo")
.setHeaders(
header("Content-Type", "text/plain"),
header("Content-Encoding", "identity"),
@@ -130,7 +129,7 @@ class BasicResource_Test extends TestBase {
@Test void b05_setHeaders_headerList() {
var hl = HeaderList.create().append("Foo", "bar");
- var x = new BasicResource(new StringEntity(null, "foo"))
+ var x = new StringResource(null, "foo")
.setHeaders(hl);
assertEquals("bar",
x.getHeaders().getFirst("Foo").get().getValue());
}
@@ -140,47 +139,47 @@ class BasicResource_Test extends TestBase {
//------------------------------------------------------------------------------------------------------------------
@Test void c01_setContent_value() throws Exception {
- var x = new BasicResource(new StringEntity(null, "old"))
+ var x = new StringResource(null, "old")
.setContent("new");
assertEquals("new", toUtf8(x.getContent()));
}
@Test void c02_setContent_supplier() throws Exception {
- var x = new BasicResource(new StringEntity(null, null))
+ var x = new StringResource(null, null)
.setContent(() -> "newish");
assertEquals("newish", toUtf8(x.getContent()));
}
@Test void c03_setContentType_string_andContentType() {
- var x = new BasicResource(new StringEntity(null, "foo"))
+ var x = new StringResource(null, "foo")
.setContentType("text/plain");
assertEquals("text/plain", x.getContentType().getValue());
- var x2 = new BasicResource(new StringEntity(null, "foo"))
+ var x2 = new StringResource(null, "foo")
.setContentType(contentType("text/html"));
assertEquals("text/html", x2.getContentType().getValue());
}
@Test void c04_setContentEncoding_string_andContentEncoding() {
- var x = new BasicResource(new StringEntity(null, "foo"))
+ var x = new StringResource(null, "foo")
.setContentEncoding("identity");
assertEquals("identity", x.getContentEncoding().getValue());
- var x2 = new BasicResource(new StringEntity(null, "foo"))
+ var x2 = new StringResource(null, "foo")
.setContentEncoding(contentEncoding("gzip"));
assertEquals("gzip", x2.getContentEncoding().getValue());
}
@Test void c05_setContentLength() {
- var x = new BasicResource(new StringEntity(null, "foo"))
+ var x = new StringResource(null, "foo")
.setContentLength(10L);
assertEquals(10L, x.getContentLength());
}
@Test void c06_chunked() {
- var x = new BasicResource(new StringEntity(null,
"foo")).setChunked();
+ var x = new StringResource(null, "foo").setChunked();
assertTrue(x.isChunked());
- var x2 = new BasicResource(new StringEntity(null,
"foo")).setChunked(false);
+ var x2 = new StringResource(null, "foo").setChunked(false);
assertFalse(x2.isChunked());
}
@@ -189,7 +188,7 @@ class BasicResource_Test extends TestBase {
//------------------------------------------------------------------------------------------------------------------
@Test void d01_setCached_andRepeatable() throws Exception {
- var x = new BasicResource(new StringEntity(null,
"foo")).setCached();
+ var x = new StringResource(null, "foo").setCached();
assertEquals("foo", toUtf8(x.getContent()));
assertEquals("foo", toUtf8(x.getContent()));
assertTrue(x.isRepeatable());
@@ -197,19 +196,19 @@ class BasicResource_Test extends TestBase {
}
@Test void d02_asBytes_asString() throws Exception {
- var x = new BasicResource(new StringEntity(null, "hello"));
+ var x = new StringResource(null, "hello");
assertEquals("hello", new String(x.asBytes()));
assertEquals("hello", x.asString());
}
@Test void d03_assertBytes_assertString() throws Exception {
- var x = new BasicResource(new StringEntity(null, "abc"));
+ var x = new StringResource(null, "abc");
assertNotNull(x.assertBytes());
assertNotNull(x.assertString());
}
@Test void d04_copy_method() throws Exception {
- var x = new BasicResource(new
StringEntity(contentType("text/plain"), "foo"))
+ var x = new StringResource(contentType("text/plain"), "foo")
.setHeader("Foo", "bar");
var x2 = x.copy();
assertNotSame(x, x2);
@@ -219,14 +218,14 @@ class BasicResource_Test extends TestBase {
}
@Test void d05_writeTo() throws Exception {
- var x = new BasicResource(new StringEntity(null, "writeMe"));
+ var x = new StringResource(null, "writeMe");
var out = new ByteArrayOutputStream();
x.writeTo(out);
assertEquals("writeMe", out.toString("UTF-8"));
}
@Test void d06_consumeContent() {
- var x = new BasicResource(new StringEntity(null, "foo"));
+ var x = new StringResource(null, "foo");
// consumeContent() is a no-op that must complete without
throwing.
assertDoesNotThrow(x::consumeContent);
}
@@ -236,12 +235,12 @@ class BasicResource_Test extends TestBase {
//------------------------------------------------------------------------------------------------------------------
@Test void e01_isUnmodifiable_default() {
- var x = new BasicResource(new StringEntity(null, "foo"));
+ var x = new StringResource(null, "foo");
assertFalse(x.isUnmodifiable());
}
@Test void e02_unmodifiable_returnsFrozenSnapshot() {
- var x = new BasicResource(new StringEntity(null, "foo"));
+ var x = new StringResource(null, "foo");
var u = x.unmodifiable();
assertFalse(x.isUnmodifiable());
assertTrue(u.isUnmodifiable());
@@ -256,13 +255,13 @@ class BasicResource_Test extends TestBase {
}
@Test void e03_unmodifiable_idempotent() {
- var u = new BasicResource(new StringEntity(null,
"foo")).unmodifiable();
+ var u = new StringResource(null, "foo").unmodifiable();
// D1 idempotency: unmodifiable() on an already-unmodifiable
snapshot returns the same instance.
assertSame(u, u.unmodifiable());
}
@Test void e04_unmodifiable_snapshotIndependence() {
- var x = new BasicResource(new StringEntity(null,
"foo")).addHeader("X-A", "a");
+ var x = new StringResource(null, "foo").addHeader("X-A", "a");
var u = x.unmodifiable();
var before = u.getHeaders().size();
x.addHeader("X-B", "b"); // Mutate original after snapshotting.
@@ -274,7 +273,7 @@ class BasicResource_Test extends TestBase {
//------------------------------------------------------------------------------------------------------------------
@Test void f01_fluentReturns() {
- var x = new BasicResource(new StringEntity(null, "foo"));
+ var x = new StringResource(null, "foo");
assertSame(x, x.addHeader("X-A", "a"));
assertSame(x, x.setHeader("X-B", "b"));
assertSame(x, x.addHeaders(header("X-C", "c")));