1 // Copyright 2007, 2008 The Apache Software Foundation 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package org.apache.tapestry5; 16 17 import org.apache.tapestry5.internal.InternalConstants; 18 import org.apache.tapestry5.ioc.internal.util.CollectionFactory; 19 import org.apache.tapestry5.ioc.internal.util.Defense; 20 import org.apache.tapestry5.ioc.internal.util.InternalUtils; 21 22 import java.util.List; 23 import java.util.Map; 24 import java.util.StringTokenizer; 25 26 /** 27 * Represents an HTTP content type. Allows to set various elements like the mime type, the character set, and other 28 * parameters. This is similar to a number of other implementations of the same concept in JAF, etc. We have created 29 * this simple implementation to avoid including the whole libraries. 30 */ 31 public final class ContentType 32 { 33 private String baseType = ""; 34 35 private String subType = ""; 36 37 private final Map<String, String> parameters = CollectionFactory.newCaseInsensitiveMap(); 38 39 /** 40 * Creates a new empty content type. 41 */ 42 public ContentType() 43 { 44 } 45 46 /** 47 * Creates a new content type from the argument. The format of the argument has to be basetype/subtype(;key=value)* 48 * 49 * @param contentType the content type that needs to be represented 50 */ 51 public ContentType(String contentType) 52 { 53 parse(contentType); 54 } 55 56 /** 57 * Creates a new content type with the given MIME type and charset 58 */ 59 public ContentType(String contentType, String charset) 60 { 61 this(contentType); 62 63 setParameter(InternalConstants.CHARSET_CONTENT_TYPE_PARAMETER, charset); 64 } 65 66 67 /** 68 * Returns true only if the other object is another instance of ContentType, and has the ssame baseType, subType and 69 * set of parameters. 70 */ 71 @Override 72 public boolean equals(Object o) 73 { 74 if (o == null) return false; 75 76 if (o.getClass() != this.getClass()) return false; 77 78 ContentType ct = (ContentType) o; 79 80 return baseType.equals(ct.baseType) && subType.equals(ct.subType) && parameters.equals(ct.parameters); 81 } 82 83 /** 84 * @return the base type of the content type 85 */ 86 public String getBaseType() 87 { 88 return baseType; 89 } 90 91 /** 92 * @param baseType 93 */ 94 public void setBaseType(String baseType) 95 { 96 Defense.notNull(baseType, "baseType"); 97 98 this.baseType = baseType; 99 } 100 101 /** 102 * @return the sub-type of the content type 103 */ 104 public String getSubType() 105 { 106 return subType; 107 } 108 109 /** 110 * @param subType 111 */ 112 public void setSubType(String subType) 113 { 114 Defense.notNull(subType, "subType"); 115 116 this.subType = subType; 117 } 118 119 /** 120 * @return the MIME type of the content type 121 */ 122 public String getMimeType() 123 { 124 return baseType + "/" + subType; 125 } 126 127 /** 128 * @return the list of names of parameters in this content type, in alphabetical order. 129 */ 130 public List<String> getParameterNames() 131 { 132 return InternalUtils.sortedKeys(parameters); 133 } 134 135 /** 136 * @return the character set (the "charset" parameter) or null. 137 */ 138 public String getCharset() 139 { 140 return getParameter(InternalConstants.CHARSET_CONTENT_TYPE_PARAMETER); 141 } 142 143 /** 144 * @param key the name of the content type parameter 145 * @return the value of the content type parameter 146 */ 147 public String getParameter(String key) 148 { 149 Defense.notNull(key, "key"); 150 151 return parameters.get(key); 152 } 153 154 /** 155 * @param key the name of the content type parameter 156 * @param value the value of the content type parameter 157 */ 158 public void setParameter(String key, String value) 159 { 160 Defense.notNull(key, "key"); 161 Defense.notNull(value, "value"); 162 163 parameters.put(key, value); 164 } 165 166 /** 167 * Parses the argument and configures the content type accordingly. The format of the argument has to be 168 * type/subtype(;key=value)* 169 * 170 * @param contentType the content type that needs to be represented 171 */ 172 public void parse(String contentType) 173 { 174 baseType = ""; 175 subType = ""; 176 parameters.clear(); 177 178 StringTokenizer tokens = new StringTokenizer(contentType, ";"); 179 if (!tokens.hasMoreTokens()) return; 180 181 String mimeType = tokens.nextToken(); 182 StringTokenizer mimeTokens = new StringTokenizer(mimeType, "/"); 183 setBaseType(mimeTokens.hasMoreTokens() ? mimeTokens.nextToken() : ""); 184 setSubType(mimeTokens.hasMoreTokens() ? mimeTokens.nextToken() : ""); 185 186 while (tokens.hasMoreTokens()) 187 { 188 String parameter = tokens.nextToken(); 189 190 StringTokenizer parameterTokens = new StringTokenizer(parameter, "="); 191 String key = parameterTokens.hasMoreTokens() ? parameterTokens.nextToken() : ""; 192 String value = parameterTokens.hasMoreTokens() ? parameterTokens.nextToken() : ""; 193 setParameter(key, value); 194 } 195 } 196 197 /** 198 * @return the string representation of this content type 199 */ 200 public String unparse() 201 { 202 StringBuilder buffer = new StringBuilder(getMimeType()); 203 204 for (String parameterName : getParameterNames()) 205 { 206 buffer.append(";"); 207 buffer.append(parameterName); 208 buffer.append("="); 209 buffer.append(parameters.get(parameterName)); 210 } 211 212 return buffer.toString(); 213 } 214 215 /** 216 * @return the string representation of this content type. Same as unparse(). 217 */ 218 @Override 219 public String toString() 220 { 221 return unparse(); 222 } 223 }