org.eclipse.jetty.http.HttpFields Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
//
// ========================================================================
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.http;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.function.BiFunction;
import java.util.function.ToIntFunction;
import java.util.stream.Stream;
import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* HTTP Fields. A collection of HTTP header and or Trailer fields.
*
* This class is not synchronized as it is expected that modifications will only be performed by a
* single thread.
*
*
The cookie handling provided by this class is guided by the Servlet specification and RFC6265.
*
* @deprecated The Eclipse Jetty and Apache Felix Http Jetty packages are no longer supported.
*/
@Deprecated(since = "2021-05-27")
public class HttpFields implements Iterable {
@Deprecated
public static final String __separators = ", \t";
private static final Logger LOG = Log.getLogger(HttpFields.class);
private HttpField[] _fields;
private int _size;
/**
* Initialize an empty HttpFields.
*/
public HttpFields() {
// Based on small sample of Chrome requests.
this(16);
}
/**
* Initialize an empty HttpFields.
*
* @param capacity the capacity of the http fields
*/
public HttpFields(int capacity) {
_fields = new HttpField[capacity];
}
/**
* Initialize HttpFields from copy.
*
* @param fields the fields to copy data from
*/
public HttpFields(HttpFields fields) {
_fields = Arrays.copyOf(fields._fields, fields._fields.length);
_size = fields._size;
}
/**
* Computes a single field for the given HttpHeader and for existing fields with the same header.
*
* The compute function receives the field name and a list of fields with the same name
* so that their values can be used to compute the value of the field that is returned
* by the compute function.
* If the compute function returns {@code null}, the fields with the given name are removed.
* This method comes handy when you want to add an HTTP header if it does not exist,
* or add a value if the HTTP header already exists, similarly to
* {@link Map#compute(Object, BiFunction)}.
*
* This method can be used to {@link #put(HttpField) put} a new field (or blindly replace its value):
*
* httpFields.computeField("X-New-Header",
* (name, fields) -> new HttpField(name, "NewValue"));
*
*
* This method can be used to coalesce many fields into one:
*
* // Input:
* GET / HTTP/1.1
* Host: localhost
* Cookie: foo=1
* Cookie: bar=2,baz=3
* User-Agent: Jetty
*
* // Computation:
* httpFields.computeField("Cookie", (name, fields) ->
* {
* // No cookies, nothing to do.
* if (fields == null)
* return null;
*
* // Coalesces all cookies.
* String coalesced = fields.stream()
* .flatMap(field -> Stream.of(field.getValues()))
* .collect(Collectors.joining(", "));
*
* // Returns a single Cookie header with all cookies.
* return new HttpField(name, coalesced);
* }
*
* // Output:
* GET / HTTP/1.1
* Host: localhost
* Cookie: foo=1, bar=2, baz=3
* User-Agent: Jetty
*
*
* This method can be used to replace a field:
*
* httpFields.computeField("X-Length", (name, fields) ->
* {
* if (fields == null)
* return null;
*
* // Get any value among the X-Length headers.
* String length = fields.stream()
* .map(HttpField::getValue)
* .findAny()
* .orElse("0");
*
* // Replace X-Length headers with X-Capacity header.
* return new HttpField("X-Capacity", length);
* });
*
*
* This method can be used to remove a field:
*
* httpFields.computeField("Connection", (name, fields) -> null);
*
*
* @param header the HTTP header
* @param computeFn the compute function
*/
public void computeField(HttpHeader header, BiFunction, HttpField> computeFn) {
computeField(header, computeFn, (f, h) -> f.getHeader() == h);
}
/**
* Computes a single field for the given HTTP header name and for existing fields with the same name.
*
* @param name the HTTP header name
* @param computeFn the compute function
* @see #computeField(HttpHeader, BiFunction)
*/
public void computeField(String name, BiFunction, HttpField> computeFn) {
computeField(name, computeFn, HttpField::is);
}
private void computeField(T header, BiFunction, HttpField> computeFn, BiFunction matcher) {
// Look for first occurrence
int first = -1;
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (matcher.apply(f, header)) {
first = i;
break;
}
}
// If the header is not found, add a new one;
if (first < 0) {
HttpField newField = computeFn.apply(header, null);
if (newField != null)
add(newField);
return;
}
// Are there any more occurrences?
List found = null;
for (int i = first + 1; i < _size; i++) {
HttpField f = _fields[i];
if (matcher.apply(f, header)) {
if (found == null) {
found = new ArrayList<>();
found.add(_fields[first]);
}
// Remember and remove additional fields
found.add(f);
remove(i--);
}
}
// If no additional fields were found, handle singleton case
if (found == null)
found = Collections.singletonList(_fields[first]);
else
found = Collections.unmodifiableList(found);
HttpField newField = computeFn.apply(header, found);
if (newField == null)
remove(first);
else
_fields[first] = newField;
}
public int size() {
return _size;
}
@Override
public Iterator iterator() {
return new ListItr();
}
public ListIterator listIterator() {
return new ListItr();
}
public Stream stream() {
return Arrays.stream(_fields).limit(_size);
}
/**
* Get Collection of header names.
*
* @return the unique set of field names.
*/
public Set getFieldNamesCollection() {
Set set = null;
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (set == null)
set = new HashSet<>();
set.add(f.getName());
}
return set == null ? Collections.emptySet() : set;
}
/**
* Get enumeration of header _names. Returns an enumeration of strings representing the header
* _names for this request.
*
* @return an enumeration of field names
*/
public Enumeration getFieldNames() {
return Collections.enumeration(getFieldNamesCollection());
}
/**
* Get a Field by index.
*
* @param index the field index
* @return A Field value or null if the Field value has not been set
*/
public HttpField getField(int index) {
if (index >= _size)
throw new NoSuchElementException();
return _fields[index];
}
public HttpField getField(HttpHeader header) {
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.getHeader() == header)
return f;
}
return null;
}
public HttpField getField(String name) {
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.is(name))
return f;
}
return null;
}
public List getFields(HttpHeader header) {
List fields = null;
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.getHeader() == header) {
if (fields == null)
fields = new ArrayList<>();
fields.add(f);
}
}
return fields == null ? Collections.emptyList() : fields;
}
public List getFields(String name) {
List fields = null;
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.is(name)) {
if (fields == null)
fields = new ArrayList<>();
fields.add(f);
}
}
return fields == null ? Collections.emptyList() : fields;
}
public boolean contains(HttpField field) {
for (int i = _size; i-- > 0; ) {
HttpField f = _fields[i];
if (f.isSameName(field) && (f.equals(field) || f.contains(field.getValue())))
return true;
}
return false;
}
public boolean contains(HttpHeader header, String value) {
for (int i = _size; i-- > 0; ) {
HttpField f = _fields[i];
if (f.getHeader() == header && f.contains(value))
return true;
}
return false;
}
public boolean contains(String name, String value) {
for (int i = _size; i-- > 0; ) {
HttpField f = _fields[i];
if (f.is(name) && f.contains(value))
return true;
}
return false;
}
public boolean contains(HttpHeader header) {
for (int i = _size; i-- > 0; ) {
HttpField f = _fields[i];
if (f.getHeader() == header)
return true;
}
return false;
}
public boolean containsKey(String name) {
for (int i = _size; i-- > 0; ) {
HttpField f = _fields[i];
if (f.is(name))
return true;
}
return false;
}
@Deprecated
public String getStringField(HttpHeader header) {
return get(header);
}
public String get(HttpHeader header) {
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.getHeader() == header)
return f.getValue();
}
return null;
}
@Deprecated
public String getStringField(String name) {
return get(name);
}
public String get(String header) {
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.is(header))
return f.getValue();
}
return null;
}
/**
* Get multiple header of the same name
*
* @param header the header
* @return List the values
*/
public List getValuesList(HttpHeader header) {
final List list = new ArrayList<>();
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.getHeader() == header)
list.add(f.getValue());
}
return list;
}
/**
* Get multiple header of the same name
*
* @param name the case-insensitive field name
* @return List the header values
*/
public List getValuesList(String name) {
List list = null;
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.is(name)) {
if (list == null)
list = new ArrayList<>(size() - i);
list.add(f.getValue());
}
}
return list == null ? Collections.emptyList() : list;
}
/**
* Add comma separated values, but only if not already
* present.
*
* @param header The header to add the value(s) to
* @param values The value(s) to add
* @return True if headers were modified
*/
public boolean addCSV(HttpHeader header, String... values) {
QuotedCSV existing = null;
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.getHeader() == header) {
if (existing == null)
existing = new QuotedCSV(false);
existing.addValue(f.getValue());
}
}
String value = addCSV(existing, values);
if (value != null) {
add(header, value);
return true;
}
return false;
}
/**
* Add comma separated values, but only if not already
* present.
*
* @param name The header to add the value(s) to
* @param values The value(s) to add
* @return True if headers were modified
*/
public boolean addCSV(String name, String... values) {
QuotedCSV existing = null;
for (int i = 0; i < _size; i++) {
HttpField f = _fields[i];
if (f.is(name)) {
if (existing == null)
existing = new QuotedCSV(false);
existing.addValue(f.getValue());
}
}
String value = addCSV(existing, values);
if (value != null) {
add(name, value);
return true;
}
return false;
}
protected String addCSV(QuotedCSV existing, String... values) {
// remove any existing values from the new values
boolean add = true;
if (existing != null && !existing.isEmpty()) {
add = false;
for (int i = values.length; i-- > 0; ) {
String unquoted = QuotedCSV.unquote(values[i]);
if (existing.getValues().contains(unquoted))
values[i] = null;
else
add = true;
}
}
if (add) {
StringBuilder value = new StringBuilder();
for (String v : values) {
if (v == null)
continue;
if (value.length() > 0)
value.append(", ");
value.append(v);
}
if (value.length() > 0)
return value.toString();
}
return null;
}
/**
* Get multiple field values of the same name, split
* as a {@link QuotedCSV}
*
* @param header The header
* @param keepQuotes True if the fields are kept quoted
* @return List the values with OWS stripped
*/
public List getCSV(HttpHeader header, boolean keepQuotes) {
QuotedCSV values = null;
for (HttpField f : this) {
if (f.getHeader() == header) {
if (values == null)
values = new QuotedCSV(keepQuotes);
values.addValue(f.getValue());
}
}
return values == null ? Collections.emptyList() : values.getValues();
}
/**
* Get multiple field values of the same name
* as a {@link QuotedCSV}
*
* @param name the case-insensitive field name
* @param keepQuotes True if the fields are kept quoted
* @return List the values with OWS stripped
*/
public List getCSV(String name, boolean keepQuotes) {
QuotedCSV values = null;
for (HttpField f : this) {
if (f.is(name)) {
if (values == null)
values = new QuotedCSV(keepQuotes);
values.addValue(f.getValue());
}
}
return values == null ? Collections.emptyList() : values.getValues();
}
/**
* Get multiple field values of the same name, split and
* sorted as a {@link QuotedQualityCSV}
*
* @param header The header
* @return List the values in quality order with the q param and OWS stripped
*/
public List getQualityCSV(HttpHeader header) {
return getQualityCSV(header, null);
}
/**
* Get multiple field values of the same name, split and
* sorted as a {@link QuotedQualityCSV}
*
* @param header The header
* @param secondaryOrdering Function to apply an ordering other than specified by quality
* @return List the values in quality order with the q param and OWS stripped
*/
public List getQualityCSV(HttpHeader header, ToIntFunction secondaryOrdering) {
QuotedQualityCSV values = null;
for (HttpField f : this) {
if (f.getHeader() == header) {
if (values == null)
values = new QuotedQualityCSV(secondaryOrdering);
values.addValue(f.getValue());
}
}
return values == null ? Collections.emptyList() : values.getValues();
}
/**
* Get multiple field values of the same name, split and
* sorted as a {@link QuotedQualityCSV}
*
* @param name the case-insensitive field name
* @return List the values in quality order with the q param and OWS stripped
*/
public List getQualityCSV(String name) {
QuotedQualityCSV values = null;
for (HttpField f : this) {
if (f.is(name)) {
if (values == null)
values = new QuotedQualityCSV();
values.addValue(f.getValue());
}
}
return values == null ? Collections.emptyList() : values.getValues();
}
/**
* Get multi headers
*
* @param name the case-insensitive field name
* @return Enumeration of the values
*/
public Enumeration getValues(final String name) {
for (int i = 0; i < _size; i++) {
final HttpField f = _fields[i];
if (f.is(name) && f.getValue() != null) {
final int first = i;
return new Enumeration() {
HttpField field = f;
int i = first + 1;
@Override
public boolean hasMoreElements() {
if (field == null) {
while (i < _size) {
field = _fields[i++];
if (field.is(name) && field.getValue() != null)
return true;
}
field = null;
return false;
}
return true;
}
@Override
public String nextElement() throws NoSuchElementException {
if (hasMoreElements()) {
String value = field.getValue();
field = null;
return value;
}
throw new NoSuchElementException();
}
};
}
}
List empty = Collections.emptyList();
return Collections.enumeration(empty);
}
/**
* Get multi field values with separator. The multiple values can be represented as separate
* headers of the same name, or by a single header using the separator(s), or a combination of
* both. Separators may be quoted.
*
* @param name the case-insensitive field name
* @param separators String of separators.
* @return Enumeration of the values, or null if no such header.
*/
@Deprecated
public Enumeration getValues(String name, final String separators) {
final Enumeration e = getValues(name);
if (e == null)
return null;
return new Enumeration() {
QuotedStringTokenizer tok = null;
@Override
public boolean hasMoreElements() {
if (tok != null && tok.hasMoreElements())
return true;
while (e.hasMoreElements()) {
String value = e.nextElement();
if (value != null) {
tok = new QuotedStringTokenizer(value, separators, false, false);
if (tok.hasMoreElements())
return true;
}
}
tok = null;
return false;
}
@Override
public String nextElement() throws NoSuchElementException {
if (!hasMoreElements())
throw new NoSuchElementException();
String next = (String) tok.nextElement();
if (next != null)
next = next.trim();
return next;
}
};
}
public void put(HttpField field) {
boolean put = false;
for (int i = _size; i-- > 0; ) {
HttpField f = _fields[i];
if (f.isSameName(field)) {
if (put) {
_size--;
System.arraycopy(_fields, i + 1, _fields, i, _size - i);
} else {
_fields[i] = field;
put = true;
}
}
}
if (!put)
add(field);
}
/**
* Set a field.
*
* @param name the name of the field
* @param value the value of the field. If null the field is cleared.
*/
public void put(String name, String value) {
if (value == null)
remove(name);
else
put(new HttpField(name, value));
}
public void put(HttpHeader header, HttpHeaderValue value) {
put(header, value.toString());
}
/**
* Set a field.
*
* @param header the header name of the field
* @param value the value of the field. If null the field is cleared.
*/
public void put(HttpHeader header, String value) {
Objects.requireNonNull(header, "header must not be null");
if (value == null)
remove(header);
else
put(new HttpField(header, value));
}
/**
* Set a field.
*
* @param name the name of the field
* @param list the List value of the field. If null the field is cleared.
*/
public void put(String name, List list) {
Objects.requireNonNull(name, "name must not be null");
remove(name);
if (list == null)
return;
for (String v : list) {
if (v != null)
add(name, v);
}
}
/**
* Add to or set a field. If the field is allowed to have multiple values, add will add multiple
* headers of the same name.
*
* @param name the name of the field
* @param value the value of the field.
*/
public void add(String name, String value) {
if (value == null)
return;
HttpField field = new HttpField(name, value);
add(field);
}
public void add(HttpHeader header, HttpHeaderValue value) {
if (value != null)
add(header, value.toString());
}
/**
* Add to or set a field. If the field is allowed to have multiple values, add will add multiple
* headers of the same name.
*
* @param header the header
* @param value the value of the field.
*/
public void add(HttpHeader header, String value) {
Objects.requireNonNull(header, "header must not be null");
if (value == null)
throw new IllegalArgumentException("null value");
HttpField field = new HttpField(header, value);
add(field);
}
/**
* Remove a field.
*
* @param name the field to remove
* @return the header that was removed
*/
public HttpField remove(HttpHeader name) {
HttpField removed = null;
for (int i = _size; i-- > 0; ) {
HttpField f = _fields[i];
if (f.getHeader() == name) {
removed = f;
remove(i);
}
}
return removed;
}
/**
* Remove a field.
*
* @param name the field to remove
* @return the header that was removed
*/
public HttpField remove(String name) {
HttpField removed = null;
for (int i = _size; i-- > 0; ) {
HttpField f = _fields[i];
if (f.is(name)) {
removed = f;
remove(i);
}
}
return removed;
}
private void remove(int i) {
_size--;
System.arraycopy(_fields, i + 1, _fields, i, _size - i);
_fields[_size] = null;
}
/**
* Get a header as an long value. Returns the value of an integer field or -1 if not found. The
* case of the field name is ignored.
*
* @param name the case-insensitive field name
* @return the value of the field as a long
* @throws NumberFormatException If bad long found
*/
public long getLongField(String name) throws NumberFormatException {
HttpField field = getField(name);
return field == null ? -1L : field.getLongValue();
}
/**
* Get a header as a date value. Returns the value of a date field, or -1 if not found. The case
* of the field name is ignored.
*
* @param name the case-insensitive field name
* @return the value of the field as a number of milliseconds since unix epoch
*/
public long getDateField(String name) {
HttpField field = getField(name);
if (field == null)
return -1;
String val = valueParameters(field.getValue(), null);
if (val == null)
return -1;
final long date = DateParser.parseDate(val);
if (date == -1)
throw new IllegalArgumentException("Cannot convert date: " + val);
return date;
}
/**
* Sets the value of an long field.
*
* @param name the field name
* @param value the field long value
*/
public void putLongField(HttpHeader name, long value) {
String v = Long.toString(value);
put(name, v);
}
/**
* Sets the value of an long field.
*
* @param name the field name
* @param value the field long value
*/
public void putLongField(String name, long value) {
String v = Long.toString(value);
put(name, v);
}
/**
* Sets the value of a date field.
*
* @param name the field name
* @param date the field date value
*/
public void putDateField(HttpHeader name, long date) {
String d = DateGenerator.formatDate(date);
put(name, d);
}
/**
* Sets the value of a date field.
*
* @param name the field name
* @param date the field date value
*/
public void putDateField(String name, long date) {
String d = DateGenerator.formatDate(date);
put(name, d);
}
/**
* Sets the value of a date field.
*
* @param name the field name
* @param date the field date value
*/
public void addDateField(String name, long date) {
String d = DateGenerator.formatDate(date);
add(name, d);
}
@Override
public int hashCode() {
int hash = 0;
for (HttpField field : _fields) {
hash += field.hashCode();
}
return hash;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof HttpFields))
return false;
HttpFields that = (HttpFields) o;
// Order is not important, so we cannot rely on List.equals().
if (size() != that.size())
return false;
loop: for (HttpField fi : this) {
for (HttpField fa : that) {
if (fi.equals(fa))
continue loop;
}
return false;
}
return true;
}
@Override
public String toString() {
try {
StringBuilder buffer = new StringBuilder();
for (HttpField field : this) {
if (field != null) {
String tmp = field.getName();
if (tmp != null)
buffer.append(tmp);
buffer.append(": ");
tmp = field.getValue();
if (tmp != null)
buffer.append(tmp);
buffer.append("\r\n");
}
}
buffer.append("\r\n");
return buffer.toString();
} catch (Exception e) {
LOG.warn(e);
return e.toString();
}
}
public void clear() {
_size = 0;
}
public void add(HttpField field) {
if (field != null) {
if (_size == _fields.length)
_fields = Arrays.copyOf(_fields, _size * 2);
_fields[_size++] = field;
}
}
public void addAll(HttpFields fields) {
for (int i = 0; i < fields._size; i++) {
add(fields._fields[i]);
}
}
/**
* Add fields from another HttpFields instance. Single valued fields are replaced, while all
* others are added.
*
* @param fields the fields to add
*/
@Deprecated
public void add(HttpFields fields) {
// TODO this implementation doesn't do what the javadoc says and is really the same
// as addAll, which is renamed to add anyway in 10.
if (fields == null)
return;
Enumeration e = fields.getFieldNames();
while (e.hasMoreElements()) {
String name = e.nextElement();
Enumeration values = fields.getValues(name);
while (values.hasMoreElements()) {
add(name, values.nextElement());
}
}
}
/**
* Get field value without parameters. Some field values can have parameters. This method separates the
* value from the parameters and optionally populates a map with the parameters. For example:
*
*
*
* FieldName : Value ; param1=val1 ; param2=val2
*
*
*
* @param value The Field value, possibly with parameters.
* @return The value.
*/
public static String stripParameters(String value) {
if (value == null)
return null;
int i = value.indexOf(';');
if (i < 0)
return value;
return value.substring(0, i).trim();
}
/**
* Get field value parameters. Some field values can have parameters. This method separates the
* value from the parameters and optionally populates a map with the parameters. For example:
*
*
*
* FieldName : Value ; param1=val1 ; param2=val2
*
*
*
* @param value The Field value, possibly with parameters.
* @param parameters A map to populate with the parameters, or null
* @return The value.
*/
public static String valueParameters(String value, Map parameters) {
if (value == null)
return null;
int i = value.indexOf(';');
if (i < 0)
return value;
if (parameters == null)
return value.substring(0, i).trim();
StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true);
while (tok1.hasMoreTokens()) {
String token = tok1.nextToken();
StringTokenizer tok2 = new QuotedStringTokenizer(token, "= ");
if (tok2.hasMoreTokens()) {
String paramName = tok2.nextToken();
String paramVal = null;
if (tok2.hasMoreTokens())
paramVal = tok2.nextToken();
parameters.put(paramName, paramVal);
}
}
return value.substring(0, i).trim();
}
@Deprecated
private static final Float __one = new Float("1.0");
@Deprecated
private static final Float __zero = new Float("0.0");
@Deprecated
private static final Trie __qualities = new ArrayTernaryTrie<>();
static {
__qualities.put("*", __one);
__qualities.put("1.0", __one);
__qualities.put("1", __one);
__qualities.put("0.9", new Float("0.9"));
__qualities.put("0.8", new Float("0.8"));
__qualities.put("0.7", new Float("0.7"));
__qualities.put("0.66", new Float("0.66"));
__qualities.put("0.6", new Float("0.6"));
__qualities.put("0.5", new Float("0.5"));
__qualities.put("0.4", new Float("0.4"));
__qualities.put("0.33", new Float("0.33"));
__qualities.put("0.3", new Float("0.3"));
__qualities.put("0.2", new Float("0.2"));
__qualities.put("0.1", new Float("0.1"));
__qualities.put("0", __zero);
__qualities.put("0.0", __zero);
}
@Deprecated
public static Float getQuality(String value) {
if (value == null)
return __zero;
int qe = value.indexOf(";");
if (qe++ < 0 || qe == value.length())
return __one;
if (value.charAt(qe++) == 'q') {
qe++;
Float q = __qualities.get(value, qe, value.length() - qe);
if (q != null)
return q;
}
Map params = new HashMap<>(4);
valueParameters(value, params);
String qs = params.get("q");
if (qs == null)
qs = "*";
Float q = __qualities.get(qs);
if (q == null) {
try {
q = new Float(qs);
} catch (Exception e) {
q = __one;
}
}
return q;
}
/**
* List values in quality order.
*
* @param e Enumeration of values with quality parameters
* @return values in quality order.
*/
@Deprecated
public static List qualityList(Enumeration e) {
if (e == null || !e.hasMoreElements())
return Collections.emptyList();
QuotedQualityCSV values = new QuotedQualityCSV();
while (e.hasMoreElements()) {
values.addValue(e.nextElement());
}
return values.getValues();
}
// @deprecated The Eclipse Jetty and Apache Felix Http Jetty packages are no longer supported.
@Deprecated(since = "2021-05-27")
private class ListItr implements ListIterator {
// index of next element to return
int _cursor;
int _current = -1;
@Override
public boolean hasNext() {
return _cursor != _size;
}
@Override
public HttpField next() {
if (_cursor == _size)
throw new NoSuchElementException();
_current = _cursor++;
return _fields[_current];
}
@Override
public void remove() {
if (_current < 0)
throw new IllegalStateException();
HttpFields.this.remove(_current);
_fields[_size] = null;
_cursor = _current;
_current = -1;
}
@Override
public boolean hasPrevious() {
return _cursor > 0;
}
@Override
public HttpField previous() {
if (_cursor == 0)
throw new NoSuchElementException();
_current = --_cursor;
return _fields[_current];
}
@Override
public int nextIndex() {
return _cursor;
}
@Override
public int previousIndex() {
return _cursor - 1;
}
@Override
public void set(HttpField field) {
if (_current < 0)
throw new IllegalStateException();
if (field == null)
remove();
else
_fields[_current] = field;
}
@Override
public void add(HttpField field) {
if (field != null) {
_fields = Arrays.copyOf(_fields, _fields.length + 1);
System.arraycopy(_fields, _cursor, _fields, _cursor + 1, _size - _cursor);
_fields[_cursor++] = field;
_size++;
_current = -1;
}
}
}
}