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 */ 020package org.apache.mina.filter.codec.statemachine; 021 022import org.apache.mina.core.buffer.IoBuffer; 023import org.apache.mina.filter.codec.ProtocolDecoderException; 024import org.apache.mina.filter.codec.ProtocolDecoderOutput; 025 026/** 027 * {@link DecodingState} which consumes all received bytes until the session is 028 * closed. 029 * 030 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 031 */ 032public abstract class ConsumeToEndOfSessionDecodingState implements DecodingState { 033 034 private IoBuffer buffer; 035 036 private final int maxLength; 037 038 /** 039 * Creates a new instance using the specified maximum length. 040 * 041 * @param maxLength the maximum number of bytes which will be consumed. If 042 * this max is reached a {@link ProtocolDecoderException} will be 043 * thrown by {@link #decode(IoBuffer, ProtocolDecoderOutput)}. 044 */ 045 public ConsumeToEndOfSessionDecodingState(int maxLength) { 046 this.maxLength = maxLength; 047 } 048 049 /** 050 * {@inheritDoc} 051 */ 052 public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { 053 if (buffer == null) { 054 buffer = IoBuffer.allocate(256).setAutoExpand(true); 055 } 056 057 if (buffer.position() + in.remaining() > maxLength) { 058 throw new ProtocolDecoderException("Received data exceeds " + maxLength + " byte(s)."); 059 } 060 buffer.put(in); 061 return this; 062 } 063 064 /** 065 * {@inheritDoc} 066 */ 067 public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { 068 try { 069 if (buffer == null) { 070 buffer = IoBuffer.allocate(0); 071 } 072 buffer.flip(); 073 return finishDecode(buffer, out); 074 } finally { 075 buffer = null; 076 } 077 } 078 079 /** 080 * Invoked when this state has consumed all bytes until the session is 081 * closed. 082 * 083 * @param product the bytes read. 084 * @param out the current {@link ProtocolDecoderOutput} used to write 085 * decoded messages. 086 * @return the next state if a state transition was triggered (use 087 * <code>this</code> for loop transitions) or <code>null</code> if 088 * the state machine has reached its end. 089 * @throws Exception if the read data violated protocol specification. 090 */ 091 protected abstract DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception; 092}