2626import java .util .ArrayList ;
2727import java .util .Collections ;
2828import java .util .LinkedHashMap ;
29- import java .util .LinkedList ;
3029import java .util .List ;
3130import java .util .Map ;
3231import java .util .Optional ;
3332
33+ import com .google .common .base .Throwables ;
34+ import com .google .common .cache .CacheBuilder ;
35+ import com .google .common .cache .CacheLoader ;
36+ import com .google .common .cache .LoadingCache ;
3437import com .google .common .collect .ImmutableList ;
3538import com .google .common .collect .ImmutableMap ;
39+ import com .google .common .util .concurrent .UncheckedExecutionException ;
3640import com .typesafe .config .Config ;
3741import com .typesafe .config .ConfigFactory ;
3842
@@ -169,7 +173,7 @@ public List<MediaType> filter(final List<MediaType> types) {
169173 if (types .size () == 1 ) {
170174 sortedTypes = ImmutableList .of (types .get (0 ));
171175 } else {
172- sortedTypes = new LinkedList <>(types );
176+ sortedTypes = new ArrayList <>(types );
173177 Collections .sort (sortedTypes );
174178 }
175179 for (MediaType accept : acceptable ) {
@@ -290,20 +294,34 @@ private MediaType doFirst(final List<MediaType> candidates) {
290294 */
291295 private final boolean wildcardSubtype ;
292296
297+ /** Name . */
298+ private String name ;
299+
300+ private int hc ;
301+
293302 /**
294303 * Alias for most used types.
295304 */
296- private static final Map <String , MediaType > alias = ImmutableMap .<String , MediaType > builder ()
297- .put ("html" , html )
298- .put ("json" , json )
299- .put ("css" , css )
300- .put ("js" , js )
301- .put ("octetstream" , octetstream )
302- .put ("form" , form )
303- .put ("multipart" , multipart )
304- .put ("xml" , xml )
305- .put ("*" , all )
306- .build ();
305+ private static final LoadingCache <String , List <MediaType >> cache = CacheBuilder .newBuilder ()
306+ .build (new CacheLoader <String , List <MediaType >>() {
307+ @ Override
308+ public List <MediaType > load (final String type ) throws Exception {
309+ return parseInternal (type );
310+ }
311+
312+ });
313+
314+ static {
315+ cache .put ("html" , ImmutableList .of (html ));
316+ cache .put ("json" , ImmutableList .of (json ));
317+ cache .put ("css" , ImmutableList .of (css ));
318+ cache .put ("js" , ImmutableList .of (js ));
319+ cache .put ("octetstream" , ImmutableList .of (octetstream ));
320+ cache .put ("form" , ImmutableList .of (form ));
321+ cache .put ("multipart" , ImmutableList .of (multipart ));
322+ cache .put ("xml" , ImmutableList .of (xml ));
323+ cache .put ("*" , ALL );
324+ }
307325
308326 static final Config types = ConfigFactory
309327 .parseResources ("mime.properties" )
@@ -322,6 +340,10 @@ private MediaType(final String type, final String subtype, final Map<String, Str
322340 this .params = ImmutableMap .copyOf (requireNonNull (parameters , "Parameters are required." ));
323341 this .wildcardType = "*" .equals (type );
324342 this .wildcardSubtype = "*" .equals (subtype );
343+ this .name = type + "/" + subtype ;
344+
345+ hc = 31 + name .hashCode ();
346+ hc = 31 * hc + params .hashCode ();
325347 }
326348
327349 /**
@@ -363,7 +385,7 @@ public String subtype() {
363385 * @return The qualified type {@link #type()}/{@link #subtype()}.
364386 */
365387 public String name () {
366- return type + "/" + subtype ;
388+ return name ;
367389 }
368390
369391 /**
@@ -374,10 +396,10 @@ public boolean isText() {
374396 return false ;
375397 }
376398
377- if (text .matches (this )) {
399+ if (this == text || text .matches (this )) {
378400 return true ;
379401 }
380- if (js .matches (this )) {
402+ if (this == js || js .matches (this )) {
381403 return true ;
382404 }
383405 if (jsonLike .matches (this )) {
@@ -474,16 +496,12 @@ public boolean equals(final Object obj) {
474496
475497 @ Override
476498 public int hashCode () {
477- final int prime = 31 ;
478- int result = prime + type .hashCode ();
479- result = prime * result + subtype .hashCode ();
480- result = prime * result + params .hashCode ();
481- return result ;
499+ return hc ;
482500 }
483501
484502 @ Override
485503 public final String toString () {
486- return name () ;
504+ return name ;
487505 }
488506
489507 /**
@@ -493,32 +511,55 @@ public final String toString() {
493511 * @return An immutable {@link MediaType}.
494512 */
495513 public static MediaType valueOf (final String type ) {
496- requireNonNull (type , "A mediaType is required." );
497- MediaType aliastype = alias .get (type .trim ());
498- if (aliastype != null ) {
499- return aliastype ;
500- }
501- String [] parts = type .trim ().split (";" );
502- if (parts [0 ].equals ("*" )) {
503- // odd and ugly media type
504- return MediaType .all ;
505- }
506- String [] typeAndSubtype = parts [0 ].split ("/" );
507- checkArgument (typeAndSubtype .length == 2 , "Bad media type: %s" , type );
508- String stype = typeAndSubtype [0 ].trim ();
509- String subtype = typeAndSubtype [1 ].trim ();
510- checkArgument (!(stype .equals ("*" ) && !subtype .equals ("*" )), "Bad media type: %s" , type );
511- Map <String , String > parameters = DEFAULT_PARAMS ;
512- if (parts .length > 1 ) {
513- parameters = new LinkedHashMap <>(DEFAULT_PARAMS );
514- for (int i = 1 ; i < parts .length ; i ++) {
515- String [] parameter = parts [i ].split ("=" );
516- if (parameter .length > 1 ) {
517- parameters .put (parameter [0 ].trim (), parameter [1 ].trim ().toLowerCase ());
514+ return parse (type ).get (0 );
515+ }
516+
517+ private static List <MediaType > parseInternal (final String value ) {
518+ String [] types = value .split ("," );
519+ @ SuppressWarnings ("serial" )
520+ List <MediaType > result = new ArrayList <MediaType >(types .length ) {
521+ int hc = 1 ;
522+
523+ @ Override
524+ public boolean add (final MediaType e ) {
525+ hc = 31 * hc + e .hashCode ();
526+ return super .add (e );
527+ }
528+
529+ @ Override
530+ public int hashCode () {
531+ return hc ;
532+ }
533+ };
534+ for (String type : types ) {
535+ requireNonNull (type , "A mediaType is required." );
536+ String [] parts = type .trim ().split (";" );
537+ if (parts [0 ].equals ("*" )) {
538+ // odd and ugly media type
539+ result .add (all );
540+ } else {
541+ String [] typeAndSubtype = parts [0 ].split ("/" );
542+ checkArgument (typeAndSubtype .length == 2 , "Bad media type: %s" , type );
543+ String stype = typeAndSubtype [0 ].trim ();
544+ String subtype = typeAndSubtype [1 ].trim ();
545+ checkArgument (!(stype .equals ("*" ) && !subtype .equals ("*" )), "Bad media type: %s" , type );
546+ Map <String , String > parameters = DEFAULT_PARAMS ;
547+ if (parts .length > 1 ) {
548+ parameters = new LinkedHashMap <>(DEFAULT_PARAMS );
549+ for (int i = 1 ; i < parts .length ; i ++) {
550+ String [] parameter = parts [i ].split ("=" );
551+ if (parameter .length > 1 ) {
552+ parameters .put (parameter [0 ].trim (), parameter [1 ].trim ().toLowerCase ());
553+ }
554+ }
518555 }
556+ result .add (new MediaType (stype , subtype , parameters ));
519557 }
520558 }
521- return new MediaType (stype , subtype , parameters );
559+ if (result .size () > 1 ) {
560+ Collections .sort (result );
561+ }
562+ return result ;
522563 }
523564
524565 /**
@@ -543,7 +584,11 @@ public static List<MediaType> valueOf(final String... types) {
543584 * @return One ore more {@link MediaType}.
544585 */
545586 public static List <MediaType > parse (final String value ) {
546- return valueOf (value .split ("," ));
587+ try {
588+ return cache .getUnchecked (value );
589+ } catch (UncheckedExecutionException ex ) {
590+ throw Throwables .propagate (ex .getCause ());
591+ }
547592 }
548593
549594 /**
0 commit comments