All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.leshan.server.registration.Registration Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2013-2015 Sierra Wireless and others.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 * 
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 *    http://www.eclipse.org/org/documents/edl-v10.html.
 * 
 * Contributors:
 *     Sierra Wireless - initial API and implementation
 *     Achim Kraus (Bosch Software Innovations GmbH) - use Identity as destination
 *******************************************************************************/
package org.eclipse.leshan.server.registration;

import java.io.Serializable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.leshan.Link;
import org.eclipse.leshan.core.request.BindingMode;
import org.eclipse.leshan.core.request.Identity;
import org.eclipse.leshan.util.StringUtils;
import org.eclipse.leshan.util.Validate;

/**
 * An immutable structure which represent a LW-M2M client registration on the server
 */
public class Registration implements Serializable {

    private static final long serialVersionUID = 1L;

    private static final long DEFAULT_LIFETIME_IN_SEC = 86400L;

    private static final String DEFAULT_LWM2M_VERSION = "1.0";

    private final Date registrationDate;

    private final Identity identity;

    /*
     * The address of the LWM2M Server's CoAP end point the client used to register.
     */
    private final InetSocketAddress registrationEndpointAddress;

    private final long lifeTimeInSec;

    private final String smsNumber;

    private final String lwM2mVersion;

    private final BindingMode bindingMode;

    /**
     * The LWM2M Client's unique end point name.
     */
    private final String endpoint;

    private final String id;

    private final Link[] objectLinks;

    private final Map additionalRegistrationAttributes;

    /** The location where LWM2M objects are hosted on the device */
    private final String rootPath;

    private final Date lastUpdate;

    protected Registration(String id, String endpoint, Identity identity, String lwM2mVersion, Long lifetimeInSec,
            String smsNumber, BindingMode bindingMode, Link[] objectLinks,
            InetSocketAddress registrationEndpointAddress,

            Date registrationDate, Date lastUpdate, Map additionalRegistrationAttributes) {

        Validate.notNull(id);
        Validate.notEmpty(endpoint);
        Validate.notNull(identity);
        Validate.notNull(registrationEndpointAddress);

        this.id = id;
        this.identity = identity;
        this.endpoint = endpoint;
        this.smsNumber = smsNumber;
        this.registrationEndpointAddress = registrationEndpointAddress;

        this.objectLinks = objectLinks;
        // extract the root objects path from the object links
        String rootPath = "/";
        if (objectLinks != null) {
            for (Link link : objectLinks) {
                if (link != null && "oma.lwm2m".equals(link.getAttributes().get("rt"))) {
                    rootPath = link.getUrl();
                    break;
                }
            }
        }
        this.rootPath = rootPath;

        this.lifeTimeInSec = lifetimeInSec == null ? DEFAULT_LIFETIME_IN_SEC : lifetimeInSec;
        this.lwM2mVersion = lwM2mVersion == null ? DEFAULT_LWM2M_VERSION : lwM2mVersion;
        this.bindingMode = bindingMode == null ? BindingMode.U : bindingMode;
        this.registrationDate = registrationDate == null ? new Date() : registrationDate;
        this.lastUpdate = lastUpdate == null ? new Date() : lastUpdate;
        if (additionalRegistrationAttributes == null || additionalRegistrationAttributes.isEmpty()) {
            this.additionalRegistrationAttributes = Collections.emptyMap();
        } else {
            // We create a new HashMap to have a real immutable map and to avoid "unmodifiableMap" encapsulation.
            this.additionalRegistrationAttributes = Collections
                    .unmodifiableMap(new HashMap<>(additionalRegistrationAttributes));
        }

    }

    public String getId() {
        return id;
    }

    public Date getRegistrationDate() {
        return registrationDate;
    }

    /**
     * Gets the clients identity.
     * 
     * @return identity from client's most recent registration or registration update.
     */
    public Identity getIdentity() {
        return identity;
    }

    /**
     * Gets the client's network socket address.
     * 
     * @return the source address from the client's most recent CoAP message.
     */
    public InetSocketAddress getSocketAddress() {
        return identity.getPeerAddress();
    }

    /**
     * Gets the client's network address.
     * 
     * @return the source address from the client's most recent CoAP message.
     */
    public InetAddress getAddress() {
        return identity.getPeerAddress().getAddress();
    }

    /**
     * Gets the client's network port number.
     * 
     * @return the source port from the client's most recent CoAP message.
     */
    public int getPort() {
        return identity.getPeerAddress().getPort();
    }

    /**
     * Gets the network address and port number of LWM2M Server's CoAP endpoint the client originally registered at.
     * 
     * A LWM2M Server may listen on multiple CoAP end points, e.g. a non-secure and a secure one. Clients are often
     * behind a firewall which will only let incoming UDP packets pass if they originate from the same address:port that
     * the client has initiated communication with, e.g. by means of registering with the LWM2M Server. It is therefore
     * important to know, which of the server's CoAP end points the client contacted for registration.
     * 
     * This information can be used to uniquely identify the CoAP endpoint that should be used to access resources on
     * the client.
     * 
     * @return the network address and port number
     */
    public InetSocketAddress getRegistrationEndpointAddress() {
        return registrationEndpointAddress;
    }

    public Link[] getObjectLinks() {
        return objectLinks;
    }

    public Link[] getSortedObjectLinks() {
        // sort the list of objects
        if (objectLinks == null) {
            return null;
        }

        Link[] res = Arrays.copyOf(objectLinks, objectLinks.length);

        Arrays.sort(res, new Comparator() {

            /* sort by path */
            @Override
            public int compare(Link o1, Link o2) {
                if (o1 == null && o2 == null)
                    return 0;
                if (o1 == null)
                    return -1;
                if (o2 == null)
                    return 1;
                // by URL
                String[] url1 = o1.getUrl().split("/");
                String[] url2 = o2.getUrl().split("/");

                for (int i = 0; i < url1.length && i < url2.length; i++) {
                    // is it two numbers?
                    if (isNumber(url1[i]) && isNumber(url2[i])) {
                        int cmp = Integer.parseInt(url1[i]) - Integer.parseInt(url2[i]);
                        if (cmp != 0) {
                            return cmp;
                        }
                    } else {

                        int v = url1[i].compareTo(url2[i]);

                        if (v != 0) {
                            return v;
                        }
                    }
                }

                return url1.length - url2.length;
            }
        });

        return res;
    }

    private static boolean isNumber(String s) {
        return !StringUtils.isEmpty(s) && StringUtils.isNumeric(s);
    }

    public Long getLifeTimeInSec() {
        return lifeTimeInSec;
    }

    public String getSmsNumber() {
        return smsNumber;
    }

    public String getLwM2mVersion() {
        return lwM2mVersion;
    }

    public BindingMode getBindingMode() {
        return bindingMode;
    }

    /**
     * @return the path where the objects are hosted on the device
     */
    public String getRootPath() {
        return rootPath;
    }

    /**
     * Gets the unique name the client has registered with.
     * 
     * @return the name
     */
    public String getEndpoint() {
        return endpoint;
    }

    public Date getLastUpdate() {
        return lastUpdate;
    }

    public long getExpirationTimeStamp() {
        return getExpirationTimeStamp(0L);
    }

    public long getExpirationTimeStamp(long gracePeriodInSec) {
        return lastUpdate.getTime() + lifeTimeInSec * 1000 + gracePeriodInSec * 1000;
    }

    /**
     * @return true if the last registration update was done less than lifetime seconds ago.
     */
    public boolean isAlive() {
        return isAlive(0);
    }

    /**
     * This is the same idea than {@link Registration#isAlive()} but with a grace period. 
* * @return true if the last registration update was done less than lifetime+gracePeriod seconds ago. */ public boolean isAlive(long gracePeriodInSec) { return getExpirationTimeStamp(gracePeriodInSec) > System.currentTimeMillis(); } public Map getAdditionalRegistrationAttributes() { return additionalRegistrationAttributes; } public boolean usesQueueMode() { return bindingMode.equals(BindingMode.UQ) || bindingMode.equals(BindingMode.UQS); } @Override public String toString() { return String.format( "Registration [registrationDate=%s, identity=%s, registrationEndpoint=%s, lifeTimeInSec=%s, smsNumber=%s, lwM2mVersion=%s, bindingMode=%s, endpoint=%s, registrationId=%s, objectLinks=%s, lastUpdate=%s]", registrationDate, identity, registrationEndpointAddress, lifeTimeInSec, smsNumber, lwM2mVersion, bindingMode, endpoint, id, Arrays.toString(objectLinks), lastUpdate); } /** * Computes a hash code for this client. * * @return the hash code based on the endpoint property */ @Override public int hashCode() { return getEndpoint().hashCode(); } /** * Compares this Client to another object. * * @return true if the other object is a Client instance and its endpoint property has the * same value as this Client */ @Override public boolean equals(Object obj) { if (obj instanceof Registration) { Registration other = (Registration) obj; return this.getEndpoint().equals(other.getEndpoint()); } else { return false; } } public static class Builder { private final String registrationId; private final String endpoint; private final Identity identity; private final InetSocketAddress registrationEndpointAddress; private Date registrationDate; private Date lastUpdate; private Long lifeTimeInSec; private String smsNumber; private BindingMode bindingMode; private String lwM2mVersion; private Link[] objectLinks; private Map additionalRegistrationAttributes; public Builder(String registrationId, String endpoint, Identity identity, InetSocketAddress registrationEndpointAddress) { Validate.notNull(registrationId); Validate.notEmpty(endpoint); Validate.notNull(identity); Validate.notNull(registrationEndpointAddress); this.registrationId = registrationId; this.endpoint = endpoint; this.identity = identity; this.registrationEndpointAddress = registrationEndpointAddress; } public Builder registrationDate(Date registrationDate) { this.registrationDate = registrationDate; return this; } public Builder lastUpdate(Date lastUpdate) { this.lastUpdate = lastUpdate; return this; } public Builder lifeTimeInSec(Long lifetimeInSec) { this.lifeTimeInSec = lifetimeInSec; return this; } public Builder smsNumber(String smsNumber) { this.smsNumber = smsNumber; return this; } public Builder bindingMode(BindingMode bindingMode) { this.bindingMode = bindingMode; return this; } public Builder lwM2mVersion(String lwM2mVersion) { this.lwM2mVersion = lwM2mVersion; return this; } public Builder objectLinks(Link[] objectLinks) { this.objectLinks = objectLinks; return this; } public Builder additionalRegistrationAttributes(Map additionalRegistrationAttributes) { this.additionalRegistrationAttributes = additionalRegistrationAttributes; return this; } public Registration build() { return new Registration(Builder.this.registrationId, Builder.this.endpoint, Builder.this.identity, Builder.this.lwM2mVersion, Builder.this.lifeTimeInSec, Builder.this.smsNumber, this.bindingMode, this.objectLinks, this.registrationEndpointAddress, this.registrationDate, this.lastUpdate, this.additionalRegistrationAttributes); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy