Package de.uniluebeck.itm.ncoap.application.server.webservice

Source Code of de.uniluebeck.itm.ncoap.application.server.webservice.WellKnownCoreResource

/**
* Copyright (c) 2012, Oliver Kleine, Institute of Telematics, University of Luebeck
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
*  - Redistributions of source messageCode must retain the above copyright notice, this list of conditions and the following
*    disclaimer.
*
*  - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
*    following disclaimer in the documentation and/or other materials provided with the distribution.
*
*  - Neither the name of the University of Luebeck nor the names of its contributors may be used to endorse or promote
*    products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package de.uniluebeck.itm.ncoap.application.server.webservice;

import com.google.common.primitives.Ints;
import com.google.common.util.concurrent.SettableFuture;

import de.uniluebeck.itm.ncoap.application.server.webservice.linkformat.EmptyLinkAttribute;
import de.uniluebeck.itm.ncoap.application.server.webservice.linkformat.LinkAttribute;
import de.uniluebeck.itm.ncoap.application.server.webservice.linkformat.LongLinkAttribute;
import de.uniluebeck.itm.ncoap.application.server.webservice.linkformat.StringLinkAttribute;
import de.uniluebeck.itm.ncoap.message.options.OptionValue;
import de.uniluebeck.itm.ncoap.message.CoapMessage;
import de.uniluebeck.itm.ncoap.message.CoapRequest;
import de.uniluebeck.itm.ncoap.message.CoapResponse;
import de.uniluebeck.itm.ncoap.message.MessageCode;
import de.uniluebeck.itm.ncoap.message.options.ContentFormat;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;

/**
* The .well-known/core resource is a standard webservice to be provided by every CoAP webserver as defined in
* the CoAP protocol draft. It provides a list of all available services on the server in CoRE Link Format.
*
* @author Oliver Kleine
*/
public final class WellKnownCoreResource extends NotObservableWebservice<Map<String, Webservice>> {

    private static Logger log = LoggerFactory.getLogger(WellKnownCoreResource.class.getName());

    private byte[] etag;

    /**
     * Creates the well-known/core resource at path /.well-known/core as defined in the CoAP draft
     * @param initialStatus the {@link java.util.Map} containing all available path
     */
    public WellKnownCoreResource(Map<String, Webservice> initialStatus, ScheduledExecutorService executor) {
        super("/.well-known/core", initialStatus, 0, executor);
    }

    /**
     * The .well-known/core resource only allows requests with {@link MessageCode.Name#GET}. Any other code
     * returns a {@link CoapResponse} with {@link MessageCode.Name#METHOD_NOT_ALLOWED_405}.
     *
     * In case of a request with {@link @link MessageCode.Name#GET} it returns a {@link CoapResponse} with
     * {@link MessageCode.Name#CONTENT_205} and with a payload listing all paths to the available resources
     * (i.e. {@link Webservice} instances}).
     *
     * <b>Note:</b> The payload is always formatted in {@link ContentFormat#APP_LINK_FORMAT}, possibly contained
     * {@link OptionValue.Name#ACCEPT} options in inbound {@link CoapRequest}s are ignored!
     *
     * @param responseFuture The {@link SettableFuture} to be set with a {@link CoapResponse} containing
     *                       the list of available services in CoRE link format.
     * @param coapRequest The {@link CoapRequest} to be processed by the {@link Webservice} instance
     * @param remoteEndpoint The address of the sender of the request
     *
     * @throws Exception Implementing classes may throw any {@link Exception}. Thrown {@link Exception}s cause the
     * framework to send a {@link CoapResponse} with {@link MessageCode.Name#INTERNAL_SERVER_ERROR_500} to the
     * client.
     */
    @Override
    public void processCoapRequest(SettableFuture<CoapResponse> responseFuture, CoapRequest coapRequest,
                                   InetSocketAddress remoteEndpoint) throws Exception{

        CoapResponse coapResponse;

        if(!(coapRequest.getMessageCodeName() == MessageCode.Name.GET)){
            coapResponse = CoapResponse.createErrorResponse(coapRequest.getMessageTypeName(),
                    MessageCode.Name.METHOD_NOT_ALLOWED_405, "GET is the only allowed method!");
        }

        else{
            coapResponse = processCoapGetRequest(coapRequest);
        }

        responseFuture.set(coapResponse);
    }


    private CoapResponse processCoapGetRequest(CoapRequest coapRequest){
        try{
            LinkAttribute filterAttribute = createLinkAttributeFromQuery(coapRequest.getUriQuery());

            CoapResponse coapResponse = new CoapResponse(coapRequest.getMessageTypeName(),
                    MessageCode.Name.CONTENT_205);

            byte[] content = getSerializedResourceStatus(filterAttribute);

            coapResponse.setContent(content, ContentFormat.APP_LINK_FORMAT);
            coapResponse.setEtag(this.etag);

            return coapResponse;
        }

        catch(IllegalArgumentException ex){

            return CoapResponse.createErrorResponse(coapRequest.getMessageTypeName(),
                    MessageCode.Name.BAD_REQUEST_400, ex.getMessage());
        }
    }


    private LinkAttribute createLinkAttributeFromQuery(String queryParameter) throws IllegalArgumentException{

        if(!queryParameter.equals("")){
            String[] param = queryParameter.split("=");

            if(param.length != 2)
                throw new IllegalArgumentException("Could not parse query " + queryParameter);

            LinkAttribute linkAttribute;
            int attributeType = LinkAttribute.getAttributeType(param[0]);

            if(attributeType == LinkAttribute.STRING_ATTRIBUTE)
                linkAttribute = new StringLinkAttribute(param[0], param[1]);

            else if(attributeType == LinkAttribute.LONG_ATTRIBUTE)
                linkAttribute = new LongLinkAttribute(param[0], Long.parseLong(param[1]));

            else if(attributeType == LinkAttribute.EMPTY_ATTRIBUTE)
                linkAttribute = new EmptyLinkAttribute(param[0]);

            else
                throw new IllegalArgumentException("This should never happen!");

            return linkAttribute;
        }

        return null;
    }


    @SuppressWarnings("unchecked")
    public byte[] getSerializedResourceStatus(LinkAttribute attribute){
        StringBuilder buffer = new StringBuilder();

        for(Webservice webservice : getStatus().values()){

            if(attribute != null && !webservice.hasLinkAttribute(attribute))
                continue;

            buffer.append("<").append(webservice.getUriPath()).append(">");

            String previousKey = null;
            for (LinkAttribute linkAttribute : (Iterable<LinkAttribute>) webservice.getLinkAttributes()) {
                buffer.append(linkAttribute.getKey().equals(previousKey) ? "" : ";" + linkAttribute.getKey());

                if(!(linkAttribute instanceof EmptyLinkAttribute)){

                    buffer.append(linkAttribute.getKey().equals(previousKey) ? " " : "=")
                          .append(linkAttribute.getValue());
                }


                previousKey = linkAttribute.getKey();
            }

            buffer.append(",\n");
        }

        if(buffer.length() > 3)
            buffer.deleteCharAt(buffer.length() - 2);

        log.debug("Content: \n{}", buffer.toString());

        return buffer.toString().getBytes(CoapMessage.CHARSET);

    }


    @Override
    @SuppressWarnings("unchecked")
    public byte[] getSerializedResourceStatus(long contentFormat){
        StringBuilder buffer = new StringBuilder();

        for(Webservice webservice : getStatus().values()){
            buffer.append("<").append(webservice.getUriPath()).append(">");

            String previousKey = null;
            for (LinkAttribute linkAttribute : (Iterable<LinkAttribute>) webservice.getLinkAttributes()) {
                buffer.append(linkAttribute.getKey().equals(previousKey) ? " " : ";")
                        .append(linkAttribute.getValue());

                previousKey = linkAttribute.getKey();
            }
        }

        if(buffer.length() > 3)
            buffer.deleteCharAt(buffer.length() - 2);

        log.debug("Content: \n{}", buffer.toString());

        return buffer.toString().getBytes(CoapMessage.CHARSET);
    }



    @Override
    public void shutdown() {
        //nothing to do here...
    }

    @Override
    public byte[] getEtag(long contentFormat) {
        return this.etag;
    }

    @Override
    public void updateEtag(Map<String, Webservice> resourceStatus) {
        this.etag = Ints.toByteArray(Arrays.hashCode(getSerializedResourceStatus(ContentFormat.APP_LINK_FORMAT)));
    }
}
TOP

Related Classes of de.uniluebeck.itm.ncoap.application.server.webservice.WellKnownCoreResource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.