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