001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020: package org.apache.mina.filter.codec.statemachine;
021:
022: import org.apache.mina.common.IoBuffer;
023: import org.apache.mina.filter.codec.ProtocolDecoderOutput;
024:
025: /**
026: * A decoder which writes all read bytes in to a known <code>Bytes</code>
027: * context until a <code>CRLF</code> has been encountered
028: *
029: * @author The Apache MINA Project (dev@mina.apache.org)
030: * @version $Rev: 601994 $, $Date: 2007-12-06 21:58:00 -0700 (Thu, 06 Dec 2007) $
031: */
032: public abstract class ConsumeToCrLfDecodingState implements
033: DecodingState {
034:
035: /**
036: * Carriage return character
037: */
038: private static final byte CR = 13;
039:
040: /**
041: * Line feed character
042: */
043: private static final byte LF = 10;
044:
045: private boolean lastIsCR;
046:
047: private IoBuffer buffer;
048:
049: /**
050: * Creates a new instance.
051: */
052: public ConsumeToCrLfDecodingState() {
053: }
054:
055: public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out)
056: throws Exception {
057: int beginPos = in.position();
058: int limit = in.limit();
059: int terminatorPos = -1;
060:
061: for (int i = beginPos; i < limit; i++) {
062: byte b = in.get(i);
063: if (b == CR) {
064: lastIsCR = true;
065: } else {
066: if (b == LF && lastIsCR) {
067: terminatorPos = i;
068: break;
069: }
070: lastIsCR = false;
071: }
072: }
073:
074: if (terminatorPos >= 0) {
075: IoBuffer product;
076:
077: int endPos = terminatorPos - 1;
078:
079: if (beginPos < endPos) {
080: in.limit(endPos);
081:
082: if (buffer == null) {
083: product = in.slice();
084: } else {
085: buffer.put(in);
086: product = buffer.flip();
087: buffer = null;
088: }
089:
090: in.limit(limit);
091: } else {
092: // When input contained only CR or LF rather than actual data...
093: if (buffer == null) {
094: product = IoBuffer.allocate(0);
095: } else {
096: product = buffer.flip();
097: buffer = null;
098: }
099: }
100: in.position(terminatorPos + 1);
101: return finishDecode(product, out);
102: } else {
103: in.position(beginPos);
104: if (buffer == null) {
105: buffer = IoBuffer.allocate(in.remaining());
106: buffer.setAutoExpand(true);
107: }
108:
109: buffer.put(in);
110: if (lastIsCR) {
111: buffer.position(buffer.position() - 1);
112: }
113: return this ;
114: }
115: }
116:
117: public DecodingState finishDecode(ProtocolDecoderOutput out)
118: throws Exception {
119: IoBuffer product;
120: // When input contained only CR or LF rather than actual data...
121: if (buffer == null) {
122: product = IoBuffer.allocate(0);
123: } else {
124: product = buffer.flip();
125: buffer = null;
126: }
127: return finishDecode(product, out);
128: }
129:
130: protected abstract DecodingState finishDecode(IoBuffer product,
131: ProtocolDecoderOutput out) throws Exception;
132: }
|