=0)
- {
- if (param<__zeroquality.length())
- param=Character.toLowerCase(c)==__zeroquality.charAt(param)?(param+1):-1;
- else if (c!='0'&&c!='.')
- param=-1;
- }
-
- }
- break;
-
- default:
- throw new IllegalStateException();
- }
- }
-
- return param!=__zeroquality.length() && match==search.length();
- }
-
-
- @Override
- public String toString()
- {
- String v=getValue();
- return getName() + ": " + (v==null?"":v);
- }
-
- public boolean isSameName(HttpField field)
- {
- if (field==null)
- return false;
- if (field==this)
- return true;
- if (_header!=null && _header==field.getHeader())
- return true;
- if (_name.equalsIgnoreCase(field.getName()))
- return true;
- return false;
- }
-
- private int nameHashCode()
- {
- int h = this.hash;
- int len = _name.length();
- if (h == 0 && len > 0)
- {
- for (int i = 0; i < len; i++)
- {
- // simple case insensitive hash
- char c = _name.charAt(i);
- // assuming us-ascii (per last paragraph on http://tools.ietf.org/html/rfc7230#section-3.2.4)
- if ((c >= 'a' && c <= 'z'))
- c -= 0x20;
- h = 31 * h + c;
- }
- this.hash = h;
- }
- return h;
- }
-
- @Override
- public int hashCode()
- {
- if (_header==null)
- return _value.hashCode() ^ nameHashCode();
- return _value.hashCode() ^ _header.hashCode();
- }
-
- @Override
- public boolean equals(Object o)
- {
- if (o==this)
- return true;
- if (!(o instanceof HttpField))
- return false;
- HttpField field=(HttpField)o;
- if (_header!=field.getHeader())
- return false;
- if (!_name.equalsIgnoreCase(field.getName()))
- return false;
- if (_value==null && field.getValue()!=null)
- return false;
- return Objects.equals(_value,field.getValue());
- }
-
- public static class IntValueHttpField extends HttpField
- {
- private final int _int;
-
- public IntValueHttpField(HttpHeader header, String name, String value, int intValue)
- {
- super(header,name,value);
- _int=intValue;
- }
-
- public IntValueHttpField(HttpHeader header, String name, String value)
- {
- this(header,name,value,Integer.valueOf(value));
- }
-
- public IntValueHttpField(HttpHeader header, String name, int intValue)
- {
- this(header,name,Integer.toString(intValue),intValue);
- }
-
- public IntValueHttpField(HttpHeader header, int value)
- {
- this(header,header.asString(),value);
- }
-
- @Override
- public int getIntValue()
- {
- return _int;
- }
-
- @Override
- public long getLongValue()
- {
- return _int;
- }
- }
-
- public static class LongValueHttpField extends HttpField
- {
- private final long _long;
-
- public LongValueHttpField(HttpHeader header, String name, String value, long longValue)
- {
- super(header,name,value);
- _long=longValue;
- }
-
- public LongValueHttpField(HttpHeader header, String name, String value)
- {
- this(header,name,value,Long.valueOf(value));
- }
-
- public LongValueHttpField(HttpHeader header, String name, long value)
- {
- this(header,name,Long.toString(value),value);
- }
-
- public LongValueHttpField(HttpHeader header,long value)
- {
- this(header,header.asString(),value);
- }
-
- @Override
- public int getIntValue()
- {
- return (int)_long;
- }
-
- @Override
- public long getLongValue()
- {
- return _long;
- }
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpFieldPreEncoder.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpFieldPreEncoder.java
deleted file mode 100644
index 0b1e4d47af..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpFieldPreEncoder.java
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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;
-
-
-/* ------------------------------------------------------------ */
-/** Interface to pre-encode HttpFields. Used by {@link PreEncodedHttpField}
- */
-public interface HttpFieldPreEncoder
-{
- /* ------------------------------------------------------------ */
- /** The major version this encoder is for. Both HTTP/1.0 and HTTP/1.1
- * use the same field encoding, so the {@link HttpVersion#HTTP_1_0} should
- * be return for all HTTP/1.x encodings.
- * @return The major version this encoder is for.
- */
- HttpVersion getHttpVersion();
- byte[] getEncodedField(HttpHeader header, String headerString, String value);
-}
\ No newline at end of file
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpFields.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpFields.java
deleted file mode 100644
index 0951a6de51..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpFields.java
+++ /dev/null
@@ -1,970 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-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.
- *
- */
-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()
- {
- _fields=new HttpField[20];
- }
-
- /**
- * 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+10);
- _size=fields._size;
- }
-
- public int size()
- {
- return _size;
- }
-
- @Override
- public Iterator iterator()
- {
- return new Itr();
- }
-
- /**
- * Get Collection of header names.
- * @return the unique set of field names.
- */
- public Set getFieldNamesCollection()
- {
- final Set set = new HashSet<>(_size);
- for (HttpField f : this)
- {
- if (f!=null)
- set.add(f.getName());
- }
- return 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.getName().equalsIgnoreCase(name))
- return f;
- }
- return null;
- }
-
- public boolean contains(HttpField field)
- {
- for (int i=_size;i-->0;)
- {
- HttpField f=_fields[i];
- if (f.isSameName(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.getName().equalsIgnoreCase(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.getName().equalsIgnoreCase(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.getName().equalsIgnoreCase(header))
- return f.getValue();
- }
- return null;
- }
-
- /**
- * Get multiple header of the same name
- *
- * @return List the values
- * @param header the header
- */
- public List getValuesList(HttpHeader header)
- {
- final List list = new ArrayList<>();
- for (HttpField f : this)
- if (f.getHeader()==header)
- list.add(f.getValue());
- return list;
- }
-
- /**
- * Get multiple header of the same name
- *
- * @return List the header values
- * @param name the case-insensitive field name
- */
- public List getValuesList(String name)
- {
- final List list = new ArrayList<>();
- for (HttpField f : this)
- if (f.getName().equalsIgnoreCase(name))
- list.add(f.getValue());
- return list;
- }
-
- /**
- * Get multiple field values of the same name, split
- * as a {@link QuotedCSV}
- *
- * @return List the values with OWS stripped
- * @param header The header
- * @param keepQuotes True if the fields are kept quoted
- */
- public List getCSV(HttpHeader header,boolean keepQuotes)
- {
- QuotedCSV values = new QuotedCSV(keepQuotes);
- for (HttpField f : this)
- if (f.getHeader()==header)
- values.addValue(f.getValue());
- return values.getValues();
- }
-
- /**
- * Get multiple field values of the same name
- * as a {@link QuotedCSV}
- *
- * @return List the values with OWS stripped
- * @param name the case-insensitive field name
- * @param keepQuotes True if the fields are kept quoted
- */
- public List getCSV(String name,boolean keepQuotes)
- {
- QuotedCSV values = new QuotedCSV(keepQuotes);
- for (HttpField f : this)
- if (f.getName().equalsIgnoreCase(name))
- values.addValue(f.getValue());
- return values.getValues();
- }
-
- /**
- * Get multiple field values of the same name, split and
- * sorted as a {@link QuotedQualityCSV}
- *
- * @return List the values in quality order with the q param and OWS stripped
- * @param header The header
- */
- public List getQualityCSV(HttpHeader header)
- {
- QuotedQualityCSV values = new QuotedQualityCSV();
- for (HttpField f : this)
- if (f.getHeader()==header)
- values.addValue(f.getValue());
- return values.getValues();
- }
-
- /**
- * Get multiple field values of the same name, split and
- * sorted as a {@link QuotedQualityCSV}
- *
- * @return List the values in quality order with the q param and OWS stripped
- * @param name the case-insensitive field name
- */
- public List getQualityCSV(String name)
- {
- QuotedQualityCSV values = new QuotedQualityCSV();
- for (HttpField f : this)
- if (f.getName().equalsIgnoreCase(name))
- values.addValue(f.getValue());
- return values.getValues();
- }
-
- /**
- * Get multi headers
- *
- * @return Enumeration of the values
- * @param name the case-insensitive field name
- */
- public Enumeration getValues(final String name)
- {
- for (int i=0;i<_size;i++)
- {
- final HttpField f = _fields[i];
-
- if (f.getName().equalsIgnoreCase(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.getName().equalsIgnoreCase(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)
- {
- 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)
- {
- 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)
- {
- remove(name);
- 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)
- {
- 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)
- {
- 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;
- System.arraycopy(_fields,i+1,_fields,i,--_size-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.getName().equalsIgnoreCase(name))
- {
- removed=f;
- System.arraycopy(_fields,i+1,_fields,i,--_size-i);
- }
- }
- return removed;
- }
-
- /**
- * 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
- * @exception 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 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();
- }
-
-
- private class Itr implements Iterator
- {
- int _cursor; // index of next element to return
- int _last=-1;
-
- public boolean hasNext()
- {
- return _cursor != _size;
- }
-
- public HttpField next()
- {
- int i = _cursor;
- if (i >= _size)
- throw new NoSuchElementException();
- _cursor = i + 1;
- return _fields[_last=i];
- }
-
- public void remove()
- {
- if (_last<0)
- throw new IllegalStateException();
-
- System.arraycopy(_fields,_last+1,_fields,_last,--_size-_last);
- _cursor=_last;
- _last=-1;
- }
- }
-
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpGenerator.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpGenerator.java
deleted file mode 100644
index f743379eb4..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpGenerator.java
+++ /dev/null
@@ -1,1023 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.io.EOFException;
-import java.io.IOException;
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.eclipse.jetty.http.HttpTokens.EndOfContent;
-import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-/**
- * HttpGenerator. Builds HTTP Messages.
- *
- * If the system property "org.eclipse.jetty.http.HttpGenerator.STRICT" is set to true,
- * then the generator will strictly pass on the exact strings received from methods and header
- * fields. Otherwise a fast case insensitive string lookup is used that may alter the
- * case and white space of some methods/headers
- */
-public class HttpGenerator
-{
- private final static Logger LOG = Log.getLogger(HttpGenerator.class);
-
- public final static boolean __STRICT=Boolean.getBoolean("org.eclipse.jetty.http.HttpGenerator.STRICT");
-
- private final static byte[] __colon_space = new byte[] {':',' '};
- private final static HttpHeaderValue[] CLOSE = {HttpHeaderValue.CLOSE};
- public static final MetaData.Response CONTINUE_100_INFO = new MetaData.Response(HttpVersion.HTTP_1_1,100,null,null,-1);
- public static final MetaData.Response PROGRESS_102_INFO = new MetaData.Response(HttpVersion.HTTP_1_1,102,null,null,-1);
- public final static MetaData.Response RESPONSE_500_INFO =
- new MetaData.Response(HttpVersion.HTTP_1_1,HttpStatus.INTERNAL_SERVER_ERROR_500,null,new HttpFields(){{put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);}},0);
-
- // states
- public enum State { START, COMMITTED, COMPLETING, COMPLETING_1XX, END }
- public enum Result { NEED_CHUNK,NEED_INFO,NEED_HEADER,FLUSH,CONTINUE,SHUTDOWN_OUT,DONE}
-
- // other statics
- public static final int CHUNK_SIZE = 12;
-
- private State _state = State.START;
- private EndOfContent _endOfContent = EndOfContent.UNKNOWN_CONTENT;
-
- private long _contentPrepared = 0;
- private boolean _noContent = false;
- private Boolean _persistent = null;
-
- private final int _send;
- private final static int SEND_SERVER = 0x01;
- private final static int SEND_XPOWEREDBY = 0x02;
- private final static Set __assumedContentMethods = new HashSet<>(Arrays.asList(new String[]{HttpMethod.POST.asString(),HttpMethod.PUT.asString()}));
-
- /* ------------------------------------------------------------------------------- */
- public static void setJettyVersion(String serverVersion)
- {
- SEND[SEND_SERVER] = StringUtil.getBytes("Server: " + serverVersion + "\015\012");
- SEND[SEND_XPOWEREDBY] = StringUtil.getBytes("X-Powered-By: " + serverVersion + "\015\012");
- SEND[SEND_SERVER | SEND_XPOWEREDBY] = StringUtil.getBytes("Server: " + serverVersion + "\015\012X-Powered-By: " +
- serverVersion + "\015\012");
- }
-
- /* ------------------------------------------------------------------------------- */
- // data
- private boolean _needCRLF = false;
-
- /* ------------------------------------------------------------------------------- */
- public HttpGenerator()
- {
- this(false,false);
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpGenerator(boolean sendServerVersion,boolean sendXPoweredBy)
- {
- _send=(sendServerVersion?SEND_SERVER:0) | (sendXPoweredBy?SEND_XPOWEREDBY:0);
- }
-
- /* ------------------------------------------------------------------------------- */
- public void reset()
- {
- _state = State.START;
- _endOfContent = EndOfContent.UNKNOWN_CONTENT;
- _noContent=false;
- _persistent = null;
- _contentPrepared = 0;
- _needCRLF = false;
- }
-
- /* ------------------------------------------------------------ */
- @Deprecated
- public boolean getSendServerVersion ()
- {
- return (_send&SEND_SERVER)!=0;
- }
-
- /* ------------------------------------------------------------ */
- @Deprecated
- public void setSendServerVersion (boolean sendServerVersion)
- {
- throw new UnsupportedOperationException();
- }
-
- /* ------------------------------------------------------------ */
- public State getState()
- {
- return _state;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isState(State state)
- {
- return _state == state;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isIdle()
- {
- return _state == State.START;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isEnd()
- {
- return _state == State.END;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isCommitted()
- {
- return _state.ordinal() >= State.COMMITTED.ordinal();
- }
-
- /* ------------------------------------------------------------ */
- public boolean isChunking()
- {
- return _endOfContent==EndOfContent.CHUNKED_CONTENT;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isNoContent()
- {
- return _noContent;
- }
-
- /* ------------------------------------------------------------ */
- public void setPersistent(boolean persistent)
- {
- _persistent=persistent;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @return true if known to be persistent
- */
- public boolean isPersistent()
- {
- return Boolean.TRUE.equals(_persistent);
- }
-
- /* ------------------------------------------------------------ */
- public boolean isWritten()
- {
- return _contentPrepared>0;
- }
-
- /* ------------------------------------------------------------ */
- public long getContentPrepared()
- {
- return _contentPrepared;
- }
-
- /* ------------------------------------------------------------ */
- public void abort()
- {
- _persistent=false;
- _state=State.END;
- _endOfContent=null;
- }
-
- /* ------------------------------------------------------------ */
- public Result generateRequest(MetaData.Request info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last) throws IOException
- {
- switch(_state)
- {
- case START:
- {
- if (info==null)
- return Result.NEED_INFO;
-
- if (header==null)
- return Result.NEED_HEADER;
-
- // If we have not been told our persistence, set the default
- if (_persistent==null)
- {
- _persistent=info.getVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal();
- if (!_persistent && HttpMethod.CONNECT.is(info.getMethod()))
- _persistent=true;
- }
-
- // prepare the header
- int pos=BufferUtil.flipToFill(header);
- try
- {
- // generate ResponseLine
- generateRequestLine(info,header);
-
- if (info.getVersion()==HttpVersion.HTTP_0_9)
- throw new BadMessageException(500,"HTTP/0.9 not supported");
-
- generateHeaders(info,header,content,last);
-
- boolean expect100 = info.getFields().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString());
-
- if (expect100)
- {
- _state = State.COMMITTED;
- }
- else
- {
- // handle the content.
- int len = BufferUtil.length(content);
- if (len>0)
- {
- _contentPrepared+=len;
- if (isChunking())
- prepareChunk(header,len);
- }
- _state = last?State.COMPLETING:State.COMMITTED;
- }
-
- return Result.FLUSH;
- }
- catch(Exception e)
- {
- String message= (e instanceof BufferOverflowException)?"Request header too large":e.getMessage();
- throw new BadMessageException(500,message,e);
- }
- finally
- {
- BufferUtil.flipToFlush(header,pos);
- }
- }
-
- case COMMITTED:
- {
- int len = BufferUtil.length(content);
-
- if (len>0)
- {
- // Do we need a chunk buffer?
- if (isChunking())
- {
- // Do we need a chunk buffer?
- if (chunk==null)
- return Result.NEED_CHUNK;
- BufferUtil.clearToFill(chunk);
- prepareChunk(chunk,len);
- BufferUtil.flipToFlush(chunk,0);
- }
- _contentPrepared+=len;
- }
-
- if (last)
- _state=State.COMPLETING;
-
- return len>0?Result.FLUSH:Result.CONTINUE;
- }
-
- case COMPLETING:
- {
- if (BufferUtil.hasContent(content))
- {
- if (LOG.isDebugEnabled())
- LOG.debug("discarding content in COMPLETING");
- BufferUtil.clear(content);
- }
-
- if (isChunking())
- {
- // Do we need a chunk buffer?
- if (chunk==null)
- return Result.NEED_CHUNK;
- BufferUtil.clearToFill(chunk);
- prepareChunk(chunk,0);
- BufferUtil.flipToFlush(chunk,0);
- _endOfContent=EndOfContent.UNKNOWN_CONTENT;
- return Result.FLUSH;
- }
-
- _state=State.END;
- return Boolean.TRUE.equals(_persistent)?Result.DONE:Result.SHUTDOWN_OUT;
- }
-
- case END:
- if (BufferUtil.hasContent(content))
- {
- if (LOG.isDebugEnabled())
- LOG.debug("discarding content in COMPLETING");
- BufferUtil.clear(content);
- }
- return Result.DONE;
-
- default:
- throw new IllegalStateException();
- }
- }
-
- /* ------------------------------------------------------------ */
- public Result generateResponse(MetaData.Response info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last) throws IOException
- {
- return generateResponse(info,false,header,chunk,content,last);
- }
-
- /* ------------------------------------------------------------ */
- public Result generateResponse(MetaData.Response info, boolean head, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last) throws IOException
- {
- switch(_state)
- {
- case START:
- {
- if (info==null)
- return Result.NEED_INFO;
- HttpVersion version=info.getVersion();
- if (version==null)
- throw new BadMessageException(500,"No version");
- switch(version)
- {
- case HTTP_1_0:
- if (_persistent==null)
- _persistent=Boolean.FALSE;
- break;
-
- case HTTP_1_1:
- if (_persistent==null)
- _persistent=Boolean.TRUE;
- break;
-
- default:
- _persistent = false;
- _endOfContent=EndOfContent.EOF_CONTENT;
- if (BufferUtil.hasContent(content))
- _contentPrepared+=content.remaining();
- _state = last?State.COMPLETING:State.COMMITTED;
- return Result.FLUSH;
- }
-
- // Do we need a response header
- if (header==null)
- return Result.NEED_HEADER;
-
- // prepare the header
- int pos=BufferUtil.flipToFill(header);
- try
- {
- // generate ResponseLine
- generateResponseLine(info,header);
-
- // Handle 1xx and no content responses
- int status=info.getStatus();
- if (status>=100 && status<200 )
- {
- _noContent=true;
-
- if (status!=HttpStatus.SWITCHING_PROTOCOLS_101 )
- {
- header.put(HttpTokens.CRLF);
- _state=State.COMPLETING_1XX;
- return Result.FLUSH;
- }
- }
- else if (status==HttpStatus.NO_CONTENT_204 || status==HttpStatus.NOT_MODIFIED_304)
- {
- _noContent=true;
- }
-
- generateHeaders(info,header,content,last);
-
- // handle the content.
- int len = BufferUtil.length(content);
- if (len>0)
- {
- _contentPrepared+=len;
- if (isChunking() && !head)
- prepareChunk(header,len);
- }
- _state = last?State.COMPLETING:State.COMMITTED;
- }
- catch(Exception e)
- {
- String message= (e instanceof BufferOverflowException)?"Response header too large":e.getMessage();
- throw new BadMessageException(500,message,e);
- }
- finally
- {
- BufferUtil.flipToFlush(header,pos);
- }
-
- return Result.FLUSH;
- }
-
- case COMMITTED:
- {
- int len = BufferUtil.length(content);
-
- // handle the content.
- if (len>0)
- {
- if (isChunking())
- {
- if (chunk==null)
- return Result.NEED_CHUNK;
- BufferUtil.clearToFill(chunk);
- prepareChunk(chunk,len);
- BufferUtil.flipToFlush(chunk,0);
- }
- _contentPrepared+=len;
- }
-
- if (last)
- {
- _state=State.COMPLETING;
- return len>0?Result.FLUSH:Result.CONTINUE;
- }
- return len>0?Result.FLUSH:Result.DONE;
-
- }
-
- case COMPLETING_1XX:
- {
- reset();
- return Result.DONE;
- }
-
- case COMPLETING:
- {
- if (BufferUtil.hasContent(content))
- {
- if (LOG.isDebugEnabled())
- LOG.debug("discarding content in COMPLETING");
- BufferUtil.clear(content);
- }
-
- if (isChunking())
- {
- // Do we need a chunk buffer?
- if (chunk==null)
- return Result.NEED_CHUNK;
-
- // Write the last chunk
- BufferUtil.clearToFill(chunk);
- prepareChunk(chunk,0);
- BufferUtil.flipToFlush(chunk,0);
- _endOfContent=EndOfContent.UNKNOWN_CONTENT;
- return Result.FLUSH;
- }
-
- _state=State.END;
-
- return Boolean.TRUE.equals(_persistent)?Result.DONE:Result.SHUTDOWN_OUT;
- }
-
- case END:
- if (BufferUtil.hasContent(content))
- {
- if (LOG.isDebugEnabled())
- LOG.debug("discarding content in COMPLETING");
- BufferUtil.clear(content);
- }
- return Result.DONE;
-
- default:
- throw new IllegalStateException();
- }
- }
-
- /* ------------------------------------------------------------ */
- private void prepareChunk(ByteBuffer chunk, int remaining)
- {
- // if we need CRLF add this to header
- if (_needCRLF)
- BufferUtil.putCRLF(chunk);
-
- // Add the chunk size to the header
- if (remaining>0)
- {
- BufferUtil.putHexInt(chunk, remaining);
- BufferUtil.putCRLF(chunk);
- _needCRLF=true;
- }
- else
- {
- chunk.put(LAST_CHUNK);
- _needCRLF=false;
- }
- }
-
- /* ------------------------------------------------------------ */
- private void generateRequestLine(MetaData.Request request,ByteBuffer header)
- {
- header.put(StringUtil.getBytes(request.getMethod()));
- header.put((byte)' ');
- header.put(StringUtil.getBytes(request.getURIString()));
- header.put((byte)' ');
- header.put(request.getVersion().toBytes());
- header.put(HttpTokens.CRLF);
- }
-
- /* ------------------------------------------------------------ */
- private void generateResponseLine(MetaData.Response response, ByteBuffer header)
- {
- // Look for prepared response line
- int status=response.getStatus();
- PreparedResponse preprepared = status<__preprepared.length?__preprepared[status]:null;
- String reason=response.getReason();
- if (preprepared!=null)
- {
- if (reason==null)
- header.put(preprepared._responseLine);
- else
- {
- header.put(preprepared._schemeCode);
- header.put(getReasonBytes(reason));
- header.put(HttpTokens.CRLF);
- }
- }
- else // generate response line
- {
- header.put(HTTP_1_1_SPACE);
- header.put((byte) ('0' + status / 100));
- header.put((byte) ('0' + (status % 100) / 10));
- header.put((byte) ('0' + (status % 10)));
- header.put((byte) ' ');
- if (reason==null)
- {
- header.put((byte) ('0' + status / 100));
- header.put((byte) ('0' + (status % 100) / 10));
- header.put((byte) ('0' + (status % 10)));
- }
- else
- header.put(getReasonBytes(reason));
- header.put(HttpTokens.CRLF);
- }
- }
-
- /* ------------------------------------------------------------ */
- private byte[] getReasonBytes(String reason)
- {
- if (reason.length()>1024)
- reason=reason.substring(0,1024);
- byte[] _bytes = StringUtil.getBytes(reason);
-
- for (int i=_bytes.length;i-->0;)
- if (_bytes[i]=='\r' || _bytes[i]=='\n')
- _bytes[i]='?';
- return _bytes;
- }
-
- /* ------------------------------------------------------------ */
- private void generateHeaders(MetaData _info,ByteBuffer header,ByteBuffer content,boolean last)
- {
- final MetaData.Request request=(_info instanceof MetaData.Request)?(MetaData.Request)_info:null;
- final MetaData.Response response=(_info instanceof MetaData.Response)?(MetaData.Response)_info:null;
-
- // default field values
- int send=_send;
- HttpField transfer_encoding=null;
- boolean keep_alive=false;
- boolean close=false;
- boolean content_type=false;
- StringBuilder connection = null;
- long content_length = _info.getContentLength();
-
- // Generate fields
- HttpFields fields = _info.getFields();
- if (fields != null)
- {
- int n=fields.size();
- for (int f=0;f0)
- {
- values=new HttpHeaderValue[split.length];
- for (int i=0;i0)
- {
- // we have been given a content length
- _endOfContent=EndOfContent.CONTENT_LENGTH;
- if ((response!=null || content_length>0 || content_type ) && !_noContent)
- {
- // known length but not actually set.
- header.put(HttpHeader.CONTENT_LENGTH.getBytesColonSpace());
- BufferUtil.putDecLong(header, content_length);
- header.put(HttpTokens.CRLF);
- }
- }
- else if (last)
- {
- // we have seen all the _content there is, so we can be content-length limited.
- _endOfContent=EndOfContent.CONTENT_LENGTH;
- long actual_length = _contentPrepared+BufferUtil.length(content);
-
- if (content_length>=0 && content_length!=actual_length)
- throw new BadMessageException(500,"Content-Length header("+content_length+") != actual("+actual_length+")");
-
- // Do we need to tell the headers about it
- putContentLength(header,actual_length,content_type,request,response);
- }
- else
- {
- // No idea, so we must assume that a body is coming.
- _endOfContent = EndOfContent.CHUNKED_CONTENT;
- // HTTP 1.0 does not understand chunked content, so we must use EOF content.
- // For a request with HTTP 1.0 & Connection: keep-alive
- // we *must* close the connection, otherwise the client
- // has no way to detect the end of the content.
- if (!isPersistent() || _info.getVersion().ordinal() < HttpVersion.HTTP_1_1.ordinal())
- _endOfContent = EndOfContent.EOF_CONTENT;
- }
- break;
-
- case CONTENT_LENGTH:
- {
- putContentLength(header,content_length,content_type,request,response);
- break;
- }
-
- case NO_CONTENT:
- throw new BadMessageException(500);
-
- case EOF_CONTENT:
- _persistent = request!=null;
- break;
-
- case CHUNKED_CONTENT:
- break;
-
- default:
- break;
- }
-
- // Add transfer_encoding if needed
- if (isChunking())
- {
- // try to use user supplied encoding as it may have other values.
- if (transfer_encoding != null && !HttpHeaderValue.CHUNKED.toString().equalsIgnoreCase(transfer_encoding.getValue()))
- {
- String c = transfer_encoding.getValue();
- if (c.endsWith(HttpHeaderValue.CHUNKED.toString()))
- putTo(transfer_encoding,header);
- else
- throw new BadMessageException(500,"BAD TE");
- }
- else
- header.put(TRANSFER_ENCODING_CHUNKED);
- }
-
- // Handle connection if need be
- if (_endOfContent==EndOfContent.EOF_CONTENT)
- {
- keep_alive=false;
- _persistent=false;
- }
-
- // If this is a response, work out persistence
- if (response!=null)
- {
- if (!isPersistent() && (close || _info.getVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal()))
- {
- if (connection==null)
- header.put(CONNECTION_CLOSE);
- else
- {
- header.put(CONNECTION_CLOSE,0,CONNECTION_CLOSE.length-2);
- header.put((byte)',');
- header.put(StringUtil.getBytes(connection.toString()));
- header.put(CRLF);
- }
- }
- else if (keep_alive)
- {
- if (connection==null)
- header.put(CONNECTION_KEEP_ALIVE);
- else
- {
- header.put(CONNECTION_KEEP_ALIVE,0,CONNECTION_KEEP_ALIVE.length-2);
- header.put((byte)',');
- header.put(StringUtil.getBytes(connection.toString()));
- header.put(CRLF);
- }
- }
- else if (connection!=null)
- {
- header.put(HttpHeader.CONNECTION.getBytesColonSpace());
- header.put(StringUtil.getBytes(connection.toString()));
- header.put(CRLF);
- }
- }
-
- if (status>199)
- header.put(SEND[send]);
-
- // end the header.
- header.put(HttpTokens.CRLF);
- }
-
- /* ------------------------------------------------------------------------------- */
- private void putContentLength(ByteBuffer header, long contentLength, boolean contentType, MetaData.Request request, MetaData.Response response)
- {
- if (contentLength>0)
- {
- header.put(HttpHeader.CONTENT_LENGTH.getBytesColonSpace());
- BufferUtil.putDecLong(header, contentLength);
- header.put(HttpTokens.CRLF);
- }
- else if (!_noContent)
- {
- if (contentType || response!=null || (request!=null && __assumedContentMethods.contains(request.getMethod())))
- header.put(CONTENT_LENGTH_0);
- }
- }
-
- /* ------------------------------------------------------------------------------- */
- public static byte[] getReasonBuffer(int code)
- {
- PreparedResponse status = code<__preprepared.length?__preprepared[code]:null;
- if (status!=null)
- return status._reason;
- return null;
- }
-
- /* ------------------------------------------------------------------------------- */
- @Override
- public String toString()
- {
- return String.format("%s@%x{s=%s}",
- getClass().getSimpleName(),
- hashCode(),
- _state);
- }
-
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- // common _content
- private static final byte[] LAST_CHUNK = { (byte) '0', (byte) '\015', (byte) '\012', (byte) '\015', (byte) '\012'};
- private static final byte[] CONTENT_LENGTH_0 = StringUtil.getBytes("Content-Length: 0\015\012");
- private static final byte[] CONNECTION_KEEP_ALIVE = StringUtil.getBytes("Connection: keep-alive\015\012");
- private static final byte[] CONNECTION_CLOSE = StringUtil.getBytes("Connection: close\015\012");
- private static final byte[] HTTP_1_1_SPACE = StringUtil.getBytes(HttpVersion.HTTP_1_1+" ");
- private static final byte[] CRLF = StringUtil.getBytes("\015\012");
- private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\015\012");
- private static final byte[][] SEND = new byte[][]{
- new byte[0],
- StringUtil.getBytes("Server: Jetty(9.x.x)\015\012"),
- StringUtil.getBytes("X-Powered-By: Jetty(9.x.x)\015\012"),
- StringUtil.getBytes("Server: Jetty(9.x.x)\015\012X-Powered-By: Jetty(9.x.x)\015\012")
- };
-
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- // Build cache of response lines for status
- private static class PreparedResponse
- {
- byte[] _reason;
- byte[] _schemeCode;
- byte[] _responseLine;
- }
- private static final PreparedResponse[] __preprepared = new PreparedResponse[HttpStatus.MAX_CODE+1];
- static
- {
- int versionLength=HttpVersion.HTTP_1_1.toString().length();
-
- for (int i=0;i<__preprepared.length;i++)
- {
- HttpStatus.Code code = HttpStatus.getCode(i);
- if (code==null)
- continue;
- String reason=code.getMessage();
- byte[] line=new byte[versionLength+5+reason.length()+2];
- HttpVersion.HTTP_1_1.toBuffer().get(line,0,versionLength);
- line[versionLength+0]=' ';
- line[versionLength+1]=(byte)('0'+i/100);
- line[versionLength+2]=(byte)('0'+(i%100)/10);
- line[versionLength+3]=(byte)('0'+(i%10));
- line[versionLength+4]=' ';
- for (int j=0;j0xff || c=='\r' || c=='\n'|| c==':')
- buffer.put((byte)'?');
- else
- buffer.put((byte)(0xff&c));
- }
- }
-
- private static void putSanitisedValue(String s,ByteBuffer buffer)
- {
- int l=s.length();
- for (int i=0;i0xff || c=='\r' || c=='\n')
- buffer.put((byte)' ');
- else
- buffer.put((byte)(0xff&c));
- }
- }
-
- public static void putTo(HttpField field, ByteBuffer bufferInFillMode)
- {
- if (field instanceof PreEncodedHttpField)
- {
- ((PreEncodedHttpField)field).putTo(bufferInFillMode,HttpVersion.HTTP_1_0);
- }
- else
- {
- HttpHeader header=field.getHeader();
- if (header!=null)
- {
- bufferInFillMode.put(header.getBytesColonSpace());
- putSanitisedValue(field.getValue(),bufferInFillMode);
- }
- else
- {
- putSanitisedName(field.getName(),bufferInFillMode);
- bufferInFillMode.put(__colon_space);
- putSanitisedValue(field.getValue(),bufferInFillMode);
- }
-
- BufferUtil.putCRLF(bufferInFillMode);
- }
- }
-
- public static void putTo(HttpFields fields, ByteBuffer bufferInFillMode)
- {
- for (HttpField field : fields)
- {
- if (field != null)
- putTo(field,bufferInFillMode);
- }
- BufferUtil.putCRLF(bufferInFillMode);
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpHeader.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpHeader.java
deleted file mode 100644
index b57a5fa244..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpHeader.java
+++ /dev/null
@@ -1,191 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.nio.ByteBuffer;
-
-import org.eclipse.jetty.util.ArrayTrie;
-import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.util.Trie;
-
-
-public enum HttpHeader
-{
- /* ------------------------------------------------------------ */
- /** General Fields.
- */
- CONNECTION("Connection"),
- CACHE_CONTROL("Cache-Control"),
- DATE("Date"),
- PRAGMA("Pragma"),
- PROXY_CONNECTION ("Proxy-Connection"),
- TRAILER("Trailer"),
- TRANSFER_ENCODING("Transfer-Encoding"),
- UPGRADE("Upgrade"),
- VIA("Via"),
- WARNING("Warning"),
- NEGOTIATE("Negotiate"),
-
- /* ------------------------------------------------------------ */
- /** Entity Fields.
- */
- ALLOW("Allow"),
- CONTENT_ENCODING("Content-Encoding"),
- CONTENT_LANGUAGE("Content-Language"),
- CONTENT_LENGTH("Content-Length"),
- CONTENT_LOCATION("Content-Location"),
- CONTENT_MD5("Content-MD5"),
- CONTENT_RANGE("Content-Range"),
- CONTENT_TYPE("Content-Type"),
- EXPIRES("Expires"),
- LAST_MODIFIED("Last-Modified"),
-
- /* ------------------------------------------------------------ */
- /** Request Fields.
- */
- ACCEPT("Accept"),
- ACCEPT_CHARSET("Accept-Charset"),
- ACCEPT_ENCODING("Accept-Encoding"),
- ACCEPT_LANGUAGE("Accept-Language"),
- AUTHORIZATION("Authorization"),
- EXPECT("Expect"),
- FORWARDED("Forwarded"),
- FROM("From"),
- HOST("Host"),
- IF_MATCH("If-Match"),
- IF_MODIFIED_SINCE("If-Modified-Since"),
- IF_NONE_MATCH("If-None-Match"),
- IF_RANGE("If-Range"),
- IF_UNMODIFIED_SINCE("If-Unmodified-Since"),
- KEEP_ALIVE("Keep-Alive"),
- MAX_FORWARDS("Max-Forwards"),
- PROXY_AUTHORIZATION("Proxy-Authorization"),
- RANGE("Range"),
- REQUEST_RANGE("Request-Range"),
- REFERER("Referer"),
- TE("TE"),
- USER_AGENT("User-Agent"),
- X_FORWARDED_FOR("X-Forwarded-For"),
- X_FORWARDED_PROTO("X-Forwarded-Proto"),
- X_FORWARDED_SERVER("X-Forwarded-Server"),
- X_FORWARDED_HOST("X-Forwarded-Host"),
-
- /* ------------------------------------------------------------ */
- /** Response Fields.
- */
- ACCEPT_RANGES("Accept-Ranges"),
- AGE("Age"),
- ETAG("ETag"),
- LOCATION("Location"),
- PROXY_AUTHENTICATE("Proxy-Authenticate"),
- RETRY_AFTER("Retry-After"),
- SERVER("Server"),
- SERVLET_ENGINE("Servlet-Engine"),
- VARY("Vary"),
- WWW_AUTHENTICATE("WWW-Authenticate"),
-
- /* ------------------------------------------------------------ */
- /** Other Fields.
- */
- COOKIE("Cookie"),
- SET_COOKIE("Set-Cookie"),
- SET_COOKIE2("Set-Cookie2"),
- MIME_VERSION("MIME-Version"),
- IDENTITY("identity"),
-
- X_POWERED_BY("X-Powered-By"),
- HTTP2_SETTINGS("HTTP2-Settings"),
-
- STRICT_TRANSPORT_SECURITY("Strict-Transport-Security"),
-
- /* ------------------------------------------------------------ */
- /** HTTP2 Fields.
- */
- C_METHOD(":method"),
- C_SCHEME(":scheme"),
- C_AUTHORITY(":authority"),
- C_PATH(":path"),
- C_STATUS(":status"),
-
- UNKNOWN("::UNKNOWN::");
-
-
- /* ------------------------------------------------------------ */
- public final static Trie CACHE= new ArrayTrie<>(560);
- static
- {
- for (HttpHeader header : HttpHeader.values())
- if (header!=UNKNOWN)
- if (!CACHE.put(header.toString(),header))
- throw new IllegalStateException();
- }
-
- private final String _string;
- private final byte[] _bytes;
- private final byte[] _bytesColonSpace;
- private final ByteBuffer _buffer;
-
- /* ------------------------------------------------------------ */
- HttpHeader(String s)
- {
- _string=s;
- _bytes=StringUtil.getBytes(s);
- _bytesColonSpace=StringUtil.getBytes(s+": ");
- _buffer=ByteBuffer.wrap(_bytes);
- }
-
- /* ------------------------------------------------------------ */
- public ByteBuffer toBuffer()
- {
- return _buffer.asReadOnlyBuffer();
- }
-
- /* ------------------------------------------------------------ */
- public byte[] getBytes()
- {
- return _bytes;
- }
-
- /* ------------------------------------------------------------ */
- public byte[] getBytesColonSpace()
- {
- return _bytesColonSpace;
- }
-
- /* ------------------------------------------------------------ */
- public boolean is(String s)
- {
- return _string.equalsIgnoreCase(s);
- }
-
- /* ------------------------------------------------------------ */
- public String asString()
- {
- return _string;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String toString()
- {
- return _string;
- }
-
-}
-
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpHeaderValue.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpHeaderValue.java
deleted file mode 100644
index 71301003ee..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpHeaderValue.java
+++ /dev/null
@@ -1,104 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.nio.ByteBuffer;
-import java.util.EnumSet;
-
-import org.eclipse.jetty.util.ArrayTrie;
-import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.Trie;
-
-
-/**
- *
- */
-public enum HttpHeaderValue
-{
- CLOSE("close"),
- CHUNKED("chunked"),
- GZIP("gzip"),
- IDENTITY("identity"),
- KEEP_ALIVE("keep-alive"),
- CONTINUE("100-continue"),
- PROCESSING("102-processing"),
- TE("TE"),
- BYTES("bytes"),
- NO_CACHE("no-cache"),
- UPGRADE("Upgrade"),
- UNKNOWN("::UNKNOWN::");
-
- /* ------------------------------------------------------------ */
- public final static Trie CACHE= new ArrayTrie();
- static
- {
- for (HttpHeaderValue value : HttpHeaderValue.values())
- if (value!=UNKNOWN)
- CACHE.put(value.toString(),value);
- }
-
- private final String _string;
- private final ByteBuffer _buffer;
-
- /* ------------------------------------------------------------ */
- HttpHeaderValue(String s)
- {
- _string=s;
- _buffer=BufferUtil.toBuffer(s);
- }
-
- /* ------------------------------------------------------------ */
- public ByteBuffer toBuffer()
- {
- return _buffer.asReadOnlyBuffer();
- }
-
- /* ------------------------------------------------------------ */
- public boolean is(String s)
- {
- return _string.equalsIgnoreCase(s);
- }
-
- /* ------------------------------------------------------------ */
- public String asString()
- {
- return _string;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String toString()
- {
- return _string;
- }
-
- /* ------------------------------------------------------------ */
- private static EnumSet __known =
- EnumSet.of(HttpHeader.CONNECTION,
- HttpHeader.TRANSFER_ENCODING,
- HttpHeader.CONTENT_ENCODING);
-
- /* ------------------------------------------------------------ */
- public static boolean hasKnownValues(HttpHeader header)
- {
- if (header==null)
- return false;
- return __known.contains(header);
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpMethod.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpMethod.java
deleted file mode 100644
index 1d2eeda0e5..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpMethod.java
+++ /dev/null
@@ -1,187 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.nio.ByteBuffer;
-
-import org.eclipse.jetty.util.ArrayTrie;
-import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.util.Trie;
-
-
-/* ------------------------------------------------------------------------------- */
-/**
- */
-public enum HttpMethod
-{
- GET,
- POST,
- HEAD,
- PUT,
- OPTIONS,
- DELETE,
- TRACE,
- CONNECT,
- MOVE,
- PROXY,
- PRI;
-
- /* ------------------------------------------------------------ */
- /**
- * Optimized lookup to find a method name and trailing space in a byte array.
- * @param bytes Array containing ISO-8859-1 characters
- * @param position The first valid index
- * @param limit The first non valid index
- * @return A HttpMethod if a match or null if no easy match.
- */
- public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
- {
- int length=limit-position;
- if (length<4)
- return null;
- switch(bytes[position])
- {
- case 'G':
- if (bytes[position+1]=='E' && bytes[position+2]=='T' && bytes[position+3]==' ')
- return GET;
- break;
- case 'P':
- if (bytes[position+1]=='O' && bytes[position+2]=='S' && bytes[position+3]=='T' && length>=5 && bytes[position+4]==' ')
- return POST;
- if (bytes[position+1]=='R' && bytes[position+2]=='O' && bytes[position+3]=='X' && length>=6 && bytes[position+4]=='Y' && bytes[position+5]==' ')
- return PROXY;
- if (bytes[position+1]=='U' && bytes[position+2]=='T' && bytes[position+3]==' ')
- return PUT;
- if (bytes[position+1]=='R' && bytes[position+2]=='I' && bytes[position+3]==' ')
- return PRI;
- break;
- case 'H':
- if (bytes[position+1]=='E' && bytes[position+2]=='A' && bytes[position+3]=='D' && length>=5 && bytes[position+4]==' ')
- return HEAD;
- break;
- case 'O':
- if (bytes[position+1]=='P' && bytes[position+2]=='T' && bytes[position+3]=='I' && length>=8 &&
- bytes[position+4]=='O' && bytes[position+5]=='N' && bytes[position+6]=='S' && bytes[position+7]==' ' )
- return OPTIONS;
- break;
- case 'D':
- if (bytes[position+1]=='E' && bytes[position+2]=='L' && bytes[position+3]=='E' && length>=7 &&
- bytes[position+4]=='T' && bytes[position+5]=='E' && bytes[position+6]==' ' )
- return DELETE;
- break;
- case 'T':
- if (bytes[position+1]=='R' && bytes[position+2]=='A' && bytes[position+3]=='C' && length>=6 &&
- bytes[position+4]=='E' && bytes[position+5]==' ' )
- return TRACE;
- break;
- case 'C':
- if (bytes[position+1]=='O' && bytes[position+2]=='N' && bytes[position+3]=='N' && length>=8 &&
- bytes[position+4]=='E' && bytes[position+5]=='C' && bytes[position+6]=='T' && bytes[position+7]==' ' )
- return CONNECT;
- break;
- case 'M':
- if (bytes[position+1]=='O' && bytes[position+2]=='V' && bytes[position+3]=='E' && length>=5 && bytes[position+4]==' ')
- return MOVE;
- break;
-
- default:
- break;
- }
- return null;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * Optimized lookup to find a method name and trailing space in a byte array.
- * @param buffer buffer containing ISO-8859-1 characters, it is not modified.
- * @return A HttpMethod if a match or null if no easy match.
- */
- public static HttpMethod lookAheadGet(ByteBuffer buffer)
- {
- if (buffer.hasArray())
- return lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position(),buffer.arrayOffset()+buffer.limit());
-
- int l = buffer.remaining();
- if (l>=4)
- {
- HttpMethod m = CACHE.getBest(buffer,0,l);
- if (m!=null)
- {
- int ml = m.asString().length();
- if (l>ml && buffer.get(buffer.position()+ml)==' ')
- return m;
- }
- }
- return null;
- }
-
- /* ------------------------------------------------------------ */
- public final static Trie CACHE= new ArrayTrie<>();
- static
- {
- for (HttpMethod method : HttpMethod.values())
- CACHE.put(method.toString(),method);
- }
-
- /* ------------------------------------------------------------ */
- private final ByteBuffer _buffer;
- private final byte[] _bytes;
-
- /* ------------------------------------------------------------ */
- HttpMethod()
- {
- _bytes=StringUtil.getBytes(toString());
- _buffer=ByteBuffer.wrap(_bytes);
- }
-
- /* ------------------------------------------------------------ */
- public byte[] getBytes()
- {
- return _bytes;
- }
-
- /* ------------------------------------------------------------ */
- public boolean is(String s)
- {
- return toString().equalsIgnoreCase(s);
- }
-
- /* ------------------------------------------------------------ */
- public ByteBuffer asBuffer()
- {
- return _buffer.asReadOnlyBuffer();
- }
-
- /* ------------------------------------------------------------ */
- public String asString()
- {
- return toString();
- }
-
- /* ------------------------------------------------------------ */
- /**
- * Converts the given String parameter to an HttpMethod
- * @param method the String to get the equivalent HttpMethod from
- * @return the HttpMethod or null if the parameter method is unknown
- */
- public static HttpMethod fromString(String method)
- {
- return CACHE.get(method);
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpParser.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpParser.java
deleted file mode 100644
index 12f74a50bb..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpParser.java
+++ /dev/null
@@ -1,1802 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Locale;
-
-import org.eclipse.jetty.http.HttpTokens.EndOfContent;
-import org.eclipse.jetty.util.ArrayTernaryTrie;
-import org.eclipse.jetty.util.ArrayTrie;
-import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.Trie;
-import org.eclipse.jetty.util.TypeUtil;
-import org.eclipse.jetty.util.Utf8StringBuilder;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-import static org.eclipse.jetty.http.HttpCompliance.LEGACY;
-import static org.eclipse.jetty.http.HttpCompliance.RFC2616;
-import static org.eclipse.jetty.http.HttpCompliance.RFC7230;
-import static org.eclipse.jetty.http.HttpTokens.CARRIAGE_RETURN;
-import static org.eclipse.jetty.http.HttpTokens.LINE_FEED;
-import static org.eclipse.jetty.http.HttpTokens.SPACE;
-import static org.eclipse.jetty.http.HttpTokens.TAB;
-
-
-/* ------------------------------------------------------------ */
-/** A Parser for 1.0 and 1.1 as defined by RFC7230
- *
- * This parser parses HTTP client and server messages from buffers
- * passed in the {@link #parseNext(ByteBuffer)} method. The parsed
- * elements of the HTTP message are passed as event calls to the
- * {@link HttpHandler} instance the parser is constructed with.
- * If the passed handler is a {@link RequestHandler} then server side
- * parsing is performed and if it is a {@link ResponseHandler}, then
- * client side parsing is done.
- *
- *
- * The contract of the {@link HttpHandler} API is that if a call returns
- * true then the call to {@link #parseNext(ByteBuffer)} will return as
- * soon as possible also with a true response. Typically this indicates
- * that the parsing has reached a stage where the caller should process
- * the events accumulated by the handler. It is the preferred calling
- * style that handling such as calling a servlet to process a request,
- * should be done after a true return from {@link #parseNext(ByteBuffer)}
- * rather than from within the scope of a call like
- * {@link RequestHandler#messageComplete()}
- *
- *
- * For performance, the parse is heavily dependent on the
- * {@link Trie#getBest(ByteBuffer, int, int)} method to look ahead in a
- * single pass for both the structure ( : and CRLF ) and semantic (which
- * header and value) of a header. Specifically the static {@link HttpHeader#CACHE}
- * is used to lookup common combinations of headers and values
- * (eg. "Connection: close"), or just header names (eg. "Connection:" ).
- * For headers who's value is not known statically (eg. Host, COOKIE) then a
- * per parser dynamic Trie of {@link HttpFields} from previous parsed messages
- * is used to help the parsing of subsequent messages.
- *
- *
- * The parser can work in varying compliance modes:
- *
- * - RFC7230
- (default) Compliance with RFC7230
- * - RFC2616
- Wrapped headers and HTTP/0.9 supported
- * - LEGACY
- (aka STRICT) Adherence to Servlet Specification requirement for
- * exact case of header names, bypassing the header caches, which are case insensitive,
- * otherwise equivalent to RFC2616
- *
- * @see RFC 7230
- */
-public class HttpParser
-{
- public static final Logger LOG = Log.getLogger(HttpParser.class);
- @Deprecated
- public final static String __STRICT="org.eclipse.jetty.http.HttpParser.STRICT";
- public final static int INITIAL_URI_LENGTH=256;
-
- /**
- * Cache of common {@link HttpField}s including:
- * - Common static combinations such as:
- * - Connection: close
- *
- Accept-Encoding: gzip
- *
- Content-Length: 0
- *
- * - Combinations of Content-Type header for common mime types by common charsets
- *
- Most common headers with null values so that a lookup will at least
- * determine the header name even if the name:value combination is not cached
- *
- */
- public final static Trie CACHE = new ArrayTrie<>(2048);
-
- // States
- public enum State
- {
- START,
- METHOD,
- RESPONSE_VERSION,
- SPACE1,
- STATUS,
- URI,
- SPACE2,
- REQUEST_VERSION,
- REASON,
- PROXY,
- HEADER,
- HEADER_IN_NAME,
- HEADER_VALUE,
- HEADER_IN_VALUE,
- CONTENT,
- EOF_CONTENT,
- CHUNKED_CONTENT,
- CHUNK_SIZE,
- CHUNK_PARAMS,
- CHUNK,
- CHUNK_END,
- END,
- CLOSE, // The associated stream/endpoint should be closed
- CLOSED // The associated stream/endpoint is at EOF
- }
-
- private final static EnumSet __idleStates = EnumSet.of(State.START,State.END,State.CLOSE,State.CLOSED);
- private final static EnumSet __completeStates = EnumSet.of(State.END,State.CLOSE,State.CLOSED);
-
- private final boolean DEBUG=LOG.isDebugEnabled(); // Cache debug to help branch prediction
- private final HttpHandler _handler;
- private final RequestHandler _requestHandler;
- private final ResponseHandler _responseHandler;
- private final ComplianceHandler _complianceHandler;
- private final int _maxHeaderBytes;
- private final HttpCompliance _compliance;
- private HttpField _field;
- private HttpHeader _header;
- private String _headerString;
- private HttpHeaderValue _value;
- private String _valueString;
- private int _responseStatus;
- private int _headerBytes;
- private boolean _host;
-
- /* ------------------------------------------------------------------------------- */
- private volatile State _state=State.START;
- private volatile boolean _eof;
- private HttpMethod _method;
- private String _methodString;
- private HttpVersion _version;
- private Utf8StringBuilder _uri=new Utf8StringBuilder(INITIAL_URI_LENGTH); // Tune?
- private EndOfContent _endOfContent;
- private long _contentLength;
- private long _contentPosition;
- private int _chunkLength;
- private int _chunkPosition;
- private boolean _headResponse;
- private boolean _cr;
- private ByteBuffer _contentChunk;
- private Trie _connectionFields;
-
- private int _length;
- private final StringBuilder _string=new StringBuilder();
-
- static
- {
- CACHE.put(new HttpField(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE));
- CACHE.put(new HttpField(HttpHeader.CONNECTION,HttpHeaderValue.KEEP_ALIVE));
- CACHE.put(new HttpField(HttpHeader.CONNECTION,HttpHeaderValue.UPGRADE));
- CACHE.put(new HttpField(HttpHeader.ACCEPT_ENCODING,"gzip"));
- CACHE.put(new HttpField(HttpHeader.ACCEPT_ENCODING,"gzip, deflate"));
- CACHE.put(new HttpField(HttpHeader.ACCEPT_ENCODING,"gzip,deflate,sdch"));
- CACHE.put(new HttpField(HttpHeader.ACCEPT_LANGUAGE,"en-US,en;q=0.5"));
- CACHE.put(new HttpField(HttpHeader.ACCEPT_LANGUAGE,"en-GB,en-US;q=0.8,en;q=0.6"));
- CACHE.put(new HttpField(HttpHeader.ACCEPT_CHARSET,"ISO-8859-1,utf-8;q=0.7,*;q=0.3"));
- CACHE.put(new HttpField(HttpHeader.ACCEPT,"*/*"));
- CACHE.put(new HttpField(HttpHeader.ACCEPT,"image/png,image/*;q=0.8,*/*;q=0.5"));
- CACHE.put(new HttpField(HttpHeader.ACCEPT,"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
- CACHE.put(new HttpField(HttpHeader.PRAGMA,"no-cache"));
- CACHE.put(new HttpField(HttpHeader.CACHE_CONTROL,"private, no-cache, no-cache=Set-Cookie, proxy-revalidate"));
- CACHE.put(new HttpField(HttpHeader.CACHE_CONTROL,"no-cache"));
- CACHE.put(new HttpField(HttpHeader.CONTENT_LENGTH,"0"));
- CACHE.put(new HttpField(HttpHeader.CONTENT_ENCODING,"gzip"));
- CACHE.put(new HttpField(HttpHeader.CONTENT_ENCODING,"deflate"));
- CACHE.put(new HttpField(HttpHeader.TRANSFER_ENCODING,"chunked"));
- CACHE.put(new HttpField(HttpHeader.EXPIRES,"Fri, 01 Jan 1990 00:00:00 GMT"));
-
- // Add common Content types as fields
- for (String type : new String[]{"text/plain","text/html","text/xml","text/json","application/json","application/x-www-form-urlencoded"})
- {
- HttpField field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type);
- CACHE.put(field);
-
- for (String charset : new String[]{"utf-8","iso-8859-1"})
- {
- CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset));
- CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset));
- CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset.toUpperCase(Locale.ENGLISH)));
- CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset.toUpperCase(Locale.ENGLISH)));
- }
- }
-
- // Add headers with null values so HttpParser can avoid looking up name again for unknown values
- for (HttpHeader h:HttpHeader.values())
- if (!CACHE.put(new HttpField(h,(String)null)))
- throw new IllegalStateException("CACHE FULL");
- // Add some more common headers
- CACHE.put(new HttpField(HttpHeader.REFERER,(String)null));
- CACHE.put(new HttpField(HttpHeader.IF_MODIFIED_SINCE,(String)null));
- CACHE.put(new HttpField(HttpHeader.IF_NONE_MATCH,(String)null));
- CACHE.put(new HttpField(HttpHeader.AUTHORIZATION,(String)null));
- CACHE.put(new HttpField(HttpHeader.COOKIE,(String)null));
- }
-
- private static HttpCompliance compliance()
- {
- Boolean strict = Boolean.getBoolean(__STRICT);
- return strict?HttpCompliance.LEGACY:HttpCompliance.RFC7230;
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpParser(RequestHandler handler)
- {
- this(handler,-1,compliance());
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpParser(ResponseHandler handler)
- {
- this(handler,-1,compliance());
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpParser(RequestHandler handler,int maxHeaderBytes)
- {
- this(handler,maxHeaderBytes,compliance());
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpParser(ResponseHandler handler,int maxHeaderBytes)
- {
- this(handler,maxHeaderBytes,compliance());
- }
-
- /* ------------------------------------------------------------------------------- */
- @Deprecated
- public HttpParser(RequestHandler handler,int maxHeaderBytes,boolean strict)
- {
- this(handler,maxHeaderBytes,strict?HttpCompliance.LEGACY:compliance());
- }
-
- /* ------------------------------------------------------------------------------- */
- @Deprecated
- public HttpParser(ResponseHandler handler,int maxHeaderBytes,boolean strict)
- {
- this(handler,maxHeaderBytes,strict?HttpCompliance.LEGACY:compliance());
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpParser(RequestHandler handler,HttpCompliance compliance)
- {
- this(handler,-1,compliance);
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpParser(RequestHandler handler,int maxHeaderBytes,HttpCompliance compliance)
- {
- _handler=handler;
- _requestHandler=handler;
- _responseHandler=null;
- _maxHeaderBytes=maxHeaderBytes;
- _compliance=compliance==null?compliance():compliance;
- _complianceHandler=(ComplianceHandler)(handler instanceof ComplianceHandler?handler:null);
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpParser(ResponseHandler handler,int maxHeaderBytes,HttpCompliance compliance)
- {
- _handler=handler;
- _requestHandler=null;
- _responseHandler=handler;
- _maxHeaderBytes=maxHeaderBytes;
- _compliance=compliance==null?compliance():compliance;
- _complianceHandler=(ComplianceHandler)(handler instanceof ComplianceHandler?handler:null);
- }
-
- /* ------------------------------------------------------------------------------- */
- public HttpHandler getHandler()
- {
- return _handler;
- }
-
- /* ------------------------------------------------------------------------------- */
- /** Check RFC compliance violation
- * @param compliance The compliance level violated
- * @param reason The reason for the violation
- * @return True if the current compliance level is set so as to Not allow this violation
- */
- protected boolean complianceViolation(HttpCompliance compliance,String reason)
- {
- if (_complianceHandler==null)
- return _compliance.ordinal()>=compliance.ordinal();
- if (_compliance.ordinal()=State.CONTENT.ordinal() && _state.ordinal()0 && _state.ordinal() SPACE)
- {
- _string.setLength(0);
- _string.append((char)ch);
- setState(_requestHandler!=null?State.METHOD:State.RESPONSE_VERSION);
- return false;
- }
- else if (ch==0)
- break;
- else if (ch<0)
- throw new BadMessageException();
-
- // count this white space as a header byte to avoid DOS
- if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
- {
- LOG.warn("padding is too large >"+_maxHeaderBytes);
- throw new BadMessageException(HttpStatus.BAD_REQUEST_400);
- }
- }
- return false;
- }
-
- /* ------------------------------------------------------------------------------- */
- private void setString(String s)
- {
- _string.setLength(0);
- _string.append(s);
- _length=s.length();
- }
-
- /* ------------------------------------------------------------------------------- */
- private String takeString()
- {
- _string.setLength(_length);
- String s =_string.toString();
- _string.setLength(0);
- _length=-1;
- return s;
- }
-
- /* ------------------------------------------------------------------------------- */
- /* Parse a request or response line
- */
- private boolean parseLine(ByteBuffer buffer)
- {
- boolean handle=false;
-
- // Process headers
- while (_state.ordinal()0 && ++_headerBytes>_maxHeaderBytes)
- {
- if (_state==State.URI)
- {
- LOG.warn("URI is too large >"+_maxHeaderBytes);
- throw new BadMessageException(HttpStatus.REQUEST_URI_TOO_LONG_414);
- }
- else
- {
- if (_requestHandler!=null)
- LOG.warn("request is too large >"+_maxHeaderBytes);
- else
- LOG.warn("response is too large >"+_maxHeaderBytes);
- throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
- }
- }
-
- switch (_state)
- {
- case METHOD:
- if (ch == SPACE)
- {
- _length=_string.length();
- _methodString=takeString();
- HttpMethod method=HttpMethod.CACHE.get(_methodString);
- if (method!=null)
- _methodString=legacyString(_methodString,method.asString());
- setState(State.SPACE1);
- }
- else if (ch < SPACE)
- {
- if (ch==LINE_FEED)
- throw new BadMessageException("No URI");
- else
- throw new IllegalCharacterException(_state,ch,buffer);
- }
- else
- _string.append((char)ch);
- break;
-
- case RESPONSE_VERSION:
- if (ch == HttpTokens.SPACE)
- {
- _length=_string.length();
- String version=takeString();
- _version=HttpVersion.CACHE.get(version);
- if (_version==null)
- throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Unknown Version");
- setState(State.SPACE1);
- }
- else if (ch < HttpTokens.SPACE)
- throw new IllegalCharacterException(_state,ch,buffer);
- else
- _string.append((char)ch);
- break;
-
- case SPACE1:
- if (ch > HttpTokens.SPACE || ch<0)
- {
- if (_responseHandler!=null)
- {
- setState(State.STATUS);
- setResponseStatus(ch-'0');
- }
- else
- {
- _uri.reset();
- setState(State.URI);
- // quick scan for space or EoBuffer
- if (buffer.hasArray())
- {
- byte[] array=buffer.array();
- int p=buffer.arrayOffset()+buffer.position();
- int l=buffer.arrayOffset()+buffer.limit();
- int i=p;
- while (iHttpTokens.SPACE)
- i++;
-
- int len=i-p;
- _headerBytes+=len;
-
- if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
- {
- LOG.warn("URI is too large >"+_maxHeaderBytes);
- throw new BadMessageException(HttpStatus.REQUEST_URI_TOO_LONG_414);
- }
- _uri.append(array,p-1,len+1);
- buffer.position(i-buffer.arrayOffset());
- }
- else
- _uri.append(ch);
- }
- }
- else if (ch < HttpTokens.SPACE)
- {
- throw new BadMessageException(HttpStatus.BAD_REQUEST_400,_requestHandler!=null?"No URI":"No Status");
- }
- break;
-
- case STATUS:
- if (ch == HttpTokens.SPACE)
- {
- setState(State.SPACE2);
- }
- else if (ch>='0' && ch<='9')
- {
- _responseStatus=_responseStatus*10+(ch-'0');
- }
- else if (ch < HttpTokens.SPACE && ch>=0)
- {
- setState(State.HEADER);
- handle=_responseHandler.startResponse(_version, _responseStatus, null)||handle;
- }
- else
- {
- throw new BadMessageException();
- }
- break;
-
- case URI:
- if (ch == HttpTokens.SPACE)
- {
- setState(State.SPACE2);
- }
- else if (ch < HttpTokens.SPACE && ch>=0)
- {
- // HTTP/0.9
- if (complianceViolation(RFC7230,"HTTP/0.9"))
- throw new BadMessageException("HTTP/0.9 not supported");
- handle=_requestHandler.startRequest(_methodString,_uri.toString(), HttpVersion.HTTP_0_9);
- setState(State.END);
- BufferUtil.clear(buffer);
- handle=_handler.headerComplete()||handle;
- handle=_handler.messageComplete()||handle;
- return handle;
- }
- else
- {
- _uri.append(ch);
- }
- break;
-
- case SPACE2:
- if (ch > HttpTokens.SPACE)
- {
- _string.setLength(0);
- _string.append((char)ch);
- if (_responseHandler!=null)
- {
- _length=1;
- setState(State.REASON);
- }
- else
- {
- setState(State.REQUEST_VERSION);
-
- // try quick look ahead for HTTP Version
- HttpVersion version;
- if (buffer.position()>0 && buffer.hasArray())
- version=HttpVersion.lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position()-1,buffer.arrayOffset()+buffer.limit());
- else
- version=HttpVersion.CACHE.getBest(buffer,0,buffer.remaining());
-
- if (version!=null)
- {
- int pos = buffer.position()+version.asString().length()-1;
- if (pos=HttpVersion.HTTP_1_1.getVersion() && _handler.getHeaderCacheSize()>0)
- {
- int header_cache = _handler.getHeaderCacheSize();
- _connectionFields=new ArrayTernaryTrie<>(header_cache);
- }
-
- setState(State.HEADER);
-
- handle=_requestHandler.startRequest(_methodString,_uri.toString(), _version)||handle;
- continue;
- }
- else if (ch>=HttpTokens.SPACE)
- _string.append((char)ch);
- else
- throw new BadMessageException();
-
- break;
-
- case REASON:
- if (ch == HttpTokens.LINE_FEED)
- {
- String reason=takeString();
- setState(State.HEADER);
- handle=_responseHandler.startResponse(_version, _responseStatus, reason)||handle;
- continue;
- }
- else if (ch>=HttpTokens.SPACE)
- {
- _string.append((char)ch);
- if (ch!=' '&&ch!='\t')
- _length=_string.length();
- }
- else
- throw new BadMessageException();
- break;
-
- default:
- throw new IllegalStateException(_state.toString());
-
- }
- }
-
- return handle;
- }
-
- private void parsedHeader()
- {
- // handler last header if any. Delayed to here just in case there was a continuation line (above)
- if (_headerString!=null || _valueString!=null)
- {
- // Handle known headers
- if (_header!=null)
- {
- boolean add_to_connection_trie=false;
- switch (_header)
- {
- case CONTENT_LENGTH:
- if (_endOfContent == EndOfContent.CONTENT_LENGTH)
- {
- throw new BadMessageException(HttpStatus.BAD_REQUEST_400, "Duplicate Content-Length");
- }
- else if (_endOfContent != EndOfContent.CHUNKED_CONTENT)
- {
- _contentLength=convertContentLength(_valueString);
- if (_contentLength <= 0)
- _endOfContent=EndOfContent.NO_CONTENT;
- else
- _endOfContent=EndOfContent.CONTENT_LENGTH;
- }
- break;
-
- case TRANSFER_ENCODING:
- if (_value==HttpHeaderValue.CHUNKED)
- {
- _endOfContent=EndOfContent.CHUNKED_CONTENT;
- _contentLength=-1;
- }
- else
- {
- if (_valueString.endsWith(HttpHeaderValue.CHUNKED.toString()))
- _endOfContent=EndOfContent.CHUNKED_CONTENT;
- else if (_valueString.contains(HttpHeaderValue.CHUNKED.toString()))
- throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad chunking");
- }
- break;
-
- case HOST:
- _host=true;
- if (!(_field instanceof HostPortHttpField))
- {
- _field=new HostPortHttpField(_header,legacyString(_headerString,_header.asString()),_valueString);
- add_to_connection_trie=_connectionFields!=null;
- }
- break;
-
- case CONNECTION:
- // Don't cache if not persistent
- if (_valueString!=null && _valueString.contains("close"))
- _connectionFields=null;
-
- break;
-
- case AUTHORIZATION:
- case ACCEPT:
- case ACCEPT_CHARSET:
- case ACCEPT_ENCODING:
- case ACCEPT_LANGUAGE:
- case COOKIE:
- case CACHE_CONTROL:
- case USER_AGENT:
- add_to_connection_trie=_connectionFields!=null && _field==null;
- break;
-
- default: break;
- }
-
- if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null)
- {
- if (_field==null)
- _field=new HttpField(_header,legacyString(_headerString,_header.asString()),_valueString);
- _connectionFields.put(_field);
- }
- }
- _handler.parsedHeader(_field!=null?_field:new HttpField(_header,_headerString,_valueString));
- }
-
- _headerString=_valueString=null;
- _header=null;
- _value=null;
- _field=null;
- }
-
- private long convertContentLength(String valueString)
- {
- try
- {
- return Long.parseLong(valueString);
- }
- catch(NumberFormatException e)
- {
- LOG.ignore(e);
- throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Invalid Content-Length Value");
- }
- }
-
- /* ------------------------------------------------------------------------------- */
- /*
- * Parse the message headers and return true if the handler has signaled for a return
- */
- protected boolean parseHeaders(ByteBuffer buffer)
- {
- boolean handle=false;
-
- // Process headers
- while (_state.ordinal()0 && ++_headerBytes>_maxHeaderBytes)
- {
- LOG.warn("Header is too large >"+_maxHeaderBytes);
- throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
- }
-
- switch (_state)
- {
- case HEADER:
- switch(ch)
- {
- case HttpTokens.COLON:
- case HttpTokens.SPACE:
- case HttpTokens.TAB:
- {
- if (complianceViolation(RFC7230,"header folding"))
- throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Header Folding");
-
- // header value without name - continuation?
- if (_valueString==null)
- {
- _string.setLength(0);
- _length=0;
- }
- else
- {
- setString(_valueString);
- _string.append(' ');
- _length++;
- _valueString=null;
- }
- setState(State.HEADER_VALUE);
- break;
- }
-
- case HttpTokens.LINE_FEED:
- {
- // process previous header
- parsedHeader();
-
- _contentPosition=0;
-
- // End of headers!
-
- // Was there a required host header?
- if (!_host && _version==HttpVersion.HTTP_1_1 && _requestHandler!=null)
- {
- throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"No Host");
- }
-
- // is it a response that cannot have a body?
- if (_responseHandler !=null && // response
- (_responseStatus == 304 || // not-modified response
- _responseStatus == 204 || // no-content response
- _responseStatus < 200)) // 1xx response
- _endOfContent=EndOfContent.NO_CONTENT; // ignore any other headers set
-
- // else if we don't know framing
- else if (_endOfContent == EndOfContent.UNKNOWN_CONTENT)
- {
- if (_responseStatus == 0 // request
- || _responseStatus == 304 // not-modified response
- || _responseStatus == 204 // no-content response
- || _responseStatus < 200) // 1xx response
- _endOfContent=EndOfContent.NO_CONTENT;
- else
- _endOfContent=EndOfContent.EOF_CONTENT;
- }
-
- // How is the message ended?
- switch (_endOfContent)
- {
- case EOF_CONTENT:
- setState(State.EOF_CONTENT);
- handle=_handler.headerComplete()||handle;
- return handle;
-
- case CHUNKED_CONTENT:
- setState(State.CHUNKED_CONTENT);
- handle=_handler.headerComplete()||handle;
- return handle;
-
- case NO_CONTENT:
- setState(State.END);
- handle=_handler.headerComplete()||handle;
- handle=_handler.messageComplete()||handle;
- return handle;
-
- default:
- setState(State.CONTENT);
- handle=_handler.headerComplete()||handle;
- return handle;
- }
- }
-
- default:
- {
- // now handle the ch
- if (chHttpTokens.SPACE)
- {
- if (_header!=null)
- {
- setString(_header.asString());
- _header=null;
- _headerString=null;
- }
-
- _string.append((char)ch);
- if (ch>HttpTokens.SPACE)
- _length=_string.length();
- break;
- }
-
- if (ch==HttpTokens.LINE_FEED && !complianceViolation(RFC7230,"name only header"))
- {
- if (_headerString==null)
- {
- _headerString=takeString();
- _header=HttpHeader.CACHE.get(_headerString);
- }
- _value=null;
- _string.setLength(0);
- _valueString="";
- _length=-1;
-
- setState(State.HEADER);
- break;
- }
-
- throw new IllegalCharacterException(_state,ch,buffer);
-
- case HEADER_VALUE:
- if (ch>HttpTokens.SPACE || ch<0)
- {
- _string.append((char)(0xff&ch));
- _length=_string.length();
- setState(State.HEADER_IN_VALUE);
- break;
- }
-
- if (ch==HttpTokens.SPACE || ch==HttpTokens.TAB)
- break;
-
- if (ch==HttpTokens.LINE_FEED)
- {
- _value=null;
- _string.setLength(0);
- _valueString="";
- _length=-1;
-
- setState(State.HEADER);
- break;
- }
- throw new IllegalCharacterException(_state,ch,buffer);
-
- case HEADER_IN_VALUE:
- if (ch>=HttpTokens.SPACE || ch<0 || ch==HttpTokens.TAB)
- {
- if (_valueString!=null)
- {
- setString(_valueString);
- _valueString=null;
- _field=null;
- }
- _string.append((char)(0xff&ch));
- if (ch>HttpTokens.SPACE || ch<0)
- _length=_string.length();
- break;
- }
-
- if (ch==HttpTokens.LINE_FEED)
- {
- if (_length > 0)
- {
- _value=null;
- _valueString=takeString();
- _length=-1;
- }
- setState(State.HEADER);
- break;
- }
-
- throw new IllegalCharacterException(_state,ch,buffer);
-
- default:
- throw new IllegalStateException(_state.toString());
-
- }
- }
-
- return handle;
- }
-
- /* ------------------------------------------------------------------------------- */
- /**
- * Parse until next Event.
- * @param buffer the buffer to parse
- * @return True if an {@link RequestHandler} method was called and it returned true;
- */
- public boolean parseNext(ByteBuffer buffer)
- {
- if (DEBUG)
- LOG.debug("parseNext s={} {}",_state,BufferUtil.toDetailString(buffer));
- try
- {
- // Start a request/response
- if (_state==State.START)
- {
- _version=null;
- _method=null;
- _methodString=null;
- _endOfContent=EndOfContent.UNKNOWN_CONTENT;
- _header=null;
- if (quickStart(buffer))
- return true;
- }
-
- // Request/response line
- if (_state.ordinal()>= State.START.ordinal() && _state.ordinal()= State.HEADER.ordinal() && _state.ordinal()= State.CONTENT.ordinal() && _state.ordinal()0 && _headResponse)
- {
- setState(State.END);
- return _handler.messageComplete();
- }
- else
- {
- if (parseContent(buffer))
- return true;
- }
- }
-
- // handle end states
- if (_state==State.END)
- {
- // eat white space
- while (buffer.remaining()>0 && buffer.get(buffer.position())<=HttpTokens.SPACE)
- buffer.get();
- }
- else if (_state==State.CLOSE)
- {
- // Seeking EOF
- if (BufferUtil.hasContent(buffer))
- {
- // Just ignore data when closed
- _headerBytes+=buffer.remaining();
- BufferUtil.clear(buffer);
- if (_maxHeaderBytes>0 && _headerBytes>_maxHeaderBytes)
- {
- // Don't want to waste time reading data of a closed request
- throw new IllegalStateException("too much data seeking EOF");
- }
- }
- }
- else if (_state==State.CLOSED)
- {
- BufferUtil.clear(buffer);
- }
-
- // Handle EOF
- if (_eof && !buffer.hasRemaining())
- {
- switch(_state)
- {
- case CLOSED:
- break;
-
- case START:
- setState(State.CLOSED);
- _handler.earlyEOF();
- break;
-
- case END:
- case CLOSE:
- setState(State.CLOSED);
- break;
-
- case EOF_CONTENT:
- setState(State.CLOSED);
- return _handler.messageComplete();
-
- case CONTENT:
- case CHUNKED_CONTENT:
- case CHUNK_SIZE:
- case CHUNK_PARAMS:
- case CHUNK:
- setState(State.CLOSED);
- _handler.earlyEOF();
- break;
-
- default:
- if (DEBUG)
- LOG.debug("{} EOF in {}",this,_state);
- setState(State.CLOSED);
- _handler.badMessage(400,null);
- break;
- }
- }
- }
- catch(BadMessageException e)
- {
- BufferUtil.clear(buffer);
-
- Throwable cause = e.getCause();
- boolean stack = LOG.isDebugEnabled() ||
- (!(cause instanceof NumberFormatException ) && (cause instanceof RuntimeException || cause instanceof Error));
-
- if (stack)
- LOG.warn("bad HTTP parsed: "+e._code+(e.getReason()!=null?" "+e.getReason():"")+" for "+_handler,e);
- else
- LOG.warn("bad HTTP parsed: "+e._code+(e.getReason()!=null?" "+e.getReason():"")+" for "+_handler);
- setState(State.CLOSE);
- _handler.badMessage(e.getCode(), e.getReason());
- }
- catch(NumberFormatException|IllegalStateException e)
- {
- BufferUtil.clear(buffer);
- LOG.warn("parse exception: {} in {} for {}",e.toString(),_state,_handler);
- if (DEBUG)
- LOG.debug(e);
-
- switch(_state)
- {
- case CLOSED:
- break;
- case CLOSE:
- _handler.earlyEOF();
- break;
- default:
- setState(State.CLOSE);
- _handler.badMessage(400,"Bad Message "+e.toString());
- }
- }
- catch(Exception|Error e)
- {
- BufferUtil.clear(buffer);
-
- LOG.warn("parse exception: "+e.toString()+" for "+_handler,e);
-
- switch(_state)
- {
- case CLOSED:
- break;
- case CLOSE:
- _handler.earlyEOF();
- break;
- default:
- setState(State.CLOSE);
- _handler.badMessage(400,null);
- }
- }
- return false;
- }
-
- protected boolean parseContent(ByteBuffer buffer)
- {
- int remaining=buffer.remaining();
- if (remaining==0 && _state==State.CONTENT)
- {
- long content=_contentLength - _contentPosition;
- if (content == 0)
- {
- setState(State.END);
- return _handler.messageComplete();
- }
- }
-
- // Handle _content
- byte ch;
- while (_state.ordinal() < State.END.ordinal() && remaining>0)
- {
- switch (_state)
- {
- case EOF_CONTENT:
- _contentChunk=buffer.asReadOnlyBuffer();
- _contentPosition += remaining;
- buffer.position(buffer.position()+remaining);
- if (_handler.content(_contentChunk))
- return true;
- break;
-
- case CONTENT:
- {
- long content=_contentLength - _contentPosition;
- if (content == 0)
- {
- setState(State.END);
- return _handler.messageComplete();
- }
- else
- {
- _contentChunk=buffer.asReadOnlyBuffer();
-
- // limit content by expected size
- if (remaining > content)
- {
- // We can cast remaining to an int as we know that it is smaller than
- // or equal to length which is already an int.
- _contentChunk.limit(_contentChunk.position()+(int)content);
- }
-
- _contentPosition += _contentChunk.remaining();
- buffer.position(buffer.position()+_contentChunk.remaining());
-
- if (_handler.content(_contentChunk))
- return true;
-
- if(_contentPosition == _contentLength)
- {
- setState(State.END);
- return _handler.messageComplete();
- }
- }
- break;
- }
-
- case CHUNKED_CONTENT:
- {
- ch=next(buffer);
- if (ch>HttpTokens.SPACE)
- {
- _chunkLength=TypeUtil.convertHexDigit(ch);
- _chunkPosition=0;
- setState(State.CHUNK_SIZE);
- }
-
- break;
- }
-
- case CHUNK_SIZE:
- {
- ch=next(buffer);
- if (ch==0)
- break;
- if (ch == HttpTokens.LINE_FEED)
- {
- if (_chunkLength == 0)
- setState(State.CHUNK_END);
- else
- setState(State.CHUNK);
- }
- else if (ch <= HttpTokens.SPACE || ch == HttpTokens.SEMI_COLON)
- setState(State.CHUNK_PARAMS);
- else
- _chunkLength=_chunkLength * 16 + TypeUtil.convertHexDigit(ch);
- break;
- }
-
- case CHUNK_PARAMS:
- {
- ch=next(buffer);
- if (ch == HttpTokens.LINE_FEED)
- {
- if (_chunkLength == 0)
- setState(State.CHUNK_END);
- else
- setState(State.CHUNK);
- }
- break;
- }
-
- case CHUNK:
- {
- int chunk=_chunkLength - _chunkPosition;
- if (chunk == 0)
- {
- setState(State.CHUNKED_CONTENT);
- }
- else
- {
- _contentChunk=buffer.asReadOnlyBuffer();
-
- if (remaining > chunk)
- _contentChunk.limit(_contentChunk.position()+chunk);
- chunk=_contentChunk.remaining();
-
- _contentPosition += chunk;
- _chunkPosition += chunk;
- buffer.position(buffer.position()+chunk);
- if (_handler.content(_contentChunk))
- return true;
- }
- break;
- }
-
- case CHUNK_END:
- {
- // TODO handle chunk trailer
- ch=next(buffer);
- if (ch==0)
- break;
- if (ch == HttpTokens.LINE_FEED)
- {
- setState(State.END);
- return _handler.messageComplete();
- }
- throw new IllegalCharacterException(_state,ch,buffer);
- }
-
- case CLOSED:
- {
- BufferUtil.clear(buffer);
- return false;
- }
-
- default:
- break;
-
- }
-
- remaining=buffer.remaining();
- }
- return false;
- }
-
- /* ------------------------------------------------------------------------------- */
- public boolean isAtEOF()
-
- {
- return _eof;
- }
-
- /* ------------------------------------------------------------------------------- */
- /** Signal that the associated data source is at EOF
- */
- public void atEOF()
- {
- if (DEBUG)
- LOG.debug("atEOF {}", this);
- _eof=true;
- }
-
- /* ------------------------------------------------------------------------------- */
- /** Request that the associated data source be closed
- */
- public void close()
- {
- if (DEBUG)
- LOG.debug("close {}", this);
- setState(State.CLOSE);
- }
-
- /* ------------------------------------------------------------------------------- */
- public void reset()
- {
- if (DEBUG)
- LOG.debug("reset {}", this);
-
- // reset state
- if (_state==State.CLOSE || _state==State.CLOSED)
- return;
-
- setState(State.START);
- _endOfContent=EndOfContent.UNKNOWN_CONTENT;
- _contentLength=-1;
- _contentPosition=0;
- _responseStatus=0;
- _contentChunk=null;
- _headerBytes=0;
- _host=false;
- }
-
- /* ------------------------------------------------------------------------------- */
- protected void setState(State state)
- {
- if (DEBUG)
- LOG.debug("{} --> {}",_state,state);
- _state=state;
- }
-
- /* ------------------------------------------------------------------------------- */
- public Trie getFieldCache()
- {
- return _connectionFields;
- }
-
- /* ------------------------------------------------------------------------------- */
- private String getProxyField(ByteBuffer buffer)
- {
- _string.setLength(0);
- _length=0;
-
- while (buffer.hasRemaining())
- {
- // process each character
- byte ch=next(buffer);
- if (ch<=' ')
- return _string.toString();
- _string.append((char)ch);
- }
- throw new BadMessageException();
- }
-
- /* ------------------------------------------------------------------------------- */
- @Override
- public String toString()
- {
- return String.format("%s{s=%s,%d of %d}",
- getClass().getSimpleName(),
- _state,
- _contentPosition,
- _contentLength);
- }
-
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- /* Event Handler interface
- * These methods return true if the caller should process the events
- * so far received (eg return from parseNext and call HttpChannel.handle).
- * If multiple callbacks are called in sequence (eg
- * headerComplete then messageComplete) from the same point in the parsing
- * then it is sufficient for the caller to process the events only once.
- */
- public interface HttpHandler
- {
- public boolean content(ByteBuffer item);
-
- public boolean headerComplete();
-
- public boolean messageComplete();
-
- /**
- * This is the method called by parser when a HTTP Header name and value is found
- * @param field The field parsed
- */
- public void parsedHeader(HttpField field);
-
- /* ------------------------------------------------------------ */
- /** Called to signal that an EOF was received unexpectedly
- * during the parsing of a HTTP message
- */
- public void earlyEOF();
-
- /* ------------------------------------------------------------ */
- /** Called to signal that a bad HTTP message has been received.
- * @param status The bad status to send
- * @param reason The textual reason for badness
- */
- public void badMessage(int status, String reason);
-
- /* ------------------------------------------------------------ */
- /** @return the size in bytes of the per parser header cache
- */
- public int getHeaderCacheSize();
- }
-
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- public interface RequestHandler extends HttpHandler
- {
- /**
- * This is the method called by parser when the HTTP request line is parsed
- * @param method The method
- * @param uri The raw bytes of the URI. These are copied into a ByteBuffer that will not be changed until this parser is reset and reused.
- * @param version the http version in use
- * @return true if handling parsing should return.
- */
- public boolean startRequest(String method, String uri, HttpVersion version);
-
- }
-
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- public interface ResponseHandler extends HttpHandler
- {
- /**
- * This is the method called by parser when the HTTP request line is parsed
- * @param version the http version in use
- * @param status the response status
- * @param reason the response reason phrase
- * @return true if handling parsing should return
- */
- public boolean startResponse(HttpVersion version, int status, String reason);
- }
-
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- /* ------------------------------------------------------------------------------- */
- public interface ComplianceHandler extends HttpHandler
- {
- public void onComplianceViolation(HttpCompliance compliance,HttpCompliance required,String reason);
- }
-
- /* ------------------------------------------------------------------------------- */
- @SuppressWarnings("serial")
- private static class IllegalCharacterException extends BadMessageException
- {
- private IllegalCharacterException(State state,byte ch,ByteBuffer buffer)
- {
- super(400,String.format("Illegal character 0x%X",ch));
- // Bug #460642 - don't reveal buffers to end user
- LOG.warn(String.format("Illegal character 0x%X in state=%s for buffer %s",ch,state,BufferUtil.toDetailString(buffer)));
- }
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpScheme.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpScheme.java
deleted file mode 100644
index 44ac0c6bc7..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpScheme.java
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.nio.ByteBuffer;
-
-import org.eclipse.jetty.util.ArrayTrie;
-import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.Trie;
-
-/* ------------------------------------------------------------------------------- */
-/**
- */
-public enum HttpScheme
-{
- HTTP("http"),
- HTTPS("https"),
- WS("ws"),
- WSS("wss");
-
- /* ------------------------------------------------------------ */
- public final static Trie CACHE= new ArrayTrie();
- static
- {
- for (HttpScheme version : HttpScheme.values())
- CACHE.put(version.asString(),version);
- }
-
- private final String _string;
- private final ByteBuffer _buffer;
-
- /* ------------------------------------------------------------ */
- HttpScheme(String s)
- {
- _string=s;
- _buffer=BufferUtil.toBuffer(s);
- }
-
- /* ------------------------------------------------------------ */
- public ByteBuffer asByteBuffer()
- {
- return _buffer.asReadOnlyBuffer();
- }
-
- /* ------------------------------------------------------------ */
- public boolean is(String s)
- {
- return s!=null && _string.equalsIgnoreCase(s);
- }
-
- public String asString()
- {
- return _string;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String toString()
- {
- return _string;
- }
-
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpStatus.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpStatus.java
deleted file mode 100644
index 5682889537..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpStatus.java
+++ /dev/null
@@ -1,1076 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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;
-
-/**
- *
- * HttpStatusCode enum class, for status codes based on various HTTP RFCs. (see
- * table below)
- *
- *
- *
- * HTTP Status Codes Table
- *
- * Enum |
- * Code |
- * Message |
- *
- * RFC 1945 - HTTP/1.0 |
- *
- * RFC 7231 - HTTP/1.1 Semantics and Content |
- *
- * RFC 7238 - HTTP/1.1 Permanent Redirect |
- *
- * RFC 2518 - WEBDAV |
- *
- *
- *
- * Informational - 1xx |
- * {@link #isInformational(int)} |
- *
- *
- *
- * {@link #CONTINUE_100} |
- * 100 |
- * Continue |
- * |
- *
- * Sec. 6.2.1 |
- * |
- *
- *
- * {@link #SWITCHING_PROTOCOLS_101} |
- * 101 |
- * Switching Protocols |
- * |
- *
- * Sec. 6.2.2 |
- * |
- *
- *
- * {@link #PROCESSING_102} |
- * 102 |
- * Processing |
- * |
- * |
- *
- * Sec. 10.1 |
- *
- *
- *
- * Success - 2xx |
- * {@link #isSuccess(int)} |
- *
- *
- *
- * {@link #OK_200} |
- * 200 |
- * OK |
- *
- * Sec. 9.2 |
- *
- * Sec. 6.3.1 |
- * |
- *
- *
- * {@link #CREATED_201} |
- * 201 |
- * Created |
- *
- * Sec. 9.2 |
- *
- * Sec. 6.3.2 |
- * |
- *
- *
- * {@link #ACCEPTED_202} |
- * 202 |
- * Accepted |
- *
- * Sec. 9.2 |
- *
- * Sec. 6.3.3 |
- * |
- *
- *
- * {@link #NON_AUTHORITATIVE_INFORMATION_203} |
- * 203 |
- * Non Authoritative Information |
- * |
- *
- * Sec. 6.3.4 |
- * |
- *
- *
- * {@link #NO_CONTENT_204} |
- * 204 |
- * No Content |
- *
- * Sec. 9.2 |
- *
- * Sec. 6.3.5 |
- * |
- *
- *
- * {@link #RESET_CONTENT_205} |
- * 205 |
- * Reset Content |
- * |
- *
- * Sec. 6.3.6 |
- * |
- *
- *
- * {@link #PARTIAL_CONTENT_206} |
- * 206 |
- * Partial Content |
- * |
- *
- * Sec. 6.3.7 |
- * |
- *
- *
- * {@link #MULTI_STATUS_207} |
- * 207 |
- * Multi-Status |
- * |
- * |
- *
- * Sec. 10.2 |
- *
- *
- * |
- * 207 |
- * Partial Update OK |
- * |
- *
- * draft/01 |
- * |
- *
- *
- *
- * Redirection - 3xx |
- * {@link #isRedirection(int)} |
- *
- *
- *
- * {@link #MULTIPLE_CHOICES_300} |
- * 300 |
- * Multiple Choices |
- *
- * Sec. 9.3 |
- *
- * Sec. 6.4.1 |
- * |
- *
- *
- * {@link #MOVED_PERMANENTLY_301} |
- * 301 |
- * Moved Permanently |
- *
- * Sec. 9.3 |
- *
- * Sec. 6.4.2 |
- * |
- *
- *
- * {@link #MOVED_TEMPORARILY_302} |
- * 302 |
- * Moved Temporarily |
- *
- * Sec. 9.3 |
- * (now "302 Found ") |
- * |
- *
- *
- * {@link #FOUND_302} |
- * 302 |
- * Found |
- * (was "302 Moved Temporarily ") |
- *
- * Sec. 6.4.3 |
- * |
- *
- *
- * {@link #SEE_OTHER_303} |
- * 303 |
- * See Other |
- * |
- *
- * Sec. 6.4.4 |
- * |
- *
- *
- * {@link #NOT_MODIFIED_304} |
- * 304 |
- * Not Modified |
- *
- * Sec. 9.3 |
- *
- * Sec. 6.4.5 |
- * |
- *
- *
- * {@link #USE_PROXY_305} |
- * 305 |
- * Use Proxy |
- * |
- *
- * Sec. 6.4.6 |
- * |
- *
- *
- * |
- * 306 |
- * (Unused) |
- * |
- *
- * Sec. 6.4.7 |
- * |
- *
- *
- * {@link #TEMPORARY_REDIRECT_307} |
- * 307 |
- * Temporary Redirect |
- * |
- *
- * Sec. 6.4.8 |
- * |
- *
- *
- *
- * {@link #PERMANENT_REDIRECT_308} |
- * 307 |
- * Permanent Redirect |
- * |
- *
- * RFC7238 |
- * |
- *
- *
- *
- * Client Error - 4xx |
- * {@link #isClientError(int)} |
- *
- *
- *
- * {@link #BAD_REQUEST_400} |
- * 400 |
- * Bad Request |
- *
- * Sec. 9.4 |
- *
- * Sec. 6.5.1 |
- * |
- *
- *
- * {@link #UNAUTHORIZED_401} |
- * 401 |
- * Unauthorized |
- *
- * Sec. 9.4 |
- *
- * Sec. 6.5.2 |
- * |
- *
- *
- * {@link #PAYMENT_REQUIRED_402} |
- * 402 |
- * Payment Required |
- *
- * Sec. 9.4 |
- *
- * Sec. 6.5.3 |
- * |
- *
- *
- * {@link #FORBIDDEN_403} |
- * 403 |
- * Forbidden |
- *
- * Sec. 9.4 |
- *
- * Sec. 6.5.4 |
- * |
- *
- *
- * {@link #NOT_FOUND_404} |
- * 404 |
- * Not Found |
- *
- * Sec. 9.4 |
- *
- * Sec. 6.5.5 |
- * |
- *
- *
- * {@link #METHOD_NOT_ALLOWED_405} |
- * 405 |
- * Method Not Allowed |
- * |
- *
- * Sec. 6.5.6 |
- * |
- *
- *
- * {@link #NOT_ACCEPTABLE_406} |
- * 406 |
- * Not Acceptable |
- * |
- *
- * Sec. 6.5.7 |
- * |
- *
- *
- * {@link #PROXY_AUTHENTICATION_REQUIRED_407} |
- * 407 |
- * Proxy Authentication Required |
- * |
- *
- * Sec. 6.5.8 |
- * |
- *
- *
- * {@link #REQUEST_TIMEOUT_408} |
- * 408 |
- * Request Timeout |
- * |
- *
- * Sec. 6.5.9 |
- * |
- *
- *
- * {@link #CONFLICT_409} |
- * 409 |
- * Conflict |
- * |
- *
- * Sec. 10.4.10
- * |
- * |
- *
- *
- * {@link #GONE_410} |
- * 410 |
- * Gone |
- * |
- *
- * Sec. 10.4.11
- * |
- * |
- *
- *
- * {@link #LENGTH_REQUIRED_411} |
- * 411 |
- * Length Required |
- * |
- *
- * Sec. 10.4.12
- * |
- * |
- *
- *
- * {@link #PRECONDITION_FAILED_412} |
- * 412 |
- * Precondition Failed |
- * |
- *
- * Sec. 10.4.13
- * |
- * |
- *
- *
- * {@link #REQUEST_ENTITY_TOO_LARGE_413} |
- * 413 |
- * Request Entity Too Large |
- * |
- *
- * Sec. 10.4.14
- * |
- * |
- *
- *
- * {@link #REQUEST_URI_TOO_LONG_414} |
- * 414 |
- * Request-URI Too Long |
- * |
- *
- * Sec. 10.4.15
- * |
- * |
- *
- *
- * {@link #UNSUPPORTED_MEDIA_TYPE_415} |
- * 415 |
- * Unsupported Media Type |
- * |
- *
- * Sec. 10.4.16
- * |
- * |
- *
- *
- * {@link #REQUESTED_RANGE_NOT_SATISFIABLE_416} |
- * 416 |
- * Requested Range Not Satisfiable |
- * |
- *
- * Sec. 10.4.17
- * |
- * |
- *
- *
- * {@link #EXPECTATION_FAILED_417} |
- * 417 |
- * Expectation Failed |
- * |
- *
- * Sec. 10.4.18
- * |
- * |
- *
- *
- * |
- * 418 |
- * Reauthentication Required |
- * |
- *
- * draft/01 |
- * |
- *
- *
- * |
- * 418 |
- * Unprocessable Entity |
- * |
- * |
- *
- * draft/05 |
- *
- *
- * |
- * 419 |
- * Proxy Reauthentication Required |
- * |
- *
- * draft/01 |
- * |
- *
- *
- * |
- * 419 |
- * Insufficient Space on Resource |
- * |
- * |
- *
- * draft/05 |
- *
- *
- * |
- * 420 |
- * Method Failure |
- * |
- * |
- *
- * draft/05 |
- *
- *
- * |
- * 421 |
- * (Unused) |
- * |
- * |
- * |
- *
- *
- * {@link #UNPROCESSABLE_ENTITY_422} |
- * 422 |
- * Unprocessable Entity |
- * |
- * |
- *
- * Sec. 10.3 |
- *
- *
- * {@link #LOCKED_423} |
- * 423 |
- * Locked |
- * |
- * |
- *
- * Sec. 10.4 |
- *
- *
- * {@link #FAILED_DEPENDENCY_424} |
- * 424 |
- * Failed Dependency |
- * |
- * |
- *
- * Sec. 10.5 |
- *
- *
- *
- * Server Error - 5xx |
- * {@link #isServerError(int)} |
- *
- *
- *
- * {@link #INTERNAL_SERVER_ERROR_500} |
- * 500 |
- * Internal Server Error |
- *
- * Sec. 9.5 |
- *
- * Sec. 6.6.1 |
- * |
- *
- *
- * {@link #NOT_IMPLEMENTED_501} |
- * 501 |
- * Not Implemented |
- *
- * Sec. 9.5 |
- *
- * Sec. 6.6.2 |
- * |
- *
- *
- * {@link #BAD_GATEWAY_502} |
- * 502 |
- * Bad Gateway |
- *
- * Sec. 9.5 |
- *
- * Sec. 6.6.3 |
- * |
- *
- *
- * {@link #SERVICE_UNAVAILABLE_503} |
- * 503 |
- * Service Unavailable |
- *
- * Sec. 9.5 |
- *
- * Sec. 6.6.4 |
- * |
- *
- *
- * {@link #GATEWAY_TIMEOUT_504} |
- * 504 |
- * Gateway Timeout |
- * |
- *
- * Sec. 6.6.5 |
- * |
- *
- *
- * {@link #HTTP_VERSION_NOT_SUPPORTED_505} |
- * 505 |
- * HTTP Version Not Supported |
- * |
- *
- * Sec. 6.6.6 |
- * |
- *
- *
- * |
- * 506 |
- * (Unused) |
- * |
- * |
- * |
- *
- *
- * {@link #INSUFFICIENT_STORAGE_507} |
- * 507 |
- * Insufficient Storage |
- * |
- * |
- *
- * Sec. 10.6 |
- *
- *
- *
- *
- * @version $Id$
- */
-public class HttpStatus
-{
- public final static int CONTINUE_100 = 100;
- public final static int SWITCHING_PROTOCOLS_101 = 101;
- public final static int PROCESSING_102 = 102;
-
- public final static int OK_200 = 200;
- public final static int CREATED_201 = 201;
- public final static int ACCEPTED_202 = 202;
- public final static int NON_AUTHORITATIVE_INFORMATION_203 = 203;
- public final static int NO_CONTENT_204 = 204;
- public final static int RESET_CONTENT_205 = 205;
- public final static int PARTIAL_CONTENT_206 = 206;
- public final static int MULTI_STATUS_207 = 207;
-
- public final static int MULTIPLE_CHOICES_300 = 300;
- public final static int MOVED_PERMANENTLY_301 = 301;
- public final static int MOVED_TEMPORARILY_302 = 302;
- public final static int FOUND_302 = 302;
- public final static int SEE_OTHER_303 = 303;
- public final static int NOT_MODIFIED_304 = 304;
- public final static int USE_PROXY_305 = 305;
- public final static int TEMPORARY_REDIRECT_307 = 307;
- public final static int PERMANENT_REDIRECT_308 = 308;
-
- public final static int BAD_REQUEST_400 = 400;
- public final static int UNAUTHORIZED_401 = 401;
- public final static int PAYMENT_REQUIRED_402 = 402;
- public final static int FORBIDDEN_403 = 403;
- public final static int NOT_FOUND_404 = 404;
- public final static int METHOD_NOT_ALLOWED_405 = 405;
- public final static int NOT_ACCEPTABLE_406 = 406;
- public final static int PROXY_AUTHENTICATION_REQUIRED_407 = 407;
- public final static int REQUEST_TIMEOUT_408 = 408;
- public final static int CONFLICT_409 = 409;
- public final static int GONE_410 = 410;
- public final static int LENGTH_REQUIRED_411 = 411;
- public final static int PRECONDITION_FAILED_412 = 412;
- public final static int REQUEST_ENTITY_TOO_LARGE_413 = 413;
- public final static int REQUEST_URI_TOO_LONG_414 = 414;
- public final static int UNSUPPORTED_MEDIA_TYPE_415 = 415;
- public final static int REQUESTED_RANGE_NOT_SATISFIABLE_416 = 416;
- public final static int EXPECTATION_FAILED_417 = 417;
- public final static int MISDIRECTED_REQUEST_421 = 421;
- public final static int UNPROCESSABLE_ENTITY_422 = 422;
- public final static int LOCKED_423 = 423;
- public final static int FAILED_DEPENDENCY_424 = 424;
- public final static int UPGRADE_REQUIRED_426 = 426;
-
- public final static int INTERNAL_SERVER_ERROR_500 = 500;
- public final static int NOT_IMPLEMENTED_501 = 501;
- public final static int BAD_GATEWAY_502 = 502;
- public final static int SERVICE_UNAVAILABLE_503 = 503;
- public final static int GATEWAY_TIMEOUT_504 = 504;
- public final static int HTTP_VERSION_NOT_SUPPORTED_505 = 505;
- public final static int INSUFFICIENT_STORAGE_507 = 507;
-
- // RFC 6585
- public final static int PRECONDITION_REQUIRED_428 = 428;
- public final static int TOO_MANY_REQUESTS_429 = 429;
- public final static int REQUEST_HEADER_FIELDS_TOO_LARGE_431 = 431;
- public final static int NETWORK_AUTHENTICATION_REQUIRED_511 = 511;
-
- public static final int MAX_CODE = 511;
-
- private static final Code[] codeMap = new Code[MAX_CODE+1];
-
- static
- {
- for (Code code : Code.values())
- {
- codeMap[code._code] = code;
- }
- }
-
-
- public enum Code
- {
- /*
- * --------------------------------------------------------------------
- * Informational messages in 1xx series. As defined by ... RFC 1945 -
- * HTTP/1.0 RFC 7231 - HTTP/1.1 RFC 2518 - WebDAV
- */
-
- /** 100 Continue
*/
- CONTINUE(CONTINUE_100, "Continue"),
- /** 101 Switching Protocols
*/
- SWITCHING_PROTOCOLS(SWITCHING_PROTOCOLS_101, "Switching Protocols"),
- /** 102 Processing
*/
- PROCESSING(PROCESSING_102, "Processing"),
-
- /*
- * --------------------------------------------------------------------
- * Success messages in 2xx series. As defined by ... RFC 1945 - HTTP/1.0
- * RFC 7231 - HTTP/1.1 RFC 2518 - WebDAV
- */
-
- /** 200 OK
*/
- OK(OK_200, "OK"),
- /** 201 Created
*/
- CREATED(CREATED_201, "Created"),
- /** 202 Accepted
*/
- ACCEPTED(ACCEPTED_202, "Accepted"),
- /** 203 Non Authoritative Information
*/
- NON_AUTHORITATIVE_INFORMATION(NON_AUTHORITATIVE_INFORMATION_203, "Non Authoritative Information"),
- /** 204 No Content
*/
- NO_CONTENT(NO_CONTENT_204, "No Content"),
- /** 205 Reset Content
*/
- RESET_CONTENT(RESET_CONTENT_205, "Reset Content"),
- /** 206 Partial Content
*/
- PARTIAL_CONTENT(PARTIAL_CONTENT_206, "Partial Content"),
- /** 207 Multi-Status
*/
- MULTI_STATUS(MULTI_STATUS_207, "Multi-Status"),
-
- /*
- * --------------------------------------------------------------------
- * Redirection messages in 3xx series. As defined by ... RFC 1945 -
- * HTTP/1.0 RFC 7231 - HTTP/1.1
- */
-
- /** 300 Mutliple Choices
*/
- MULTIPLE_CHOICES(MULTIPLE_CHOICES_300, "Multiple Choices"),
- /** 301 Moved Permanently
*/
- MOVED_PERMANENTLY(MOVED_PERMANENTLY_301, "Moved Permanently"),
- /** 302 Moved Temporarily
*/
- MOVED_TEMPORARILY(MOVED_TEMPORARILY_302, "Moved Temporarily"),
- /** 302 Found
*/
- FOUND(FOUND_302, "Found"),
- /** 303 See Other
*/
- SEE_OTHER(SEE_OTHER_303, "See Other"),
- /** 304 Not Modified
*/
- NOT_MODIFIED(NOT_MODIFIED_304, "Not Modified"),
- /** 305 Use Proxy
*/
- USE_PROXY(USE_PROXY_305, "Use Proxy"),
- /** 307 Temporary Redirect
*/
- TEMPORARY_REDIRECT(TEMPORARY_REDIRECT_307, "Temporary Redirect"),
- /** 308 Permanent Redirect
*/
- PERMANET_REDIRECT(PERMANENT_REDIRECT_308, "Permanent Redirect"),
-
- /*
- * --------------------------------------------------------------------
- * Client Error messages in 4xx series. As defined by ... RFC 1945 -
- * HTTP/1.0 RFC 7231 - HTTP/1.1 RFC 2518 - WebDAV
- */
-
- /** 400 Bad Request
*/
- BAD_REQUEST(BAD_REQUEST_400, "Bad Request"),
- /** 401 Unauthorized
*/
- UNAUTHORIZED(UNAUTHORIZED_401, "Unauthorized"),
- /** 402 Payment Required
*/
- PAYMENT_REQUIRED(PAYMENT_REQUIRED_402, "Payment Required"),
- /** 403 Forbidden
*/
- FORBIDDEN(FORBIDDEN_403, "Forbidden"),
- /** 404 Not Found
*/
- NOT_FOUND(NOT_FOUND_404, "Not Found"),
- /** 405 Method Not Allowed
*/
- METHOD_NOT_ALLOWED(METHOD_NOT_ALLOWED_405, "Method Not Allowed"),
- /** 406 Not Acceptable
*/
- NOT_ACCEPTABLE(NOT_ACCEPTABLE_406, "Not Acceptable"),
- /** 407 Proxy Authentication Required
*/
- PROXY_AUTHENTICATION_REQUIRED(PROXY_AUTHENTICATION_REQUIRED_407, "Proxy Authentication Required"),
- /** 408 Request Timeout
*/
- REQUEST_TIMEOUT(REQUEST_TIMEOUT_408, "Request Timeout"),
- /** 409 Conflict
*/
- CONFLICT(CONFLICT_409, "Conflict"),
- /** 410 Gone
*/
- GONE(GONE_410, "Gone"),
- /** 411 Length Required
*/
- LENGTH_REQUIRED(LENGTH_REQUIRED_411, "Length Required"),
- /** 412 Precondition Failed
*/
- PRECONDITION_FAILED(PRECONDITION_FAILED_412, "Precondition Failed"),
- /** 413 Request Entity Too Large
*/
- REQUEST_ENTITY_TOO_LARGE(REQUEST_ENTITY_TOO_LARGE_413, "Request Entity Too Large"),
- /** 414 Request-URI Too Long
*/
- REQUEST_URI_TOO_LONG(REQUEST_URI_TOO_LONG_414, "Request-URI Too Long"),
- /** 415 Unsupported Media Type
*/
- UNSUPPORTED_MEDIA_TYPE(UNSUPPORTED_MEDIA_TYPE_415, "Unsupported Media Type"),
- /** 416 Requested Range Not Satisfiable
*/
- REQUESTED_RANGE_NOT_SATISFIABLE(REQUESTED_RANGE_NOT_SATISFIABLE_416, "Requested Range Not Satisfiable"),
- /** 417 Expectation Failed
*/
- EXPECTATION_FAILED(EXPECTATION_FAILED_417, "Expectation Failed"),
- /** 421 Misdirected Request(RFC7234)y
*/
- MISDIRECTED_REQUEST(MISDIRECTED_REQUEST_421, "Misdirected Request"),
- /** 422 Unprocessable Entity
*/
- UNPROCESSABLE_ENTITY(UNPROCESSABLE_ENTITY_422, "Unprocessable Entity"),
- /** 423 Locked
*/
- LOCKED(LOCKED_423, "Locked"),
- /** 424 Failed Dependency
*/
- FAILED_DEPENDENCY(FAILED_DEPENDENCY_424, "Failed Dependency"),
-
- /** 426 Upgrade Required (RFC7231)
*/
- UPGRADE_REQUIRED(UPGRADE_REQUIRED_426, "Upgrade Required"),
-
- /** 428 Precondition Required (RFC6585)
*/
- PRECONDITION_REQUIRED(PRECONDITION_REQUIRED_428, "Precondition Required"),
- /** 429 Too Many Requests (RFC6585)
*/
- TOO_MANY_REQUESTS(TOO_MANY_REQUESTS_429, "Too Many Requests"),
- /** 431 Request Header Fields Too Large (RFC6585)
*/
- REQUEST_HEADER_FIELDS_TOO_LARGE(REQUEST_HEADER_FIELDS_TOO_LARGE_431, "Request Header Fields Too Large"),
-
- /*
- * --------------------------------------------------------------------
- * Server Error messages in 5xx series. As defined by ... RFC 1945 -
- * HTTP/1.0 RFC 7231 - HTTP/1.1 RFC 2518 - WebDAV
- */
-
- /** 500 Server Error
*/
- INTERNAL_SERVER_ERROR(INTERNAL_SERVER_ERROR_500, "Server Error"),
- /** 501 Not Implemented
*/
- NOT_IMPLEMENTED(NOT_IMPLEMENTED_501, "Not Implemented"),
- /** 502 Bad Gateway
*/
- BAD_GATEWAY(BAD_GATEWAY_502, "Bad Gateway"),
- /** 503 Service Unavailable
*/
- SERVICE_UNAVAILABLE(SERVICE_UNAVAILABLE_503, "Service Unavailable"),
- /** 504 Gateway Timeout
*/
- GATEWAY_TIMEOUT(GATEWAY_TIMEOUT_504, "Gateway Timeout"),
- /** 505 HTTP Version Not Supported
*/
- HTTP_VERSION_NOT_SUPPORTED(HTTP_VERSION_NOT_SUPPORTED_505, "HTTP Version Not Supported"),
- /** 507 Insufficient Storage
*/
- INSUFFICIENT_STORAGE(INSUFFICIENT_STORAGE_507, "Insufficient Storage"),
-
- /** 511 Network Authentication Required (RFC6585)
*/
- NETWORK_AUTHENTICATION_REQUIRED(NETWORK_AUTHENTICATION_REQUIRED_511, "Network Authentication Required"),
-
- ;
-
- private final int _code;
- private final String _message;
-
- private Code(int code, String message)
- {
- this._code = code;
- _message=message;
- }
-
- public int getCode()
- {
- return _code;
- }
-
- public String getMessage()
- {
- return _message;
- }
-
-
- public boolean equals(int code)
- {
- return (this._code == code);
- }
-
- @Override
- public String toString()
- {
- return String.format("[%03d %s]",this._code,this.getMessage());
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Informational
message category as defined in the RFC 1945 - HTTP/1.0,
- * and RFC 7231 -
- * HTTP/1.1.
- *
- * @return true if within range of codes that belongs to
- * Informational
messages.
- */
- public boolean isInformational()
- {
- return HttpStatus.isInformational(this._code);
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Success
message category as defined in the RFC 1945 - HTTP/1.0,
- * and RFC 7231 -
- * HTTP/1.1.
- *
- * @return true if within range of codes that belongs to
- * Success
messages.
- */
- public boolean isSuccess()
- {
- return HttpStatus.isSuccess(this._code);
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Redirection
message category as defined in the RFC 1945 - HTTP/1.0,
- * and RFC 7231 -
- * HTTP/1.1.
- *
- * @return true if within range of codes that belongs to
- * Redirection
messages.
- */
- public boolean isRedirection()
- {
- return HttpStatus.isRedirection(this._code);
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Client Error
message category as defined in the RFC 1945 - HTTP/1.0,
- * and RFC 7231 -
- * HTTP/1.1.
- *
- * @return true if within range of codes that belongs to
- * Client Error
messages.
- */
- public boolean isClientError()
- {
- return HttpStatus.isClientError(this._code);
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Server Error
message category as defined in the RFC 1945 - HTTP/1.0,
- * and RFC 7231 -
- * HTTP/1.1.
- *
- * @return true if within range of codes that belongs to
- * Server Error
messages.
- */
- public boolean isServerError()
- {
- return HttpStatus.isServerError(this._code);
- }
- }
-
-
- /**
- * Get the HttpStatusCode for a specific code
- *
- * @param code
- * the code to lookup.
- * @return the {@link HttpStatus} if found, or null if not found.
- */
- public static Code getCode(int code)
- {
- if (code <= MAX_CODE)
- {
- return codeMap[code];
- }
- return null;
- }
-
- /**
- * Get the status message for a specific code.
- *
- * @param code
- * the code to look up
- * @return the specific message, or the code number itself if code
- * does not match known list.
- */
- public static String getMessage(int code)
- {
- Code codeEnum = getCode(code);
- if (codeEnum != null)
- {
- return codeEnum.getMessage();
- }
- else
- {
- return Integer.toString(code);
- }
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Informational
message category as defined in the RFC 1945 - HTTP/1.0, and RFC 7231 - HTTP/1.1.
- *
- * @param code
- * the code to test.
- * @return true if within range of codes that belongs to
- * Informational
messages.
- */
- public static boolean isInformational(int code)
- {
- return ((100 <= code) && (code <= 199));
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Success
message category as defined in the RFC 1945 - HTTP/1.0, and RFC 7231 - HTTP/1.1.
- *
- * @param code
- * the code to test.
- * @return true if within range of codes that belongs to
- * Success
messages.
- */
- public static boolean isSuccess(int code)
- {
- return ((200 <= code) && (code <= 299));
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Redirection
message category as defined in the RFC 1945 - HTTP/1.0, and RFC 7231 - HTTP/1.1.
- *
- * @param code
- * the code to test.
- * @return true if within range of codes that belongs to
- * Redirection
messages.
- */
- public static boolean isRedirection(int code)
- {
- return ((300 <= code) && (code <= 399));
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Client Error
message category as defined in the RFC 1945 - HTTP/1.0, and RFC 7231 - HTTP/1.1.
- *
- * @param code
- * the code to test.
- * @return true if within range of codes that belongs to
- * Client Error
messages.
- */
- public static boolean isClientError(int code)
- {
- return ((400 <= code) && (code <= 499));
- }
-
- /**
- * Simple test against an code to determine if it falls into the
- * Server Error
message category as defined in the RFC 1945 - HTTP/1.0, and RFC 7231 - HTTP/1.1.
- *
- * @param code
- * the code to test.
- * @return true if within range of codes that belongs to
- * Server Error
messages.
- */
- public static boolean isServerError(int code)
- {
- return ((500 <= code) && (code <= 599));
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpTokens.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpTokens.java
deleted file mode 100644
index 66aabdaf72..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpTokens.java
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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;
-
-/**
- * HTTP constants
- */
-public interface HttpTokens
-{
- // Terminal symbols.
- static final byte COLON= (byte)':';
- static final byte TAB= 0x09;
- static final byte LINE_FEED= 0x0A;
- static final byte CARRIAGE_RETURN= 0x0D;
- static final byte SPACE= 0x20;
- static final byte[] CRLF = {CARRIAGE_RETURN,LINE_FEED};
- static final byte SEMI_COLON= (byte)';';
-
- public enum EndOfContent { UNKNOWN_CONTENT,NO_CONTENT,EOF_CONTENT,CONTENT_LENGTH,CHUNKED_CONTENT }
-
-}
-
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpURI.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpURI.java
deleted file mode 100644
index 87ce90cf42..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpURI.java
+++ /dev/null
@@ -1,783 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-
-import org.eclipse.jetty.util.MultiMap;
-import org.eclipse.jetty.util.TypeUtil;
-import org.eclipse.jetty.util.URIUtil;
-import org.eclipse.jetty.util.UrlEncoded;
-
-
-/* ------------------------------------------------------------ */
-/** Http URI.
- * Parse a HTTP URI from a string or byte array. Given a URI
- * http://user@host:port/path/info;param?query#fragment
- * this class will split it into the following undecoded optional elements:
- * - {@link #getScheme()} - http:
- * - {@link #getAuthority()} - //name@host:port
- * - {@link #getHost()} - host
- * - {@link #getPort()} - port
- * - {@link #getPath()} - /path/info
- * - {@link #getParam()} - param
- * - {@link #getQuery()} - query
- * - {@link #getFragment()} - fragment
- *
- *
- * Any parameters will be returned from {@link #getPath()}, but are excluded from the
- * return value of {@link #getDecodedPath()}. If there are multiple parameters, the
- * {@link #getParam()} method returns only the last one.
- */
-public class HttpURI
-{
- private enum State {
- START,
- HOST_OR_PATH,
- SCHEME_OR_PATH,
- HOST,
- IPV6,
- PORT,
- PATH,
- PARAM,
- QUERY,
- FRAGMENT,
- ASTERISK};
-
- private String _scheme;
- private String _user;
- private String _host;
- private int _port;
- private String _path;
- private String _param;
- private String _query;
- private String _fragment;
-
- String _uri;
- String _decodedPath;
-
- /* ------------------------------------------------------------ */
- /**
- * Construct a normalized URI.
- * Port is not set if it is the default port.
- * @param scheme the URI scheme
- * @param host the URI hose
- * @param port the URI port
- * @param path the URI path
- * @param param the URI param
- * @param query the URI query
- * @param fragment the URI fragment
- * @return the normalized URI
- */
- public static HttpURI createHttpURI(String scheme, String host, int port, String path, String param, String query, String fragment)
- {
- if (port==80 && HttpScheme.HTTP.is(scheme))
- port=0;
- if (port==443 && HttpScheme.HTTPS.is(scheme))
- port=0;
- return new HttpURI(scheme,host,port,path,param,query,fragment);
- }
-
- /* ------------------------------------------------------------ */
- public HttpURI()
- {
- }
-
- /* ------------------------------------------------------------ */
- public HttpURI(String scheme, String host, int port, String path, String param, String query, String fragment)
- {
- _scheme = scheme;
- _host = host;
- _port = port;
- _path = path;
- _param = param;
- _query = query;
- _fragment = fragment;
- }
-
- /* ------------------------------------------------------------ */
- public HttpURI(HttpURI uri)
- {
- this(uri._scheme,uri._host,uri._port,uri._path,uri._param,uri._query,uri._fragment);
- }
-
- /* ------------------------------------------------------------ */
- public HttpURI(String uri)
- {
- _port=-1;
- parse(State.START,uri,0,uri.length());
- }
-
- /* ------------------------------------------------------------ */
- public HttpURI(URI uri)
- {
- _uri=null;
-
- _scheme=uri.getScheme();
- _host=uri.getHost();
- if (_host==null && uri.getRawSchemeSpecificPart().startsWith("//"))
- _host="";
- _port=uri.getPort();
- _user = uri.getUserInfo();
- _path=uri.getRawPath();
-
- _decodedPath = uri.getPath();
- if (_decodedPath != null)
- {
- int p = _decodedPath.lastIndexOf(';');
- if (p >= 0)
- _param = _decodedPath.substring(p + 1);
- }
- _query=uri.getRawQuery();
- _fragment=uri.getFragment();
-
- _decodedPath=null;
- }
-
- /* ------------------------------------------------------------ */
- public HttpURI(String scheme, String host, int port, String pathQuery)
- {
- _uri=null;
-
- _scheme=scheme;
- _host=host;
- _port=port;
-
- parse(State.PATH,pathQuery,0,pathQuery.length());
-
- }
-
- /* ------------------------------------------------------------ */
- public void parse(String uri)
- {
- clear();
- _uri=uri;
- parse(State.START,uri,0,uri.length());
- }
-
- /* ------------------------------------------------------------ */
- /** Parse according to https://tools.ietf.org/html/rfc7230#section-5.3
- * @param method
- * @param uri
- */
- public void parseRequestTarget(String method,String uri)
- {
- clear();
- _uri=uri;
-
- if (HttpMethod.CONNECT.is(method))
- _path=uri;
- else
- parse(uri.startsWith("/")?State.PATH:State.START,uri,0,uri.length());
- }
-
- /* ------------------------------------------------------------ */
- @Deprecated
- public void parseConnect(String uri)
- {
- clear();
- _uri=uri;
- _path=uri;
- }
-
- /* ------------------------------------------------------------ */
- public void parse(String uri, int offset, int length)
- {
- clear();
- int end=offset+length;
- _uri=uri.substring(offset,end);
- parse(State.START,uri,offset,end);
- }
-
- /* ------------------------------------------------------------ */
- private void parse(State state, final String uri, final int offset, final int end)
- {
- boolean encoded=false;
- int mark=offset;
- int path_mark=0;
-
- for (int i=offset; i mark)
- _host=uri.substring(mark,i);
- mark=i+1;
- state=State.PORT;
- break;
- case '@':
- if (_user!=null)
- throw new IllegalArgumentException("Bad authority");
- _user=uri.substring(mark,i);
- mark=i+1;
- break;
-
- case '[':
- state=State.IPV6;
- break;
- }
- continue;
- }
-
- case IPV6:
- {
- switch (c)
- {
- case '/':
- throw new IllegalArgumentException("No closing ']' for ipv6 in " + uri);
- case ']':
- c = uri.charAt(++i);
- _host=uri.substring(mark,i);
- if (c == ':')
- {
- mark=i+1;
- state=State.PORT;
- }
- else
- {
- path_mark=mark=i;
- state=State.PATH;
- }
- break;
- }
-
- continue;
- }
-
- case PORT:
- {
- if (c=='@')
- {
- if (_user!=null)
- throw new IllegalArgumentException("Bad authority");
- // It wasn't a port, but a password!
- _user=_host+":"+uri.substring(mark,i);
- mark=i+1;
- state=State.HOST;
- }
- else if (c=='/')
- {
- _port=TypeUtil.parseInt(uri,mark,i-mark,10);
- path_mark=mark=i;
- state=State.PATH;
- }
- continue;
- }
-
- case PATH:
- {
- switch (c)
- {
- case ';':
- mark=i+1;
- state=State.PARAM;
- break;
- case '?':
- _path=uri.substring(path_mark,i);
- mark=i+1;
- state=State.QUERY;
- break;
- case '#':
- _path=uri.substring(path_mark,i);
- mark=i+1;
- state=State.FRAGMENT;
- break;
- case '%':
- encoded=true;
- break;
- }
- continue;
- }
-
- case PARAM:
- {
- switch (c)
- {
- case '?':
- _path=uri.substring(path_mark,i);
- _param=uri.substring(mark,i);
- mark=i+1;
- state=State.QUERY;
- break;
- case '#':
- _path=uri.substring(path_mark,i);
- _param=uri.substring(mark,i);
- mark=i+1;
- state=State.FRAGMENT;
- break;
- case '/':
- encoded=true;
- // ignore internal params
- state=State.PATH;
- break;
- case ';':
- // multiple parameters
- mark=i+1;
- break;
- }
- continue;
- }
-
- case QUERY:
- {
- if (c=='#')
- {
- _query=uri.substring(mark,i);
- mark=i+1;
- state=State.FRAGMENT;
- }
- continue;
- }
-
- case ASTERISK:
- {
- throw new IllegalArgumentException("only '*'");
- }
-
- case FRAGMENT:
- {
- _fragment=uri.substring(mark,end);
- i=end;
- }
- }
- }
-
-
- switch(state)
- {
- case START:
- break;
- case SCHEME_OR_PATH:
- _path=uri.substring(mark,end);
- break;
-
- case HOST_OR_PATH:
- _path=uri.substring(mark,end);
- break;
-
- case HOST:
- if(end>mark)
- _host=uri.substring(mark,end);
- break;
-
- case IPV6:
- throw new IllegalArgumentException("No closing ']' for ipv6 in " + uri);
-
- case PORT:
- _port=TypeUtil.parseInt(uri,mark,end-mark,10);
- break;
-
- case ASTERISK:
- break;
-
- case FRAGMENT:
- _fragment=uri.substring(mark,end);
- break;
-
- case PARAM:
- _path=uri.substring(path_mark,end);
- _param=uri.substring(mark,end);
- break;
-
- case PATH:
- _path=uri.substring(path_mark,end);
- break;
-
- case QUERY:
- _query=uri.substring(mark,end);
- break;
- }
-
- if (!encoded)
- {
- if (_param==null)
- _decodedPath=_path;
- else
- _decodedPath=_path.substring(0,_path.length()-_param.length()-1);
- }
- }
-
- /* ------------------------------------------------------------ */
- public String getScheme()
- {
- return _scheme;
- }
-
- /* ------------------------------------------------------------ */
- public String getHost()
- {
- // Return null for empty host to retain compatibility with java.net.URI
- if (_host!=null && _host.length()==0)
- return null;
- return _host;
- }
-
- /* ------------------------------------------------------------ */
- public int getPort()
- {
- return _port;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * The parsed Path.
- *
- * @return the path as parsed on valid URI. null for invalid URI.
- */
- public String getPath()
- {
- return _path;
- }
-
- /* ------------------------------------------------------------ */
- public String getDecodedPath()
- {
- if (_decodedPath==null && _path!=null)
- _decodedPath=URIUtil.decodePath(_path);
- return _decodedPath;
- }
-
- /* ------------------------------------------------------------ */
- public String getParam()
- {
- return _param;
- }
-
- /* ------------------------------------------------------------ */
- public String getQuery()
- {
- return _query;
- }
-
- /* ------------------------------------------------------------ */
- public boolean hasQuery()
- {
- return _query!=null && _query.length()>0;
- }
-
- /* ------------------------------------------------------------ */
- public String getFragment()
- {
- return _fragment;
- }
-
- /* ------------------------------------------------------------ */
- public void decodeQueryTo(MultiMap parameters)
- {
- if (_query==_fragment)
- return;
- UrlEncoded.decodeUtf8To(_query,parameters);
- }
-
- /* ------------------------------------------------------------ */
- public void decodeQueryTo(MultiMap parameters, String encoding) throws UnsupportedEncodingException
- {
- decodeQueryTo(parameters,Charset.forName(encoding));
- }
-
- /* ------------------------------------------------------------ */
- public void decodeQueryTo(MultiMap parameters, Charset encoding) throws UnsupportedEncodingException
- {
- if (_query==_fragment)
- return;
-
- if (encoding==null || StandardCharsets.UTF_8.equals(encoding))
- UrlEncoded.decodeUtf8To(_query,parameters);
- else
- UrlEncoded.decodeTo(_query,parameters,encoding);
- }
-
- /* ------------------------------------------------------------ */
- public void clear()
- {
- _uri=null;
-
- _scheme=null;
- _host=null;
- _port=-1;
- _path=null;
- _param=null;
- _query=null;
- _fragment=null;
-
- _decodedPath=null;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isAbsolute()
- {
- return _scheme!=null && _scheme.length()>0;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String toString()
- {
- if (_uri==null)
- {
- StringBuilder out = new StringBuilder();
-
- if (_scheme!=null)
- out.append(_scheme).append(':');
-
- if (_host != null)
- {
- out.append("//");
- if (_user != null)
- out.append(_user).append('@');
- out.append(_host);
- }
-
- if (_port>0)
- out.append(':').append(_port);
-
- if (_path!=null)
- out.append(_path);
-
- if (_query!=null)
- out.append('?').append(_query);
-
- if (_fragment!=null)
- out.append('#').append(_fragment);
-
- if (out.length()>0)
- _uri=out.toString();
- else
- _uri="";
- }
- return _uri;
- }
-
- /* ------------------------------------------------------------ */
- public boolean equals(Object o)
- {
- if (o==this)
- return true;
- if (!(o instanceof HttpURI))
- return false;
- return toString().equals(o.toString());
- }
-
- /* ------------------------------------------------------------ */
- public void setScheme(String scheme)
- {
- _scheme=scheme;
- _uri=null;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @param host the host
- * @param port the port
- */
- public void setAuthority(String host, int port)
- {
- _host=host;
- _port=port;
- _uri=null;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @param path the path
- */
- public void setPath(String path)
- {
- _uri=null;
- _path=path;
- _decodedPath=null;
- }
-
- /* ------------------------------------------------------------ */
- public void setPathQuery(String path)
- {
- _uri=null;
- _path=null;
- _decodedPath=null;
- _param=null;
- _fragment=null;
- if (path!=null)
- parse(State.PATH,path,0,path.length());
- }
-
- /* ------------------------------------------------------------ */
- public void setQuery(String query)
- {
- _query=query;
- _uri=null;
- }
-
- /* ------------------------------------------------------------ */
- public URI toURI() throws URISyntaxException
- {
- return new URI(_scheme,null,_host,_port,_path,_query==null?null:UrlEncoded.decodeString(_query),_fragment);
- }
-
- /* ------------------------------------------------------------ */
- public String getPathQuery()
- {
- if (_query==null)
- return _path;
- return _path+"?"+_query;
- }
-
- /* ------------------------------------------------------------ */
- public String getAuthority()
- {
- if (_port>0)
- return _host+":"+_port;
- return _host;
- }
-
- /* ------------------------------------------------------------ */
- public String getUser()
- {
- return _user;
- }
-
-
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpVersion.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpVersion.java
deleted file mode 100644
index ddedc27471..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/HttpVersion.java
+++ /dev/null
@@ -1,173 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.nio.ByteBuffer;
-
-import org.eclipse.jetty.util.ArrayTrie;
-import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.util.Trie;
-
-
-/* ------------------------------------------------------------------------------- */
-public enum HttpVersion
-{
- HTTP_0_9("HTTP/0.9",9),
- HTTP_1_0("HTTP/1.0",10),
- HTTP_1_1("HTTP/1.1",11),
- HTTP_2("HTTP/2.0",20);
-
- /* ------------------------------------------------------------ */
- public final static Trie CACHE= new ArrayTrie();
- static
- {
- for (HttpVersion version : HttpVersion.values())
- CACHE.put(version.toString(),version);
- }
-
- /* ------------------------------------------------------------ */
- /**
- * Optimised lookup to find a Http Version and whitespace in a byte array.
- * @param bytes Array containing ISO-8859-1 characters
- * @param position The first valid index
- * @param limit The first non valid index
- * @return A HttpMethod if a match or null if no easy match.
- */
- public static HttpVersion lookAheadGet(byte[] bytes, int position, int limit)
- {
- int length=limit-position;
- if (length<9)
- return null;
-
- if (bytes[position+4]=='/' && bytes[position+6]=='.' && Character.isWhitespace((char)bytes[position+8]) &&
- ((bytes[position]=='H' && bytes[position+1]=='T' && bytes[position+2]=='T' && bytes[position+3]=='P') ||
- (bytes[position]=='h' && bytes[position+1]=='t' && bytes[position+2]=='t' && bytes[position+3]=='p')))
- {
- switch(bytes[position+5])
- {
- case '1':
- switch(bytes[position+7])
- {
- case '0':
- return HTTP_1_0;
- case '1':
- return HTTP_1_1;
- }
- break;
- case '2':
- switch(bytes[position+7])
- {
- case '0':
- return HTTP_2;
- }
- break;
- }
- }
-
- return null;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * Optimised lookup to find a HTTP Version and trailing white space in a byte array.
- * @param buffer buffer containing ISO-8859-1 characters
- * @return A HttpVersion if a match or null if no easy match.
- */
- public static HttpVersion lookAheadGet(ByteBuffer buffer)
- {
- if (buffer.hasArray())
- return lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position(),buffer.arrayOffset()+buffer.limit());
- return null;
- }
-
-
- private final String _string;
- private final byte[] _bytes;
- private final ByteBuffer _buffer;
- private final int _version;
-
- /* ------------------------------------------------------------ */
- HttpVersion(String s,int version)
- {
- _string=s;
- _bytes=StringUtil.getBytes(s);
- _buffer=ByteBuffer.wrap(_bytes);
- _version=version;
- }
-
- /* ------------------------------------------------------------ */
- public byte[] toBytes()
- {
- return _bytes;
- }
-
- /* ------------------------------------------------------------ */
- public ByteBuffer toBuffer()
- {
- return _buffer.asReadOnlyBuffer();
- }
-
- /* ------------------------------------------------------------ */
- public int getVersion()
- {
- return _version;
- }
-
- /* ------------------------------------------------------------ */
- public boolean is(String s)
- {
- return _string.equalsIgnoreCase(s);
- }
-
- /* ------------------------------------------------------------ */
- public String asString()
- {
- return _string;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String toString()
- {
- return _string;
- }
-
- /**
- * Case insensitive fromString() conversion
- * @param version the String to convert to enum constant
- * @return the enum constant or null if version unknown
- */
- public static HttpVersion fromString(String version)
- {
- return CACHE.get(version);
- }
-
- /* ------------------------------------------------------------ */
- public static HttpVersion fromVersion(int version)
- {
- switch(version)
- {
- case 9: return HttpVersion.HTTP_0_9;
- case 10: return HttpVersion.HTTP_1_0;
- case 11: return HttpVersion.HTTP_1_1;
- case 20: return HttpVersion.HTTP_2;
- default: throw new IllegalArgumentException();
- }
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/MetaData.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/MetaData.java
deleted file mode 100644
index 725870db92..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/MetaData.java
+++ /dev/null
@@ -1,298 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.Collections;
-import java.util.Iterator;
-
-public class MetaData implements Iterable
-{
- private HttpVersion _httpVersion;
- private HttpFields _fields;
- private long _contentLength;
-
- public MetaData(HttpVersion version, HttpFields fields)
- {
- this(version, fields, Long.MIN_VALUE);
- }
-
- public MetaData(HttpVersion version, HttpFields fields, long contentLength)
- {
- _httpVersion = version;
- _fields = fields;
- _contentLength = contentLength;
- }
-
- protected void recycle()
- {
- _httpVersion = null;
- if (_fields != null)
- _fields.clear();
- _contentLength = Long.MIN_VALUE;
- }
-
- public boolean isRequest()
- {
- return false;
- }
-
- public boolean isResponse()
- {
- return false;
- }
-
- /**
- * @return the HTTP version of this MetaData object
- */
- public HttpVersion getVersion()
- {
- return _httpVersion;
- }
-
- /**
- * @param httpVersion the HTTP version to set
- */
- public void setHttpVersion(HttpVersion httpVersion)
- {
- _httpVersion = httpVersion;
- }
-
- /**
- * @return the HTTP fields of this MetaData object
- */
- public HttpFields getFields()
- {
- return _fields;
- }
-
- /**
- * @return the content length if available, otherwise {@link Long#MIN_VALUE}
- */
- public long getContentLength()
- {
- if (_contentLength == Long.MIN_VALUE)
- {
- if (_fields != null)
- {
- HttpField field = _fields.getField(HttpHeader.CONTENT_LENGTH);
- _contentLength = field == null ? -1 : field.getLongValue();
- }
- }
- return _contentLength;
- }
-
- /**
- * @return an iterator over the HTTP fields
- * @see #getFields()
- */
- public Iterator iterator()
- {
- HttpFields fields = getFields();
- return fields == null ? Collections.emptyIterator() : fields.iterator();
- }
-
- @Override
- public String toString()
- {
- StringBuilder out = new StringBuilder();
- for (HttpField field : this)
- out.append(field).append(System.lineSeparator());
- return out.toString();
- }
-
- public static class Request extends MetaData
- {
- private String _method;
- private HttpURI _uri;
-
- public Request(HttpFields fields)
- {
- this(null, null, null, fields);
- }
-
- public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields)
- {
- this(method, uri, version, fields, Long.MIN_VALUE);
- }
-
- public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields, long contentLength)
- {
- super(version, fields, contentLength);
- _method = method;
- _uri = uri;
- }
-
- public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields)
- {
- this(method, new HttpURI(scheme == null ? null : scheme.asString(), hostPort.getHost(), hostPort.getPort(), uri), version, fields);
- }
-
- public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength)
- {
- this(method, new HttpURI(scheme == null ? null : scheme.asString(), hostPort.getHost(), hostPort.getPort(), uri), version, fields, contentLength);
- }
-
- public Request(String method, String scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength)
- {
- this(method, new HttpURI(scheme, hostPort.getHost(), hostPort.getPort(), uri), version, fields, contentLength);
- }
-
- public Request(Request request)
- {
- this(request.getMethod(),new HttpURI(request.getURI()), request.getVersion(), new HttpFields(request.getFields()), request.getContentLength());
- }
-
- // TODO MetaData should be immuttable!!!
- public void recycle()
- {
- super.recycle();
- _method = null;
- if (_uri != null)
- _uri.clear();
- }
-
- @Override
- public boolean isRequest()
- {
- return true;
- }
-
- /**
- * @return the HTTP method
- */
- public String getMethod()
- {
- return _method;
- }
-
- /**
- * @param method the HTTP method to set
- */
- public void setMethod(String method)
- {
- _method = method;
- }
-
- /**
- * @return the HTTP URI
- */
- public HttpURI getURI()
- {
- return _uri;
- }
-
- /**
- * @return the HTTP URI in string form
- */
- public String getURIString()
- {
- return _uri == null ? null : _uri.toString();
- }
-
- /**
- * @param uri the HTTP URI to set
- */
- public void setURI(HttpURI uri)
- {
- _uri = uri;
- }
-
- @Override
- public String toString()
- {
- HttpFields fields = getFields();
- return String.format("%s{u=%s,%s,h=%d}",
- getMethod(), getURI(), getVersion(), fields == null ? -1 : fields.size());
- }
- }
-
- public static class Response extends MetaData
- {
- private int _status;
- private String _reason;
-
- public Response()
- {
- this(null, 0, null);
- }
-
- public Response(HttpVersion version, int status, HttpFields fields)
- {
- this(version, status, fields, Long.MIN_VALUE);
- }
-
- public Response(HttpVersion version, int status, HttpFields fields, long contentLength)
- {
- super(version, fields, contentLength);
- _status = status;
- }
-
- public Response(HttpVersion version, int status, String reason, HttpFields fields, long contentLength)
- {
- super(version, fields, contentLength);
- _reason = reason;
- _status = status;
- }
-
- @Override
- public boolean isResponse()
- {
- return true;
- }
-
- /**
- * @return the HTTP status
- */
- public int getStatus()
- {
- return _status;
- }
-
- /**
- * @return the HTTP reason
- */
- public String getReason()
- {
- return _reason;
- }
-
- /**
- * @param status the HTTP status to set
- */
- public void setStatus(int status)
- {
- _status = status;
- }
-
- /**
- * @param reason the HTTP reason to set
- */
- public void setReason(String reason)
- {
- _reason = reason;
- }
-
- @Override
- public String toString()
- {
- HttpFields fields = getFields();
- return String.format("%s{s=%d,h=%d}", getVersion(), getStatus(), fields == null ? -1 : fields.size());
- }
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/MimeTypes.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/MimeTypes.java
deleted file mode 100644
index dbdd4b83c6..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/MimeTypes.java
+++ /dev/null
@@ -1,497 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.Set;
-
-import org.eclipse.jetty.util.ArrayTrie;
-import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.util.Trie;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-
-/* ------------------------------------------------------------ */
-/**
- *
- */
-public class MimeTypes
-{
- public enum Type
- {
- FORM_ENCODED("application/x-www-form-urlencoded"),
- MESSAGE_HTTP("message/http"),
- MULTIPART_BYTERANGES("multipart/byteranges"),
-
- TEXT_HTML("text/html"),
- TEXT_PLAIN("text/plain"),
- TEXT_XML("text/xml"),
- TEXT_JSON("text/json",StandardCharsets.UTF_8),
- APPLICATION_JSON("application/json",StandardCharsets.UTF_8),
-
- TEXT_HTML_8859_1("text/html;charset=iso-8859-1",TEXT_HTML),
- TEXT_HTML_UTF_8("text/html;charset=utf-8",TEXT_HTML),
-
- TEXT_PLAIN_8859_1("text/plain;charset=iso-8859-1",TEXT_PLAIN),
- TEXT_PLAIN_UTF_8("text/plain;charset=utf-8",TEXT_PLAIN),
-
- TEXT_XML_8859_1("text/xml;charset=iso-8859-1",TEXT_XML),
- TEXT_XML_UTF_8("text/xml;charset=utf-8",TEXT_XML),
-
- TEXT_JSON_8859_1("text/json;charset=iso-8859-1",TEXT_JSON),
- TEXT_JSON_UTF_8("text/json;charset=utf-8",TEXT_JSON),
-
- APPLICATION_JSON_8859_1("text/json;charset=iso-8859-1",APPLICATION_JSON),
- APPLICATION_JSON_UTF_8("text/json;charset=utf-8",APPLICATION_JSON);
-
-
- /* ------------------------------------------------------------ */
- private final String _string;
- private final Type _base;
- private final ByteBuffer _buffer;
- private final Charset _charset;
- private final String _charsetString;
- private final boolean _assumedCharset;
- private final HttpField _field;
-
- /* ------------------------------------------------------------ */
- Type(String s)
- {
- _string=s;
- _buffer=BufferUtil.toBuffer(s);
- _base=this;
- _charset=null;
- _charsetString=null;
- _assumedCharset=false;
- _field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
- }
-
- /* ------------------------------------------------------------ */
- Type(String s,Type base)
- {
- _string=s;
- _buffer=BufferUtil.toBuffer(s);
- _base=base;
- int i=s.indexOf(";charset=");
- _charset=Charset.forName(s.substring(i+9));
- _charsetString=_charset.toString().toLowerCase(Locale.ENGLISH);
- _assumedCharset=false;
- _field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
- }
-
- /* ------------------------------------------------------------ */
- Type(String s,Charset cs)
- {
- _string=s;
- _base=this;
- _buffer=BufferUtil.toBuffer(s);
- _charset=cs;
- _charsetString=_charset==null?null:_charset.toString().toLowerCase(Locale.ENGLISH);
- _assumedCharset=true;
- _field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
- }
-
- /* ------------------------------------------------------------ */
- public ByteBuffer asBuffer()
- {
- return _buffer.asReadOnlyBuffer();
- }
-
- /* ------------------------------------------------------------ */
- public Charset getCharset()
- {
- return _charset;
- }
-
- /* ------------------------------------------------------------ */
- public String getCharsetString()
- {
- return _charsetString;
- }
-
- /* ------------------------------------------------------------ */
- public boolean is(String s)
- {
- return _string.equalsIgnoreCase(s);
- }
-
- /* ------------------------------------------------------------ */
- public String asString()
- {
- return _string;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String toString()
- {
- return _string;
- }
-
- /* ------------------------------------------------------------ */
- public boolean isCharsetAssumed()
- {
- return _assumedCharset;
- }
-
- /* ------------------------------------------------------------ */
- public HttpField getContentTypeField()
- {
- return _field;
- }
-
- /* ------------------------------------------------------------ */
- public Type getBaseType()
- {
- return _base;
- }
- }
-
- /* ------------------------------------------------------------ */
- private static final Logger LOG = Log.getLogger(MimeTypes.class);
- public final static Trie CACHE= new ArrayTrie<>(512);
- private final static Trie TYPES= new ArrayTrie(512);
- private final static Map __dftMimeMap = new HashMap();
- private final static Map __encodings = new HashMap();
-
- static
- {
- for (MimeTypes.Type type : MimeTypes.Type.values())
- {
- CACHE.put(type.toString(),type);
- TYPES.put(type.toString(),type.asBuffer());
-
- int charset=type.toString().indexOf(";charset=");
- if (charset>0)
- {
- String alt=type.toString().replace(";charset=","; charset=");
- CACHE.put(alt,type);
- TYPES.put(alt,type.asBuffer());
- }
- }
-
- try
- {
- ResourceBundle mime = ResourceBundle.getBundle("org/eclipse/jetty/http/mime");
- Enumeration i = mime.getKeys();
- while(i.hasMoreElements())
- {
- String ext = i.nextElement();
- String m = mime.getString(ext);
- __dftMimeMap.put(StringUtil.asciiToLowerCase(ext),normalizeMimeType(m));
- }
- }
- catch(MissingResourceException e)
- {
- LOG.warn(e.toString());
- LOG.debug(e);
- }
-
- try
- {
- ResourceBundle encoding = ResourceBundle.getBundle("org/eclipse/jetty/http/encoding");
- Enumeration i = encoding.getKeys();
- while(i.hasMoreElements())
- {
- String type = i.nextElement();
- __encodings.put(type,encoding.getString(type));
- }
- }
- catch(MissingResourceException e)
- {
- LOG.warn(e.toString());
- LOG.debug(e);
- }
- }
-
-
- /* ------------------------------------------------------------ */
- private final Map _mimeMap=new HashMap();
-
- /* ------------------------------------------------------------ */
- /** Constructor.
- */
- public MimeTypes()
- {
- }
-
- /* ------------------------------------------------------------ */
- public synchronized Map getMimeMap()
- {
- return _mimeMap;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @param mimeMap A Map of file extension to mime-type.
- */
- public void setMimeMap(Map mimeMap)
- {
- _mimeMap.clear();
- if (mimeMap!=null)
- {
- for (Entry ext : mimeMap.entrySet())
- _mimeMap.put(StringUtil.asciiToLowerCase(ext.getKey()),normalizeMimeType(ext.getValue()));
- }
- }
-
- /* ------------------------------------------------------------ */
- /** Get the MIME type by filename extension.
- * @param filename A file name
- * @return MIME type matching the longest dot extension of the
- * file name.
- */
- public String getMimeByExtension(String filename)
- {
- String type=null;
-
- if (filename!=null)
- {
- int i=-1;
- while(type==null)
- {
- i=filename.indexOf(".",i+1);
-
- if (i<0 || i>=filename.length())
- break;
-
- String ext=StringUtil.asciiToLowerCase(filename.substring(i+1));
- if (_mimeMap!=null)
- type=_mimeMap.get(ext);
- if (type==null)
- type=__dftMimeMap.get(ext);
- }
- }
-
- if (type==null)
- {
- if (_mimeMap!=null)
- type=_mimeMap.get("*");
- if (type==null)
- type=__dftMimeMap.get("*");
- }
-
- return type;
- }
-
- /* ------------------------------------------------------------ */
- /** Set a mime mapping
- * @param extension the extension
- * @param type the mime type
- */
- public void addMimeMapping(String extension,String type)
- {
- _mimeMap.put(StringUtil.asciiToLowerCase(extension),normalizeMimeType(type));
- }
-
- /* ------------------------------------------------------------ */
- public static Set getKnownMimeTypes()
- {
- return new HashSet<>(__dftMimeMap.values());
- }
-
- /* ------------------------------------------------------------ */
- private static String normalizeMimeType(String type)
- {
- MimeTypes.Type t =CACHE.get(type);
- if (t!=null)
- return t.asString();
-
- return StringUtil.asciiToLowerCase(type);
- }
-
- /* ------------------------------------------------------------ */
- public static String getCharsetFromContentType(String value)
- {
- if (value==null)
- return null;
- int end=value.length();
- int state=0;
- int start=0;
- boolean quote=false;
- int i=0;
- for (;i
- * This mapping implements the path specification recommended
- * in the 2.2 Servlet API.
- *
- *
- *
- * Path specifications can be of the following forms:
- *
- *
- * /foo/bar - an exact path specification.
- * /foo/* - a prefix path specification (must end '/*').
- * *.ext - a suffix path specification.
- * / - the default path specification.
- * "" - the / path specification
- *
- *
- * Matching is performed in the following order
- *
- * - Exact match.
- * - Longest prefix match.
- * - Longest suffix match.
- * - default.
- *
- *
- *
- * Multiple path specifications can be mapped by providing a list of
- * specifications. By default this class uses characters ":," as path
- * separators, unless configured differently by calling the static
- * method @see PathMap#setPathSpecSeparators(String)
- *
- * Special characters within paths such as '?� and ';' are not treated specially
- * as it is assumed they would have been either encoded in the original URL or
- * stripped from the path.
- *
- * This class is not synchronized. If concurrent modifications are
- * possible then it should be synchronized at a higher level.
- *
- * @param the Map.Entry value type
- * @deprecated replaced with {@link org.eclipse.jetty.http.pathmap.PathMappings} (this class will be removed in Jetty 10)
- */
-@Deprecated
-public class PathMap extends HashMap
-{
- /* ------------------------------------------------------------ */
- private static String __pathSpecSeparators = ":,";
-
- /* ------------------------------------------------------------ */
- /** Set the path spec separator.
- * Multiple path specification may be included in a single string
- * if they are separated by the characters set in this string.
- * By default this class uses ":," characters as path separators.
- * @param s separators
- */
- public static void setPathSpecSeparators(String s)
- {
- __pathSpecSeparators=s;
- }
-
- /* --------------------------------------------------------------- */
- Trie> _prefixMap=new ArrayTernaryTrie<>(false);
- Trie> _suffixMap=new ArrayTernaryTrie<>(false);
- final Map> _exactMap=new HashMap<>();
-
- List> _defaultSingletonList=null;
- MappedEntry _prefixDefault=null;
- MappedEntry _default=null;
- boolean _nodefault=false;
-
- /* --------------------------------------------------------------- */
- public PathMap()
- {
- this(11);
- }
-
- /* --------------------------------------------------------------- */
- public PathMap(boolean noDefault)
- {
- this(11, noDefault);
- }
-
- /* --------------------------------------------------------------- */
- public PathMap(int capacity)
- {
- this(capacity, false);
- }
-
- /* --------------------------------------------------------------- */
- private PathMap(int capacity, boolean noDefault)
- {
- super(capacity);
- _nodefault=noDefault;
- }
-
- /* --------------------------------------------------------------- */
- /**
- * Construct from dictionary PathMap.
- * @param dictMap the map representing the dictionary to build this PathMap from
- */
- public PathMap(Map dictMap)
- {
- putAll(dictMap);
- }
-
- /* --------------------------------------------------------------- */
- /** Add a single path match to the PathMap.
- * @param pathSpec The path specification, or comma separated list of
- * path specifications.
- * @param object The object the path maps to
- */
- @Override
- public O put(String pathSpec, O object)
- {
- if ("".equals(pathSpec.trim()))
- {
- MappedEntry entry = new MappedEntry<>("",object);
- entry.setMapped("");
- _exactMap.put("", entry);
- return super.put("", object);
- }
-
- StringTokenizer tok = new StringTokenizer(pathSpec,__pathSpecSeparators);
- O old =null;
-
- while (tok.hasMoreTokens())
- {
- String spec=tok.nextToken();
-
- if (!spec.startsWith("/") && !spec.startsWith("*."))
- throw new IllegalArgumentException("PathSpec "+spec+". must start with '/' or '*.'");
-
- old = super.put(spec,object);
-
- // Make entry that was just created.
- MappedEntry entry = new MappedEntry<>(spec,object);
-
- if (entry.getKey().equals(spec))
- {
- if (spec.equals("/*"))
- _prefixDefault=entry;
- else if (spec.endsWith("/*"))
- {
- String mapped=spec.substring(0,spec.length()-2);
- entry.setMapped(mapped);
- while (!_prefixMap.put(mapped,entry))
- _prefixMap=new ArrayTernaryTrie<>((ArrayTernaryTrie>)_prefixMap,1.5);
- }
- else if (spec.startsWith("*."))
- {
- String suffix=spec.substring(2);
- while(!_suffixMap.put(suffix,entry))
- _suffixMap=new ArrayTernaryTrie<>((ArrayTernaryTrie>)_suffixMap,1.5);
- }
- else if (spec.equals(URIUtil.SLASH))
- {
- if (_nodefault)
- _exactMap.put(spec,entry);
- else
- {
- _default=entry;
- _defaultSingletonList=Collections.singletonList(_default);
- }
- }
- else
- {
- entry.setMapped(spec);
- _exactMap.put(spec,entry);
- }
- }
- }
-
- return old;
- }
-
- /* ------------------------------------------------------------ */
- /** Get object matched by the path.
- * @param path the path.
- * @return Best matched object or null.
- */
- public O match(String path)
- {
- MappedEntry entry = getMatch(path);
- if (entry!=null)
- return entry.getValue();
- return null;
- }
-
-
- /* --------------------------------------------------------------- */
- /** Get the entry mapped by the best specification.
- * @param path the path.
- * @return Map.Entry of the best matched or null.
- */
- public MappedEntry getMatch(String path)
- {
- if (path==null)
- return null;
-
- int l=path.length();
-
- MappedEntry entry=null;
-
- //special case
- if (l == 1 && path.charAt(0)=='/')
- {
- entry = _exactMap.get("");
- if (entry != null)
- return entry;
- }
-
- // try exact match
- entry=_exactMap.get(path);
- if (entry!=null)
- return entry;
-
- // prefix search
- int i=l;
- final Trie> prefix_map=_prefixMap;
- while(i>=0)
- {
- entry=prefix_map.getBest(path,0,i);
- if (entry==null)
- break;
- String key = entry.getKey();
- if (key.length()-2>=path.length() || path.charAt(key.length()-2)=='/')
- return entry;
- i=key.length()-3;
- }
-
- // Prefix Default
- if (_prefixDefault!=null)
- return _prefixDefault;
-
- // Extension search
- i=0;
- final Trie> suffix_map=_suffixMap;
- while ((i=path.indexOf('.',i+1))>0)
- {
- entry=suffix_map.get(path,i+1,l-i-1);
- if (entry!=null)
- return entry;
- }
-
- // Default
- return _default;
- }
-
- /* --------------------------------------------------------------- */
- /** Get all entries matched by the path.
- * Best match first.
- * @param path Path to match
- * @return List of Map.Entry instances key=pathSpec
- */
- public List extends Map.Entry> getMatches(String path)
- {
- MappedEntry entry;
- List> entries=new ArrayList<>();
-
- if (path==null)
- return entries;
- if (path.length()==0)
- return _defaultSingletonList;
-
- // try exact match
- entry=_exactMap.get(path);
- if (entry!=null)
- entries.add(entry);
-
- // prefix search
- int l=path.length();
- int i=l;
- final Trie> prefix_map=_prefixMap;
- while(i>=0)
- {
- entry=prefix_map.getBest(path,0,i);
- if (entry==null)
- break;
- String key = entry.getKey();
- if (key.length()-2>=path.length() || path.charAt(key.length()-2)=='/')
- entries.add(entry);
-
- i=key.length()-3;
- }
-
- // Prefix Default
- if (_prefixDefault!=null)
- entries.add(_prefixDefault);
-
- // Extension search
- i=0;
- final Trie> suffix_map=_suffixMap;
- while ((i=path.indexOf('.',i+1))>0)
- {
- entry=suffix_map.get(path,i+1,l-i-1);
- if (entry!=null)
- entries.add(entry);
- }
-
- // root match
- if ("/".equals(path))
- {
- entry=_exactMap.get("");
- if (entry!=null)
- entries.add(entry);
- }
-
- // Default
- if (_default!=null)
- entries.add(_default);
-
- return entries;
- }
-
-
- /* --------------------------------------------------------------- */
- /** Return whether the path matches any entries in the PathMap,
- * excluding the default entry
- * @param path Path to match
- * @return Whether the PathMap contains any entries that match this
- */
- public boolean containsMatch(String path)
- {
- MappedEntry> match = getMatch(path);
- return match!=null && !match.equals(_default);
- }
-
- /* --------------------------------------------------------------- */
- @Override
- public O remove(Object pathSpec)
- {
- if (pathSpec!=null)
- {
- String spec=(String) pathSpec;
- if (spec.equals("/*"))
- _prefixDefault=null;
- else if (spec.endsWith("/*"))
- _prefixMap.remove(spec.substring(0,spec.length()-2));
- else if (spec.startsWith("*."))
- _suffixMap.remove(spec.substring(2));
- else if (spec.equals(URIUtil.SLASH))
- {
- _default=null;
- _defaultSingletonList=null;
- }
- else
- _exactMap.remove(spec);
- }
- return super.remove(pathSpec);
- }
-
- /* --------------------------------------------------------------- */
- @Override
- public void clear()
- {
- _exactMap.clear();
- _prefixMap=new ArrayTernaryTrie<>(false);
- _suffixMap=new ArrayTernaryTrie<>(false);
- _default=null;
- _defaultSingletonList=null;
- _prefixDefault=null;
- super.clear();
- }
-
- /* --------------------------------------------------------------- */
- /**
- * @param pathSpec the path spec
- * @param path the path
- * @return true if match.
- */
- public static boolean match(String pathSpec, String path)
- {
- return match(pathSpec, path, false);
- }
-
- /* --------------------------------------------------------------- */
- /**
- * @param pathSpec the path spec
- * @param path the path
- * @param noDefault true to not handle the default path "/" special, false to allow matcher rules to run
- * @return true if match.
- */
- public static boolean match(String pathSpec, String path, boolean noDefault)
- {
- if (pathSpec.length()==0)
- return "/".equals(path);
-
- char c = pathSpec.charAt(0);
- if (c=='/')
- {
- if (!noDefault && pathSpec.length()==1 || pathSpec.equals(path))
- return true;
-
- if(isPathWildcardMatch(pathSpec, path))
- return true;
- }
- else if (c=='*')
- return path.regionMatches(path.length()-pathSpec.length()+1,
- pathSpec,1,pathSpec.length()-1);
- return false;
- }
-
- /* --------------------------------------------------------------- */
- private static boolean isPathWildcardMatch(String pathSpec, String path)
- {
- // For a spec of "/foo/*" match "/foo" , "/foo/..." but not "/foobar"
- int cpl=pathSpec.length()-2;
- if (pathSpec.endsWith("/*") && path.regionMatches(0,pathSpec,0,cpl))
- {
- if (path.length()==cpl || '/'==path.charAt(cpl))
- return true;
- }
- return false;
- }
-
-
- /* --------------------------------------------------------------- */
- /** Return the portion of a path that matches a path spec.
- * @param pathSpec the path spec
- * @param path the path
- * @return null if no match at all.
- */
- public static String pathMatch(String pathSpec, String path)
- {
- char c = pathSpec.charAt(0);
-
- if (c=='/')
- {
- if (pathSpec.length()==1)
- return path;
-
- if (pathSpec.equals(path))
- return path;
-
- if (isPathWildcardMatch(pathSpec, path))
- return path.substring(0,pathSpec.length()-2);
- }
- else if (c=='*')
- {
- if (path.regionMatches(path.length()-(pathSpec.length()-1),
- pathSpec,1,pathSpec.length()-1))
- return path;
- }
- return null;
- }
-
- /* --------------------------------------------------------------- */
- /** Return the portion of a path that is after a path spec.
- * @param pathSpec the path spec
- * @param path the path
- * @return The path info string
- */
- public static String pathInfo(String pathSpec, String path)
- {
- if ("".equals(pathSpec))
- return path; //servlet 3 spec sec 12.2 will be '/'
-
- char c = pathSpec.charAt(0);
-
- if (c=='/')
- {
- if (pathSpec.length()==1)
- return null;
-
- boolean wildcard = isPathWildcardMatch(pathSpec, path);
-
- // handle the case where pathSpec uses a wildcard and path info is "/*"
- if (pathSpec.equals(path) && !wildcard)
- return null;
-
- if (wildcard)
- {
- if (path.length()==pathSpec.length()-2)
- return null;
- return path.substring(pathSpec.length()-2);
- }
- }
- return null;
- }
-
-
- /* ------------------------------------------------------------ */
- /** Relative path.
- * @param base The base the path is relative to.
- * @param pathSpec The spec of the path segment to ignore.
- * @param path the additional path
- * @return base plus path with pathspec removed
- */
- public static String relativePath(String base,
- String pathSpec,
- String path )
- {
- String info=pathInfo(pathSpec,path);
- if (info==null)
- info=path;
-
- if( info.startsWith( "./"))
- info = info.substring( 2);
- if( base.endsWith( URIUtil.SLASH))
- if( info.startsWith( URIUtil.SLASH))
- path = base + info.substring(1);
- else
- path = base + info;
- else
- if( info.startsWith( URIUtil.SLASH))
- path = base + info;
- else
- path = base + URIUtil.SLASH + info;
- return path;
- }
-
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- public static class MappedEntry implements Map.Entry
- {
- private final String key;
- private final O value;
- private String mapped;
-
- MappedEntry(String key, O value)
- {
- this.key=key;
- this.value=value;
- }
-
- @Override
- public String getKey()
- {
- return key;
- }
-
- @Override
- public O getValue()
- {
- return value;
- }
-
- @Override
- public O setValue(O o)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String toString()
- {
- return key+"="+value;
- }
-
- public String getMapped()
- {
- return mapped;
- }
-
- void setMapped(String mapped)
- {
- this.mapped = mapped;
- }
- }
-
- public static class PathSet extends AbstractSet implements Predicate
- {
- private final PathMap _map = new PathMap<>();
-
- @Override
- public Iterator iterator()
- {
- return _map.keySet().iterator();
- }
-
- @Override
- public int size()
- {
- return _map.size();
- }
-
- @Override
- public boolean add(String item)
- {
- return _map.put(item,Boolean.TRUE)==null;
- }
-
- @Override
- public boolean remove(Object item)
- {
- return _map.remove(item)!=null;
- }
-
- @Override
- public boolean contains(Object o)
- {
- return _map.containsKey(o);
- }
-
- @Override
- public boolean test(String s)
- {
- return _map.containsMatch(s);
- }
-
- public boolean containsMatch(String s)
- {
- return _map.containsMatch(s);
- }
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/PreEncodedHttpField.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/PreEncodedHttpField.java
deleted file mode 100644
index 6c81a91469..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/PreEncodedHttpField.java
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ServiceLoader;
-
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-
-/* ------------------------------------------------------------ */
-/** Pre encoded HttpField.
- * A HttpField that will be cached and used many times can be created as
- * a {@link PreEncodedHttpField}, which will use the {@link HttpFieldPreEncoder}
- * instances discovered by the {@link ServiceLoader} to pre-encode the header
- * for each version of HTTP in use. This will save garbage
- * and CPU each time the field is encoded into a response.
- *
- */
-public class PreEncodedHttpField extends HttpField
-{
- private final static Logger LOG = Log.getLogger(PreEncodedHttpField.class);
- private final static HttpFieldPreEncoder[] __encoders;
-
- static
- {
- List encoders = new ArrayList<>();
- Iterator iter = ServiceLoader.load(HttpFieldPreEncoder.class,PreEncodedHttpField.class.getClassLoader()).iterator();
- while (iter.hasNext())
- {
- try
- {
- encoders.add(iter.next());
- }
- catch(Error|RuntimeException e)
- {
- LOG.debug(e);
- }
- }
- // TODO avoid needing this catch all
- if (encoders.size()==0)
- encoders.add(new Http1FieldPreEncoder());
- LOG.debug("HttpField encoders loaded: {}",encoders);
- __encoders = encoders.toArray(new HttpFieldPreEncoder[encoders.size()]);
- }
-
- private final byte[][] _encodedField=new byte[2][];
-
- public PreEncodedHttpField(HttpHeader header,String name,String value)
- {
- super(header,name, value);
-
- for (HttpFieldPreEncoder e:__encoders)
- {
- _encodedField[e.getHttpVersion()==HttpVersion.HTTP_2?1:0]=e.getEncodedField(header,header.asString(),value);
- }
- }
-
- public PreEncodedHttpField(HttpHeader header,String value)
- {
- this(header,header.asString(),value);
- }
-
- public PreEncodedHttpField(String name,String value)
- {
- this(null,name,value);
- }
-
- public void putTo(ByteBuffer bufferInFillMode, HttpVersion version)
- {
- bufferInFillMode.put(_encodedField[version==HttpVersion.HTTP_2?1:0]);
- }
-}
\ No newline at end of file
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/QuotedCSV.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/QuotedCSV.java
deleted file mode 100644
index 8c9a779c41..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/QuotedCSV.java
+++ /dev/null
@@ -1,229 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.Iterator;
-import java.util.List;
-
-/* ------------------------------------------------------------ */
-/**
- * Implements a quoted comma separated list of values
- * in accordance with RFC7230.
- * OWS is removed and quoted characters ignored for parsing.
- * @see "https://tools.ietf.org/html/rfc7230#section-3.2.6"
- * @see "https://tools.ietf.org/html/rfc7230#section-7"
- */
-public class QuotedCSV implements Iterable
-{
- private enum State { VALUE, PARAM_NAME, PARAM_VALUE};
-
- private final List _values = new ArrayList<>();
- private final boolean _keepQuotes;
-
- /* ------------------------------------------------------------ */
- public QuotedCSV(String... values)
- {
- this(true,values);
- }
-
- /* ------------------------------------------------------------ */
- public QuotedCSV(boolean keepQuotes,String... values)
- {
- _keepQuotes=keepQuotes;
- for (String v:values)
- addValue(v);
- }
-
- /* ------------------------------------------------------------ */
- public void addValue(String value)
- {
- StringBuffer buffer = new StringBuffer();
-
- int l=value.length();
- State state=State.VALUE;
- boolean quoted=false;
- boolean sloshed=false;
- int nws_length=0;
- int last_length=0;
- for (int i=0;i<=l;i++)
- {
- char c=i==l?0:value.charAt(i);
-
- // Handle quoting https://tools.ietf.org/html/rfc7230#section-3.2.6
- if (quoted && c!=0)
- {
- if (sloshed)
- sloshed=false;
- else
- {
- switch(c)
- {
- case '\\':
- sloshed=true;
- if (!_keepQuotes)
- continue;
- break;
- case '"':
- quoted=false;
- if (!_keepQuotes)
- continue;
- break;
- }
- }
-
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- // Handle common cases
- switch(c)
- {
- case ' ':
- case '\t':
- if (buffer.length()>last_length) // not leading OWS
- buffer.append(c);
- continue;
-
- case '"':
- quoted=true;
- if (_keepQuotes)
- buffer.append(c);
- nws_length=buffer.length();
- continue;
-
- case ';':
- buffer.setLength(nws_length); // trim following OWS
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_NAME;
- continue;
-
- case ',':
- case 0:
- if (nws_length>0)
- {
- buffer.setLength(nws_length); // trim following OWS
- _values.add(buffer.toString());
- }
- buffer.setLength(0);
- last_length=0;
- nws_length=0;
- state=State.VALUE;
- continue;
-
- default:
- {
- switch (state)
- {
- case VALUE:
- {
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- case PARAM_NAME:
- {
- if (c=='=')
- {
- buffer.setLength(nws_length); // trim following OWS
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_VALUE;
- continue;
- }
- buffer.append(c);
- nws_length=buffer.length();
-
- continue;
- }
-
- case PARAM_VALUE:
- {
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
- }
- }
- }
- }
- }
-
- public List getValues()
- {
- return _values;
- }
-
- @Override
- public Iterator iterator()
- {
- return _values.iterator();
- }
-
- public static String unquote(String s)
- {
- // handle trivial cases
- int l=s.length();
- if (s==null || l==0)
- return s;
-
- // Look for any quotes
- int i=0;
- for (;i
-{
- private final static Double ZERO=new Double(0.0);
- private final static Double ONE=new Double(1.0);
- private enum State { VALUE, PARAM_NAME, PARAM_VALUE, Q_VALUE};
-
- private final List _values = new ArrayList<>();
- private final List _quality = new ArrayList<>();
- private boolean _sorted = false;
-
- /* ------------------------------------------------------------ */
- public QuotedQualityCSV(String... values)
- {
- for (String v:values)
- addValue(v);
- }
-
-
- /* ------------------------------------------------------------ */
- public void addValue(String value)
- {
- StringBuffer buffer = new StringBuffer();
-
- int l=value.length();
- State state=State.VALUE;
- boolean quoted=false;
- boolean sloshed=false;
- int nws_length=0;
- int last_length=0;
- Double q=ONE;
- for (int i=0;i<=l;i++)
- {
- char c=i==l?0:value.charAt(i);
-
- // Handle quoting https://tools.ietf.org/html/rfc7230#section-3.2.6
- if (quoted && c!=0)
- {
- if (sloshed)
- sloshed=false;
- else
- {
- switch(c)
- {
- case '\\':
- sloshed=true;
- break;
- case '"':
- quoted=false;
- if (state==State.Q_VALUE)
- continue;
- break;
- }
- }
-
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- // Handle common cases
- switch(c)
- {
- case ' ':
- case '\t':
- if (buffer.length()>last_length) // not leading OWS
- buffer.append(c);
- continue;
-
- case '"':
- quoted=true;
- if (state==State.Q_VALUE)
- continue;
-
- buffer.append(c);
- nws_length=buffer.length();
- continue;
-
- case ';':
- if (state==State.Q_VALUE)
- {
- try
- {
- q=new Double(buffer.substring(last_length));
- }
- catch(Exception e)
- {
- q=ZERO;
- }
- nws_length=last_length;
- }
-
- buffer.setLength(nws_length); // trim following OWS
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_NAME;
- continue;
-
- case ',':
- case 0:
- if (state==State.Q_VALUE)
- {
- try
- {
- q=new Double(buffer.substring(last_length));
- }
- catch(Exception e)
- {
- q=ZERO;
- }
- nws_length=last_length;
- }
- buffer.setLength(nws_length); // trim following OWS
- if (q>0.0 && nws_length>0)
- {
- _values.add(buffer.toString());
- _quality.add(q);
- _sorted=false;
- }
- buffer.setLength(0);
- last_length=0;
- nws_length=0;
- q=ONE;
- state=State.VALUE;
- continue;
-
- default:
- {
- switch (state)
- {
- case VALUE:
- {
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- case PARAM_NAME:
- {
- if (c=='=')
- {
- buffer.setLength(nws_length); // trim following OWS
- if (nws_length-last_length==1 && Character.toLowerCase(buffer.charAt(last_length))=='q')
- {
- buffer.setLength(last_length-1);
- nws_length=buffer.length();
- last_length=nws_length;
- state=State.Q_VALUE;
- continue;
- }
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_VALUE;
- continue;
- }
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- case PARAM_VALUE:
- case Q_VALUE:
- {
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
- }
- }
- }
- }
- }
-
- public List getValues()
- {
- if (!_sorted)
- sort();
- return _values;
- }
-
- @Override
- public Iterator iterator()
- {
- if (!_sorted)
- sort();
- return _values.iterator();
- }
-
- protected void sort()
- {
- _sorted=true;
-
- Double last = ZERO;
- int len = Integer.MIN_VALUE;
-
- for (int i = _values.size(); i-- > 0;)
- {
- String v = _values.get(i);
- Double q = _quality.get(i);
-
- int compare=last.compareTo(q);
- if (compare > 0 || (compare==0 && v.length()The HttpContent is used to server static content that is not
- * cached. So fields and values are only generated as need be an not
- * kept for reuse
- */
-public class ResourceHttpContent implements HttpContent
-{
- final Resource _resource;
- final String _contentType;
- final int _maxBuffer;
- HttpContent _gzip;
- String _etag;
-
- /* ------------------------------------------------------------ */
- public ResourceHttpContent(final Resource resource, final String contentType)
- {
- this(resource,contentType,-1,null);
- }
-
- /* ------------------------------------------------------------ */
- public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer)
- {
- this(resource,contentType,maxBuffer,null);
- }
-
- /* ------------------------------------------------------------ */
- public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer, HttpContent gzip)
- {
- _resource=resource;
- _contentType=contentType;
- _maxBuffer=maxBuffer;
- _gzip=gzip;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String getContentTypeValue()
- {
- return _contentType;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public HttpField getContentType()
- {
- return _contentType==null?null:new HttpField(HttpHeader.CONTENT_TYPE,_contentType);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public HttpField getContentEncoding()
- {
- return null;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String getContentEncodingValue()
- {
- return null;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String getCharacterEncoding()
- {
- return _contentType==null?null:MimeTypes.getCharsetFromContentType(_contentType);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public Type getMimeType()
- {
- return _contentType==null?null:MimeTypes.CACHE.get(MimeTypes.getContentTypeWithoutCharset(_contentType));
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public HttpField getLastModified()
- {
- long lm = _resource.lastModified();
- return lm>=0?new HttpField(HttpHeader.LAST_MODIFIED,DateGenerator.formatDate(lm)):null;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String getLastModifiedValue()
- {
- long lm = _resource.lastModified();
- return lm>=0?DateGenerator.formatDate(lm):null;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public ByteBuffer getDirectBuffer()
- {
- if (_resource.length()<=0 || _maxBuffer>0 && _maxBuffer<_resource.length())
- return null;
- try
- {
- return BufferUtil.toBuffer(_resource,true);
- }
- catch(IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public HttpField getETag()
- {
- return new HttpField(HttpHeader.ETAG,getETagValue());
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String getETagValue()
- {
- return _resource.getWeakETag();
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public ByteBuffer getIndirectBuffer()
- {
- if (_resource.length()<=0 || _maxBuffer>0 && _maxBuffer<_resource.length())
- return null;
- try
- {
- return BufferUtil.toBuffer(_resource,false);
- }
- catch(IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public HttpField getContentLength()
- {
- long l=_resource.length();
- return l==-1?null:new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,_resource.length());
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public long getContentLengthValue()
- {
- return _resource.length();
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public InputStream getInputStream() throws IOException
- {
- return _resource.getInputStream();
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public ReadableByteChannel getReadableByteChannel() throws IOException
- {
- return _resource.getReadableByteChannel();
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public Resource getResource()
- {
- return _resource;
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public void release()
- {
- _resource.close();
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String toString()
- {
- return String.format("%s@%x{r=%s,gz=%b}",this.getClass().getSimpleName(),hashCode(),_resource,_gzip!=null);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public HttpContent getGzipContent()
- {
- return _gzip==null?null:new GzipHttpContent(this,_gzip);
- }
-
-}
\ No newline at end of file
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/encoding.properties b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/encoding.properties
deleted file mode 100644
index 04fe87e751..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/encoding.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-text/html=utf-8
-text/plain=iso-8859-1
-text/xml=utf-8
-text/json=utf-8
-application/xhtml+xml=utf-8
\ No newline at end of file
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/mime.properties b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/mime.properties
deleted file mode 100644
index 0112b88a25..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/mime.properties
+++ /dev/null
@@ -1,189 +0,0 @@
-ai=application/postscript
-aif=audio/x-aiff
-aifc=audio/x-aiff
-aiff=audio/x-aiff
-apk=application/vnd.android.package-archive
-asc=text/plain
-asf=video/x.ms.asf
-asx=video/x.ms.asx
-au=audio/basic
-avi=video/x-msvideo
-bcpio=application/x-bcpio
-bin=application/octet-stream
-bmp=image/bmp
-cab=application/x-cabinet
-cdf=application/x-netcdf
-chm=application/vnd.ms-htmlhelp
-class=application/java-vm
-cpio=application/x-cpio
-cpt=application/mac-compactpro
-crt=application/x-x509-ca-cert
-csh=application/x-csh
-css=text/css
-csv=text/csv
-dcr=application/x-director
-dir=application/x-director
-dll=application/x-msdownload
-dms=application/octet-stream
-doc=application/msword
-dtd=application/xml-dtd
-dvi=application/x-dvi
-dxr=application/x-director
-eps=application/postscript
-etx=text/x-setext
-exe=application/octet-stream
-ez=application/andrew-inset
-gif=image/gif
-gtar=application/x-gtar
-gz=application/gzip
-gzip=application/gzip
-hdf=application/x-hdf
-hqx=application/mac-binhex40
-htc=text/x-component
-htm=text/html
-html=text/html
-ice=x-conference/x-cooltalk
-ico=image/x-icon
-ief=image/ief
-iges=model/iges
-igs=model/iges
-jad=text/vnd.sun.j2me.app-descriptor
-jar=application/java-archive
-java=text/plain
-jnlp=application/x-java-jnlp-file
-jpe=image/jpeg
-jp2=image/jpeg2000
-jpeg=image/jpeg
-jpg=image/jpeg
-js=application/javascript
-json=application/json
-jsp=text/html
-kar=audio/midi
-latex=application/x-latex
-lha=application/octet-stream
-lzh=application/octet-stream
-man=application/x-troff-man
-mathml=application/mathml+xml
-me=application/x-troff-me
-mesh=model/mesh
-mid=audio/midi
-midi=audio/midi
-mif=application/vnd.mif
-mol=chemical/x-mdl-molfile
-mov=video/quicktime
-movie=video/x-sgi-movie
-mp2=audio/mpeg
-mp3=audio/mpeg
-mpe=video/mpeg
-mpeg=video/mpeg
-mpg=video/mpeg
-mpga=audio/mpeg
-ms=application/x-troff-ms
-msh=model/mesh
-msi=application/octet-stream
-nc=application/x-netcdf
-oda=application/oda
-odb=application/vnd.oasis.opendocument.database
-odc=application/vnd.oasis.opendocument.chart
-odf=application/vnd.oasis.opendocument.formula
-odg=application/vnd.oasis.opendocument.graphics
-odi=application/vnd.oasis.opendocument.image
-odm=application/vnd.oasis.opendocument.text-master
-odp=application/vnd.oasis.opendocument.presentation
-ods=application/vnd.oasis.opendocument.spreadsheet
-odt=application/vnd.oasis.opendocument.text
-ogg=application/ogg
-otc=application/vnd.oasis.opendocument.chart-template
-otf=application/vnd.oasis.opendocument.formula-template
-otg=application/vnd.oasis.opendocument.graphics-template
-oth=application/vnd.oasis.opendocument.text-web
-oti=application/vnd.oasis.opendocument.image-template
-otp=application/vnd.oasis.opendocument.presentation-template
-ots=application/vnd.oasis.opendocument.spreadsheet-template
-ott=application/vnd.oasis.opendocument.text-template
-pbm=image/x-portable-bitmap
-pdb=chemical/x-pdb
-pdf=application/pdf
-pgm=image/x-portable-graymap
-pgn=application/x-chess-pgn
-png=image/png
-pnm=image/x-portable-anymap
-ppm=image/x-portable-pixmap
-pps=application/vnd.ms-powerpoint
-ppt=application/vnd.ms-powerpoint
-ps=application/postscript
-qml=text/x-qml
-qt=video/quicktime
-ra=audio/x-pn-realaudio
-rar=application/x-rar-compressed
-ram=audio/x-pn-realaudio
-ras=image/x-cmu-raster
-rdf=application/rdf+xml
-rgb=image/x-rgb
-rm=audio/x-pn-realaudio
-roff=application/x-troff
-rpm=application/x-rpm
-rtf=application/rtf
-rtx=text/richtext
-rv=video/vnd.rn-realvideo
-ser=application/java-serialized-object
-sgm=text/sgml
-sgml=text/sgml
-sh=application/x-sh
-shar=application/x-shar
-silo=model/mesh
-sit=application/x-stuffit
-skd=application/x-koan
-skm=application/x-koan
-skp=application/x-koan
-skt=application/x-koan
-smi=application/smil
-smil=application/smil
-snd=audio/basic
-spl=application/x-futuresplash
-src=application/x-wais-source
-sv4cpio=application/x-sv4cpio
-sv4crc=application/x-sv4crc
-svg=image/svg+xml
-svgz=image/svg+xml
-swf=application/x-shockwave-flash
-t=application/x-troff
-tar=application/x-tar
-tar.gz=application/x-gtar
-tcl=application/x-tcl
-tex=application/x-tex
-texi=application/x-texinfo
-texinfo=application/x-texinfo
-tgz=application/x-gtar
-tif=image/tiff
-tiff=image/tiff
-tr=application/x-troff
-tsv=text/tab-separated-values
-txt=text/plain
-ustar=application/x-ustar
-vcd=application/x-cdlink
-vrml=model/vrml
-vxml=application/voicexml+xml
-wav=audio/x-wav
-wbmp=image/vnd.wap.wbmp
-wml=text/vnd.wap.wml
-wmlc=application/vnd.wap.wmlc
-wmls=text/vnd.wap.wmlscript
-wmlsc=application/vnd.wap.wmlscriptc
-wrl=model/vrml
-wtls-ca-certificate=application/vnd.wap.wtls-ca-certificate
-xbm=image/x-xbitmap
-xcf=image/xcf
-xht=application/xhtml+xml
-xhtml=application/xhtml+xml
-xls=application/vnd.ms-excel
-xml=application/xml
-xpm=image/x-xpixmap
-xsd=application/xml
-xsl=application/xml
-xslt=application/xslt+xml
-xul=application/vnd.mozilla.xul+xml
-xwd=image/x-xwindowdump
-xyz=chemical/x-xyz
-z=application/compress
-zip=application/zip
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/package-info.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/package-info.java
deleted file mode 100644
index aeca4a3f2a..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.
-// ========================================================================
-//
-
-/**
- * Jetty Http : Tools for Http processing
- */
-package org.eclipse.jetty.http;
-
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/MappedResource.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/MappedResource.java
deleted file mode 100644
index 155dce8b8b..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/MappedResource.java
+++ /dev/null
@@ -1,101 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.pathmap;
-
-import org.eclipse.jetty.util.annotation.ManagedAttribute;
-import org.eclipse.jetty.util.annotation.ManagedObject;
-
-@ManagedObject("Mapped Resource")
-public class MappedResource implements Comparable>
-{
- private final PathSpec pathSpec;
- private final E resource;
-
- public MappedResource(PathSpec pathSpec, E resource)
- {
- this.pathSpec = pathSpec;
- this.resource = resource;
- }
-
- /**
- * Comparison is based solely on the pathSpec
- */
- @Override
- public int compareTo(MappedResource other)
- {
- return this.pathSpec.compareTo(other.pathSpec);
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- MappedResource> other = (MappedResource>)obj;
- if (pathSpec == null)
- {
- if (other.pathSpec != null)
- {
- return false;
- }
- }
- else if (!pathSpec.equals(other.pathSpec))
- {
- return false;
- }
- return true;
- }
-
- @ManagedAttribute(value = "path spec", readonly = true)
- public PathSpec getPathSpec()
- {
- return pathSpec;
- }
-
- @ManagedAttribute(value = "resource", readonly = true)
- public E getResource()
- {
- return resource;
- }
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = (prime * result) + ((pathSpec == null) ? 0 : pathSpec.hashCode());
- return result;
- }
-
- @Override
- public String toString()
- {
- return String.format("MappedResource[pathSpec=%s,resource=%s]",pathSpec,resource);
- }
-}
\ No newline at end of file
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathMappings.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathMappings.java
deleted file mode 100644
index d1c36cfbd6..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathMappings.java
+++ /dev/null
@@ -1,159 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.pathmap;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.jetty.util.annotation.ManagedAttribute;
-import org.eclipse.jetty.util.annotation.ManagedObject;
-import org.eclipse.jetty.util.component.ContainerLifeCycle;
-import org.eclipse.jetty.util.component.Dumpable;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-/**
- * Path Mappings of PathSpec to Resource.
- *
- * Sorted into search order upon entry into the Set
- *
- * @param the type of mapping endpoint
- */
-@ManagedObject("Path Mappings")
-public class PathMappings implements Iterable>, Dumpable
-{
- private static final Logger LOG = Log.getLogger(PathMappings.class);
- private List> mappings = new ArrayList>();
- private MappedResource defaultResource = null;
- private MappedResource rootResource = null;
-
- @Override
- public String dump()
- {
- return ContainerLifeCycle.dump(this);
- }
-
- @Override
- public void dump(Appendable out, String indent) throws IOException
- {
- ContainerLifeCycle.dump(out,indent,mappings);
- }
-
- @ManagedAttribute(value = "mappings", readonly = true)
- public List> getMappings()
- {
- return mappings;
- }
-
- public void reset()
- {
- mappings.clear();
- }
-
- /**
- * Return a list of MappedResource matches for the specified path.
- *
- * @param path the path to return matches on
- * @return the list of mapped resource the path matches on
- */
- public List> getMatches(String path)
- {
- boolean matchRoot = "/".equals(path);
-
- List> ret = new ArrayList<>();
- int len = mappings.size();
- for (int i = 0; i < len; i++)
- {
- MappedResource mr = mappings.get(i);
-
- switch (mr.getPathSpec().group)
- {
- case ROOT:
- if (matchRoot)
- ret.add(mr);
- break;
- case DEFAULT:
- if (matchRoot || mr.getPathSpec().matches(path))
- ret.add(mr);
- break;
- default:
- if (mr.getPathSpec().matches(path))
- ret.add(mr);
- break;
- }
- }
- return ret;
- }
-
- public MappedResource getMatch(String path)
- {
- if (path.equals("/") && rootResource != null)
- {
- return rootResource;
- }
-
- int len = mappings.size();
- for (int i = 0; i < len; i++)
- {
- MappedResource mr = mappings.get(i);
- if (mr.getPathSpec().matches(path))
- {
- return mr;
- }
- }
- return defaultResource;
- }
-
- @Override
- public Iterator> iterator()
- {
- return mappings.iterator();
- }
-
- @SuppressWarnings("incomplete-switch")
- public void put(PathSpec pathSpec, E resource)
- {
- MappedResource entry = new MappedResource<>(pathSpec,resource);
- switch (pathSpec.group)
- {
- case DEFAULT:
- defaultResource = entry;
- break;
- case ROOT:
- rootResource = entry;
- break;
- }
-
- // TODO: add warning when replacing an existing pathspec?
-
- mappings.add(entry);
- if (LOG.isDebugEnabled())
- LOG.debug("Added {} to {}",entry,this);
- Collections.sort(mappings);
- }
-
- @Override
- public String toString()
- {
- return String.format("%s[size=%d]",this.getClass().getSimpleName(),mappings.size());
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpec.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpec.java
deleted file mode 100644
index a2b8ea56cf..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpec.java
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.pathmap;
-
-/**
- * The base PathSpec, what all other path specs are based on
- */
-public abstract class PathSpec implements Comparable
-{
- protected String pathSpec;
- protected PathSpecGroup group;
- protected int pathDepth;
- protected int specLength;
-
- @Override
- public int compareTo(PathSpec other)
- {
- // Grouping (increasing)
- int diff = this.group.ordinal() - other.group.ordinal();
- if (diff != 0)
- {
- return diff;
- }
-
- // Spec Length (decreasing)
- diff = other.specLength - this.specLength;
- if (diff != 0)
- {
- return diff;
- }
-
- // Path Spec Name (alphabetical)
- return this.pathSpec.compareTo(other.pathSpec);
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- if (obj == null)
- {
- return false;
- }
- if (getClass() != obj.getClass())
- {
- return false;
- }
- PathSpec other = (PathSpec)obj;
- if (pathSpec == null)
- {
- if (other.pathSpec != null)
- {
- return false;
- }
- }
- else if (!pathSpec.equals(other.pathSpec))
- {
- return false;
- }
- return true;
- }
-
- public PathSpecGroup getGroup()
- {
- return group;
- }
-
- /**
- * Get the number of path elements that this path spec declares.
- *
- * This is used to determine longest match logic.
- *
- * @return the depth of the path segments that this spec declares
- */
- public int getPathDepth()
- {
- return pathDepth;
- }
-
- /**
- * Return the portion of the path that is after the path spec.
- *
- * @param path
- * the path to match against
- * @return the path info portion of the string
- */
- public abstract String getPathInfo(String path);
-
- /**
- * Return the portion of the path that matches a path spec.
- *
- * @param path
- * the path to match against
- * @return the match, or null if no match at all
- */
- public abstract String getPathMatch(String path);
-
- /**
- * The as-provided path spec.
- *
- * @return the as-provided path spec
- */
- public String getDeclaration()
- {
- return pathSpec;
- }
-
- /**
- * Get the relative path.
- *
- * @param base
- * the base the path is relative to
- * @param path
- * the additional path
- * @return the base plus path with pathSpec portion removed
- */
- public abstract String getRelativePath(String base, String path);
-
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = (prime * result) + ((pathSpec == null)?0:pathSpec.hashCode());
- return result;
- }
-
- /**
- * Test to see if the provided path matches this path spec
- *
- * @param path
- * the path to test
- * @return true if the path matches this path spec, false otherwise
- */
- public abstract boolean matches(String path);
-
- @Override
- public String toString()
- {
- StringBuilder str = new StringBuilder();
- str.append(this.getClass().getSimpleName()).append("[\"");
- str.append(pathSpec);
- str.append("\",pathDepth=").append(pathDepth);
- str.append(",group=").append(group);
- str.append("]");
- return str.toString();
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpecGroup.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpecGroup.java
deleted file mode 100644
index f9d96ced22..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpecGroup.java
+++ /dev/null
@@ -1,101 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.pathmap;
-
-/**
- * Types of path spec groups.
- *
- * This is used to facilitate proper pathspec search order.
- *
- * Search Order:
- *
- * - {@link PathSpecGroup#ordinal()} [increasing]
- * - {@link PathSpec#specLength} [decreasing]
- * - {@link PathSpec#pathSpec} [natural sort order]
- *
- */
-public enum PathSpecGroup
-{
- // NOTE: Order of enums determines order of Groups.
-
- /**
- * For exactly defined path specs, no glob.
- */
- EXACT,
- /**
- * For path specs that have a hardcoded prefix and suffix with wildcard glob in the middle.
- *
- *
- * "^/downloads/[^/]*.zip$" - regex spec
- * "/a/{var}/c" - uri-template spec
- *
- *
- * Note: there is no known servlet spec variant of this kind of path spec
- */
- MIDDLE_GLOB,
- /**
- * For path specs that have a hardcoded prefix and a trailing wildcard glob.
- *
- *
- *
- * "/downloads/*" - servlet spec
- * "/api/*" - servlet spec
- * "^/rest/.*$" - regex spec
- * "/bookings/{guest-id}" - uri-template spec
- * "/rewards/{vip-level}" - uri-template spec
- *
- */
- PREFIX_GLOB,
- /**
- * For path specs that have a wildcard glob with a hardcoded suffix
- *
- *
- * "*.do" - servlet spec
- * "*.css" - servlet spec
- * "^.*\.zip$" - regex spec
- *
- *
- * Note: there is no known uri-template spec variant of this kind of path spec
- */
- SUFFIX_GLOB,
- /**
- * The root spec for accessing the Root behavior.
- *
- *
- * "" - servlet spec (Root Servlet)
- * null - servlet spec (Root Servlet)
- *
- *
- * Note: there is no known uri-template spec variant of this kind of path spec
- */
- ROOT,
- /**
- * The default spec for accessing the Default path behavior.
- *
- *
- * "/" - servlet spec (Default Servlet)
- * "/" - uri-template spec (Root Context)
- * "^/$" - regex spec (Root Context)
- *
- *
- * Per Servlet Spec, pathInfo is always null for these specs.
- * If nothing above matches, then default will match.
- */
- DEFAULT,
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpecSet.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpecSet.java
deleted file mode 100644
index c1a3235472..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/PathSpecSet.java
+++ /dev/null
@@ -1,222 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.pathmap;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.function.Predicate;
-
-/**
- * A Set of PathSpec strings.
- *
- * Used by {@link org.eclipse.jetty.util.IncludeExclude} logic
- */
-public class PathSpecSet implements Set, Predicate
-{
- private final Set specs = new TreeSet<>();
-
- @Override
- public boolean test(String s)
- {
- for (PathSpec spec : specs)
- {
- if (spec.matches(s))
- {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean isEmpty()
- {
- return specs.isEmpty();
- }
-
- @Override
- public Iterator iterator()
- {
- return new Iterator()
- {
- private Iterator iter = specs.iterator();
-
- @Override
- public boolean hasNext()
- {
- return iter.hasNext();
- }
-
- @Override
- public String next()
- {
- PathSpec spec = iter.next();
- if (spec == null)
- {
- return null;
- }
- return spec.getDeclaration();
- }
-
- @Override
- public void remove()
- {
- throw new UnsupportedOperationException("Remove not supported by this Iterator");
- }
- };
- }
-
- @Override
- public int size()
- {
- return specs.size();
- }
-
- @Override
- public boolean contains(Object o)
- {
- if (o instanceof PathSpec)
- {
- return specs.contains(o);
- }
- if (o instanceof String)
- {
- return specs.contains(toPathSpec((String)o));
- }
- return false;
- }
-
- private PathSpec asPathSpec(Object o)
- {
- if (o == null)
- {
- return null;
- }
- if (o instanceof PathSpec)
- {
- return (PathSpec)o;
- }
- if (o instanceof String)
- {
- return toPathSpec((String)o);
- }
- return toPathSpec(o.toString());
- }
-
- private PathSpec toPathSpec(String rawSpec)
- {
- if ((rawSpec == null) || (rawSpec.length() < 1))
- {
- throw new RuntimeException("Path Spec String must start with '^', '/', or '*.': got [" + rawSpec + "]");
- }
- if (rawSpec.charAt(0) == '^')
- {
- return new RegexPathSpec(rawSpec);
- }
- else
- {
- return new ServletPathSpec(rawSpec);
- }
- }
-
- @Override
- public Object[] toArray()
- {
- return toArray(new String[specs.size()]);
- }
-
- @Override
- public T[] toArray(T[] a)
- {
- int i = 0;
- for (PathSpec spec : specs)
- {
- a[i++] = (T)spec.getDeclaration();
- }
- return a;
- }
-
- @Override
- public boolean add(String e)
- {
- return specs.add(toPathSpec(e));
- }
-
- @Override
- public boolean remove(Object o)
- {
- return specs.remove(asPathSpec(o));
- }
-
- @Override
- public boolean containsAll(Collection> coll)
- {
- for (Object o : coll)
- {
- if (!specs.contains(asPathSpec(o)))
- return false;
- }
- return true;
- }
-
- @Override
- public boolean addAll(Collection extends String> coll)
- {
- boolean ret = false;
-
- for (String s : coll)
- {
- ret |= add(s);
- }
-
- return ret;
- }
-
- @Override
- public boolean retainAll(Collection> coll)
- {
- List collSpecs = new ArrayList<>();
- for (Object o : coll)
- {
- collSpecs.add(asPathSpec(o));
- }
- return specs.retainAll(collSpecs);
- }
-
- @Override
- public boolean removeAll(Collection> coll)
- {
- List collSpecs = new ArrayList<>();
- for (Object o : coll)
- {
- collSpecs.add(asPathSpec(o));
- }
- return specs.removeAll(collSpecs);
- }
-
- @Override
- public void clear()
- {
- specs.clear();
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/RegexPathSpec.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/RegexPathSpec.java
deleted file mode 100644
index 0d83f3b000..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/RegexPathSpec.java
+++ /dev/null
@@ -1,176 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.pathmap;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class RegexPathSpec extends PathSpec
-{
- protected Pattern pattern;
-
- protected RegexPathSpec()
- {
- super();
- }
-
- public RegexPathSpec(String regex)
- {
- super.pathSpec = regex;
- boolean inGrouping = false;
- this.pathDepth = 0;
- this.specLength = pathSpec.length();
- // build up a simple signature we can use to identify the grouping
- StringBuilder signature = new StringBuilder();
- for (char c : pathSpec.toCharArray())
- {
- switch (c)
- {
- case '[':
- inGrouping = true;
- break;
- case ']':
- inGrouping = false;
- signature.append('g'); // glob
- break;
- case '*':
- signature.append('g'); // glob
- break;
- case '/':
- if (!inGrouping)
- {
- this.pathDepth++;
- }
- break;
- default:
- if (!inGrouping)
- {
- if (Character.isLetterOrDigit(c))
- {
- signature.append('l'); // literal (exact)
- }
- }
- break;
- }
- }
- this.pattern = Pattern.compile(pathSpec);
-
- // Figure out the grouping based on the signature
- String sig = signature.toString();
-
- if (Pattern.matches("^l*$",sig))
- {
- this.group = PathSpecGroup.EXACT;
- }
- else if (Pattern.matches("^l*g+",sig))
- {
- this.group = PathSpecGroup.PREFIX_GLOB;
- }
- else if (Pattern.matches("^g+l+$",sig))
- {
- this.group = PathSpecGroup.SUFFIX_GLOB;
- }
- else
- {
- this.group = PathSpecGroup.MIDDLE_GLOB;
- }
- }
-
- public Matcher getMatcher(String path)
- {
- return this.pattern.matcher(path);
- }
-
- @Override
- public String getPathInfo(String path)
- {
- // Path Info only valid for PREFIX_GLOB types
- if (group == PathSpecGroup.PREFIX_GLOB)
- {
- Matcher matcher = getMatcher(path);
- if (matcher.matches())
- {
- if (matcher.groupCount() >= 1)
- {
- String pathInfo = matcher.group(1);
- if ("".equals(pathInfo))
- {
- return "/";
- }
- else
- {
- return pathInfo;
- }
- }
- }
- }
- return null;
- }
-
- @Override
- public String getPathMatch(String path)
- {
- Matcher matcher = getMatcher(path);
- if (matcher.matches())
- {
- if (matcher.groupCount() >= 1)
- {
- int idx = matcher.start(1);
- if (idx > 0)
- {
- if (path.charAt(idx - 1) == '/')
- {
- idx--;
- }
- return path.substring(0,idx);
- }
- }
- return path;
- }
- return null;
- }
-
- public Pattern getPattern()
- {
- return this.pattern;
- }
-
- @Override
- public String getRelativePath(String base, String path)
- {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public boolean matches(final String path)
- {
- int idx = path.indexOf('?');
- if (idx >= 0)
- {
- // match only non-query part
- return getMatcher(path.substring(0,idx)).matches();
- }
- else
- {
- // match entire path
- return getMatcher(path).matches();
- }
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/ServletPathSpec.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/ServletPathSpec.java
deleted file mode 100644
index 4563305659..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/ServletPathSpec.java
+++ /dev/null
@@ -1,261 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.pathmap;
-
-import org.eclipse.jetty.util.URIUtil;
-
-public class ServletPathSpec extends PathSpec
-{
- public ServletPathSpec(String servletPathSpec)
- {
- super();
- assertValidServletPathSpec(servletPathSpec);
-
- // The Root Path Spec
- if ((servletPathSpec == null) || (servletPathSpec.length() == 0))
- {
- super.pathSpec = "";
- super.pathDepth = -1; // force this to be at the end of the sort order
- this.specLength = 1;
- this.group = PathSpecGroup.ROOT;
- return;
- }
-
- // The Default Path Spec
- if("/".equals(servletPathSpec))
- {
- super.pathSpec = "/";
- super.pathDepth = -1; // force this to be at the end of the sort order
- this.specLength = 1;
- this.group = PathSpecGroup.DEFAULT;
- return;
- }
-
- this.specLength = servletPathSpec.length();
- super.pathDepth = 0;
- char lastChar = servletPathSpec.charAt(specLength - 1);
- // prefix based
- if ((servletPathSpec.charAt(0) == '/') && (specLength > 1) && (lastChar == '*'))
- {
- this.group = PathSpecGroup.PREFIX_GLOB;
- }
- // suffix based
- else if (servletPathSpec.charAt(0) == '*')
- {
- this.group = PathSpecGroup.SUFFIX_GLOB;
- }
- else
- {
- this.group = PathSpecGroup.EXACT;
- }
-
- for (int i = 0; i < specLength; i++)
- {
- int cp = servletPathSpec.codePointAt(i);
- if (cp < 128)
- {
- char c = (char)cp;
- switch (c)
- {
- case '/':
- super.pathDepth++;
- break;
- }
- }
- }
-
- super.pathSpec = servletPathSpec;
- }
-
- private void assertValidServletPathSpec(String servletPathSpec)
- {
- if ((servletPathSpec == null) || servletPathSpec.equals(""))
- {
- return; // empty path spec
- }
-
- int len = servletPathSpec.length();
- // path spec must either start with '/' or '*.'
- if (servletPathSpec.charAt(0) == '/')
- {
- // Prefix Based
- if (len == 1)
- {
- return; // simple '/' path spec
- }
- int idx = servletPathSpec.indexOf('*');
- if (idx < 0)
- {
- return; // no hit on glob '*'
- }
- // only allowed to have '*' at the end of the path spec
- if (idx != (len - 1))
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: glob '*' can only exist at end of prefix based matches: bad spec \""+ servletPathSpec +"\"");
- }
- }
- else if (servletPathSpec.startsWith("*."))
- {
- // Suffix Based
- int idx = servletPathSpec.indexOf('/');
- // cannot have path separator
- if (idx >= 0)
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: suffix based path spec cannot have path separators: bad spec \""+ servletPathSpec +"\"");
- }
-
- idx = servletPathSpec.indexOf('*',2);
- // only allowed to have 1 glob '*', at the start of the path spec
- if (idx >= 1)
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: suffix based path spec cannot have multiple glob '*': bad spec \""+ servletPathSpec +"\"");
- }
- }
- else
- {
- throw new IllegalArgumentException("Servlet Spec 12.2 violation: path spec must start with \"/\" or \"*.\": bad spec \""+ servletPathSpec +"\"");
- }
- }
-
- @Override
- public String getPathInfo(String path)
- {
- // Path Info only valid for PREFIX_GLOB types
- if (group == PathSpecGroup.PREFIX_GLOB)
- {
- if (path.length() == (specLength - 2))
- {
- return null;
- }
- return path.substring(specLength - 2);
- }
-
- return null;
- }
-
- @Override
- public String getPathMatch(String path)
- {
- switch (group)
- {
- case EXACT:
- if (pathSpec.equals(path))
- {
- return path;
- }
- else
- {
- return null;
- }
- case PREFIX_GLOB:
- if (isWildcardMatch(path))
- {
- return path.substring(0,specLength - 2);
- }
- else
- {
- return null;
- }
- case SUFFIX_GLOB:
- if (path.regionMatches(path.length() - (specLength - 1),pathSpec,1,specLength - 1))
- {
- return path;
- }
- else
- {
- return null;
- }
- case DEFAULT:
- return path;
- default:
- return null;
- }
- }
-
- @Override
- public String getRelativePath(String base, String path)
- {
- String info = getPathInfo(path);
- if (info == null)
- {
- info = path;
- }
-
- if (info.startsWith("./"))
- {
- info = info.substring(2);
- }
- if (base.endsWith(URIUtil.SLASH))
- {
- if (info.startsWith(URIUtil.SLASH))
- {
- path = base + info.substring(1);
- }
- else
- {
- path = base + info;
- }
- }
- else if (info.startsWith(URIUtil.SLASH))
- {
- path = base + info;
- }
- else
- {
- path = base + URIUtil.SLASH + info;
- }
- return path;
- }
-
- private boolean isWildcardMatch(String path)
- {
- // For a spec of "/foo/*" match "/foo" , "/foo/..." but not "/foobar"
- int cpl = specLength - 2;
- if ((group == PathSpecGroup.PREFIX_GLOB) && (path.regionMatches(0,pathSpec,0,cpl)))
- {
- if ((path.length() == cpl) || ('/' == path.charAt(cpl)))
- {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean matches(String path)
- {
- switch (group)
- {
- case EXACT:
- return pathSpec.equals(path);
- case PREFIX_GLOB:
- return isWildcardMatch(path);
- case SUFFIX_GLOB:
- return path.regionMatches((path.length() - specLength) + 1,pathSpec,1,specLength - 1);
- case ROOT:
- // Only "/" matches
- return ("/".equals(path));
- case DEFAULT:
- // If we reached this point, then everything matches
- return true;
- default:
- return false;
- }
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/UriTemplatePathSpec.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/UriTemplatePathSpec.java
deleted file mode 100644
index 208820b6e3..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http/pathmap/UriTemplatePathSpec.java
+++ /dev/null
@@ -1,341 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.pathmap;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.eclipse.jetty.util.TypeUtil;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-/**
- * PathSpec for URI Template based declarations
- *
- * @see URI Templates (Level 1)
- */
-public class UriTemplatePathSpec extends RegexPathSpec
-{
- private static final Logger LOG = Log.getLogger(UriTemplatePathSpec.class);
-
- private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{(.*)\\}");
- /** Reserved Symbols in URI Template variable */
- private static final String VARIABLE_RESERVED = ":/?#[]@" + // gen-delims
- "!$&'()*+,;="; // sub-delims
- /** Allowed Symbols in a URI Template variable */
- private static final String VARIABLE_SYMBOLS="-._";
- private static final Set FORBIDDEN_SEGMENTS;
-
- static
- {
- FORBIDDEN_SEGMENTS = new HashSet<>();
- FORBIDDEN_SEGMENTS.add("/./");
- FORBIDDEN_SEGMENTS.add("/../");
- FORBIDDEN_SEGMENTS.add("//");
- }
-
- private String variables[];
-
- public UriTemplatePathSpec(String rawSpec)
- {
- super();
- Objects.requireNonNull(rawSpec,"Path Param Spec cannot be null");
-
- if ("".equals(rawSpec) || "/".equals(rawSpec))
- {
- super.pathSpec = "/";
- super.pattern = Pattern.compile("^/$");
- super.pathDepth = 1;
- this.specLength = 1;
- this.variables = new String[0];
- this.group = PathSpecGroup.EXACT;
- return;
- }
-
- if (rawSpec.charAt(0) != '/')
- {
- // path specs must start with '/'
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: path spec \"");
- err.append(rawSpec);
- err.append("\" must start with '/'");
- throw new IllegalArgumentException(err.toString());
- }
-
- for (String forbidden : FORBIDDEN_SEGMENTS)
- {
- if (rawSpec.contains(forbidden))
- {
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: segment ");
- err.append(forbidden);
- err.append(" is forbidden in path spec: ");
- err.append(rawSpec);
- throw new IllegalArgumentException(err.toString());
- }
- }
-
- this.pathSpec = rawSpec;
-
- StringBuilder regex = new StringBuilder();
- regex.append('^');
-
- List varNames = new ArrayList<>();
- // split up into path segments (ignoring the first slash that will always be empty)
- String segments[] = rawSpec.substring(1).split("/");
- char segmentSignature[] = new char[segments.length];
- this.pathDepth = segments.length;
- for (int i = 0; i < segments.length; i++)
- {
- String segment = segments[i];
- Matcher mat = VARIABLE_PATTERN.matcher(segment);
-
- if (mat.matches())
- {
- // entire path segment is a variable.
- String variable = mat.group(1);
- if (varNames.contains(variable))
- {
- // duplicate variable names
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: variable ");
- err.append(variable);
- err.append(" is duplicated in path spec: ");
- err.append(rawSpec);
- throw new IllegalArgumentException(err.toString());
- }
-
- assertIsValidVariableLiteral(variable);
-
- segmentSignature[i] = 'v'; // variable
- // valid variable name
- varNames.add(variable);
- // build regex
- regex.append("/([^/]+)");
- }
- else if (mat.find(0))
- {
- // variable exists as partial segment
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: variable ");
- err.append(mat.group());
- err.append(" must exist as entire path segment: ");
- err.append(rawSpec);
- throw new IllegalArgumentException(err.toString());
- }
- else if ((segment.indexOf('{') >= 0) || (segment.indexOf('}') >= 0))
- {
- // variable is split with a path separator
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: invalid path segment /");
- err.append(segment);
- err.append("/ variable declaration incomplete: ");
- err.append(rawSpec);
- throw new IllegalArgumentException(err.toString());
- }
- else if (segment.indexOf('*') >= 0)
- {
- // glob segment
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: path segment /");
- err.append(segment);
- err.append("/ contains a wildcard symbol (not supported by this uri-template implementation): ");
- err.append(rawSpec);
- throw new IllegalArgumentException(err.toString());
- }
- else
- {
- // valid path segment
- segmentSignature[i] = 'e'; // exact
- // build regex
- regex.append('/');
- // escape regex special characters
- for (char c : segment.toCharArray())
- {
- if ((c == '.') || (c == '[') || (c == ']') || (c == '\\'))
- {
- regex.append('\\');
- }
- regex.append(c);
- }
- }
- }
-
- // Handle trailing slash (which is not picked up during split)
- if(rawSpec.charAt(rawSpec.length()-1) == '/')
- {
- regex.append('/');
- }
-
- regex.append('$');
-
- this.pattern = Pattern.compile(regex.toString());
-
- int varcount = varNames.size();
- this.variables = varNames.toArray(new String[varcount]);
-
- // Convert signature to group
- String sig = String.valueOf(segmentSignature);
-
- if (Pattern.matches("^e*$",sig))
- {
- this.group = PathSpecGroup.EXACT;
- }
- else if (Pattern.matches("^e*v+",sig))
- {
- this.group = PathSpecGroup.PREFIX_GLOB;
- }
- else if (Pattern.matches("^v+e+",sig))
- {
- this.group = PathSpecGroup.SUFFIX_GLOB;
- }
- else
- {
- this.group = PathSpecGroup.MIDDLE_GLOB;
- }
- }
-
- /**
- * Validate variable literal name, per RFC6570, Section 2.1 Literals
- * @param variable
- * @param pathParamSpec
- */
- private void assertIsValidVariableLiteral(String variable)
- {
- int len = variable.length();
-
- int i = 0;
- int codepoint;
- boolean valid = (len > 0); // must not be zero length
-
- while (valid && i < len)
- {
- codepoint = variable.codePointAt(i);
- i += Character.charCount(codepoint);
-
- // basic letters, digits, or symbols
- if (isValidBasicLiteralCodepoint(codepoint))
- {
- continue;
- }
-
- // The ucschar and iprivate pieces
- if (Character.isSupplementaryCodePoint(codepoint))
- {
- continue;
- }
-
- // pct-encoded
- if (codepoint == '%')
- {
- if (i + 2 > len)
- {
- // invalid percent encoding, missing extra 2 chars
- valid = false;
- continue;
- }
- codepoint = TypeUtil.convertHexDigit(variable.codePointAt(i++)) << 4;
- codepoint |= TypeUtil.convertHexDigit(variable.codePointAt(i++));
-
- // validate basic literal
- if (isValidBasicLiteralCodepoint(codepoint))
- {
- continue;
- }
- }
-
- valid = false;
- }
-
- if (!valid)
- {
- // invalid variable name
- StringBuilder err = new StringBuilder();
- err.append("Syntax Error: variable {");
- err.append(variable);
- err.append("} an invalid variable name: ");
- err.append(pathSpec);
- throw new IllegalArgumentException(err.toString());
- }
- }
-
- private boolean isValidBasicLiteralCodepoint(int codepoint)
- {
- // basic letters or digits
- if((codepoint >= 'a' && codepoint <= 'z') ||
- (codepoint >= 'A' && codepoint <= 'Z') ||
- (codepoint >= '0' && codepoint <= '9'))
- {
- return true;
- }
-
- // basic allowed symbols
- if(VARIABLE_SYMBOLS.indexOf(codepoint) >= 0)
- {
- return true; // valid simple value
- }
-
- // basic reserved symbols
- if(VARIABLE_RESERVED.indexOf(codepoint) >= 0)
- {
- LOG.warn("Detected URI Template reserved symbol [{}] in path spec \"{}\"",(char)codepoint,pathSpec);
- return false; // valid simple value
- }
-
- return false;
- }
-
- public Map getPathParams(String path)
- {
- Matcher matcher = getMatcher(path);
- if (matcher.matches())
- {
- if (group == PathSpecGroup.EXACT)
- {
- return Collections.emptyMap();
- }
- Map ret = new HashMap<>();
- int groupCount = matcher.groupCount();
- for (int i = 1; i <= groupCount; i++)
- {
- ret.put(this.variables[i - 1],matcher.group(i));
- }
- return ret;
- }
- return null;
- }
-
- public int getVariableCount()
- {
- return variables.length;
- }
-
- public String[] getVariables()
- {
- return this.variables;
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/AuthorityHttpField.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/AuthorityHttpField.java
deleted file mode 100644
index 155b3f7520..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/AuthorityHttpField.java
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.http2.hpack;
-
-import org.eclipse.jetty.http.HostPortHttpField;
-import org.eclipse.jetty.http.HttpHeader;
-
-
-/* ------------------------------------------------------------ */
-/**
- */
-public class AuthorityHttpField extends HostPortHttpField
-{
- public final static String AUTHORITY = HpackContext.STATIC_TABLE[1][0];
-
- public AuthorityHttpField(String authority)
- {
- super(HttpHeader.C_AUTHORITY,AUTHORITY,authority);
- }
-
- @Override
- public String toString()
- {
- return String.format("%s(preparsed h=%s p=%d)",super.toString(),getHost(),getPort());
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackContext.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackContext.java
deleted file mode 100644
index 89fbf00e4a..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackContext.java
+++ /dev/null
@@ -1,515 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.http2.hpack;
-
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.jetty.http.HttpField;
-import org.eclipse.jetty.http.HttpHeader;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.http.HttpScheme;
-import org.eclipse.jetty.util.ArrayQueue;
-import org.eclipse.jetty.util.ArrayTernaryTrie;
-import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.util.Trie;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-
-/* ------------------------------------------------------------ */
-/** HPACK - Header Compression for HTTP/2
- * This class maintains the compression context for a single HTTP/2
- * connection. Specifically it holds the static and dynamic Header Field Tables
- * and the associated sizes and limits.
- *
- * It is compliant with draft 11 of the specification
- */
-public class HpackContext
-{
- public static final Logger LOG = Log.getLogger(HpackContext.class);
-
- public static final String[][] STATIC_TABLE =
- {
- {null,null},
- /* 1 */ {":authority",null},
- /* 2 */ {":method","GET"},
- /* 3 */ {":method","POST"},
- /* 4 */ {":path","/"},
- /* 5 */ {":path","/index.html"},
- /* 6 */ {":scheme","http"},
- /* 7 */ {":scheme","https"},
- /* 8 */ {":status","200"},
- /* 9 */ {":status","204"},
- /* 10 */ {":status","206"},
- /* 11 */ {":status","304"},
- /* 12 */ {":status","400"},
- /* 13 */ {":status","404"},
- /* 14 */ {":status","500"},
- /* 15 */ {"accept-charset",null},
- /* 16 */ {"accept-encoding","gzip, deflate"},
- /* 17 */ {"accept-language",null},
- /* 18 */ {"accept-ranges",null},
- /* 19 */ {"accept",null},
- /* 20 */ {"access-control-allow-origin",null},
- /* 21 */ {"age",null},
- /* 22 */ {"allow",null},
- /* 23 */ {"authorization",null},
- /* 24 */ {"cache-control",null},
- /* 25 */ {"content-disposition",null},
- /* 26 */ {"content-encoding",null},
- /* 27 */ {"content-language",null},
- /* 28 */ {"content-length",null},
- /* 29 */ {"content-location",null},
- /* 30 */ {"content-range",null},
- /* 31 */ {"content-type",null},
- /* 32 */ {"cookie",null},
- /* 33 */ {"date",null},
- /* 34 */ {"etag",null},
- /* 35 */ {"expect",null},
- /* 36 */ {"expires",null},
- /* 37 */ {"from",null},
- /* 38 */ {"host",null},
- /* 39 */ {"if-match",null},
- /* 40 */ {"if-modified-since",null},
- /* 41 */ {"if-none-match",null},
- /* 42 */ {"if-range",null},
- /* 43 */ {"if-unmodified-since",null},
- /* 44 */ {"last-modified",null},
- /* 45 */ {"link",null},
- /* 46 */ {"location",null},
- /* 47 */ {"max-forwards",null},
- /* 48 */ {"proxy-authenticate",null},
- /* 49 */ {"proxy-authorization",null},
- /* 50 */ {"range",null},
- /* 51 */ {"referer",null},
- /* 52 */ {"refresh",null},
- /* 53 */ {"retry-after",null},
- /* 54 */ {"server",null},
- /* 55 */ {"set-cookie",null},
- /* 56 */ {"strict-transport-security",null},
- /* 57 */ {"transfer-encoding",null},
- /* 58 */ {"user-agent",null},
- /* 59 */ {"vary",null},
- /* 60 */ {"via",null},
- /* 61 */ {"www-authenticate",null},
- };
-
- private static final Map __staticFieldMap = new HashMap<>();
- private static final Trie __staticNameMap = new ArrayTernaryTrie<>(true,512);
- private static final StaticEntry[] __staticTableByHeader = new StaticEntry[HttpHeader.UNKNOWN.ordinal()];
- private static final StaticEntry[] __staticTable=new StaticEntry[STATIC_TABLE.length];
- static
- {
- Set added = new HashSet<>();
- for (int i=1;i _fieldMap = new HashMap<>();
- private final Map _nameMap = new HashMap<>();
-
- HpackContext(int maxDynamicTableSize)
- {
- _maxDynamicTableSizeInBytes=maxDynamicTableSize;
- int guesstimateEntries = 10+maxDynamicTableSize/(32+10+10);
- _dynamicTable=new DynamicTable(guesstimateEntries,guesstimateEntries+10);
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("HdrTbl[%x] created max=%d",hashCode(),maxDynamicTableSize));
- }
-
- public void resize(int newMaxDynamicTableSize)
- {
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("HdrTbl[%x] resized max=%d->%d",hashCode(),_maxDynamicTableSizeInBytes,newMaxDynamicTableSize));
- _maxDynamicTableSizeInBytes=newMaxDynamicTableSize;
- int guesstimateEntries = 10+newMaxDynamicTableSize/(32+10+10);
- evict();
- _dynamicTable.resizeUnsafe(guesstimateEntries);
- }
-
- public Entry get(HttpField field)
- {
- Entry entry = _fieldMap.get(field);
- if (entry==null)
- entry=__staticFieldMap.get(field);
- return entry;
- }
-
- public Entry get(String name)
- {
- Entry entry = __staticNameMap.get(name);
- if (entry!=null)
- return entry;
- return _nameMap.get(StringUtil.asciiToLowerCase(name));
- }
-
- public Entry get(int index)
- {
- if (index<__staticTable.length)
- return __staticTable[index];
-
- int d=_dynamicTable.size()-index+__staticTable.length-1;
-
- if (d>=0)
- return _dynamicTable.getUnsafe(d);
- return null;
- }
-
- public Entry get(HttpHeader header)
- {
- Entry e = __staticTableByHeader[header.ordinal()];
- if (e==null)
- return get(header.asString());
- return e;
- }
-
- public static Entry getStatic(HttpHeader header)
- {
- return __staticTableByHeader[header.ordinal()];
- }
-
- public Entry add(HttpField field)
- {
- int slot=_dynamicTable.getNextSlotUnsafe();
- Entry entry=new Entry(slot,field);
- int size = entry.getSize();
- if (size>_maxDynamicTableSizeInBytes)
- {
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("HdrTbl[%x] !added size %d>%d",hashCode(),size,_maxDynamicTableSizeInBytes));
- return null;
- }
- _dynamicTableSizeInBytes+=size;
- _dynamicTable.addUnsafe(entry);
- _fieldMap.put(field,entry);
- _nameMap.put(StringUtil.asciiToLowerCase(field.getName()),entry);
-
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("HdrTbl[%x] added %s",hashCode(),entry));
- evict();
- return entry;
- }
-
- /**
- * @return Current dynamic table size in entries
- */
- public int size()
- {
- return _dynamicTable.size();
- }
-
- /**
- * @return Current Dynamic table size in Octets
- */
- public int getDynamicTableSize()
- {
- return _dynamicTableSizeInBytes;
- }
-
- /**
- * @return Max Dynamic table size in Octets
- */
- public int getMaxDynamicTableSize()
- {
- return _maxDynamicTableSizeInBytes;
- }
-
- public int index(Entry entry)
- {
- if (entry._slot<0)
- return 0;
- if (entry.isStatic())
- return entry._slot;
-
- return _dynamicTable.index(entry)+__staticTable.length-1;
- }
-
- public static int staticIndex(HttpHeader header)
- {
- if (header==null)
- return 0;
- Entry entry=__staticNameMap.get(header.asString());
- if (entry==null)
- return 0;
- return entry.getSlot();
- }
-
- private void evict()
- {
- while (_dynamicTableSizeInBytes>_maxDynamicTableSizeInBytes)
- {
- Entry entry = _dynamicTable.pollUnsafe();
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("HdrTbl[%x] evict %s",hashCode(),entry));
- _dynamicTableSizeInBytes-=entry.getSize();
- entry._slot=-1;
- _fieldMap.remove(entry.getHttpField());
- String lc=StringUtil.asciiToLowerCase(entry.getHttpField().getName());
- if (entry==_nameMap.get(lc))
- _nameMap.remove(lc);
- }
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("HdrTbl[%x] entries=%d, size=%d, max=%d",hashCode(),_dynamicTable.size(),_dynamicTableSizeInBytes,_maxDynamicTableSizeInBytes));
- }
-
- @Override
- public String toString()
- {
- return String.format("HpackContext@%x{entries=%d,size=%d,max=%d}",hashCode(),_dynamicTable.size(),_dynamicTableSizeInBytes,_maxDynamicTableSizeInBytes);
- }
-
-
-
- /* ------------------------------------------------------------ */
- /**
- */
- private class DynamicTable extends ArrayQueue
- {
- /* ------------------------------------------------------------ */
- /**
- * @param initCapacity
- * @param growBy
- */
- private DynamicTable(int initCapacity, int growBy)
- {
- super(initCapacity,growBy);
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @see org.eclipse.jetty.util.ArrayQueue#growUnsafe()
- */
- @Override
- protected void resizeUnsafe(int newCapacity)
- {
- // Relay on super.growUnsafe to pack all entries 0 to _nextSlot
- super.resizeUnsafe(newCapacity);
- for (int s=0;s<_nextSlot;s++)
- ((Entry)_elements[s])._slot=s;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @see org.eclipse.jetty.util.ArrayQueue#enqueue(java.lang.Object)
- */
- @Override
- public boolean enqueue(Entry e)
- {
- return super.enqueue(e);
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @see org.eclipse.jetty.util.ArrayQueue#dequeue()
- */
- @Override
- public Entry dequeue()
- {
- return super.dequeue();
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @param entry
- * @return
- */
- private int index(Entry entry)
- {
- return entry._slot>=_nextE?_size-entry._slot+_nextE:_nextSlot-entry._slot;
- }
-
- }
-
-
-
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- public static class Entry
- {
- final HttpField _field;
- int _slot;
-
- Entry()
- {
- _slot=0;
- _field=null;
- }
-
- Entry(int index,String name, String value)
- {
- _slot=index;
- _field=new HttpField(name,value);
- }
-
- Entry(int slot, HttpField field)
- {
- _slot=slot;
- _field=field;
- }
-
- public int getSize()
- {
- return 32+_field.getName().length()+_field.getValue().length();
- }
-
- public HttpField getHttpField()
- {
- return _field;
- }
-
- public boolean isStatic()
- {
- return false;
- }
-
- public byte[] getStaticHuffmanValue()
- {
- return null;
- }
-
- public int getSlot()
- {
- return _slot;
- }
-
- public String toString()
- {
- return String.format("{%s,%d,%s,%x}",isStatic()?"S":"D",_slot,_field,hashCode());
- }
- }
-
- public static class StaticEntry extends Entry
- {
- private final byte[] _huffmanValue;
- private final byte _encodedField;
-
- StaticEntry(int index,HttpField field)
- {
- super(index,field);
- String value = field.getValue();
- if (value!=null && value.length()>0)
- {
- int huffmanLen = Huffman.octetsNeeded(value);
- int lenLen = NBitInteger.octectsNeeded(7,huffmanLen);
- _huffmanValue = new byte[1+lenLen+huffmanLen];
- ByteBuffer buffer = ByteBuffer.wrap(_huffmanValue);
-
- // Indicate Huffman
- buffer.put((byte)0x80);
- // Add huffman length
- NBitInteger.encode(buffer,7,huffmanLen);
- // Encode value
- Huffman.encode(buffer,value);
- }
- else
- _huffmanValue=null;
-
- _encodedField=(byte)(0x80|index);
- }
-
- @Override
- public boolean isStatic()
- {
- return true;
- }
-
- @Override
- public byte[] getStaticHuffmanValue()
- {
- return _huffmanValue;
- }
-
- public byte getEncodedField()
- {
- return _encodedField;
- }
- }
-
-
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackDecoder.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackDecoder.java
deleted file mode 100644
index 38dc8567f1..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackDecoder.java
+++ /dev/null
@@ -1,280 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.http2.hpack;
-
-import java.nio.ByteBuffer;
-
-import org.eclipse.jetty.http.BadMessageException;
-import org.eclipse.jetty.http.HttpField;
-import org.eclipse.jetty.http.HttpHeader;
-import org.eclipse.jetty.http.HttpStatus;
-import org.eclipse.jetty.http.MetaData;
-import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
-import org.eclipse.jetty.util.TypeUtil;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-
-/**
- * Hpack Decoder
- * This is not thread safe and may only be called by 1 thread at a time.
- */
-public class HpackDecoder
-{
- public static final Logger LOG = Log.getLogger(HpackDecoder.class);
- public final static HttpField.LongValueHttpField CONTENT_LENGTH_0 =
- new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,0L);
-
- private final HpackContext _context;
- private final MetaDataBuilder _builder;
- private int _localMaxDynamicTableSize;
-
- /**
- * @param localMaxDynamicTableSize The maximum allowed size of the local dynamic header field table.
- * @param maxHeaderSize The maximum allowed size of a headers block, expressed as total of all name and value characters.
- */
- public HpackDecoder(int localMaxDynamicTableSize, int maxHeaderSize)
- {
- _context=new HpackContext(localMaxDynamicTableSize);
- _localMaxDynamicTableSize=localMaxDynamicTableSize;
- _builder = new MetaDataBuilder(maxHeaderSize);
- }
-
- public HpackContext getHpackContext()
- {
- return _context;
- }
-
- public void setLocalMaxDynamicTableSize(int localMaxdynamciTableSize)
- {
- _localMaxDynamicTableSize=localMaxdynamciTableSize;
- }
-
- public MetaData decode(ByteBuffer buffer)
- {
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("CtxTbl[%x] decoding %d octets",_context.hashCode(),buffer.remaining()));
-
- // If the buffer is big, don't even think about decoding it
- if (buffer.remaining()>_builder.getMaxSize())
- throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header frame size "+buffer.remaining()+">"+_builder.getMaxSize());
-
-
- while(buffer.hasRemaining())
- {
- if (LOG.isDebugEnabled())
- {
- int l=Math.min(buffer.remaining(),16);
- // TODO: not guaranteed the buffer has a backing array !
- LOG.debug("decode {}{}",
- TypeUtil.toHexString(buffer.array(),buffer.arrayOffset()+buffer.position(),l),
- l>4);
- String name;
- HttpHeader header;
- String value;
-
- boolean indexed;
- int name_index;
-
- switch (f)
- {
- case 2: // 7.3
- case 3: // 7.3
- // change table size
- int size = NBitInteger.decode(buffer,5);
- if (LOG.isDebugEnabled())
- LOG.debug("decode resize="+size);
- if (size>_localMaxDynamicTableSize)
- throw new IllegalArgumentException();
- _context.resize(size);
- continue;
-
- case 0: // 7.2.2
- case 1: // 7.2.3
- indexed=false;
- name_index=NBitInteger.decode(buffer,4);
- break;
-
-
- case 4: // 7.2.1
- case 5: // 7.2.1
- case 6: // 7.2.1
- case 7: // 7.2.1
- indexed=true;
- name_index=NBitInteger.decode(buffer,6);
- break;
-
- default:
- throw new IllegalStateException();
- }
-
-
- boolean huffmanName=false;
-
- // decode the name
- if (name_index>0)
- {
- Entry name_entry=_context.get(name_index);
- name=name_entry.getHttpField().getName();
- header=name_entry.getHttpField().getHeader();
- }
- else
- {
- huffmanName = (buffer.get()&0x80)==0x80;
- int length = NBitInteger.decode(buffer,7);
- _builder.checkSize(length,huffmanName);
- if (huffmanName)
- name=Huffman.decode(buffer,length);
- else
- name=toASCIIString(buffer,length);
- for (int i=0;i='A'&&c<='Z')
- {
- throw new BadMessageException(400,"Uppercase header name");
- }
- }
- header=HttpHeader.CACHE.get(name);
- }
-
- // decode the value
- boolean huffmanValue = (buffer.get()&0x80)==0x80;
- int length = NBitInteger.decode(buffer,7);
- _builder.checkSize(length,huffmanValue);
- if (huffmanValue)
- value=Huffman.decode(buffer,length);
- else
- value=toASCIIString(buffer,length);
-
- // Make the new field
- HttpField field;
- if (header==null)
- {
- // just make a normal field and bypass header name lookup
- field = new HttpField(null,name,value);
- }
- else
- {
- // might be worthwhile to create a value HttpField if it is indexed
- // and/or of a type that may be looked up multiple times.
- switch(header)
- {
- case C_STATUS:
- if (indexed)
- field = new HttpField.IntValueHttpField(header,name,value);
- else
- field = new HttpField(header,name,value);
- break;
-
- case C_AUTHORITY:
- field = new AuthorityHttpField(value);
- break;
-
- case CONTENT_LENGTH:
- if ("0".equals(value))
- field = CONTENT_LENGTH_0;
- else
- field = new HttpField.LongValueHttpField(header,name,value);
- break;
-
- default:
- field = new HttpField(header,name,value);
- break;
- }
- }
-
- if (LOG.isDebugEnabled())
- {
- LOG.debug("decoded '{}' by {}/{}/{}",
- field,
- name_index > 0 ? "IdxName" : (huffmanName ? "HuffName" : "LitName"),
- huffmanValue ? "HuffVal" : "LitVal",
- indexed ? "Idx" : "");
- }
-
- // emit the field
- _builder.emit(field);
-
- // if indexed
- if (indexed)
- {
- // add to dynamic table
- _context.add(field);
- }
-
- }
- }
-
- return _builder.build();
- }
-
- public static String toASCIIString(ByteBuffer buffer,int length)
- {
- StringBuilder builder = new StringBuilder(length);
- int position=buffer.position();
- int start=buffer.arrayOffset()+ position;
- int end=start+length;
- buffer.position(position+length);
- byte[] array=buffer.array();
- for (int i=start;i __DO_NOT_HUFFMAN =
- EnumSet.of(
- HttpHeader.AUTHORIZATION,
- HttpHeader.CONTENT_MD5,
- HttpHeader.PROXY_AUTHENTICATE,
- HttpHeader.PROXY_AUTHORIZATION);
-
- final static EnumSet __DO_NOT_INDEX =
- EnumSet.of(
- // HttpHeader.C_PATH, // TODO more data needed
- // HttpHeader.DATE, // TODO more data needed
- HttpHeader.AUTHORIZATION,
- HttpHeader.CONTENT_MD5,
- HttpHeader.CONTENT_RANGE,
- HttpHeader.ETAG,
- HttpHeader.IF_MODIFIED_SINCE,
- HttpHeader.IF_UNMODIFIED_SINCE,
- HttpHeader.IF_NONE_MATCH,
- HttpHeader.IF_RANGE,
- HttpHeader.IF_MATCH,
- HttpHeader.LOCATION,
- HttpHeader.RANGE,
- HttpHeader.RETRY_AFTER,
- // HttpHeader.EXPIRES,
- HttpHeader.LAST_MODIFIED,
- HttpHeader.SET_COOKIE,
- HttpHeader.SET_COOKIE2);
-
-
- final static EnumSet __NEVER_INDEX =
- EnumSet.of(
- HttpHeader.AUTHORIZATION,
- HttpHeader.SET_COOKIE,
- HttpHeader.SET_COOKIE2);
-
- static
- {
- for (HttpStatus.Code code : HttpStatus.Code.values())
- __status[code.getCode()]=new PreEncodedHttpField(HttpHeader.C_STATUS,Integer.toString(code.getCode()));
- }
-
- private final HpackContext _context;
- private final boolean _debug;
- private int _remoteMaxDynamicTableSize;
- private int _localMaxDynamicTableSize;
-
- public HpackEncoder()
- {
- this(4096,4096);
- }
-
- public HpackEncoder(int localMaxDynamicTableSize)
- {
- this(localMaxDynamicTableSize,4096);
- }
-
- public HpackEncoder(int localMaxDynamicTableSize,int remoteMaxDynamicTableSize)
- {
- _context=new HpackContext(remoteMaxDynamicTableSize);
- _remoteMaxDynamicTableSize=remoteMaxDynamicTableSize;
- _localMaxDynamicTableSize=localMaxDynamicTableSize;
- _debug=LOG.isDebugEnabled();
- }
-
- public HpackContext getHpackContext()
- {
- return _context;
- }
-
- public void setRemoteMaxDynamicTableSize(int remoteMaxDynamicTableSize)
- {
- _remoteMaxDynamicTableSize=remoteMaxDynamicTableSize;
- }
-
- public void setLocalMaxDynamicTableSize(int localMaxDynamicTableSize)
- {
- _localMaxDynamicTableSize=localMaxDynamicTableSize;
- }
-
- public void encode(ByteBuffer buffer, MetaData metadata)
- {
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("CtxTbl[%x] encoding",_context.hashCode()));
-
- int pos = buffer.position();
-
- // Check the dynamic table sizes!
- int maxDynamicTableSize=Math.min(_remoteMaxDynamicTableSize,_localMaxDynamicTableSize);
- if (maxDynamicTableSize!=_context.getMaxDynamicTableSize())
- encodeMaxDynamicTableSize(buffer,maxDynamicTableSize);
-
- // Add Request/response meta fields
- if (metadata.isRequest())
- {
- MetaData.Request request = (MetaData.Request)metadata;
-
- // TODO optimise these to avoid HttpField creation
- String scheme=request.getURI().getScheme();
- encode(buffer,new HttpField(HttpHeader.C_SCHEME,scheme==null?HttpScheme.HTTP.asString():scheme));
- encode(buffer,new HttpField(HttpHeader.C_METHOD,request.getMethod()));
- encode(buffer,new HttpField(HttpHeader.C_AUTHORITY,request.getURI().getAuthority()));
- encode(buffer,new HttpField(HttpHeader.C_PATH,request.getURI().getPathQuery()));
-
- }
- else if (metadata.isResponse())
- {
- MetaData.Response response = (MetaData.Response)metadata;
- int code=response.getStatus();
- HttpField status = code<__status.length?__status[code]:null;
- if (status==null)
- status=new HttpField.IntValueHttpField(HttpHeader.C_STATUS,code);
- encode(buffer,status);
- }
-
- // Add all the other fields
- for (HttpField field : metadata)
- encode(buffer,field);
-
- if (LOG.isDebugEnabled())
- LOG.debug(String.format("CtxTbl[%x] encoded %d octets",_context.hashCode(), buffer.position() - pos));
- }
-
- public void encodeMaxDynamicTableSize(ByteBuffer buffer, int maxDynamicTableSize)
- {
- if (maxDynamicTableSize>_remoteMaxDynamicTableSize)
- throw new IllegalArgumentException();
- buffer.put((byte)0x20);
- NBitInteger.encode(buffer,5,maxDynamicTableSize);
- _context.resize(maxDynamicTableSize);
- }
-
- public void encode(ByteBuffer buffer, HttpField field)
- {
- final int p=_debug?buffer.position():-1;
-
- String encoding=null;
-
- // Is there an entry for the field?
- Entry entry = _context.get(field);
- if (entry!=null)
- {
- // Known field entry, so encode it as indexed
- if (entry.isStatic())
- {
- buffer.put(((StaticEntry)entry).getEncodedField());
- if (_debug)
- encoding="IdxFieldS1";
- }
- else
- {
- int index=_context.index(entry);
- buffer.put((byte)0x80);
- NBitInteger.encode(buffer,7,index);
- if (_debug)
- encoding="IdxField"+(entry.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(7,index));
- }
- }
- else
- {
- // Unknown field entry, so we will have to send literally.
- final boolean indexed;
-
- // But do we know it's name?
- HttpHeader header = field.getHeader();
-
- // Select encoding strategy
- if (header==null)
- {
- // Select encoding strategy for unknown header names
- Entry name = _context.get(field.getName());
-
- if (field instanceof PreEncodedHttpField)
- {
- int i=buffer.position();
- ((PreEncodedHttpField)field).putTo(buffer,HttpVersion.HTTP_2);
- byte b=buffer.get(i);
- indexed=b<0||b>=0x40;
- if (_debug)
- encoding=indexed?"PreEncodedIdx":"PreEncoded";
- }
- // has the custom header name been seen before?
- else if (name==null)
- {
- // unknown name and value, so let's index this just in case it is
- // the first time we have seen a custom name or a custom field.
- // unless the name is changing, this is worthwhile
- indexed=true;
- encodeName(buffer,(byte)0x40,6,field.getName(),null);
- encodeValue(buffer,true,field.getValue());
- if (_debug)
- encoding="LitHuffNHuffVIdx";
- }
- else
- {
- // known custom name, but unknown value.
- // This is probably a custom field with changing value, so don't index.
- indexed=false;
- encodeName(buffer,(byte)0x00,4,field.getName(),null);
- encodeValue(buffer,true,field.getValue());
- if (_debug)
- encoding="LitHuffNHuffV!Idx";
- }
- }
- else
- {
- // Select encoding strategy for known header names
- Entry name = _context.get(header);
-
- if (field instanceof PreEncodedHttpField)
- {
- // Preencoded field
- int i=buffer.position();
- ((PreEncodedHttpField)field).putTo(buffer,HttpVersion.HTTP_2);
- byte b=buffer.get(i);
- indexed=b<0||b>=0x40;
- if (_debug)
- encoding=indexed?"PreEncodedIdx":"PreEncoded";
- }
- else if (__DO_NOT_INDEX.contains(header))
- {
- // Non indexed field
- indexed=false;
- boolean never_index=__NEVER_INDEX.contains(header);
- boolean huffman=!__DO_NOT_HUFFMAN.contains(header);
- encodeName(buffer,never_index?(byte)0x10:(byte)0x00,4,header.asString(),name);
- encodeValue(buffer,huffman,field.getValue());
-
- if (_debug)
- encoding="Lit"+
- ((name==null)?"HuffN":("IdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(4,_context.index(name)))))+
- (huffman?"HuffV":"LitV")+
- (indexed?"Idx":(never_index?"!!Idx":"!Idx"));
- }
- else if (header==HttpHeader.CONTENT_LENGTH && field.getValue().length()>1)
- {
- // Non indexed content length for 2 digits or more
- indexed=false;
- encodeName(buffer,(byte)0x00,4,header.asString(),name);
- encodeValue(buffer,true,field.getValue());
- if (_debug)
- encoding="LitIdxNS"+(1+NBitInteger.octectsNeeded(4,_context.index(name)))+"HuffV!Idx";
- }
- else
- {
- // indexed
- indexed=true;
- boolean huffman=!__DO_NOT_HUFFMAN.contains(header);
- encodeName(buffer,(byte)0x40,6,header.asString(),name);
- encodeValue(buffer,huffman,field.getValue());
- if (_debug)
- encoding=((name==null)?"LitHuffN":("LitIdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(6,_context.index(name)))))+
- (huffman?"HuffVIdx":"LitVIdx");
- }
- }
-
- // If we want the field referenced, then we add it to our
- // table and reference set.
- if (indexed)
- _context.add(field);
- }
-
- if (_debug)
- {
- int e=buffer.position();
- if (LOG.isDebugEnabled())
- LOG.debug("encode {}:'{}' to '{}'",encoding,field,TypeUtil.toHexString(buffer.array(),buffer.arrayOffset()+p,e-p));
- }
- }
-
- private void encodeName(ByteBuffer buffer, byte mask, int bits, String name, Entry entry)
- {
- buffer.put(mask);
- if (entry==null)
- {
- // leave name index bits as 0
- // Encode the name always with lowercase huffman
- buffer.put((byte)0x80);
- NBitInteger.encode(buffer,7,Huffman.octetsNeededLC(name));
- Huffman.encodeLC(buffer,name);
- }
- else
- {
- NBitInteger.encode(buffer,bits,_context.index(entry));
- }
- }
-
- static void encodeValue(ByteBuffer buffer, boolean huffman, String value)
- {
- if (huffman)
- {
- // huffman literal value
- buffer.put((byte)0x80);
- NBitInteger.encode(buffer,7,Huffman.octetsNeeded(value));
- Huffman.encode(buffer,value);
- }
- else
- {
- // add literal assuming iso_8859_1
- buffer.put((byte)0x00);
- NBitInteger.encode(buffer,7,value.length());
- for (int i=0;i127)
- throw new IllegalArgumentException();
- buffer.put((byte)c);
- }
- }
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java
deleted file mode 100644
index f73b34728e..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/HpackFieldPreEncoder.java
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.http2.hpack;
-
-import java.nio.ByteBuffer;
-
-import org.eclipse.jetty.http.HttpFieldPreEncoder;
-import org.eclipse.jetty.http.HttpHeader;
-import org.eclipse.jetty.http.HttpVersion;
-import org.eclipse.jetty.util.BufferUtil;
-
-
-/* ------------------------------------------------------------ */
-/**
- */
-public class HpackFieldPreEncoder implements HttpFieldPreEncoder
-{
- /* ------------------------------------------------------------ */
- /**
- * @see org.eclipse.jetty.http.HttpFieldPreEncoder#getHttpVersion()
- */
- @Override
- public HttpVersion getHttpVersion()
- {
- return HttpVersion.HTTP_2;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * @see org.eclipse.jetty.http.HttpFieldPreEncoder#getEncodedField(org.eclipse.jetty.http.HttpHeader, java.lang.String, java.lang.String)
- */
- @Override
- public byte[] getEncodedField(HttpHeader header, String name, String value)
- {
- boolean not_indexed=HpackEncoder.__DO_NOT_INDEX.contains(header);
-
- ByteBuffer buffer = BufferUtil.allocate(name.length()+value.length()+10);
- BufferUtil.clearToFill(buffer);
- boolean huffman;
- int bits;
-
- if (not_indexed)
- {
- // Non indexed field
- boolean never_index=HpackEncoder.__NEVER_INDEX.contains(header);
- huffman=!HpackEncoder.__DO_NOT_HUFFMAN.contains(header);
- buffer.put(never_index?(byte)0x10:(byte)0x00);
- bits=4;
- }
- else if (header==HttpHeader.CONTENT_LENGTH && value.length()>1)
- {
- // Non indexed content length for 2 digits or more
- buffer.put((byte)0x00);
- huffman=true;
- bits=4;
- }
- else
- {
- // indexed
- buffer.put((byte)0x40);
- huffman=!HpackEncoder.__DO_NOT_HUFFMAN.contains(header);
- bits=6;
- }
-
- int name_idx=HpackContext.staticIndex(header);
- if (name_idx>0)
- NBitInteger.encode(buffer,bits,name_idx);
- else
- {
- buffer.put((byte)0x80);
- NBitInteger.encode(buffer,7,Huffman.octetsNeededLC(name));
- Huffman.encodeLC(buffer,name);
- }
-
- HpackEncoder.encodeValue(buffer,huffman,value);
-
- BufferUtil.flipToFlush(buffer,0);
- return BufferUtil.toArray(buffer);
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/Huffman.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/Huffman.java
deleted file mode 100644
index da28684c4a..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/Huffman.java
+++ /dev/null
@@ -1,480 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.http2.hpack;
-
-import java.nio.ByteBuffer;
-
-public class Huffman
-{
-
- // Appendix C: Huffman Codes
- // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#appendix-C
- static final int[][] CODES =
- {
- /* ( 0) |11111111|11000 */ {0x1ff8,13},
- /* ( 1) |11111111|11111111|1011000 */ {0x7fffd8,23},
- /* ( 2) |11111111|11111111|11111110|0010 */ {0xfffffe2,28},
- /* ( 3) |11111111|11111111|11111110|0011 */ {0xfffffe3,28},
- /* ( 4) |11111111|11111111|11111110|0100 */ {0xfffffe4,28},
- /* ( 5) |11111111|11111111|11111110|0101 */ {0xfffffe5,28},
- /* ( 6) |11111111|11111111|11111110|0110 */ {0xfffffe6,28},
- /* ( 7) |11111111|11111111|11111110|0111 */ {0xfffffe7,28},
- /* ( 8) |11111111|11111111|11111110|1000 */ {0xfffffe8,28},
- /* ( 9) |11111111|11111111|11101010 */ {0xffffea,24},
- /* ( 10) |11111111|11111111|11111111|111100 */ {0x3ffffffc,30},
- /* ( 11) |11111111|11111111|11111110|1001 */ {0xfffffe9,28},
- /* ( 12) |11111111|11111111|11111110|1010 */ {0xfffffea,28},
- /* ( 13) |11111111|11111111|11111111|111101 */ {0x3ffffffd,30},
- /* ( 14) |11111111|11111111|11111110|1011 */ {0xfffffeb,28},
- /* ( 15) |11111111|11111111|11111110|1100 */ {0xfffffec,28},
- /* ( 16) |11111111|11111111|11111110|1101 */ {0xfffffed,28},
- /* ( 17) |11111111|11111111|11111110|1110 */ {0xfffffee,28},
- /* ( 18) |11111111|11111111|11111110|1111 */ {0xfffffef,28},
- /* ( 19) |11111111|11111111|11111111|0000 */ {0xffffff0,28},
- /* ( 20) |11111111|11111111|11111111|0001 */ {0xffffff1,28},
- /* ( 21) |11111111|11111111|11111111|0010 */ {0xffffff2,28},
- /* ( 22) |11111111|11111111|11111111|111110 */ {0x3ffffffe,30},
- /* ( 23) |11111111|11111111|11111111|0011 */ {0xffffff3,28},
- /* ( 24) |11111111|11111111|11111111|0100 */ {0xffffff4,28},
- /* ( 25) |11111111|11111111|11111111|0101 */ {0xffffff5,28},
- /* ( 26) |11111111|11111111|11111111|0110 */ {0xffffff6,28},
- /* ( 27) |11111111|11111111|11111111|0111 */ {0xffffff7,28},
- /* ( 28) |11111111|11111111|11111111|1000 */ {0xffffff8,28},
- /* ( 29) |11111111|11111111|11111111|1001 */ {0xffffff9,28},
- /* ( 30) |11111111|11111111|11111111|1010 */ {0xffffffa,28},
- /* ( 31) |11111111|11111111|11111111|1011 */ {0xffffffb,28},
- /*' ' ( 32) |010100 */ {0x14, 6},
- /*'!' ( 33) |11111110|00 */ {0x3f8,10},
- /*'"' ( 34) |11111110|01 */ {0x3f9,10},
- /*'#' ( 35) |11111111|1010 */ {0xffa,12},
- /*'$' ( 36) |11111111|11001 */ {0x1ff9,13},
- /*'%' ( 37) |010101 */ {0x15, 6},
- /*'&' ( 38) |11111000 */ {0xf8, 8},
- /*''' ( 39) |11111111|010 */ {0x7fa,11},
- /*'(' ( 40) |11111110|10 */ {0x3fa,10},
- /*')' ( 41) |11111110|11 */ {0x3fb,10},
- /*'*' ( 42) |11111001 */ {0xf9, 8},
- /*'+' ( 43) |11111111|011 */ {0x7fb,11},
- /*',' ( 44) |11111010 */ {0xfa, 8},
- /*'-' ( 45) |010110 */ {0x16, 6},
- /*'.' ( 46) |010111 */ {0x17, 6},
- /*'/' ( 47) |011000 */ {0x18, 6},
- /*'0' ( 48) |00000 */ {0x0, 5},
- /*'1' ( 49) |00001 */ {0x1, 5},
- /*'2' ( 50) |00010 */ {0x2, 5},
- /*'3' ( 51) |011001 */ {0x19, 6},
- /*'4' ( 52) |011010 */ {0x1a, 6},
- /*'5' ( 53) |011011 */ {0x1b, 6},
- /*'6' ( 54) |011100 */ {0x1c, 6},
- /*'7' ( 55) |011101 */ {0x1d, 6},
- /*'8' ( 56) |011110 */ {0x1e, 6},
- /*'9' ( 57) |011111 */ {0x1f, 6},
- /*':' ( 58) |1011100 */ {0x5c, 7},
- /*';' ( 59) |11111011 */ {0xfb, 8},
- /*'<' ( 60) |11111111|1111100 */ {0x7ffc,15},
- /*'=' ( 61) |100000 */ {0x20, 6},
- /*'>' ( 62) |11111111|1011 */ {0xffb,12},
- /*'?' ( 63) |11111111|00 */ {0x3fc,10},
- /*'@' ( 64) |11111111|11010 */ {0x1ffa,13},
- /*'A' ( 65) |100001 */ {0x21, 6},
- /*'B' ( 66) |1011101 */ {0x5d, 7},
- /*'C' ( 67) |1011110 */ {0x5e, 7},
- /*'D' ( 68) |1011111 */ {0x5f, 7},
- /*'E' ( 69) |1100000 */ {0x60, 7},
- /*'F' ( 70) |1100001 */ {0x61, 7},
- /*'G' ( 71) |1100010 */ {0x62, 7},
- /*'H' ( 72) |1100011 */ {0x63, 7},
- /*'I' ( 73) |1100100 */ {0x64, 7},
- /*'J' ( 74) |1100101 */ {0x65, 7},
- /*'K' ( 75) |1100110 */ {0x66, 7},
- /*'L' ( 76) |1100111 */ {0x67, 7},
- /*'M' ( 77) |1101000 */ {0x68, 7},
- /*'N' ( 78) |1101001 */ {0x69, 7},
- /*'O' ( 79) |1101010 */ {0x6a, 7},
- /*'P' ( 80) |1101011 */ {0x6b, 7},
- /*'Q' ( 81) |1101100 */ {0x6c, 7},
- /*'R' ( 82) |1101101 */ {0x6d, 7},
- /*'S' ( 83) |1101110 */ {0x6e, 7},
- /*'T' ( 84) |1101111 */ {0x6f, 7},
- /*'U' ( 85) |1110000 */ {0x70, 7},
- /*'V' ( 86) |1110001 */ {0x71, 7},
- /*'W' ( 87) |1110010 */ {0x72, 7},
- /*'X' ( 88) |11111100 */ {0xfc, 8},
- /*'Y' ( 89) |1110011 */ {0x73, 7},
- /*'Z' ( 90) |11111101 */ {0xfd, 8},
- /*'[' ( 91) |11111111|11011 */ {0x1ffb,13},
- /*'\' ( 92) |11111111|11111110|000 */ {0x7fff0,19},
- /*']' ( 93) |11111111|11100 */ {0x1ffc,13},
- /*'^' ( 94) |11111111|111100 */ {0x3ffc,14},
- /*'_' ( 95) |100010 */ {0x22, 6},
- /*'`' ( 96) |11111111|1111101 */ {0x7ffd,15},
- /*'a' ( 97) |00011 */ {0x3, 5},
- /*'b' ( 98) |100011 */ {0x23, 6},
- /*'c' ( 99) |00100 */ {0x4, 5},
- /*'d' (100) |100100 */ {0x24, 6},
- /*'e' (101) |00101 */ {0x5, 5},
- /*'f' (102) |100101 */ {0x25, 6},
- /*'g' (103) |100110 */ {0x26, 6},
- /*'h' (104) |100111 */ {0x27, 6},
- /*'i' (105) |00110 */ {0x6, 5},
- /*'j' (106) |1110100 */ {0x74, 7},
- /*'k' (107) |1110101 */ {0x75, 7},
- /*'l' (108) |101000 */ {0x28, 6},
- /*'m' (109) |101001 */ {0x29, 6},
- /*'n' (110) |101010 */ {0x2a, 6},
- /*'o' (111) |00111 */ {0x7, 5},
- /*'p' (112) |101011 */ {0x2b, 6},
- /*'q' (113) |1110110 */ {0x76, 7},
- /*'r' (114) |101100 */ {0x2c, 6},
- /*'s' (115) |01000 */ {0x8, 5},
- /*'t' (116) |01001 */ {0x9, 5},
- /*'u' (117) |101101 */ {0x2d, 6},
- /*'v' (118) |1110111 */ {0x77, 7},
- /*'w' (119) |1111000 */ {0x78, 7},
- /*'x' (120) |1111001 */ {0x79, 7},
- /*'y' (121) |1111010 */ {0x7a, 7},
- /*'z' (122) |1111011 */ {0x7b, 7},
- /*'{' (123) |11111111|1111110 */ {0x7ffe,15},
- /*'|' (124) |11111111|100 */ {0x7fc,11},
- /*'}' (125) |11111111|111101 */ {0x3ffd,14},
- /*'~' (126) |11111111|11101 */ {0x1ffd,13},
- /* (127) |11111111|11111111|11111111|1100 */ {0xffffffc,28},
- /* (128) |11111111|11111110|0110 */ {0xfffe6,20},
- /* (129) |11111111|11111111|010010 */ {0x3fffd2,22},
- /* (130) |11111111|11111110|0111 */ {0xfffe7,20},
- /* (131) |11111111|11111110|1000 */ {0xfffe8,20},
- /* (132) |11111111|11111111|010011 */ {0x3fffd3,22},
- /* (133) |11111111|11111111|010100 */ {0x3fffd4,22},
- /* (134) |11111111|11111111|010101 */ {0x3fffd5,22},
- /* (135) |11111111|11111111|1011001 */ {0x7fffd9,23},
- /* (136) |11111111|11111111|010110 */ {0x3fffd6,22},
- /* (137) |11111111|11111111|1011010 */ {0x7fffda,23},
- /* (138) |11111111|11111111|1011011 */ {0x7fffdb,23},
- /* (139) |11111111|11111111|1011100 */ {0x7fffdc,23},
- /* (140) |11111111|11111111|1011101 */ {0x7fffdd,23},
- /* (141) |11111111|11111111|1011110 */ {0x7fffde,23},
- /* (142) |11111111|11111111|11101011 */ {0xffffeb,24},
- /* (143) |11111111|11111111|1011111 */ {0x7fffdf,23},
- /* (144) |11111111|11111111|11101100 */ {0xffffec,24},
- /* (145) |11111111|11111111|11101101 */ {0xffffed,24},
- /* (146) |11111111|11111111|010111 */ {0x3fffd7,22},
- /* (147) |11111111|11111111|1100000 */ {0x7fffe0,23},
- /* (148) |11111111|11111111|11101110 */ {0xffffee,24},
- /* (149) |11111111|11111111|1100001 */ {0x7fffe1,23},
- /* (150) |11111111|11111111|1100010 */ {0x7fffe2,23},
- /* (151) |11111111|11111111|1100011 */ {0x7fffe3,23},
- /* (152) |11111111|11111111|1100100 */ {0x7fffe4,23},
- /* (153) |11111111|11111110|11100 */ {0x1fffdc,21},
- /* (154) |11111111|11111111|011000 */ {0x3fffd8,22},
- /* (155) |11111111|11111111|1100101 */ {0x7fffe5,23},
- /* (156) |11111111|11111111|011001 */ {0x3fffd9,22},
- /* (157) |11111111|11111111|1100110 */ {0x7fffe6,23},
- /* (158) |11111111|11111111|1100111 */ {0x7fffe7,23},
- /* (159) |11111111|11111111|11101111 */ {0xffffef,24},
- /* (160) |11111111|11111111|011010 */ {0x3fffda,22},
- /* (161) |11111111|11111110|11101 */ {0x1fffdd,21},
- /* (162) |11111111|11111110|1001 */ {0xfffe9,20},
- /* (163) |11111111|11111111|011011 */ {0x3fffdb,22},
- /* (164) |11111111|11111111|011100 */ {0x3fffdc,22},
- /* (165) |11111111|11111111|1101000 */ {0x7fffe8,23},
- /* (166) |11111111|11111111|1101001 */ {0x7fffe9,23},
- /* (167) |11111111|11111110|11110 */ {0x1fffde,21},
- /* (168) |11111111|11111111|1101010 */ {0x7fffea,23},
- /* (169) |11111111|11111111|011101 */ {0x3fffdd,22},
- /* (170) |11111111|11111111|011110 */ {0x3fffde,22},
- /* (171) |11111111|11111111|11110000 */ {0xfffff0,24},
- /* (172) |11111111|11111110|11111 */ {0x1fffdf,21},
- /* (173) |11111111|11111111|011111 */ {0x3fffdf,22},
- /* (174) |11111111|11111111|1101011 */ {0x7fffeb,23},
- /* (175) |11111111|11111111|1101100 */ {0x7fffec,23},
- /* (176) |11111111|11111111|00000 */ {0x1fffe0,21},
- /* (177) |11111111|11111111|00001 */ {0x1fffe1,21},
- /* (178) |11111111|11111111|100000 */ {0x3fffe0,22},
- /* (179) |11111111|11111111|00010 */ {0x1fffe2,21},
- /* (180) |11111111|11111111|1101101 */ {0x7fffed,23},
- /* (181) |11111111|11111111|100001 */ {0x3fffe1,22},
- /* (182) |11111111|11111111|1101110 */ {0x7fffee,23},
- /* (183) |11111111|11111111|1101111 */ {0x7fffef,23},
- /* (184) |11111111|11111110|1010 */ {0xfffea,20},
- /* (185) |11111111|11111111|100010 */ {0x3fffe2,22},
- /* (186) |11111111|11111111|100011 */ {0x3fffe3,22},
- /* (187) |11111111|11111111|100100 */ {0x3fffe4,22},
- /* (188) |11111111|11111111|1110000 */ {0x7ffff0,23},
- /* (189) |11111111|11111111|100101 */ {0x3fffe5,22},
- /* (190) |11111111|11111111|100110 */ {0x3fffe6,22},
- /* (191) |11111111|11111111|1110001 */ {0x7ffff1,23},
- /* (192) |11111111|11111111|11111000|00 */ {0x3ffffe0,26},
- /* (193) |11111111|11111111|11111000|01 */ {0x3ffffe1,26},
- /* (194) |11111111|11111110|1011 */ {0xfffeb,20},
- /* (195) |11111111|11111110|001 */ {0x7fff1,19},
- /* (196) |11111111|11111111|100111 */ {0x3fffe7,22},
- /* (197) |11111111|11111111|1110010 */ {0x7ffff2,23},
- /* (198) |11111111|11111111|101000 */ {0x3fffe8,22},
- /* (199) |11111111|11111111|11110110|0 */ {0x1ffffec,25},
- /* (200) |11111111|11111111|11111000|10 */ {0x3ffffe2,26},
- /* (201) |11111111|11111111|11111000|11 */ {0x3ffffe3,26},
- /* (202) |11111111|11111111|11111001|00 */ {0x3ffffe4,26},
- /* (203) |11111111|11111111|11111011|110 */ {0x7ffffde,27},
- /* (204) |11111111|11111111|11111011|111 */ {0x7ffffdf,27},
- /* (205) |11111111|11111111|11111001|01 */ {0x3ffffe5,26},
- /* (206) |11111111|11111111|11110001 */ {0xfffff1,24},
- /* (207) |11111111|11111111|11110110|1 */ {0x1ffffed,25},
- /* (208) |11111111|11111110|010 */ {0x7fff2,19},
- /* (209) |11111111|11111111|00011 */ {0x1fffe3,21},
- /* (210) |11111111|11111111|11111001|10 */ {0x3ffffe6,26},
- /* (211) |11111111|11111111|11111100|000 */ {0x7ffffe0,27},
- /* (212) |11111111|11111111|11111100|001 */ {0x7ffffe1,27},
- /* (213) |11111111|11111111|11111001|11 */ {0x3ffffe7,26},
- /* (214) |11111111|11111111|11111100|010 */ {0x7ffffe2,27},
- /* (215) |11111111|11111111|11110010 */ {0xfffff2,24},
- /* (216) |11111111|11111111|00100 */ {0x1fffe4,21},
- /* (217) |11111111|11111111|00101 */ {0x1fffe5,21},
- /* (218) |11111111|11111111|11111010|00 */ {0x3ffffe8,26},
- /* (219) |11111111|11111111|11111010|01 */ {0x3ffffe9,26},
- /* (220) |11111111|11111111|11111111|1101 */ {0xffffffd,28},
- /* (221) |11111111|11111111|11111100|011 */ {0x7ffffe3,27},
- /* (222) |11111111|11111111|11111100|100 */ {0x7ffffe4,27},
- /* (223) |11111111|11111111|11111100|101 */ {0x7ffffe5,27},
- /* (224) |11111111|11111110|1100 */ {0xfffec,20},
- /* (225) |11111111|11111111|11110011 */ {0xfffff3,24},
- /* (226) |11111111|11111110|1101 */ {0xfffed,20},
- /* (227) |11111111|11111111|00110 */ {0x1fffe6,21},
- /* (228) |11111111|11111111|101001 */ {0x3fffe9,22},
- /* (229) |11111111|11111111|00111 */ {0x1fffe7,21},
- /* (230) |11111111|11111111|01000 */ {0x1fffe8,21},
- /* (231) |11111111|11111111|1110011 */ {0x7ffff3,23},
- /* (232) |11111111|11111111|101010 */ {0x3fffea,22},
- /* (233) |11111111|11111111|101011 */ {0x3fffeb,22},
- /* (234) |11111111|11111111|11110111|0 */ {0x1ffffee,25},
- /* (235) |11111111|11111111|11110111|1 */ {0x1ffffef,25},
- /* (236) |11111111|11111111|11110100 */ {0xfffff4,24},
- /* (237) |11111111|11111111|11110101 */ {0xfffff5,24},
- /* (238) |11111111|11111111|11111010|10 */ {0x3ffffea,26},
- /* (239) |11111111|11111111|1110100 */ {0x7ffff4,23},
- /* (240) |11111111|11111111|11111010|11 */ {0x3ffffeb,26},
- /* (241) |11111111|11111111|11111100|110 */ {0x7ffffe6,27},
- /* (242) |11111111|11111111|11111011|00 */ {0x3ffffec,26},
- /* (243) |11111111|11111111|11111011|01 */ {0x3ffffed,26},
- /* (244) |11111111|11111111|11111100|111 */ {0x7ffffe7,27},
- /* (245) |11111111|11111111|11111101|000 */ {0x7ffffe8,27},
- /* (246) |11111111|11111111|11111101|001 */ {0x7ffffe9,27},
- /* (247) |11111111|11111111|11111101|010 */ {0x7ffffea,27},
- /* (248) |11111111|11111111|11111101|011 */ {0x7ffffeb,27},
- /* (249) |11111111|11111111|11111111|1110 */ {0xffffffe,28},
- /* (250) |11111111|11111111|11111101|100 */ {0x7ffffec,27},
- /* (251) |11111111|11111111|11111101|101 */ {0x7ffffed,27},
- /* (252) |11111111|11111111|11111101|110 */ {0x7ffffee,27},
- /* (253) |11111111|11111111|11111101|111 */ {0x7ffffef,27},
- /* (254) |11111111|11111111|11111110|000 */ {0x7fffff0,27},
- /* (255) |11111111|11111111|11111011|10 */ {0x3ffffee,26},
- /*EOS (256) |11111111|11111111|11111111|111111 */ {0x3fffffff,30},
- };
-
- static final int[][] LCCODES = new int[CODES.length][];
-
- // Huffman decode tree stored in a flattened char array for good
- // locality of reference.
- static final char[] tree;
- static final char[] rowsym;
- static final byte[] rowbits;
-
- // Build the Huffman lookup tree and LC TABLE
- static
- {
- System.arraycopy(CODES,0,LCCODES,0,CODES.length);
- for (int i='A';i<='Z';i++)
- LCCODES[i]=LCCODES['a'+i-'A'];
-
- int r=0;
- for (int i=0;i 8)
- {
- len -= 8;
- int i = ((code >>> len) & 0xFF);
-
- int t=current*256+i;
- current = tree[t];
- if (current == 0)
- {
- tree[t] = (char)++r;
- current=r;
- }
- }
-
- int terminal = ++r;
- rowsym[r]=(char)sym;
- int b = len & 0x07;
- int terminalBits = b == 0?8:b;
-
- rowbits[r]=(byte)terminalBits;
- int shift = 8 - len;
- int start = current*256 + ((code << shift) & 0xFF);
- int end = start + (1<= 8)
- {
- int c = (current >>> (bits - 8)) & 0xFF;
- node = tree[node*256+c];
- if (rowbits[node]!=0)
- {
- // terminal node
- out.append(rowsym[node]);
- bits -= rowbits[node];
- node = 0;
- }
- else
- {
- // non-terminal node
- bits -= 8;
- }
- }
- }
-
- while (bits > 0)
- {
- int c = (current << (8 - bits)) & 0xFF;
- node = tree[node*256+c];
- if (rowbits[node]==0 || rowbits[node] > bits)
- break;
-
- if (rowbits[node]==0)
- throw new IllegalStateException();
-
- out.append(rowsym[node]);
- bits -= rowbits[node];
- node = 0;
- }
-
- return out.toString();
- }
-
- public static int octetsNeeded(String s)
- {
- return octetsNeeded(CODES,s);
- }
-
- public static void encode(ByteBuffer buffer,String s)
- {
- encode(CODES,buffer,s);
- }
-
- public static int octetsNeededLC(String s)
- {
- return octetsNeeded(LCCODES,s);
- }
-
- public static void encodeLC(ByteBuffer buffer, String s)
- {
- encode(LCCODES,buffer,s);
- }
-
- private static int octetsNeeded(final int[][] table,String s)
- {
- int needed=0;
- int len = s.length();
- for (int i=0;i=128 || c<' ')
- throw new IllegalArgumentException();
- needed += table[c][1];
- }
-
- return (needed+7) / 8;
- }
-
- private static void encode(final int[][] table,ByteBuffer buffer,String s)
- {
- long current = 0;
- int n = 0;
-
- byte[] array = buffer.array();
- int p=buffer.arrayOffset()+buffer.position();
-
- int len = s.length();
- for (int i=0;i=128 || c<' ')
- throw new IllegalArgumentException();
- int code = table[c][0];
- int bits = table[c][1];
-
- current <<= bits;
- current |= code;
- n += bits;
-
- while (n >= 8)
- {
- n -= 8;
- array[p++]=(byte)(current >> n);
- }
- }
-
- if (n > 0)
- {
- current <<= (8 - n);
- current |= (0xFF >>> n);
- array[p++]=(byte)current;
- }
-
- buffer.position(p-buffer.arrayOffset());
- }
-
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java
deleted file mode 100644
index 1db32e3a1e..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java
+++ /dev/null
@@ -1,184 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.http2.hpack;
-
-
-import org.eclipse.jetty.http.BadMessageException;
-import org.eclipse.jetty.http.HostPortHttpField;
-import org.eclipse.jetty.http.HttpField;
-import org.eclipse.jetty.http.HttpFields;
-import org.eclipse.jetty.http.HttpScheme;
-import org.eclipse.jetty.http.HttpStatus;
-import org.eclipse.jetty.http.HttpVersion;
-import org.eclipse.jetty.http.MetaData;
-
-public class MetaDataBuilder
-{
- private final int _maxSize;
- private int _size;
- private int _status;
- private String _method;
- private HttpScheme _scheme;
- private HostPortHttpField _authority;
- private String _path;
- private long _contentLength=Long.MIN_VALUE;
-
- private HttpFields _fields = new HttpFields(10);
-
- /* ------------------------------------------------------------ */
- /**
- * @param maxHeadersSize The maximum size of the headers, expressed as total name and value characters.
- */
- MetaDataBuilder(int maxHeadersSize)
- {
- _maxSize=maxHeadersSize;
- }
-
- /** Get the maxSize.
- * @return the maxSize
- */
- public int getMaxSize()
- {
- return _maxSize;
- }
-
- /** Get the size.
- * @return the current size in bytes
- */
- public int getSize()
- {
- return _size;
- }
-
- public void emit(HttpField field)
- {
- int field_size = field.getName().length()+field.getValue().length();
- _size+=field_size;
- if (_size>_maxSize)
- throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+_size+">"+_maxSize);
-
- if (field instanceof StaticTableHttpField)
- {
- StaticTableHttpField value = (StaticTableHttpField)field;
- switch(field.getHeader())
- {
- case C_STATUS:
- _status=(Integer)value.getStaticValue();
- break;
-
- case C_METHOD:
- _method=field.getValue();
- break;
-
- case C_SCHEME:
- _scheme = (HttpScheme)value.getStaticValue();
- break;
-
- default:
- throw new IllegalArgumentException(field.getName());
- }
- }
- else if (field.getHeader()!=null)
- {
- switch(field.getHeader())
- {
- case C_STATUS:
- _status=field.getIntValue();
- break;
-
- case C_METHOD:
- _method=field.getValue();
- break;
-
- case C_SCHEME:
- _scheme = HttpScheme.CACHE.get(field.getValue());
- break;
-
- case C_AUTHORITY:
- _authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue());
- break;
-
- case HOST:
- // :authority fields must come first. If we have one, ignore the host header as far as authority goes.
- if (_authority==null)
- _authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue());
- _fields.add(field);
- break;
-
- case C_PATH:
- _path = field.getValue();
- break;
-
- case CONTENT_LENGTH:
- _contentLength = field.getLongValue();
- _fields.add(field);
- break;
-
- default:
- if (field.getName().charAt(0)!=':')
- _fields.add(field);
- }
- }
- else
- {
- if (field.getName().charAt(0)!=':')
- _fields.add(field);
- }
- }
-
- public MetaData build()
- {
- try
- {
- HttpFields fields = _fields;
- _fields = new HttpFields(Math.max(10,fields.size()+5));
-
- if (_method!=null)
- return new MetaData.Request(_method,_scheme,_authority,_path,HttpVersion.HTTP_2,fields,_contentLength);
- if (_status!=0)
- return new MetaData.Response(HttpVersion.HTTP_2,_status,fields,_contentLength);
- return new MetaData(HttpVersion.HTTP_2,fields,_contentLength);
- }
- finally
- {
- _status=0;
- _method=null;
- _scheme=null;
- _authority=null;
- _path=null;
- _size=0;
- _contentLength=Long.MIN_VALUE;
- }
- }
-
- /* ------------------------------------------------------------ */
- /** Check that the max size will not be exceeded.
- * @param length the length
- * @param huffman the huffman name
- */
- public void checkSize(int length, boolean huffman)
- {
- // Apply a huffman fudge factor
- if (huffman)
- length=(length*4)/3;
- if ((_size+length)>_maxSize)
- throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+(_size+length)+">"+_maxSize);
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/NBitInteger.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/NBitInteger.java
deleted file mode 100644
index 5e991173dc..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/NBitInteger.java
+++ /dev/null
@@ -1,151 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.http2.hpack;
-
-import java.nio.ByteBuffer;
-
-public class NBitInteger
-{
- public static int octectsNeeded(int n,int i)
- {
- if (n==8)
- {
- int nbits = 0xFF;
- i=i-nbits;
- if (i<0)
- return 1;
- if (i==0)
- return 2;
- int lz=Integer.numberOfLeadingZeros(i);
- int log=32-lz;
- return 1+(log+6)/7;
- }
-
- int nbits = 0xFF >>> (8 - n);
- i=i-nbits;
- if (i<0)
- return 0;
- if (i==0)
- return 1;
- int lz=Integer.numberOfLeadingZeros(i);
- int log=32-lz;
- return (log+6)/7;
- }
-
- public static void encode(ByteBuffer buf, int n, int i)
- {
- if (n==8)
- {
- if (i < 0xFF)
- {
- buf.put((byte)i);
- }
- else
- {
- buf.put((byte)0xFF);
-
- int length = i - 0xFF;
- while (true)
- {
- if ((length & ~0x7F) == 0)
- {
- buf.put((byte)length);
- return;
- }
- else
- {
- buf.put((byte)((length & 0x7F) | 0x80));
- length >>>= 7;
- }
- }
- }
- }
- else
- {
- int p=buf.position()-1;
- int bits = 0xFF >>> (8 - n);
-
- if (i < bits)
- {
- buf.put(p,(byte)((buf.get(p)&~bits)|i));
- }
- else
- {
- buf.put(p,(byte)(buf.get(p)|bits));
-
- int length = i - bits;
- while (true)
- {
- if ((length & ~0x7F) == 0)
- {
- buf.put((byte)length);
- return;
- }
- else
- {
- buf.put((byte)((length & 0x7F) | 0x80));
- length >>>= 7;
- }
- }
- }
- }
- }
-
- public static int decode(ByteBuffer buffer, int n)
- {
- if (n==8)
- {
- int nbits = 0xFF;
-
- int i=buffer.get()&0xff;
-
- if (i == nbits)
- {
- int m=1;
- int b;
- do
- {
- b = 0xff&buffer.get();
- i = i + (b&127) * m;
- m = m*128;
- }
- while ((b&128) == 128);
- }
- return i;
- }
-
- int nbits = 0xFF >>> (8 - n);
-
- int i=buffer.get(buffer.position()-1)&nbits;
-
- if (i == nbits)
- {
- int m=1;
- int b;
- do
- {
- b = 0xff&buffer.get();
- i = i + (b&127) * m;
- m = m*128;
- }
- while ((b&128) == 128);
- }
- return i;
- }
-}
diff --git a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/StaticTableHttpField.java b/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/StaticTableHttpField.java
deleted file mode 100644
index 275ab53629..0000000000
--- a/org.eclipse.jetty.http/src/org/eclipse/jetty/http2/hpack/StaticTableHttpField.java
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// 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.http2.hpack;
-
-import org.eclipse.jetty.http.HttpField;
-import org.eclipse.jetty.http.HttpHeader;
-
-/* ------------------------------------------------------------ */
-public class StaticTableHttpField extends HttpField
-{
- private final Object _value;
-
- public StaticTableHttpField(HttpHeader header, String name, String valueString, Object value)
- {
- super(header,name,valueString);
- if (value==null)
- throw new IllegalArgumentException();
- _value=value;
- }
-
- public StaticTableHttpField(HttpHeader header,String valueString, Object value)
- {
- this (header,header.asString(),valueString, value);
- }
-
- public StaticTableHttpField(String name, String valueString, Object value)
- {
- super(name,valueString);
- if (value==null)
- throw new IllegalArgumentException();
- _value=value;
- }
-
- public Object getStaticValue()
- {
- return _value;
- }
-
- @Override
- public String toString()
- {
- return super.toString()+"(evaluated)";
- }
-}
\ No newline at end of file
diff --git a/org.idempiere.customize-feature/.project b/org.idempiere.customize-feature/.project
deleted file mode 100644
index 14d94e9777..0000000000
--- a/org.idempiere.customize-feature/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- org.idempiere.customize-feature
-
-
-
-
-
- org.eclipse.pde.FeatureBuilder
-
-
-
-
-
- org.eclipse.pde.FeatureNature
-
-
diff --git a/org.idempiere.customize-feature/build.properties b/org.idempiere.customize-feature/build.properties
deleted file mode 100644
index 64f93a9f0b..0000000000
--- a/org.idempiere.customize-feature/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-bin.includes = feature.xml
diff --git a/org.idempiere.customize-feature/feature.xml b/org.idempiere.customize-feature/feature.xml
deleted file mode 100644
index 7dbdfe04b9..0000000000
--- a/org.idempiere.customize-feature/feature.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
- [Enter Feature Description here.]
-
-
-
- [Enter Copyright Description here.]
-
-
-
- [Enter License Description here.]
-
-
-
diff --git a/org.idempiere.eclipse.platform-feature/director/configuration/config.ini b/org.idempiere.eclipse.platform-feature/director/configuration/config.ini
index 2c3262519f..7172f72136 100644
--- a/org.idempiere.eclipse.platform-feature/director/configuration/config.ini
+++ b/org.idempiere.eclipse.platform-feature/director/configuration/config.ini
@@ -1,4 +1,4 @@
-osgi.framework=file\:../plugins/org.eclipse.osgi_3.10.2.v20150203-1939.jar
+osgi.framework=file\:../plugins/org.eclipse.osgi_3.12.50.v20170928-1321.jar
osgi.install.area=director
equinox.use.ds=true
osgi.bundles=org.eclipse.core.net@start,\
diff --git a/org.idempiere.eclipse.platform-feature/feature.xml b/org.idempiere.eclipse.platform-feature/feature.xml
index 60f029a951..3796697414 100644
--- a/org.idempiere.eclipse.platform-feature/feature.xml
+++ b/org.idempiere.eclipse.platform-feature/feature.xml
@@ -137,20 +137,6 @@
version="0.0.0"
unpack="false"/>
-
-
-
-
+
+
diff --git a/org.idempiere.fitnesse.server/WEB-INF/web.xml b/org.idempiere.fitnesse.server/WEB-INF/web.xml
index 655e4cbcb1..66fbf0a087 100644
--- a/org.idempiere.fitnesse.server/WEB-INF/web.xml
+++ b/org.idempiere.fitnesse.server/WEB-INF/web.xml
@@ -1,8 +1,8 @@
-
+
Fitnesse Server
diff --git a/org.idempiere.fitrecorder/META-INF/MANIFEST.MF b/org.idempiere.fitrecorder/META-INF/MANIFEST.MF
index b9caf0f1da..595f04f8ea 100644
--- a/org.idempiere.fitrecorder/META-INF/MANIFEST.MF
+++ b/org.idempiere.fitrecorder/META-INF/MANIFEST.MF
@@ -11,3 +11,4 @@ Import-Package: org.adempiere.base,
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Service-Component: plugin.xml
Require-Bundle: org.adempiere.base;bundle-version="0.0.0"
+Bundle-ActivationPolicy: lazy
diff --git a/org.idempiere.hazelcast.service.config/bin/.hgignore b/org.idempiere.hazelcast.service.config/bin/.hgignore
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/org.idempiere.webservices/META-INF/MANIFEST.MF b/org.idempiere.webservices/META-INF/MANIFEST.MF
index 61e48d602b..5d6d4347cd 100644
--- a/org.idempiere.webservices/META-INF/MANIFEST.MF
+++ b/org.idempiere.webservices/META-INF/MANIFEST.MF
@@ -220,3 +220,4 @@ Export-Package: javax.ws.rs,
org.springframework.web.context,
org.springframework.web.util
Web-ContextPath: ADInterface
+Bundle-ActivationPolicy: lazy
diff --git a/zk.xml b/zk.xml
new file mode 100644
index 0000000000..bb7495b189
--- /dev/null
+++ b/zk.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ org.zkoss.web.classWebResource.cache
+ false
+
+
+ org.zkoss.zk.WPD.cache
+ false
+
+
+ org.zkoss.zk.WCS.cache
+ false
+
+
+
+ true
+
+