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.ProtocolDecoderOutput; 024 025/** 026 * {@link DecodingState} which skips data until {@link #canSkip(byte)} returns 027 * <tt>false</tt>. 028 * 029 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 030 */ 031public abstract class SkippingState implements DecodingState { 032 033 private int skippedBytes; 034 035 /** 036 * {@inheritDoc} 037 */ 038 public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception { 039 int beginPos = in.position(); 040 int limit = in.limit(); 041 for (int i = beginPos; i < limit; i++) { 042 byte b = in.get(i); 043 if (!canSkip(b)) { 044 in.position(i); 045 int answer = this.skippedBytes; 046 this.skippedBytes = 0; 047 return finishDecode(answer); 048 } 049 050 skippedBytes++; 051 } 052 053 in.position(limit); 054 return this; 055 } 056 057 /** 058 * {@inheritDoc} 059 */ 060 public DecodingState finishDecode(ProtocolDecoderOutput out) throws Exception { 061 return finishDecode(skippedBytes); 062 } 063 064 /** 065 * Called to determine whether the specified byte can be skipped. 066 * 067 * @param b the byte to check. 068 * @return <tt>true</tt> if the byte can be skipped. 069 */ 070 protected abstract boolean canSkip(byte b); 071 072 /** 073 * Invoked when this state cannot skip any more bytes. 074 * 075 * @param skippedBytes the number of bytes skipped. 076 * @return the next state if a state transition was triggered (use 077 * <code>this</code> for loop transitions) or <code>null</code> if 078 * the state machine has reached its end. 079 * @throws Exception if the read data violated protocol specification. 080 */ 081 protected abstract DecodingState finishDecode(int skippedBytes) throws Exception; 082}