package org.ws4d.coap.messages;
import java.io.UnsupportedEncodingException;
import java.util.Vector;
import org.ws4d.coap.interfaces.CoapRequest;
/**
* @author Christian Lerche <christian.lerche@uni-rostock.de>
*/
public class BasicCoapRequest extends AbstractCoapMessage implements CoapRequest {
CoapRequestCode requestCode;
public BasicCoapRequest(byte[] bytes, int length) {
/* length ought to be provided by UDP header */
this(bytes, length, 0);
}
public BasicCoapRequest(byte[] bytes, int length, int offset) {
serialize(bytes, length, offset);
/* check if request code is valid, this function throws an error in case of an invalid argument */
requestCode = CoapRequestCode.parseRequestCode(this.messageCodeValue);
//TODO: check integrity of header options
}
public BasicCoapRequest(CoapPacketType packetType, CoapRequestCode requestCode, int messageId) {
this.version = 1;
this.packetType = packetType;
this.requestCode = requestCode;
this.messageCodeValue = requestCode.getValue();
this.messageId = messageId;
}
@Override
public void setToken(byte[] token){
/* this function is only public for a request*/
super.setToken(token);
}
public CoapRequestCode getRequestCode() {
return requestCode;
}
public void setUriHost(String host) {
if (host == null) return;
if (options.optionExists(CoapHeaderOptionType.Uri_Host)){
throw new IllegalArgumentException("Uri-Host option already exists");
}
if (host.length() < 1 || host.length() > CoapHeaderOption.MAX_LENGTH){
throw new IllegalArgumentException("Invalid Uri-Host option length");
}
/*TODO: check if host is a valid address */
options.addOption(CoapHeaderOptionType.Uri_Host, host.getBytes());
}
public void setUriPort(int port) {
if (port < 0) return;
if (options.optionExists(CoapHeaderOptionType.Uri_Port)){
throw new IllegalArgumentException("Uri-Port option already exists");
}
byte[] value = long2CoapUint(port);
if(value.length < 0 || value.length > 2){
throw new IllegalStateException("Illegal Uri-Port length");
}
options.addOption(new CoapHeaderOption(CoapHeaderOptionType.Uri_Port, value));
}
public void setUriPath(String path) {
if (path == null) return;
if (path.length() > CoapHeaderOption.MAX_LENGTH ){
throw new IllegalArgumentException("Uri-Path option too long");
}
/* delete old options if present */
options.removeOption(CoapHeaderOptionType.Uri_Path);
/*create substrings */
String[] pathElements = path.split("/");
/* add a Uri Path option for each part */
for (String element : pathElements) {
/* check length */
if(element.length() < 0 || element.length() > CoapHeaderOption.MAX_LENGTH){
throw new IllegalArgumentException("Invalid Uri-Path");
} else if (element.length() > 0){
/* ignore empty substrings */
options.addOption(CoapHeaderOptionType.Uri_Path, element.getBytes());
}
}
}
public void setUriQuery(String query) {
if (query == null) return;
if (query.length() > CoapHeaderOption.MAX_LENGTH ){
throw new IllegalArgumentException("Uri-Query option too long");
}
/* delete old options if present */
options.removeOption(CoapHeaderOptionType.Uri_Query);
/*create substrings */
String[] pathElements = query.split("&");
/* add a Uri Path option for each part */
for (String element : pathElements) {
/* check length */
if(element.length() < 0 || element.length() > CoapHeaderOption.MAX_LENGTH){
throw new IllegalArgumentException("Invalid Uri-Path");
} else if (element.length() > 0){
/* ignore empty substrings */
options.addOption(CoapHeaderOptionType.Uri_Query, element.getBytes());
}
}
}
public void setProxyUri(String proxyUri) {
if (proxyUri == null) return;
if (options.optionExists(CoapHeaderOptionType.Proxy_Uri)){
throw new IllegalArgumentException("Proxy Uri already exists");
}
if (proxyUri.length() < 1){
throw new IllegalArgumentException("Proxy Uri must be at least one byte long");
}
if (proxyUri.length() > CoapHeaderOption.MAX_LENGTH ){
throw new IllegalArgumentException("Proxy Uri longer then 270 bytes are not supported yet (to be implemented)");
}
options.addOption(CoapHeaderOptionType.Proxy_Uri, proxyUri.getBytes());
}
public Vector<String> getUriQuery(){
Vector<String> queryList = new Vector<String>();
for (CoapHeaderOption option : options) {
if(option.getOptionType() == CoapHeaderOptionType.Uri_Query){
queryList.add(new String(option.getOptionData()));
}
}
return queryList;
}
public String getUriHost(){
return new String(options.getOption(CoapHeaderOptionType.Uri_Host).getOptionData());
}
public int getUriPort(){
CoapHeaderOption option = options.getOption(CoapHeaderOptionType.Uri_Port);
if (option == null){
return -1; //TODO: return default Coap Port?
}
byte[] value = option.getOptionData();
if(value.length < 0 || value.length > 2){
/* should never happen because this is an internal variable and should be checked during serialization */
throw new IllegalStateException("Illegal Uri-Port Option length");
}
/* checked length -> cast is safe*/
return (int)coapUint2Long(options.getOption(CoapHeaderOptionType.Uri_Port).getOptionData());
}
public String getUriPath() {
if (options.getOption(CoapHeaderOptionType.Uri_Path) == null){
return null;
}
StringBuilder uriPathBuilder = new StringBuilder();
for (CoapHeaderOption option : options) {
if (option.getOptionType() == CoapHeaderOptionType.Uri_Path) {
String uriPathElement;
try {
uriPathElement = new String(option.getOptionData(), "UTF-8");
uriPathBuilder.append("/");
uriPathBuilder.append(uriPathElement);
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("Invalid Encoding");
}
}
}
return uriPathBuilder.toString();
}
public void addAccept(CoapMediaType mediaType){
options.addOption(CoapHeaderOptionType.Accept, long2CoapUint(mediaType.getValue()));
}
public Vector<CoapMediaType> getAccept(CoapMediaType mediaType){
if (options.getOption(CoapHeaderOptionType.Accept) == null){
return null;
}
Vector<CoapMediaType> acceptList = new Vector<CoapMediaType>();
for (CoapHeaderOption option : options) {
if (option.getOptionType() == CoapHeaderOptionType.Accept) {
CoapMediaType accept = CoapMediaType.parse((int)coapUint2Long(option.optionData));
// if (accept != CoapMediaType.UNKNOWN){
/* add also UNKNOWN types to list */
acceptList.add(accept);
// }
}
}
return acceptList;
}
public String getProxyUri(){
CoapHeaderOption option = options.getOption(CoapHeaderOptionType.Proxy_Uri);
if (option == null)
return null;
return new String(option.getOptionData());
}
public void addETag(byte[] etag) {
if (etag == null){
throw new IllegalArgumentException("etag MUST NOT be null");
}
if (etag.length < 1 || etag.length > 8){
throw new IllegalArgumentException("Invalid etag length");
}
options.addOption(CoapHeaderOptionType.Etag, etag);
}
public Vector<byte[]> getETag() {
if (options.getOption(CoapHeaderOptionType.Etag) == null){
return null;
}
Vector<byte[]> etagList = new Vector<byte[]>();
for (CoapHeaderOption option : options) {
if (option.getOptionType() == CoapHeaderOptionType.Etag) {
byte[] data = option.getOptionData();
if (data.length >= 1 && data.length <= 8){
etagList.add(option.getOptionData());
}
}
}
return etagList;
}
public boolean isRequest() {
return true;
}
public boolean isResponse() {
return false;
}
public boolean isEmpty() {
return false;
}
@Override
public String toString() {
return packetType.toString() + ", " + requestCode.toString() + ", MsgId: " + getMessageID() +", #Options: " + options.getOptionCount();
}
public void setRequestCode(CoapRequestCode requestCode) {
this.requestCode = requestCode;
}
}