1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.mimo.netty.handler.codec.icap;
15
16 import java.io.UnsupportedEncodingException;
17 import java.util.Map;
18
19 import org.jboss.netty.buffer.ChannelBuffer;
20 import org.jboss.netty.buffer.ChannelBuffers;
21 import org.jboss.netty.channel.Channel;
22 import org.jboss.netty.channel.ChannelHandlerContext;
23 import org.jboss.netty.handler.codec.http.HttpRequest;
24 import org.jboss.netty.handler.codec.http.HttpResponse;
25 import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
26 import org.jboss.netty.logging.InternalLogger;
27 import org.jboss.netty.logging.InternalLoggerFactory;
28
29
30
31
32
33
34
35
36
37 public abstract class IcapMessageEncoder extends OneToOneEncoder {
38
39 private final InternalLogger LOG;
40
41 public IcapMessageEncoder() {
42 LOG = InternalLoggerFactory.getInstance(getClass());
43 }
44
45 @Override
46 protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
47 LOG.debug("Encoding [" + msg.getClass().getName() + "]");
48 if(msg instanceof IcapMessage) {
49 IcapMessage message = (IcapMessage)msg;
50 ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(channel.getConfig().getBufferFactory());
51 encodeInitialLine(buffer,message);
52 encodeHeaders(buffer,message);
53 ChannelBuffer httpRequestBuffer = encodeHttpRequestHeader(message.getHttpRequest());
54 ChannelBuffer httpResponseBuffer = encodeHttpResponseHeader(message.getHttpResponse());
55 int index = 0;
56 Encapsulated encapsulated = new Encapsulated();
57 if(httpRequestBuffer.readableBytes() > 0) {
58 encapsulated.addEntry(IcapMessageElementEnum.REQHDR,index);
59 httpRequestBuffer.writeBytes(IcapCodecUtil.CRLF);
60 index += httpRequestBuffer.readableBytes();
61 }
62 if(httpResponseBuffer.readableBytes() > 0) {
63 encapsulated.addEntry(IcapMessageElementEnum.RESHDR,index);
64 httpResponseBuffer.writeBytes(IcapCodecUtil.CRLF);
65 index += httpResponseBuffer.readableBytes();
66 }
67 if(message.getBodyType() != null) {
68 encapsulated.addEntry(message.getBodyType(),index);
69 } else {
70 encapsulated.addEntry(IcapMessageElementEnum.NULLBODY,index);
71 }
72 encapsulated.encode(buffer);
73 buffer.writeBytes(httpRequestBuffer);
74 buffer.writeBytes(httpResponseBuffer);
75 return buffer;
76 } else if(msg instanceof IcapChunk) {
77 ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(channel.getConfig().getBufferFactory());
78 IcapChunk chunk = (IcapChunk)msg;
79 if(chunk.isLast()) {
80 if(chunk.isEarlyTerminated()) {
81 buffer.writeBytes(IcapCodecUtil.NATIVE_IEOF_SEQUENCE);
82 buffer.writeBytes(IcapCodecUtil.CRLF);
83 buffer.writeBytes(IcapCodecUtil.CRLF);
84 } else if(msg instanceof IcapChunkTrailer) {
85 buffer.writeByte((byte) '0');
86 buffer.writeBytes(IcapCodecUtil.CRLF);
87 encodeTrailingHeaders(buffer,(IcapChunkTrailer)msg);
88 buffer.writeBytes(IcapCodecUtil.CRLF);
89 } else {
90 buffer.writeByte((byte) '0');
91 buffer.writeBytes(IcapCodecUtil.CRLF);
92 buffer.writeBytes(IcapCodecUtil.CRLF);
93 }
94 } else {
95 ChannelBuffer chunkBuffer = chunk.getContent();
96 int contentLength = chunkBuffer.readableBytes();
97 buffer.writeBytes(Integer.toHexString(contentLength).getBytes(IcapCodecUtil.ASCII_CHARSET));
98 buffer.writeBytes(IcapCodecUtil.CRLF);
99 buffer.writeBytes(chunkBuffer);
100 buffer.writeBytes(IcapCodecUtil.CRLF);
101 }
102 return buffer;
103 }
104 return null;
105 }
106
107 protected abstract int encodeInitialLine(ChannelBuffer buffer, IcapMessage message) throws Exception;
108
109 private ChannelBuffer encodeHttpRequestHeader(HttpRequest httpRequest) throws UnsupportedEncodingException {
110 ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
111 if(httpRequest != null) {
112 buffer.writeBytes(httpRequest.getMethod().toString().getBytes(IcapCodecUtil.ASCII_CHARSET));
113 buffer.writeByte(IcapCodecUtil.SPACE);
114 buffer.writeBytes(httpRequest.getUri().getBytes(IcapCodecUtil.ASCII_CHARSET));
115 buffer.writeByte(IcapCodecUtil.SPACE);
116 buffer.writeBytes(httpRequest.getProtocolVersion().toString().getBytes(IcapCodecUtil.ASCII_CHARSET));
117 buffer.writeBytes(IcapCodecUtil.CRLF);
118 for (Map.Entry<String, String> h: httpRequest.getHeaders()) {
119 encodeHeader(buffer, h.getKey(), h.getValue());
120 }
121 }
122 return buffer;
123 }
124
125 private ChannelBuffer encodeHttpResponseHeader(HttpResponse httpResponse) throws UnsupportedEncodingException {
126 ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
127 if(httpResponse != null) {
128 buffer.writeBytes(httpResponse.getProtocolVersion().toString().getBytes(IcapCodecUtil.ASCII_CHARSET));
129 buffer.writeByte(IcapCodecUtil.SPACE);
130 buffer.writeBytes(httpResponse.getStatus().toString().getBytes(IcapCodecUtil.ASCII_CHARSET));
131 buffer.writeBytes(IcapCodecUtil.CRLF);
132 for (Map.Entry<String, String> h: httpResponse.getHeaders()) {
133 encodeHeader(buffer, h.getKey(), h.getValue());
134 }
135 }
136 return buffer;
137 }
138
139 private int encodeTrailingHeaders(ChannelBuffer buffer, IcapChunkTrailer chunkTrailer) {
140 int index = buffer.readableBytes();
141 for (Map.Entry<String, String> h: chunkTrailer.getHeaders()) {
142 encodeHeader(buffer, h.getKey(), h.getValue());
143 }
144 return buffer.readableBytes() - index;
145 }
146
147 private int encodeHeaders(ChannelBuffer buffer, IcapMessage message) {
148 int index = buffer.readableBytes();
149 for (Map.Entry<String, String> h: message.getHeaders()) {
150 encodeHeader(buffer, h.getKey(), h.getValue());
151 }
152 return buffer.readableBytes() - index;
153 }
154
155 private void encodeHeader(ChannelBuffer buf, String header, String value) {
156 buf.writeBytes(header.getBytes(IcapCodecUtil.ASCII_CHARSET));
157 buf.writeByte(IcapCodecUtil.COLON);
158 buf.writeByte(IcapCodecUtil.SPACE);
159 buf.writeBytes(value.getBytes(IcapCodecUtil.ASCII_CHARSET));
160 buf.writeBytes(IcapCodecUtil.CRLF);
161 }
162 }