OSDN Git Service

libjava/ChangeLog:
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / activation / MimeTypeParameterList.java
1 /* MimeTypeParameterList.java -- Handle a list of MIME type parameters.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package javax.activation;
39
40 import gnu.java.lang.CPStringBuilder;
41
42 import java.util.ArrayList;
43 import java.util.Enumeration;
44 import java.util.HashMap;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.Map;
48
49 /**
50  * A list of MIME type parameters, as specified in RFCs 2045 and 2046.
51  *
52  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
53  * @version 1.1
54  */
55 public class MimeTypeParameterList
56 {
57
58   private final List<String> parameterNames;
59   private final Map<String,String> parameterValues;
60   
61   /**
62    * Constructor for an empty parameter list.
63    */
64   public MimeTypeParameterList()
65   {
66     parameterNames = new ArrayList<String>();
67     parameterValues = new HashMap<String,String>();
68   }
69
70   /**
71    * Constructor that parses the specified MIME parameter data.
72    * @param parameterList a MIME parameter list string representation
73    */
74   public MimeTypeParameterList(String parameterList)
75     throws MimeTypeParseException
76   {
77     this();
78     parse(parameterList);
79   }
80
81   /**
82    * Parses the specified MIME parameter data, storing the results in this
83    * object.
84    * @param parameterList a MIME parameter list string representation
85    */
86   protected void parse(String parameterList)
87     throws MimeTypeParseException
88   {
89     if (parameterList == null)
90       {
91         return;
92       }
93     // Tokenize list into parameters
94     char[] chars = parameterList.toCharArray();
95     int len = chars.length;
96     boolean inQuotedString = false;
97     CPStringBuilder buffer = new CPStringBuilder();
98     List<String> params = new ArrayList<String>();
99     for (int i = 0; i < len; i++)
100       {
101         char c = chars[i];
102         if (c == ';' && !inQuotedString)
103           {
104             String param = buffer.toString().trim();
105             if (param.length() > 0)
106               {
107                 params.add(param);
108               }
109             buffer.setLength(0);
110           }
111         else
112           {
113             if (c == '"')
114               {
115                 inQuotedString = !inQuotedString;
116               }
117             buffer.append(c);
118           }
119       }
120     String param = buffer.toString().trim();
121     if (param.length() > 0)
122       {
123         params.add(param);
124       }
125     
126     // Tokenize each parameter into name + value
127     for (Iterator<String> i = params.iterator(); i.hasNext();)
128       {
129         param = i.next();
130         int ei = param.indexOf('=');
131         if (ei == -1)
132           {
133             throw new MimeTypeParseException("Couldn't find the '=' that " +
134                                              "separates a parameter name " +
135                                              "from its value.");
136           }
137         String name = param.substring(0, ei).trim();
138         MimeType.checkValidity(name, "Parameter name is invalid");
139         String value = param.substring(ei + 1).trim();
140         len = value.length();
141         if (len > 1 && value.charAt(0) == '"' &&
142             value.charAt(len - 1) == '"')
143           {
144             value = unquote(value);
145           }
146         else
147           {
148             MimeType.checkValidity(name, "Parameter value is invalid");
149           }
150         
151         parameterNames.add(name);
152         parameterValues.put(name.toLowerCase(), value);
153       }
154   }
155   
156   /**
157    * Returns the number of parameters.
158    */
159   public synchronized int size()
160   {
161     return parameterNames.size();
162   }
163   
164   /**
165    * Indicates if there are no parameters.
166    */
167   public synchronized boolean isEmpty()
168   {
169     return parameterNames.isEmpty();
170   }
171
172   /**
173    * Returns the value for the specified parameter name.
174    * @param name the parameter name
175    */
176   public synchronized String get(String name)
177   {
178     name = name.trim();
179     return parameterValues.get(name.toLowerCase());
180   }
181   
182   /**
183    * Sets the value for the specified parameter name.
184    * @param name the parameter name
185    * @param value the parameter value
186    */
187   public synchronized void set(String name, String value)
188   {
189     name = name.trim();
190     boolean exists = false;
191     for (String pname : parameterNames)
192       {
193         if (name.equalsIgnoreCase(pname))
194           {
195             exists = true;
196           }
197       }
198     if (!exists)
199       {
200         parameterNames.add(name);
201       }
202     parameterValues.put(name.toLowerCase(), value);
203   }
204   
205   /**
206    * Removes the parameter identified by the specified name.
207    * @param name the parameter name
208    */
209   public synchronized void remove(String name)
210   {
211     name = name.trim();
212     for (Iterator<String> i = parameterNames.iterator();i.hasNext();)
213       {
214         String pname = i.next();
215         if (name.equalsIgnoreCase(pname))
216           {
217             i.remove();
218           }
219       }
220     parameterValues.remove(name.toLowerCase());
221   }
222   
223   /**
224    * Returns an enumeration of all the parameter names.
225    */
226   // Raw type is forced by public spec.
227   @SuppressWarnings("unchecked")
228   public synchronized Enumeration getNames()
229   {
230     return new IteratorEnumeration(parameterNames.iterator());
231   }
232   
233   /**
234    * Returns an RFC 2045-compliant string representation of this parameter
235    * list.
236    */
237   public synchronized String toString()
238   {
239     CPStringBuilder buffer = new CPStringBuilder();
240     for (String name : parameterNames)
241       {
242         String value = parameterValues.get(name.toLowerCase());
243         
244         buffer.append(';');
245         buffer.append(' ');
246         buffer.append(name);
247         buffer.append('=');
248         buffer.append(quote(value));
249       }
250     return buffer.toString();
251   }
252   
253   private static String quote(String value)
254   {
255     boolean needsQuoting = false;
256     int len = value.length();
257     for (int i = 0; i < len; i++)
258       {
259         if (!MimeType.isValidChar(value.charAt(i)))
260           {
261             needsQuoting = true;
262             break;
263           }
264       }
265     
266     if (needsQuoting)
267       {
268         CPStringBuilder buffer = new CPStringBuilder();
269         buffer.append('"');
270         for (int i = 0; i < len; i++)
271           {
272             char c = value.charAt(i);
273             if (c == '\\' || c == '"')
274               {
275                 buffer.append('\\');
276               }
277             buffer.append(c);
278           }
279         buffer.append('"');
280         return buffer.toString();
281       }
282     return value;
283   }
284   
285   private static String unquote(String value)
286   {
287     int len = value.length();
288     CPStringBuilder buffer = new CPStringBuilder();
289     for (int i = 1; i < len - 1; i++)
290       {
291         char c = value.charAt(i);
292         if (c == '\\')
293           {
294             i++;
295             if (i < len - 1)
296               {
297                 c = value.charAt(i);
298                 if (c != '\\' && c != '"')
299                   {
300                     buffer.append('\\');
301                   }
302               }
303           }
304         buffer.append(c);
305       }
306     return buffer.toString();
307   }
308   
309   /**
310    * Enumeration proxy for an Iterator.
311    */
312   static class IteratorEnumeration
313     implements Enumeration<String>
314   {
315     
316     final Iterator<String> iterator;
317     
318     IteratorEnumeration(Iterator<String> iterator)
319     {
320       this.iterator = iterator;
321     }
322     
323     public boolean hasMoreElements()
324     {
325       return iterator.hasNext();
326     }
327     
328     public String nextElement()
329     {
330       return iterator.next();
331     }
332     
333   }
334   
335 }
336