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 }