public static ContentDisposition parse(String contentDisposition) {
        List<String> parts = tokenize(contentDisposition);
        String type = parts.get(0);
        String name = null;
        String filename = null;
        Charset charset = null;
        Long size = null;
        ZonedDateTime creationDate = null;
        ZonedDateTime modificationDate = null;
        ZonedDateTime readDate = null;
        for (int i = 1; i < parts.size(); i++) {
            String part = parts.get(i);
            int eqIndex = part.indexOf('=');
            if (eqIndex != -1) {
                String attribute = part.substring(0, eqIndex);
                String value = (part.startsWith("\"", eqIndex + 1) && part.endsWith("\"") ?
                                     part.substring(eqIndex + 2, part.length() - 1) :
                                                                                         part.substring(eqIndex + 1));
                if (attribute.equals("name") ) {
                    name = value;
                }
                else if (attribute.equals("filename*") ) {
                    int idx1 = value.indexOf('\'');
                    int idx2 = value.indexOf('\'', idx1 + 1);
                    if (idx1 != -1 && idx2 != -1) {
                        charset = Charset.forName(value.substring(0, idx1).trim());
                        Preconditions.checkArgument(UTF_8.equals(charset) || ISO_8859_1.equals(charset),
                             "Charset should be UTF-8 or ISO-8859-1");
                        filename = decodeFilename(value.substring(idx2 + 1), charset);
                    }
                    else {
                        // US ASCII
                        filename = decodeFilename(value, StandardCharsets.US_ASCII);
                    }
                }
                else if (attribute.equals("filename") && (filename == null)) {
                    if (value.startsWith("=?") ) {
                        Matcher matcher = BASE64_ENCODED_PATTERN.matcher(value);
                        if (matcher.find()) {
                            String match1 = matcher.group(1);
                            String match2 = matcher.group(2);
                            filename = new String(Base64.getDecoder().decode(match2), Charset.forName(match1));
                        }
                        else {
                            filename = value;
                        }
                    }
                    else {
                        filename = value;
                    }
                }
                else if (attribute.equals("size") ) {
                    size = Long.parseLong(value);
                }
                else if (attribute.equals("creation-date")) {
                    try {
                        creationDate = ZonedDateTime.parse(value, RFC_1123_DATE_TIME);
                    }
                    catch (DateTimeParseException ex) {
                        // ignore
                    }
                }
                else if (attribute.equals("modification-date")) {
                    try {
                        modificationDate = ZonedDateTime.parse(value, RFC_1123_DATE_TIME);
                    }
                    catch (DateTimeParseException ex) {
                        // ignore
                    }
                }
                else if (attribute.equals("read-date")) {
                    try {
                        readDate = ZonedDateTime.parse(value, RFC_1123_DATE_TIME);
                    }
                    catch (DateTimeParseException ex) {
                        // ignore
                    }
                }
            }
            else {
                throw new IllegalArgumentException("Invalid content disposition format");
            }
        }
        return new ContentDisposition(type, name, filename, charset, size, creationDate, modificationDate, readDate);
    }
Parse a {@literal Content-Disposition} header value as defined in RFC 2183.
@param contentDisposition the {@literal Content-Disposition} header value
@return the parsed content disposition
@see #toString()
manager/api/rest-impl/src/main/java/io/apiman/manager/api/rest/impl/util/ContentDisposition.java