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.core.session; 021 022import java.util.HashMap; 023import java.util.HashSet; 024import java.util.Queue; 025import java.util.Set; 026import java.util.concurrent.ConcurrentHashMap; 027import java.util.concurrent.ConcurrentLinkedQueue; 028 029import org.apache.mina.core.write.WriteRequest; 030import org.apache.mina.core.write.WriteRequestQueue; 031 032/** 033 * The default {@link IoSessionDataStructureFactory} implementation 034 * that creates a new {@link HashMap}-based {@link IoSessionAttributeMap} 035 * instance and a new synchronized {@link ConcurrentLinkedQueue} instance per 036 * {@link IoSession}. 037 * 038 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 039 */ 040public class DefaultIoSessionDataStructureFactory implements IoSessionDataStructureFactory { 041 042 public IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception { 043 return new DefaultIoSessionAttributeMap(); 044 } 045 046 public WriteRequestQueue getWriteRequestQueue(IoSession session) throws Exception { 047 return new DefaultWriteRequestQueue(); 048 } 049 050 private static class DefaultIoSessionAttributeMap implements IoSessionAttributeMap { 051 private final ConcurrentHashMap<Object, Object> attributes = new ConcurrentHashMap<Object, Object>(4); 052 053 /** 054 * Default constructor 055 */ 056 public DefaultIoSessionAttributeMap() { 057 super(); 058 } 059 060 /** 061 * {@inheritDoc} 062 */ 063 public Object getAttribute(IoSession session, Object key, Object defaultValue) { 064 if (key == null) { 065 throw new IllegalArgumentException("key"); 066 } 067 068 if (defaultValue == null) { 069 return attributes.get(key); 070 } 071 072 Object object = attributes.putIfAbsent(key, defaultValue); 073 074 if (object == null) { 075 return defaultValue; 076 } else { 077 return object; 078 } 079 } 080 081 /** 082 * {@inheritDoc} 083 */ 084 public Object setAttribute(IoSession session, Object key, Object value) { 085 if (key == null) { 086 throw new IllegalArgumentException("key"); 087 } 088 089 if (value == null) { 090 return attributes.remove(key); 091 } 092 093 return attributes.put(key, value); 094 } 095 096 /** 097 * {@inheritDoc} 098 */ 099 public Object setAttributeIfAbsent(IoSession session, Object key, Object value) { 100 if (key == null) { 101 throw new IllegalArgumentException("key"); 102 } 103 104 if (value == null) { 105 return null; 106 } 107 108 return attributes.putIfAbsent(key, value); 109 } 110 111 /** 112 * {@inheritDoc} 113 */ 114 public Object removeAttribute(IoSession session, Object key) { 115 if (key == null) { 116 throw new IllegalArgumentException("key"); 117 } 118 119 return attributes.remove(key); 120 } 121 122 /** 123 * {@inheritDoc} 124 */ 125 public boolean removeAttribute(IoSession session, Object key, Object value) { 126 if (key == null) { 127 throw new IllegalArgumentException("key"); 128 } 129 130 if (value == null) { 131 return false; 132 } 133 134 try { 135 return attributes.remove(key, value); 136 } catch (NullPointerException e) { 137 return false; 138 } 139 } 140 141 /** 142 * {@inheritDoc} 143 */ 144 public boolean replaceAttribute(IoSession session, Object key, Object oldValue, Object newValue) { 145 try { 146 return attributes.replace(key, oldValue, newValue); 147 } catch (NullPointerException e) { 148 } 149 150 return false; 151 } 152 153 /** 154 * {@inheritDoc} 155 */ 156 public boolean containsAttribute(IoSession session, Object key) { 157 return attributes.containsKey(key); 158 } 159 160 /** 161 * {@inheritDoc} 162 */ 163 public Set<Object> getAttributeKeys(IoSession session) { 164 synchronized (attributes) { 165 return new HashSet<Object>(attributes.keySet()); 166 } 167 } 168 169 /** 170 * {@inheritDoc} 171 */ 172 public void dispose(IoSession session) throws Exception { 173 // Do nothing 174 } 175 } 176 177 private static class DefaultWriteRequestQueue implements WriteRequestQueue { 178 /** A queue to store incoming write requests */ 179 private final Queue<WriteRequest> q = new ConcurrentLinkedQueue<WriteRequest>(); 180 181 /** 182 * Default constructor 183 */ 184 public DefaultWriteRequestQueue() { 185 } 186 187 /** 188 * {@inheritDoc} 189 */ 190 public void dispose(IoSession session) { 191 // Do nothing 192 } 193 194 /** 195 * {@inheritDoc} 196 */ 197 public void clear(IoSession session) { 198 q.clear(); 199 } 200 201 /** 202 * {@inheritDoc} 203 */ 204 public synchronized boolean isEmpty(IoSession session) { 205 return q.isEmpty(); 206 } 207 208 /** 209 * {@inheritDoc} 210 */ 211 public synchronized void offer(IoSession session, WriteRequest writeRequest) { 212 q.offer(writeRequest); 213 } 214 215 /** 216 * {@inheritDoc} 217 */ 218 public synchronized WriteRequest poll(IoSession session) { 219 WriteRequest answer = q.poll(); 220 221 if (answer == AbstractIoSession.CLOSE_REQUEST) { 222 session.closeNow(); 223 dispose(session); 224 answer = null; 225 } 226 227 return answer; 228 } 229 230 @Override 231 public String toString() { 232 return q.toString(); 233 } 234 235 /** 236 * {@inheritDoc} 237 */ 238 public int size() { 239 return q.size(); 240 } 241 } 242}