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 repeatable entity that obtains its content from a {@link File}.
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 FileEntity extends BasicHttpEntity {
038
039   //-----------------------------------------------------------------------------------------------------------------
040   // Instance
041   //-----------------------------------------------------------------------------------------------------------------
042
043   private byte[] byteCache;
044   private String stringCache;
045
046   /**
047    * Constructor.
048    */
049   public FileEntity() {
050   }
051
052   /**
053    * Constructor.
054    *
055    * @param contentType The entity content type.
056    * @param content The entity contents.
057    */
058   public FileEntity(ContentType contentType, File content) {
059      super(contentType, content);
060   }
061
062   /**
063    * Copy constructor.
064    *
065    * @param copyFrom The bean being copied.
066    */
067   protected FileEntity(FileEntity copyFrom) {
068      super(copyFrom);
069   }
070
071   @Override
072   public FileEntity copy() {
073      return new FileEntity(this);
074   }
075
076   //-----------------------------------------------------------------------------------------------------------------
077   // Other methods
078   //-----------------------------------------------------------------------------------------------------------------
079
080   private File content() {
081      File f = contentOrElse((File)null);
082      Objects.requireNonNull(f, "File");
083      if (! f.exists())
084         throw new IllegalStateException("File " + f.getAbsolutePath() + " does not exist.");
085      if (! f.canRead())
086         throw new IllegalStateException("File " + f.getAbsolutePath() + " is not readable.");
087      return f;
088   }
089
090   @Override /* AbstractHttpEntity */
091   public String asString() throws IOException {
092      if (isCached() && stringCache == null)
093         stringCache = read(new InputStreamReader(new FileInputStream(content()), getCharset()), getMaxLength());
094      if (stringCache != null)
095         return stringCache;
096      return read(new InputStreamReader(new FileInputStream(content()), getCharset()), getMaxLength());
097   }
098
099   @Override /* AbstractHttpEntity */
100   public byte[] asBytes() throws IOException {
101      if (isCached() && byteCache == null)
102         byteCache = readBytes(content(), getMaxLength());
103      if (byteCache != null)
104         return byteCache;
105      return readBytes(content());
106   }
107
108   @Override /* HttpEntity */
109   public boolean isRepeatable() {
110      return true;
111   }
112
113   @Override /* HttpEntity */
114   public long getContentLength() {
115      return content().length();
116   }
117
118   @Override /* HttpEntity */
119   public InputStream getContent() throws IOException {
120      if (isCached())
121         return new ByteArrayInputStream(asBytes());
122      return new FileInputStream(content());
123   }
124
125   @Override /* HttpEntity */
126   public void writeTo(OutputStream out) throws IOException {
127      Utils.assertArgNotNull("out", out);
128
129      if (isCached()) {
130         out.write(asBytes());
131      } else {
132         try (InputStream is = getContent()) {
133            IOUtils.pipe(is, out, getMaxLength());
134         }
135      }
136   }
137   @Override /* Overridden from BasicHttpEntity */
138   public FileEntity setCached() throws IOException{
139      super.setCached();
140      return this;
141   }
142
143   @Override /* Overridden from BasicHttpEntity */
144   public FileEntity setCharset(Charset value) {
145      super.setCharset(value);
146      return this;
147   }
148
149   @Override /* Overridden from BasicHttpEntity */
150   public FileEntity setChunked() {
151      super.setChunked();
152      return this;
153   }
154
155   @Override /* Overridden from BasicHttpEntity */
156   public FileEntity setChunked(boolean value) {
157      super.setChunked(value);
158      return this;
159   }
160
161   @Override /* Overridden from BasicHttpEntity */
162   public FileEntity setContent(Object value) {
163      super.setContent(value);
164      return this;
165   }
166
167   @Override /* Overridden from BasicHttpEntity */
168   public FileEntity setContent(Supplier<?> value) {
169      super.setContent(value);
170      return this;
171   }
172
173   @Override /* Overridden from BasicHttpEntity */
174   public FileEntity setContentEncoding(String value) {
175      super.setContentEncoding(value);
176      return this;
177   }
178
179   @Override /* Overridden from BasicHttpEntity */
180   public FileEntity setContentEncoding(ContentEncoding value) {
181      super.setContentEncoding(value);
182      return this;
183   }
184
185   @Override /* Overridden from BasicHttpEntity */
186   public FileEntity setContentLength(long value) {
187      super.setContentLength(value);
188      return this;
189   }
190
191   @Override /* Overridden from BasicHttpEntity */
192   public FileEntity setContentType(String value) {
193      super.setContentType(value);
194      return this;
195   }
196
197   @Override /* Overridden from BasicHttpEntity */
198   public FileEntity setContentType(ContentType value) {
199      super.setContentType(value);
200      return this;
201   }
202
203   @Override /* Overridden from BasicHttpEntity */
204   public FileEntity setMaxLength(int value) {
205      super.setMaxLength(value);
206      return this;
207   }
208
209   @Override /* Overridden from BasicHttpEntity */
210   public FileEntity setUnmodifiable() {
211      super.setUnmodifiable();
212      return this;
213   }
214}