View Javadoc
1   package com.foxinmy.weixin4j.http;
2   
3   import java.io.Serializable;
4   import java.util.ArrayList;
5   import java.util.List;
6   import java.util.Locale;
7   
8   import com.foxinmy.weixin4j.util.StringUtil;
9   
10  /**
11   * MIME type
12   * 
13   * @className MimeType
14   * @author jinyu
15   * @date Jul 20, 2016
16   * @since JDK 1.6
17   */
18  public class MimeType implements Serializable {
19  
20  	private static final long serialVersionUID = 4430596628682058362L;
21  
22  	private static final String WILDCARD_TYPE = "*";
23  
24  	private final String type;
25  	private final String subType;
26  
27  	public static final MimeType APPLICATION_FORM_URLENCODED;
28  	public static final MimeType APPLICATION_JSON;
29  	public static final MimeType APPLICATION_OCTET_STREAM;
30  	public static final MimeType APPLICATION_XML;
31  	public static final MimeType MULTIPART_FORM_DATA;
32  	public static final MimeType TEXT_HTML;
33  	public static final MimeType TEXT_PLAIN;
34  	public static final MimeType IMAGE_JPG;
35  	public static final MimeType AUDIO_MP3;
36  	public static final MimeType VIDEO_MPEG4;
37  	public static final MimeType TEXT_XML;
38  	public static final MimeType TEXT_JSON;
39  
40  	public static final List<MimeType> STREAM_MIMETYPES;
41  
42  	static {
43  		APPLICATION_FORM_URLENCODED = valueOf("application/x-www-form-urlencoded");
44  		APPLICATION_JSON = valueOf("application/json");
45  		APPLICATION_OCTET_STREAM = valueOf("application/octet-stream");
46  		APPLICATION_XML = valueOf("application/xml");
47  		MULTIPART_FORM_DATA = valueOf("multipart/form-data");
48  		TEXT_HTML = valueOf("text/html");
49  		TEXT_PLAIN = valueOf("text/plain");
50  		IMAGE_JPG = valueOf("image/jpg");
51  		AUDIO_MP3 = valueOf("audio/mp3");
52  		VIDEO_MPEG4 = valueOf("video/mpeg4");
53  		TEXT_XML = valueOf("text/xml");
54  		TEXT_JSON = valueOf("text/json");
55  
56  		STREAM_MIMETYPES = new ArrayList<MimeType>(4);
57  		STREAM_MIMETYPES.add(APPLICATION_OCTET_STREAM);
58  		STREAM_MIMETYPES.add(valueOf("image/*"));
59  		STREAM_MIMETYPES.add(valueOf("audio/*"));
60  		STREAM_MIMETYPES.add(valueOf("video/*"));
61  		STREAM_MIMETYPES.add(valueOf("application/zip"));
62  		STREAM_MIMETYPES.add(valueOf("application/x-gzip"));
63  	}
64  
65  	public MimeType(String type) {
66  		this(type, WILDCARD_TYPE);
67  	}
68  
69  	public MimeType(String type, String subType) {
70  		this.type = type.toLowerCase(Locale.ENGLISH);
71  		this.subType = subType.toLowerCase(Locale.ENGLISH);
72  	}
73  
74  	public String getType() {
75  		return type;
76  	}
77  
78  	public String getSubType() {
79  		return subType;
80  	}
81  
82  	public boolean isWildcardType() {
83  		return WILDCARD_TYPE.equals(getType());
84  	}
85  
86  	public boolean isWildcardSubtype() {
87  		return WILDCARD_TYPE.equals(getSubType())
88  				|| getSubType().startsWith("*+");
89  	}
90  
91  	public static MimeType valueOf(String value) {
92  		if (StringUtil.isBlank(value)) {
93  			return null;
94  		}
95  		String mimeType = StringUtil.tokenizeToStringArray(value, ";")[0]
96  				.trim().toLowerCase(Locale.ENGLISH);
97  		if (WILDCARD_TYPE.equals(mimeType)) {
98  			mimeType = "*/*";
99  		}
100 		int subIndex = mimeType.indexOf('/');
101 		if (subIndex == -1) {
102 			throw new IllegalArgumentException(mimeType
103 					+ ":does not contain '/'");
104 		}
105 		if (subIndex == mimeType.length() - 1) {
106 			throw new IllegalArgumentException(mimeType
107 					+ ":does not contain subtype after '/'");
108 		}
109 		String type = mimeType.substring(0, subIndex);
110 		String subType = mimeType.substring(subIndex + 1, mimeType.length());
111 		if (WILDCARD_TYPE.equals(type) && !WILDCARD_TYPE.equals(subType)) {
112 			throw new IllegalArgumentException(mimeType
113 					+ ":wildcard type is legal only in '*/*' (all mime types)");
114 		}
115 		return new MimeType(type, subType);
116 	}
117 
118 	/**
119 	 * reference of Spring Web
120 	 */
121 	public boolean includes(MimeType other) {
122 		if (other == null) {
123 			return false;
124 		}
125 		if (this.isWildcardType()) {
126 			// */* includes anything
127 			return true;
128 		} else if (getType().equals(other.getType())) {
129 			if (getSubType().equals(other.getSubType())) {
130 				return true;
131 			}
132 			if (this.isWildcardSubtype()) {
133 				// wildcard with suffix, e.g. application/*+xml
134 				int thisPlusIdx = getSubType().indexOf('+');
135 				if (thisPlusIdx == -1) {
136 					return true;
137 				} else {
138 					// application/*+xml includes application/soap+xml
139 					int otherPlusIdx = other.getSubType().indexOf('+');
140 					if (otherPlusIdx != -1) {
141 						String thisSubtypeNoSuffix = getSubType().substring(0,
142 								thisPlusIdx);
143 						String thisSubtypeSuffix = getSubType().substring(
144 								thisPlusIdx + 1);
145 						String otherSubtypeSuffix = other.getSubType()
146 								.substring(otherPlusIdx + 1);
147 						if (thisSubtypeSuffix.equals(otherSubtypeSuffix)
148 								&& WILDCARD_TYPE.equals(thisSubtypeNoSuffix)) {
149 							return true;
150 						}
151 					}
152 				}
153 			}
154 		}
155 		return false;
156 	}
157 
158 	@Override
159 	public String toString() {
160 		return String.format("%s/%s", this.type, this.subType);
161 	}
162 
163 	@Override
164 	public boolean equals(Object other) {
165 		if (this == other) {
166 			return true;
167 		}
168 		if (!(other instanceof MimeType)) {
169 			return false;
170 		}
171 		MimeType otherType = (MimeType) other;
172 		return this.type.equalsIgnoreCase(otherType.type)
173 				&& this.subType.equalsIgnoreCase(otherType.subType);
174 	}
175 
176 	@Override
177 	public int hashCode() {
178 		final int prime = 31;
179 		int result = 1;
180 		result = prime * result + ((subType == null) ? 0 : subType.hashCode());
181 		result = prime * result + ((type == null) ? 0 : type.hashCode());
182 		return result;
183 	}
184 }