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