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.*;
020import static org.apache.juneau.common.utils.ThrowableUtils.*;
021import static org.apache.juneau.http.HttpHeaders.*;
022
023import java.io.*;
024import java.nio.charset.*;
025import java.util.function.*;
026
027import org.apache.http.*;
028import org.apache.juneau.*;
029import org.apache.juneau.http.header.*;
030import org.apache.juneau.httppart.*;
031import org.apache.juneau.internal.*;
032import org.apache.juneau.serializer.*;
033
034/**
035 * HttpEntity for serializing POJOs as the body of HTTP requests.
036 *
037 * <h5 class='section'>See Also:</h5><ul>
038 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a>
039
040 * </ul>
041 */
042public class SerializedEntity extends BasicHttpEntity {
043
044   //-----------------------------------------------------------------------------------------------------------------
045   // Instances
046   //-----------------------------------------------------------------------------------------------------------------
047
048   Serializer serializer;
049   HttpPartSchema schema;
050
051   /**
052    * Constructor.
053    */
054   public SerializedEntity() {
055   }
056
057   /**
058    * Constructor.
059    *
060    * @param contentType The entity content type.
061    * @param content The entity content.
062    * @param serializer The entity serializer.
063    * @param schema The entity schema.  Can be <jk>null</jk>.
064    */
065   public SerializedEntity(ContentType contentType, Object content, Serializer serializer, HttpPartSchema schema) {
066      super(contentType, content);
067      this.serializer = serializer;
068      this.schema = schema;
069   }
070
071   /**
072    * Copy constructor.
073    *
074    * @param copyFrom The bean being copied.
075    */
076   public SerializedEntity(SerializedEntity copyFrom) {
077      super(copyFrom);
078      this.serializer = copyFrom.serializer;
079      this.schema = copyFrom.schema;
080   }
081
082   /**
083    * Creates a builder for this class initialized with the contents of this bean.
084    *
085    * <p>
086    * Allows you to create a modifiable copy of this bean.
087    *
088    * @return A new builder bean.
089    */
090   @Override
091   public SerializedEntity copy() {
092      return new SerializedEntity(this);
093   }
094
095
096   /**
097    * Copies this bean and sets the serializer and schema on it.
098    *
099    * @param serializer The new serializer for the bean.  Can be <jk>null</jk>.
100    * @param schema The new schema for the bean.  Can be <jk>null</jk>.
101    * @return Either a new bean with the serializer set, or this bean if
102    *    both values are <jk>null</jk> or the serializer and schema were already set.
103    */
104   public SerializedEntity copyWith(Serializer serializer, HttpPartSchema schema) {
105      if ((this.serializer == null && serializer != null) || (this.schema == null && schema != null)) {
106         SerializedEntity h = copy();
107         if (serializer != null)
108            h.setSerializer(serializer);
109         if (schema != null)
110            h.setSchema(schema);
111         return h;
112      }
113      return this;
114   }
115
116   //-----------------------------------------------------------------------------------------------------------------
117
118   /**
119    * Sets the serializer on this entity bean.
120    *
121    * @param value The entity serializer, can be <jk>null</jk>.
122    * @return This object.
123    */
124   public SerializedEntity setSerializer(Serializer value) {
125      assertModifiable();
126      this.serializer = value;
127      return this;
128   }
129
130   /**
131    * Sets the schema on this entity bean.
132    *
133    * <p>
134    * Used to provide instructions to the serializer on how to serialize this object.
135    *
136    * @param value The entity schema, can be <jk>null</jk>.
137    * @return This object.
138    */
139   public SerializedEntity setSchema(HttpPartSchema value) {
140      assertModifiable();
141      this.schema = value;
142      return this;
143   }
144
145
146
147   @Override
148   public Header getContentType() {
149      Header x = super.getContentType();
150      if (x == null && serializer != null)
151         x = contentType(serializer.getPrimaryMediaType());
152      return x;
153   }
154
155   @Override /* HttpEntity */
156   public void writeTo(OutputStream os) throws IOException {
157      try {
158         os = new NoCloseOutputStream(os);
159         Object o = contentOrElse(null);
160         if (serializer == null) {
161            try (Writer w = new OutputStreamWriter(os, UTF8)) {
162               w.write(o.toString());
163            }
164         } else {
165            SerializerSession session = serializer.createSession().schema(schema).build();
166            try (Closeable c = session.isWriterSerializer() ? new OutputStreamWriter(os, UTF8) : os) {
167               session.serialize(o, c);
168            }
169         }
170      } catch (SerializeException e) {
171         throw new BasicRuntimeException(e, "Serialization error on request body.");
172      }
173   }
174
175   @Override /* BasicHttpEntity */
176   public boolean isRepeatable() {
177      return true;
178   }
179
180   @Override /* BasicHttpEntity */
181   public long getContentLength() {
182      return -1;
183   }
184
185   @Override /* BasicHttpEntity */
186   public InputStream getContent() {
187      ByteArrayOutputStream baos = new ByteArrayOutputStream();
188      try {
189         writeTo(baos);
190         return new ByteArrayInputStream(baos.toByteArray());
191      } catch (IOException e) {
192         throw asRuntimeException(e);
193      }
194   }
195   @Override /* Overridden from BasicHttpEntity */
196   public SerializedEntity setCached() throws IOException{
197      super.setCached();
198      return this;
199   }
200
201   @Override /* Overridden from BasicHttpEntity */
202   public SerializedEntity setCharset(Charset value) {
203      super.setCharset(value);
204      return this;
205   }
206
207   @Override /* Overridden from BasicHttpEntity */
208   public SerializedEntity setChunked() {
209      super.setChunked();
210      return this;
211   }
212
213   @Override /* Overridden from BasicHttpEntity */
214   public SerializedEntity setChunked(boolean value) {
215      super.setChunked(value);
216      return this;
217   }
218
219   @Override /* Overridden from BasicHttpEntity */
220   public SerializedEntity setContent(Object value) {
221      super.setContent(value);
222      return this;
223   }
224
225   @Override /* Overridden from BasicHttpEntity */
226   public SerializedEntity setContent(Supplier<?> value) {
227      super.setContent(value);
228      return this;
229   }
230
231   @Override /* Overridden from BasicHttpEntity */
232   public SerializedEntity setContentEncoding(String value) {
233      super.setContentEncoding(value);
234      return this;
235   }
236
237   @Override /* Overridden from BasicHttpEntity */
238   public SerializedEntity setContentEncoding(ContentEncoding value) {
239      super.setContentEncoding(value);
240      return this;
241   }
242
243   @Override /* Overridden from BasicHttpEntity */
244   public SerializedEntity setContentLength(long value) {
245      super.setContentLength(value);
246      return this;
247   }
248
249   @Override /* Overridden from BasicHttpEntity */
250   public SerializedEntity setContentType(String value) {
251      super.setContentType(value);
252      return this;
253   }
254
255   @Override /* Overridden from BasicHttpEntity */
256   public SerializedEntity setContentType(ContentType value) {
257      super.setContentType(value);
258      return this;
259   }
260
261   @Override /* Overridden from BasicHttpEntity */
262   public SerializedEntity setMaxLength(int value) {
263      super.setMaxLength(value);
264      return this;
265   }
266
267   @Override /* Overridden from BasicHttpEntity */
268   public SerializedEntity setUnmodifiable() {
269      super.setUnmodifiable();
270      return this;
271   }
272}