[#441] Provide a better way to handle decoder failures

* Add DecodeResult that represents the result of decoding a message
* Add HttpObject which HttpMessage and HttpChunk extend.
** HttpObject has a property 'decodeResult'
This commit is contained in:
Trustin Lee 2012-09-28 13:48:17 +09:00
parent 817309c7c8
commit adebda1560
8 changed files with 156 additions and 5 deletions

View File

@ -20,7 +20,7 @@ import io.netty.buffer.ByteBuf;
/** /**
* The default {@link HttpChunk} implementation. * The default {@link HttpChunk} implementation.
*/ */
public class DefaultHttpChunk implements HttpChunk { public class DefaultHttpChunk extends DefaultHttpObject implements HttpChunk {
private ByteBuf content; private ByteBuf content;
private boolean last; private boolean last;

View File

@ -25,7 +25,7 @@ import java.util.Set;
/** /**
* The default {@link HttpChunkTrailer} implementation. * The default {@link HttpChunkTrailer} implementation.
*/ */
public class DefaultHttpChunkTrailer implements HttpChunkTrailer { public class DefaultHttpChunkTrailer extends DefaultHttpObject implements HttpChunkTrailer {
private final HttpHeaders headers = new HttpHeaders() { private final HttpHeaders headers = new HttpHeaders() {
@Override @Override

View File

@ -26,7 +26,7 @@ import java.util.Set;
/** /**
* The default {@link HttpMessage} implementation. * The default {@link HttpMessage} implementation.
*/ */
public class DefaultHttpMessage implements HttpMessage { public class DefaultHttpMessage extends DefaultHttpObject implements HttpMessage {
private final HttpHeaders headers = new HttpHeaders(); private final HttpHeaders headers = new HttpHeaders();
private HttpVersion version; private HttpVersion version;

View File

@ -0,0 +1,40 @@
/*
* Copyright 2012 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.http;
import io.netty.handler.codec.DecodeResult;
public class DefaultHttpObject implements HttpObject {
private DecodeResult decodeResult = DecodeResult.SUCCESS;
protected DefaultHttpObject() {
// Disallow direct instantiation
}
@Override
public DecodeResult getDecodeResult() {
return decodeResult;
}
@Override
public void setDecodeResult(DecodeResult result) {
if (result == null) {
throw new NullPointerException("result");
}
decodeResult = result;
}
}

View File

@ -18,6 +18,7 @@ package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.DecodeResult;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -33,7 +34,7 @@ import java.util.Set;
* {@link ChannelPipeline}. * {@link ChannelPipeline}.
* @apiviz.landmark * @apiviz.landmark
*/ */
public interface HttpChunk { public interface HttpChunk extends HttpObject {
/** /**
* The 'end of content' marker in chunked encoding. * The 'end of content' marker in chunked encoding.
@ -103,6 +104,16 @@ public interface HttpChunk {
public void setHeader(String name, Iterable<?> values) { public void setHeader(String name, Iterable<?> values) {
throw new IllegalStateException("read-only"); throw new IllegalStateException("read-only");
} }
@Override
public DecodeResult getDecodeResult() {
return DecodeResult.SUCCESS;
}
@Override
public void setDecodeResult(DecodeResult result) {
throw new IllegalStateException("read-only");
}
}; };
/** /**

View File

@ -34,7 +34,7 @@ import java.util.Set;
* @apiviz.landmark * @apiviz.landmark
* @apiviz.has io.netty.handler.codec.http.HttpChunk oneway - - is followed by * @apiviz.has io.netty.handler.codec.http.HttpChunk oneway - - is followed by
*/ */
public interface HttpMessage { public interface HttpMessage extends HttpObject {
/** /**
* Returns the value of a header with the specified name. If there are * Returns the value of a header with the specified name. If there are

View File

@ -0,0 +1,23 @@
/*
* Copyright 2012 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.http;
import io.netty.handler.codec.DecodeResult;
public interface HttpObject {
DecodeResult getDecodeResult();
void setDecodeResult(DecodeResult result);
}

View File

@ -0,0 +1,77 @@
/*
* Copyright 2012 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;
public class DecodeResult {
public static final DecodeResult SUCCESS = new DecodeResult(false, null);
public static DecodeResult failure(Throwable cause) {
if (cause == null) {
throw new NullPointerException("cause");
}
return new DecodeResult(false, cause);
}
public static DecodeResult partialFailure(Throwable cause) {
if (cause == null) {
throw new NullPointerException("cause");
}
return new DecodeResult(true, cause);
}
private final boolean partial;
private final Throwable cause;
protected DecodeResult(boolean partial, Throwable cause) {
if (partial && cause == null) {
throw new IllegalArgumentException("successful result cannot be partial.");
}
this.partial = partial;
this.cause = cause;
}
public boolean isSuccess() {
return cause == null;
}
public boolean isPartial() {
return partial;
}
public Throwable cause() {
return cause;
}
@Override
public String toString() {
if (isSuccess()) {
return "success";
}
String cause = cause().toString();
StringBuilder buf = new StringBuilder(cause.length() + 17);
if (isPartial()) {
buf.append("partial_");
}
buf.append("failure(");
buf.append(cause);
buf.append(')');
return buf.toString();
}
}