@@ -124,7 +124,7 @@ public HttpField getContentTypeField(Charset charset)
124
124
private final Charset _charset ;
125
125
private final String _charsetString ;
126
126
private final boolean _assumedCharset ;
127
- private final HttpField _field ;
127
+ private final ContentTypeField _field ;
128
128
129
129
Type (String name )
130
130
{
@@ -133,18 +133,18 @@ public HttpField getContentTypeField(Charset charset)
133
133
_charset = null ;
134
134
_charsetString = null ;
135
135
_assumedCharset = false ;
136
- _field = new PreEncodedHttpField ( HttpHeader . CONTENT_TYPE , _string );
136
+ _field = new ContentTypeField ( this );
137
137
}
138
138
139
139
Type (String name , Type base )
140
140
{
141
141
_string = name ;
142
- _base = base ;
142
+ _base = Objects . requireNonNull ( base ) ;
143
143
int i = name .indexOf (";charset=" );
144
144
_charset = Charset .forName (name .substring (i + 9 ));
145
145
_charsetString = _charset .toString ().toLowerCase (Locale .ENGLISH );
146
146
_assumedCharset = false ;
147
- _field = new PreEncodedHttpField ( HttpHeader . CONTENT_TYPE , _string );
147
+ _field = new ContentTypeField ( this );
148
148
}
149
149
150
150
Type (String name , Charset cs )
@@ -154,9 +154,12 @@ public HttpField getContentTypeField(Charset charset)
154
154
_charset = cs ;
155
155
_charsetString = _charset == null ? null : _charset .toString ().toLowerCase (Locale .ENGLISH );
156
156
_assumedCharset = true ;
157
- _field = new PreEncodedHttpField ( HttpHeader . CONTENT_TYPE , _string );
157
+ _field = new ContentTypeField ( this );
158
158
}
159
159
160
+ /**
161
+ * @return The {@link Charset} for this type or {@code null} if it is not known
162
+ */
160
163
public Charset getCharset ()
161
164
{
162
165
return _charset ;
@@ -167,6 +170,11 @@ public String getCharsetString()
167
170
return _charsetString ;
168
171
}
169
172
173
+ /**
174
+ * Check if this type is equal to the type passed as a string
175
+ * @param type The type to compare to
176
+ * @return {@code true} if this is the same type
177
+ */
170
178
public boolean is (String type )
171
179
{
172
180
return _string .equalsIgnoreCase (type );
@@ -183,6 +191,9 @@ public String toString()
183
191
return _string ;
184
192
}
185
193
194
+ /**
195
+ * @return {@code true} If the {@link Charset} for this type is assumed rather than being explicitly declared.
196
+ */
186
197
public boolean isCharsetAssumed ()
187
198
{
188
199
return _assumedCharset ;
@@ -200,6 +211,10 @@ public HttpField getContentTypeField(Charset charset)
200
211
return new HttpField (HttpHeader .CONTENT_TYPE , getContentTypeWithoutCharset (_string ) + ";charset=" + charset .name ());
201
212
}
202
213
214
+ /**
215
+ * Get the base type of this type, which is the type without a charset specified
216
+ * @return The base type or this type if it is a base type
217
+ */
203
218
public Type getBaseType ()
204
219
{
205
220
return _base ;
@@ -227,23 +242,34 @@ public Type getBaseType()
227
242
})
228
243
.build ();
229
244
245
+ /**
246
+ * Get the base value, stripped of any parameters
247
+ * @param value The value
248
+ * @return A string with any semicolon separated parameters removed
249
+ */
250
+ public static String getBase (String value )
251
+ {
252
+ int index = value .indexOf (';' );
253
+ return index == -1 ? value : value .substring (0 , index );
254
+ }
255
+
256
+ /**
257
+ * Get the base type of this type, which is the type without a charset specified
258
+ * @param contentType The mimetype as a string
259
+ * @return The base type or this type if it is a base type
260
+ */
230
261
public static Type getBaseType (String contentType )
231
262
{
232
263
if (StringUtil .isEmpty (contentType ))
233
264
return null ;
234
265
Type type = CACHE .getBest (contentType );
235
266
if (type == null )
236
- return null ;
237
- if (type .asString ().length () == contentType .length ())
238
- return type .getBaseType ();
239
- if (contentType .charAt (type .asString ().length ()) == ';' )
240
- return type .getBaseType ();
241
- contentType = contentType .replace (" " , "" );
242
- if (type .asString ().length () == contentType .length ())
243
- return type .getBaseType ();
244
- if (contentType .charAt (type .asString ().length ()) == ';' )
245
- return type .getBaseType ();
246
- return null ;
267
+ {
268
+ type = CACHE .get (getBase (contentType ));
269
+ if (type == null )
270
+ return null ;
271
+ }
272
+ return type .getBaseType ();
247
273
}
248
274
249
275
public static boolean isKnownLocale (Locale locale )
@@ -326,6 +352,23 @@ public MimeTypes(MimeTypes defaults)
326
352
}
327
353
}
328
354
355
+ /**
356
+ * Get the explicit, assumed, or inferred Charset for a HttpField containing a mime type value
357
+ * @param field HttpField with a mime type value (e.g. Content-Type)
358
+ * @return A {@link Charset} or null;
359
+ * @throws IllegalCharsetNameException
360
+ * If the given charset name is illegal
361
+ * @throws UnsupportedCharsetException
362
+ * If no support for the named charset is available
363
+ * in this instance of the Java virtual machine
364
+ */
365
+ public Charset getCharset (HttpField field ) throws IllegalCharsetNameException , UnsupportedCharsetException
366
+ {
367
+ if (field instanceof ContentTypeField contentTypeField )
368
+ return contentTypeField .getMimeType ().getCharset ();
369
+ return getCharset (field .getValue ());
370
+ }
371
+
329
372
/**
330
373
* Get the explicit, assumed, or inferred Charset for a mime type
331
374
* @param mimeType String form or a mimeType
@@ -638,6 +681,46 @@ private static String normalizeMimeType(String type)
638
681
return StringUtil .asciiToLowerCase (type );
639
682
}
640
683
684
+ public static MimeTypes .Type getMimeTypeFromContentType (HttpField field )
685
+ {
686
+ if (field == null )
687
+ return null ;
688
+
689
+ assert field .getHeader () == HttpHeader .CONTENT_TYPE ;
690
+
691
+ if (field instanceof MimeTypes .ContentTypeField contentTypeField )
692
+ return contentTypeField .getMimeType ();
693
+
694
+ return MimeTypes .CACHE .get (field .getValue ());
695
+ }
696
+
697
+ /**
698
+ * Efficiently extract the charset value from a {@code Content-Type} {@link HttpField}.
699
+ * @param field A {@code Content-Type} field.
700
+ * @return The {@link Charset}
701
+ */
702
+ public static Charset getCharsetFromContentType (HttpField field )
703
+ {
704
+ if (field == null )
705
+ return null ;
706
+
707
+ assert field .getHeader () == HttpHeader .CONTENT_TYPE ;
708
+
709
+ if (field instanceof ContentTypeField contentTypeField )
710
+ return contentTypeField ._type .getCharset ();
711
+
712
+ String charset = getCharsetFromContentType (field .getValue ());
713
+ if (charset == null )
714
+ return null ;
715
+
716
+ return Charset .forName (charset );
717
+ }
718
+
719
+ /**
720
+ * Efficiently extract the charset value from a {@code Content-Type} string
721
+ * @param value A content-type value (e.g. {@code text/plain; charset=utf8}).
722
+ * @return The charset value (e.g. {@code utf-8}).
723
+ */
641
724
public static String getCharsetFromContentType (String value )
642
725
{
643
726
if (value == null )
@@ -751,6 +834,11 @@ else if (' ' != b)
751
834
return null ;
752
835
}
753
836
837
+ /**
838
+ * Efficiently extract the base mime-type from a content-type value
839
+ * @param value A content-type value (e.g. {@code text/plain; charset=utf8}).
840
+ * @return The base mime-type value (e.g. {@code text/plain}).
841
+ */
754
842
public static String getContentTypeWithoutCharset (String value )
755
843
{
756
844
int end = value .length ();
@@ -876,4 +964,29 @@ else if (' ' != b)
876
964
return value ;
877
965
return builder .toString ();
878
966
}
967
+
968
+ /**
969
+ * A {@link PreEncodedHttpField} for `Content-Type` that can hold a {@link MimeTypes.Type} field
970
+ * for later recovery.
971
+ */
972
+ static class ContentTypeField extends PreEncodedHttpField
973
+ {
974
+ private final Type _type ;
975
+
976
+ public ContentTypeField (MimeTypes .Type type )
977
+ {
978
+ this (type , type .toString ());
979
+ }
980
+
981
+ public ContentTypeField (MimeTypes .Type type , String value )
982
+ {
983
+ super (HttpHeader .CONTENT_TYPE , value );
984
+ _type = type ;
985
+ }
986
+
987
+ public Type getMimeType ()
988
+ {
989
+ return _type ;
990
+ }
991
+ }
879
992
}
0 commit comments