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