blob: 7aeb7f52193586c4865e81b85d8d76735f94cd77 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2017 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 quality values
* in accordance with RFC7230 and RFC7231.
* Values are returned sorted in quality order, with OWS and the
* quality parameters removed.
* @see "https://tools.ietf.org/html/rfc7230#section-3.2.6"
* @see "https://tools.ietf.org/html/rfc7230#section-7"
* @see "https://tools.ietf.org/html/rfc7231#section-5.3.1"
*/
public class QuotedQualityCSV extends QuotedCSV implements Iterable<String>
{
private final static Double ZERO=new Double(0.0);
private final static Double ONE=new Double(1.0);
private final List<Double> _quality = new ArrayList<>();
private boolean _sorted = false;
/* ------------------------------------------------------------ */
public QuotedQualityCSV(String... values)
{
for (String v:values)
addValue(v);
}
/* ------------------------------------------------------------ */
public void addValue(String value)
{
super.addValue(value);
while(_quality.size()<_values.size())
_quality.add(ONE);
}
/* ------------------------------------------------------------ */
@Override
protected void parsedValue(StringBuffer buffer)
{
super.parsedValue(buffer);
}
/* ------------------------------------------------------------ */
@Override
protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
{
if (paramName<0)
{
if (buffer.charAt(buffer.length()-1)==';')
buffer.setLength(buffer.length()-1);
}
if (paramValue>=0 &&
buffer.charAt(paramName)=='q' && paramValue>paramName &&
buffer.length()>=paramName && buffer.charAt(paramName+1)=='=')
{
Double q;
try
{
q=(_keepQuotes && buffer.charAt(paramValue)=='"')
?new Double(buffer.substring(paramValue+1,buffer.length()-1))
:new Double(buffer.substring(paramValue));
}
catch(Exception e)
{
q=ZERO;
}
buffer.setLength(paramName-1);
while(_quality.size()<_values.size())
_quality.add(ONE);
_quality.add(q);
}
}
public List<String> getValues()
{
if (!_sorted)
sort();
return _values;
}
@Override
public Iterator<String> iterator()
{
if (!_sorted)
sort();
return _values.iterator();
}
protected void sort()
{
_sorted=true;
Double last = ZERO;
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)
{
_values.set(i, _values.get(i + 1));
_values.set(i + 1, v);
_quality.set(i, _quality.get(i + 1));
_quality.set(i + 1, q);
last = ZERO;
i = _values.size();
continue;
}
last=q;
}
int last_element=_quality.size();
while(last_element>0 && _quality.get(--last_element).equals(ZERO))
{
_quality.remove(last_element);
_values.remove(last_element);
}
}
}