001 // Copyright 2007, 2008, 2010 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5; 016 017 import java.util.List; 018 import java.util.Map; 019 import java.util.StringTokenizer; 020 021 import org.apache.tapestry5.internal.InternalConstants; 022 import org.apache.tapestry5.ioc.internal.util.CollectionFactory; 023 import org.apache.tapestry5.ioc.internal.util.InternalUtils; 024 025 /** 026 * Represents an HTTP content type. Allows to set various elements like the mime type, the character set, and other 027 * parameters. This is similar to a number of other implementations of the same concept in JAF, etc. We have created 028 * this simple implementation to avoid including the whole libraries. 029 */ 030 public final class ContentType 031 { 032 private String baseType = ""; 033 034 private String subType = ""; 035 036 private final Map<String, String> parameters = CollectionFactory.newCaseInsensitiveMap(); 037 038 /** 039 * Creates a new empty content type. 040 */ 041 public ContentType() 042 { 043 } 044 045 /** 046 * Creates a new content type from the argument. The format of the argument has to be basetype/subtype(;key=value)* 047 * 048 * @param contentType the content type that needs to be represented 049 */ 050 public ContentType(String contentType) 051 { 052 parse(contentType); 053 } 054 055 /** 056 * Creates a new content type with the given MIME type and charset 057 */ 058 public ContentType(String contentType, String charset) 059 { 060 this(contentType); 061 062 setParameter(InternalConstants.CHARSET_CONTENT_TYPE_PARAMETER, charset); 063 } 064 065 066 /** 067 * Returns true only if the other object is another instance of ContentType, and has the ssame baseType, subType and 068 * set of parameters. 069 */ 070 @Override 071 public boolean equals(Object o) 072 { 073 if (o == null) return false; 074 075 if (o.getClass() != this.getClass()) return false; 076 077 ContentType ct = (ContentType) o; 078 079 return baseType.equals(ct.baseType) && subType.equals(ct.subType) && parameters.equals(ct.parameters); 080 } 081 082 /** 083 * @return the base type of the content type 084 */ 085 public String getBaseType() 086 { 087 return baseType; 088 } 089 090 /** 091 * @param baseType 092 */ 093 public void setBaseType(String baseType) 094 { 095 assert baseType != null; 096 this.baseType = baseType; 097 } 098 099 /** 100 * @return the sub-type of the content type 101 */ 102 public String getSubType() 103 { 104 return subType; 105 } 106 107 /** 108 * @param subType 109 */ 110 public void setSubType(String subType) 111 { 112 assert subType != null; 113 this.subType = subType; 114 } 115 116 /** 117 * @return the MIME type of the content type 118 */ 119 public String getMimeType() 120 { 121 return baseType + "/" + subType; 122 } 123 124 /** 125 * @return the list of names of parameters in this content type, in alphabetical order. 126 */ 127 public List<String> getParameterNames() 128 { 129 return InternalUtils.sortedKeys(parameters); 130 } 131 132 /** 133 * @return the character set (the "charset" parameter) or null. 134 */ 135 public String getCharset() 136 { 137 return getParameter(InternalConstants.CHARSET_CONTENT_TYPE_PARAMETER); 138 } 139 140 /** 141 * @param key the name of the content type parameter 142 * @return the value of the content type parameter 143 */ 144 public String getParameter(String key) 145 { 146 assert key != null; 147 return parameters.get(key); 148 } 149 150 /** 151 * @param key the name of the content type parameter 152 * @param value the value of the content type parameter 153 */ 154 public void setParameter(String key, String value) 155 { 156 assert key != null; 157 assert value != null; 158 parameters.put(key, value); 159 } 160 161 /** 162 * Parses the argument and configures the content type accordingly. The format of the argument has to be 163 * type/subtype(;key=value)* 164 * 165 * @param contentType the content type that needs to be represented 166 */ 167 public void parse(String contentType) 168 { 169 baseType = ""; 170 subType = ""; 171 parameters.clear(); 172 173 StringTokenizer tokens = new StringTokenizer(contentType, ";"); 174 if (!tokens.hasMoreTokens()) return; 175 176 String mimeType = tokens.nextToken(); 177 StringTokenizer mimeTokens = new StringTokenizer(mimeType, "/"); 178 setBaseType(mimeTokens.hasMoreTokens() ? mimeTokens.nextToken() : ""); 179 setSubType(mimeTokens.hasMoreTokens() ? mimeTokens.nextToken() : ""); 180 181 while (tokens.hasMoreTokens()) 182 { 183 String parameter = tokens.nextToken(); 184 185 StringTokenizer parameterTokens = new StringTokenizer(parameter, "="); 186 String key = parameterTokens.hasMoreTokens() ? parameterTokens.nextToken() : ""; 187 String value = parameterTokens.hasMoreTokens() ? parameterTokens.nextToken() : ""; 188 setParameter(key, value); 189 } 190 } 191 192 /** 193 * @return the string representation of this content type 194 */ 195 public String unparse() 196 { 197 StringBuilder buffer = new StringBuilder(getMimeType()); 198 199 for (String parameterName : getParameterNames()) 200 { 201 buffer.append(";"); 202 buffer.append(parameterName); 203 buffer.append("="); 204 buffer.append(parameters.get(parameterName)); 205 } 206 207 return buffer.toString(); 208 } 209 210 /** 211 * @return the string representation of this content type. Same as unparse(). 212 */ 213 @Override 214 public String toString() 215 { 216 return unparse(); 217 } 218 }