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.util.List;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19
20
21
22
23
24
25
26
27
28 public class ReadIcapHeaderState extends State<Object> {
29
30 public ReadIcapHeaderState(String name) {
31 super(name);
32 }
33
34 @Override
35 public void onEntry(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder) throws DecodingException {
36 if(icapMessageDecoder.message == null) {
37 throw new IllegalArgumentException("This state requires a valid IcapMessage instance");
38 }
39 }
40
41 @Override
42 public StateReturnValue execute(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder) throws DecodingException {
43 List<String[]> headerList = IcapDecoderUtil.readHeaders(buffer,icapMessageDecoder.maxIcapHeaderSize);
44 icapMessageDecoder.message.clearHeaders();
45 for(String[] header : headerList) {
46 icapMessageDecoder.message.addHeader(header[0],header[1]);
47 }
48 boolean isRequest = icapMessageDecoder.message instanceof IcapRequest;
49 boolean isOptionsRequest = isRequest && ((IcapRequest)icapMessageDecoder.message).getMethod().equals(IcapMethod.OPTIONS);
50
51 validateMandatoryMessageHeaders(icapMessageDecoder.message,icapMessageDecoder.isDecodingResponse(),isOptionsRequest);
52
53 Encapsulated encapsulated = null;
54 String headerValue = icapMessageDecoder.message.getHeader(IcapHeaders.Names.ENCAPSULATED);
55 if(headerValue != null) {
56 encapsulated = new Encapsulated(icapMessageDecoder.message.getHeader(IcapHeaders.Names.ENCAPSULATED));
57 icapMessageDecoder.message.setEncapsulatedHeader(encapsulated);
58 }
59 if(isOptionsRequest) {
60 return StateReturnValue.createRelevantResult(icapMessageDecoder.message);
61 } else if(encapsulated != null && !encapsulated.containsEntry(IcapMessageElementEnum.REQHDR) & !encapsulated.containsEntry(IcapMessageElementEnum.RESHDR)) {
62 return StateReturnValue.createRelevantResult(icapMessageDecoder.message);
63 }
64 return StateReturnValue.createIrrelevantResult();
65 }
66
67 @Override
68 public StateEnum onExit(ChannelBuffer buffer, IcapMessageDecoder icapMessageDecoder, Object decisionInformation) throws DecodingException {
69 IcapMessage message = icapMessageDecoder.message;
70 Encapsulated encapsulated = message.getEncapsulatedHeader();
71 if(message instanceof IcapRequest && ((IcapRequest)message).getMethod().equals(IcapMethod.OPTIONS)) {
72 if(encapsulated != null && encapsulated.containsEntry(IcapMessageElementEnum.OPTBODY)) {
73 return StateEnum.READ_CHUNK_SIZE_STATE;
74 } else {
75 return null;
76 }
77 } else {
78 IcapMessageElementEnum entry = encapsulated.getNextEntry();
79 if(entry != null) {
80 if(entry.equals(IcapMessageElementEnum.REQHDR)) {
81 return StateEnum.READ_HTTP_REQUEST_INITIAL_AND_HEADERS;
82 } else if(entry.equals(IcapMessageElementEnum.RESHDR)) {
83 return StateEnum.READ_HTTP_RESPONSE_INITIAL_AND_HEADERS;
84 } else if(entry.equals(IcapMessageElementEnum.REQBODY)) {
85 return StateEnum.READ_CHUNK_SIZE_STATE;
86 } else if(entry.equals(IcapMessageElementEnum.RESBODY)) {
87 return StateEnum.READ_CHUNK_SIZE_STATE;
88 }
89 }
90 }
91 return null;
92 }
93
94 private void validateMandatoryMessageHeaders(IcapMessage message, boolean isDecodingResponse, boolean isDecodingOptionsRequest) {
95 if(!isDecodingResponse) {
96 if(!message.containsHeader(IcapHeaders.Names.HOST)) {
97 throw new IcapDecodingError("Mandatory ICAP message header [Host] is missing");
98 }
99 }
100 if(!isDecodingOptionsRequest) {
101 if(!message.containsHeader(IcapHeaders.Names.ENCAPSULATED)) {
102 throw new IcapDecodingError("Mandatory ICAP message header [Encapsulated] is missing");
103 }
104 }
105 }
106
107 }