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.util;
021
022import java.util.Map;
023import java.util.Set;
024import java.util.concurrent.ConcurrentHashMap;
025
026import org.apache.mina.core.filterchain.IoFilter;
027import org.apache.mina.core.filterchain.IoFilterAdapter;
028import org.apache.mina.core.session.IoSession;
029
030/**
031 * An {@link IoFilter} that sets initial attributes when a new
032 * {@link IoSession} is created.  By default, the attribute map is empty when
033 * an {@link IoSession} is newly created.  Inserting this filter will make
034 * the pre-configured attributes available after this filter executes the
035 * <tt>sessionCreated</tt> event.
036 *
037 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
038 * @org.apache.xbean.XBean
039 */
040public class SessionAttributeInitializingFilter extends IoFilterAdapter {
041    private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
042
043    /**
044     * Creates a new instance with no default attributes.  You can set
045     * the additional attributes by calling methods such as
046     * {@link #setAttribute(String, Object)} and {@link #setAttributes(Map)}.
047     */
048    public SessionAttributeInitializingFilter() {
049        // Do nothing
050    }
051
052    /**
053     * Creates a new instance with the specified default attributes.  You can
054     * set the additional attributes by calling methods such as
055     * {@link #setAttribute(String, Object)} and {@link #setAttributes(Map)}.
056     * 
057     * @param attributes The Attribute's Map to set 
058     */
059    public SessionAttributeInitializingFilter(Map<String, ? extends Object> attributes) {
060        setAttributes(attributes);
061    }
062
063    /**
064     * Returns the value of user-defined attribute.
065     *
066     * @param key the key of the attribute
067     * @return <tt>null</tt> if there is no attribute with the specified key
068     */
069    public Object getAttribute(String key) {
070        return attributes.get(key);
071    }
072
073    /**
074     * Sets a user-defined attribute.
075     *
076     * @param key the key of the attribute
077     * @param value the value of the attribute
078     * @return The old value of the attribute.  <tt>null</tt> if it is new.
079     */
080    public Object setAttribute(String key, Object value) {
081        if (value == null) {
082            return removeAttribute(key);
083        }
084
085        return attributes.put(key, value);
086    }
087
088    /**
089     * Sets a user defined attribute without a value.  This is useful when
090     * you just want to put a 'mark' attribute.  Its value is set to
091     * {@link Boolean#TRUE}.
092     *
093     * @param key the key of the attribute
094     * @return The old value of the attribute.  <tt>null</tt> if it is new.
095     */
096    public Object setAttribute(String key) {
097        return attributes.put(key, Boolean.TRUE);
098    }
099
100    /**
101     * Removes a user-defined attribute with the specified key.
102     *
103     * @param key The attribut's key we want to removee
104     * @return The old value of the attribute.  <tt>null</tt> if not found.
105     */
106    public Object removeAttribute(String key) {
107        return attributes.remove(key);
108    }
109
110    /**
111     * @return <tt>true</tt> if this session contains the attribute with
112     * the specified <tt>key</tt>.
113     */
114    boolean containsAttribute(String key) {
115        return attributes.containsKey(key);
116    }
117
118    /**
119     * @return the set of keys of all user-defined attributes.
120     */
121    public Set<String> getAttributeKeys() {
122        return attributes.keySet();
123    }
124
125    /**
126     * Sets the attribute map.  The specified attributes are copied into the
127     * underlying map, so modifying the specified attributes parameter after
128     * the call won't change the internal state.
129     * 
130     * @param attributes The attributes Map to set
131     */
132    public void setAttributes(Map<String, ? extends Object> attributes) {
133        if (attributes == null) {
134            attributes = new ConcurrentHashMap<String, Object>();
135        }
136
137        this.attributes.clear();
138        this.attributes.putAll(attributes);
139    }
140
141    /**
142     * Puts all pre-configured attributes into the actual session attribute
143     * map and forward the event to the next filter.
144     */
145    @Override
146    public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
147        for (Map.Entry<String, Object> e : attributes.entrySet()) {
148            session.setAttribute(e.getKey(), e.getValue());
149        }
150
151        nextFilter.sessionCreated(session);
152    }
153}