michael@0: /*
michael@0: * ====================================================================
michael@0: * Licensed to the Apache Software Foundation (ASF) under one
michael@0: * or more contributor license agreements. See the NOTICE file
michael@0: * distributed with this work for additional information
michael@0: * regarding copyright ownership. The ASF licenses this file
michael@0: * to you under the Apache License, Version 2.0 (the
michael@0: * "License"); you may not use this file except in compliance
michael@0: * with the License. You may obtain a copy of the License at
michael@0: *
michael@0: * http://www.apache.org/licenses/LICENSE-2.0
michael@0: *
michael@0: * Unless required by applicable law or agreed to in writing,
michael@0: * software distributed under the License is distributed on an
michael@0: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
michael@0: * KIND, either express or implied. See the License for the
michael@0: * specific language governing permissions and limitations
michael@0: * under the License.
michael@0: * ====================================================================
michael@0: *
michael@0: * This software consists of voluntary contributions made by many
michael@0: * individuals on behalf of the Apache Software Foundation. For more
michael@0: * information on the Apache Software Foundation, please see
michael@0: *
michael@0: * Note: This class was created by refactoring parsing code located in michael@0: * various other classes. The author tags from those other classes have michael@0: * been replicated here, although the association with the parsing code michael@0: * taken from there has not been traced. michael@0: *
michael@0: * michael@0: * @since 4.0 michael@0: */ michael@0: public class BasicLineParser implements LineParser { michael@0: michael@0: /** michael@0: * A default instance of this class, for use as default or fallback. michael@0: * Note that {@link BasicLineParser} is not a singleton, there can michael@0: * be many instances of the class itself and of derived classes. michael@0: * The instance here provides non-customized, default behavior. michael@0: */ michael@0: public final static BasicLineParser DEFAULT = new BasicLineParser(); michael@0: michael@0: michael@0: /** michael@0: * A version of the protocol to parse. michael@0: * The version is typically not relevant, but the protocol name. michael@0: */ michael@0: protected final ProtocolVersion protocol; michael@0: michael@0: michael@0: /** michael@0: * Creates a new line parser for the given HTTP-like protocol. michael@0: * michael@0: * @param proto a version of the protocol to parse, or michael@0: *null
for HTTP. The actual version
michael@0: * is not relevant, only the protocol name.
michael@0: */
michael@0: public BasicLineParser(ProtocolVersion proto) {
michael@0: if (proto == null) {
michael@0: proto = HttpVersion.HTTP_1_1;
michael@0: }
michael@0: this.protocol = proto;
michael@0: }
michael@0:
michael@0:
michael@0: /**
michael@0: * Creates a new line parser for HTTP.
michael@0: */
michael@0: public BasicLineParser() {
michael@0: this(null);
michael@0: }
michael@0:
michael@0:
michael@0: public final static
michael@0: ProtocolVersion parseProtocolVersion(String value,
michael@0: LineParser parser)
michael@0: throws ParseException {
michael@0:
michael@0: if (value == null) {
michael@0: throw new IllegalArgumentException
michael@0: ("Value to parse may not be null.");
michael@0: }
michael@0:
michael@0: if (parser == null)
michael@0: parser = BasicLineParser.DEFAULT;
michael@0:
michael@0: CharArrayBuffer buffer = new CharArrayBuffer(value.length());
michael@0: buffer.append(value);
michael@0: ParserCursor cursor = new ParserCursor(0, value.length());
michael@0: return parser.parseProtocolVersion(buffer, cursor);
michael@0: }
michael@0:
michael@0:
michael@0: // non-javadoc, see interface LineParser
michael@0: public ProtocolVersion parseProtocolVersion(final CharArrayBuffer buffer,
michael@0: final ParserCursor cursor)
michael@0: throws ParseException {
michael@0:
michael@0: if (buffer == null) {
michael@0: throw new IllegalArgumentException("Char array buffer may not be null");
michael@0: }
michael@0: if (cursor == null) {
michael@0: throw new IllegalArgumentException("Parser cursor may not be null");
michael@0: }
michael@0:
michael@0: final String protoname = this.protocol.getProtocol();
michael@0: final int protolength = protoname.length();
michael@0:
michael@0: int indexFrom = cursor.getPos();
michael@0: int indexTo = cursor.getUpperBound();
michael@0:
michael@0: skipWhitespace(buffer, cursor);
michael@0:
michael@0: int i = cursor.getPos();
michael@0:
michael@0: // long enough for "HTTP/1.1"?
michael@0: if (i + protolength + 4 > indexTo) {
michael@0: throw new ParseException
michael@0: ("Not a valid protocol version: " +
michael@0: buffer.substring(indexFrom, indexTo));
michael@0: }
michael@0:
michael@0: // check the protocol name and slash
michael@0: boolean ok = true;
michael@0: for (int j=0; ok && (j