1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.beep4j.internal.message;
17
18 import java.io.StringReader;
19 import java.nio.ByteBuffer;
20 import java.nio.CharBuffer;
21 import java.nio.charset.Charset;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.Map;
26
27 import net.sf.beep4j.Message;
28 import net.sf.beep4j.internal.message.contenttype.ContentTypeParser;
29 import net.sf.beep4j.internal.message.contenttype.ParseException;
30
31 public class MessageHeader {
32
33 private static final String EOL = "\r\n";
34
35 private final Map<String,String> header;
36
37 private ByteBuffer buffer;
38
39 private String type = "application";
40
41 private String subtype = "octet-stream";
42
43 private String charset = "UTF-8";
44
45 private String transferEncoding = "binary";
46
47 public MessageHeader() {
48 this.header = new HashMap<String,String>();
49 }
50
51 public void addHeader(String name, String value) {
52 if (Message.CONTENT_TYPE.equalsIgnoreCase(name)) {
53 parseContentType(value.trim());
54 } else if (Message.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(name)) {
55 parseContentTransferEncoding(value);
56 } else {
57 header.put(name, value.trim());
58 }
59 }
60
61 public void setContentType(String type, String subtype) {
62 this.type = type.toLowerCase();
63 this.subtype = subtype.toLowerCase();
64 }
65
66 public String getContentType() {
67 return type + "/" + subtype;
68 }
69
70 public void setCharset(String name) {
71 this.charset = name;
72 }
73
74 public String getCharset() {
75 return charset;
76 }
77
78 public void setTransferEncoding(String transferEncoding) {
79 this.transferEncoding = transferEncoding.toLowerCase();
80 }
81
82 public String getTransferEncoding() {
83 return transferEncoding;
84 }
85
86 private void parseContentType(String value) {
87 ContentTypeParser parser = new ContentTypeParser(new StringReader(value));
88
89 try {
90 parser.parseAll();
91 this.type = parser.getType().toLowerCase();
92 this.subtype = parser.getSubType().toLowerCase();
93 this.charset = (String) parser.getParameters().get("charset");
94
95 if (this.charset == null && "application/beep+xml".equals(getContentType())) {
96 this.charset = "UTF-8";
97 } else if (this.charset == null && "text".equals(type)) {
98 this.charset = "US-ASCII";
99 }
100 } catch (ParseException e) {
101
102 throw new IllegalArgumentException(e);
103 }
104 }
105
106 private void parseContentTransferEncoding(String value) {
107 value = value.toLowerCase();
108 if (Message.BINARY_TRANSFER_ENCODING.equals(value)) {
109 transferEncoding = value;
110 } else if (Message.BASE64_TRANSFER_ENCODING.equals(value)) {
111 transferEncoding = value;
112 } else {
113 throw new IllegalArgumentException("unknown or unsupported transfer encoding: '"
114 + value + "'");
115 }
116 }
117
118 public Iterator<String> getHeaderNames() {
119 return Collections.unmodifiableCollection(header.keySet()).iterator();
120 }
121
122 public String getHeader(String name) {
123 return header.get(name);
124 }
125
126 public synchronized ByteBuffer asByteBuffer() {
127 if (buffer == null) {
128 StringBuilder builder = new StringBuilder();
129
130 builder.append("Content-Type: ");
131 builder.append(getContentType());
132 if (!"UTF-8".equals(charset)) {
133 builder.append("; charset=");
134 builder.append(charset);
135 }
136 builder.append(EOL);
137
138 if (!Message.BINARY_TRANSFER_ENCODING.equals(getTransferEncoding())) {
139 builder.append("Content-Transfer-Encoding: ");
140 builder.append(getTransferEncoding());
141 builder.append(EOL);
142 }
143
144 Iterator<String> names = getHeaderNames();
145 while (names.hasNext()) {
146 String name = names.next();
147 String value = header.get(name);
148 builder.append(name);
149 builder.append(": ");
150 builder.append(value);
151 builder.append(EOL);
152 }
153 builder.append(EOL);
154
155 CharBuffer chars = CharBuffer.wrap(builder);
156 buffer = Charset.forName("US-ASCII").encode(chars);
157 }
158
159 return buffer.asReadOnlyBuffer();
160 }
161
162 }