![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.james.imap.decode.FetchPartPathDecoder Maven / Gradle / Ivy
/****************************************************************
* 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 org.apache.james.imap.decode;
import java.util.ArrayList;
import java.util.List;
import org.apache.james.imap.api.display.HumanReadableText;
import org.apache.james.imap.api.message.SectionType;
public class FetchPartPathDecoder {
/**
* Going to need to make one array copy so might as well ensure plenty of
* space
*/
private static final int ARRAY_INCREMENT = 20;
/** Embedded RFC882 messages are rare so start size one array */
private static final int ARRAY_INITIAL_SIZE = 1;
private SectionType sectionType;
private int[] path;
private int partial;
private int used;
private List names;
public FetchPartPathDecoder() {
}
public SectionType decode(CharSequence sectionSpecification) throws DecodingException {
init();
sectionType = decode(0, sectionSpecification);
prunePath();
return sectionType;
}
private void prunePath() {
if (path != null) {
int length = path.length;
if (used < length) {
int[] newPath = new int[used];
System.arraycopy(path, 0, newPath, 0, used);
path = newPath;
}
}
}
private SectionType decode(int at, CharSequence sectionSpecification) throws DecodingException {
SectionType result;
int length = sectionSpecification.length();
if (at < length) {
final char next = sectionSpecification.charAt(at);
switch (next) {
case '.':
separator();
result = decode(at + 1, sectionSpecification);
break;
case '0':
result = digit(at, sectionSpecification, 0);
break;
case '1':
result = digit(at, sectionSpecification, 1);
break;
case '2':
result = digit(at, sectionSpecification, 2);
break;
case '3':
result = digit(at, sectionSpecification, 3);
break;
case '4':
result = digit(at, sectionSpecification, 4);
break;
case '5':
result = digit(at, sectionSpecification, 5);
break;
case '6':
result = digit(at, sectionSpecification, 6);
break;
case '7':
result = digit(at, sectionSpecification, 7);
break;
case '8':
result = digit(at, sectionSpecification, 8);
break;
case '9':
result = digit(at, sectionSpecification, 9);
break;
case 't':
case 'T':
result = text(at, sectionSpecification);
break;
case 'h':
case 'H':
result = header(at, sectionSpecification);
break;
case 'm':
case 'M':
result = mime(at, sectionSpecification);
break;
default:
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Did not expect '" + next + "' here in body specification.");
}
} else {
storePartial();
result = SectionType.CONTENT;
}
return result;
}
private SectionType mime(int at, CharSequence sectionSpecification) throws DecodingException {
if (sectionSpecification.length() == at + 4) {
mustBeI(sectionSpecification, at + 1);
mustBeM(sectionSpecification, at + 2);
mustBeE(sectionSpecification, at + 3);
storePartial();
} else {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
return SectionType.MIME;
}
private void mustBeI(CharSequence sectionSpecification, int position) throws DecodingException {
char i = sectionSpecification.charAt(position);
if (!(i == 'i' || i == 'I')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeM(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'm' || next == 'M')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeN(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'n' || next == 'N')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeO(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'o' || next == 'O')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeE(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'e' || next == 'E')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeA(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'a' || next == 'A')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeD(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'd' || next == 'D')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeR(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'r' || next == 'R')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeX(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'x' || next == 'X')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeT(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 't' || next == 'T')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeF(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'f' || next == 'F')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeL(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 'l' || next == 'L')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeS(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == 's' || next == 'S')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeDot(CharSequence sectionSpecification, int position) throws DecodingException {
char next = sectionSpecification.charAt(position);
if (!(next == '.')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private void mustBeOpenParen(CharSequence sectionSpecification, int position) throws DecodingException {
if (position >= sectionSpecification.length()) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
char next = sectionSpecification.charAt(position);
if (!(next == '(')) {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
}
private SectionType header(int at, CharSequence sectionSpecification) throws DecodingException {
SectionType result;
int length = sectionSpecification.length();
if (length > at + 5) {
mustBeE(sectionSpecification, at + 1);
mustBeA(sectionSpecification, at + 2);
mustBeD(sectionSpecification, at + 3);
mustBeE(sectionSpecification, at + 4);
mustBeR(sectionSpecification, at + 5);
storePartial();
if (length == at + 6) {
result = SectionType.HEADER;
} else {
result = headerFields(at + 6, sectionSpecification);
}
} else {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
return result;
}
private SectionType headerFields(int at, CharSequence sectionSpecification) throws DecodingException {
SectionType result;
int length = sectionSpecification.length();
if (length > at + 7) {
mustBeDot(sectionSpecification, at);
mustBeF(sectionSpecification, at + 1);
mustBeI(sectionSpecification, at + 2);
mustBeE(sectionSpecification, at + 3);
mustBeL(sectionSpecification, at + 4);
mustBeD(sectionSpecification, at + 5);
mustBeS(sectionSpecification, at + 6);
char next = sectionSpecification.charAt(at + 7);
int namesStartAt;
switch (next) {
case ' ':
result = SectionType.HEADER_FIELDS;
namesStartAt = skipSpaces(at + 7, sectionSpecification);
break;
case '.':
if (length > at + 10) {
mustBeN(sectionSpecification, at + 8);
mustBeO(sectionSpecification, at + 9);
mustBeT(sectionSpecification, at + 10);
result = SectionType.HEADER_NOT_FIELDS;
namesStartAt = skipSpaces(at + 11, sectionSpecification);
} else {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
break;
default:
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
mustBeOpenParen(sectionSpecification, namesStartAt);
readHeaderNames(namesStartAt + 1, sectionSpecification);
} else {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
return result;
}
private void readHeaderNames(int at, CharSequence sectionSpecification) throws DecodingException {
names = new ArrayList<>();
int firstWordStart = skipSpaces(at, sectionSpecification);
readHeaderNames(firstWordStart, firstWordStart, sectionSpecification);
}
private void readHeaderNames(int at, int lastWordStart, CharSequence sectionSpecification) throws DecodingException {
while (at < sectionSpecification.length()) {
final char next = sectionSpecification.charAt(at);
switch (next) {
case ' ':
readName(lastWordStart, at, sectionSpecification);
int nextWord = skipSpaces(at, sectionSpecification);
at = nextWord;
lastWordStart = nextWord;
break;
case ')':
readName(lastWordStart, at, sectionSpecification);
return;
default:
at = at + 1;
}
}
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Closing parenthesis missing.");
}
private void readName(int wordStart, int wordFinish, CharSequence sectionSpecification) {
if (wordStart <= wordFinish) {
CharSequence word = sectionSpecification.subSequence(wordStart, wordFinish);
String name = word.toString();
names.add(name);
}
}
private int skipSpaces(int at, CharSequence sectionSpecification) {
int result;
if (at < sectionSpecification.length()) {
char next = sectionSpecification.charAt(at);
if (next == ' ') {
result = skipSpaces(at + 1, sectionSpecification);
} else {
result = at;
}
} else {
result = at;
}
return result;
}
private SectionType text(int at, CharSequence sectionSpecification) throws DecodingException {
if (sectionSpecification.length() == at + 4) {
mustBeE(sectionSpecification, at + 1);
mustBeX(sectionSpecification, at + 2);
mustBeT(sectionSpecification, at + 3);
storePartial();
} else {
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Unknown body specification");
}
return SectionType.TEXT;
}
private SectionType digit(int at, CharSequence sectionSpecification, int digit) throws DecodingException {
digit(digit);
return decode(at + 1, sectionSpecification);
}
private void init() {
sectionType = SectionType.CONTENT;
resetPartial();
path = null;
used = 0;
names = null;
}
private void resetPartial() {
partial = 0;
}
private void separator() {
storePartial();
}
private void storePartial() {
if (partial > 0) {
ensureSpaceForOneInPath();
path[used++] = partial;
resetPartial();
}
}
private void ensureSpaceForOneInPath() {
if (path == null) {
path = new int[ARRAY_INITIAL_SIZE];
} else {
int length = path.length;
if (used >= length) {
int[] newPath = new int[length + ARRAY_INCREMENT];
System.arraycopy(path, 0, newPath, 0, length);
path = newPath;
}
}
}
private void digit(int digit) {
partial = (partial * 10) + digit;
}
/**
* Gets the decoded path.
*
* @return the path
*/
public final int[] getPath() {
return path;
}
/**
* Gets the{@link SectionType}
*/
public final SectionType getSpecifier() {
return sectionType;
}
/**
* Gets field names.
*
* @return List
of String
names when
* {@link SectionType#HEADER_FIELDS} or {@link SectionType#HEADER_NOT_FIELDS}, null
* otherwise
*/
public final List getNames() {
return names;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy