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 InputStream}.
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 StreamEntity extends BasicHttpEntity {
035
036   //-----------------------------------------------------------------------------------------------------------------
037   // Instance
038   //-----------------------------------------------------------------------------------------------------------------
039
040   private byte[] byteCache;
041   private String stringCache;
042
043   /**
044    * Constructor.
045    */
046   public StreamEntity() {
047   }
048
049   /**
050    * Constructor.
051    *
052    * @param contentType The entity content type.
053    * @param content The entity contents.
054    */
055   public StreamEntity(ContentType contentType, InputStream content) {
056      super(contentType, content);
057   }
058
059   /**
060    * Copy constructor.
061    *
062    * @param copyFrom The bean being copied.
063    */
064   protected StreamEntity(StreamEntity copyFrom) {
065      super(copyFrom);
066   }
067
068   @Override
069   public StreamEntity copy() {
070      return new StreamEntity(this);
071   }
072
073   //-----------------------------------------------------------------------------------------------------------------
074   // Other methods
075   //-----------------------------------------------------------------------------------------------------------------
076
077   @SuppressWarnings("resource") // Caller closes
078    private InputStream content() {
079      return Objects.requireNonNull(contentOrElse((InputStream) null), "Input stream is null.");
080   }
081
082   @Override /* AbstractHttpEntity */
083   public String asString() throws IOException {
084      if (isCached() && stringCache == null)
085         stringCache = read(content(), getCharset());
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(), getMaxLength());
095      if (byteCache != null)
096         return byteCache;
097      return readBytes(content(), getMaxLength());
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 content();
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         try (InputStream is = getContent()) {
133            pipe(is, out, getMaxLength());
134         }
135      }
136   }
137
138   @Override /* HttpEntity */
139   public boolean isStreaming() {
140      return ! isCached();
141   }
142
143   // <FluentSetters>
144
145   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
146   public StreamEntity setCached() throws IOException{
147      super.setCached();
148      return this;
149   }
150
151   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
152   public StreamEntity setCharset(Charset value) {
153      super.setCharset(value);
154      return this;
155   }
156
157   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
158   public StreamEntity setChunked() {
159      super.setChunked();
160      return this;
161   }
162
163   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
164   public StreamEntity setChunked(boolean value) {
165      super.setChunked(value);
166      return this;
167   }
168
169   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
170   public StreamEntity setContent(Object value) {
171      super.setContent(value);
172      return this;
173   }
174
175   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
176   public StreamEntity setContent(Supplier<?> value) {
177      super.setContent(value);
178      return this;
179   }
180
181   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
182   public StreamEntity setContentEncoding(String value) {
183      super.setContentEncoding(value);
184      return this;
185   }
186
187   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
188   public StreamEntity setContentEncoding(ContentEncoding value) {
189      super.setContentEncoding(value);
190      return this;
191   }
192
193   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
194   public StreamEntity setContentLength(long value) {
195      super.setContentLength(value);
196      return this;
197   }
198
199   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
200   public StreamEntity setContentType(String value) {
201      super.setContentType(value);
202      return this;
203   }
204
205   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
206   public StreamEntity setContentType(ContentType value) {
207      super.setContentType(value);
208      return this;
209   }
210
211   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
212   public StreamEntity setMaxLength(int value) {
213      super.setMaxLength(value);
214      return this;
215   }
216
217   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
218   public StreamEntity setUnmodifiable() {
219      super.setUnmodifiable();
220      return this;
221   }
222
223   // </FluentSetters>
224}