1 20 package org.apache.mina.filter.codec.textline; 21 22 import java.nio.charset.CharacterCodingException ; 23 import java.nio.charset.Charset ; 24 import java.nio.charset.CharsetDecoder ; 25 26 import org.apache.mina.common.BufferDataException; 27 import org.apache.mina.common.ByteBuffer; 28 import org.apache.mina.common.IoSession; 29 import org.apache.mina.filter.codec.ProtocolDecoder; 30 import org.apache.mina.filter.codec.ProtocolDecoderOutput; 31 32 38 public class TextLineDecoder implements ProtocolDecoder { 39 private static final String CONTEXT = TextLineDecoder.class.getName() 40 + ".context"; 41 42 private final Charset charset; 43 44 private final LineDelimiter delimiter; 45 46 private ByteBuffer delimBuf; 47 48 private int maxLineLength = 1024; 49 50 54 public TextLineDecoder() { 55 this(Charset.defaultCharset(), LineDelimiter.AUTO); 56 } 57 58 62 public TextLineDecoder(Charset charset) { 63 this(charset, LineDelimiter.AUTO); 64 } 65 66 70 public TextLineDecoder(Charset charset, LineDelimiter delimiter) { 71 if (charset == null) { 72 throw new NullPointerException ("charset"); 73 } 74 if (delimiter == null) { 75 throw new NullPointerException ("delimiter"); 76 } 77 78 this.charset = charset; 79 this.delimiter = delimiter; 80 } 81 82 88 public int getMaxLineLength() { 89 return maxLineLength; 90 } 91 92 98 public void setMaxLineLength(int maxLineLength) { 99 if (maxLineLength <= 0) { 100 throw new IllegalArgumentException ("maxLineLength: " 101 + maxLineLength); 102 } 103 104 this.maxLineLength = maxLineLength; 105 } 106 107 public void decode(IoSession session, ByteBuffer in, 108 ProtocolDecoderOutput out) throws Exception { 109 Context ctx = getContext(session); 110 111 if (LineDelimiter.AUTO.equals(delimiter)) { 112 ctx.setMatchCount(decodeAuto(in, ctx.getBuffer(), ctx 113 .getMatchCount(), ctx.getDecoder(), out)); 114 } else { 115 ctx.setMatchCount(decodeNormal(in, ctx.getBuffer(), ctx 116 .getMatchCount(), ctx.getDecoder(), out)); 117 } 118 } 119 120 private Context getContext(IoSession session) { 121 Context ctx = (Context) session.getAttribute(CONTEXT); 122 if (ctx == null) { 123 ctx = new Context(); 124 session.setAttribute(CONTEXT, ctx); 125 } 126 return ctx; 127 } 128 129 public void finishDecode(IoSession session, ProtocolDecoderOutput out) 130 throws Exception { 131 } 132 133 public void dispose(IoSession session) throws Exception { 134 Context ctx = (Context) session.getAttribute(CONTEXT); 135 if (ctx != null) { 136 ctx.getBuffer().release(); 137 session.removeAttribute(CONTEXT); 138 } 139 } 140 141 private int decodeAuto(ByteBuffer in, ByteBuffer buf, int matchCount, 142 CharsetDecoder decoder, ProtocolDecoderOutput out) 143 throws CharacterCodingException { 144 int oldPos = in.position(); 146 int oldLimit = in.limit(); 147 while (in.hasRemaining()) { 148 byte b = in.get(); 149 boolean matched = false; 150 switch (b) { 151 case '\r': 152 matchCount++; 155 break; 156 case '\n': 157 matchCount++; 159 matched = true; 160 break; 161 default: 162 matchCount = 0; 163 } 164 165 if (matched) { 166 int pos = in.position(); 168 in.limit(pos); 169 in.position(oldPos); 170 171 buf.put(in); 172 if (buf.position() > maxLineLength) { 173 throw new BufferDataException("Line is too long: " 174 + buf.position()); 175 } 176 buf.flip(); 177 buf.limit(buf.limit() - matchCount); 178 out.write(buf.getString(decoder)); 179 buf.clear(); 180 181 in.limit(oldLimit); 182 in.position(pos); 183 oldPos = pos; 184 matchCount = 0; 185 } 186 } 187 188 in.position(oldPos); 190 buf.put(in); 191 192 return matchCount; 193 } 194 195 private int decodeNormal(ByteBuffer in, ByteBuffer buf, int matchCount, 196 CharsetDecoder decoder, ProtocolDecoderOutput out) 197 throws CharacterCodingException { 198 if (delimBuf == null) { 200 ByteBuffer tmp = ByteBuffer.allocate(2).setAutoExpand(true); 201 tmp.putString(delimiter.getValue(), charset.newEncoder()); 202 tmp.flip(); 203 delimBuf = tmp; 204 } 205 206 int oldPos = in.position(); 208 int oldLimit = in.limit(); 209 while (in.hasRemaining()) { 210 byte b = in.get(); 211 if (delimBuf.get(matchCount) == b) { 212 matchCount++; 213 if (matchCount == delimBuf.limit()) { 214 int pos = in.position(); 216 in.limit(pos); 217 in.position(oldPos); 218 219 buf.put(in); 220 if (buf.position() > maxLineLength) { 221 throw new BufferDataException("Line is too long: " 222 + buf.position()); 223 } 224 buf.flip(); 225 buf.limit(buf.limit() - matchCount); 226 out.write(buf.getString(decoder)); 227 buf.clear(); 228 229 in.limit(oldLimit); 230 in.position(pos); 231 oldPos = pos; 232 matchCount = 0; 233 } 234 } else { 235 matchCount = 0; 236 } 237 } 238 239 in.position(oldPos); 241 buf.put(in); 242 243 return matchCount; 244 } 245 246 private class Context { 247 private final CharsetDecoder decoder; 248 249 private final ByteBuffer buf; 250 251 private int matchCount = 0; 252 253 private Context() { 254 decoder = charset.newDecoder(); 255 buf = ByteBuffer.allocate(80).setAutoExpand(true); 256 } 257 258 public CharsetDecoder getDecoder() { 259 return decoder; 260 } 261 262 public ByteBuffer getBuffer() { 263 return buf; 264 } 265 266 public int getMatchCount() { 267 return matchCount; 268 } 269 270 public void setMatchCount(int matchCount) { 271 this.matchCount = matchCount; 272 } 273 } 274 } | Popular Tags |