/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eclipse.webdav.http.client;
import java.util.Enumeration;
import java.util.Hashtable;
import org.eclipse.webdav.client.Policy;
import org.eclipse.webdav.internal.kernel.utils.Assert;
/**
* Parses an HTTP Content-Type entity-header field. See section 14.18 of
* RFC2068 for more information on this field.
* <p>
* <b>Note:</b> This class/interface is part of an interim API that is still under
* development and expected to change significantly before reaching stability.
* It is being made available at this early stage to solicit feedback from pioneering
* adopters on the understanding that any code that uses this API will almost
* certainly be broken (repeatedly) as the API evolves.
* </p>
*/
public class ContentType {
private String contentType;
private int position;
private boolean foundDelim;
private String type;
private String subtype;
private Hashtable parameters = new Hashtable(5);
/**
* Parses the given HTTP Content-Type entity-header field. For example,
* if the content type is "text/xml; charset="ISO-8859-4"" the type is
* "text", the subtype is "xml", and the value of the attribute "charset"
* is "ISO-8859-4".
*
* @param contentType the value of the content type field to parse
* @throws IllegalArgumentException if the content type is
* malformed
*/
public ContentType(String contentType) throws IllegalArgumentException {
Assert.isNotNull(contentType);
this.contentType = contentType;
position = 0;
parse();
}
private void checkPosition() throws IllegalArgumentException {
if (position >= contentType.length())
illegalArgument();
}
/**
* Returns an <code>Enumeration</code> of this content type's attributes.
* For example, if the content type is "text/xml; charset="ISO-8859-4"",
* it has one attribute namely, "charset".
*
* @return an <code>Enumeration</code> of <code>String</code>s
*/
public Enumeration getAttributes() {
return parameters.keys();
}
/**
* Returns this content type's subtype. For example, if the content type
* is "text/xml; charset="ISO-8859-4"", the the subtype is "xml".
*
* @return this content type's subtype
*/
public String getSubtype() {
return subtype;
}
/**
* Returns this content type's type. For example, if the content type is
* "text/xml; charset="ISO-8859-4"", the the type is "text".
*
* @return this content type's type
*/
public String getType() {
return type;
}
/**
* Returns the value of the given attribute for this content type. For
* example, if the content type is "text/xml; charset="ISO-8859-4"", then
* the value for the attribute "charset" is "IS-8859-4".
*
* @return the value of the given attribute for this content type
*/
public String getValue(String attribute) {
return (String) parameters.get(attribute);
}
private void illegalArgument() throws IllegalArgumentException {
throw new IllegalArgumentException(Policy.bind("exception.malformedContentType", contentType)); //$NON-NLS-1$
}
private String nextToken(char delim, boolean trim) throws IllegalArgumentException {
int start = position;
int end = start;
boolean done = false;
boolean trimming = false;
while (!done) {
if (position == contentType.length()) {
done = true;
foundDelim = false;
} else {
char c = contentType.charAt(position);
if (Character.isWhitespace(c)) {
if (trim) {
trimming = true;
} else {
illegalArgument();
}
} else {
if (c == delim) {
done = true;
foundDelim = true;
} else {
if (trimming) {
illegalArgument();
}
end = position + 1;
}
}
++position;
}
}
return contentType.substring(start, end);
}
private void parse() throws IllegalArgumentException {
checkPosition();
skipWhiteSpace();
checkPosition();
type = nextToken('/', false);
checkPosition();
subtype = nextToken(';', true);
skipWhiteSpace();
if (foundDelim) {
checkPosition();
}
while (position < contentType.length()) {
String attribute = nextToken('=', false);
checkPosition();
String value = nextToken(';', true);
if (value.startsWith("\"") && value.endsWith("\"")) { //$NON-NLS-1$ //$NON-NLS-2$
value = value.substring(1, value.length() - 1);
}
skipWhiteSpace();
if (foundDelim) {
checkPosition();
}
parameters.put(attribute, value);
}
}
private void skipWhiteSpace() {
while (position < contentType.length() && Character.isWhitespace(contentType.charAt(position))) {
++position;
}
}
}