/*
* Copyright Ericsson AB 2011-2014. All Rights Reserved.
*
* The contents of this file are subject to the Lesser GNU Public License,
* (the "License"), either version 2.1 of the License, or
* (at your option) any later version.; you may not use this file except in
* compliance with the License. You should have received a copy of the
* License along with this software. If not, it can be
* retrieved online at https://www.gnu.org/licenses/lgpl.html. Moreover
* it could also be requested from Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
* WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
* EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
* OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
* LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
*
* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
* WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
* REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
* DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
* DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
* (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
* INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE
* OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
* HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
*/
package com.ericsson.deviceaccess.coap.basedriver.util;
import com.ericsson.common.util.BitUtil;
import com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPContentType;
import com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionHeader;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.ACCEPT;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.BLOCK1;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.BLOCK2;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.CONTENT_FORMAT;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.ETAG;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.IF_MATCH;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.IF_NONE_MATCH;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.LOCATION_PATH;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.LOCATION_QUERY;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.MAX_AGE;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.OBSERVE;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.PROXY_URI;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.URI_HOST;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.URI_PATH;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.URI_PORT;
import static com.ericsson.deviceaccess.coap.basedriver.api.message.CoAPOptionName.URI_QUERY;
import java.nio.charset.StandardCharsets;
/**
* This is a helper class to convert option header to string format from byte
* arrays
*
*/
public class CoAPOptionHeaderConverter {
private static final char[] HEX_CHARS = new char[]{
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* Constructor. Creates an instance of the converter.
*/
public CoAPOptionHeaderConverter() {
}
/**
* Convert the value of the option header to string. There are different
* formats for option headers, so different headers are handled differently
* based on the format. For now, Etag, Token and If-Match are converted to
* hex strings.
*
* @param header header whose value is to be converted
* @return string representation of the header value
*/
public String convertOptionHeaderToString(CoAPOptionHeader header) {
byte[] bytes = header.getValue();
switch (header.getOptionName()) {
case CONTENT_FORMAT:
return CoAPContentType.get(BitUtil.shortToUnsignedInt(bytes)).getContentType();
case URI_PORT:
case ACCEPT:
case OBSERVE:
return Integer.toString(BitUtil.shortToUnsignedInt(bytes));
case MAX_AGE:
return Long.toString(BitUtil.convertIntToUnsignedLong(bytes));
case PROXY_URI:
case URI_HOST:
case URI_QUERY:
case URI_PATH:
case LOCATION_QUERY:
case LOCATION_PATH:
return new String(bytes, StandardCharsets.UTF_8);
case ETAG:
case IF_MATCH: // TODO etag and if-match
// TODO check if the byte array is hex or string??
return convertHexToString(bytes);
case BLOCK1:
case BLOCK2:
// show the value as unsigned int
long longValue = BitUtil.convertIntToUnsignedLong(bytes);
// More details for debug (Ryoji)
//value = Long.toString(longValue);
long num = longValue >> 4;
long m = (longValue >> 3) & 0x1L;
long szx = longValue & 7L;
return longValue + " (Num=" + num + "/M=" + m + "/Sz=" + CoAPUtil.getBlockSize(szx) + ")";
case IF_NONE_MATCH:
default:
return "";
}
}
public boolean isHex(String in) {
boolean isHex = false;
try {
// try to parse the string to an integer, using 16 as radix
Integer.parseInt(in, 16);
isHex = true;
} catch (NumberFormatException e) {
}
return isHex;
}
/**
* Convert value of the option header byte array to a hex string
*
* @param header header to be converted
* @return hex string representation of a byte array
*/
private String convertHexToString(byte[] bytes) {
StringBuilder buff = new StringBuilder(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
buff.insert(i * 2, HEX_CHARS[(bytes[i] >> 4) & 0xf]);
buff.insert(i * 2 + 1, HEX_CHARS[bytes[i] & 0xf]);
}
return buff.toString();
}
}