You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by tr...@apache.org on 2007/10/30 10:44:04 UTC
svn commit: r590006 - in /mina/trunk:
core/src/main/java/org/apache/mina/common/
core/src/main/java/org/apache/mina/filter/codec/demux/
core/src/main/java/org/apache/mina/handler/demux/
example/src/main/java/org/apache/mina/example/httpserver/codec/ ex...
Author: trustin
Date: Tue Oct 30 02:44:02 2007
New Revision: 590006
URL: http://svn.apache.org/viewvc?rev=590006&view=rev
Log:
Resolved issue: DIRMINA-439 (DemuxingProtocolEncoder and DemuxingProtocolDecoder by refactoring DemuxingProtocolCodecFactory)
* Added DemuxingProtocolEncoder
* Added DemuxingProtocolDecoder
* Rewrote DemuxingProtocolCodecFactory by using DemuxingProtocolEncoder and Decoder
* Updated JavaDoc
* Moved UnknownMessageTypeException to org.apache.mina.common
Added:
mina/trunk/core/src/main/java/org/apache/mina/common/UnknownMessageTypeException.java
- copied, changed from r589979, mina/trunk/core/src/main/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDecoder.java (with props)
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEncoder.java (with props)
Removed:
mina/trunk/core/src/main/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java
Modified:
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolCodecFactory.java
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoder.java
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderFactory.java
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoder.java
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoderFactory.java
mina/trunk/core/src/main/java/org/apache/mina/handler/demux/DemuxingIoHandler.java
mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpResponseEncoder.java
mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpServerProtocolCodecFactory.java
mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageEncoder.java
mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageEncoder.java
mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageEncoder.java
mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/SumUpProtocolCodecFactory.java
Copied: mina/trunk/core/src/main/java/org/apache/mina/common/UnknownMessageTypeException.java (from r589979, mina/trunk/core/src/main/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java)
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/common/UnknownMessageTypeException.java?p2=mina/trunk/core/src/main/java/org/apache/mina/common/UnknownMessageTypeException.java&p1=mina/trunk/core/src/main/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java&r1=589979&r2=590006&rev=590006&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/common/UnknownMessageTypeException.java Tue Oct 30 02:44:02 2007
@@ -17,14 +17,11 @@
* under the License.
*
*/
-package org.apache.mina.handler.demux;
+package org.apache.mina.common;
+
/**
- * An exception that is thrown when {@link DemuxingIoHandler}
- * cannot find any {@link MessageHandler}s associated with the specific
- * message type. You have to use
- * {@link DemuxingIoHandler#addMessageHandler(Class, MessageHandler)}
- * to associate a message type and a message handler.
+ * An exception that is thrown when the type of the message cannot be determined.
*
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolCodecFactory.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolCodecFactory.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolCodecFactory.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolCodecFactory.java Tue Oct 30 02:44:02 2007
@@ -19,390 +19,59 @@
*/
package org.apache.mina.filter.codec.demux;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.mina.common.IoBuffer;
-import org.apache.mina.common.IoSession;
-import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
-import org.apache.mina.filter.codec.ProtocolDecoderException;
-import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoder;
-import org.apache.mina.filter.codec.ProtocolEncoderException;
-import org.apache.mina.filter.codec.ProtocolEncoderOutput;
-import org.apache.mina.util.IdentityHashSet;
/**
- * A composite {@link ProtocolCodecFactory} that consists of multiple
- * {@link MessageEncoder}s and {@link MessageDecoder}s.
- * {@link ProtocolEncoder} and {@link ProtocolDecoder} this factory
- * returns demultiplex incoming messages and buffers to
- * appropriate {@link MessageEncoder}s and {@link MessageDecoder}s.
- *
- * <h2>Disposing resources acquired by {@link MessageEncoder} and {@link MessageDecoder}</h2>
+ * A convenience {@link ProtocolCodecFactory} that provides {@link DemuxingProtocolEncoder}
+ * and {@link DemuxingProtocolDecoder} as a pair.
* <p>
- * Make your {@link MessageEncoder} and {@link MessageDecoder} to put all
- * resources that need to be released as a session attribute. {@link #disposeCodecResources(IoSession)}
- * method will be invoked when a session is closed. Override {@link #disposeCodecResources(IoSession)}
- * to release the resources you've put as an attribute.
- * <p>
- * We didn't provide any <tt>dispose</tt> method for {@link MessageEncoder} and {@link MessageDecoder}
- * because they can give you a big performance penalty in case you have a lot of
- * message types to handle.
+ * {@link DemuxingProtocolEncoder} and {@link DemuxingProtocolDecoder} demultiplex
+ * incoming messages and buffers to appropriate {@link MessageEncoder}s and
+ * {@link MessageDecoder}s.
*
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
- *
- * @see MessageEncoder
- * @see MessageDecoder
*/
public class DemuxingProtocolCodecFactory implements ProtocolCodecFactory {
- private MessageDecoderFactory[] decoderFactories = new MessageDecoderFactory[0];
- private MessageEncoderFactory<?>[] encoderFactories = new MessageEncoderFactory[0];
-
- private static final Class<?>[] EMPTY_PARAMS = new Class[0];
+ private final DemuxingProtocolEncoder encoder = new DemuxingProtocolEncoder();
+ private final DemuxingProtocolDecoder decoder = new DemuxingProtocolDecoder();
public DemuxingProtocolCodecFactory() {
}
- public void register(Class<?> encoderOrDecoderClass) {
- if (encoderOrDecoderClass == null) {
- throw new NullPointerException("encoderOrDecoderClass");
- }
-
- try {
- encoderOrDecoderClass.getConstructor(EMPTY_PARAMS);
- } catch (NoSuchMethodException e) {
- throw new IllegalArgumentException(
- "The specifiec class doesn't have a public default constructor.");
- }
-
- boolean registered = false;
- if (MessageEncoder.class.isAssignableFrom(encoderOrDecoderClass)) {
- register(new DefaultConstructorMessageEncoderFactory(encoderOrDecoderClass));
- registered = true;
- }
-
- if (MessageDecoder.class.isAssignableFrom(encoderOrDecoderClass)) {
- register(new DefaultConstructorMessageDecoderFactory(
- encoderOrDecoderClass));
- registered = true;
- }
-
- if (!registered) {
- throw new IllegalArgumentException("Unregisterable type: "
- + encoderOrDecoderClass);
- }
- }
-
- public <T> void register(MessageEncoder<T> encoder) {
- register(new SingletonMessageEncoderFactory<T>(encoder));
- }
-
- public void register(MessageEncoderFactory<?> factory) {
- if (factory == null) {
- throw new NullPointerException("factory");
- }
- MessageEncoderFactory<?>[] encoderFactories = this.encoderFactories;
- MessageEncoderFactory<?>[] newEncoderFactories = new MessageEncoderFactory[encoderFactories.length + 1];
- System.arraycopy(encoderFactories, 0, newEncoderFactories, 0,
- encoderFactories.length);
- newEncoderFactories[encoderFactories.length] = factory;
- this.encoderFactories = newEncoderFactories;
- }
-
- public void register(MessageDecoder decoder) {
- register(new SingletonMessageDecoderFactory(decoder));
- }
-
- public void register(MessageDecoderFactory factory) {
- if (factory == null) {
- throw new NullPointerException("factory");
- }
- MessageDecoderFactory[] decoderFactories = this.decoderFactories;
- MessageDecoderFactory[] newDecoderFactories = new MessageDecoderFactory[decoderFactories.length + 1];
- System.arraycopy(decoderFactories, 0, newDecoderFactories, 0,
- decoderFactories.length);
- newDecoderFactories[decoderFactories.length] = factory;
- this.decoderFactories = newDecoderFactories;
- }
-
public ProtocolEncoder getEncoder() throws Exception {
- return new ProtocolEncoderImpl();
+ return encoder;
}
public ProtocolDecoder getDecoder() throws Exception {
- return new ProtocolDecoderImpl();
- }
-
- /**
- * Implement this method to release all resources acquired to perform
- * encoding and decoding messages for the specified <tt>session</tt>.
- * By default, this method does nothing.
- *
- * @param session the session that requires resource deallocation now
- */
- protected void disposeCodecResources(IoSession session) {
- // Do nothing by default; let users implement it as they want.
-
- // This statement is just to avoid compiler warning. Please ignore.
- session.getService();
+ return decoder;
}
-
+
@SuppressWarnings("unchecked")
- private class ProtocolEncoderImpl implements ProtocolEncoder {
- private final Map<Class<?>, MessageEncoder> encoders =
- new IdentityHashMap<Class<?>, MessageEncoder>();
-
- private ProtocolEncoderImpl() throws Exception {
- MessageEncoderFactory[] encoderFactories =
- DemuxingProtocolCodecFactory.this.encoderFactories;
- for (int i = encoderFactories.length - 1; i >= 0; i--) {
- MessageEncoder encoder = encoderFactories[i].getEncoder();
- Set<Class<?>> messageTypes = encoder.getMessageTypes();
- if (messageTypes == null) {
- throw new IllegalStateException(encoder.getClass()
- .getName()
- + "#getMessageTypes() may not return null.");
- }
-
- Iterator<Class<?>> it = messageTypes.iterator();
- while (it.hasNext()) {
- Class<?> type = it.next();
- encoders.put(type, encoder);
- }
- }
- }
-
- public void encode(IoSession session, Object message,
- ProtocolEncoderOutput out) throws Exception {
- Class<?> type = message.getClass();
- MessageEncoder encoder = findEncoder(type);
- if (encoder == null) {
- throw new ProtocolEncoderException("Unexpected message type: "
- + type);
- }
-
- encoder.encode(session, message, out);
- }
-
- private MessageEncoder findEncoder(Class<?> type) {
- MessageEncoder encoder = encoders.get(type);
- if (encoder == null) {
- encoder = findEncoder(type, new IdentityHashSet<Class<?>>());
- }
-
- return encoder;
- }
-
- private MessageEncoder findEncoder(Class<?> type,
- Set<Class<?>> triedClasses) {
- MessageEncoder encoder;
-
- if (triedClasses.contains(type)) {
- return null;
- }
- triedClasses.add(type);
-
- encoder = encoders.get(type);
- if (encoder == null) {
- encoder = findEncoder(type, triedClasses);
- if (encoder != null) {
- return encoder;
- }
-
- Class<?>[] interfaces = type.getInterfaces();
- for (Class<?> element : interfaces) {
- encoder = findEncoder(element, triedClasses);
- if (encoder != null) {
- return encoder;
- }
- }
-
- return null;
- } else {
- return encoder;
- }
- }
-
- public void dispose(IoSession session) throws Exception {
- DemuxingProtocolCodecFactory.this.disposeCodecResources(session);
- }
+ public void addMessageEncoder(Class<?> messageType, Class<? extends MessageEncoder> encoderClass) {
+ this.encoder.addMessageEncoder(messageType, encoderClass);
}
- private class ProtocolDecoderImpl extends CumulativeProtocolDecoder {
- private final MessageDecoder[] decoders;
-
- private MessageDecoder currentDecoder;
-
- protected ProtocolDecoderImpl() throws Exception {
- MessageDecoderFactory[] decoderFactories = DemuxingProtocolCodecFactory.this.decoderFactories;
- decoders = new MessageDecoder[decoderFactories.length];
- for (int i = decoderFactories.length - 1; i >= 0; i--) {
- decoders[i] = decoderFactories[i].getDecoder();
- }
- }
-
- @Override
- protected boolean doDecode(IoSession session, IoBuffer in,
- ProtocolDecoderOutput out) throws Exception {
- if (currentDecoder == null) {
- MessageDecoder[] decoders = this.decoders;
- int undecodables = 0;
- for (int i = decoders.length - 1; i >= 0; i--) {
- MessageDecoder decoder = decoders[i];
- int limit = in.limit();
- int pos = in.position();
-
- MessageDecoderResult result;
- try {
- result = decoder.decodable(session, in);
- } finally {
- in.position(pos);
- in.limit(limit);
- }
-
- if (result == MessageDecoder.OK) {
- currentDecoder = decoder;
- break;
- } else if (result == MessageDecoder.NOT_OK) {
- undecodables++;
- } else if (result != MessageDecoder.NEED_DATA) {
- throw new IllegalStateException(
- "Unexpected decode result (see your decodable()): "
- + result);
- }
- }
-
- if (undecodables == decoders.length) {
- // Throw an exception if all decoders cannot decode data.
- String dump = in.getHexDump();
- in.position(in.limit()); // Skip data
- throw new ProtocolDecoderException(
- "No appropriate message decoder: " + dump);
- }
-
- if (currentDecoder == null) {
- // Decoder is not determined yet (i.e. we need more data)
- return false;
- }
- }
-
- MessageDecoderResult result = currentDecoder.decode(session, in,
- out);
- if (result == MessageDecoder.OK) {
- currentDecoder = null;
- return true;
- } else if (result == MessageDecoder.NEED_DATA) {
- return false;
- } else if (result == MessageDecoder.NOT_OK) {
- currentDecoder = null;
- throw new ProtocolDecoderException(
- "Message decoder returned NOT_OK.");
- } else {
- currentDecoder = null;
- throw new IllegalStateException(
- "Unexpected decode result (see your decode()): "
- + result);
- }
- }
-
- @Override
- public void finishDecode(IoSession session, ProtocolDecoderOutput out)
- throws Exception {
- if (currentDecoder == null) {
- return;
- }
-
- currentDecoder.finishDecode(session, out);
- }
-
- @Override
- public void dispose(IoSession session) throws Exception {
- super.dispose(session);
-
- // ProtocolEncoder.dispose() already called disposeCodec(),
- // so there's nothing more we need to do.
- }
+ public <T> void addMessageEncoder(Class<T> messageType, MessageEncoder<? super T> encoder) {
+ this.encoder.addMessageEncoder(messageType, encoder);
}
- private static class SingletonMessageEncoderFactory<T> implements
- MessageEncoderFactory<T> {
- private final MessageEncoder<T> encoder;
-
- private SingletonMessageEncoderFactory(MessageEncoder<T> encoder) {
- if (encoder == null) {
- throw new NullPointerException("encoder");
- }
- this.encoder = encoder;
- }
-
- public MessageEncoder<T> getEncoder() {
- return encoder;
- }
+ public <T> void addMessageEncoder(Class<T> messageType, MessageEncoderFactory<? super T> factory) {
+ this.encoder.addMessageEncoder(messageType, factory);
}
- private static class SingletonMessageDecoderFactory implements
- MessageDecoderFactory {
- private final MessageDecoder decoder;
-
- private SingletonMessageDecoderFactory(MessageDecoder decoder) {
- if (decoder == null) {
- throw new NullPointerException("decoder");
- }
- this.decoder = decoder;
- }
-
- public MessageDecoder getDecoder() {
- return decoder;
- }
+ public void addMessageDecoder(Class<? extends MessageDecoder> decoderClass) {
+ this.decoder.addMessageDecoder(decoderClass);
}
- @SuppressWarnings("unchecked")
- private static class DefaultConstructorMessageEncoderFactory implements
- MessageEncoderFactory {
- private final Class encoderClass;
-
- private DefaultConstructorMessageEncoderFactory(Class encoderClass) {
- if (encoderClass == null) {
- throw new NullPointerException("encoderClass");
- }
-
- if (!MessageEncoder.class.isAssignableFrom(encoderClass)) {
- throw new IllegalArgumentException(
- "encoderClass is not assignable to MessageEncoder");
- }
- this.encoderClass = encoderClass;
- }
-
- public MessageEncoder getEncoder() throws Exception {
- return (MessageEncoder) encoderClass.newInstance();
- }
+ public void addMessageDecoder(MessageDecoder decoder) {
+ this.decoder.addMessageDecoder(decoder);
}
- private static class DefaultConstructorMessageDecoderFactory implements
- MessageDecoderFactory {
- private final Class<?> decoderClass;
-
- private DefaultConstructorMessageDecoderFactory(Class<?> decoderClass) {
- if (decoderClass == null) {
- throw new NullPointerException("decoderClass");
- }
-
- if (!MessageDecoder.class.isAssignableFrom(decoderClass)) {
- throw new IllegalArgumentException(
- "decoderClass is not assignable to MessageDecoder");
- }
- this.decoderClass = decoderClass;
- }
-
- public MessageDecoder getDecoder() throws Exception {
- return (MessageDecoder) decoderClass.newInstance();
- }
+ public void addMessageDecoder(MessageDecoderFactory factory) {
+ this.decoder.addMessageDecoder(factory);
}
}
Added: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDecoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDecoder.java?rev=590006&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDecoder.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDecoder.java Tue Oct 30 02:44:02 2007
@@ -0,0 +1,268 @@
+/*
+ * 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.filter.codec.demux;
+
+import org.apache.mina.common.AttributeKey;
+import org.apache.mina.common.IoBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolDecoderException;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+/**
+ * A composite {@link ProtocoDecoder} that demultiplexes incoming {@link IoBuffer}
+ * decoding requests into an appropriate {@link MessageDecoder}.
+ *
+ * <h2>Internal mechanism of {@link MessageDecoder} selection</h2>
+ * <p>
+ * <ol>
+ * <li>{@link DemuxingProtocolDecoder} iterates the list of candidate
+ * {@link MessageDecoder}s and calls {@link MessageDecoder#decodable(IoSession, IoBuffer)}.
+ * Initially, all registered {@link MessageDecoder}s are candidates.</li>
+ * <li>If {@link MessageDecoderResult#NOT_OK} is returned, it is removed from the candidate
+ * list.</li>
+ * <li>If {@link MessageDecoderResult#NEED_DATA} is returned, it is retained in the candidate
+ * list, and its {@link MessageDecoder#decodable(IoSession, IoBuffer)} will be invoked
+ * again when more data is received.</li>
+ * <li>If {@link MessageDecoderResult#OK} is returned, {@link DemuxingProtocolDecoder}
+ * found the right {@link MessageDecoder}.</li>
+ * <li>If there's no candidate left, an exception is raised. Otherwise,
+ * {@link DemuxingProtocolDecoder} will keep iterating the candidate list.
+ * </ol>
+ *
+ * Please note that any change of position and limit of the specified {@link IoBuffer}
+ * in {@link MessageDecoder#decodable(IoSession, IoBuffer)} will be reverted back to its
+ * original value.
+ * <p>
+ * Once a {@link MessageDecoder} is selected, {@link DemuxingProtocolDecoder} calls
+ * {@link MessageDecoder#decode(IoSession, IoBuffer, ProtocolDecoderOutput)} continuously
+ * reading its return value:
+ * <ul>
+ * <li>{@link MessageDecoderResult#NOT_OK} - protocol violation; {@link ProtocolDecoderException}
+ * is raised automatically.</li>
+ * <li>{@link MessageDecoderResult#NEED_DATA} - needs more data to read the whole message;
+ * {@link MessageDecoder#decode(IoSession, IoBuffer, ProtocolDecoderOutput)}
+ * will be invoked again when more data is received.</li>
+ * <li>{@link MessageDecoderResult#OK} - successfully decoded a message; the candidate list will
+ * be reset and the selection process will start over.</li>
+ * </ul>
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ *
+ * @see MessageDecoderFactory
+ * @see MessageDecoder
+ */
+public class DemuxingProtocolDecoder extends CumulativeProtocolDecoder {
+
+ private final AttributeKey STATE = new AttributeKey(getClass(), "state");
+
+ private MessageDecoderFactory[] decoderFactories = new MessageDecoderFactory[0];
+ private static final Class<?>[] EMPTY_PARAMS = new Class[0];
+
+ public DemuxingProtocolDecoder() {
+ }
+
+ public void addMessageDecoder(Class<? extends MessageDecoder> decoderClass) {
+ if (decoderClass == null) {
+ throw new NullPointerException("decoderClass");
+ }
+
+ try {
+ decoderClass.getConstructor(EMPTY_PARAMS);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException(
+ "The specified class doesn't have a public default constructor.");
+ }
+
+ boolean registered = false;
+ if (MessageDecoder.class.isAssignableFrom(decoderClass)) {
+ addMessageDecoder(new DefaultConstructorMessageDecoderFactory(decoderClass));
+ registered = true;
+ }
+
+ if (!registered) {
+ throw new IllegalArgumentException(
+ "Unregisterable type: " + decoderClass);
+ }
+ }
+
+ public void addMessageDecoder(MessageDecoder decoder) {
+ addMessageDecoder(new SingletonMessageDecoderFactory(decoder));
+ }
+
+ public void addMessageDecoder(MessageDecoderFactory factory) {
+ if (factory == null) {
+ throw new NullPointerException("factory");
+ }
+ MessageDecoderFactory[] decoderFactories = this.decoderFactories;
+ MessageDecoderFactory[] newDecoderFactories = new MessageDecoderFactory[decoderFactories.length + 1];
+ System.arraycopy(decoderFactories, 0, newDecoderFactories, 0,
+ decoderFactories.length);
+ newDecoderFactories[decoderFactories.length] = factory;
+ this.decoderFactories = newDecoderFactories;
+ }
+
+ @Override
+ protected boolean doDecode(IoSession session, IoBuffer in,
+ ProtocolDecoderOutput out) throws Exception {
+ State state = getState(session);
+ if (state.currentDecoder == null) {
+ MessageDecoder[] decoders = state.decoders;
+ int undecodables = 0;
+ for (int i = decoders.length - 1; i >= 0; i--) {
+ MessageDecoder decoder = decoders[i];
+ int limit = in.limit();
+ int pos = in.position();
+
+ MessageDecoderResult result;
+ try {
+ result = decoder.decodable(session, in);
+ } finally {
+ in.position(pos);
+ in.limit(limit);
+ }
+
+ if (result == MessageDecoder.OK) {
+ state.currentDecoder = decoder;
+ break;
+ } else if (result == MessageDecoder.NOT_OK) {
+ undecodables++;
+ } else if (result != MessageDecoder.NEED_DATA) {
+ throw new IllegalStateException(
+ "Unexpected decode result (see your decodable()): "
+ + result);
+ }
+ }
+
+ if (undecodables == decoders.length) {
+ // Throw an exception if all decoders cannot decode data.
+ String dump = in.getHexDump();
+ in.position(in.limit()); // Skip data
+ throw new ProtocolDecoderException(
+ "No appropriate message decoder: " + dump);
+ }
+
+ if (state.currentDecoder == null) {
+ // Decoder is not determined yet (i.e. we need more data)
+ return false;
+ }
+ }
+
+ MessageDecoderResult result = state.currentDecoder.decode(session, in,
+ out);
+ if (result == MessageDecoder.OK) {
+ state.currentDecoder = null;
+ return true;
+ } else if (result == MessageDecoder.NEED_DATA) {
+ return false;
+ } else if (result == MessageDecoder.NOT_OK) {
+ state.currentDecoder = null;
+ throw new ProtocolDecoderException(
+ "Message decoder returned NOT_OK.");
+ } else {
+ state.currentDecoder = null;
+ throw new IllegalStateException(
+ "Unexpected decode result (see your decode()): "
+ + result);
+ }
+ }
+
+ @Override
+ public void finishDecode(IoSession session, ProtocolDecoderOutput out)
+ throws Exception {
+ super.finishDecode(session, out);
+ State state = getState(session);
+ MessageDecoder currentDecoder = state.currentDecoder;
+ if (currentDecoder == null) {
+ return;
+ }
+
+ currentDecoder.finishDecode(session, out);
+ }
+
+ @Override
+ public void dispose(IoSession session) throws Exception {
+ super.dispose(session);
+ session.removeAttribute(STATE);
+ }
+
+ private State getState(IoSession session) throws Exception {
+ State state = (State) session.getAttribute(STATE);
+ if (state == null) {
+ state = new State();
+ State oldState = (State) session.setAttributeIfAbsent(STATE, state);
+ if (oldState != null) {
+ state = oldState;
+ }
+ }
+ return state;
+ }
+
+ private class State {
+ private final MessageDecoder[] decoders;
+ private MessageDecoder currentDecoder;
+
+ private State() throws Exception {
+ MessageDecoderFactory[] decoderFactories = DemuxingProtocolDecoder.this.decoderFactories;
+ decoders = new MessageDecoder[decoderFactories.length];
+ for (int i = decoderFactories.length - 1; i >= 0; i--) {
+ decoders[i] = decoderFactories[i].getDecoder();
+ }
+ }
+ }
+
+ private static class SingletonMessageDecoderFactory implements
+ MessageDecoderFactory {
+ private final MessageDecoder decoder;
+
+ private SingletonMessageDecoderFactory(MessageDecoder decoder) {
+ if (decoder == null) {
+ throw new NullPointerException("decoder");
+ }
+ this.decoder = decoder;
+ }
+
+ public MessageDecoder getDecoder() {
+ return decoder;
+ }
+ }
+
+ private static class DefaultConstructorMessageDecoderFactory implements
+ MessageDecoderFactory {
+ private final Class<?> decoderClass;
+
+ private DefaultConstructorMessageDecoderFactory(Class<?> decoderClass) {
+ if (decoderClass == null) {
+ throw new NullPointerException("decoderClass");
+ }
+
+ if (!MessageDecoder.class.isAssignableFrom(decoderClass)) {
+ throw new IllegalArgumentException(
+ "decoderClass is not assignable to MessageDecoder");
+ }
+ this.decoderClass = decoderClass;
+ }
+
+ public MessageDecoder getDecoder() throws Exception {
+ return (MessageDecoder) decoderClass.newInstance();
+ }
+ }
+}
Propchange: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDecoder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolDecoder.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEncoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEncoder.java?rev=590006&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEncoder.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEncoder.java Tue Oct 30 02:44:02 2007
@@ -0,0 +1,254 @@
+/*
+ * 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.filter.codec.demux;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.mina.common.AttributeKey;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.UnknownMessageTypeException;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+import org.apache.mina.util.IdentityHashSet;
+
+/**
+ * A composite {@link ProtocolEncoder} that demultiplexes incoming message
+ * encoding requests into an appropriate {@link MessageEncoder}.
+ *
+ * <h2>Disposing resources acquired by {@link MessageEncoder}</h2>
+ * <p>
+ * Override {@link #dispose(IoSession)} method. Please don't forget to call
+ * <tt>super.dispose()</tt>.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ *
+ * @see MessageEncoderFactory
+ * @see MessageEncoder
+ */
+public class DemuxingProtocolEncoder implements ProtocolEncoder {
+
+ private final AttributeKey STATE = new AttributeKey(getClass(), "state");
+
+ @SuppressWarnings("unchecked")
+ private final ConcurrentMap<Class<?>, MessageEncoderFactory> type2encoderFactory = new ConcurrentHashMap<Class<?>, MessageEncoderFactory>();
+
+ private static final Class<?>[] EMPTY_PARAMS = new Class[0];
+
+ public DemuxingProtocolEncoder() {
+ }
+
+ @SuppressWarnings("unchecked")
+ public void addMessageEncoder(Class<?> messageType, Class<? extends MessageEncoder> encoderClass) {
+ if (encoderClass == null) {
+ throw new NullPointerException("encoderClass");
+ }
+
+ try {
+ encoderClass.getConstructor(EMPTY_PARAMS);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException(
+ "The specified class doesn't have a public default constructor.");
+ }
+
+ boolean registered = false;
+ if (MessageEncoder.class.isAssignableFrom(encoderClass)) {
+ addMessageEncoder(messageType, new DefaultConstructorMessageEncoderFactory(encoderClass));
+ registered = true;
+ }
+
+ if (!registered) {
+ throw new IllegalArgumentException(
+ "Unregisterable type: " + encoderClass);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> void addMessageEncoder(Class<T> messageType, MessageEncoder<? super T> encoder) {
+ addMessageEncoder(messageType, new SingletonMessageEncoderFactory(encoder));
+ }
+
+ public <T> void addMessageEncoder(Class<T> messageType, MessageEncoderFactory<? super T> factory) {
+ if (messageType == null) {
+ throw new NullPointerException("messageType");
+ }
+
+ if (factory == null) {
+ throw new NullPointerException("factory");
+ }
+
+ if (type2encoderFactory.putIfAbsent(messageType, factory) != null) {
+ throw new IllegalStateException(
+ "The specified message type (" + messageType.getName() + ") is registered already.");
+ }
+ }
+
+ public void encode(IoSession session, Object message,
+ ProtocolEncoderOutput out) throws Exception {
+ State state = getState(session);
+ MessageEncoder<Object> encoder = findEncoder(state, message.getClass());
+ if (encoder != null) {
+ encoder.encode(session, message, out);
+ } else {
+ throw new UnknownMessageTypeException(
+ "No message encoder found for message: " + message);
+ }
+ }
+
+ protected MessageEncoder<Object> findEncoder(State state, Class<?> type) {
+ return findEncoder(state, type, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ private MessageEncoder<Object> findEncoder(
+ State state, Class type, Set<Class> triedClasses) {
+ MessageEncoder encoder = null;
+
+ if (triedClasses != null && triedClasses.contains(type)) {
+ return null;
+ }
+
+ /*
+ * Try the cache first.
+ */
+ encoder = state.findEncoderCache.get(type);
+ if (encoder != null) {
+ return encoder;
+ }
+
+ /*
+ * Try the registered encoders for an immediate match.
+ */
+ encoder = state.type2encoder.get(type);
+
+ if (encoder == null) {
+ /*
+ * No immediate match could be found. Search the type's interfaces.
+ */
+
+ if (triedClasses == null) {
+ triedClasses = new IdentityHashSet<Class>();
+ }
+ triedClasses.add(type);
+
+ Class[] interfaces = type.getInterfaces();
+ for (Class element : interfaces) {
+ encoder = findEncoder(state, element, triedClasses);
+ if (encoder != null) {
+ break;
+ }
+ }
+ }
+
+ if (encoder == null) {
+ /*
+ * No match in type's interfaces could be found. Search the
+ * superclass.
+ */
+
+ Class superclass = type.getSuperclass();
+ if (superclass != null) {
+ encoder = findEncoder(state, superclass);
+ }
+ }
+
+ /*
+ * Make sure the encoder is added to the cache. By updating the cache
+ * here all the types (superclasses and interfaces) in the path which
+ * led to a match will be cached along with the immediate message type.
+ */
+ if (encoder != null) {
+ state.findEncoderCache.put(type, encoder);
+ }
+
+ return encoder;
+ }
+
+ public void dispose(IoSession session) throws Exception {
+ session.removeAttribute(STATE);
+ }
+
+ private State getState(IoSession session) throws Exception {
+ State state = (State) session.getAttribute(STATE);
+ if (state == null) {
+ state = new State();
+ State oldState = (State) session.setAttributeIfAbsent(STATE, state);
+ if (oldState != null) {
+ state = oldState;
+ }
+ }
+ return state;
+ }
+
+ private class State {
+ @SuppressWarnings("unchecked")
+ private final Map<Class<?>, MessageEncoder> findEncoderCache = new ConcurrentHashMap<Class<?>, MessageEncoder>();
+
+ @SuppressWarnings("unchecked")
+ private final Map<Class<?>, MessageEncoder> type2encoder = new ConcurrentHashMap<Class<?>, MessageEncoder>();
+
+ @SuppressWarnings("unchecked")
+ private State() throws Exception {
+ for (Map.Entry<Class<?>, MessageEncoderFactory> e: type2encoderFactory.entrySet()) {
+ type2encoder.put(e.getKey(), e.getValue().getEncoder());
+ }
+ }
+ }
+
+ private static class SingletonMessageEncoderFactory<T> implements
+ MessageEncoderFactory<T> {
+ private final MessageEncoder<T> encoder;
+
+ private SingletonMessageEncoderFactory(MessageEncoder<T> encoder) {
+ if (encoder == null) {
+ throw new NullPointerException("encoder");
+ }
+ this.encoder = encoder;
+ }
+
+ public MessageEncoder<T> getEncoder() {
+ return encoder;
+ }
+ }
+
+ private static class DefaultConstructorMessageEncoderFactory<T> implements
+ MessageEncoderFactory<T> {
+ private final Class<MessageEncoder<T>> encoderClass;
+
+ private DefaultConstructorMessageEncoderFactory(Class<MessageEncoder<T>> encoderClass) {
+ if (encoderClass == null) {
+ throw new NullPointerException("encoderClass");
+ }
+
+ if (!MessageEncoder.class.isAssignableFrom(encoderClass)) {
+ throw new IllegalArgumentException(
+ "encoderClass is not assignable to MessageEncoder");
+ }
+ this.encoderClass = encoderClass;
+ }
+
+ public MessageEncoder<T> getEncoder() throws Exception {
+ return encoderClass.newInstance();
+ }
+ }
+}
Propchange: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEncoder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/DemuxingProtocolEncoder.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoder.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoder.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoder.java Tue Oct 30 02:44:02 2007
@@ -24,12 +24,16 @@
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
/**
- * Decodes specific messages.
+ * Decodes a certain type of messages.
+ * <p>
+ * We didn't provide any <tt>dispose</tt> method for {@link MessageDecoder}
+ * because it can give you performance penalty in case you have a lot of
+ * message types to handle.
*
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
*
- * @see DemuxingProtocolCodecFactory
+ * @see DemuxingProtocolDecoder
* @see MessageDecoderFactory
*/
public interface MessageDecoder {
Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderFactory.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderFactory.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderFactory.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageDecoderFactory.java Tue Oct 30 02:44:02 2007
@@ -25,7 +25,7 @@
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
*
- * @see DemuxingProtocolCodecFactory
+ * @see DemuxingProtocolDecoder
*/
public interface MessageDecoderFactory {
/**
Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoder.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoder.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoder.java Tue Oct 30 02:44:02 2007
@@ -19,27 +19,24 @@
*/
package org.apache.mina.filter.codec.demux;
-import java.util.Set;
-
import org.apache.mina.common.IoBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
/**
- * Encodes messages of specific types specified by {@link #getMessageTypes()}.
- *
+ * Encodes a certain type of messages.
+ * <p>
+ * We didn't provide any <tt>dispose</tt> method for {@link MessageEncoder}
+ * because it can give you performance penalty in case you have a lot of
+ * message types to handle.
+ *
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
*
- * @see DemuxingProtocolCodecFactory
+ * @see DemuxingProtocolEncoder
* @see MessageEncoderFactory
*/
public interface MessageEncoder<T> {
- /**
- * Returns the set of message classes this encoder can encode.
- */
- Set<Class<? extends T>> getMessageTypes();
-
/**
* Encodes higher-level message objects into binary or protocol-specific data.
* MINA invokes {@link #encode(IoSession, Object, ProtocolEncoderOutput)}
Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoderFactory.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoderFactory.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoderFactory.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/demux/MessageEncoderFactory.java Tue Oct 30 02:44:02 2007
@@ -25,7 +25,7 @@
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
*
- * @see DemuxingProtocolCodecFactory
+ * @see DemuxingProtocolEncoder
*/
public interface MessageEncoderFactory<T> {
/**
Modified: mina/trunk/core/src/main/java/org/apache/mina/handler/demux/DemuxingIoHandler.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/handler/demux/DemuxingIoHandler.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/handler/demux/DemuxingIoHandler.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/handler/demux/DemuxingIoHandler.java Tue Oct 30 02:44:02 2007
@@ -27,6 +27,7 @@
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
+import org.apache.mina.common.UnknownMessageTypeException;
import org.apache.mina.util.IdentityHashSet;
/**
Modified: mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpResponseEncoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpResponseEncoder.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpResponseEncoder.java (original)
+++ mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpResponseEncoder.java Tue Oct 30 02:44:02 2007
@@ -22,9 +22,6 @@
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
import java.util.Map.Entry;
import org.apache.mina.common.IoBuffer;
@@ -38,23 +35,15 @@
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
*/
-public class HttpResponseEncoder implements MessageEncoder {
- private static final Set<Class<?>> TYPES;
-
- static {
- Set<Class<?>> types = new HashSet<Class<?>>();
- types.add(HttpResponseMessage.class);
- TYPES = Collections.unmodifiableSet(types);
- }
+public class HttpResponseEncoder implements MessageEncoder<HttpResponseMessage> {
private static final byte[] CRLF = new byte[] { 0x0D, 0x0A };
public HttpResponseEncoder() {
}
- public void encode(IoSession session, Object message,
+ public void encode(IoSession session, HttpResponseMessage message,
ProtocolEncoderOutput out) throws Exception {
- HttpResponseMessage msg = (HttpResponseMessage) message;
IoBuffer buf = IoBuffer.allocate(256);
// Enable auto-expand for easier encoding
buf.setAutoExpand(true);
@@ -63,8 +52,8 @@
// output all headers except the content length
CharsetEncoder encoder = Charset.defaultCharset().newEncoder();
buf.putString("HTTP/1.1 ", encoder);
- buf.putString(String.valueOf(msg.getResponseCode()), encoder);
- switch (msg.getResponseCode()) {
+ buf.putString(String.valueOf(message.getResponseCode()), encoder);
+ switch (message.getResponseCode()) {
case HttpResponseMessage.HTTP_STATUS_SUCCESS:
buf.putString(" OK", encoder);
break;
@@ -73,7 +62,7 @@
break;
}
buf.put(CRLF);
- for (Entry<String, String> entry: msg.getHeaders().entrySet()) {
+ for (Entry<String, String> entry: message.getHeaders().entrySet()) {
buf.putString(entry.getKey(), encoder);
buf.putString(": ", encoder);
buf.putString(entry.getValue(), encoder);
@@ -81,11 +70,11 @@
}
// now the content length is the body length
buf.putString("Content-Length: ", encoder);
- buf.putString(String.valueOf(msg.getBodyLength()), encoder);
+ buf.putString(String.valueOf(message.getBodyLength()), encoder);
buf.put(CRLF);
buf.put(CRLF);
// add body
- buf.put(msg.getBody());
+ buf.put(message.getBody());
//System.out.println("\n+++++++");
//for (int i=0; i<buf.position();i++)System.out.print(new String(new byte[]{buf.get(i)}));
//System.out.println("\n+++++++");
@@ -95,9 +84,5 @@
buf.flip();
out.write(buf);
- }
-
- public Set<Class<?>> getMessageTypes() {
- return TYPES;
}
}
Modified: mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpServerProtocolCodecFactory.java
URL: http://svn.apache.org/viewvc/mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpServerProtocolCodecFactory.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpServerProtocolCodecFactory.java (original)
+++ mina/trunk/example/src/main/java/org/apache/mina/example/httpserver/codec/HttpServerProtocolCodecFactory.java Tue Oct 30 02:44:02 2007
@@ -30,7 +30,7 @@
public class HttpServerProtocolCodecFactory extends
DemuxingProtocolCodecFactory {
public HttpServerProtocolCodecFactory() {
- super.register(HttpRequestDecoder.class);
- super.register(HttpResponseEncoder.class);
+ super.addMessageDecoder(HttpRequestDecoder.class);
+ super.addMessageEncoder(HttpResponseMessage.class, HttpResponseEncoder.class);
}
}
Modified: mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageEncoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageEncoder.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageEncoder.java (original)
+++ mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AbstractMessageEncoder.java Tue Oct 30 02:44:02 2007
@@ -32,29 +32,26 @@
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
*/
-public abstract class AbstractMessageEncoder implements MessageEncoder {
+public abstract class AbstractMessageEncoder<T extends AbstractMessage> implements MessageEncoder<T> {
private final int type;
protected AbstractMessageEncoder(int type) {
this.type = type;
}
- public void encode(IoSession session, Object message,
- ProtocolEncoderOutput out) throws Exception {
- AbstractMessage m = (AbstractMessage) message;
+ public void encode(IoSession session, T message, ProtocolEncoderOutput out) throws Exception {
IoBuffer buf = IoBuffer.allocate(16);
buf.setAutoExpand(true); // Enable auto-expand for easier encoding
// Encode a header
buf.putShort((short) type);
- buf.putInt(m.getSequence());
+ buf.putInt(message.getSequence());
// Encode a body
- encodeBody(session, m, buf);
+ encodeBody(session, message, buf);
buf.flip();
out.write(buf);
}
- protected abstract void encodeBody(IoSession session,
- AbstractMessage message, IoBuffer out);
+ protected abstract void encodeBody(IoSession session, T message, IoBuffer out);
}
Modified: mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageEncoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageEncoder.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageEncoder.java (original)
+++ mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/AddMessageEncoder.java Tue Oct 30 02:44:02 2007
@@ -19,13 +19,8 @@
*/
package org.apache.mina.example.sumup.codec;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
import org.apache.mina.common.IoBuffer;
import org.apache.mina.common.IoSession;
-import org.apache.mina.example.sumup.message.AbstractMessage;
import org.apache.mina.example.sumup.message.AddMessage;
import org.apache.mina.filter.codec.demux.MessageEncoder;
@@ -35,28 +30,14 @@
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
*/
-public class AddMessageEncoder extends AbstractMessageEncoder {
- private static final Set<Class<?>> TYPES;
-
- static {
- Set<Class<?>> types = new HashSet<Class<?>>();
- types.add(AddMessage.class);
- TYPES = Collections.unmodifiableSet(types);
- }
-
+public class AddMessageEncoder<T extends AddMessage> extends AbstractMessageEncoder<T> {
public AddMessageEncoder() {
super(Constants.ADD);
}
@Override
- protected void encodeBody(IoSession session, AbstractMessage message,
- IoBuffer out) {
- AddMessage m = (AddMessage) message;
- out.putInt(m.getValue());
- }
-
- public Set<Class<?>> getMessageTypes() {
- return TYPES;
+ protected void encodeBody(IoSession session, T message, IoBuffer out) {
+ out.putInt(message.getValue());
}
public void dispose() throws Exception {
Modified: mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageEncoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageEncoder.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageEncoder.java (original)
+++ mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/ResultMessageEncoder.java Tue Oct 30 02:44:02 2007
@@ -19,13 +19,8 @@
*/
package org.apache.mina.example.sumup.codec;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
import org.apache.mina.common.IoBuffer;
import org.apache.mina.common.IoSession;
-import org.apache.mina.example.sumup.message.AbstractMessage;
import org.apache.mina.example.sumup.message.ResultMessage;
import org.apache.mina.filter.codec.demux.MessageEncoder;
@@ -35,36 +30,21 @@
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
*/
-public class ResultMessageEncoder extends AbstractMessageEncoder {
- private static final Set<Class<?>> TYPES;
-
- static {
- Set<Class<?>> types = new HashSet<Class<?>>();
- types.add(ResultMessage.class);
- TYPES = Collections.unmodifiableSet(types);
- }
-
+public class ResultMessageEncoder<T extends ResultMessage> extends AbstractMessageEncoder<T> {
public ResultMessageEncoder() {
super(Constants.RESULT);
}
@Override
- protected void encodeBody(IoSession session, AbstractMessage message,
- IoBuffer out) {
- ResultMessage m = (ResultMessage) message;
- if (m.isOk()) {
+ protected void encodeBody(IoSession session, T message, IoBuffer out) {
+ if (message.isOk()) {
out.putShort((short) Constants.RESULT_OK);
- out.putInt(m.getValue());
+ out.putInt(message.getValue());
} else {
out.putShort((short) Constants.RESULT_ERROR);
}
}
- public Set<Class<?>> getMessageTypes() {
- return TYPES;
- }
-
public void dispose() throws Exception {
}
-
}
Modified: mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/SumUpProtocolCodecFactory.java
URL: http://svn.apache.org/viewvc/mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/SumUpProtocolCodecFactory.java?rev=590006&r1=590005&r2=590006&view=diff
==============================================================================
--- mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/SumUpProtocolCodecFactory.java (original)
+++ mina/trunk/example/src/main/java/org/apache/mina/example/sumup/codec/SumUpProtocolCodecFactory.java Tue Oct 30 02:44:02 2007
@@ -19,6 +19,8 @@
*/
package org.apache.mina.example.sumup.codec;
+import org.apache.mina.example.sumup.message.AddMessage;
+import org.apache.mina.example.sumup.message.ResultMessage;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory;
@@ -33,12 +35,12 @@
public SumUpProtocolCodecFactory(boolean server) {
if (server) {
- super.register(AddMessageDecoder.class);
- super.register(ResultMessageEncoder.class);
+ super.addMessageDecoder(AddMessageDecoder.class);
+ super.addMessageEncoder(ResultMessage.class, ResultMessageEncoder.class);
} else // Client
{
- super.register(AddMessageEncoder.class);
- super.register(ResultMessageDecoder.class);
+ super.addMessageEncoder(AddMessage.class, AddMessageEncoder.class);
+ super.addMessageDecoder(ResultMessageDecoder.class);
}
}
}