1 package com.foxinmy.weixin4j.http;
2
3 import java.io.Serializable;
4 import java.nio.charset.Charset;
5 import java.nio.charset.UnsupportedCharsetException;
6 import java.util.ArrayList;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9 import java.util.Locale;
10 import java.util.Map;
11
12 import com.foxinmy.weixin4j.util.CharArrayBuffer;
13 import com.foxinmy.weixin4j.util.Consts;
14 import com.foxinmy.weixin4j.util.NameValue;
15 import com.foxinmy.weixin4j.util.StringUtil;
16
17
18
19
20
21
22
23
24
25
26 public final class ContentType implements Serializable {
27
28 private static final long serialVersionUID = 1544245878894784980L;
29
30 private final MimeType mimeType;
31 private final Charset charset;
32 private final NameValue[] params;
33 private static final Charset DEFAULT_CHARSET = Consts.UTF_8;
34
35 public static final ContentType APPLICATION_JSON;
36 public static final ContentType APPLICATION_FORM_URLENCODED;
37 public static final ContentType MULTIPART_FORM_DATA;
38 public static final ContentType DEFAULT_BINARY;
39 public static final ContentType DEFAULT_TEXT;
40
41 static {
42 APPLICATION_JSON = new ContentType(MimeType.APPLICATION_JSON);
43 APPLICATION_FORM_URLENCODED = new ContentType(
44 MimeType.APPLICATION_FORM_URLENCODED);
45 MULTIPART_FORM_DATA = new ContentType(MimeType.MULTIPART_FORM_DATA);
46 DEFAULT_BINARY = new ContentType(MimeType.APPLICATION_OCTET_STREAM);
47 DEFAULT_TEXT = new ContentType(MimeType.TEXT_PLAIN);
48 }
49
50 ContentType(final MimeType mimeType) {
51 this(mimeType, DEFAULT_CHARSET);
52 }
53
54 ContentType(final MimeType mimeType, final Charset charset) {
55 this(mimeType, charset, null);
56 }
57
58 ContentType(final MimeType mimeType, final Charset charset,
59 final NameValue[] params) {
60 this.mimeType = mimeType;
61 this.charset = charset;
62 this.params = params;
63 }
64
65 public MimeType getMimeType() {
66 return this.mimeType;
67 }
68
69 public Charset getCharset() {
70 return this.charset;
71 }
72
73
74
75
76 public String getParameter(final String name) {
77 if (this.params == null) {
78 return null;
79 }
80 for (final NameValue param : this.params) {
81 if (param.getName().equalsIgnoreCase(name)) {
82 return param.getValue();
83 }
84 }
85 return null;
86 }
87
88
89
90
91
92 @Override
93 public String toString() {
94 final CharArrayBuffer buf = new CharArrayBuffer(64);
95 buf.append(this.mimeType);
96 if (this.params != null) {
97 buf.append("; ");
98 HeaderValueFormatter.INSTANCE.formatParameters(buf,
99 this.params, false);
100 } else if (this.charset != null) {
101 buf.append("; charset=");
102 buf.append(this.charset.name());
103 }
104 return buf.toString();
105 }
106
107 public static String toString(List<ContentType> contentTypes) {
108 if (contentTypes == null || contentTypes.isEmpty()) {
109 return null;
110 }
111 StringBuilder buf = new StringBuilder();
112 for (ContentType contentType : contentTypes) {
113 buf.append(contentType.toString()).append(",");
114 }
115 return buf.delete(buf.length() - 1, buf.length()).toString();
116 }
117
118 private static boolean valid(final String s) {
119 for (int i = 0; i < s.length(); i++) {
120 char ch = s.charAt(i);
121 if (ch == '"' || ch == ',' || ch == ';') {
122 return false;
123 }
124 }
125 return true;
126 }
127
128 public static ContentType create(final MimeType mimeType,
129 final Charset charset) {
130 if (mimeType == null) {
131 throw new IllegalArgumentException("MIME type may not be null");
132 }
133 return new ContentType(mimeType, charset);
134 }
135
136 public static ContentType create(final String mimeType) {
137 return create(MimeType.valueOf(mimeType), (Charset) null);
138 }
139
140 public static ContentType create(final String mimeType, final String charset)
141 throws UnsupportedCharsetException {
142 return create(
143 mimeType,
144 (charset != null && charset.length() > 0) ? Charset
145 .forName(charset) : null);
146 }
147
148 public static ContentType create(final String mimeType,
149 final Charset charset) {
150 if (mimeType == null) {
151 throw new IllegalArgumentException("MIME type may not be null");
152 }
153 String type = mimeType.trim().toLowerCase(Locale.US);
154 if (type.length() == 0) {
155 throw new IllegalArgumentException("MIME type may not be empty");
156 }
157 if (!valid(type)) {
158 throw new IllegalArgumentException(
159 "MIME type may not contain reserved characters");
160 }
161 return new ContentType(MimeType.valueOf(type), charset);
162 }
163
164 private static ContentType create(final MimeType mimeType,
165 final NameValue[] params, final boolean strict) {
166 Charset charset = null;
167 for (final NameValue param : params) {
168 if (param.getName().equalsIgnoreCase("charset")) {
169 final String s = param.getValue();
170 if (StringUtil.isNotBlank(s)) {
171 try {
172 charset = Charset.forName(s);
173 } catch (final UnsupportedCharsetException ex) {
174 if (strict) {
175 throw ex;
176 }
177 }
178 }
179 break;
180 }
181 }
182 return new ContentType(mimeType, charset, params != null
183 && params.length > 0 ? params : null);
184 }
185
186
187
188
189
190
191
192
193
194
195
196 public static ContentType create(final String mimeType,
197 final NameValue... params) throws UnsupportedCharsetException {
198 final String type = mimeType.toLowerCase(Locale.ROOT);
199 if (!valid(type)) {
200 throw new IllegalArgumentException(
201 "MIME type may not contain reserved characters");
202 }
203 return create(MimeType.valueOf(mimeType), params, true);
204 }
205
206
207
208
209
210
211
212
213 public ContentType withParameters(final NameValue... params)
214 throws UnsupportedCharsetException {
215 if (params.length == 0) {
216 return this;
217 }
218 final Map<String, String> paramMap = new LinkedHashMap<String, String>();
219 if (this.params != null) {
220 for (final NameValue param : this.params) {
221 paramMap.put(param.getName(), param.getValue());
222 }
223 }
224 for (final NameValue param : params) {
225 paramMap.put(param.getName(), param.getValue());
226 }
227 final List<NameValue> newParams = new ArrayList<NameValue>(
228 paramMap.size() + 1);
229 if (this.charset != null && !paramMap.containsKey("charset")) {
230 newParams.add(new NameValue("charset", this.charset.name()));
231 }
232 for (final Map.Entry<String, String> entry : paramMap.entrySet()) {
233 newParams.add(new NameValue(entry.getKey(), entry.getValue()));
234 }
235 return create(this.getMimeType(),
236 newParams.toArray(new NameValue[newParams.size()]), true);
237 }
238 }