1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.mina.filter.codec.netty;
21
22 import net.gleamynode.netty2.Message;
23 import net.gleamynode.netty2.MessageParseException;
24 import net.gleamynode.netty2.MessageRecognizer;
25
26 import org.apache.mina.common.ByteBuffer;
27 import org.apache.mina.common.IoSession;
28 import org.apache.mina.filter.codec.ProtocolDecoder;
29 import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
30 import org.apache.mina.filter.codec.ProtocolDecoderException;
31 import org.apache.mina.filter.codec.ProtocolDecoderOutput;
32
33 /**
34 * A MINA {@link ProtocolDecoder} that decodes byte buffers into
35 * Netty2 {@link Message}s using specified {@link MessageRecognizer}s.
36 *
37 * @author The Apache Directory Project (mina-dev@directory.apache.org)
38 * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (Fri, 13 Jul 2007) $,
39 */
40 public class NettyDecoder extends ProtocolDecoderAdapter {
41 private final MessageRecognizer recognizer;
42
43 private java.nio.ByteBuffer readBuf = java.nio.ByteBuffer.allocate(1024);
44
45 private Message readingMessage;
46
47 /**
48 * Creates a new instance with the specified {@link MessageRecognizer}.
49 */
50 public NettyDecoder(MessageRecognizer recognizer) {
51 if (recognizer == null)
52 throw new NullPointerException();
53
54 this.recognizer = recognizer;
55 }
56
57 private void put(ByteBuffer in) {
58 // copy to read buffer
59 if (in.remaining() > readBuf.remaining())
60 expand((readBuf.position() + in.remaining()) * 3 / 2);
61 readBuf.put(in.buf());
62 }
63
64 private void expand(int newCapacity) {
65 java.nio.ByteBuffer newBuf = java.nio.ByteBuffer.allocate(newCapacity);
66 readBuf.flip();
67 newBuf.put(readBuf);
68 readBuf = newBuf;
69 }
70
71 public void decode(IoSession session, ByteBuffer in,
72 ProtocolDecoderOutput out) throws Exception {
73 put(in);
74
75 Message m = readingMessage;
76 try {
77 for (;;) {
78 readBuf.flip();
79 if (m == null) {
80 int limit = readBuf.limit();
81 boolean failed = true;
82 try {
83 m = recognizer.recognize(readBuf);
84 failed = false;
85 } finally {
86 if (failed) {
87 // clear the read buffer if failed to recognize
88 readBuf.clear();
89 break;
90 } else {
91 if (m == null) {
92 readBuf.limit(readBuf.capacity());
93 readBuf.position(limit);
94 break; // finish decoding
95 } else {
96 // reset buffer for read
97 readBuf.limit(limit);
98 readBuf.position(0);
99 }
100 }
101 }
102 }
103
104 if (m != null) {
105 try {
106 if (m.read(readBuf)) {
107 out.write(m);
108 m = null;
109 } else {
110 break;
111 }
112 } finally {
113 if (readBuf.hasRemaining()) {
114 readBuf.compact();
115 } else {
116 readBuf.clear();
117 break;
118 }
119 }
120 }
121 }
122 } catch (MessageParseException e) {
123 m = null; // discard reading message
124 throw new ProtocolDecoderException("Failed to decode.", e);
125 } finally {
126 readingMessage = m;
127 }
128 }
129 }