// HttpAccept.java
// $Id: HttpAccept.java,v 1.9 2000/08/16 21:37:58 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html
package org.w3c.www.http;
import java.util.Vector;
import org.w3c.www.mime.MimeType;
public class HttpAccept extends BasicValue {
/**
* The list of accept parameters name.
*/
protected String aparams[] = null;
/**
* The list of accept parameters value.
*/
protected String avalues[] = null;
/**
* The accepted MIME type.
*/
protected MimeType type = null;
/**
* The list we belong to, if any.
*/
HttpAcceptList list = null;
/**
* the quality
*/
protected double quality = -1;
/**
* parse.
* @exception HttpParserException if parsing failed.
*/
protected void parse()
throws HttpParserException
{
ParseState ps = new ParseState(roff, rlen);
// We need to do our own MIME type parsing, to avoid ambiguities !
// Get the type:
ps.separator = (byte) '/';
ps.spaceIsSep = false;
if ( HttpParser.nextItem(raw, ps) < 0 )
error("Invalid Accept: has no type.");
String type = new String(raw, 0, ps.start, ps.end-ps.start);
// Get the subtype:
ps.prepare();
ps.separator = (byte) ';';
if ( HttpParser.nextItem(raw, ps) < 0 )
error("Invalid accept: no subtype");
String subtype = new String(raw, 0, ps.start, ps.end-ps.start);
// Get the parameters:
ParseState it = new ParseState();
it.separator = (byte) '=';
it.spaceIsSep = false;
ps.prepare();
Vector vparams = new Vector(4);
Vector vvalues = new Vector(4);
boolean accept = false;
while (HttpParser.nextItem(raw, ps) >= 0) {
it.ioff = ps.start;
it.bufend = ps.end;
if ( HttpParser.nextItem(raw, it) < 0 )
error("Invalid parameter: no param name.");
// The Hack !
String param = new String(raw, 0, it.start, it.end-it.start);
if ( param.equalsIgnoreCase("q") ) {
// Switching to accept-params
accept = true;
break ;
}
vparams.addElement(new String(raw, 0, it.start, it.end-it.start));
it.prepare();
if ( HttpParser.nextItem(raw, it) < 0 )
error("Invalid parameter: no value.");
vvalues.addElement(new String(raw, 0, it.start, it.end-it.start));
ps.prepare();
}
if ( vparams.size() > 0 ) {
String pparams[] = new String[vparams.size()];
String pvalues[] = new String[pparams.length];
vparams.copyInto(pparams);
vvalues.copyInto(pvalues);
this.type = new MimeType(type, subtype, pparams, pvalues);
} else {
this.type = new MimeType(type, subtype);
}
// Parse remaining accept parameters:
if ( accept ) {
vparams.setSize(0);
vvalues.setSize(0);
// Hack to finish with the q parameter
it.prepare();
if ( HttpParser.nextItem(raw, it) < 0 )
error("Invalid accept parameter: no value.");
vparams.addElement("q");
vvalues.addElement(new String(raw, 0, it.start, it.end-it.start));
it.prepare();
while (HttpParser.nextItem(raw, ps) >= 0) {
it.ioff = ps.start;
it.bufend = ps.end;
if ( HttpParser.nextItem(raw, it) < 0 )
error("Invalid accept parameter: no name.");
vparams.addElement(new String(raw,0,it.start,it.end-it.start));
it.prepare();
if (HttpParser.nextItem(raw, it) < 0 )
error("Invalid accept parameter: no value.");
vvalues.addElement(new String(raw,0,it.start,it.end-it.start));
ps.prepare();
}
this.aparams = new String[vparams.size()];
this.avalues = new String[aparams.length];
vparams.copyInto(aparams);
vvalues.copyInto(avalues);
}
}
protected void updateByteValue() {
HttpBuffer buf = new HttpBuffer();
buf.append(type.toString());
if ( aparams != null ) {
for (int i = 0 ; i < aparams.length ; i++) {
if ( i > 0 )
buf.append(';');
buf.append(aparams[i], (byte) '=', avalues[i]);
}
}
raw = buf.getByteCopy();
roff = 0;
rlen = raw.length;
}
protected void invalideByteValue() {
super.invalidateByteValue();
if ( list != null )
list.invalidateByteValue();
}
public Object getValue() {
validate();
return this;
}
/**
* Lookup for the given parameter binding.
* @return The slot number for this parameter, or <strong>-1</strong>
* if undefined.
*/
protected int lookup(String name) {
if ( aparams == null )
return -1;
for (int i = 0 ; i < aparams.length ; i++) {
if ( name.equalsIgnoreCase(aparams[i]) )
return i;
}
return -1;
}
/**
* Get the String value for a parameter.
* @return The String value for the accept parameter, or
* <strong>null</strong> if undefined.
*/
public String getAcceptParameter(String name) {
validate();
int slot = lookup(name);
return (slot == -1) ? null : avalues[slot];
}
/**
* Set the value of an accept parameter.
* @param name The name of the accept parameter to set.
* @param value The value of the accept parameter to set.
*/
public void setAcceptParameter(String name, String value) {
validate();
int slot = lookup(name);
if ( slot == -1 ) {
// Look for a free slot:
for (int i = 0 ; i < aparams.length ; i++) {
if ( aparams[i] == null ) {
slot = i;
break;
}
}
// Do we need to resize ?
if ( slot == -1 ) {
slot = aparams.length;
String nap[] = new String[slot<<1];
String nav[] = new String[nap.length];
System.arraycopy(aparams, 0, nap, 0, slot);
System.arraycopy(avalues, 0, nav, 0, slot);
aparams = nap;
avalues = nav;
}
}
// Set the slot value:
invalidateByteValue();
aparams[slot] = name;
avalues[slot] = value;
}
/**
* Get this object accepted MIME type.
* @return The accepted MIME type.
*/
public MimeType getMimeType() {
validate();
return type;
}
/**
* Set the accepted MIME type.
* @param type The accepted MIME type.
*/
public void setMimeType(MimeType type) {
invalidateByteValue();
this.type = type;
}
/**
* Get the quality of this accept clause.
* @return A double value, encoding the quality, or <strong>1.0</strong>
* if undefined.
*/
public double getQuality() {
String value = getAcceptParameter("q");
if ( value == null ) {
if (quality != -1 ) {
return quality;
}
String strtype = type.getType();
String strsubtype = type.getSubtype();
if (strtype.equals("*"))
return strsubtype.equals("*") ? 0.1 : 0.5 ;
return strsubtype.equals("*") ? 0.5 : 1.0;
}
try {
return Double.valueOf(value).doubleValue();
} catch (Exception ex) {
String msg = "invalid quality value: "+value;
throw new HttpInvalidValueException(msg);
}
}
HttpAccept(HttpAcceptList list, byte raw[], int roff, int rlen) {
this.list = list;
this.raw = raw;
this.roff = roff;
this.rlen = rlen;
this.isValid = false;
}
HttpAccept(boolean isValid, MimeType type, double quality) {
this.isValid = isValid;
setMimeType(type);
this.quality = quality;
}
public HttpAccept() {
this.isValid = false;
}
}