1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http.message;
29
30 import java.util.ArrayList;
31 import java.util.List;
32
33 import org.apache.hc.core5.annotation.Contract;
34 import org.apache.hc.core5.annotation.ThreadingBehavior;
35 import org.apache.hc.core5.http.HeaderElement;
36 import org.apache.hc.core5.http.NameValuePair;
37 import org.apache.hc.core5.util.Args;
38 import org.apache.hc.core5.util.Tokenizer;
39
40
41
42
43
44
45 @Contract(threading = ThreadingBehavior.IMMUTABLE)
46 public class BasicHeaderValueParser implements HeaderValueParser {
47
48 public final static BasicHeaderValueParser INSTANCE = new BasicHeaderValueParser();
49
50 private final static char PARAM_DELIMITER = ';';
51 private final static char ELEM_DELIMITER = ',';
52
53 private static final Tokenizer.Delimiter TOKEN_DELIMITER = Tokenizer.delimiters('=', PARAM_DELIMITER, ELEM_DELIMITER);
54 private static final Tokenizer.Delimiter VALUE_DELIMITER = Tokenizer.delimiters(PARAM_DELIMITER, ELEM_DELIMITER);
55
56 private final Tokenizer tokenizer;
57
58 public BasicHeaderValueParser() {
59 this.tokenizer = Tokenizer.INSTANCE;
60 }
61
62
63
64
65 private static final HeaderElement[] EMPTY_HEADER_ELEMENT_ARRAY = {};
66
67
68
69
70 private static final NameValuePair[] EMPTY_NAME_VALUE_ARRAY = {};
71
72 @Override
73 public HeaderElement[] parseElements(final CharSequence buffer, final ParserCursor cursor) {
74 Args.notNull(buffer, "Char sequence");
75 Args.notNull(cursor, "Parser cursor");
76 final List<HeaderElement> elements = new ArrayList<>();
77 while (!cursor.atEnd()) {
78 final HeaderElement element = parseHeaderElement(buffer, cursor);
79 if (!(element.getName().isEmpty() && element.getValue() == null)) {
80 elements.add(element);
81 }
82 }
83 return elements.toArray(EMPTY_HEADER_ELEMENT_ARRAY);
84 }
85
86 @Override
87 public HeaderElement parseHeaderElement(final CharSequence buffer, final ParserCursor cursor) {
88 Args.notNull(buffer, "Char sequence");
89 Args.notNull(cursor, "Parser cursor");
90 final NameValuePair nvp = parseNameValuePair(buffer, cursor);
91 NameValuePair[] params = null;
92 if (!cursor.atEnd()) {
93 final char ch = buffer.charAt(cursor.getPos());
94 if (ch == PARAM_DELIMITER || ch == ELEM_DELIMITER) {
95 cursor.updatePos(cursor.getPos() + 1);
96 }
97 if (ch != ELEM_DELIMITER) {
98 params = parseParameters(buffer, cursor);
99 }
100 }
101 return new BasicHeaderElement(nvp.getName(), nvp.getValue(), params);
102 }
103
104 @Override
105 public NameValuePair[] parseParameters(final CharSequence buffer, final ParserCursor cursor) {
106 Args.notNull(buffer, "Char sequence");
107 Args.notNull(cursor, "Parser cursor");
108 tokenizer.skipWhiteSpace(buffer, cursor);
109 final List<NameValuePair> params = new ArrayList<>();
110 while (!cursor.atEnd()) {
111 final NameValuePair param = parseNameValuePair(buffer, cursor);
112 params.add(param);
113 if (!cursor.atEnd()) {
114 final char ch = buffer.charAt(cursor.getPos());
115 if (ch == PARAM_DELIMITER) {
116 cursor.updatePos(cursor.getPos() + 1);
117 }
118 if (ch == ELEM_DELIMITER) {
119 break;
120 }
121 }
122 }
123 return params.toArray(EMPTY_NAME_VALUE_ARRAY);
124 }
125
126 @Override
127 public NameValuePair parseNameValuePair(final CharSequence buffer, final ParserCursor cursor) {
128 Args.notNull(buffer, "Char sequence");
129 Args.notNull(cursor, "Parser cursor");
130
131 final String name = tokenizer.parseToken(buffer, cursor, TOKEN_DELIMITER);
132 if (cursor.atEnd()) {
133 return new BasicNameValuePair(name, null);
134 }
135 final char delim = buffer.charAt(cursor.getPos());
136 if (delim != '=') {
137 return new BasicNameValuePair(name, null);
138 }
139 cursor.updatePos(cursor.getPos() + 1);
140 final String value = tokenizer.parseValue(buffer, cursor, VALUE_DELIMITER);
141 return new BasicNameValuePair(name, value);
142 }
143
144 }
145