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.rest.processor; 018 019import static org.apache.juneau.commons.utils.StringUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022import java.io.*; 023import org.apache.juneau.*; 024import org.apache.juneau.http.header.*; 025import org.apache.juneau.http.response.*; 026import org.apache.juneau.httppart.*; 027import org.apache.juneau.marshaller.*; 028import org.apache.juneau.rest.*; 029import org.apache.juneau.rest.util.*; 030import org.apache.juneau.serializer.*; 031 032/** 033 * Response handler for plain-old Java objects. 034 * 035 * <h5 class='section'>See Also:</h5><ul> 036 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ResponseProcessors">Response Processors</a> 037 * </ul> 038 */ 039@SuppressWarnings("resource") 040public class SerializedPojoProcessor implements ResponseProcessor { 041 042 @Override /* Overridden from ResponseProcessor */ 043 public int process(RestOpSession opSession) throws IOException, NotAcceptable, BasicHttpException { 044 RestRequest req = opSession.getRequest(); 045 RestResponse res = opSession.getResponse(); 046 SerializerMatch sm = res.getSerializerMatch().orElse(null); 047 HttpPartSchema schema = res.getContentSchema().orElse(null); 048 049 Object o = res.getContent(Object.class); 050 051 if (nn(sm)) { 052 try { 053 Serializer s = sm.getSerializer(); 054 MediaType mediaType = res.getMediaType(); 055 if (mediaType == null) 056 mediaType = sm.getMediaType(); 057 058 MediaType responseType = s.getResponseContentType(); 059 if (responseType == null) 060 responseType = mediaType; 061 062 if (req.isPlainText()) 063 res.setHeader(ContentType.TEXT_PLAIN); 064 else 065 res.setHeader(ContentType.of(responseType.toString())); 066 067 // @formatter:off 068 SerializerSession session = s 069 .createSession() 070 .properties(req.getAttributes().asMap()) 071 .javaMethod(req.getOpContext().getJavaMethod()) 072 .locale(req.getLocale()) 073 .timeZone(req.getTimeZone().orElse(null)) 074 .mediaType(mediaType) 075 .apply(WriterSerializerSession.Builder.class, x -> x.streamCharset(res.getCharset()).useWhitespace(req.isPlainText() ? true : null)) 076 .schema(schema) 077 .debug(req.isDebug() ? true : null) 078 .uriContext(req.getUriContext()) 079 .resolver(req.getVarResolverSession()) 080 .build(); 081 // @formatter:on 082 083 for (var h : session.getResponseHeaders().entrySet()) 084 res.addHeader(h.getKey(), h.getValue()); 085 086 if (! session.isWriterSerializer()) { 087 if (req.isPlainText()) { 088 FinishablePrintWriter w = res.getNegotiatedWriter(); 089 var baos = new ByteArrayOutputStream(); 090 session.serialize(o, baos); 091 w.write(toSpacedHex(baos.toByteArray())); 092 w.flush(); 093 w.finish(); 094 } else { 095 FinishableServletOutputStream os = res.getNegotiatedOutputStream(); 096 session.serialize(o, os); 097 os.flush(); 098 os.finish(); 099 } 100 } else { 101 FinishablePrintWriter w = res.getNegotiatedWriter(); 102 session.serialize(o, w); 103 w.flush(); 104 w.finish(); 105 } 106 } catch (SerializeException e) { 107 throw new InternalServerError(e); 108 } 109 return FINISHED; 110 } 111 112 if (o == null) 113 return FINISHED; 114 115 throw new NotAcceptable("Unsupported media-type in request header ''Accept'': ''{0}''\n\tSupported media-types: {1}", req.getHeaderParam("Accept").orElse(""), 116 Json5.of(res.getOpContext().getSerializers().getSupportedMediaTypes())); 117 } 118}