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; 014 015import static org.apache.juneau.internal.IOUtils.*; 016 017import java.io.*; 018import java.util.function.*; 019 020import org.apache.http.*; 021import org.apache.juneau.*; 022import org.apache.juneau.http.header.*; 023import org.apache.juneau.httppart.*; 024import org.apache.juneau.internal.*; 025import org.apache.juneau.serializer.*; 026 027/** 028 * HttpEntity for serializing POJOs as the body of HTTP requests. 029 */ 030public class SerializedHttpEntity extends BasicHttpEntity { 031 private final Serializer serializer; 032 private HttpPartSchema schema; 033 034 /** 035 * Creator. 036 * 037 * @param content The POJO to serialize. Can also be a {@link Reader} or {@link InputStream}. 038 * @param serializer The serializer to use to serialize this response. 039 * @return A new {@link SerializedHttpEntity} with uninitialized serializer and schema. 040 */ 041 public static SerializedHttpEntity of(Object content, Serializer serializer) { 042 return new SerializedHttpEntity(content, serializer); 043 } 044 045 /** 046 * Creator. 047 * 048 * @param content The POJO to serialize. Can also be a {@link Reader} or {@link InputStream}. 049 * @param serializer The serializer to use to serialize this response. 050 * @return A new {@link SerializedHttpEntity} with uninitialized serializer and schema. 051 */ 052 public static SerializedHttpEntity of(Supplier<?> content, Serializer serializer) { 053 return new SerializedHttpEntity(content, serializer); 054 } 055 056 /** 057 * Constructor. 058 * 059 * @param content The POJO to serialize. Can also be a {@link Reader} or {@link InputStream}. 060 * @param serializer The serializer to use to serialize this response. 061 */ 062 public SerializedHttpEntity(Object content, Serializer serializer) { 063 super(content, ContentType.of(serializer == null ? null : serializer.getResponseContentType()), null); 064 this.serializer = serializer; 065 } 066 067 /** 068 * Sets the schema to use to serialize the content. 069 * 070 * <p> 071 * Value is ignored if the serializer is not schema-aware. 072 * 073 * @param value The schema. 074 * @return This object (for method chaining). 075 */ 076 @FluentSetter 077 public SerializedHttpEntity schema(HttpPartSchema value) { 078 this.schema = value; 079 return this; 080 } 081 082 @Override /* BasicHttpEntity */ 083 public void writeTo(OutputStream os) throws IOException { 084 if (isSerializable()) { 085 try { 086 os = new NoCloseOutputStream(os); 087 Object o = getRawContent(); 088 if (serializer == null) { 089 os.write(o.toString().getBytes()); 090 os.close(); 091 } else { 092 SerializerSessionArgs sArgs = SerializerSessionArgs.create().schema(schema); 093 SerializerSession session = serializer.createSession(sArgs); 094 try (Closeable c = session.isWriterSerializer() ? new OutputStreamWriter(os, UTF8) : os) { 095 session.serialize(o, c); 096 } 097 } 098 } catch (SerializeException e) { 099 throw new BasicRuntimeException(e, "Serialization error on request body."); 100 } 101 } else { 102 super.writeTo(os); 103 } 104 } 105 106 @Override /* BasicHttpEntity */ 107 public boolean isRepeatable() { 108 if (isSerializable()) 109 return true; 110 return super.isRepeatable(); 111 } 112 113 @Override /* BasicHttpEntity */ 114 public long getContentLength() { 115 if (isSerializable()) 116 return -1; 117 return super.getContentLength(); 118 } 119 120 @Override /* BasicHttpEntity */ 121 public InputStream getContent() { 122 if (isSerializable()) { 123 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { 124 writeTo(baos); 125 return new ByteArrayInputStream(baos.toByteArray()); 126 } catch (IOException e) { 127 throw new RuntimeException(e); 128 } 129 } 130 return super.getContent(); 131 } 132 133 private boolean isSerializable() { 134 Object o = getRawContent(); 135 return ! (o instanceof InputStream || o instanceof Reader || o instanceof File); 136 } 137 138 // <FluentSetters> 139 140 @Override /* GENERATED - BasicHttpEntity */ 141 public SerializedHttpEntity cache() { 142 super.cache(); 143 return this; 144 } 145 146 @Override /* GENERATED - BasicHttpEntity */ 147 public SerializedHttpEntity cache(boolean value) { 148 super.cache(value); 149 return this; 150 } 151 152 @Override /* GENERATED - BasicHttpEntity */ 153 public SerializedHttpEntity chunked() { 154 super.chunked(); 155 return this; 156 } 157 158 @Override /* GENERATED - BasicHttpEntity */ 159 public SerializedHttpEntity chunked(boolean value) { 160 super.chunked(value); 161 return this; 162 } 163 164 @Override /* GENERATED - BasicHttpEntity */ 165 public SerializedHttpEntity contentEncoding(String value) { 166 super.contentEncoding(value); 167 return this; 168 } 169 170 @Override /* GENERATED - BasicHttpEntity */ 171 public SerializedHttpEntity contentEncoding(Header value) { 172 super.contentEncoding(value); 173 return this; 174 } 175 176 @Override /* GENERATED - BasicHttpEntity */ 177 public SerializedHttpEntity contentLength(long value) { 178 super.contentLength(value); 179 return this; 180 } 181 182 @Override /* GENERATED - BasicHttpEntity */ 183 public SerializedHttpEntity contentType(String value) { 184 super.contentType(value); 185 return this; 186 } 187 188 @Override /* GENERATED - BasicHttpEntity */ 189 public SerializedHttpEntity contentType(Header value) { 190 super.contentType(value); 191 return this; 192 } 193 194 // </FluentSetters> 195}