Add constructor parameters that do not perform type parameter auto-detection for the languages without type parameters

- Fixes #1177
- Add TypeParameterMatcher.get(parameterType)
- Add alternative constructors
This commit is contained in:
Trustin Lee 2013-03-21 16:11:47 +09:00
parent 2b014ce82a
commit 8b722d29a7
8 changed files with 79 additions and 24 deletions

View File

@ -56,6 +56,10 @@ public abstract class ByteToMessageCodec<I> extends ChannelDuplexHandler
outboundMsgMatcher = TypeParameterMatcher.find(this, ByteToMessageCodec.class, "I"); outboundMsgMatcher = TypeParameterMatcher.find(this, ByteToMessageCodec.class, "I");
} }
protected ByteToMessageCodec(Class<? extends I> outboundMessageType) {
outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType);
}
@Override @Override
public void beforeAdd(ChannelHandlerContext ctx) throws Exception { public void beforeAdd(ChannelHandlerContext ctx) throws Exception {
decoder.beforeAdd(ctx); decoder.beforeAdd(ctx);

View File

@ -40,6 +40,12 @@ import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
*/ */
public abstract class MessageToByteEncoder<I> extends ChannelOutboundMessageHandlerAdapter<I> { public abstract class MessageToByteEncoder<I> extends ChannelOutboundMessageHandlerAdapter<I> {
protected MessageToByteEncoder() { }
protected MessageToByteEncoder(Class<? extends I> outboundMessageType) {
super(outboundMessageType);
}
@Override @Override
public void flush(ChannelHandlerContext ctx, I msg) throws Exception { public void flush(ChannelHandlerContext ctx, I msg) throws Exception {
try { try {

View File

@ -90,6 +90,12 @@ public abstract class MessageToMessageCodec<INBOUND_IN, OUTBOUND_IN>
outboundMsgMatcher = TypeParameterMatcher.find(this, MessageToMessageCodec.class, "OUTBOUND_IN"); outboundMsgMatcher = TypeParameterMatcher.find(this, MessageToMessageCodec.class, "OUTBOUND_IN");
} }
protected MessageToMessageCodec(
Class<? extends INBOUND_IN> inboundMessageType, Class<? extends OUTBOUND_IN> outboundMessageType) {
inboundMsgMatcher = TypeParameterMatcher.get(inboundMessageType);
outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType);
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public MessageBuf<INBOUND_IN> newInboundBuffer(ChannelHandlerContext ctx) throws Exception { public MessageBuf<INBOUND_IN> newInboundBuffer(ChannelHandlerContext ctx) throws Exception {

View File

@ -44,6 +44,12 @@ import io.netty.channel.ChannelInboundMessageHandlerAdapter;
*/ */
public abstract class MessageToMessageDecoder<I> extends ChannelInboundMessageHandlerAdapter<I> { public abstract class MessageToMessageDecoder<I> extends ChannelInboundMessageHandlerAdapter<I> {
protected MessageToMessageDecoder() { }
protected MessageToMessageDecoder(Class<? extends I> inboundMessageType) {
super(inboundMessageType);
}
@Override @Override
public final void messageReceived(ChannelHandlerContext ctx, I msg) throws Exception { public final void messageReceived(ChannelHandlerContext ctx, I msg) throws Exception {
ctx.nextInboundMessageBuffer().unfoldAndAdd(decode(ctx, msg)); ctx.nextInboundMessageBuffer().unfoldAndAdd(decode(ctx, msg));

View File

@ -42,6 +42,12 @@ import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
*/ */
public abstract class MessageToMessageEncoder<I> extends ChannelOutboundMessageHandlerAdapter<I> { public abstract class MessageToMessageEncoder<I> extends ChannelOutboundMessageHandlerAdapter<I> {
protected MessageToMessageEncoder() { }
protected MessageToMessageEncoder(Class<? extends I> outboundMessageType) {
super(outboundMessageType);
}
@Override @Override
public final void flush(ChannelHandlerContext ctx, I msg) throws Exception { public final void flush(ChannelHandlerContext ctx, I msg) throws Exception {
try { try {

View File

@ -30,7 +30,45 @@ public abstract class TypeParameterMatcher {
private static final TypeParameterMatcher NOOP = new NoOpTypeParameterMatcher(); private static final TypeParameterMatcher NOOP = new NoOpTypeParameterMatcher();
private static final Object TEST_OBJECT = new Object(); private static final Object TEST_OBJECT = new Object();
private static final ThreadLocal<Map<Class<?>, Map<String, TypeParameterMatcher>>> typeMap = private static final ThreadLocal<Map<Class<?>, TypeParameterMatcher>> getCache =
new ThreadLocal<Map<Class<?>, TypeParameterMatcher>>() {
@Override
protected Map<Class<?>, TypeParameterMatcher> initialValue() {
return new IdentityHashMap<Class<?>, TypeParameterMatcher>();
}
};
public static TypeParameterMatcher get(final Class<?> parameterType) {
final Map<Class<?>, TypeParameterMatcher> getCache = TypeParameterMatcher.getCache.get();
TypeParameterMatcher matcher = getCache.get(parameterType);
if (matcher == null) {
if (parameterType == Object.class) {
matcher = NOOP;
} else if (PlatformDependent.hasJavassist()) {
try {
matcher = JavassistTypeParameterMatcherGenerator.generate(parameterType);
matcher.match(TEST_OBJECT);
} catch (IllegalAccessError e) {
// Happens if parameterType is not public.
matcher = null;
} catch (Exception e) {
// Will not usually happen, but just in case.
matcher = null;
}
}
if (matcher == null) {
matcher = new ReflectiveMatcher(parameterType);
}
getCache.put(parameterType, matcher);
}
return matcher;
}
private static final ThreadLocal<Map<Class<?>, Map<String, TypeParameterMatcher>>> findCache =
new ThreadLocal<Map<Class<?>, Map<String, TypeParameterMatcher>>>() { new ThreadLocal<Map<Class<?>, Map<String, TypeParameterMatcher>>>() {
@Override @Override
protected Map<Class<?>, Map<String, TypeParameterMatcher>> initialValue() { protected Map<Class<?>, Map<String, TypeParameterMatcher>> initialValue() {
@ -41,37 +79,18 @@ public abstract class TypeParameterMatcher {
public static TypeParameterMatcher find( public static TypeParameterMatcher find(
final Object object, final Class<?> parameterizedSuperclass, final String typeParamName) { final Object object, final Class<?> parameterizedSuperclass, final String typeParamName) {
final Map<Class<?>, Map<String, TypeParameterMatcher>> typeMap = TypeParameterMatcher.typeMap.get(); final Map<Class<?>, Map<String, TypeParameterMatcher>> findCache = TypeParameterMatcher.findCache.get();
final Class<?> thisClass = object.getClass(); final Class<?> thisClass = object.getClass();
Map<String, TypeParameterMatcher> map = typeMap.get(thisClass); Map<String, TypeParameterMatcher> map = findCache.get(thisClass);
if (map == null) { if (map == null) {
map = new HashMap<String, TypeParameterMatcher>(); map = new HashMap<String, TypeParameterMatcher>();
typeMap.put(thisClass, map); findCache.put(thisClass, map);
} }
TypeParameterMatcher matcher = map.get(typeParamName); TypeParameterMatcher matcher = map.get(typeParamName);
if (matcher == null) { if (matcher == null) {
Class<?> messageType = find0(object, parameterizedSuperclass, typeParamName); matcher = get(find0(object, parameterizedSuperclass, typeParamName));
if (messageType == Object.class) {
matcher = NOOP;
} else if (PlatformDependent.hasJavassist()) {
try {
matcher = JavassistTypeParameterMatcherGenerator.generate(messageType);
matcher.match(TEST_OBJECT);
} catch (IllegalAccessError e) {
// Happens if messageType is not public.
matcher = null;
} catch (Exception e) {
// Will not usually happen, but just in case.
matcher = null;
}
}
if (matcher == null) {
matcher = new ReflectiveMatcher(messageType);
}
map.put(typeParamName, matcher); map.put(typeParamName, matcher);
} }

View File

@ -63,6 +63,10 @@ public abstract class ChannelInboundMessageHandlerAdapter<I>
msgMatcher = TypeParameterMatcher.find(this, ChannelInboundMessageHandlerAdapter.class, "I"); msgMatcher = TypeParameterMatcher.find(this, ChannelInboundMessageHandlerAdapter.class, "I");
} }
protected ChannelInboundMessageHandlerAdapter(Class<? extends I> inboundMessageType) {
msgMatcher = TypeParameterMatcher.get(inboundMessageType);
}
@Override @Override
public MessageBuf<I> newInboundBuffer(ChannelHandlerContext ctx) throws Exception { public MessageBuf<I> newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
return Unpooled.messageBuffer(); return Unpooled.messageBuffer();

View File

@ -47,6 +47,10 @@ public abstract class ChannelOutboundMessageHandlerAdapter<I>
msgMatcher = TypeParameterMatcher.find(this, ChannelOutboundMessageHandlerAdapter.class, "I"); msgMatcher = TypeParameterMatcher.find(this, ChannelOutboundMessageHandlerAdapter.class, "I");
} }
protected ChannelOutboundMessageHandlerAdapter(Class<? extends I> outboundMessageType) {
msgMatcher = TypeParameterMatcher.get(outboundMessageType);
}
protected final boolean isCloseOnFailedFlush() { protected final boolean isCloseOnFailedFlush() {
return closeOnFailedFlush; return closeOnFailedFlush;
} }