001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.http.entity;
014
015import static org.apache.juneau.common.internal.ArgUtils.*;
016import static org.apache.juneau.common.internal.IOUtils.*;
017
018import java.io.*;
019import java.nio.charset.*;
020import java.util.Objects;
021import java.util.function.*;
022
023import org.apache.juneau.http.header.*;
024import org.apache.juneau.internal.*;
025
026/**
027 * A streamed, non-repeatable entity that obtains its content from an {@link Reader}.
028 *
029 * <h5 class='section'>See Also:</h5><ul>
030 *    <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-common">juneau-rest-common</a>
031 * </ul>
032 */
033@FluentSetters
034public class ReaderEntity extends BasicHttpEntity {
035
036   //-----------------------------------------------------------------------------------------------------------------
037   // Instance
038   //-----------------------------------------------------------------------------------------------------------------
039
040   private byte[] byteCache;
041   private String stringCache;
042
043   /**
044    * Constructor.
045    */
046   public ReaderEntity() {
047   }
048
049   /**
050    * Constructor.
051    *
052    * @param contentType The entity content type.
053    * @param content The entity contents.
054    */
055   public ReaderEntity(ContentType contentType, Reader content) {
056      super(contentType, content);
057   }
058
059   /**
060    * Copy constructor.
061    *
062    * @param copyFrom The bean being copied.
063    */
064   protected ReaderEntity(ReaderEntity copyFrom) {
065      super(copyFrom);
066   }
067
068   @Override
069   public ReaderEntity copy() {
070      return new ReaderEntity(this);
071   }
072
073   //-----------------------------------------------------------------------------------------------------------------
074   // Other methods
075   //-----------------------------------------------------------------------------------------------------------------
076
077   @SuppressWarnings("resource") // Caller closes
078    private Reader content() {
079      return Objects.requireNonNull(contentOrElse((Reader) null), "Reader is null.");
080   }
081
082   @Override /* AbstractHttpEntity */
083   public String asString() throws IOException {
084      if (isCached() && stringCache == null)
085         stringCache = read(content(), getMaxLength());
086      if (stringCache != null)
087         return stringCache;
088      return read(content());
089   }
090
091   @Override /* AbstractHttpEntity */
092   public byte[] asBytes() throws IOException {
093      if (isCached() && byteCache == null)
094         byteCache = readBytes(content());
095      if (byteCache != null)
096         return byteCache;
097      return readBytes(content());
098   }
099
100   @Override /* HttpEntity */
101   public boolean isRepeatable() {
102      return isCached();
103   }
104
105   @Override /* HttpEntity */
106   public long getContentLength() {
107      if (isCached())
108         return asSafeBytes().length;
109      return super.getContentLength();
110   }
111
112   @Override /* HttpEntity */
113   public InputStream getContent() throws IOException {
114      if (isCached())
115         return new ByteArrayInputStream(asBytes());
116      return new ReaderInputStream(content(), getCharset());
117   }
118
119   /**
120    * Writes bytes from the {@code InputStream} this entity was constructed
121    * with to an {@code OutputStream}.  The content length
122    * determines how many bytes are written.  If the length is unknown ({@code -1}), the
123    * stream will be completely consumed (to the end of the stream).
124    */
125   @Override
126   public void writeTo(OutputStream out) throws IOException {
127      assertArgNotNull("out", out);
128
129      if (isCached()) {
130         out.write(asBytes());
131      } else {
132         OutputStreamWriter osw = new OutputStreamWriter(out, getCharset());
133         pipe(content(), osw);
134         osw.flush();
135      }
136      out.flush();
137   }
138
139   @Override /* HttpEntity */
140   public boolean isStreaming() {
141      return ! isCached();
142   }
143
144   // <FluentSetters>
145
146   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
147   public ReaderEntity setCached() throws IOException{
148      super.setCached();
149      return this;
150   }
151
152   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
153   public ReaderEntity setCharset(Charset value) {
154      super.setCharset(value);
155      return this;
156   }
157
158   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
159   public ReaderEntity setChunked() {
160      super.setChunked();
161      return this;
162   }
163
164   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
165   public ReaderEntity setChunked(boolean value) {
166      super.setChunked(value);
167      return this;
168   }
169
170   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
171   public ReaderEntity setContent(Object value) {
172      super.setContent(value);
173      return this;
174   }
175
176   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
177   public ReaderEntity setContent(Supplier<?> value) {
178      super.setContent(value);
179      return this;
180   }
181
182   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
183   public ReaderEntity setContentEncoding(String value) {
184      super.setContentEncoding(value);
185      return this;
186   }
187
188   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
189   public ReaderEntity setContentEncoding(ContentEncoding value) {
190      super.setContentEncoding(value);
191      return this;
192   }
193
194   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
195   public ReaderEntity setContentLength(long value) {
196      super.setContentLength(value);
197      return this;
198   }
199
200   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
201   public ReaderEntity setContentType(String value) {
202      super.setContentType(value);
203      return this;
204   }
205
206   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
207   public ReaderEntity setContentType(ContentType value) {
208      super.setContentType(value);
209      return this;
210   }
211
212   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
213   public ReaderEntity setMaxLength(int value) {
214      super.setMaxLength(value);
215      return this;
216   }
217
218   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
219   public ReaderEntity setUnmodifiable() {
220      super.setUnmodifiable();
221      return this;
222   }
223
224   // </FluentSetters>
225}