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.IOUtils.*;
016import static org.apache.juneau.common.internal.ThrowableUtils.*;
017import static org.apache.juneau.http.HttpHeaders.*;
018
019import java.io.*;
020import java.nio.charset.*;
021import java.util.function.*;
022
023import org.apache.http.*;
024import org.apache.juneau.*;
025import org.apache.juneau.http.header.*;
026import org.apache.juneau.httppart.*;
027import org.apache.juneau.internal.*;
028import org.apache.juneau.serializer.*;
029
030/**
031 * HttpEntity for serializing POJOs as the body of HTTP requests.
032 *
033 * <h5 class='section'>See Also:</h5><ul>
034 *    <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-common">juneau-rest-common</a>
035
036 * </ul>
037 */
038@FluentSetters
039public class SerializedEntity extends BasicHttpEntity {
040
041   //-----------------------------------------------------------------------------------------------------------------
042   // Instances
043   //-----------------------------------------------------------------------------------------------------------------
044
045   Serializer serializer;
046   HttpPartSchema schema;
047
048   /**
049    * Constructor.
050    */
051   public SerializedEntity() {
052      super();
053   }
054
055   /**
056    * Constructor.
057    *
058    * @param contentType The entity content type.
059    * @param content The entity content.
060    * @param serializer The entity serializer.
061    * @param schema The entity schema.  Can be <jk>null</jk>.
062    */
063   public SerializedEntity(ContentType contentType, Object content, Serializer serializer, HttpPartSchema schema) {
064      super(contentType, content);
065      this.serializer = serializer;
066      this.schema = schema;
067   }
068
069   /**
070    * Copy constructor.
071    *
072    * @param copyFrom The bean being copied.
073    */
074   public SerializedEntity(SerializedEntity copyFrom) {
075      super(copyFrom);
076      this.serializer = copyFrom.serializer;
077      this.schema = copyFrom.schema;
078   }
079
080   /**
081    * Creates a builder for this class initialized with the contents of this bean.
082    *
083    * <p>
084    * Allows you to create a modifiable copy of this bean.
085    *
086    * @return A new builder bean.
087    */
088   @Override
089   public SerializedEntity copy() {
090      return new SerializedEntity(this);
091   }
092
093
094   /**
095    * Copies this bean and sets the serializer and schema on it.
096    *
097    * @param serializer The new serializer for the bean.  Can be <jk>null</jk>.
098    * @param schema The new schema for the bean.  Can be <jk>null</jk>.
099    * @return Either a new bean with the serializer set, or this bean if
100    *    both values are <jk>null</jk> or the serializer and schema were already set.
101    */
102   public SerializedEntity copyWith(Serializer serializer, HttpPartSchema schema) {
103      if ((this.serializer == null && serializer != null) || (this.schema == null && schema != null)) {
104         SerializedEntity h = copy();
105         if (serializer != null)
106            h.setSerializer(serializer);
107         if (schema != null)
108            h.setSchema(schema);
109         return h;
110      }
111      return this;
112   }
113
114   //-----------------------------------------------------------------------------------------------------------------
115
116   /**
117    * Sets the serializer on this entity bean.
118    *
119    * @param value The entity serializer, can be <jk>null</jk>.
120    * @return This object.
121    */
122   @FluentSetter
123   public SerializedEntity setSerializer(Serializer value) {
124      assertModifiable();
125      this.serializer = value;
126      return this;
127   }
128
129   /**
130    * Sets the schema on this entity bean.
131    *
132    * <p>
133    * Used to provide instructions to the serializer on how to serialize this object.
134    *
135    * @param value The entity schema, can be <jk>null</jk>.
136    * @return This object.
137    */
138   @FluentSetter
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
196   // <FluentSetters>
197
198   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
199   public SerializedEntity setCached() throws IOException{
200      super.setCached();
201      return this;
202   }
203
204   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
205   public SerializedEntity setCharset(Charset value) {
206      super.setCharset(value);
207      return this;
208   }
209
210   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
211   public SerializedEntity setChunked() {
212      super.setChunked();
213      return this;
214   }
215
216   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
217   public SerializedEntity setChunked(boolean value) {
218      super.setChunked(value);
219      return this;
220   }
221
222   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
223   public SerializedEntity setContent(Object value) {
224      super.setContent(value);
225      return this;
226   }
227
228   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
229   public SerializedEntity setContent(Supplier<?> value) {
230      super.setContent(value);
231      return this;
232   }
233
234   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
235   public SerializedEntity setContentEncoding(String value) {
236      super.setContentEncoding(value);
237      return this;
238   }
239
240   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
241   public SerializedEntity setContentEncoding(ContentEncoding value) {
242      super.setContentEncoding(value);
243      return this;
244   }
245
246   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
247   public SerializedEntity setContentLength(long value) {
248      super.setContentLength(value);
249      return this;
250   }
251
252   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
253   public SerializedEntity setContentType(String value) {
254      super.setContentType(value);
255      return this;
256   }
257
258   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
259   public SerializedEntity setContentType(ContentType value) {
260      super.setContentType(value);
261      return this;
262   }
263
264   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
265   public SerializedEntity setMaxLength(int value) {
266      super.setMaxLength(value);
267      return this;
268   }
269
270   @Override /* GENERATED - org.apache.juneau.http.entity.BasicHttpEntity */
271   public SerializedEntity setUnmodifiable() {
272      super.setUnmodifiable();
273      return this;
274   }
275
276   // </FluentSetters>
277}