mina-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1222398 - in /mina/trunk: core/src/main/java/org/apache/mina/api/ core/src/main/java/org/apache/mina/filter/codec/ core/src/main/java/org/apache/mina/session/ core/src/main/java/org/apache/mina/transport/tcp/ core/src/main/java/org/apache/...
Date Thu, 22 Dec 2011 19:08:30 GMT
Author: elecharny
Date: Thu Dec 22 19:08:30 2011
New Revision: 1222398

URL: http://svn.apache.org/viewvc?rev=1222398&view=rev
Log:
Applied Christian's patch for AttributeKey (cf DIRMINA-874)

Added:
    mina/trunk/core/src/main/java/org/apache/mina/session/AttributeContainer.java
    mina/trunk/core/src/main/java/org/apache/mina/session/AttributeKey.java
    mina/trunk/core/src/main/java/org/apache/mina/session/DefaultAttributeContainer.java
    mina/trunk/core/src/main/java/org/apache/mina/util/Assert.java
    mina/trunk/core/src/test/java/org/apache/mina/AllTests.java
    mina/trunk/core/src/test/java/org/apache/mina/session/AttributeContainerTest.java
    mina/trunk/core/src/test/java/org/apache/mina/session/AttributeKeyTest.java
    mina/trunk/core/src/test/java/org/apache/mina/util/AssertTest.java
Modified:
    mina/trunk/core/src/main/java/org/apache/mina/api/IoSession.java
    mina/trunk/core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecFilter.java
    mina/trunk/core/src/main/java/org/apache/mina/session/AbstractIoSession.java
    mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java
    mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java
    mina/trunk/core/src/test/java/org/apache/mina/session/AbstractIoSessionTest.java
    mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerCodec.java
    mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerDecoder.java

Modified: mina/trunk/core/src/main/java/org/apache/mina/api/IoSession.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/api/IoSession.java?rev=1222398&r1=1222397&r2=1222398&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/api/IoSession.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/api/IoSession.java Thu Dec 22 19:08:30 2011
@@ -20,6 +20,7 @@
 package org.apache.mina.api;
 
 import java.net.SocketAddress;
+import java.util.Collections;
 import java.util.Queue;
 import java.util.Set;
 
@@ -28,6 +29,8 @@ import javax.net.ssl.SSLException;
 
 import org.apache.mina.filterchain.IoFilterController;
 import org.apache.mina.service.SelectorProcessor;
+import org.apache.mina.session.AttributeKey;
+import org.apache.mina.session.SslHelper;
 import org.apache.mina.session.WriteRequest;
 
 /**
@@ -54,7 +57,7 @@ import org.apache.mina.session.WriteRequ
  */
 public interface IoSession {
     /** The SslHelper instance name, stored in the session's attributes */
-    static final String SSL_HELPER = "internal_sslHelper";
+    static final AttributeKey<SslHelper> SSL_HELPER = new AttributeKey<SslHelper>(SslHelper.class, "internal_sslHelper");
 
     /**
      * The unique identifier of this session.
@@ -265,43 +268,66 @@ public interface IoSession {
 
     /* Session context management */
     /**
-     * Returns the value of the user-defined attribute for this session.
+     * Returns the value of the user-defined attribute for the given
+     * <code>key</code>.If the there is no attribute with the specified key the <tt>defaultValue</tt> will be returned.
      * 
-     * @param name the attribute's name
-     * @return <tt>null</tt> if there is no attribute with the specified name
+     * @param key
+     *            the attribute's key, must not be <code>null</code>
+     * @return <tt>defaultValue</tt> if there is no attribute with the specified key
+     * @exception IllegalArgumentException
+     *                if <code>key==null</code>
+     * @see #setAttribute(AttributeKey, Object)
      */
-    <T> T getAttribute(String name);
+    <T> T getAttribute(AttributeKey<T> key, T defaultValue);
 
     /**
-     * Sets a user-defined attribute.
+     * Sets a user-defined attribute. If the <code>value</code> is
+     * <code>null</code> the attribute will be removed from this
+     * {@link IoSession}.
      * 
-     * @param name the attribute's name
-     * @param value the attribute's value
-     * @return The old attribute's value. <tt>null</tt> if there is no previous value or if the value is null
-     */
-    <T> T setAttribute(String name, T value);
-
-    /**
-     * Removes a user-defined attribute with the specified name.
+     * @param key
+     *            the attribute's key, must not be <code>null</code>
+     * @param value
+     *            the attribute's value, <code>null</code> to remove the
+     *            attribute
+     * @return the old attribute's value or <code>null</code> if there is no
+     *         previous value
+     * @exception IllegalArgumentException
+     *                <ul>
+     *                <li>if <code>key==null</code>
+     *                <li>if <code>value</code> is not <code>null</code> and not
+     *                an instance of type that is specified in by the given
+     *                <code>key</code> (see {@link AttributeKey#getType()})
+     * 
+     *                </ul>
      * 
-     * @param name the attribute's name
-     * @return The old attribute's value. <tt>null</tt> if not found or if the attribute had no value
+     * @see #getAttribute(AttributeKey)
      */
-    <T> T removeAttribute(String name);
+    <T> T setAttribute(AttributeKey<? extends T> key, T value);
 
     /**
-     * Tells if the session has an attached attribute.
+     * Returns an unmodifiable {@link Set} of all Keys of this {@link IoSession}. If
+     * this {@link IoSession} contains no attributes an empty {@link Set} will be returned.
      * 
-     * @return <tt>true</tt> if this session contains the attribute with the specified <tt>name</tt>.
+     * @return all Keys, never <code>null</code>
+     * @see Collections#unmodifiableSet(Set)
      */
-    boolean containsAttribute(String name);
+    Set<AttributeKey<?>> getAttributeKeys();
 
     /**
-     * Gets the set of attributes stored within the session.
+     * Removes the specified Attribute from this container. The old value will
+     * be returned, <code>null</code> will be rutrnen if there is no such
+     * attribute in this container.<br>
+     * <br>
+     * This method is equivalent to <code>setAttribute(key,null)</code>.
      * 
-     * @return the set of names of all user-defined attributes.
+     * @param key
+     *            of the attribute to be removed,must not be <code>null</code>
+     * @return the removed value, <code>null</code> if this container doesn't
+     *         contain the specified attribute
+     * @exception IllegalArgumentException if <code>key==null</code>
      */
-    Set<String> getAttributeNames();
+    public <T> T removeAttribute(AttributeKey<T> key);
 
     /**
      * State of a {@link IoSession}

Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecFilter.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecFilter.java?rev=1222398&r1=1222397&r2=1222398&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecFilter.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/ProtocolCodecFilter.java Thu Dec 22 19:08:30 2011
@@ -26,7 +26,7 @@ import org.apache.mina.api.IoFilter;
 import org.apache.mina.api.IoSession;
 import org.apache.mina.filterchain.ReadFilterChainController;
 import org.apache.mina.filterchain.WriteFilterChainController;
-import org.apache.mina.util.IoBuffer;
+import org.apache.mina.session.AttributeKey;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,10 +44,12 @@ public class ProtocolCodecFilter extends
     private static final Class<?>[] EMPTY_PARAMS = new Class[0];
 
     /** key for session attribute holding the encoder */
-    private final String ENCODER = ProtocolCodecFilter.class.getSimpleName() + "encoder";
+    private final AttributeKey<ProtocolEncoder> ENCODER = new AttributeKey<ProtocolEncoder>(ProtocolEncoder.class,
+            "internal_encoder");
 
     /** key for session attribute holding the decoder */
-    private final String DECODER = ProtocolCodecFilter.class.getSimpleName() + "decoder";
+    private final AttributeKey<ProtocolDecoder> DECODER = new AttributeKey<ProtocolDecoder>(ProtocolDecoder.class,
+            "internal_decoder");
 
     /** The factory responsible for creating the encoder and decoder */
     private final ProtocolCodecFactory factory;
@@ -224,7 +226,7 @@ public class ProtocolCodecFilter extends
     public void messageWriting(IoSession session, Object message, WriteFilterChainController controller) {
         LOGGER.debug("Processing a MESSAGE_WRITTING for session {}", session);
 
-        ProtocolEncoder encoder = session.getAttribute(ENCODER);
+        ProtocolEncoder encoder = session.getAttribute(ENCODER, null);
 
         encoder.encode(session, message, controller);
     }

Modified: mina/trunk/core/src/main/java/org/apache/mina/session/AbstractIoSession.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/session/AbstractIoSession.java?rev=1222398&r1=1222397&r2=1222398&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/session/AbstractIoSession.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/session/AbstractIoSession.java Thu Dec 22 19:08:30 2011
@@ -19,10 +19,9 @@
  */
 package org.apache.mina.session;
 
-import java.util.Map;
+import java.util.Collections;
 import java.util.Queue;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.Lock;
@@ -76,7 +75,7 @@ public abstract class AbstractIoSession 
     private volatile long lastWriteTime;
 
     /** attributes map */
-    private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>(4);
+    private final AttributeContainer attributes = new DefaultAttributeContainer();
 
     /** unique identifier generator */
     private static final AtomicLong NEXT_ID = new AtomicLong(0);
@@ -326,7 +325,7 @@ public abstract class AbstractIoSession 
         SslHelper sslHelper = new SslHelper(this, sslContext);
         sslHelper.init();
 
-        attributes.put(SSL_HELPER, sslHelper);
+        attributes.setAttribute(SSL_HELPER, sslHelper);
         setSecured(true);
     }
 
@@ -396,44 +395,56 @@ public abstract class AbstractIoSession 
 
     /**
      * {@inheritDoc}
+     * 
+     * @exception IllegalArgumentException if <code>key==null</code>
+     * @see #setAttribute(AttributeKey, Object)
      */
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T> T getAttribute(String name) {
-        return (T) attributes.get(name);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @SuppressWarnings("unchecked")
     @Override
-    public <T> T setAttribute(String name, T value) {
-        return (T) attributes.put(name, value);
+    public final <T> T getAttribute(AttributeKey<T> key, T defaultValue) {
+        return attributes.getAttribute(key, defaultValue);
     }
 
     /**
      * {@inheritDoc}
+     * 
+     * @exception IllegalArgumentException
+     * <ul>
+     *   <li>
+     *     if <code>key==null</code>
+     *   </li>
+     *   <li>
+     *     if <code>value</code> is not <code>null</code> and not
+     *     an instance of type that is specified in by the given
+     *     <code>key</code> (see {@link AttributeKey#getType()})
+     *   </li>
+     *  </ul>
+     * 
+     * @see #getAttribute(AttributeKey)
      */
     @Override
-    public boolean containsAttribute(String name) {
-        return attributes.containsKey(name);
-    }
+    public final <T> T setAttribute(AttributeKey<? extends T> key, T value) {
+        return attributes.setAttribute(key, value);
+    };
 
     /**
      * {@inheritDoc}
+     * 
+     * @see Collections#unmodifiableSet(Set)
      */
     @Override
-    public Object removeAttribute(String name) {
-        return attributes.remove(name);
+    public Set<AttributeKey<?>> getAttributeKeys() {
+        return attributes.getAttributeKeys();
     }
 
     /**
      * {@inheritDoc}
+     * 
+     * @exception IllegalArgumentException
+     *                if <code>key==null</code>
      */
     @Override
-    public Set<String> getAttributeNames() {
-        return attributes.keySet();
+    public <T> T removeAttribute(AttributeKey<T> key) {
+        return attributes.removeAttribute(key);
     }
 
     /**
@@ -479,7 +490,7 @@ public abstract class AbstractIoSession 
 
             if (isConnectedSecured()) {
                 // SSL/TLS : we have to encrypt the message
-                SslHelper sslHelper = getAttribute(IoSession.SSL_HELPER);
+                SslHelper sslHelper = getAttribute(SSL_HELPER, null);
 
                 if (sslHelper == null) {
                     throw new IllegalStateException();

Added: mina/trunk/core/src/main/java/org/apache/mina/session/AttributeContainer.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/session/AttributeContainer.java?rev=1222398&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/session/AttributeContainer.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/session/AttributeContainer.java Thu Dec 22 19:08:30 2011
@@ -0,0 +1,100 @@
+/*
+ *  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.session;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * An interface exposing the getters and setters on Attributes
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+interface AttributeContainer {
+    /**
+     * Returns the value of the user-defined attribute for the given
+     * <code>key</code>.
+     * 
+     * @param key
+     *            the attribute's key, must not be <code>null</code>
+     * @return <tt>null</tt> if there is no attribute with the specified key
+     * @exception IllegalArgumentException
+     *                if <code>key==null</code>
+     * @see #setAttribute(AttributeKey, Object)
+     */
+    <T> T getAttribute(AttributeKey<T> key);
+
+    /**
+     * Returns the value of the user-defined attribute for the given
+     * <code>key</code>.
+     * 
+     * @param key
+     *            the attribute's key, must not be <code>null</code>
+     * @return <tt>null</tt> if there is no attribute with the specified key
+     * @exception IllegalArgumentException
+     *                if <code>key==null</code>
+     * @see #setAttribute(AttributeKey, Object)
+     */
+    <T> T getAttribute(AttributeKey<T> key, T value);
+
+    /**
+     * Removes the specified Attribute from this container. The old value will
+     * be returned, <code>null</code> will be returned if there is no such
+     * attribute in this container.<br>
+     * <br>
+     * This method is equivalent to <code>setAttribute(key,null)</code>.
+     * 
+     * @param key
+     *            of the attribute to be removed,must not be <code>null</code>
+     * @return the removed value, <code>null</code> if this container doesn't
+     *         contain the specified attribute
+     * @exception IllegalArgumentException
+     *                if <code>key==null</code>
+     */
+    <T> T removeAttribute(AttributeKey<T> key);
+
+    /**
+     * Sets a user-defined attribute. If the <code>value</code> is
+     * <code>null</code> the attribute will be removed from this container.
+     * 
+     * @param key
+     *            the attribute's key, must not be <code>null</code>
+     * @param value
+     *            the attribute's value, <code>null</code> to remove the
+     *            attribute
+     * @return The old attribute's value. <code>null</code> if there is no
+     *         previous value or if the value is <code>null</code>
+     * @exception IllegalArgumentException
+     *                if {@code value!=null} and not an instance of type that is
+     *                specified in the key (see {@link AttributeKey#getType()})
+     * 
+     * @see #getAttribute(AttributeKey)
+     */
+    <T> T setAttribute(AttributeKey<? extends T> key, T value);
+
+    /**
+     * Returns an unmodifiable {@link Set} including all Keys of this container. If
+     * this container contains no key's an empty {@link Set} will be returned.
+     * 
+     * @return all Keys, never <code>null</code>
+     * @see Collections#unmodifiableSet(Set)
+     */
+    Set<AttributeKey<?>> getAttributeKeys();
+}
\ No newline at end of file

Added: mina/trunk/core/src/main/java/org/apache/mina/session/AttributeKey.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/session/AttributeKey.java?rev=1222398&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/session/AttributeKey.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/session/AttributeKey.java Thu Dec 22 19:08:30 2011
@@ -0,0 +1,140 @@
+/*
+ *  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.session;
+
+import static org.apache.mina.util.Assert.assertNotNull;
+
+import org.apache.mina.api.IoSession;
+
+/**
+ * Represents the Key for an attribute-value of an {@link IoSession}. A key
+ * consists of the Type of the referenced attribute value and a name.<br>
+ * <br>
+ * Two {@link AttributeKey}'s are equal if the have the same attribute-type and
+ * attribute-name.
+ * 
+ * @param <T> Type of the attribute-value this key is referring to
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public final class AttributeKey<T> {
+    /** the {@link Class} of the referenced attribute-value */
+    private final Class<T> attributeType;
+
+    /** the name of this key */
+    private final String attributeName;
+
+    /** the cached hash code of this instance */
+    private final int hashCode;
+
+    /**
+     * Creates a new {@link AttributeKey} with the given parameters. A
+     * {@link IllegalArgumentException} will be thrown if any parameter is
+     * <code>null</code>.
+     * 
+     * @param attributeType
+     *            type of the referenced attribute-value, must not be
+     *            <code>null</code>
+     * @param attributeName
+     *            name of this key, must not be <code>null</code>
+     * @exception IllegalArgumentException
+     *                if any parameter is <code>null</code>
+     * @see #createKey(Class, String)
+     */
+    public AttributeKey(Class<T> attributeType, String attributeName) {
+        this.attributeType = assertNotNull(attributeType, "attributeType");
+        this.attributeName = assertNotNull(attributeName, "attributeName");
+
+        this.hashCode = createHashCode();
+    }
+
+    /**
+     * Creates a new {@link AttributeKey} with the given parameters. A
+     * {@link IllegalArgumentException} will be thrown if any parameter is
+     * <code>null</code>. <br>
+     * This call is equal to {@link AttributeKey#AttributeKey(Class, String)}
+     * 
+     * @param attributeType
+     *            type of the referenced attribute-value, must not be
+     *            <code>null</code>
+     * @param attributeName
+     *            name of this key, must not be <code>null</code>
+     * @exception IllegalArgumentException
+     *                if any parameter is <code>null</code>
+     * @see #AttributeKey(Class, String)
+     */
+    public static <T> AttributeKey<T> createKey(Class<T> attributeType, String attributeName) {
+        return new AttributeKey<T>(attributeType, attributeName);
+    }
+
+    /**
+     * Creates the hash code for this instance
+     * 
+     * @return
+     */
+    private int createHashCode() {
+        final int prime = 31;
+        int result = prime + attributeName.hashCode();
+        result = prime * result + attributeType.hashCode();
+
+        return result;
+    }
+
+    /**
+     * Returns the name of this key.
+     * 
+     * @return name of this key, never <code>null</code>
+     */
+    public String getName() {
+        return attributeName;
+    }
+
+    /**
+     * Returns the type of this key.
+     * 
+     * @return type of this key, never <code>null</code>
+     */
+    public Class<T> getType() {
+        return attributeType;
+    }
+
+    @Override
+    public int hashCode() {
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        AttributeKey<?> other = (AttributeKey<?>) obj;
+
+        return hashCode == other.hashCode;
+    }
+}

Added: mina/trunk/core/src/main/java/org/apache/mina/session/DefaultAttributeContainer.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/session/DefaultAttributeContainer.java?rev=1222398&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/session/DefaultAttributeContainer.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/session/DefaultAttributeContainer.java Thu Dec 22 19:08:30 2011
@@ -0,0 +1,223 @@
+/*
+ *  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.session;
+
+import static java.util.Collections.unmodifiableSet;
+import static org.apache.mina.util.Assert.assertNotNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * An {@link AttributeContainer} provides type-safe access to attribute values,
+ * using {@link AttributeKey}' s which as reference-key to an attribute value. <br>
+ * <br>
+ * This class is Thread-Safe !
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+final class DefaultAttributeContainer implements AttributeContainer {
+    /**
+     * Contains all attributes
+     * <ul>
+     * <li>Key: the typesafe attribute key
+     * <li>Value: the attribute value
+     * </ul>
+     */
+    private final Map<AttributeKey<?>, Object> attributes = new HashMap<AttributeKey<?>, Object>();
+
+    /** Synchronizes the read operations */
+    private final Lock readLock;
+
+    /** Synchronizes the write operations */
+    private final Lock writeLock;
+
+    {
+        ReadWriteLock rwLock = new ReentrantReadWriteLock();
+        readLock = rwLock.readLock();
+        writeLock = rwLock.writeLock();
+    }
+
+    /**
+     * Returns the value of the user-defined attribute for the given
+     * <code>key</code>.
+     * 
+     * @param key
+     *            the attribute's key, must not be <code>null</code>
+     * @return <tt>null</tt> if there is no attribute with the specified key
+     * @exception IllegalArgumentException
+     *                if <code>key==null</code>
+     * @see #setAttribute(AttributeKey, Object)
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T getAttribute(AttributeKey<T> key) {
+        assertNotNull(key, "key");
+        readLock.lock();
+
+        try {
+            T value = (T) attributes.get(key);
+
+            return value;
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * Returns the value of the user-defined attribute for the given
+     * <code>key</code>.
+     * 
+     * @param key
+     *            the attribute's key, must not be <code>null</code>
+     * @return <tt>null</tt> if there is no attribute with the specified key
+     * @exception IllegalArgumentException
+     *                if <code>key==null</code>
+     * @see #setAttribute(AttributeKey, Object)
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T getAttribute(AttributeKey<T> key, T defaultValue) {
+        assertNotNull(key, "key");
+        readLock.lock();
+
+        try {
+            T value = (T) attributes.get(key);
+
+            if (value != null) {
+                return value;
+            }
+
+            return defaultValue;
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * Sets a user-defined attribute. If the <code>value</code> is
+     * <code>null</code> the attribute will be removed from this container.
+     * 
+     * @param key
+     *            the attribute's key, must not be <code>null</code>
+     * @param value
+     *            the attribute's value, <code>null</code> to remove the
+     *            attribute
+     * @return The old attribute's value, <code>null</code> if there is no
+     *         previous value
+     * @exception IllegalArgumentException
+     *                <ul>
+     *                <li>if <code>key==null</code>
+     *                <li>if <code>value</code> is not <code>null</code> and not
+     *                an instance of type that is specified in by the given
+     *                <code>key</code> (see {@link AttributeKey#getType()})
+     * 
+     *                </ul>
+     * 
+     * @see #getAttribute(AttributeKey)
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T setAttribute(AttributeKey<? extends T> key, T value) {
+        assertNotNull(key, "key");
+        assertValueIsOfExpectedType(key, value);
+        writeLock.lock();
+
+        try {
+            if (value == null) {
+                return removeAttribute(key);
+            }
+
+            return (T) attributes.put(key, value);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * Throws an {@link IllegalArgumentException} if the given
+     * <code>value</code> is not of the expected type and not <code>null</code>.
+     * 
+     * @param <T>
+     * @param key
+     * @param value
+     * @exception IllegalArgumentException
+     *                if <code>value</code> is not an instance of
+     *                {@link AttributeKey#getType()}
+     */
+    private static <T> void assertValueIsOfExpectedType(AttributeKey<? extends T> key, T value) {
+        if (value == null) {
+            return;
+        }
+
+        Class<? extends T> expectedValueType = key.getType();
+
+        if (!expectedValueType.isInstance(value)) {
+            throw new IllegalArgumentException("Invalid attribute value" + "\r\n  expected type: "
+                    + expectedValueType.getName() + "\r\n  actual type  : " + value.getClass().getName()
+                    + "\r\n  actual value : " + value);
+        }
+    }
+
+    /**
+     * Returns an unmodifiable {@link Set} of all Keys of this container. If
+     * this container contains no key's an empty {@link Set} will be returned.
+     * 
+     * @return all Keys, never <code>null</code>
+     * @see Collections#unmodifiableSet(Set)
+     */
+    public Set<AttributeKey<?>> getAttributeKeys() {
+        readLock.lock();
+
+        try {
+            return unmodifiableSet(attributes.keySet());
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    /**
+     * Removes the specified Attribute from this container. The old value will
+     * be returned, <code>null</code> will be returned if there is no such
+     * attribute in this container.<br>
+     * <br>
+     * This method is equivalent to <code>setAttribute(key,null)</code>.
+     * 
+     * @param key
+     *            of the attribute to be removed,must not be <code>null</code>
+     * @return the removed value, <code>null</code> if this container doesn't
+     *         contain the specified attribute
+     * @exception IllegalArgumentException
+     *                if <code>key==null</code>
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T removeAttribute(AttributeKey<T> key) {
+        assertNotNull(key, "key");
+        writeLock.lock();
+
+        try {
+            return (T) attributes.remove(key);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+}

Modified: mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java?rev=1222398&r1=1222397&r2=1222398&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/session/SslHelper.java Thu Dec 22 19:08:30 2011
@@ -19,6 +19,8 @@
  */
 package org.apache.mina.session;
 
+import static org.apache.mina.session.AttributeKey.createKey;
+
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.util.Queue;
@@ -68,11 +70,12 @@ public class SslHelper {
      *
      * @see SSLContext#createSSLEngine(String, int)
      */
-    public static final String PEER_ADDRESS = "internal_peerAddress";
+    public static final AttributeKey<InetSocketAddress> PEER_ADDRESS = createKey(InetSocketAddress.class,
+            "internal_peerAddress");
 
-    public static final String WANT_CLIENT_AUTH = "internal_wantClientAuth";
+    public static final AttributeKey<Boolean> WANT_CLIENT_AUTH = createKey(Boolean.class, "internal_wantClientAuth");
 
-    public static final String NEED_CLIENT_AUTH = "internal_needClientAuth";
+    public static final AttributeKey<Boolean> NEED_CLIENT_AUTH = createKey(Boolean.class, "internal_needClientAuth");
 
     /** Incoming buffer accumulating bytes read from the channel */
     private ByteBuffer accBuffer;
@@ -120,7 +123,7 @@ public class SslHelper {
 
         LOGGER.debug("{} Initializing the SSL Helper", session);
 
-        InetSocketAddress peer = (InetSocketAddress) session.getAttribute(PEER_ADDRESS);
+        InetSocketAddress peer = session.getAttribute(PEER_ADDRESS, null);
 
         // Create the SSL engine here
         if (peer == null) {
@@ -135,15 +138,15 @@ public class SslHelper {
         // Initialize the different SslEngine modes
         if (!sslEngine.getUseClientMode()) {
             // Those parameters are only valid when in server mode
-            Boolean needClientAuth = session.<Boolean> getAttribute(NEED_CLIENT_AUTH);
-            Boolean wantClientAuth = session.<Boolean> getAttribute(WANT_CLIENT_AUTH);
+            boolean needClientAuth = session.getAttribute(NEED_CLIENT_AUTH, false);
+            boolean wantClientAuth = session.getAttribute(WANT_CLIENT_AUTH, false);
 
             // The WantClientAuth supersede the NeedClientAuth, if set.
-            if ((needClientAuth != null) && (needClientAuth)) {
+            if (needClientAuth) {
                 sslEngine.setNeedClientAuth(true);
             }
 
-            if ((wantClientAuth != null) && (wantClientAuth)) {
+            if (wantClientAuth) {
                 sslEngine.setWantClientAuth(true);
             }
         }

Modified: mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java?rev=1222398&r1=1222397&r2=1222398&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/transport/tcp/NioSelectorProcessor.java Thu Dec 22 19:08:30 2011
@@ -20,6 +20,8 @@
 
 package org.apache.mina.transport.tcp;
 
+import static org.apache.mina.api.IoSession.SSL_HELPER;
+
 import java.io.IOException;
 import java.net.SocketAddress;
 import java.nio.ByteBuffer;
@@ -56,7 +58,6 @@ import org.slf4j.LoggerFactory;
  * A {@link SelectorProcessor} for processing NIO based {@link IoSession}.
  * 
  * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- * 
  */
 public class NioSelectorProcessor implements SelectorProcessor {
     /** A logger for this class */
@@ -472,7 +473,7 @@ public class NioSelectorProcessor implem
                 if (session.isSecured()) {
                     // We are reading data over a SSL/TLS encrypted connection. Redirect
                     // the processing to the SslHelper class.
-                    SslHelper sslHelper = session.getAttribute(IoSession.SSL_HELPER);
+                    SslHelper sslHelper = session.getAttribute(SSL_HELPER, null);
 
                     if (sslHelper == null) {
                         throw new IllegalStateException();

Added: mina/trunk/core/src/main/java/org/apache/mina/util/Assert.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/util/Assert.java?rev=1222398&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/util/Assert.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/util/Assert.java Thu Dec 22 19:08:30 2011
@@ -0,0 +1,69 @@
+/*
+ *  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.util;
+
+/**
+ * Provides methods to check preconditions.
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class Assert {
+    /**
+     * This class is not intended to be instantiated! It has no state and
+     * provides only static methods
+     */
+    private Assert() {
+    }
+
+    /**
+     * Returns <code>value</code> if it is not <code>null</code>. Otherwise a
+     * {@link IllegalArgumentException} will be thrown, the given
+     * <code>parameterName</code> is included in the Message. Eg. <br>
+     * <br>
+     * <b>Example:</b>
+     * If <code>null</code> will be passed, the message of the exception is <i>"Parameter >value< must not be null !"</i>
+     * <pre>
+     * public void myMethod(Integer value){
+     *     <b>assertNotNull(value,"value");</b>
+     *     ...
+     * }
+     * </pre>
+     * @param <T>
+     *            Type of the value
+     * @param value
+     *            the value to check
+     * @param parameterName
+     *            name of the parameter to be included in a possible
+     *            {@link IllegalArgumentException}
+     * @return parameter <code>value</code>
+     * @exception IllegalArgumentException if <code>value==null</code>
+     */
+    public static <T> T assertNotNull(T value, String parameterName) {
+        if (parameterName == null) {
+            throw new IllegalArgumentException("You must provide a parameter name!");
+        }
+
+        if (value == null) {
+            throw new IllegalArgumentException("Parameter >" + parameterName + "< must not be null!");
+        }
+
+        return value;
+    }
+}
\ No newline at end of file

Added: mina/trunk/core/src/test/java/org/apache/mina/AllTests.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/AllTests.java?rev=1222398&view=auto
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/AllTests.java (added)
+++ mina/trunk/core/src/test/java/org/apache/mina/AllTests.java Thu Dec 22 19:08:30 2011
@@ -0,0 +1,57 @@
+/*
+ *  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;
+
+import org.apache.mina.session.AbstractIoSessionTest;
+import org.apache.mina.session.AttributeContainerTest;
+import org.apache.mina.session.AttributeKeyTest;
+import org.apache.mina.util.AbstractIoFutureTest;
+import org.apache.mina.util.AssertTest;
+import org.apache.mina.util.ByteBufferDumper;
+import org.apache.mina.util.IoBufferTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+/**
+ * The Test-Suite for all Mina Tests
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+@RunWith(Suite.class)
+@SuiteClasses(value = {
+        //filter.codec
+
+        //filterchain
+
+        //session
+        AbstractIoSessionTest.class, 
+        AttributeContainerTest.class, 
+        AttributeKeyTest.class,
+
+        //transport.tcp
+
+        //util
+        AbstractIoFutureTest.class, 
+        AssertTest.class, 
+        ByteBufferDumper.class, 
+        IoBufferTest.class })
+public class AllTests {
+}

Modified: mina/trunk/core/src/test/java/org/apache/mina/session/AbstractIoSessionTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/session/AbstractIoSessionTest.java?rev=1222398&r1=1222397&r2=1222398&view=diff
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/session/AbstractIoSessionTest.java (original)
+++ mina/trunk/core/src/test/java/org/apache/mina/session/AbstractIoSessionTest.java Thu Dec 22 19:08:30 2011
@@ -18,7 +18,11 @@
  */
 package org.apache.mina.session;
 
-import static org.mockito.Mockito.*;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import java.net.SocketAddress;
 
@@ -31,6 +35,11 @@ import org.apache.mina.api.IoSessionConf
 import org.junit.Before;
 import org.junit.Test;
 
+/**
+ * A test class for IoSession
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
 public class AbstractIoSessionTest {
 
     private static final class DummySession extends AbstractIoSession {
@@ -134,20 +143,18 @@ public class AbstractIoSessionTest {
     public void testAttachment() {
         AbstractIoSession aio = new DummySession(service);
         String value = "value";
-        Assert.assertNull(aio.getAttribute("test"));
-        Assert.assertEquals(null, aio.setAttribute("test", value));
-        Assert.assertTrue(aio.containsAttribute("test"));
-        Assert.assertEquals(aio.getAttributeNames().size(), 1);
-        Assert.assertEquals(value, aio.setAttribute("test", value));
-        Assert.assertEquals(aio.getAttributeNames().size(), 1);
-        Assert.assertTrue(aio.containsAttribute("test"));
-        Assert.assertEquals(value, aio.getAttribute("test"));
-        Assert.assertEquals(value, aio.removeAttribute("test"));
-        Assert.assertEquals(aio.getAttributeNames().size(), 0);
-        Assert.assertFalse(aio.containsAttribute("test"));
+        AttributeKey<String> key = new AttributeKey<String>(String.class, "test");
+        assertNull(aio.getAttribute(key, null));
+        assertEquals(null, aio.setAttribute(key, value));
+
+        assertEquals(aio.getAttributeKeys().size(), 1);
+        assertEquals(value, aio.setAttribute(key, value));
+        assertEquals(aio.getAttributeKeys().size(), 1);
+        assertEquals(value, aio.getAttribute(key, null));
+        assertEquals(value, aio.removeAttribute(key));
+        assertEquals(aio.getAttributeKeys().size(), 0);
 
-        Assert.assertEquals(null, aio.getAttribute("test"));
-        Assert.assertNotNull(aio.getService());
+        assertEquals(null, aio.getAttribute(key, null));
+        assertNotNull(aio.getService());
     }
-
 }

Added: mina/trunk/core/src/test/java/org/apache/mina/session/AttributeContainerTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/session/AttributeContainerTest.java?rev=1222398&view=auto
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/session/AttributeContainerTest.java (added)
+++ mina/trunk/core/src/test/java/org/apache/mina/session/AttributeContainerTest.java Thu Dec 22 19:08:30 2011
@@ -0,0 +1,228 @@
+/*
+ *  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.session;
+
+import static org.apache.mina.session.AttributeKey.createKey;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Tests the class {@link AttributeContainer}
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class AttributeContainerTest {
+
+    /** the default value that is used for every test that calls {@link AttributeContainer#getAttribute(AttributeKey, Object)}*/
+    private static final int DEFAULT_VALUE = 0;
+
+    /** the class under test */
+    private AttributeContainer container;
+
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+
+    private static final AttributeKey<Integer> ATTRIBUTE_KEY = createKey(Integer.class, "myKey");
+
+    @Before
+    public void setUp() {
+        container = new DefaultAttributeContainer();
+    }
+
+    /**
+     * Test if a {@link IllegalArgumentException} is thrown when the key is
+     * <code>null</code>.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void setAttributeWithoutKey() throws Exception {
+        exception.expect(IllegalArgumentException.class);
+        exception.expectMessage("Parameter >key< must not be null!");
+        container.setAttribute(null, DEFAULT_VALUE);
+    }
+
+    /**
+     * Test if a {@link IllegalArgumentException} is thrown if illegal value is
+     * set using an unsafe key.<br>
+     * Expected is a value of type Integer, but passed is a Double-value using
+     * an covariant key.
+     * 
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void setAttributeWithUnsafeKey() throws Exception {
+        exception.expect(IllegalArgumentException.class);
+        exception.expectMessage("Invalid attribute value\r\n" + "  expected type: java.lang.Integer\r\n"
+                + "  actual type  : java.lang.Double\r\n" + "  actual value : 12.3");
+
+        AttributeKey<? extends Number> key = ATTRIBUTE_KEY;
+        Double value = 12.3;
+        container.setAttribute(key, value);
+    }
+
+    /**
+     * Test if <code>null</code> is returned when an Attribute is set for the
+     * first time.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void setAttributeForTheFirstTime() throws Exception {
+        Integer oldValue = container.setAttribute(ATTRIBUTE_KEY, 123);
+        assertThat(oldValue, is(nullValue()));
+    }
+
+    /**
+     * Test if the old value is returned, if the attribute was set before.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void setAttributeForTheSecondTime() throws Exception {
+        container.setAttribute(ATTRIBUTE_KEY, 123);
+        Integer oldValue = container.setAttribute(ATTRIBUTE_KEY, 456);
+        assertThat(oldValue, is(123));
+    }
+
+    /**
+     * Test if the <code>null</code> value is returned, if the attribute has no
+     * previous value.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void setAttributeValueToNull() throws Exception {
+        Integer oldValue = container.setAttribute(ATTRIBUTE_KEY, 456);
+
+        assertThat(oldValue, is(nullValue()));
+    }
+
+    /**
+     * Test if the old value is returned, if the attribute has a previous value.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void setAttributeValueToNullIfPreviousValueIsAvailable() throws Exception {
+        container.setAttribute(ATTRIBUTE_KEY, 123);
+        Integer oldValue = container.setAttribute(ATTRIBUTE_KEY, null);
+
+        assertThat(oldValue, is(123));
+    }
+
+    /**
+     * Test if {@link IllegalArgumentException} is thrown when <code>null</code>
+     * is passed.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void getAttributeWithoutKey() throws Exception {
+        exception.expect(IllegalArgumentException.class);
+        exception.expectMessage("Parameter >key< must not be null!");
+        container.getAttribute(null, DEFAULT_VALUE);
+    }
+
+    /**
+     * Test if the default is returned if the value is not present.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void getAttributeThatIsNotPresent() throws Exception {
+        Integer value = container.getAttribute(ATTRIBUTE_KEY, DEFAULT_VALUE);
+        assertThat(value, is(DEFAULT_VALUE));
+    }
+
+    /**
+     * Test if {@link IllegalArgumentException} is thrown when <code>null</code>
+     * is passed.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void getAttributeThatIsPresent() throws Exception {
+        container.setAttribute(ATTRIBUTE_KEY, 123);
+        Integer value = container.getAttribute(ATTRIBUTE_KEY, DEFAULT_VALUE);
+        assertThat(value, is(123));
+    }
+
+    /**
+     * Test if write-operations on the Key-Set of
+     * {@link AttributeContainer#getAttributeKeys()}, doesn't affect the
+     * container it self.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void getAttributeKeysAndRemoveKey() throws Exception {
+        container.setAttribute(ATTRIBUTE_KEY, 123);
+        Set<AttributeKey<?>> set = container.getAttributeKeys();
+
+        try {
+            set.remove(ATTRIBUTE_KEY);
+        } catch (UnsupportedOperationException e) {
+        }
+
+        Integer value = container.getAttribute(ATTRIBUTE_KEY, DEFAULT_VALUE);
+        assertThat(value, is(123));
+    }
+
+    /**
+     * Test if a present attribute is returned after remove. 
+     * @throws Exception
+     */
+    @Test
+    public void removeAPresentAttribute() throws Exception {
+        container.setAttribute(ATTRIBUTE_KEY, 123);
+        Integer oldValue = container.removeAttribute(ATTRIBUTE_KEY);
+        assertThat(oldValue, is(123));
+    }
+
+    /**
+     * Test if a <code>null</code> is returned if no attribute is present. 
+     * @throws Exception
+     */
+    @Test
+    public void removeNonPresentAttribute() throws Exception {
+        Integer oldValue = container.removeAttribute(ATTRIBUTE_KEY);
+        assertThat(oldValue, is(nullValue()));
+    }
+
+    /**
+     * Test if a {@link IllegalArgumentException} is thrown if a<code>null</code> key is passed. 
+     * @throws Exception
+     */
+    @Test
+    public void removeWithNullKey() throws Exception {
+        exception.expect(IllegalArgumentException.class);
+        exception.expectMessage("Parameter >key< must not be null!");
+        container.removeAttribute(null);
+    }
+}

Added: mina/trunk/core/src/test/java/org/apache/mina/session/AttributeKeyTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/session/AttributeKeyTest.java?rev=1222398&view=auto
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/session/AttributeKeyTest.java (added)
+++ mina/trunk/core/src/test/java/org/apache/mina/session/AttributeKeyTest.java Thu Dec 22 19:08:30 2011
@@ -0,0 +1,138 @@
+/*
+ * 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.session;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Date;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Tests the class {@link AttributeKey}
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class AttributeKeyTest {
+    /** checks Exception parameters */
+    @Rule
+    public final ExpectedException exception = ExpectedException.none();
+
+    /**
+     * Tests if the constructor throws an {@link IllegalArgumentException} if
+     * parameter <code>attributeType</code> is <code>null</code>.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void constructorWithoutKeyType() throws Exception {
+        exception.expect(IllegalArgumentException.class);
+        exception.expectMessage("Parameter >attributeType< must not be null!");
+        new AttributeKey<Number>(null, "key");
+    }
+
+    /**
+     * Tests if the constructor throws an {@link IllegalArgumentException} if
+     * parameter <code>attributeType</code> is <code>null</code>.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void constructorWithoutKeyName() throws Exception {
+        exception.expect(IllegalArgumentException.class);
+        exception.expectMessage("Parameter >attributeName< must not be null!");
+        new AttributeKey<Number>(Number.class, null);
+    }
+
+    /**
+     * Test if the key-name passed into the constructor will be returned
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void getName() throws Exception {
+        String name = new AttributeKey<Number>(Number.class, "keyName").getName();
+        assertThat(name, is("keyName"));
+    }
+
+    /**
+     * Test if the key-type passed into the constructor will be returned.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void getType() throws Exception {
+        Class<?> type = new AttributeKey<Number>(Number.class, "keyName").getType();
+        assertThat(type, is((Object) Number.class));
+    }
+
+    /**
+     * Test the equals method is symmetric, if two {@link AttributeKey}s  with the same attribute type and attribute-name. 
+     * @throws Exception
+     */
+    @Test
+    public void equalsSymmetric() throws Exception {
+        AttributeKey<Number> key1 = new AttributeKey<Number>(Number.class, "keyName");
+        AttributeKey<Number> key2 = new AttributeKey<Number>(Number.class, "keyName");
+
+        assertThat(key1.equals(key2), is(true));
+        assertThat(key2.equals(key1), is(true));
+    }
+
+    /**
+     * Test if the equals method returns <code>false</code>  if the attribute type is different. 
+     * @throws Exception
+     */
+    @Test
+    public void equalsWithDifferentTypes() throws Exception {
+        AttributeKey<Number> key1 = new AttributeKey<Number>(Number.class, "keyName");
+        AttributeKey<Date> key2 = new AttributeKey<Date>(Date.class, "keyName");
+
+        assertThat(key1.equals(key2), is(false));
+        assertThat(key2.equals(key1), is(false));
+    }
+
+    /**
+     * Test if the equals method returns <code>false</code>  if the attribute name is different. 
+     * @throws Exception
+     */
+    @Test
+    public void equalsWithDifferentName() throws Exception {
+        AttributeKey<Number> key1 = new AttributeKey<Number>(Number.class, "key1");
+        AttributeKey<Number> key2 = new AttributeKey<Number>(Number.class, "key2");
+
+        assertThat(key1.equals(key2), is(false));
+        assertThat(key2.equals(key1), is(false));
+    }
+
+    /**
+     * Test if two {@link AttributeKey}s with the same attribute type and attribute-name have the same hashCode
+     * @throws Exception
+     */
+    @Test
+    public void hashCodeValue() throws Exception {
+        AttributeKey<Number> key1 = new AttributeKey<Number>(Number.class, "keyName");
+        AttributeKey<Number> key2 = new AttributeKey<Number>(Number.class, "keyName");
+
+        assertThat(key1.hashCode(), is(key2.hashCode()));
+    }
+}

Added: mina/trunk/core/src/test/java/org/apache/mina/util/AssertTest.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/util/AssertTest.java?rev=1222398&view=auto
==============================================================================
--- mina/trunk/core/src/test/java/org/apache/mina/util/AssertTest.java (added)
+++ mina/trunk/core/src/test/java/org/apache/mina/util/AssertTest.java Thu Dec 22 19:08:30 2011
@@ -0,0 +1,70 @@
+/*
+ * 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.util;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+/**
+ * Tests class {@link Assert}
+ * 
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class AssertTest {
+    /** checks Exception parameters */
+    @Rule
+    public final ExpectedException exception = ExpectedException.none();
+
+    /**
+     * Tests if a {@link IllegalArgumentException} is thrown when a
+     * <code>null</code>-value is passed.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void parameterNotNullWithNullValue() throws Exception {
+        exception.expect(IllegalArgumentException.class);
+        exception.expectMessage("Parameter >parameterName< must not be null!");
+        Assert.assertNotNull(null, "parameterName");
+    }
+
+    /** Tests if a non <code>null</code> value is returned.  */
+    @Test
+    public void parameterNotNullWithNonNullValue() {
+        Integer result = Assert.assertNotNull(123, "parameterName");
+        assertThat(result, is(123));
+    }
+
+    /**
+     * Tests if a {@link IllegalArgumentException} is thrown when a
+     * <code>null</code>-value is passed.
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void parameterNotNullWithMissingParameterName() throws Exception {
+        exception.expect(IllegalArgumentException.class);
+        exception.expectMessage("You must provide a parameter name!");
+        Assert.assertNotNull("", null);
+    }
+}

Modified: mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerCodec.java
URL: http://svn.apache.org/viewvc/mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerCodec.java?rev=1222398&r1=1222397&r2=1222398&view=diff
==============================================================================
--- mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerCodec.java (original)
+++ mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerCodec.java Thu Dec 22 19:08:30 2011
@@ -19,10 +19,13 @@
  */
 package org.apache.mina.http;
 
+import static org.apache.mina.session.AttributeKey.createKey;
+
 import org.apache.mina.api.IoSession;
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
 import org.apache.mina.filter.codec.ProtocolDecoder;
 import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.session.AttributeKey;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -31,10 +34,10 @@ public class HttpServerCodec extends Pro
     private static final Logger LOG = LoggerFactory.getLogger(HttpServerCodec.class);
 
     /** Key for decoder current state */
-    private static final String DECODER_STATE_ATT = "http.ds";
+    private static final AttributeKey<String> DECODER_STATE_ATT = createKey(String.class, "internal_http.ds");
 
     /** Key for the partial HTTP requests head */
-    private static final String PARTIAL_HEAD_ATT = "http.ph";
+    private static final AttributeKey<String> PARTIAL_HEAD_ATT = createKey(String.class, "internal_http.ph");
 
     private static ProtocolEncoder encoder = new HttpServerEncoder();
 

Modified: mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerDecoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerDecoder.java?rev=1222398&r1=1222397&r2=1222398&view=diff
==============================================================================
--- mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerDecoder.java (original)
+++ mina/trunk/http/src/main/java/org/apache/mina/http/HttpServerDecoder.java Thu Dec 22 19:08:30 2011
@@ -19,6 +19,8 @@
  */
 package org.apache.mina.http;
 
+import static org.apache.mina.session.AttributeKey.createKey;
+
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.util.HashMap;
@@ -31,6 +33,7 @@ import org.apache.mina.filterchain.ReadF
 import org.apache.mina.http.api.HttpEndOfContent;
 import org.apache.mina.http.api.HttpMethod;
 import org.apache.mina.http.api.HttpVersion;
+import org.apache.mina.session.AttributeKey;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,13 +41,14 @@ public class HttpServerDecoder implement
     private static final Logger LOG = LoggerFactory.getLogger(HttpServerCodec.class);
 
     /** Key for decoder current state */
-    private static final String DECODER_STATE_ATT = "http.ds";
+    private static final AttributeKey<DecoderState> DECODER_STATE_ATT = createKey(DecoderState.class,
+            "internal_http.ds");
 
     /** Key for the partial HTTP requests head */
-    private static final String PARTIAL_HEAD_ATT = "http.ph";
+    private static final AttributeKey<ByteBuffer> PARTIAL_HEAD_ATT = createKey(ByteBuffer.class, "internal_http.ph");
 
     /** Key for the number of bytes remaining to read for completing the body */
-    private static final String BODY_REMAINING_BYTES = "http.brb";
+    private static final AttributeKey<Integer> BODY_REMAINING_BYTES = createKey(Integer.class, "internal_http.brb");
 
     /** Regex to parse HttpRequest Request Line */
     public static final Pattern REQUEST_LINE_PATTERN = Pattern.compile(" ");
@@ -72,13 +76,13 @@ public class HttpServerDecoder implement
 
     @Override
     public Object decode(IoSession session, ByteBuffer msg, ReadFilterChainController controller) {
-        DecoderState state = session.getAttribute(DECODER_STATE_ATT);
+        DecoderState state = session.getAttribute(DECODER_STATE_ATT, null);
 
         switch (state) {
         case HEAD:
             LOG.debug("decoding HEAD");
             // grab the stored a partial HEAD request
-            ByteBuffer oldBuffer = session.getAttribute(PARTIAL_HEAD_ATT);
+            ByteBuffer oldBuffer = session.getAttribute(PARTIAL_HEAD_ATT, null);
             // concat the old buffer and the new incoming one
             msg = ByteBuffer.allocate(oldBuffer.remaining() + msg.remaining()).put(oldBuffer).put(msg);
             msg.flip();
@@ -127,7 +131,7 @@ public class HttpServerDecoder implement
             // send the chunk of body
             controller.callReadNextFilter(session, msg);
             // do we have reach end of body ?
-            int remaining = (Integer) session.getAttribute(BODY_REMAINING_BYTES);
+            int remaining = session.getAttribute(BODY_REMAINING_BYTES, null);
             remaining -= chunkSize;
 
             if (remaining <= 0) {



Mime
View raw message