001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2010–2011 ApexIdentity Inc.
015 * Portions Copyright 2011-2014 ForgeRock AS.
016 */
017
018package org.forgerock.openig.header;
019
020import static java.lang.Long.*;
021
022import org.forgerock.openig.http.Message;
023
024/**
025 * Processes the <strong>{@code Content-Length}</strong> message header. For more information,
026 * see <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a> §14.13.
027 */
028public class ContentLengthHeader implements Header {
029
030    /** The name of the header that this object represents. */
031    public static final String NAME = "Content-Length";
032
033    /** The content length, or {@code -1} if not specified. */
034    private long length = -1;
035
036    /**
037     * Constructs a new empty header.
038     */
039    public ContentLengthHeader() {
040    }
041
042    /**
043     * Constructs a new header, initialized from the specified message.
044     *
045     * @param message the message to initialize the header from.
046     */
047    public ContentLengthHeader(Message<?> message) {
048        fromMessage(message);
049    }
050
051    /**
052     * Constructs a new header, initialized from the specified string value.
053     *
054     * @param string the value to initialize the header from.
055     */
056    public ContentLengthHeader(String string) {
057        fromString(string);
058    }
059
060    /**
061     * Returns a non-negative value when content length is known or {@code -1}
062     * when content length is not known.
063     *
064     * @return a non-negative value when content length is known or {@code -1}
065     *         when content length is not known.
066     */
067    public long getLength() {
068        return length;
069    }
070
071    @Override
072    public String getKey() {
073        return NAME;
074    }
075
076    @Override
077    public void fromMessage(Message<?> message) {
078        if (message != null && message.getHeaders() != null) {
079            // expect only one header value
080            fromString(message.getHeaders().getFirst(NAME));
081        }
082    }
083
084    @Override
085    public void fromString(String string) {
086        length = -1;
087        if (string != null) {
088            try {
089                final long value = parseLong(string);
090                length = value >= 0 ? value : -1;
091            } catch (NumberFormatException nfe) {
092                // Ignored.
093            }
094        }
095    }
096
097    @Override
098    public void toMessage(Message<?> message) {
099        String value = toString();
100        if (value != null) {
101            message.getHeaders().putSingle(NAME, value);
102        }
103    }
104
105    @Override
106    public String toString() {
107        return length >= 0 ? Long.toString(length) : null;
108    }
109
110    @Override
111    public boolean equals(Object o) {
112        return o == this || (o instanceof ContentLengthHeader && length == ((ContentLengthHeader) o).length);
113    }
114
115    @Override
116    public int hashCode() {
117        return (int) (length ^ length >>> 32);
118    }
119}