* Added JavaDoc for the handler.codec.serialization package

* Improved JavaDoc for handler.codec.string and handler.ssl
This commit is contained in:
Trustin Lee 2008-09-04 05:48:41 +00:00
parent f0c2c95c32
commit f744de9d85
8 changed files with 205 additions and 25 deletions

View File

@ -24,6 +24,7 @@ package org.jboss.netty.handler.codec.serialization;
import java.io.InputStream; import java.io.InputStream;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamConstants; import java.io.ObjectStreamConstants;
import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffer;
@ -34,6 +35,20 @@ import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
import org.jboss.netty.util.SwitchableInputStream; import org.jboss.netty.util.SwitchableInputStream;
/** /**
* A decoder which deserializes the received {@link ChannelBuffer}s into Java
* objects (interoperability version).
* <p>
* This decoder is interoperable with the standard Java object
* streams such as {@link ObjectInputStream} and {@link ObjectOutputStream}.
* <p>
* However, this decoder might perform worse than {@link ObjectDecoder} if
* the serialized object is big and complex. Also, it doesn't limit the
* maximum size of the object, and consequently your application might face
* the risk of <a href="http://en.wikipedia.org/wiki/DoS">DoS attack</a>.
* Please use {@link ObjectEncoder} and {@link ObjectDecoder} if you are not
* required to keep the interoperability with the standard object streams.
*
*
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
* *
@ -45,10 +60,22 @@ public class CompatibleObjectDecoder extends ReplayingDecoder<CompatibleObjectDe
private final SwitchableInputStream bin = new SwitchableInputStream(); private final SwitchableInputStream bin = new SwitchableInputStream();
private volatile ObjectInputStream oin; private volatile ObjectInputStream oin;
/**
* Creates a new decoder.
*/
public CompatibleObjectDecoder() { public CompatibleObjectDecoder() {
super(CompatibleObjectDecoderState.READ_HEADER); super(CompatibleObjectDecoderState.READ_HEADER);
} }
/**
* Creates a new {@link ObjectInputStream} which wraps the specified
* {@link InputStream}. Override this method to use a subclass of the
* {@link ObjectInputStream}.
*/
protected ObjectInputStream newObjectInputStream(InputStream in) throws Exception {
return new ObjectInputStream(in);
}
@Override @Override
protected Object decode( protected Object decode(
ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, CompatibleObjectDecoderState state) throws Exception { ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, CompatibleObjectDecoderState state) throws Exception {
@ -65,10 +92,6 @@ public class CompatibleObjectDecoder extends ReplayingDecoder<CompatibleObjectDe
} }
} }
protected ObjectInputStream newObjectInputStream(InputStream in) throws Exception {
return new ObjectInputStream(in);
}
@Override @Override
protected Object decodeLast(ChannelHandlerContext ctx, Channel channel, protected Object decodeLast(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buffer, CompatibleObjectDecoderState state) ChannelBuffer buffer, CompatibleObjectDecoderState state)

View File

@ -25,6 +25,7 @@ package org.jboss.netty.handler.codec.serialization;
import static org.jboss.netty.buffer.ChannelBuffers.*; import static org.jboss.netty.buffer.ChannelBuffers.*;
import static org.jboss.netty.channel.Channels.*; import static org.jboss.netty.channel.Channels.*;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -37,11 +38,16 @@ import org.jboss.netty.channel.ChannelPipelineCoverage;
import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.MessageEvent;
/** /**
* An encoder which serializes a Java object into a {@link ChannelBuffer}
* (interoperability version).
* <p>
* This encoder is interoperable with the standard Java object streams such as
* {@link ObjectInputStream} and {@link ObjectOutputStream}.
*
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
* *
* @version $Rev:231 $, $Date:2008-06-12 16:44:50 +0900 (, 12 6월 2008) $ * @version $Rev:231 $, $Date:2008-06-12 16:44:50 +0900 (, 12 6월 2008) $
*
*/ */
@ChannelPipelineCoverage("all") @ChannelPipelineCoverage("all")
public class CompatibleObjectEncoder implements ChannelDownstreamHandler { public class CompatibleObjectEncoder implements ChannelDownstreamHandler {
@ -51,10 +57,22 @@ public class CompatibleObjectEncoder implements ChannelDownstreamHandler {
private volatile ObjectOutputStream oout; private volatile ObjectOutputStream oout;
private int writtenObjects; private int writtenObjects;
/**
* Creates a new instance with the reset interval of {@code 16}.
*/
public CompatibleObjectEncoder() { public CompatibleObjectEncoder() {
this(16); // Reset at every sixteen writes this(16); // Reset at every sixteen writes
} }
/**
* Creates a new instance.
*
* @param resetInterval
* the number of objects between {@link ObjectOutputStream#reset()}.
* {@code 0} will disable resetting the stream, but the remote
* peer will be at the risk of getting {@link OutOfMemoryError} in
* the long term.
*/
public CompatibleObjectEncoder(int resetInterval) { public CompatibleObjectEncoder(int resetInterval) {
if (resetInterval < 0) { if (resetInterval < 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
@ -63,6 +81,15 @@ public class CompatibleObjectEncoder implements ChannelDownstreamHandler {
this.resetInterval = resetInterval; this.resetInterval = resetInterval;
} }
/**
* Creates a new {@link ObjectOutputStream} which wraps the specified
* {@link OutputStream}. Override this method to use a subclass of the
* {@link ObjectOutputStream}.
*/
protected ObjectOutputStream newObjectOutputStream(OutputStream out) throws Exception {
return new ObjectOutputStream(out);
}
public void handleDownstream( public void handleDownstream(
ChannelHandlerContext context, ChannelEvent evt) throws Exception { ChannelHandlerContext context, ChannelEvent evt) throws Exception {
if (!(evt instanceof MessageEvent)) { if (!(evt instanceof MessageEvent)) {
@ -90,8 +117,4 @@ public class CompatibleObjectEncoder implements ChannelDownstreamHandler {
ChannelBuffer encoded = buffer.readBytes(buffer.readableBytes()); ChannelBuffer encoded = buffer.readBytes(buffer.readableBytes());
write(context, e.getChannel(), e.getFuture(), encoded, e.getRemoteAddress()); write(context, e.getChannel(), e.getFuture(), encoded, e.getRemoteAddress());
} }
protected ObjectOutputStream newObjectOutputStream(OutputStream out) throws Exception {
return new ObjectOutputStream(out);
}
} }

View File

@ -22,6 +22,7 @@
*/ */
package org.jboss.netty.handler.codec.serialization; package org.jboss.netty.handler.codec.serialization;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException; import java.io.StreamCorruptedException;
import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffer;
@ -31,32 +32,65 @@ import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder; import org.jboss.netty.handler.codec.frame.FrameDecoder;
/** /**
* A decoder which deserializes the received {@link ChannelBuffer}s into Java
* objects.
* <p>
* Please note that the serialized form this decoder expects is not
* compatible with the standard {@link ObjectOutputStream}. Please use
* {@link ObjectEncoder} or {@link ObjectEncoderOutputStream} to ensure the
* interoperability with this decoder.
* <p>
* Unless there's a requirement for the interoperability with the standard
* object streams, it is recommended to use {@link ObjectEncoder} and
* {@link ObjectDecoder} rather than {@link CompatibleObjectEncoder} and
* {@link CompatibleObjectDecoder}.
*
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
* *
* @version $Rev$, $Date$ * @version $Rev$, $Date$
*
*/ */
public class ObjectDecoder extends FrameDecoder { public class ObjectDecoder extends FrameDecoder {
private final int maxObjectSize; private final int maxObjectSize;
private final ClassLoader classLoader; private final ClassLoader classLoader;
/**
* Creates a new decoder whose maximum object size is {@code 1048576}
* bytes. If the size of the received object is greater than
* {@code 1048576} bytes, a {@link StreamCorruptedException} will be
* raised.
*/
public ObjectDecoder() { public ObjectDecoder() {
this(1048576); this(1048576);
} }
/**
* Creates a new decoder with the specified maximum object size.
*
* @param maxObjectSize the maximum byte length of the serialized object.
* if the length of the received object is greater
* than this value, {@link StreamCorruptedException}
* will be raised.
*/
public ObjectDecoder(int maxObjectSize) { public ObjectDecoder(int maxObjectSize) {
this(maxObjectSize, Thread.currentThread().getContextClassLoader()); this(maxObjectSize, null);
} }
/**
* Creates a new decoder with the specified maximum object size.
*
* @param maxObjectSize the maximum byte length of the serialized object.
* if the length of the received object is greater
* than this value, {@link StreamCorruptedException}
* will be raised.
* @param classLoader the {@link ClassLoader} which will load the class
* of the serialized object
*/
public ObjectDecoder(int maxObjectSize, ClassLoader classLoader) { public ObjectDecoder(int maxObjectSize, ClassLoader classLoader) {
if (maxObjectSize <= 0) { if (maxObjectSize <= 0) {
throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize); throw new IllegalArgumentException("maxObjectSize: " + maxObjectSize);
} }
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
this.maxObjectSize = maxObjectSize; this.maxObjectSize = maxObjectSize;
this.classLoader = classLoader; this.classLoader = classLoader;
@ -83,8 +117,7 @@ public class ObjectDecoder extends FrameDecoder {
} }
buffer.skipBytes(4); buffer.skipBytes(4);
return new CompactObjectInputStream( return new CompactObjectInputStream(new ChannelBufferInputStream(
new ChannelBufferInputStream(buffer, dataLen), buffer, dataLen), classLoader).readObject();
classLoader).readObject();
} }
} }

View File

@ -29,6 +29,9 @@ import java.io.ObjectInput;
import java.io.StreamCorruptedException; import java.io.StreamCorruptedException;
/** /**
* An {@link ObjectInput} which is interoperable with {@link ObjectEncoder}
* and {@link ObjectEncoderOutputStream}.
*
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
* *
@ -42,18 +45,60 @@ public class ObjectDecoderInputStream extends InputStream implements
private final ClassLoader classLoader; private final ClassLoader classLoader;
private final int maxObjectSize; private final int maxObjectSize;
/**
* Creates a new {@link ObjectInput}.
*
* @param in
* the {@link InputStream} where the serialized form will be
* read from
*/
public ObjectDecoderInputStream(InputStream in) { public ObjectDecoderInputStream(InputStream in) {
this(in, Thread.currentThread().getContextClassLoader()); this(in, null);
} }
/**
* Creates a new {@link ObjectInput}.
*
* @param in
* the {@link InputStream} where the serialized form will be
* read from
* @param classLoader
* the {@link ClassLoader} which will load the class of the
* serialized object
*/
public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader) { public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader) {
this(in, classLoader, 1048576); this(in, classLoader, 1048576);
} }
/**
* Creates a new {@link ObjectInput}.
*
* @param in
* the {@link InputStream} where the serialized form will be
* read from
* @param maxObjectSize
* the maximum byte length of the serialized object. if the length
* of the received object is greater than this value,
* a {@link StreamCorruptedException} will be raised.
*/
public ObjectDecoderInputStream(InputStream in, int maxObjectSize) { public ObjectDecoderInputStream(InputStream in, int maxObjectSize) {
this(in, Thread.currentThread().getContextClassLoader(), maxObjectSize); this(in, null, maxObjectSize);
} }
/**
* Creates a new {@link ObjectInput}.
*
* @param in
* the {@link InputStream} where the serialized form will be
* read from
* @param classLoader
* the {@link ClassLoader} which will load the class of the
* serialized object
* @param maxObjectSize
* the maximum byte length of the serialized object. if the length
* of the received object is greater than this value,
* a {@link StreamCorruptedException} will be raised.
*/
public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader, int maxObjectSize) { public ObjectDecoderInputStream(InputStream in, ClassLoader classLoader, int maxObjectSize) {
if (in == null) { if (in == null) {
throw new NullPointerException("in"); throw new NullPointerException("in");

View File

@ -25,6 +25,7 @@ package org.jboss.netty.handler.codec.serialization;
import static org.jboss.netty.buffer.ChannelBuffers.*; import static org.jboss.netty.buffer.ChannelBuffers.*;
import static org.jboss.netty.channel.Channels.*; import static org.jboss.netty.channel.Channels.*;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffer;
@ -36,11 +37,22 @@ import org.jboss.netty.channel.ChannelPipelineCoverage;
import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.MessageEvent;
/** /**
* An encoder which serializes a Java object into a {@link ChannelBuffer}.
* <p>
* Please note that the serialized form this encoder produces is not
* compatible with the standard {@link ObjectInputStream}. Please use
* {@link ObjectDecoder} or {@link ObjectDecoderInputStream} to ensure the
* interoperability with this encoder.
* <p>
* Unless there's a requirement for the interoperability with the standard
* object streams, it is recommended to use {@link ObjectEncoder} and
* {@link ObjectDecoder} rather than {@link CompatibleObjectEncoder} and
* {@link CompatibleObjectDecoder}.
*
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
* *
* @version $Rev:231 $, $Date:2008-06-12 16:44:50 +0900 (, 12 6월 2008) $ * @version $Rev:231 $, $Date:2008-06-12 16:44:50 +0900 (, 12 6월 2008) $
*
*/ */
@ChannelPipelineCoverage("all") @ChannelPipelineCoverage("all")
public class ObjectEncoder implements ChannelDownstreamHandler { public class ObjectEncoder implements ChannelDownstreamHandler {
@ -48,10 +60,24 @@ public class ObjectEncoder implements ChannelDownstreamHandler {
private final int estimatedLength; private final int estimatedLength;
/**
* Creates a new encoder with the estimated length of 512 bytes.
*/
public ObjectEncoder() { public ObjectEncoder() {
this(512); this(512);
} }
/**
* Creates a new encoder.
*
* @param estimatedLength
* the estimated byte length of the serialized form of an object.
* If the length of the serialized form exceeds this value, the
* internal buffer will be expanded automatically at the cost of
* memory bandwidth. If this value is too big, it will also waste
* memory bandwidth. To avoid unnecessary memory copy or allocation
* cost, please specify the properly estimated value.
*/
public ObjectEncoder(int estimatedLength) { public ObjectEncoder(int estimatedLength) {
if (estimatedLength < 0) { if (estimatedLength < 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(

View File

@ -33,6 +33,9 @@ import org.jboss.netty.buffer.ChannelBufferOutputStream;
import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.buffer.ChannelBuffers;
/** /**
* An {@link ObjectOutput} which is interoperable with {@link ObjectDecoder}
* and {@link ObjectDecoderInputStream}.
*
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)
* *
@ -45,6 +48,33 @@ public class ObjectEncoderOutputStream extends OutputStream implements
private final DataOutputStream out; private final DataOutputStream out;
private final int estimatedLength; private final int estimatedLength;
/**
* Creates a new {@link ObjectOutput} with the estimated length of 512
* bytes.
*
* @param out
* the {@link OutputStream} where the serialized form will be
* written out
*/
public ObjectEncoderOutputStream(OutputStream out) {
this(out, 512);
}
/**
* Creates a new {@link ObjectOutput}.
*
* @param out
* the {@link OutputStream} where the serialized form will be
* written out
*
* @param estimatedLength
* the estimated byte length of the serialized form of an object.
* If the length of the serialized form exceeds this value, the
* internal buffer will be expanded automatically at the cost of
* memory bandwidth. If this value is too big, it will also waste
* memory bandwidth. To avoid unnecessary memory copy or allocation
* cost, please specify the properly estimated value.
*/
public ObjectEncoderOutputStream(OutputStream out, int estimatedLength) { public ObjectEncoderOutputStream(OutputStream out, int estimatedLength) {
if (out == null) { if (out == null) {
throw new NullPointerException("out"); throw new NullPointerException("out");

View File

@ -22,7 +22,7 @@
*/ */
/** /**
* Encoder and decoder which transform a {@link String} into a * Encoder and decoder which transform a {@link java.lang.String} into a
* {@link org.jboss.netty.buffer.ChannelBuffer} and vice versa. * {@link org.jboss.netty.buffer.ChannelBuffer} and vice versa.
*/ */
package org.jboss.netty.handler.codec.string; package org.jboss.netty.handler.codec.string;

View File

@ -35,10 +35,10 @@ import javax.net.ssl.SSLEngine;
* <p> * <p>
* The reason why {@link SslHandler} requires a buffer pool is because the * The reason why {@link SslHandler} requires a buffer pool is because the
* current {@link SSLEngine} implementation always requires a 17KiB buffer for * current {@link SSLEngine} implementation always requires a 17KiB buffer for
* the 'wrap' and 'unwrap' operation. In most cases, the size of the required * every 'wrap' and 'unwrap' operation. In most cases, the actual size of the
* buffer is much smaller than that, and therefore allocating a 17KiB buffer * required buffer is much smaller than that, and therefore allocating a 17KiB
* for every 'wrap' and 'unwrap' operation wastes a lot of memory bandwidth, * buffer for every 'wrap' and 'unwrap' operation wastes a lot of memory
* resulting in the application performance degradation. * bandwidth, resulting in the application performance degradation.
* *
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com) * @author Trustin Lee (tlee@redhat.com)