/*
* 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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.apache.mina.common.IoFilter.NextFilter;
import org.apache.mina.common.IoFilterChain.Entry;
import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
/**
* The default implementation of {@link IoFilterChainBuilder} which is useful
* in most cases. {@link DefaultIoFilterChainBuilder} has an identical interface
* with {@link IoFilter}; it contains a list of {@link IoFilter}s that you can
* modify. The {@link IoFilter}s which are added to this builder will be appended
* to the {@link IoFilterChain} when {@link #buildFilterChain(IoFilterChain)} is
* invoked.
* <p>
* However, the identical interface doesn't mean that it behaves in an exactly
* same way with {@link IoFilterChain}. {@link DefaultIoFilterChainBuilder}
* doesn't manage the life cycle of the {@link IoFilter}s at all, and the
* existing {@link IoSession}s won't get affected by the changes in this builder.
* {@link IoFilterChainBuilder}s affect only newly created {@link IoSession}s.
*
* <pre>
* IoAcceptor acceptor = ...;
* DefaultIoFilterChainBuilder builder = acceptor.getFilterChain();
* builder.addLast( "myFilter", new MyFilter() );
* ...
* </pre>
*
* @author The Apache Directory Project (mina-dev@directory.apache.org)
* @version $Rev: 562335 $, $Date: 2007-08-03 14:28:02 +0900 (금, 03 8월 2007) $
*/
public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder,
Cloneable {
private final List entries;
/**
* Creates a new instance with an empty filter list.
*/
public DefaultIoFilterChainBuilder() {
entries = new CopyOnWriteArrayList();
}
/**
* @see IoFilterChain#getEntry(String)
*/
public Entry getEntry(String name) {
for (Iterator i = entries.iterator(); i.hasNext(); ) {
Entry e = (Entry) i.next();
if (e.getName().equals(name)) {
return e;
}
}
return null;
}
/**
* @see IoFilterChain#get(String)
*/
public IoFilter get(String name) {
Entry e = getEntry(name);
if (e == null) {
return null;
}
return e.getFilter();
}
/**
* @see IoFilterChain#getAll()
*/
public List getAll() {
return new ArrayList(entries);
}
/**
* @see IoFilterChain#getAllReversed()
*/
public List getAllReversed() {
List result = getAll();
Collections.reverse(result);
return result;
}
/**
* @see IoFilterChain#contains(String)
*/
public boolean contains(String name) {
return getEntry(name) != null;
}
/**
* @see IoFilterChain#contains(IoFilter)
*/
public boolean contains(IoFilter filter) {
for (Iterator i = entries.iterator(); i.hasNext();) {
Entry e = (Entry) i.next();
if (e.getFilter() == filter) {
return true;
}
}
return false;
}
/**
* @see IoFilterChain#contains(Class)
*/
public boolean contains(Class filterType) {
for (Iterator i = entries.iterator(); i.hasNext();) {
Entry e = (Entry) i.next();
if (filterType.isAssignableFrom(e.getFilter().getClass())) {
return true;
}
}
return false;
}
/**
* @see IoFilterChain#addFirst(String, IoFilter)
*/
public synchronized void addFirst(String name, IoFilter filter) {
register(0, new EntryImpl(name, filter));
}
/**
* @see IoFilterChain#addLast(String, IoFilter)
*/
public synchronized void addLast(String name, IoFilter filter) {
register(entries.size(), new EntryImpl(name, filter));
}
/**
* @see IoFilterChain#addBefore(String, String, IoFilter)
*/
public synchronized void addBefore(String baseName, String name,
IoFilter filter) {
checkBaseName(baseName);
for (ListIterator i = entries.listIterator(); i.hasNext();) {
Entry base = (Entry) i.next();
if (base.getName().equals(baseName)) {
register(i.previousIndex(), new EntryImpl(name, filter));
break;
}
}
}
/**
* @see IoFilterChain#addAfter(String, String, IoFilter)
*/
public synchronized void addAfter(String baseName, String name,
IoFilter filter) {
checkBaseName(baseName);
for (ListIterator i = entries.listIterator(); i.hasNext();) {
Entry base = (Entry) i.next();
if (base.getName().equals(baseName)) {
register(i.nextIndex(), new EntryImpl(name, filter));
break;
}
}
}
/**
* @see IoFilterChain#remove(String)
*/
public synchronized IoFilter remove(String name) {
if (name == null) {
throw new NullPointerException("name");
}
for (ListIterator i = entries.listIterator(); i.hasNext();) {
Entry e = (Entry) i.next();
if (e.getName().equals(name)) {
entries.remove(i.previousIndex());
return e.getFilter();
}
}
throw new IllegalArgumentException("Unknown filter name: " + name);
}
/**
* @see IoFilterChain#clear()
*/
public synchronized void clear() throws Exception {
entries.clear();
}
public void buildFilterChain(IoFilterChain chain) throws Exception {
for (Iterator i = entries.iterator(); i.hasNext();) {
Entry e = (Entry) i.next();
chain.addLast(e.getName(), e.getFilter());
}
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("{ ");
boolean empty = true;
for (Iterator i = entries.iterator(); i.hasNext();) {
Entry e = (Entry) i.next();
if (!empty) {
buf.append(", ");
} else {
empty = false;
}
buf.append('(');
buf.append(e.getName());
buf.append(':');
buf.append(e.getFilter());
buf.append(')');
}
if (empty) {
buf.append("empty");
}
buf.append(" }");
return buf.toString();
}
public Object clone() {
DefaultIoFilterChainBuilder ret = new DefaultIoFilterChainBuilder();
for (Iterator i = entries.iterator(); i.hasNext();) {
Entry e = (Entry) i.next();
ret.addLast(e.getName(), e.getFilter());
}
return ret;
}
private void checkBaseName(String baseName) {
if (baseName == null) {
throw new NullPointerException("baseName");
}
if (!contains(baseName)) {
throw new IllegalArgumentException("Unknown filter name: "
+ baseName);
}
}
private void register(int index, Entry e) {
if (contains(e.getName())) {
throw new IllegalArgumentException(
"Other filter is using the same name: " + e.getName());
}
entries.add(index, e);
}
private static class EntryImpl implements Entry {
private final String name;
private final IoFilter filter;
private EntryImpl(String name, IoFilter filter) {
if (name == null) {
throw new NullPointerException("name");
}
if (filter == null) {
throw new NullPointerException("filter");
}
this.name = name;
this.filter = filter;
}
public String getName() {
return name;
}
public IoFilter getFilter() {
return filter;
}
public NextFilter getNextFilter() {
throw new IllegalStateException();
}
public String toString() {
return "(" + getName() + ':' + filter + ')';
}
}
}