/**
 * Copyright (c) 2016 Bosch Software Innovations GmbH.
 *
 * 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
 *
 * Contributors:
 *    Bosch Software Innovations GmbH - initial creation
 */
package org.eclipse.hono.util;

import java.security.Principal;

import io.vertx.proton.ProtonConnection;
import io.vertx.proton.ProtonLink;

/**
 * Constants used throughout Hono.
 *
 */
public final class Constants {

    /**
     * The name of the default tenant.
     */
    public static final String DEFAULT_TENANT = "DEFAULT_TENANT";

    /**
     * The key that an authenticated client's principal is stored under in a {@code ProtonConnection}'s
     * attachments.
     */
    public static final String KEY_CLIENT_PRINCIPAL = "CLIENT_PRINCIPAL";
    /**
     * The key that the (surrogate) ID of a connection is stored under in a {@code ProtonConnection}'s
     * and/or {@code ProtonLink}'s attachments.
     */
    public static final String KEY_CONNECTION_ID = "CONNECTION_ID";

    /**
     * The address that the ID of a connection that has been closed by a client is published to.
     */
    public static final String EVENT_BUS_ADDRESS_CONNECTION_CLOSED = "hono.connection.closed";

    /**
     * The default separator character for target addresses.
     */
    public static final String DEFAULT_PATH_SEPARATOR = "/";

    /**
     * The AMQP 1.0 port defined by IANA for TLS encrypted connections.
     */
    public static final int PORT_AMQPS = 5671;

    /**
     * The AMQP 1.0 port defined by IANA for unencrypted connections.
     */
    public static final int PORT_AMQP = 5672;

    /**
     * Default value for a port that is not explicitly configured.
     */
    public static final int PORT_UNCONFIGURED = -1;

    /**
     * The subject name to use for anonymous clients.
     */
    public static final String SUBJECT_ANONYMOUS = "ANONYMOUS";

    private Constants() {
    }

    /**
     * Gets the principal representing a connection's authenticated client.
     * 
     * @param con The connection to get the principal for.
     * @return The principal or {@code null} if the connection's client is not authenticated.
     */
    public static Principal getClientPrincipal(final ProtonConnection con) {
        return con.attachments().get(KEY_CLIENT_PRINCIPAL, Principal.class);
    }

    /**
     * Gets the (surrogate) identifier of the AMQP connection that a link is part of.
     * 
     * @param link The link to determine the connection id for.
     * @return The identifier retrieved from the link's <em>attachment</em> using key {@link #KEY_CONNECTION_ID}
     *         or {@code null} if the attachments do not contain a value for that a key.
     */
    public static String getConnectionId(final ProtonLink<?> link) {
        return link.attachments().get(KEY_CONNECTION_ID, String.class);
    }

    /**
     * Checks if a given tenant identifier is the {@code DEFAULT_TENANT}.
     * 
     * @param tenantId The identifier to check.
     * @return {@code true} if the given identifier is equal to {@link #DEFAULT_TENANT}.
     */
    public static boolean isDefaultTenant(final String tenantId) {
        return DEFAULT_TENANT.equals(tenantId);
    }
}

@@ -18,16 +18,22 @@
 (c) 2016
+, 2017
  Bosch S
@@ -451,16 +451,88 @@
 incipal;
+%0Aimport java.util.Objects;%0A%0Aimport org.apache.qpid.proton.engine.Record;
 %0A%0Aimport
@@ -2148,112 +2148,1037 @@
     
-private Constants() %7B%0A    %7D%0A%0A    /**%0A     * Gets the principal representing a connection's authenticated
+/**%0A     * The principal to use for anonymous clients.%0A     */%0A    public static final Principal PRINCIPAL_ANONYMOUS = new Principal() %7B%0A%0A        @Override%0A        public String getName() %7B%0A            return SUBJECT_ANONYMOUS;%0A        %7D%0A    %7D;%0A%0A    private Constants() %7B%0A    %7D%0A%0A    /**%0A     * Gets the principal representing an authenticated peer.%0A     * %0A     * @param record The attachments to retrieve the principal from.%0A     * @return The principal representing the authenticated client or %7B@link Constants#PRINCIPAL_ANONYMOUS%7D%0A     *         if the client has not been authenticated or record is %7B@code null%7D.%0A     */%0A    public static Principal getClientPrincipal(final Record record) %7B%0A%0A        if (record != null) %7B%0A            Principal client = record.get(KEY_CLIENT_PRINCIPAL, Principal.class);%0A            return client == null ? Constants.PRINCIPAL_ANONYMOUS : client;%0A        %7D else %7B%0A            return Constants.PRINCIPAL_ANONYMOUS;%0A        %7D%0A    %7D%0A%0A    /**%0A     * Gets the principal representing a connection's
  cli
@@ -3282,51 +3282,116 @@
 pal 
-or %7B@code null%7D if the connection's
+representing the authenticated client or %7B@link Constants#PRINCIPAL_ANONYMOUS%7D%0A     *         if the
  client 
 is n
@@ -3386,23 +3386,29 @@
  client 
-i
+ha
 s not 
+been 
 authenti
@@ -3410,24 +3410,84 @@
 henticated.%0A
+     * @throws NullPointerException if con is %7B@code null%7D.%0A
      */%0A    
@@ -3571,18 +3571,56 @@
     
-return 
+Record attachments = Objects.requireNonNull(
 con
+)
 .att
@@ -3633,49 +3633,54 @@
 ts()
-.get(KEY_CLIENT_PRINCIPAL, Principal.clas
+;%0A        return getClientPrincipal(attachment
 s);%0A

Add support for retrieving principal from link attachments.