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