org.eclipse.om2m.binding.coap.CoapClient.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.om2m.binding.coap.CoapClient.java

Source

/*******************************************************************************
 * Copyright (c) 2013-2016 LAAS-CNRS (www.laas.fr)
 * 7 Colonel Roche 31077 Toulouse - France
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Initial Contributors:
 *     Thierry Monteil : Project manager, technical co-manager
 *     Mahdi Ben Alaya : Technical co-manager
 *     Samir Medjiah : Technical co-manager
 *     Khalil Drira : Strategy expert
 *     Guillaume Garzone : Developer
 *     Franois Assaoui : Developer
 *
 * New contributors :
 *******************************************************************************/

package org.eclipse.om2m.binding.coap;

import java.math.BigInteger;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.om2m.binding.service.RestClientService;
import org.eclipse.om2m.commons.constants.MimeMediaType;
import org.eclipse.om2m.commons.constants.Operation;
import org.eclipse.om2m.commons.constants.ResponseStatusCode;
import org.eclipse.om2m.commons.resource.Attribute;
import org.eclipse.om2m.commons.resource.FilterCriteria;
import org.eclipse.om2m.commons.resource.RequestPrimitive;
import org.eclipse.om2m.commons.resource.ResponsePrimitive;
import org.eclipse.om2m.commons.resource.StatusCode;

import ch.ethz.inf.vs.californium.coap.CoAP;
import ch.ethz.inf.vs.californium.coap.MediaTypeRegistry;
import ch.ethz.inf.vs.californium.coap.Option;
import ch.ethz.inf.vs.californium.coap.OptionSet;
import ch.ethz.inf.vs.californium.coap.Request;
import ch.ethz.inf.vs.californium.coap.Response;

public class CoapClient implements RestClientService {

    /** Logger: */
    private static Log LOGGER = LogFactory.getLog(CoapClient.class);
    /** implemented specific protocol name */
    private static String protocol = "coap";

    /**
     * gets the implemented specific protocol name
     * 
     * @return protocol name
     */
    public String getProtocol() {
        return protocol;
    }

    /**
     * Converts a protocol-independent {@link RequestIndication} object into a
     * standard CoAP request and sends a standard CoAP request. Converts the
     * received standard CoAP response into {@link ResponseConfirm} object and
     * returns it back.
     * 
     * @param requestIndication
     *            - protocol independent request.
     * @return protocol independent response.
     */
    public ResponsePrimitive sendRequest(RequestPrimitive requestPrimitive) {
        LOGGER.debug("Sending request with CoAP binding: " + requestPrimitive);

        // Retrieve the url
        String url = requestPrimitive.getTo();
        if (!url.startsWith(protocol + "://")) {
            if (url.startsWith("://")) {
                url = protocol + url;
            } else if (url.startsWith("//")) {
                url = protocol + ":" + url;
            } else {
                url = protocol + "://" + url;
            }
        }

        // create the standard final response
        ResponsePrimitive responsePrimitive = new ResponsePrimitive();

        // get the Payload from requestIndication
        String representation = requestPrimitive.getContent() != null ? requestPrimitive.getContent().toString()
                : null;

        // create the code in order to create a coap request
        CoAP.Code code = null;

        // get the method from requestIndication
        BigInteger operation = requestPrimitive.getOperation();
        if (operation != null) {
            if (operation.equals(Operation.CREATE)) {
                code = CoAP.Code.POST;
            } else if (operation.equals(Operation.RETRIEVE) || operation.equals(Operation.DISCOVERY)) {
                code = CoAP.Code.GET;
            } else if (operation.equals(Operation.UPDATE)) {
                code = CoAP.Code.PUT;
            } else if (operation.equals(Operation.DELETE)) {
                code = CoAP.Code.DELETE;
            } else if (operation.equals(Operation.NOTIFY)) {
                code = CoAP.Code.POST;
            }
        } else {
            return responsePrimitive;
        }

        // create a coap request
        Request request = new Request(code);

        // get the options of the CoAP request (which is still empty)
        OptionSet options = new OptionSet();
        request.setOptions(options);
        // set the CoAP message Id
        int MId = (int) (1000 + Math.random() * (9001));
        request.setMID(MId);
        // request.setToken(token);
        CoAP.Type coapType = CoAP.Type.CON;
        request.setType(coapType);

        // set the request URI
        request.setURI(url);

        // set the payload
        if (representation != null) {
            request.setPayload(representation);
        }

        // set the content format of the request
        if (requestPrimitive.getRequestContentType() != null) {
            switch (requestPrimitive.getRequestContentType()) {
            case MimeMediaType.XML:
                request.getOptions().setContentFormat(CoapContentType.APP_XML);
                break;
            case MimeMediaType.XML_RESOURCE:
                request.getOptions().setContentFormat(CoapContentType.RES_XML);
                break;
            case MimeMediaType.JSON:
                request.getOptions().setContentFormat(CoapContentType.APP_JSON);
                break;
            case MimeMediaType.JSON_RESOURCE:
                request.getOptions().setContentFormat(CoapContentType.RES_JSON);
            default:
                break;
            }
        }

        // set the accept of the request
        if (requestPrimitive.getReturnContentType() != null) {
            switch (requestPrimitive.getReturnContentType()) {
            case MimeMediaType.XML:
                request.getOptions().setAccept(CoapContentType.APP_XML);
                break;
            case MimeMediaType.XML_RESOURCE:
                request.getOptions().setAccept(CoapContentType.RES_XML);
                break;
            case MimeMediaType.JSON:
                request.getOptions().setAccept(CoapContentType.APP_JSON);
                break;
            case MimeMediaType.JSON_RESOURCE:
                request.getOptions().setAccept(CoapContentType.RES_JSON);
            default:
                break;
            }
        }

        // Set multiple parameters from the request primitive
        if (requestPrimitive.getFrom() != null) {
            options.addOption(new Option(CoapOptions.ONEM2M_FR, requestPrimitive.getFrom()));
        }
        if (requestPrimitive.getRequestIdentifier() != null) {
            options.addOption(new Option(CoapOptions.ONEM2M_RQI, requestPrimitive.getRequestIdentifier()));
        }
        if (requestPrimitive.getResourceType() != null) {
            options.addOption(new Option(CoapOptions.ONEM2M_TY, requestPrimitive.getResourceType().intValue()));
        }
        if (requestPrimitive.getEventCategory() != null) {
            options.addOption(new Option(CoapOptions.ONEM2M_EC, requestPrimitive.getEventCategory()));
        }
        if (!requestPrimitive.getQueryStrings().isEmpty()) {
            for (String queryStringKey : requestPrimitive.getQueryStrings().keySet()) {
                for (String value : requestPrimitive.getQueryStrings().get(queryStringKey)) {
                    options.addURIQuery(queryStringKey + "=" + value);
                }
            }
        }
        if (requestPrimitive.getResponseTypeInfo() != null) {
            if (!requestPrimitive.getResponseTypeInfo().getNotificationURI().isEmpty()) {
                String notifUris = "";
                for (String nu : requestPrimitive.getResponseTypeInfo().getNotificationURI()) {
                    notifUris += nu + "&";
                }
                if (notifUris.endsWith("&")) {
                    notifUris = notifUris.substring(0, notifUris.length() - 1);
                }
                options.addOption(new Option(CoapOptions.ONEM2M_RTURI, notifUris));
            }
            if (requestPrimitive.getResponseTypeInfo().getResponseType() != null) {
                options.addURIQuery(CoapParameters.RESPONSE_TYPE + "="
                        + requestPrimitive.getResponseTypeInfo().getResponseType());
            }
        }

        if (requestPrimitive.getResultPersistence() != null) {
            options.addURIQuery(CoapParameters.RESULT_PERSISTENCE + "=" + requestPrimitive.getResultPersistence());
        }

        if (requestPrimitive.getResultContent() != null) {
            options.addURIQuery(CoapParameters.RESULT_CONTENT + "=" + requestPrimitive.getResultContent());
        }

        if (requestPrimitive.getDiscoveryResultType() != null) {
            options.addURIQuery(
                    CoapParameters.DISCOVERY_RESULT_TYPE + "=" + requestPrimitive.getDiscoveryResultType());
        }

        // Set the filter criteria parameters
        if (requestPrimitive.getFilterCriteria() != null) {
            FilterCriteria filter = requestPrimitive.getFilterCriteria();
            if (!filter.getAttribute().isEmpty()) {
                for (Attribute att : filter.getAttribute()) {
                    options.addURIQuery(att.getName() + "=" + att.getValue());
                }
            }
            if (filter.getFilterUsage() != null) {
                options.addURIQuery(CoapParameters.FILTER_USAGE + "=" + filter.getFilterUsage());
            }
            if (!filter.getLabels().isEmpty()) {
                for (String label : filter.getLabels()) {
                    options.addURIQuery(CoapParameters.LABELS + "=" + label);
                }
            }
            if (filter.getLimit() != null) {
                options.addURIQuery(CoapParameters.LIMIT + "=" + filter.getLimit());
            }
            if (filter.getResourceType() != null) {
                options.addURIQuery(CoapParameters.RESOURCE_TYPE + "=" + filter.getResourceType());
            }
        }

        if (requestPrimitive.getGroupRequestIdentifier() != null) {
            options.addOption(new Option(CoapOptions.ONEM2M_GID, requestPrimitive.getGroupRequestIdentifier()));
        }

        // send the request
        request.setScheme(url);
        request.send();

        // get the response
        Response response = null;
        try {
            response = request.waitForResponse();
        } catch (InterruptedException e) {
            LOGGER.error("CoAP Client > Failed to receive response: " + e.getMessage(), e);
            responsePrimitive.setResponseStatusCode(ResponseStatusCode.TARGET_NOT_REACHABLE);
            responsePrimitive.setContent("Target is not reachable");
            responsePrimitive.setContentType(MimeMediaType.TEXT_PLAIN);
            return responsePrimitive;
        }
        if (response != null) {
            if (response.getOptions().hasContentFormat(MediaTypeRegistry.APPLICATION_LINK_FORMAT)) {

                String linkFormat = response.getPayloadString();
                // fill in the representation of the responsePrimitive
                responsePrimitive.setContent(linkFormat);
            } else {
                responsePrimitive.setContent(response.getPayloadString());
            }
        }

        // Parse response options
        List<Option> optionsList = response.getOptions().asSortedList();
        for (Option o : optionsList) {
            switch (o.getNumber()) {
            case CoapOptions.ONEM2M_FR:
                responsePrimitive.setFrom(o.getStringValue());
                break;
            case CoapOptions.ONEM2M_RQI:
                responsePrimitive.setRequestIdentifier(o.getStringValue());
                break;
            case CoapOptions.ONEM2M_RSC:
                responsePrimitive.setResponseStatusCode(BigInteger.valueOf(o.getIntegerValue()));
                break;
            case CoapOptions.LOCATION:
                responsePrimitive.setLocation(o.getStringValue());
                break;
            default:
                LOGGER.trace("Option not handled: " + o.getNumber());
            }
        }

        if (responsePrimitive.getResponseStatusCode() == null) {
            responsePrimitive.setResponseStatusCode(getResponseStatusCode(response.getCode().value));
        }
        switch (response.getOptions().getContentFormat()) {
        case CoapContentType.APP_XML:
            responsePrimitive.setContentType(MimeMediaType.XML);
            break;
        case CoapContentType.RES_XML:
            responsePrimitive.setContentType(MimeMediaType.XML_RESOURCE);
            break;
        case CoapContentType.APP_JSON:
            responsePrimitive.setContentType(MimeMediaType.JSON);
            break;
        case CoapContentType.RES_JSON:
            responsePrimitive.setContentType(MimeMediaType.JSON_RESOURCE);
        }
        LOGGER.debug("CoAP Client > " + responsePrimitive);
        return responsePrimitive;
    }

    /**
     * Converts a standard CoAP status code into a protocol-independent
     * {@link StatusCode} object.
     * 
     * @param statusCode
     *            - standard CoAP status code.
     * @return protocol independent status.
     */
    private BigInteger getResponseStatusCode(int statusCode) {
        switch (statusCode) {
        case 200:
            return ResponseStatusCode.OK;
        case 202:
            return ResponseStatusCode.ACCEPTED;
        case 201:
            return ResponseStatusCode.CREATED;
        case 204:
            return ResponseStatusCode.DELETED;
        case 400:
            return ResponseStatusCode.BAD_REQUEST;
        case 403:
            return ResponseStatusCode.ACCESS_DENIED;
        case 404:
            return ResponseStatusCode.NOT_FOUND;
        case 405:
            return ResponseStatusCode.OPERATION_NOT_ALLOWED;
        case 409:
            return ResponseStatusCode.CONFLICT;
        case 500:
            return ResponseStatusCode.INTERNAL_SERVER_ERROR;
        case 501:
            return ResponseStatusCode.NOT_IMPLEMENTED;
        case 503:
            return ResponseStatusCode.SERVICE_UNAVAILABLE;
        default:
            return ResponseStatusCode.INTERNAL_SERVER_ERROR;
        }
    }
}