001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020 package javax.activation;
021
022 import java.util.Collections;
023 import java.util.Enumeration;
024 import java.util.HashMap;
025 import java.util.Iterator;
026 import java.util.Map;
027
028
029 /**
030 * @version $Rev: 467742 $ $Date: 2006-10-25 21:30:38 +0200 (Wed, 25 Oct 2006) $
031 */
032 public class MimeTypeParameterList {
033
034 private final Map params = new HashMap();
035
036 public MimeTypeParameterList() {
037 }
038
039 public MimeTypeParameterList(String parameterList) throws MimeTypeParseException {
040 parse(parameterList);
041 }
042
043 protected void parse(String parameterList) throws MimeTypeParseException {
044 if (parameterList == null) {
045 throw new MimeTypeParseException("parameterList is null");
046 }
047
048 RFC2045Parser parser = new RFC2045Parser(parameterList);
049 while (parser.hasMoreParams()) {
050 String attribute = parser.expectAttribute();
051 parser.expectEquals();
052 String value = parser.expectValue();
053 params.put(attribute.toLowerCase(), value);
054 }
055 }
056
057 public int size() {
058 return params.size();
059 }
060
061 public boolean isEmpty() {
062 return params.isEmpty();
063 }
064
065 public String get(String name) {
066 return (String) params.get(name.toLowerCase());
067 }
068
069 public void set(String name, String value) {
070 params.put(name.toLowerCase(), value);
071 }
072
073 public void remove(String name) {
074 params.remove(name.toLowerCase());
075 }
076
077 public Enumeration getNames() {
078 return Collections.enumeration(params.keySet());
079 }
080
081 /**
082 * String representation of this parameter list.
083 *
084 * @return
085 */
086 public String toString() {
087 StringBuffer buf = new StringBuffer(params.size() << 4);
088 for (Iterator i = params.entrySet().iterator(); i.hasNext();) {
089 Map.Entry entry = (Map.Entry) i.next();
090 buf.append("; ").append(entry.getKey()).append('=');
091 quote(buf, (String) entry.getValue());
092 }
093 return buf.toString();
094 }
095
096 private void quote(StringBuffer buf, String value) {
097 int length = value.length();
098 boolean quote = false;
099 for (int i = 0; i < length; i++) {
100 if (MimeType.isSpecial(value.charAt(i))) {
101 quote = true;
102 break;
103 }
104 }
105 if (quote) {
106 buf.append('"');
107 for (int i = 0; i < length; i++) {
108 char c = value.charAt(i);
109 if (c == '\\' || c == '"') {
110 buf.append('\\');
111 }
112 buf.append(c);
113 }
114 buf.append('"');
115 } else {
116 buf.append(value);
117 }
118 }
119
120 private static class RFC2045Parser {
121 private final String text;
122 private int index = 0;
123
124 private RFC2045Parser(String text) {
125 this.text = text;
126 }
127
128 /**
129 * Look the next ";" to start a parameter (skipping whitespace)
130 *
131 * @return
132 */
133 private boolean hasMoreParams() throws MimeTypeParseException {
134 char c;
135 do {
136 if (index == text.length()) {
137 return false;
138 }
139 c = text.charAt(index++);
140 } while (Character.isWhitespace(c));
141 if (c != ';') {
142 throw new MimeTypeParseException("Expected \";\" at " + (index - 1) + " in " + text);
143 }
144 return true;
145 }
146
147 private String expectAttribute() throws MimeTypeParseException {
148 char c;
149 do {
150 if (index == text.length()) {
151 throw new MimeTypeParseException("Expected attribute at " + (index - 1) + " in " + text);
152 }
153 c = text.charAt(index++);
154 } while (Character.isWhitespace(c));
155 int start = index - 1;
156 while (index != text.length() && !MimeType.isSpecial(text.charAt(index))) {
157 index += 1;
158 }
159 return text.substring(start, index);
160 }
161
162 private void expectEquals() throws MimeTypeParseException {
163 char c;
164 do {
165 if (index == text.length()) {
166 throw new MimeTypeParseException("Expected \"=\" at " + (index - 1) + " in " + text);
167 }
168 c = text.charAt(index++);
169 } while (Character.isWhitespace(c));
170 if (c != '=') {
171 throw new MimeTypeParseException("Expected \"=\" at " + (index - 1) + " in " + text);
172 }
173 }
174
175 private String expectValue() throws MimeTypeParseException {
176 char c;
177 do {
178 if (index == text.length()) {
179 throw new MimeTypeParseException("Expected value at " + (index - 1) + " in " + text);
180 }
181 c = text.charAt(index++);
182 } while (Character.isWhitespace(c));
183 if (c == '"') {
184 // quoted-string
185 StringBuffer buf = new StringBuffer();
186 while (true) {
187 if (index == text.length()) {
188 throw new MimeTypeParseException("Expected closing quote at " + (index - 1) + " in " + text);
189 }
190 c = text.charAt(index++);
191 if (c == '"') {
192 break;
193 }
194 if (c == '\\') {
195 if (index == text.length()) {
196 throw new MimeTypeParseException("Expected escaped char at " + (index - 1) + " in " + text);
197 }
198 c = text.charAt(index++);
199 }
200 buf.append(c);
201 }
202 return buf.toString();
203 } else {
204 // token
205 int start = index - 1;
206 while (index != text.length() && !MimeType.isSpecial(text.charAt(index))) {
207 index += 1;
208 }
209 return text.substring(start, index);
210 }
211 }
212 }
213 }