/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * 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 myjava.awt.datatransfer; import java.io.Serializable; import java.util.Enumeration; import java.util.Hashtable; final class MimeTypeProcessor { private static MimeTypeProcessor instance; private MimeTypeProcessor() { super(); } static MimeType parse(String str) { MimeType res; if (instance == null) { instance = new MimeTypeProcessor(); } res = new MimeType(); if (str != null) { StringPosition pos = new StringPosition(); retrieveType(str, res, pos); retrieveParams(str, res, pos); } return res; } static String assemble(MimeType type) { StringBuilder buf = new StringBuilder(); buf.append(type.getFullType()); for (Enumeration<String> keys = type.parameters.keys(); keys.hasMoreElements();) { String name = keys.nextElement(); String value = type.parameters.get(name); buf.append("; "); //$NON-NLS-1$ buf.append(name); buf.append("=\""); //$NON-NLS-1$ buf.append(value); buf.append('"'); } return buf.toString(); } private static void retrieveType(String str, MimeType res, StringPosition pos) { res.primaryType = retrieveToken(str, pos).toLowerCase(); pos.i = getNextMeaningfulIndex(str, pos.i); if ((pos.i >= str.length()) || (str.charAt(pos.i) != '/')) { throw new IllegalArgumentException(); } pos.i++; res.subType = retrieveToken(str, pos).toLowerCase(); } private static void retrieveParams(String str, MimeType res, StringPosition pos) { res.parameters = new Hashtable<String, String>(); res.systemParameters = new Hashtable<String, Object>(); do { pos.i = getNextMeaningfulIndex(str, pos.i); if (pos.i >= str.length()) { return; } if (str.charAt(pos.i) != ';') { throw new IllegalArgumentException(); } pos.i++; retrieveParam(str, res, pos); } while (true); } private static void retrieveParam(String str, MimeType res, StringPosition pos) { String name = retrieveToken(str, pos).toLowerCase(); pos.i = getNextMeaningfulIndex(str, pos.i); if ((pos.i >= str.length()) || (str.charAt(pos.i) != '=')) { throw new IllegalArgumentException(); } pos.i++; pos.i = getNextMeaningfulIndex(str, pos.i); if ((pos.i >= str.length())) { throw new IllegalArgumentException(); } String value; if (str.charAt(pos.i) == '"') { value = retrieveQuoted(str, pos); } else { value = retrieveToken(str, pos); } res.parameters.put(name, value); } private static String retrieveQuoted(String str, StringPosition pos) { StringBuilder buf = new StringBuilder(); boolean check = true; pos.i++; while ((str.charAt(pos.i) != '"') || !check) { char c = str.charAt(pos.i++); if (!check) { check = true; } else if (c == '\\') { check = false; } if (check) { buf.append(c); } if (pos.i == str.length()) { throw new IllegalArgumentException(); } } pos.i++; return buf.toString(); } private static String retrieveToken(String str, StringPosition pos) { StringBuilder buf = new StringBuilder(); pos.i = getNextMeaningfulIndex(str, pos.i); if ((pos.i >= str.length()) || isTSpecialChar(str.charAt(pos.i))) { throw new IllegalArgumentException(); } do { buf.append(str.charAt(pos.i++)); } while ((pos.i < str.length()) && isMeaningfulChar(str.charAt(pos.i)) && !isTSpecialChar(str.charAt(pos.i))); return buf.toString(); } private static int getNextMeaningfulIndex(String str, int i) { while ((i < str.length()) && !isMeaningfulChar(str.charAt(i))) { i++; } return i; } private static boolean isTSpecialChar(char c) { return ((c == '(') || (c == ')') || (c == '[') || (c == ']') || (c == '<') || (c == '>') || (c == '@') || (c == ',') || (c == ';') || (c == ':') || (c == '\\') || (c == '\"') || (c == '/') || (c == '?') || (c == '=')); } private static boolean isMeaningfulChar(char c) { return ((c >= '!') && (c <= '~')); } private static final class StringPosition { int i = 0; } static final class MimeType implements Cloneable, Serializable { private static final long serialVersionUID = -6693571907475992044L; private String primaryType; private String subType; private Hashtable<String, String> parameters; private Hashtable<String, Object> systemParameters; MimeType() { primaryType = null; subType = null; parameters = null; systemParameters = null; } MimeType(String primaryType, String subType) { this.primaryType = primaryType; this.subType = subType; parameters = new Hashtable<String, String>(); systemParameters = new Hashtable<String, Object>(); } boolean equals(MimeType that) { if (that == null) { return false; } return getFullType().equals(that.getFullType()); } String getPrimaryType() { return primaryType; } String getSubType() { return subType; } String getFullType() { return (primaryType + "/" + subType); //$NON-NLS-1$ } String getParameter(String name) { return parameters.get(name); } void addParameter(String name, String value) { if (value == null) { return; } if ((value.charAt(0) == '\"') && (value.charAt(value.length() - 1) == '\"')) { value = value.substring(1, value.length() - 2); } if (value.length() == 0) { return; } parameters.put(name, value); } void removeParameter(String name) { parameters.remove(name); } Object getSystemParameter(String name) { return systemParameters.get(name); } void addSystemParameter(String name, Object value) { systemParameters.put(name, value); } @SuppressWarnings("unchecked") @Override public Object clone() { MimeType clone = new MimeType(primaryType, subType); clone.parameters = (Hashtable<String, String>)parameters.clone(); clone.systemParameters = (Hashtable<String, Object>)systemParameters.clone(); return clone; } } }