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    public SessionAttributeInitializingFilter(Map<String, ? extends Object> attributes) {
058        setAttributes(attributes);
059    }
060
061    /**
062     * Returns the value of user-defined attribute.
063     *
064     * @param key the key of the attribute
065     * @return <tt>null</tt> if there is no attribute with the specified key
066     */
067    public Object getAttribute(String key) {
068        return attributes.get(key);
069    }
070
071    /**
072     * Sets a user-defined attribute.
073     *
074     * @param key the key of the attribute
075     * @param value the value of the attribute
076     * @return The old value of the attribute.  <tt>null</tt> if it is new.
077     */
078    public Object setAttribute(String key, Object value) {
079        if (value == null) {
080            return removeAttribute(key);
081        }
082
083        return attributes.put(key, value);
084    }
085
086    /**
087     * Sets a user defined attribute without a value.  This is useful when
088     * you just want to put a 'mark' attribute.  Its value is set to
089     * {@link Boolean#TRUE}.
090     *
091     * @param key the key of the attribute
092     * @return The old value of the attribute.  <tt>null</tt> if it is new.
093     */
094    public Object setAttribute(String key) {
095        return attributes.put(key, Boolean.TRUE);
096    }
097
098    /**
099     * Removes a user-defined attribute with the specified key.
100     *
101     * @return The old value of the attribute.  <tt>null</tt> if not found.
102     */
103    public Object removeAttribute(String key) {
104        return attributes.remove(key);
105    }
106
107    /**
108     * Returns <tt>true</tt> if this session contains the attribute with
109     * the specified <tt>key</tt>.
110     */
111    boolean containsAttribute(String key) {
112        return attributes.containsKey(key);
113    }
114
115    /**
116     * Returns the set of keys of all user-defined attributes.
117     */
118    public Set<String> getAttributeKeys() {
119        return attributes.keySet();
120    }
121
122    /**
123     * Sets the attribute map.  The specified attributes are copied into the
124     * underlying map, so modifying the specified attributes parameter after
125     * the call won't change the internal state.
126     */
127    public void setAttributes(Map<String, ? extends Object> attributes) {
128        if (attributes == null) {
129            attributes = new ConcurrentHashMap<String, Object>();
130        }
131
132        this.attributes.clear();
133        this.attributes.putAll(attributes);
134    }
135
136    /**
137     * Puts all pre-configured attributes into the actual session attribute
138     * map and forward the event to the next filter.
139     */
140    @Override
141    public void sessionCreated(NextFilter nextFilter, IoSession session) throws Exception {
142        for (Map.Entry<String, Object> e : attributes.entrySet()) {
143            session.setAttribute(e.getKey(), e.getValue());
144        }
145
146        nextFilter.sessionCreated(session);
147    }
148}