/*
 * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.server;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.EntityTag;
import jakarta.ws.rs.core.GenericEntity;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Link;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NewCookie;
import jakarta.ws.rs.core.Response;

import org.glassfish.jersey.message.internal.OutboundJaxrsResponse;
import org.glassfish.jersey.message.internal.OutboundMessageContext;
import org.glassfish.jersey.message.internal.Statuses;

Jersey container response context.
Author:Marek Potociar
/** * Jersey container response context. * * @author Marek Potociar */
public class ContainerResponse implements ContainerResponseContext { private Response.StatusType status; private final ContainerRequest requestContext; private final OutboundMessageContext messageContext; private boolean mappedFromException; private boolean closed;
Create a new Jersey container response context.
Params:
  • requestContext – associated container request context.
  • response – response instance initializing the response context.
/** * Create a new Jersey container response context. * * @param requestContext associated container request context. * @param response response instance initializing the response context. */
public ContainerResponse(final ContainerRequest requestContext, final Response response) { this(requestContext, OutboundJaxrsResponse.from(response, requestContext.getConfiguration())); }
Create a new Jersey container response context.
Params:
  • requestContext – associated container request context.
  • response – response instance initializing the response context.
/** * Create a new Jersey container response context. * * @param requestContext associated container request context. * @param response response instance initializing the response context. */
ContainerResponse(final ContainerRequest requestContext, final OutboundJaxrsResponse response) { this.requestContext = requestContext; this.requestContext.inResponseProcessing(); this.status = response.getStatusInfo(); this.messageContext = response.getContext(); final String varyValue = requestContext.getVaryValue(); if (varyValue != null && !this.messageContext.getHeaders().containsKey(HttpHeaders.VARY)) { /** * Add a Vary header using the value computed in the request if present * and if the Vary header was not explicitly set in the response already. */ this.messageContext.getHeaders().add(HttpHeaders.VARY, varyValue); } }
Returns true if the response is result of the exception (for example created during exception mapping).
Returns:True if this response was created based on the exception, false otherwise.
/** * Returns true if the response is result of the exception (for example created during * {@link jakarta.ws.rs.ext.ExceptionMapper exception mapping}). * * @return True if this response was created based on the exception, false otherwise. */
public boolean isMappedFromException() { return mappedFromException; }
Sets the flag indicating whether the response was created based on the exception.
Params:
  • mappedFromException – True if this exception if result of the exception (for example result of exception mapping).
/** * Sets the flag indicating whether the response was created based on the exception. * @param mappedFromException True if this exception if result of the exception (for example result of * {@link jakarta.ws.rs.ext.ExceptionMapper exception mapping}). */
public void setMappedFromException(final boolean mappedFromException) { this.mappedFromException = mappedFromException; } @Override public int getStatus() { return status.getStatusCode(); } @Override public void setStatus(final int code) { this.status = Statuses.from(code); } @Override public void setStatusInfo(final Response.StatusType status) { if (status == null) { throw new NullPointerException("Response status must not be 'null'"); } this.status = status; } @Override public Response.StatusType getStatusInfo() { return status; }
Get the associated container request context paired with this response context.
Returns:associated container request context.
/** * Get the associated container request context paired with this response context. * * @return associated container request context. */
public ContainerRequest getRequestContext() { return requestContext; } @Override public Map<String, NewCookie> getCookies() { return messageContext.getResponseCookies(); }
Get the wrapped response message context.
Returns:wrapped response message context.
/** * Get the wrapped response message context. * * @return wrapped response message context. */
public OutboundMessageContext getWrappedMessageContext() { return messageContext; } @Override public String getHeaderString(final String name) { return messageContext.getHeaderString(name); } @Override public MultivaluedMap<String, Object> getHeaders() { return messageContext.getHeaders(); } @Override public MultivaluedMap<String, String> getStringHeaders() { return messageContext.getStringHeaders(); } @Override public Date getDate() { return messageContext.getDate(); } @Override public Locale getLanguage() { return messageContext.getLanguage(); } @Override public MediaType getMediaType() { return messageContext.getMediaType(); } @Override public Set<String> getAllowedMethods() { return messageContext.getAllowedMethods(); } @Override public int getLength() { return messageContext.getLength(); } @Override public EntityTag getEntityTag() { return messageContext.getEntityTag(); } @Override public Date getLastModified() { return messageContext.getLastModified(); } @Override public URI getLocation() { return messageContext.getLocation(); } @Override public Set<Link> getLinks() { return messageContext.getLinks(); } @Override public boolean hasLink(final String relation) { return messageContext.hasLink(relation); } @Override public Link getLink(final String relation) { return messageContext.getLink(relation); } @Override public Link.Builder getLinkBuilder(final String relation) { return messageContext.getLinkBuilder(relation); } @Override public boolean hasEntity() { return messageContext.hasEntity(); } @Override public Object getEntity() { return messageContext.getEntity(); }
Set a new message message entity.
Params:
  • entity – entity object.
See Also:
/** * Set a new message message entity. * * @param entity entity object. * @see jakarta.ws.rs.ext.MessageBodyWriter */
public void setEntity(final Object entity) { messageContext.setEntity(entity); }
Set a new message message entity.
Params:
  • entity – entity object.
  • annotations – annotations attached to the entity.
See Also:
/** * Set a new message message entity. * * @param entity entity object. * @param annotations annotations attached to the entity. * @see jakarta.ws.rs.ext.MessageBodyWriter */
public void setEntity(final Object entity, final Annotation[] annotations) { messageContext.setEntity(entity, annotations); }
Set a new message message entity.
Params:
  • entity – entity object.
  • type – declared entity class.
  • annotations – annotations attached to the entity.
See Also:
/** * Set a new message message entity. * * @param entity entity object. * @param type declared entity class. * @param annotations annotations attached to the entity. * @see jakarta.ws.rs.ext.MessageBodyWriter */
public void setEntity(final Object entity, final Type type, final Annotation[] annotations) { messageContext.setEntity(entity, type, annotations); } @Override public void setEntity(final Object entity, final Annotation[] annotations, final MediaType mediaType) { messageContext.setEntity(entity, annotations, mediaType); }
Set the message content media type.
Params:
  • mediaType – message content media type.
/** * Set the message content media type. * * @param mediaType message content media type. */
public void setMediaType(final MediaType mediaType) { messageContext.setMediaType(mediaType); } @Override public Class<?> getEntityClass() { return messageContext.getEntityClass(); } @Override public Type getEntityType() { return messageContext.getEntityType(); }
Set the message entity type information. This method overrides any computed or previously set entity type information.
Params:
  • type – overriding message entity type.
/** * Set the message entity type information. * * This method overrides any computed or previously set entity type information. * * @param type overriding message entity type. */
public void setEntityType(final Type type) { Type t = type; if (type instanceof ParameterizedType) { final ParameterizedType parameterizedType = (ParameterizedType) type; if (parameterizedType.getRawType().equals(GenericEntity.class)) { t = parameterizedType.getActualTypeArguments()[0]; } } messageContext.setEntityType(t); } @Override public Annotation[] getEntityAnnotations() { return messageContext.getEntityAnnotations(); }
Set the annotations attached to the entity.
Params:
  • annotations – entity annotations.
/** * Set the annotations attached to the entity. * * @param annotations entity annotations. */
public void setEntityAnnotations(final Annotation[] annotations) { messageContext.setEntityAnnotations(annotations); } @Override public OutputStream getEntityStream() { return messageContext.getEntityStream(); } @Override public void setEntityStream(final OutputStream outputStream) { messageContext.setEntityStream(outputStream); }
Set the output stream provider callback.

This method must be called before first bytes are written to the entity stream.
Params:
  • streamProvider – non-null output stream provider.
/** * Set the output stream provider callback. * <p/> * This method must be called before first bytes are written to the {@link #getEntityStream() entity stream}. * * @param streamProvider non-{@code null} output stream provider. */
public void setStreamProvider(final OutboundMessageContext.StreamProvider streamProvider) { messageContext.setStreamProvider(streamProvider); }
Enable a buffering of serialized entity. The buffering will be configured from configuration. The property determining the size of the buffer is CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER.

The buffering functionality is by default disabled and could be enabled by calling this method. In this case this method must be called before first bytes are written to the entity stream.
Params:
  • configuration – runtime configuration.
/** * Enable a buffering of serialized entity. The buffering will be configured from configuration. The property * determining the size of the buffer is {@link org.glassfish.jersey.CommonProperties#OUTBOUND_CONTENT_LENGTH_BUFFER}. * <p/> * The buffering functionality is by default disabled and could be enabled by calling this method. In this case * this method must be called before first bytes are written to the {@link #getEntityStream() entity stream}. * * @param configuration runtime configuration. */
public void enableBuffering(final Configuration configuration) { messageContext.enableBuffering(configuration); }
Commit the entity stream unless already committed.
Throws:
/** * Commit the {@link #getEntityStream() entity stream} unless already committed. * * @throws IOException in case of the IO error. */
public void commitStream() throws IOException { messageContext.commitStream(); }
Returns true if the entity stream has been committed.
Returns:true if the entity stream has been committed. Otherwise returns false.
/** * Returns {@code true} if the entity stream has been committed. * @return {@code true} if the entity stream has been committed. Otherwise returns {@code false}. */
public boolean isCommitted() { return messageContext.isCommitted(); }
Closes the response. Flushes and closes the entity stream, frees up container resources associated with the corresponding request.
/** * Closes the response. Flushes and closes the entity stream, frees up container resources associated with * the corresponding request. */
public void close() { if (!closed) { closed = true; messageContext.close(); requestContext.getResponseWriter().commit(); } }
Returns true if the response entity is a ChunkedOutput instance.
Returns:true if the entity is a ChunkedOutput instance, false otherwise.
/** * Returns {@code true} if the response entity is a {@link ChunkedOutput} instance. * @return {@code true} if the entity is a {@link ChunkedOutput} instance, {@code false} otherwise. */
public boolean isChunked() { return hasEntity() && ChunkedOutput.class.isAssignableFrom(getEntity().getClass()); } }