Introduce UniqueName, UniqueKey, and Signal
- UniqueKey removes the duplication between ChannelOption and AttributeKey - UniqueName provides common name collision check for AttributeKey, ChannelOption, and Signal. - Replaced ReplayError with Signal
This commit is contained in:
parent
5344dc242c
commit
dbd973d825
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The Netty Project
|
||||
*
|
||||
* The Netty Project 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 io.netty.handler.codec;
|
||||
|
||||
final class ReplayError extends Error {
|
||||
|
||||
private static final long serialVersionUID = 2666698631187527681L;
|
||||
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelInboundHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.util.Signal;
|
||||
|
||||
/**
|
||||
* A specialized variation of {@link StreamToMessageDecoder} which enables implementation
|
||||
@ -281,6 +282,8 @@ import io.netty.channel.ChannelPipeline;
|
||||
*/
|
||||
public abstract class ReplayingDecoder<O, S extends Enum<S>> extends ChannelInboundHandlerAdapter<Byte> {
|
||||
|
||||
static final Signal REPLAY = new Signal(ReplayingDecoder.class.getName() + ".REPLAY");
|
||||
|
||||
private final ChannelBufferHolder<Byte> in = ChannelBufferHolders.byteBuffer();
|
||||
private final ChannelBuffer cumulation = in.byteBuffer();
|
||||
private final ReplayingDecoderBuffer replayable = new ReplayingDecoderBuffer(cumulation);
|
||||
@ -365,8 +368,9 @@ public abstract class ReplayingDecoder<O, S extends Enum<S>> extends ChannelInbo
|
||||
in.discardReadBytes();
|
||||
ctx.fireInboundBufferUpdated();
|
||||
}
|
||||
} catch (ReplayError replay) {
|
||||
} catch (Signal replay) {
|
||||
// Ignore
|
||||
replay.expect(REPLAY);
|
||||
} catch (Throwable t) {
|
||||
ctx.fireExceptionCaught(t);
|
||||
}
|
||||
@ -393,7 +397,8 @@ public abstract class ReplayingDecoder<O, S extends Enum<S>> extends ChannelInbo
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (ReplayError replay) {
|
||||
} catch (Signal replay) {
|
||||
replay.expect(REPLAY);
|
||||
// Return to the checkpoint (or oldPosition) and retry.
|
||||
int checkpoint = this.checkpoint;
|
||||
if (checkpoint >= 0) {
|
||||
|
@ -15,6 +15,12 @@
|
||||
*/
|
||||
package io.netty.handler.codec;
|
||||
|
||||
import io.netty.buffer.ChannelBuffer;
|
||||
import io.netty.buffer.ChannelBufferFactory;
|
||||
import io.netty.buffer.ChannelBufferIndexFinder;
|
||||
import io.netty.buffer.ChannelBuffers;
|
||||
import io.netty.util.Signal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@ -24,14 +30,9 @@ import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import io.netty.buffer.ChannelBuffer;
|
||||
import io.netty.buffer.ChannelBufferFactory;
|
||||
import io.netty.buffer.ChannelBufferIndexFinder;
|
||||
import io.netty.buffer.ChannelBuffers;
|
||||
|
||||
class ReplayingDecoderBuffer implements ChannelBuffer {
|
||||
|
||||
private static final Error REPLAY = new ReplayError();
|
||||
private static final Signal REPLAY = ReplayingDecoder.REPLAY;
|
||||
|
||||
private final ChannelBuffer buffer;
|
||||
private boolean terminated;
|
||||
@ -119,7 +120,7 @@ class ReplayingDecoderBuffer implements ChannelBuffer {
|
||||
public ChannelBuffer duplicate() {
|
||||
throw new UnreplayableOperationException();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(int index) {
|
||||
checkIndex(index);
|
||||
@ -356,8 +357,8 @@ class ReplayingDecoderBuffer implements ChannelBuffer {
|
||||
} else {
|
||||
return Integer.MAX_VALUE - buffer.readerIndex();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readBoolean() {
|
||||
checkReadableBytes(1);
|
||||
@ -511,7 +512,7 @@ class ReplayingDecoderBuffer implements ChannelBuffer {
|
||||
public void resetWriterIndex() {
|
||||
throw new UnreplayableOperationException();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBoolean(int index, boolean value) {
|
||||
throw new UnreplayableOperationException();
|
||||
@ -679,7 +680,7 @@ class ReplayingDecoderBuffer implements ChannelBuffer {
|
||||
public int writableBytes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void writeBoolean(boolean value) {
|
||||
throw new UnreplayableOperationException();
|
||||
|
@ -1,51 +1,13 @@
|
||||
package io.netty.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public final class AttributeKey<T> implements Serializable, Comparable<AttributeKey<T>> {
|
||||
|
||||
private static final long serialVersionUID = 2783354860083517323L;
|
||||
public final class AttributeKey<T> extends UniqueKey<T> {
|
||||
|
||||
private static final ConcurrentMap<String, Boolean> names = new ConcurrentHashMap<String, Boolean>();
|
||||
|
||||
private final String name;
|
||||
private final Class<T> valueType;
|
||||
private final String strVal;
|
||||
|
||||
public AttributeKey(String name, Class<T> valueType) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
if (valueType == null) {
|
||||
throw new NullPointerException("valueType");
|
||||
}
|
||||
|
||||
if (names.putIfAbsent(name, Boolean.TRUE) != null) {
|
||||
throw new IllegalArgumentException("key name already in use: " + name);
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
this.valueType = valueType;
|
||||
strVal = name + '[' + valueType.getSimpleName() + ']';
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<T> valueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AttributeKey<T> o) {
|
||||
return name().compareTo(o.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strVal;
|
||||
super(names, name, valueType);
|
||||
}
|
||||
}
|
||||
|
47
common/src/main/java/io/netty/util/Signal.java
Normal file
47
common/src/main/java/io/netty/util/Signal.java
Normal file
@ -0,0 +1,47 @@
|
||||
package io.netty.util;
|
||||
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public final class Signal extends Error {
|
||||
|
||||
private static final long serialVersionUID = -221145131122459977L;
|
||||
|
||||
private static final ConcurrentMap<String, Boolean> map =
|
||||
new ConcurrentHashMap<String, Boolean>();
|
||||
|
||||
private final SignalName uname;
|
||||
|
||||
public Signal(String name) {
|
||||
super(name);
|
||||
uname = new SignalName(name);
|
||||
}
|
||||
|
||||
public void expect(Signal signal) {
|
||||
if (this != signal) {
|
||||
throw new IllegalStateException("unexpected signal: " + signal);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable initCause(Throwable cause) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return uname.name();
|
||||
}
|
||||
|
||||
private static class SignalName extends UniqueName {
|
||||
protected SignalName(String name) {
|
||||
super(map, name);
|
||||
}
|
||||
}
|
||||
}
|
32
common/src/main/java/io/netty/util/UniqueKey.java
Normal file
32
common/src/main/java/io/netty/util/UniqueKey.java
Normal file
@ -0,0 +1,32 @@
|
||||
package io.netty.util;
|
||||
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class UniqueKey<T> extends UniqueName {
|
||||
|
||||
private final Class<T> valueType;
|
||||
private final String strVal;
|
||||
|
||||
protected UniqueKey(ConcurrentMap<String, Boolean> map, String name, Class<T> valueType) {
|
||||
super(map, name, valueType);
|
||||
this.valueType = valueType;
|
||||
strVal = name + '[' + valueType.getSimpleName() + ']';
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateArgs(Object... args) {
|
||||
super.validateArgs(args);
|
||||
if (args[0] == null) {
|
||||
throw new NullPointerException("valueType");
|
||||
}
|
||||
}
|
||||
|
||||
public final Class<T> valueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strVal;
|
||||
}
|
||||
}
|
74
common/src/main/java/io/netty/util/UniqueName.java
Normal file
74
common/src/main/java/io/netty/util/UniqueName.java
Normal file
@ -0,0 +1,74 @@
|
||||
package io.netty.util;
|
||||
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class UniqueName implements Comparable<UniqueName> {
|
||||
|
||||
private static final AtomicInteger nextId = new AtomicInteger();
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
||||
protected UniqueName(ConcurrentMap<String, Boolean> map, String name, Object... args) {
|
||||
if (map == null) {
|
||||
throw new NullPointerException("map");
|
||||
}
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
if (args != null && args.length > 0) {
|
||||
validateArgs(args);
|
||||
}
|
||||
|
||||
if (map.putIfAbsent(name, Boolean.TRUE) != null) {
|
||||
throw new IllegalArgumentException(String.format("'%s' already in use", name));
|
||||
}
|
||||
|
||||
id = nextId.incrementAndGet();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void validateArgs(Object... args) {
|
||||
// Subclasses will override.
|
||||
}
|
||||
|
||||
public final String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(UniqueName o) {
|
||||
if (this == o) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = name.compareTo(o.name);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (id < o.id) {
|
||||
return -1;
|
||||
} else if (id > o.id) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name();
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package io.netty.channel;
|
||||
|
||||
import io.netty.util.UniqueKey;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketAddress;
|
||||
@ -7,7 +9,7 @@ import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class ChannelOption<T> implements Comparable<ChannelOption<T>> {
|
||||
public class ChannelOption<T> extends UniqueKey<T> {
|
||||
|
||||
private static final ConcurrentMap<String, Boolean> names = new ConcurrentHashMap<String, Boolean>();
|
||||
|
||||
@ -75,33 +77,8 @@ public class ChannelOption<T> implements Comparable<ChannelOption<T>> {
|
||||
public static final ChannelOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR =
|
||||
new ChannelOption<SocketAddress>("SCTP_SET_PEER_PRIMARY_ADDR", SocketAddress.class);
|
||||
|
||||
private final String name;
|
||||
private final Class<T> valueType;
|
||||
private final String strVal;
|
||||
|
||||
public ChannelOption(String name, Class<T> valueType) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
if (valueType == null) {
|
||||
throw new NullPointerException("valueType");
|
||||
}
|
||||
|
||||
if (names.putIfAbsent(name, Boolean.TRUE) != null) {
|
||||
throw new IllegalArgumentException("option name already in use: " + name);
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
this.valueType = valueType;
|
||||
strVal = name + '[' + valueType.getSimpleName() + ']';
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<T> valueType() {
|
||||
return valueType;
|
||||
super(names, name, valueType);
|
||||
}
|
||||
|
||||
public void validate(T value) {
|
||||
@ -109,14 +86,4 @@ public class ChannelOption<T> implements Comparable<ChannelOption<T>> {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ChannelOption<T> o) {
|
||||
return name().compareTo(o.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strVal;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user