001 // Copyright 2004, 2005 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.tapestry.util;
016
017 import java.util.HashMap;
018 import java.util.Map;
019 import java.util.Set;
020 import java.util.StringTokenizer;
021
022 import org.apache.hivemind.util.Defense;
023
024 /**
025 * Represents an HTTP content type. Allows to set various elements like the mime type, the character
026 * set, and other parameters. This is similar to a number of other implementations of the same
027 * concept in JAF, etc. We have created this simple implementation to avoid including the whole
028 * libraries.
029 *
030 * @author mindbridge
031 * @since 3.0
032 */
033 public class ContentType
034 {
035 private String _baseType = "";
036
037 private String _subType = "";
038
039 private final Map _parameters = new HashMap();
040
041 /**
042 * Creates a new empty content type
043 */
044 public ContentType()
045 {
046 }
047
048 /**
049 * Creates a new content type from the argument. The format of the argument has to be
050 * basetype/subtype(;key=value)*
051 *
052 * @param contentType
053 * the content type that needs to be represented
054 */
055 public ContentType(String contentType)
056 {
057 this();
058 parse(contentType);
059 }
060
061 /**
062 * Returns true only if the other object is another instance of ContentType, and has the ssame
063 * baseType, subType and set of parameters.
064 */
065 public boolean equals(Object o)
066 {
067 if (o == null)
068 return false;
069
070 if (o.getClass() != this.getClass())
071 return false;
072
073 ContentType ct = (ContentType) o;
074
075 return _baseType.equals(ct._baseType) && _subType.equals(ct._subType)
076 && _parameters.equals(ct._parameters);
077 }
078
079 /**
080 * @return the base type of the content type
081 */
082 public String getBaseType()
083 {
084 return _baseType;
085 }
086
087 /**
088 * @param baseType
089 */
090 public void setBaseType(String baseType)
091 {
092 Defense.notNull(baseType, "baseType");
093
094 _baseType = baseType;
095 }
096
097 /**
098 * @return the sub-type of the content type
099 */
100 public String getSubType()
101 {
102 return _subType;
103 }
104
105 /**
106 * @param subType
107 */
108 public void setSubType(String subType)
109 {
110 Defense.notNull(subType, "subType");
111
112 _subType = subType;
113 }
114
115 /**
116 * @return the MIME type of the content type
117 */
118 public String getMimeType()
119 {
120 return _baseType + "/" + _subType;
121 }
122
123 /**
124 * @return the list of names of parameters in this content type
125 */
126 public String[] getParameterNames()
127 {
128 Set parameterNames = _parameters.keySet();
129 return (String[]) parameterNames.toArray(new String[parameterNames.size()]);
130 }
131
132 /**
133 * @param key
134 * the name of the content type parameter
135 * @return the value of the content type parameter
136 */
137 public String getParameter(String key)
138 {
139 Defense.notNull(key, "key");
140
141 return (String) _parameters.get(key);
142 }
143
144 /**
145 * @param key
146 * the name of the content type parameter
147 * @param value
148 * the value of the content type parameter
149 */
150 public void setParameter(String key, String value)
151 {
152 Defense.notNull(key, "key");
153 Defense.notNull(value, "value");
154
155 _parameters.put(key.toLowerCase(), value);
156 }
157
158 /**
159 * Parses the argument and configures the content type accordingly. The format of the argument
160 * has to be type/subtype(;key=value)*
161 *
162 * @param contentType
163 * the content type that needs to be represented
164 */
165 public void parse(String contentType)
166 {
167 _baseType = "";
168 _subType = "";
169 _parameters.clear();
170
171 StringTokenizer tokens = new StringTokenizer(contentType, ";");
172 if (!tokens.hasMoreTokens())
173 return;
174
175 String mimeType = tokens.nextToken();
176 StringTokenizer mimeTokens = new StringTokenizer(mimeType, "/");
177 setBaseType(mimeTokens.hasMoreTokens() ? mimeTokens.nextToken() : "");
178 setSubType(mimeTokens.hasMoreTokens() ? mimeTokens.nextToken() : "");
179
180 while (tokens.hasMoreTokens())
181 {
182 String parameter = tokens.nextToken();
183
184 StringTokenizer parameterTokens = new StringTokenizer(parameter, "=");
185 String key = parameterTokens.hasMoreTokens() ? parameterTokens.nextToken() : "";
186 String value = parameterTokens.hasMoreTokens() ? parameterTokens.nextToken() : "";
187 setParameter(key, value);
188 }
189 }
190
191 /**
192 * @return the string representation of this content type
193 */
194 public String unparse()
195 {
196 StringBuffer buf = new StringBuffer(getMimeType());
197
198 String[] parameterNames = getParameterNames();
199 for (int i = 0; i < parameterNames.length; i++)
200 {
201 String key = parameterNames[i];
202 String value = getParameter(key);
203 buf.append(";" + key + "=" + value);
204 }
205
206 return buf.toString();
207 }
208
209 /**
210 * @return the string representation of this content type. Same as unparse().
211 */
212 public String toString()
213 {
214 return unparse();
215 }
216
217 }