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