View Javadoc

1   /**
2    * Copyright (C) 2005-2009 Alfresco Software Limited.
3    *
4    * This file is part of the Spring Surf Extension project.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.springframework.extensions.webscripts;
20  
21  
22  /**
23   * Represents a MediaType as described at
24   * 
25   * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
26   */
27  public class MediaType
28  {
29      private String type;
30      private String subtype;
31      private String params = "";
32      private float quality = 1.0f;
33      
34  
35      /**
36       * Construct
37       * 
38       * @param  mediatype  string representation of mediatype e.g. text/html;level=1;q=0.8
39       */
40      public MediaType(String mediatype)
41      {
42          if (mediatype == null || mediatype.length() == 0)
43          {
44              throw new WebScriptException("Invalid mediatype: " + mediatype);
45          }
46          String[] parts = mediatype.split("/");
47          if (parts.length != 2)
48          {
49              throw new WebScriptException("Invalid mediatype: " + mediatype + " does not consists of type and subtype");
50          }
51          
52          this.type = parts[0].trim();
53  
54          int paramsIdx = parts[1].indexOf(';');
55          if (paramsIdx == -1)
56          {
57              // subtype only has been specified
58              this.subtype = parts[1];
59          }
60          else
61          {
62              String params = parts[1].substring(paramsIdx);
63              int qualityIdx = params.lastIndexOf(";");
64              String[] qualityParts = params.substring(qualityIdx +1).split("=");
65              if (qualityParts.length == 2 && qualityParts[0].trim().equals("q"))
66              {
67                  // mediatype includes quality factor (and potentially accept-params)
68                  this.subtype = parts[1].substring(0, paramsIdx).replace(" ", "");
69                  this.quality = new Float(qualityParts[1].trim()).floatValue();
70                  if (qualityIdx > 0)
71                  {
72                      this.params = params.substring(1, qualityIdx).replace(" ", "");
73                  }
74              }
75              else
76              {
77                  // mediatype includes accept-params only
78                  this.subtype = parts[1].substring(0, paramsIdx).replace(" ", "");
79                  this.params = params.substring(1).replace(" ", "");
80              }
81          }
82      }
83      
84      /**
85       * @return  type
86       */
87      public String getType()
88      {
89          return type;
90      }
91  
92      /**
93       * @return  subtype
94       */
95      public String getSubtype()
96      {
97          return subtype;
98      }
99  
100     /**
101      * @return  params
102      */
103     public String getParams()
104     {
105         return params;
106     }
107 
108     /**
109      * @return  quality factory
110      */
111     public float getQuality()
112     {
113         return quality;
114     }
115     
116     /**
117      * Compare to another media type
118      * 
119      * @param to  media type to compare to
120      * @return  score representing how close a match the compared media types are
121      */
122     public float compare(MediaType to)
123     {
124         boolean typeWildcard = to.type.equals("*");
125         boolean subtypeWildcard = to.subtype.equals("*");
126         boolean paramsWildcard = to.params.length() == 0;
127         if (typeWildcard || type.equals(to.type))
128         {
129             if (subtypeWildcard || subtype.equals(to.subtype))
130             {
131                 if (paramsWildcard || params.equals(to.params))
132                 {
133                     return (typeWildcard ? 0.0f : 10.0f) + (subtypeWildcard ? 0.0f : 100.0f) + (paramsWildcard ? 0.0f : 1000f) + to.quality;
134                 }
135             }
136         }
137         return 0.0f;
138     }
139     
140     /**
141      * @return  string representation of media type in the format of type/subtype[;params]
142      */
143     private String toMediaType()
144     {
145         return type + "/" + subtype + (params.length() == 0 ? "" : ";" + params);
146     }
147     
148     /* (non-Javadoc)
149      * @see java.lang.Object#hashCode()
150      */
151     public int hashCode()
152     {
153         return toMediaType().hashCode();
154     }
155     
156     /* (non-Javadoc)
157      * @see java.lang.Object#equals(java.lang.Object)
158      */
159     public boolean equals(Object other)
160     {
161         if (other == null)
162         {
163             return false;
164         }
165         if (other instanceof MediaType)
166         {
167             return this.type.equals(((MediaType)other).type) && this.subtype.equals(((MediaType)other).subtype) &&
168                    this.params.equals(((MediaType)other).params);
169         }
170         return false;
171     }
172     
173     /* (non-Javadoc)
174      * @see java.lang.Object#toString()
175      */
176     public String toString()
177     {
178         return toMediaType() + ";q=" + quality;
179     }
180 
181     
182     
183     /**
184      * Simple exampe usage
185      * 
186      * @param args
187      */
188     public static void main(String[] args)
189     {
190         MediaType one = new MediaType("*/*");
191         System.out.println(one.toString());
192         MediaType two = new MediaType("a/b");
193         System.out.println(two.toString());
194         MediaType three = new MediaType("a/*");
195         System.out.println(three.toString());
196         MediaType four = new MediaType("a/*;b=1");
197         System.out.println(four.toString());
198         MediaType five = new MediaType("a/* ; b=1");
199         System.out.println(five.toString());
200         System.out.println(four.equals(five));
201         MediaType six = new MediaType("a/*;q=0.1");
202         System.out.println(six.toString());
203         MediaType seven = new MediaType("a/*;q = 0.1");
204         System.out.println(seven.toString());
205         MediaType eight = new MediaType("a/*; q = 0.1");
206         System.out.println(eight.toString());
207         MediaType nine = new MediaType("a/*;b=1; q = 0.1");
208         System.out.println(nine.toString());
209         MediaType ten = new MediaType("a/*;");
210         System.out.println(ten.toString());
211         MediaType eleven = new MediaType("a/*;b=1;c=2;q=1.0");
212         System.out.println(eleven.toString());
213         
214         MediaType textHtmlLevel1 = new MediaType("text/html;level=1");
215         MediaType textHtml = new MediaType("text/html");
216         MediaType textPlain = new MediaType("text/plain");
217         MediaType imageJpeg = new MediaType("image/jpeg");
218         MediaType textHtmlLevel2 = new MediaType("text/html;level=2");
219         MediaType textHtmlLevel3 = new MediaType("text/html;level=3");
220         
221         MediaType acceptTextStar = new MediaType("text/*;q=0.3");
222         MediaType acceptTextHtml = new MediaType("text/html;q=0.7");
223         MediaType acceptTextHtmlLevel1 = new MediaType("text/html;level=1");
224         MediaType acceptTextHtmlLevel2 = new MediaType("text/html;level=2;q=0.4");
225         MediaType acceptStarStar = new MediaType("*/*;q=0.5");
226         
227 
228         MediaType[] negotiated = new MediaType[] {textHtmlLevel1, textHtml, textPlain, imageJpeg, textHtmlLevel2, textHtmlLevel3};
229         MediaType[] accept = new MediaType[] {acceptTextStar, acceptTextHtml, acceptTextHtmlLevel1, acceptTextHtmlLevel2, acceptStarStar};
230 
231         for (MediaType neg : negotiated)
232         {
233             System.out.println("Testing " + neg.toMediaType());
234             float q = 0.0f;
235             for (MediaType acc : accept)
236             {
237                 float accq = neg.compare(acc);
238                 System.out.println(" Compare to " + acc.toString() + " = " + accq);
239                 if (accq > q)
240                 {
241                     q = accq;
242                 }
243             }
244             System.out.println(" Result = " + q);
245         }
246     }
247     
248 }