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: */
020: package org.apache.mina.filter.codec.netty;
021:
022: import java.nio.ByteBuffer;
023:
024: import net.gleamynode.netty2.Message;
025: import net.gleamynode.netty2.MessageParseException;
026: import net.gleamynode.netty2.MessageRecognizer;
027:
028: import org.apache.mina.common.IoBuffer;
029: import org.apache.mina.common.IoSession;
030: import org.apache.mina.filter.codec.ProtocolDecoder;
031: import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
032: import org.apache.mina.filter.codec.ProtocolDecoderException;
033: import org.apache.mina.filter.codec.ProtocolDecoderOutput;
034:
035: /**
036: * A MINA {@link ProtocolDecoder} that decodes buffers into
037: * Netty2 {@link Message}s using specified {@link MessageRecognizer}s.
038: *
039: * @author The Apache MINA Project (dev@mina.apache.org)
040: * @version $Rev: 581243 $, $Date: 2007-10-02 07:59:36 -0600 (Tue, 02 Oct 2007) $,
041: */
042: public class NettyDecoder extends ProtocolDecoderAdapter {
043: private final MessageRecognizer recognizer;
044:
045: private ByteBuffer readBuf = ByteBuffer.allocate(1024);
046:
047: private Message readingMessage;
048:
049: /**
050: * Creates a new instance with the specified {@link MessageRecognizer}.
051: */
052: public NettyDecoder(MessageRecognizer recognizer) {
053: if (recognizer == null) {
054: throw new NullPointerException();
055: }
056:
057: this .recognizer = recognizer;
058: }
059:
060: private void put(IoBuffer in) {
061: // copy to read buffer
062: if (in.remaining() > readBuf.remaining()) {
063: expand((readBuf.position() + in.remaining()) * 3 / 2);
064: }
065: readBuf.put(in.buf());
066: }
067:
068: private void expand(int newCapacity) {
069: ByteBuffer newBuf = ByteBuffer.allocate(newCapacity);
070: readBuf.flip();
071: newBuf.put(readBuf);
072: readBuf = newBuf;
073: }
074:
075: public void decode(IoSession session, IoBuffer in,
076: ProtocolDecoderOutput out) throws Exception {
077: put(in);
078:
079: Message m = readingMessage;
080: try {
081: for (;;) {
082: readBuf.flip();
083: if (m == null) {
084: int limit = readBuf.limit();
085: boolean failed = true;
086: try {
087: m = recognizer.recognize(readBuf);
088: failed = false;
089: } finally {
090: if (failed) {
091: // clear the read buffer if failed to recognize
092: readBuf.clear();
093: break;
094: } else {
095: if (m == null) {
096: readBuf.limit(readBuf.capacity());
097: readBuf.position(limit);
098: break; // finish decoding
099: } else {
100: // reset buffer for read
101: readBuf.limit(limit);
102: readBuf.position(0);
103: }
104: }
105: }
106: }
107:
108: if (m != null) {
109: try {
110: if (m.read(readBuf)) {
111: out.write(m);
112: m = null;
113: } else {
114: break;
115: }
116: } finally {
117: if (readBuf.hasRemaining()) {
118: readBuf.compact();
119: } else {
120: readBuf.clear();
121: break;
122: }
123: }
124: }
125: }
126: } catch (MessageParseException e) {
127: m = null; // discard reading message
128: throw new ProtocolDecoderException("Failed to decode.", e);
129: } finally {
130: readingMessage = m;
131: }
132: }
133: }
|