📄 protocolcodecfilter.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */package org.apache.mina.filter.codec;import java.net.SocketAddress;import java.util.Queue;import org.apache.mina.core.buffer.IoBuffer;import org.apache.mina.core.file.FileRegion;import org.apache.mina.core.filterchain.IoFilter;import org.apache.mina.core.filterchain.IoFilterAdapter;import org.apache.mina.core.filterchain.IoFilterChain;import org.apache.mina.core.future.DefaultWriteFuture;import org.apache.mina.core.future.WriteFuture;import org.apache.mina.core.session.AttributeKey;import org.apache.mina.core.session.IoSession;import org.apache.mina.core.write.DefaultWriteRequest;import org.apache.mina.core.write.NothingWrittenException;import org.apache.mina.core.write.WriteRequest;import org.apache.mina.core.write.WriteRequestWrapper;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * An {@link IoFilter} which translates binary or protocol specific data into * message object and vice versa using {@link ProtocolCodecFactory}, * {@link ProtocolEncoder}, or {@link ProtocolDecoder}. * * @author The Apache MINA Project (dev@mina.apache.org) * @version $Rev: 756234 $, $Date: 2009-03-19 23:07:05 +0100 (Thu, 19 Mar 2009) $ * @org.apache.xbean.XBean */public class ProtocolCodecFilter extends IoFilterAdapter { private static final Class<?>[] EMPTY_PARAMS = new Class[0]; private static final IoBuffer EMPTY_BUFFER = IoBuffer.wrap(new byte[0]); private final AttributeKey ENCODER = new AttributeKey(getClass(), "encoder"); private final AttributeKey DECODER = new AttributeKey(getClass(), "decoder"); private final AttributeKey DECODER_OUT = new AttributeKey(getClass(), "decoderOut"); private final AttributeKey ENCODER_OUT = new AttributeKey(getClass(), "encoderOut"); /** The factory responsible for creating the encoder and decoder */ private final ProtocolCodecFactory factory; private final Logger logger = LoggerFactory.getLogger(getClass()); /** * * Creates a new instance of ProtocolCodecFilter, associating a factory * for the creation of the encoder and decoder. * * @param factory The associated factory */ public ProtocolCodecFilter(ProtocolCodecFactory factory) { if (factory == null) { throw new NullPointerException("factory"); } this.factory = factory; } /** * Creates a new instance of ProtocolCodecFilter, without any factory. * The encoder/decoder factory will be created as an inner class, using * the two parameters (encoder and decoder). * * @param encoder The class responsible for encoding the message * @param decoder The class responsible for decoding the message */ public ProtocolCodecFilter(final ProtocolEncoder encoder, final ProtocolDecoder decoder) { if (encoder == null) { throw new NullPointerException("encoder"); } if (decoder == null) { throw new NullPointerException("decoder"); } // Create the inner Factory based on the two parameters this.factory = new ProtocolCodecFactory() { public ProtocolEncoder getEncoder(IoSession session) { return encoder; } public ProtocolDecoder getDecoder(IoSession session) { return decoder; } }; } /** * Creates a new instance of ProtocolCodecFilter, without any factory. * The encoder/decoder factory will be created as an inner class, using * the two parameters (encoder and decoder), which are class names. Instances * for those classes will be created in this constructor. * * @param encoder The class responsible for encoding the message * @param decoder The class responsible for decoding the message */ public ProtocolCodecFilter( final Class<? extends ProtocolEncoder> encoderClass, final Class<? extends ProtocolDecoder> decoderClass) { if (encoderClass == null) { throw new NullPointerException("encoderClass"); } if (decoderClass == null) { throw new NullPointerException("decoderClass"); } if (!ProtocolEncoder.class.isAssignableFrom(encoderClass)) { throw new IllegalArgumentException("encoderClass: " + encoderClass.getName()); } if (!ProtocolDecoder.class.isAssignableFrom(decoderClass)) { throw new IllegalArgumentException("decoderClass: " + decoderClass.getName()); } try { encoderClass.getConstructor(EMPTY_PARAMS); } catch (NoSuchMethodException e) { throw new IllegalArgumentException( "encoderClass doesn't have a public default constructor."); } try { decoderClass.getConstructor(EMPTY_PARAMS); } catch (NoSuchMethodException e) { throw new IllegalArgumentException( "decoderClass doesn't have a public default constructor."); } // Create the inner Factory based on the two parameters. We instanciate // the encoder and decoder locally. this.factory = new ProtocolCodecFactory() { public ProtocolEncoder getEncoder(IoSession session) throws Exception { return encoderClass.newInstance(); } public ProtocolDecoder getDecoder(IoSession session) throws Exception { return decoderClass.newInstance(); } }; } /** * Get the encoder instance from a given session. * * @param session The associated session we will get the encoder from * @return The encoder instance, if any */ public ProtocolEncoder getEncoder(IoSession session) { return (ProtocolEncoder) session.getAttribute(ENCODER); } @Override public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { if (parent.contains(this)) { throw new IllegalArgumentException( "You can't add the same filter instance more than once. Create another instance and add it."); } // Initialize the encoder and decoder initCodec(parent.getSession()); } @Override public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception { // Clean everything disposeCodec(parent.getSession()); } /** * Process the incoming message, calling the session decoder. As the incoming * buffer might contains more than one messages, we have to loop until the decoder * throws an exception. * * while ( buffer not empty ) * try * decode ( buffer ) * catch * break; * */ @Override public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { if (!(message instanceof IoBuffer)) { nextFilter.messageReceived(session, message); return; } IoBuffer in = (IoBuffer) message; ProtocolDecoder decoder = getDecoder(session); ProtocolDecoderOutput decoderOut = getDecoderOut(session, nextFilter); // Loop until we don't have anymore byte in the buffer, // or until the decoder throws an unrecoverable exception or // can't decoder a message, because there are not enough // data in the buffer while (in.hasRemaining()) { int oldPos = in.position(); try { synchronized (decoderOut) { // Call the decoder with the read bytes decoder.decode(session, in, decoderOut); } // Finish decoding if no exception was thrown. decoderOut.flush(nextFilter, session); } catch (Throwable t) { ProtocolDecoderException pde; if (t instanceof ProtocolDecoderException) { pde = (ProtocolDecoderException) t; } else { pde = new ProtocolDecoderException(t); } if (pde.getHexdump() == null) { // Generate a message hex dump int curPos = in.position(); in.position(oldPos); pde.setHexdump(in.getHexDump()); in.position(curPos); } // Fire the exceptionCaught event. decoderOut.flush(nextFilter, session); nextFilter.exceptionCaught(session, pde); // Retry only if the type of the caught exception is // recoverable and the buffer position has changed. // We check buffer position additionally to prevent an // infinite loop. if (!(t instanceof RecoverableProtocolDecoderException) || (in.position() == oldPos)) { break; } } } } @Override public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { if (writeRequest instanceof EncodedWriteRequest) { return; } if (!(writeRequest instanceof MessageWriteRequest)) { nextFilter.messageSent(session, writeRequest); return; } MessageWriteRequest wrappedRequest = (MessageWriteRequest) writeRequest; nextFilter.messageSent(session, wrappedRequest.getParentRequest()); } @Override public void filterWrite(NextFilter nextFilter, IoSession session,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -