/*
 * Copyright (c) 2010, 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.grizzly.http;

import java.util.Locale;

import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.http.util.DataChunk;
import org.glassfish.grizzly.http.util.HttpStatus;
import org.glassfish.grizzly.http.util.MimeHeaders;

The HttpHeader object, which represents HTTP response message.
Author:Alexey Stashok
See Also:
/** * The {@link HttpHeader} object, which represents HTTP response message. * * @see HttpHeader * @see HttpRequestPacket * * @author Alexey Stashok */
public abstract class HttpResponsePacket extends HttpHeader { // ----------------------------------------------------- Instance Variables
The request that triggered this response.
/** * The request that triggered this response. */
private HttpRequestPacket request;
The Locale of the entity body being sent by this response.
/** * The {@link Locale} of the entity body being sent by this response. */
private Locale locale;
The value of the Content-Language response header.
/** * The value of the <code>Content-Language</code> response header. */
private String contentLanguage;
Status code.
/** * Status code. */
protected HttpStatus httpStatus;
Status message.
/** * Status message. */
private final DataChunk reasonPhraseC = DataChunk.newInstance();
Does this HttpResponsePacket represent an acknowledgment to an Expect header.
/** * Does this HttpResponsePacket represent an acknowledgment to an Expect header. */
private boolean acknowledgment;
Do we allow custom reason phrase.
/** * Do we allow custom reason phrase. */
private boolean allowCustomReasonPhrase = true;
Do we need to encode HTML sensitive characters in custom reason phrase.
/** * Do we need to encode HTML sensitive characters in custom reason phrase. */
private boolean isHtmlEncodingCustomReasonPhrase = true;
Returns HttpResponsePacket builder.
Returns:Builder.
/** * Returns {@link HttpResponsePacket} builder. * * @return {@link Builder}. */
public static Builder builder(final HttpRequestPacket request) { return new Builder().requestPacket(request); } // ----------------------------------------------------------- Constructors protected HttpResponsePacket() { } // -------------------- State --------------------
Gets the status code for this response.
Returns:the status code for this response.
/** * Gets the status code for this response. * * @return the status code for this response. */
public int getStatus() { return getHttpStatus().getStatusCode(); }
Gets the HTTP status for this response.
Returns:the HTTP status for this response.
/** * Gets the HTTP status for this response. * * @return the HTTP status for this response. */
public HttpStatus getHttpStatus() { if (httpStatus == null) { httpStatus = HttpStatus.OK_200; } return httpStatus; }
Sets the status code for this response.
Params:
  • status – the status code for this response.
/** * Sets the status code for this response. * * @param status the status code for this response. */
public void setStatus(final int status) { // the order is important here as statusDC.setXXX will reset the parsedIntStatus httpStatus = HttpStatus.getHttpStatus(status); }
Sets the status code for this response.
Params:
  • status – the status for this response.
/** * Sets the status code for this response. * * @param status the status for this response. */
public void setStatus(final HttpStatus status) { this.httpStatus = status; this.reasonPhraseC.recycle(); }
Returns true if custom status reason phrases are allowed for this response, or false otherwise.
Returns:true if custom status reason phrases are allowed for this response, or false otherwise.
/** * Returns <code>true</code> if custom status reason phrases are allowed for this response, or <code>false</tt> * otherwise. * * @return <code>true</code> if custom status reason phrases are allowed for this response, or <code>false</tt> * otherwise. */
public final boolean isAllowCustomReasonPhrase() { return allowCustomReasonPhrase; }
Sets if the custom status reason phrases are allowed for this response.
Params:
  • allowCustomReasonPhrase – true if custom status reason phrases are allowed for this response, or false otherwise.
/** * Sets if the custom status reason phrases are allowed for this response. * * @param allowCustomReasonPhrase <code>true</code> if custom status reason phrases are allowed for this response, or * <code>false</tt> otherwise. */
public final void setAllowCustomReasonPhrase(final boolean allowCustomReasonPhrase) { this.allowCustomReasonPhrase = allowCustomReasonPhrase; }
Returns if we need to encode HTML sensitive characters in custom reason phrase.
/** * Returns if we need to encode HTML sensitive characters in custom reason phrase. */
public boolean isHtmlEncodingCustomReasonPhrase() { return isHtmlEncodingCustomReasonPhrase; }
Sets if we need to encode HTML sensitive characters in custom reason phrase.
/** * Sets if we need to encode HTML sensitive characters in custom reason phrase. */
public void setHtmlEncodingCustomReasonPhrase(boolean isHtmlEncodingCustomReasonPhrase) { this.isHtmlEncodingCustomReasonPhrase = isHtmlEncodingCustomReasonPhrase; }
Gets the custom status reason phrase for this response as DataChunk (avoid creation of a String object}.
Returns:the status reason phrase for this response as DataChunk (avoid creation of a String object}.
/** * Gets the custom status reason phrase for this response as {@link DataChunk} (avoid creation of a String object}. * * @return the status reason phrase for this response as {@link DataChunk} (avoid creation of a String object}. */
public final DataChunk getReasonPhraseRawDC() { return reasonPhraseC; }
Gets the status reason phrase for this response as DataChunk (avoid creation of a String object}. This implementation takes into consideration the isAllowCustomReasonPhrase() property - if the custom reason phrase is allowed and it's value is not null - then the returned result will be equal to getReasonPhraseRawDC(), otherwise if custom reason phrase is disallowed or its value is null - the default reason phrase for the HTTP response getStatus() will be returned.
Returns:the status reason phrase for this response as DataChunk (avoid creation of a String object}.
/** * Gets the status reason phrase for this response as {@link DataChunk} (avoid creation of a String object}. This * implementation takes into consideration the {@link #isAllowCustomReasonPhrase()} property - if the custom reason * phrase is allowed and it's value is not null - then the returned result will be equal to * {@link #getReasonPhraseRawDC()}, otherwise if custom reason phrase is disallowed or its value is null - the default * reason phrase for the HTTP response {@link #getStatus()} will be returned. * * @return the status reason phrase for this response as {@link DataChunk} (avoid creation of a String object}. */
public final DataChunk getReasonPhraseDC() { if (isCustomReasonPhraseSet()) { return reasonPhraseC; } else { reasonPhraseC.setBytes(httpStatus.getReasonPhraseBytes()); return reasonPhraseC; } }
Gets the status reason phrase for this response.
Returns:the status reason phrase for this response.
/** * Gets the status reason phrase for this response. * * @return the status reason phrase for this response. */
public final String getReasonPhrase() { return getReasonPhraseDC().toString(); }
Sets the status reason phrase for this response.
Params:
  • message – the status reason phrase for this response.
/** * Sets the status reason phrase for this response. * * @param message the status reason phrase for this response. */
public void setReasonPhrase(final String message) { reasonPhraseC.setString(message); } public void setReasonPhrase(final Buffer reason) { reasonPhraseC.setBuffer(reason, reason.position(), reason.limit()); } public final boolean isCustomReasonPhraseSet() { return allowCustomReasonPhrase && !reasonPhraseC.isNull(); }
Returns:the request that triggered this response
/** * @return the request that triggered this response */
public HttpRequestPacket getRequest() { return request; }
Returns:true if this response packet is intended as an acknowledgment to an expectation from a client request.
/** * @return <code>true</code> if this response packet is intended as an acknowledgment to an expectation from a client * request. */
public boolean isAcknowledgement() { return acknowledgment; }
Mark this packet as an acknowledgment to a client expectation.
Params:
  • acknowledgement – true if this packet is an acknowledgment to a client expectation.
/** * Mark this packet as an acknowledgment to a client expectation. * * @param acknowledgement <code>true</code> if this packet is an acknowledgment to a client expectation. */
public void setAcknowledgement(final boolean acknowledgement) { this.acknowledgment = acknowledgement; }
Mark this packet as having been acknowledged.
/** * Mark this packet as having been acknowledged. */
public void acknowledged() { request.requiresAcknowledgement(false); acknowledgment = false; httpStatus = null; reasonPhraseC.recycle(); } // --------------------
{@inheritDoc}
/** * {@inheritDoc} */
@Override protected void reset() { httpStatus = null; acknowledgment = false; allowCustomReasonPhrase = true; isHtmlEncodingCustomReasonPhrase = true; reasonPhraseC.recycle(); locale = null; contentLanguage = null; request = null; super.reset(); }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public final boolean isRequest() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String toString() { final StringBuilder sb = new StringBuilder(256); sb.append("HttpResponsePacket (\n status=").append(getStatus()).append("\n reason=").append(getReasonPhrase()).append("\n protocol=") .append(getProtocol().getProtocolString()).append("\n content-length=").append(getContentLength()).append("\n committed=") .append(isCommitted()).append("\n headers=["); final MimeHeaders headersLocal = getHeaders(); for (final String name : headersLocal.names()) { for (String value : headersLocal.values(name)) { sb.append("\n ").append(name).append('=').append(value); } } sb.append("]\n)"); return sb.toString(); }
Returns:the Locale of this response.
/** * @return the {@link Locale} of this response. */
public Locale getLocale() { return locale; }
Called explicitly by user to set the Content-Language and the default encoding
/** * Called explicitly by user to set the Content-Language and the default encoding */
public void setLocale(final Locale locale) { if (locale == null) { return; // throw an exception? } // Save the locale for use by getLocale() this.locale = locale; // Set the contentLanguage for header output contentLanguage = locale.getLanguage(); if (contentLanguage != null && contentLanguage.length() > 0) { final String country = locale.getCountry(); if (country != null && country.length() > 0) { final StringBuilder value = new StringBuilder(contentLanguage); value.append('-'); value.append(country); contentLanguage = value.toString(); } } }
Returns:the value that will be used by the Content-Language response header
/** * @return the value that will be used by the <code>Content-Language</code> response header */
public String getContentLanguage() { return contentLanguage; }
Set the value that will be used by the Content-Language response header.
/** * Set the value that will be used by the <code>Content-Language</code> response header. */
public void setContentLanguage(final String contentLanguage) { this.contentLanguage = contentLanguage; } @Override public void setContentLengthLong(long contentLength) { setChunked(contentLength < 0); super.setContentLengthLong(contentLength); } // ------------------------------------------------- Package Private Methods
Associates the request that triggered this response.
Params:
  • request – the request that triggered this response
/** * Associates the request that triggered this response. * * @param request the request that triggered this response */
public void setRequest(final HttpRequestPacket request) { this.request = request; } // ---------------------------------------------------------- Nested Classes
HttpResponsePacket message builder.
/** * <tt>HttpResponsePacket</tt> message builder. */
public static class Builder extends HttpHeader.Builder<Builder> { protected Integer status; protected String reasonPhrase; protected HttpRequestPacket requestPacket;
Sets the status code for this response.
Params:
  • status – the status code for this response.
/** * Sets the status code for this response. * * @param status the status code for this response. */
public Builder status(final int status) { this.status = status; return this; }
Sets the status reason phrase for this response.
Params:
  • reasonPhrase – the status reason phrase for this response.
/** * Sets the status reason phrase for this response. * * @param reasonPhrase the status reason phrase for this response. */
public Builder reasonPhrase(final String reasonPhrase) { this.reasonPhrase = reasonPhrase; return this; } public Builder requestPacket(final HttpRequestPacket requestPacket) { this.requestPacket = requestPacket; return this; }
Build the HttpResponsePacket message.
Returns:HttpResponsePacket
/** * Build the <tt>HttpResponsePacket</tt> message. * * @return <tt>HttpResponsePacket</tt> */
@Override public final HttpResponsePacket build() { HttpResponsePacket responsePacket = (HttpResponsePacket) super.build(); if (status != null) { responsePacket.setStatus(status); } if (reasonPhrase != null) { responsePacket.setReasonPhrase(reasonPhrase); } return responsePacket; } @Override public void reset() { super.reset(); status = null; reasonPhrase = null; } @Override protected HttpHeader create() { if (requestPacket == null) { throw new IllegalStateException("Unable to create new HttpResponsePacket. No HttpRequestPacket available."); } HttpResponsePacket responsePacket = requestPacket.getResponse(); if (responsePacket == null) { responsePacket = HttpResponsePacketImpl.create(); responsePacket.setRequest(requestPacket); responsePacket.setSecure(requestPacket.isSecure()); } return responsePacket; } } }