001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027
028package org.apache.http.message;
029
030import java.io.Serializable;
031
032import org.apache.http.FormattedHeader;
033import org.apache.http.HeaderElement;
034import org.apache.http.ParseException;
035import org.apache.http.util.Args;
036import org.apache.http.util.CharArrayBuffer;
037
038/**
039 * This class represents a raw HTTP header whose content is parsed 'on demand'
040 * only when the header value needs to be consumed.
041 *
042 * @since 4.0
043 */
044public class BufferedHeader implements FormattedHeader, Cloneable, Serializable {
045
046    private static final long serialVersionUID = -2768352615787625448L;
047
048    /**
049     * Header name.
050     */
051    private final String name;
052
053    /**
054     * The buffer containing the entire header line.
055     */
056    private final CharArrayBuffer buffer;
057
058    /**
059     * The beginning of the header value in the buffer
060     */
061    private final int valuePos;
062
063
064    /**
065     * Creates a new header from a buffer.
066     * The name of the header will be parsed immediately,
067     * the value only if it is accessed.
068     *
069     * @param buffer    the buffer containing the header to represent
070     *
071     * @throws ParseException   in case of a parse error
072     */
073    public BufferedHeader(final CharArrayBuffer buffer)
074        throws ParseException {
075
076        super();
077        Args.notNull(buffer, "Char array buffer");
078        final int colon = buffer.indexOf(':');
079        if (colon == -1) {
080            throw new ParseException
081                ("Invalid header: " + buffer.toString());
082        }
083        final String s = buffer.substringTrimmed(0, colon);
084        if (s.length() == 0) {
085            throw new ParseException
086                ("Invalid header: " + buffer.toString());
087        }
088        this.buffer = buffer;
089        this.name = s;
090        this.valuePos = colon + 1;
091    }
092
093
094    @Override
095    public String getName() {
096        return this.name;
097    }
098
099    @Override
100    public String getValue() {
101        return this.buffer.substringTrimmed(this.valuePos, this.buffer.length());
102    }
103
104    @Override
105    public HeaderElement[] getElements() throws ParseException {
106        final ParserCursor cursor = new ParserCursor(0, this.buffer.length());
107        cursor.updatePos(this.valuePos);
108        return BasicHeaderValueParser.INSTANCE.parseElements(this.buffer, cursor);
109    }
110
111    @Override
112    public int getValuePos() {
113        return this.valuePos;
114    }
115
116    @Override
117    public CharArrayBuffer getBuffer() {
118        return this.buffer;
119    }
120
121    @Override
122    public String toString() {
123        return this.buffer.toString();
124    }
125
126    @Override
127    public Object clone() throws CloneNotSupportedException {
128        // buffer is considered immutable
129        // no need to make a copy of it
130        return super.clone();
131    }
132
133}