📄 abstractiofilterchain.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.common.support;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import org.apache.mina.common.ConnectFuture;import org.apache.mina.common.IdleStatus;import org.apache.mina.common.IoFilter;import org.apache.mina.common.IoFilterAdapter;import org.apache.mina.common.IoFilterChain;import org.apache.mina.common.IoFilterLifeCycleException;import org.apache.mina.common.IoSession;import org.apache.mina.common.IoFilter.NextFilter;import org.apache.mina.common.IoFilter.WriteRequest;import org.apache.mina.util.ByteBufferUtil;import org.apache.mina.util.SessionLog;/** * An abstract implementation of {@link IoFilterChain} that provides * common operations for developers to implement their own transport layer. * <p> * The only method a developer should implement is * {@link #doWrite(IoSession, IoFilter.WriteRequest)}. This method is invoked * when filter chain is evaluated for * {@link IoFilter#filterWrite(NextFilter, IoSession, IoFilter.WriteRequest)} and * finally to be written out. * * @author The Apache Directory Project (mina-dev@directory.apache.org) * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (금, 13 7월 2007) $ */public abstract class AbstractIoFilterChain implements IoFilterChain { /** * A session attribute that stores a {@link ConnectFuture} related with * the {@link IoSession}. {@link AbstractIoFilterChain} clears this * attribute and notifies the future when {@link #fireSessionOpened(IoSession)} * or {@link #fireExceptionCaught(IoSession, Throwable)} is invoked */ public static final String CONNECT_FUTURE = AbstractIoFilterChain.class .getName() + ".connectFuture"; private final IoSession session; private final Map<String, Entry> name2entry = new HashMap<String, Entry>(); private final EntryImpl head; private final EntryImpl tail; protected AbstractIoFilterChain(IoSession session) { if (session == null) { throw new NullPointerException("session"); } this.session = session; head = new EntryImpl(null, null, "head", new HeadFilter()); tail = new EntryImpl(head, null, "tail", new TailFilter()); head.nextEntry = tail; } public IoSession getSession() { return session; } public Entry getEntry(String name) { Entry e = name2entry.get(name); if (e == null) { return null; } return e; } public IoFilter get(String name) { Entry e = getEntry(name); if (e == null) { return null; } return e.getFilter(); } public NextFilter getNextFilter(String name) { Entry e = getEntry(name); if (e == null) { return null; } return e.getNextFilter(); } public synchronized void addFirst(String name, IoFilter filter) { checkAddable(name); register(head, name, filter); } public synchronized void addLast(String name, IoFilter filter) { checkAddable(name); register(tail.prevEntry, name, filter); } public synchronized void addBefore(String baseName, String name, IoFilter filter) { EntryImpl baseEntry = checkOldName(baseName); checkAddable(name); register(baseEntry.prevEntry, name, filter); } public synchronized void addAfter(String baseName, String name, IoFilter filter) { EntryImpl baseEntry = checkOldName(baseName); checkAddable(name); register(baseEntry, name, filter); } public synchronized IoFilter remove(String name) { EntryImpl entry = checkOldName(name); deregister(entry); return entry.getFilter(); } public synchronized void clear() throws Exception { Iterator<String> it = new ArrayList<String>(name2entry.keySet()) .iterator(); while (it.hasNext()) { this.remove(it.next()); } } private void register(EntryImpl prevEntry, String name, IoFilter filter) { EntryImpl newEntry = new EntryImpl(prevEntry, prevEntry.nextEntry, name, filter); try { filter.onPreAdd(this, name, newEntry.getNextFilter()); } catch (Exception e) { throw new IoFilterLifeCycleException("onPreAdd(): " + name + ':' + filter + " in " + getSession(), e); } prevEntry.nextEntry.prevEntry = newEntry; prevEntry.nextEntry = newEntry; name2entry.put(name, newEntry); try { filter.onPostAdd(this, name, newEntry.getNextFilter()); } catch (Exception e) { deregister0(newEntry); throw new IoFilterLifeCycleException("onPostAdd(): " + name + ':' + filter + " in " + getSession(), e); } } private void deregister(EntryImpl entry) { IoFilter filter = entry.getFilter(); try { filter.onPreRemove(this, entry.getName(), entry.getNextFilter()); } catch (Exception e) { throw new IoFilterLifeCycleException("onPreRemove(): " + entry.getName() + ':' + filter + " in " + getSession(), e); } deregister0(entry); try { filter.onPostRemove(this, entry.getName(), entry.getNextFilter()); } catch (Exception e) { throw new IoFilterLifeCycleException("onPostRemove(): " + entry.getName() + ':' + filter + " in " + getSession(), e); } } private void deregister0(EntryImpl entry) { EntryImpl prevEntry = entry.prevEntry; EntryImpl nextEntry = entry.nextEntry; prevEntry.nextEntry = nextEntry; nextEntry.prevEntry = prevEntry; name2entry.remove(entry.name); } /** * Throws an exception when the specified filter name is not registered in this chain. * * @return An filter entry with the specified name. */ private EntryImpl checkOldName(String baseName) { EntryImpl e = (EntryImpl) name2entry.get(baseName); if (e == null) { throw new IllegalArgumentException("Unknown filter name:" + baseName); } return e; } /** * Checks the specified filter name is already taken and throws an exception if already taken. */ private void checkAddable(String name) { if (name2entry.containsKey(name)) { throw new IllegalArgumentException( "Other filter is using the same name '" + name + "'"); } } public void fireSessionCreated(IoSession session) { Entry head = this.head; callNextSessionCreated(head, session); } private void callNextSessionCreated(Entry entry, IoSession session) { try { entry.getFilter().sessionCreated(entry.getNextFilter(), session); } catch (Throwable e) { fireExceptionCaught(session, e); } } public void fireSessionOpened(IoSession session) { Entry head = this.head; callNextSessionOpened(head, session); } private void callNextSessionOpened(Entry entry, IoSession session) { try { entry.getFilter().sessionOpened(entry.getNextFilter(), session); } catch (Throwable e) { fireExceptionCaught(session, e); } } public void fireSessionClosed(IoSession session) { // Update future. try { session.getCloseFuture().setClosed(); } catch (Throwable t) { fireExceptionCaught(session, t); } // And start the chain. Entry head = this.head; callNextSessionClosed(head, session); } private void callNextSessionClosed(Entry entry, IoSession session) { try { entry.getFilter().sessionClosed(entry.getNextFilter(), session); } catch (Throwable e) { fireExceptionCaught(session, e); } } public void fireSessionIdle(IoSession session, IdleStatus status) { Entry head = this.head; callNextSessionIdle(head, session, status); } private void callNextSessionIdle(Entry entry, IoSession session, IdleStatus status) { try { entry.getFilter().sessionIdle(entry.getNextFilter(), session, status); } catch (Throwable e) { fireExceptionCaught(session, e); } } public void fireMessageReceived(IoSession session, Object message) { Entry head = this.head; callNextMessageReceived(head, session, message); } private void callNextMessageReceived(Entry entry, IoSession session, Object message) { try { entry.getFilter().messageReceived(entry.getNextFilter(), session, message); } catch (Throwable e) { fireExceptionCaught(session, e); } } public void fireMessageSent(IoSession session, WriteRequest request) { try { request.getFuture().setWritten(true); } catch (Throwable t) { fireExceptionCaught(session, t); } Entry head = this.head; callNextMessageSent(head, session, request.getMessage()); } private void callNextMessageSent(Entry entry, IoSession session, Object message) { try { entry.getFilter().messageSent(entry.getNextFilter(), session, message); } catch (Throwable e) { fireExceptionCaught(session, e); } } public void fireExceptionCaught(IoSession session, Throwable cause) { // Notify the related ConnectFuture // if the session is created from SocketConnector. ConnectFuture future = (ConnectFuture) session .removeAttribute(CONNECT_FUTURE); if (future == null) { Entry head = this.head; callNextExceptionCaught(head, session, cause); } else { // Please note that this place is not the only place that // calls ConnectFuture.setException(). future.setException(cause); } } private void callNextExceptionCaught(Entry entry, IoSession session, Throwable cause) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -