View Javadoc

1   /*
2    *  Copyright 2006 Simon Raess
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
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 			// TODO: proper exception type
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 }