DISPATCH-446 - Removed all annotations. Turned sslProfile to an entity. Updated documentation and add tests
diff --git a/doc/man/qdrouterd.conf.5.py b/doc/man/qdrouterd.conf.5.py
index 4c3877c..e71f7a1 100644
--- a/doc/man/qdrouterd.conf.5.py
+++ b/doc/man/qdrouterd.conf.5.py
@@ -35,9 +35,6 @@
 
     def __init__(self):
         super(ManPageWriter, self).__init__(sys.stdout, QdSchema())
-        self.sslProfileAttributes = []
-        self.connectionRoleAddrPortAttrs = []
-        self.connectionRoleAddrPortAnnotations = {}
 
     def attribute_type(self, attr, holder):
         # Don't show read-only attributes
@@ -47,37 +44,7 @@
                 return
         super(ManPageWriter, self).attribute_type(attr, holder, show_create=False, show_update=False)
 
-    def is_entity_connector_or_listener(self, entity_type):
-        if CONNECTOR == entity_type.name or LISTENER == entity_type.name:
-            return True
-        return False
 
-    def add_connector_listener_attributes(self, entity_type):
-
-        attr_type = AttributeType('name', type="string", defined_in=entity_type, create=True, update=True,
-                                  description="Unique name optionally assigned by user. Can be changed.")
-        entity_type.attributes['name'] = attr_type
-        self.connectionRoleAddrPortAttrs.append('name')
-
-        # We will have to add the connectionRole and addrPort attributes to listener and connector entities
-        # so that they show up in the man doc page.
-        for attr in self.connectionRoleAddrPortAnnotations.keys():
-            annotation = self.connectionRoleAddrPortAnnotations.get(attr)
-
-            for key in annotation.attributes.keys():
-                self.connectionRoleAddrPortAttrs.append(key)
-                annotation_attr = annotation.attributes.get(key)
-                if not annotation_attr.deprecated:
-                    attr_type = AttributeType(key, type=annotation_attr.type,
-                                              defined_in=entity_type,
-                                              create=True, update=True, description=annotation_attr.description)
-                    entity_type.attributes[key] = attr_type
-
-        # Artificially add an sslProfile
-        ssl_profile_attr = AttributeType("sslProfile", type="string", defined_in=entity_type,
-                                         create=True, update=True, description="name of the sslProfile ")
-
-        entity_type.attributes[u'sslProfile'] = ssl_profile_attr
 
     def man_page(self):
         self.writeln(r"""
@@ -163,54 +130,9 @@
 """)
 
         with self.section("Configuration Sections"):
-            for annotation in self.schema.annotations.itervalues():
-                # We are skipping connectionRole and addrPort annotations from the doc because it is
-                # confusing to the user
-                if "addrPort" in annotation.name or "connectionRole" in annotation.name:
-                    self.connectionRoleAddrPortAnnotations[annotation.short_name] = annotation
-                    continue
-                used_by = [e.short_name for e in self.schema.entity_types.itervalues()
-                           if annotation in e.annotations]
-                with self.section(annotation.short_name):
-                    if annotation.description:
-                        self.para(annotation.description)
-                    if used_by:
-                        self.para('Used by: **%s**.'%('**, **'.join(used_by)))
-
-                    if "sslProfile" in annotation.name:
-                        # sslProfileName is an internal attribute and should not show in the doc
-                        del annotation.attributes[u'sslProfileName']
-
-                        for attribute in annotation.attributes.keys():
-                            self.sslProfileAttributes.append(attribute)
-
-                        attrs = annotation.attributes
-
-                        annotation.attributes = OrderedDict()
-                        # The name has to appear first in the doc, the other attributes appear after name
-                        name_attr = AttributeType("name", type="string", defined_in=annotation,
-                                                  create=True, update=True, description="name of the sslProfile ")
-                        annotation.attributes[u'name'] = name_attr
-                        annotation.attributes.update(attrs)
-
-                    self.attribute_types(annotation)
 
             config = self.schema.entity_type("configurationEntity")
             for entity_type in self.schema.entity_types.itervalues():
-                if self.is_entity_connector_or_listener(entity_type):
-                    for sslProfileAttribute in self.sslProfileAttributes:
-                        del entity_type.attributes[sslProfileAttribute]
-                    current_attrs = entity_type.attributes
-
-                    entity_type.attributes = OrderedDict()
-                    # The attributes from the annotations must appear first in the doc
-                    self.add_connector_listener_attributes(entity_type)
-
-                    for attr in self.connectionRoleAddrPortAttrs:
-                        if current_attrs.get(attr):
-                            del current_attrs[attr]
-                    entity_type.attributes.update(current_attrs)
-
                 if config in entity_type.all_bases:
                     with self.section(entity_type.short_name):
                         if entity_type.description:
diff --git a/include/qpid/dispatch/connection_manager.h b/include/qpid/dispatch/connection_manager.h
index 4c2b319..28a944c 100644
--- a/include/qpid/dispatch/connection_manager.h
+++ b/include/qpid/dispatch/connection_manager.h
@@ -29,6 +29,7 @@
 typedef struct qd_connection_manager_t qd_connection_manager_t;
 typedef struct qd_config_connector_t qd_config_connector_t;
 typedef struct qd_config_listener_t qd_config_listener_t;
+typedef struct qd_config_ssl_profile_t qd_config_ssl_profile_t;
 
 typedef void (*qd_connection_manager_handler_t) (void *context, qd_connection_t *conn);
 
@@ -50,13 +51,19 @@
 /**
  * Free all the resources associated with a config listener
  */
-void qd_config_listener_free(qd_config_listener_t *cl);
+void qd_config_listener_free(qd_connection_manager_t *cm, qd_config_listener_t *cl);
+
+/**
+ * Free the SSL Profile. Only SSL Profiles that are not referenced from other connectors/listeners can be freed.
+ * @return true if the ssl_profile has been freed, false if it is being referenced and cannot be freed
+ */
+bool qd_config_ssl_profile_free(qd_connection_manager_t *cm, qd_config_ssl_profile_t *ssl_profile);
 
 
 /**
  * Free all the resources associated with a config connector
  */
-void qd_config_connector_free(qd_config_connector_t *cl);
+void qd_config_connector_free(qd_connection_manager_t *cm, qd_config_connector_t *cl);
 
 
 /**
diff --git a/include/qpid/dispatch/server.h b/include/qpid/dispatch/server.h
index 935cb17..03d4e4b 100644
--- a/include/qpid/dispatch/server.h
+++ b/include/qpid/dispatch/server.h
@@ -286,11 +286,6 @@
     int sasl_maxssf;
 
     /**
-     * SSL is enabled for this connection iff true.
-     */
-    bool ssl_enabled;
-
-    /**
      * Iff true, SSL/TLS must be used on the connection.
      */
     bool ssl_required;
@@ -365,6 +360,11 @@
     char *ssl_uid_format;
 
     /**
+     * The name of the related ssl profile.
+     */
+    char *ssl_profile;
+
+    /**
      * Full path to the file that contains the uid to display name mapping.
      */
     char *ssl_display_name_file;
diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json
index 325a954..ae1b901 100644
--- a/python/qpid_dispatch/management/qdrouter.json
+++ b/python/qpid_dispatch/management/qdrouter.json
@@ -3,116 +3,6 @@
 
     "prefix": "org.apache.qpid.dispatch",
 
-    "annotations": {
-
-        "addrPort": {
-            "description": "Attributes for internet address and port.",
-            "attributes": {
-                "addr": {
-                    "description":"(DEPRECATED)IP address: ipv4 or ipv6 literal or a host name. This attribute has been deprecated. Use host instead",
-                    "deprecated": true,
-                    "type": "string",
-                    "default": "127.0.0.1",
-                    "create": true
-                },
-                "host": {
-                    "description":"IP address: ipv4 or ipv6 literal or a host name",
-                    "type": "string",
-                    "default": "127.0.0.1",
-                    "create": true
-                },
-                "port": {
-                    "description": "Port number or symbolic service name.",
-                    "type": "string",
-                    "default": "amqp",
-                    "create": true
-
-                },
-                "protocolFamily": {
-                    "type": ["IPv4", "IPv6"],
-                    "required": false,
-                    "description": "['IPv4', 'IPv6'] IPv4: Internet Protocol version 4; IPv6: Internet Protocol version 6.  If not specified, the protocol family will be automatically determined from the address.",
-                    "create": true
-                }
-            }
-        },
-
-        "connectionRole": {
-            "description": "Attribute for the role of a connection.",
-            "attributes": {
-                "role": {
-                    "type": [
-                        "normal",
-                        "inter-router",
-                        "route-container",
-                        "on-demand"
-                    ],
-                    "default": "normal",
-                    "description": "The role of an established connection. In the normal role, the connection is assumed to be used for AMQP clients that are doing normal message delivery over the connection.  In the inter-router role, the connection is assumed to be to another router in the network.  Inter-router discovery and routing protocols can only be used over inter-router connections. route-container role can be used for router-container connections, for example, a router-broker connection. on-demand role has been deprecated.",
-                    "create": true
-                },
-                "cost": {
-                    "type": "integer",
-                    "default": "1",
-                    "required": false,
-                    "create": true,
-                    "description": "For the 'inter-router' role only.  This value assigns a cost metric to the inter-router connection.  The default (and minimum) value is one.  Higher values represent higher costs.  The cost is used to influence the routing algorithm as it attempts to use the path with the lowest total cost from ingress to egress."
-                }
-            }
-        },
-
-        "sslProfile": {
-            "description":"Attributes for setting TLS/SSL configuration for connections.",
-            "referential": true,
-            "attributes": {
-                "certDb": {
-                    "type": "path",
-                    "description": "The absolute path to the database that contains the public certificates of trusted certificate authorities (CA).",
-                    "create": true
-                },
-                "certFile": {
-                    "type": "path",
-                    "description": "The absolute path to the file containing the PEM-formatted public certificate to be used on the local end of any connections using this profile.",
-                    "create": true
-
-                },
-                "keyFile": {
-                    "type": "path",
-                    "description": "The absolute path to the file containing the PEM-formatted private key for the above certificate.",
-                    "create": true
-
-                },
-                "passwordFile": {
-                    "type": "path",
-                    "description": "If the above private key is password protected, this is the absolute path to a file containing the password that unlocks the certificate key.",
-                    "create": true
-
-                },
-                "password": {
-                    "type": "string",
-                    "description": "An alternative to storing the password in a file referenced by passwordFile is to supply the password right here in the configuration file.  This option can be used by supplying the password in the 'password' option.  Don't use both password and passwordFile in the same profile.",
-                    "create": true
-
-                },
-                "uidFormat": {
-                    "type": "string",
-                    "description": "A list of x509 client certificate fields that will be used to build a string that will uniquely identify the client certificate owner. For e.g. a value of 'cou' indicates that the uid will consist of c - common name concatenated with o - organization-company name concatenated with u - organization unit; or a value of 'o2' indicates that the uid will consist of o (organization name) concatenated with 2 (the sha256 fingerprint of the entire certificate) . Allowed values can be any combination of 'c'( ISO3166 two character country code), 's'(state or province), 'l'(Locality; generally - city), 'o'(Organization - Company Name), 'u'(Organization Unit - typically certificate type or brand), 'n'(CommonName - typically a user name for client certificates) and '1'(sha1 certificate fingerprint, as displayed in the fingerprints section when looking at a certificate with say a web browser is the hash of the entire certificate) and 2 (sha256 certificate fingerprint) and 5 (sha512 certificate fingerprint). ",
-                    "create": true
-                },
-                "displayNameFile": {
-                    "type": "string",
-                    "description": "The absolute path to the file containing the unique id to dispay name mapping",
-                    "create": true
-                },
-                "sslProfileName": {
-                    "type": "string",
-                    "description": "The name of the ssl profile. This is for internal use only. Use the 'name' attribute to assign a name to an sslProfile section ",
-                    "create": false
-                }
-            }
-        }
-    },
-
     "entityTypes": {
 
         "entity": {
@@ -356,7 +246,7 @@
                     }
                 },
                 "GET-ATTRIBUTES": {
-                    "description": "Get the set of entity types and the annotations they implement",
+                    "description": "Get the set of entity types",
                     "request": {
                         "properties": {
                             "identity": {
@@ -478,59 +368,11 @@
             "attributes": {}
         },
 
-        "container": {
-            "description":"(DEPRECATED)Attributes related to the AMQP container. This entity has been deprecated. Use the router entity instead.",
-            "extends": "configurationEntity",
-            "deprecated": true,
-            "singleton": true,
-            "attributes": {
-
-                "containerName": {
-                    "type": "string",
-                    "description": "The  name of the AMQP container.  If not specified, the container name will be set to a value of the container's choosing.  The automatically assigned container name is not guaranteed to be persistent across restarts of the container.",
-                    "create": true
-
-                },
-                "workerThreads": {
-                    "type": "integer",
-                    "default": 4,
-                    "description": "The number of threads that will be created to process message traffic and other application work (timers, non-amqp file descriptors, etc.) .",
-                    "create": true
-
-                },
-                "debugDump": {
-                    "type": "path",
-                    "description": "A file to dump debugging information that can't be logged normally.",
-                    "create": true
-
-                },
-                "saslConfigPath": {
-                    "type": "path",
-                    "description": "Absolute path to the SASL configuration file.",
-                    "required": false,
-                    "create": true
-                },
-                "saslConfigName": {
-                    "type": "string",
-                    "description": "Name of the SASL configuration.  This string + '.conf' is the name of the configuration file.",
-                    "required": false,
-                    "create": true
-                }
-            }
-        },
-
         "router": {
             "description":"Tracks peer routers and computes routes to destinations.",
             "extends": "configurationEntity",
             "singleton": true,
             "attributes": {
-                "routerId": {
-                    "description":"(DEPRECATED) Router's unique identity. This attribute has been deprecated. Use id instead",
-                    "type": "string",
-                    "required": false,
-                    "deprecated": true,
-                    "create": true
-                },
                 "id": {
                     "description":"Router's unique identity. One of id or routerId is required. The router will fail to start without id or routerId",
                     "type": "string",
@@ -581,14 +423,6 @@
                     "description": "Time in seconds after which link state is declared stale if no RA is received.",
                     "create": true
                 },
-                "mobileAddrMaxAge": {
-                    "type": "integer",
-                    "default": 60,
-                    "deprecated": true,
-                    "description": "(DEPRECATED) This value is no longer used in the router.",
-                    "create": true
-                },
-
                 "addrCount": {
                     "type":
                     "integer", "description":"Number of addresses known to the router.",
@@ -629,20 +463,120 @@
                     "default": "qdrouterd",
                     "required": false,
                     "create": true
+                },
+                "routerId": {
+                    "description":"(DEPRECATED) Router's unique identity. This attribute has been deprecated. Use id instead",
+                    "type": "string",
+                    "required": false,
+                    "deprecated": true,
+                    "create": true
+                },
+                "mobileAddrMaxAge": {
+                    "type": "integer",
+                    "default": 60,
+                    "deprecated": true,
+                    "description": "(DEPRECATED) This value is no longer used in the router.",
+                    "create": true
+                }                                
+            }
+        },
+        
+        "sslProfile": {
+            "description":"Attributes for setting TLS/SSL configuration for connections.",
+            "referential": true,
+            "extends": "configurationEntity",
+            "operations": ["CREATE", "DELETE"],
+            "attributes": {
+                "certDb": {
+                    "type": "path",
+                    "description": "The absolute path to the database that contains the public certificates of trusted certificate authorities (CA).",
+                    "create": true
+                },
+                "certFile": {
+                    "type": "path",
+                    "description": "The absolute path to the file containing the PEM-formatted public certificate to be used on the local end of any connections using this profile.",
+                    "create": true
+
+                },
+                "keyFile": {
+                    "type": "path",
+                    "description": "The absolute path to the file containing the PEM-formatted private key for the above certificate.",
+                    "create": true
+
+                },
+                "passwordFile": {
+                    "type": "path",
+                    "description": "If the above private key is password protected, this is the absolute path to a file containing the password that unlocks the certificate key.",
+                    "create": true
+
+                },
+                "password": {
+                    "type": "string",
+                    "description": "An alternative to storing the password in a file referenced by passwordFile is to supply the password right here in the configuration file.  This option can be used by supplying the password in the 'password' option.  Don't use both password and passwordFile in the same profile.",
+                    "create": true
+
+                },
+                "uidFormat": {
+                    "type": "string",
+                    "description": "A list of x509 client certificate fields that will be used to build a string that will uniquely identify the client certificate owner. For e.g. a value of 'cou' indicates that the uid will consist of c - common name concatenated with o - organization-company name concatenated with u - organization unit; or a value of 'o2' indicates that the uid will consist of o (organization name) concatenated with 2 (the sha256 fingerprint of the entire certificate) . Allowed values can be any combination of 'c'( ISO3166 two character country code), 's'(state or province), 'l'(Locality; generally - city), 'o'(Organization - Company Name), 'u'(Organization Unit - typically certificate type or brand), 'n'(CommonName - typically a user name for client certificates) and '1'(sha1 certificate fingerprint, as displayed in the fingerprints section when looking at a certificate with say a web browser is the hash of the entire certificate) and 2 (sha256 certificate fingerprint) and 5 (sha512 certificate fingerprint). ",
+                    "create": true
+                },
+                "displayNameFile": {
+                    "type": "string",
+                    "description": "The absolute path to the file containing the unique id to dispay name mapping",
+                    "create": true
                 }
             }
         },
-
+        
         "listener": {
             "description": "Listens for incoming connections to the router.",
             "extends": "configurationEntity",
             "operations": ["CREATE", "DELETE"],
-            "annotations": [
-                "addrPort",
-                "connectionRole",
-                "sslProfile"
-            ],
             "attributes": {
+                "host": {
+                    "description":"IP address: ipv4 or ipv6 literal or a host name",
+                    "type": "string",
+                    "default": "127.0.0.1",
+                    "create": true
+                },
+                "port": {
+                    "description": "Port number or symbolic service name.",
+                    "type": "string",
+                    "default": "amqp",
+                    "create": true
+
+                },
+                "protocolFamily": {
+                    "type": ["IPv4", "IPv6"],
+                    "required": false,
+                    "description": "['IPv4', 'IPv6'] IPv4: Internet Protocol version 4; IPv6: Internet Protocol version 6.  If not specified, the protocol family will be automatically determined from the address.",
+                    "create": true
+                },
+                "role": {
+                    "type": [
+                        "normal",
+                        "inter-router",
+                        "route-container",
+                        "on-demand"
+                    ],
+                    "default": "normal",
+                    "description": "The role of an established connection. In the normal role, the connection is assumed to be used for AMQP clients that are doing normal message delivery over the connection.  In the inter-router role, the connection is assumed to be to another router in the network.  Inter-router discovery and routing protocols can only be used over inter-router connections. route-container role can be used for router-container connections, for example, a router-broker connection. on-demand role has been deprecated.",
+                    "create": true
+                },
+                "cost": {
+                    "type": "integer",
+                    "default": "1",
+                    "required": false,
+                    "create": true,
+                    "description": "For the 'inter-router' role only.  This value assigns a cost metric to the inter-router connection.  The default (and minimum) value is one.  Higher values represent higher costs.  The cost is used to influence the routing algorithm as it attempts to use the path with the lowest total cost from ingress to egress."
+                },                     
+                "sslProfile": {
+                    "type": "string",
+                    "required": false,
+                    "description": "Name of the sslProfile.",
+                    "create": true
+                },            
                 "saslMechanisms": {
                     "type": "string",
                     "required": false,
@@ -684,24 +618,6 @@
                     "description": "The idle timeout, in seconds, for connections through this listener.  If no frames are received on the connection for this time interval, the connection shall be closed.",
                     "create": true
                 },
-                "requirePeerAuth": {
-                    "type": "boolean",
-                    "create": true,
-                    "deprecated": true,
-                    "description": "(DEPRECATED) This attribute is now controlled by the authenticatePeer attribute."
-                },
-                "allowUnsecured": {
-                    "type": "boolean",
-                    "create": true,
-                    "deprecated": true,
-                    "description": "(DEPRECATED) This attribute is now controlled by the requireEncryption attribute."
-                },
-                "allowNoSasl": {
-                    "type": "boolean",
-                    "create": true,
-                    "deprecated": true,
-                    "description": "(DEPRECATED) This attribute is now controlled by the authenticatePeer attribute."
-                },
                 "stripAnnotations": {
                     "type": ["in", "out", "both", "no"],
                     "default": "both",
@@ -713,7 +629,32 @@
                     "create": true,
                     "required": false,
                     "description": "The capacity of links within this connection, in terms of message deliveries.  The capacity is the number of messages that can be in-flight concurrently for each link."
-                }
+                },
+                "addr": {
+                    "description":"(DEPRECATED)IP address: ipv4 or ipv6 literal or a host name. This attribute has been deprecated. Use host instead",
+                    "deprecated": true,
+                    "type": "string",
+                    "default": "127.0.0.1",
+                    "create": true
+                },
+                "allowNoSasl": {
+                    "type": "boolean",
+                    "create": true,
+                    "deprecated": true,
+                    "description": "(DEPRECATED) This attribute is now controlled by the authenticatePeer attribute."
+                },
+                "requirePeerAuth": {
+                    "type": "boolean",
+                    "create": true,
+                    "deprecated": true,
+                    "description": "(DEPRECATED) This attribute is now controlled by the authenticatePeer attribute."
+                },
+                "allowUnsecured": {
+                    "type": "boolean",
+                    "create": true,
+                    "deprecated": true,
+                    "description": "(DEPRECATED) This attribute is now controlled by the requireEncryption attribute."
+                }                                               
             }
         },
 
@@ -721,12 +662,52 @@
             "description": "Establishes an outgoing connection from the router.",
             "extends": "configurationEntity",
             "operations": ["CREATE", "DELETE"],
-            "annotations": [
-                "addrPort",
-                "connectionRole",
-                "sslProfile"
-            ],
             "attributes": {
+                "host": {
+                    "description":"IP address: ipv4 or ipv6 literal or a host name",
+                    "type": "string",
+                    "default": "127.0.0.1",
+                    "create": true
+                },
+                "port": {
+                    "description": "Port number or symbolic service name.",
+                    "type": "string",
+                    "default": "amqp",
+                    "create": true
+
+                },
+                "protocolFamily": {
+                    "type": ["IPv4", "IPv6"],
+                    "required": false,
+                    "description": "['IPv4', 'IPv6'] IPv4: Internet Protocol version 4; IPv6: Internet Protocol version 6.  If not specified, the protocol family will be automatically determined from the address.",
+                    "create": true
+                },
+                
+                "role": {
+                    "type": [
+                        "normal",
+                        "inter-router",
+                        "route-container",
+                        "on-demand"
+                    ],
+                    "default": "normal",
+                    "description": "The role of an established connection. In the normal role, the connection is assumed to be used for AMQP clients that are doing normal message delivery over the connection.  In the inter-router role, the connection is assumed to be to another router in the network.  Inter-router discovery and routing protocols can only be used over inter-router connections. route-container role can be used for router-container connections, for example, a router-broker connection. on-demand role has been deprecated.",
+                    "create": true
+                },
+                "cost": {
+                    "type": "integer",
+                    "default": "1",
+                    "required": false,
+                    "create": true,
+                    "description": "For the 'inter-router' role only.  This value assigns a cost metric to the inter-router connection.  The default (and minimum) value is one.  Higher values represent higher costs.  The cost is used to influence the routing algorithm as it attempts to use the path with the lowest total cost from ingress to egress."
+                },                
+                            
+                "sslProfile": {
+                    "type": "string",
+                    "required": false,
+                    "description": "Name of the sslProfile.",
+                    "create": true
+                },            
                 "saslMechanisms": {
                     "type": "string",
                     "required": false,
@@ -781,7 +762,14 @@
                     "description": "The password that the connector is using to connect to a peer.",
                     "create": true,
                     "hidden": true
-                }
+                },
+                "addr": {
+                    "description":"(DEPRECATED)IP address: ipv4 or ipv6 literal or a host name. This attribute has been deprecated. Use host instead",
+                    "deprecated": true,
+                    "type": "string",
+                    "default": "127.0.0.1",
+                    "create": true
+                }                
             }
         },
 
@@ -832,106 +820,6 @@
             }
         },
 
-        "fixedAddress": {
-            "description":"(DEPRECATED) Establishes treatment for addresses starting with a prefix. This entity has been deprecated. Use address instead",
-            "extends": "configurationEntity",
-            "deprecated": true,
-            "operations": ["CREATE"],
-            "attributes": {
-                "prefix": {
-                    "type": "string",
-                    "required": true,
-                    "description": "The address prefix (always starting with '/').",
-                    "create": true
-                },
-                "phase": {
-                    "type": "integer",
-                    "description": "The phase of a multi-hop address passing through one or more waypoints.",
-                    "create": true
-                },
-                "fanout": {
-                    "type": [
-                        "multiple",
-                        "single"
-                    ],
-                    "default": "multiple",
-                    "description": "One of 'multiple' or 'single'.  Multiple fanout is a non-competing pattern.  If there are multiple consumers using the same address, each consumer will receive its own copy of every message sent to the address.  Single fanout is a competing pattern where each message is sent to only one consumer.",
-                    "create": true
-                },
-                "bias": {
-                    "type": [
-                        "closest",
-                        "spread"
-                    ],
-                    "default": "closest",
-                    "description": "Only if fanout is single.  One of 'closest' or 'spread'.  Closest bias means that messages to an address will always be delivered to the closest (lowest cost) subscribed consumer. Spread bias will distribute the messages across subscribers in an approximately even manner.",
-                    "create": true
-                }
-            }
-        },
-
-        "waypoint": {
-            "description":"(DEPRECATED) A remote node that messages for an address pass through. This entity has been deprecated. Use autoLink instead",
-            "deprecated": true,
-            "extends": "configurationEntity",
-            "operations": ["CREATE", "DELETE"],
-            "attributes": {
-                "address": {
-                    "description":"The AMQP address of the waypoint.",
-                    "type": "string",
-                    "required": true,
-                    "create": true
-                },
-                "connector": {
-                    "description":"The name of the on-demand connector used to reach the waypoint's container.",
-                    "type": "string",
-                    "required": true,
-                    "create": true
-                },
-                "inPhase": {
-                    "description":"The phase of the address as it is routed _to_ the waypoint.",
-                    "type": "integer",
-                    "default": -1,
-                    "create": true
-                },
-                "outPhase": {
-                    "description":"The phase of the address as it is routed _from_ the waypoint.",
-                    "type": "integer",
-                    "default": -1,
-                    "create": true
-                }
-            }
-        },
-
-        "linkRoutePattern": {
-            "description":"(DEPRECATED) An address pattern to match against link sources and targets to cause the router to link-route the attach across the network to a remote node. This entity has been deprecated. Use linkRoute instead",
-            "deprecated": true,
-            "extends": "configurationEntity",
-            "operations": ["CREATE"],
-            "attributes": {
-                "prefix": {
-                    "description":"An address prefix to match against target and source addresses.  This pattern must be of the form '<text>.<text1>.<textN>' or '<text>' or '<text>.' and matches any address that contains that prefix.  For example, if the prefix is set to org.apache (or org.apache.), any address that has the prefix 'org.apache'  (like org.apache.dev) will match. Note that a prefix must not start with a (.), can end in a (.) and can contain zero or more dots (.).  Any characters between the dots are simply treated as part of the address",
-                    "type": "string",
-                    "required": true,
-                    "create": true
-                },
-                "dir": {
-                    "description":"Link direction for match: 'in' matches only links inbound to the client; 'out' matches only links outbound from the client; 'both' matches any link.",
-                    "type": ["in", "out", "both"],
-                    "required": false,
-                    "default": "both",
-                    "create": true
-                },
-                "connector": {
-                    "description":"The name of the on-demand connector used to reach the target node's container.  If this value is not provided, it means that the target container is expected to be connected to a different router in the network.  This prevents links to a link-routable address from being misinterpreted as message-routing links when there is no route to a valid destination available.",
-                    "type": "string",
-                    "required": false,
-                    "default": "",
-                    "create": true
-                }
-            }
-        },
-
         "router.config.address": {
             "description": "Entity type for address configuration.  This is used to configure the treatment of message-routed deliveries within a particular address-space.  The configuration controls distribution and address phasing.",
             "extends": "configurationEntity",
@@ -1452,6 +1340,147 @@
                 "receiverDenied": {"type": "integer", "graph": true}
             }
         },
+        
+        "container": {
+            "description":"(DEPRECATED)Attributes related to the AMQP container. This entity has been deprecated. Use the router entity instead.",
+            "extends": "configurationEntity",
+            "deprecated": true,
+            "singleton": true,
+            "attributes": {
+
+                "containerName": {
+                    "type": "string",
+                    "description": "The  name of the AMQP container.  If not specified, the container name will be set to a value of the container's choosing.  The automatically assigned container name is not guaranteed to be persistent across restarts of the container.",
+                    "create": true
+
+                },
+                "workerThreads": {
+                    "type": "integer",
+                    "default": 4,
+                    "description": "The number of threads that will be created to process message traffic and other application work (timers, non-amqp file descriptors, etc.) .",
+                    "create": true
+
+                },
+                "debugDump": {
+                    "type": "path",
+                    "description": "A file to dump debugging information that can't be logged normally.",
+                    "create": true
+
+                },
+                "saslConfigPath": {
+                    "type": "path",
+                    "description": "Absolute path to the SASL configuration file.",
+                    "required": false,
+                    "create": true
+                },
+                "saslConfigName": {
+                    "type": "string",
+                    "description": "Name of the SASL configuration.  This string + '.conf' is the name of the configuration file.",
+                    "required": false,
+                    "create": true
+                }
+            }
+        },  
+
+        "waypoint": {
+            "description":"(DEPRECATED) A remote node that messages for an address pass through. This entity has been deprecated. Use autoLink instead",
+            "deprecated": true,
+            "extends": "configurationEntity",
+            "operations": ["CREATE", "DELETE"],
+            "attributes": {
+                "address": {
+                    "description":"The AMQP address of the waypoint.",
+                    "type": "string",
+                    "required": true,
+                    "create": true
+                },
+                "connector": {
+                    "description":"The name of the on-demand connector used to reach the waypoint's container.",
+                    "type": "string",
+                    "required": true,
+                    "create": true
+                },
+                "inPhase": {
+                    "description":"The phase of the address as it is routed _to_ the waypoint.",
+                    "type": "integer",
+                    "default": -1,
+                    "create": true
+                },
+                "outPhase": {
+                    "description":"The phase of the address as it is routed _from_ the waypoint.",
+                    "type": "integer",
+                    "default": -1,
+                    "create": true
+                }
+            }
+        },        
+        
+        "fixedAddress": {
+            "description":"(DEPRECATED) Establishes treatment for addresses starting with a prefix. This entity has been deprecated. Use address instead",
+            "extends": "configurationEntity",
+            "deprecated": true,
+            "operations": ["CREATE"],
+            "attributes": {
+                "prefix": {
+                    "type": "string",
+                    "required": true,
+                    "description": "The address prefix (always starting with '/').",
+                    "create": true
+                },
+                "phase": {
+                    "type": "integer",
+                    "description": "The phase of a multi-hop address passing through one or more waypoints.",
+                    "create": true
+                },
+                "fanout": {
+                    "type": [
+                        "multiple",
+                        "single"
+                    ],
+                    "default": "multiple",
+                    "description": "One of 'multiple' or 'single'.  Multiple fanout is a non-competing pattern.  If there are multiple consumers using the same address, each consumer will receive its own copy of every message sent to the address.  Single fanout is a competing pattern where each message is sent to only one consumer.",
+                    "create": true
+                },
+                "bias": {
+                    "type": [
+                        "closest",
+                        "spread"
+                    ],
+                    "default": "closest",
+                    "description": "Only if fanout is single.  One of 'closest' or 'spread'.  Closest bias means that messages to an address will always be delivered to the closest (lowest cost) subscribed consumer. Spread bias will distribute the messages across subscribers in an approximately even manner.",
+                    "create": true
+                }
+            }
+        },         
+        
+        "linkRoutePattern": {
+            "description":"(DEPRECATED) An address pattern to match against link sources and targets to cause the router to link-route the attach across the network to a remote node. This entity has been deprecated. Use linkRoute instead",
+            "deprecated": true,
+            "extends": "configurationEntity",
+            "operations": ["CREATE"],
+            "attributes": {
+                "prefix": {
+                    "description":"An address prefix to match against target and source addresses.  This pattern must be of the form '<text>.<text1>.<textN>' or '<text>' or '<text>.' and matches any address that contains that prefix.  For example, if the prefix is set to org.apache (or org.apache.), any address that has the prefix 'org.apache'  (like org.apache.dev) will match. Note that a prefix must not start with a (.), can end in a (.) and can contain zero or more dots (.).  Any characters between the dots are simply treated as part of the address",
+                    "type": "string",
+                    "required": true,
+                    "create": true
+                },
+                "dir": {
+                    "description":"Link direction for match: 'in' matches only links inbound to the client; 'out' matches only links outbound from the client; 'both' matches any link.",
+                    "type": ["in", "out", "both"],
+                    "required": false,
+                    "default": "both",
+                    "create": true
+                },
+                "connector": {
+                    "description":"The name of the on-demand connector used to reach the target node's container.  If this value is not provided, it means that the target container is expected to be connected to a different router in the network.  This prevents links to a link-routable address from being misinterpreted as message-routing links when there is no route to a valid destination available.",
+                    "type": "string",
+                    "required": false,
+                    "default": "",
+                    "create": true
+                }
+            }
+        },             
 
         "dummy": {
             "description": "Dummy entity for test purposes.",
diff --git a/python/qpid_dispatch/management/qdrouter.json.readme.txt b/python/qpid_dispatch/management/qdrouter.json.readme.txt
index b765955..ea9a139 100644
--- a/python/qpid_dispatch/management/qdrouter.json.readme.txt
+++ b/python/qpid_dispatch/management/qdrouter.json.readme.txt
@@ -19,7 +19,7 @@
 
 # The qdrouter management schema
 
-The schema `qdrouterd.json` is a JSON format file that defines annotations and
+The schema `qdrouterd.json` is a JSON format file that defines
 entity types of the Qpid Dispatch Router management model.  The model is based
 on the AMQP management specification.
 
@@ -30,7 +30,7 @@
 
 - "entityTypes": map of entity type names to definitions (see below)
 
-Annotation and entity type definition maps have the following keys:
+Entity type definition maps have the following keys:
 
 - "description": documentation string.
 - "fullName": if true use the type name as-is, do not apply the schema prefix.
@@ -41,7 +41,6 @@
 Entity type definitions also have these fields:
 
 - "extends": Name of base type. The new type includes attributes, operations and operationDefs from the base type.
-- "annotations": List of annotation names. The new type includes operations and attributes from all the annotations.
 
 Operation definitions are optional, you can call an operation in the operations
 list without an operation definition. They have the following fields:
diff --git a/python/qpid_dispatch/management/qdrouter.policyRuleset.settings.txt b/python/qpid_dispatch/management/qdrouter.policyRuleset.settings.txt
index 2f40fef..c0c4208 100644
--- a/python/qpid_dispatch/management/qdrouter.policyRuleset.settings.txt
+++ b/python/qpid_dispatch/management/qdrouter.policyRuleset.settings.txt
@@ -17,7 +17,7 @@
 
 
 
-The schema `qdrouterd.json` is a JSON format file that defines annotations and
+The schema `qdrouterd.json` is a JSON format file that defines
 entity types of the Qpid Dispatch Router management model.  The model is based
 on the AMQP management specification.
 
diff --git a/python/qpid_dispatch_internal/dispatch.py b/python/qpid_dispatch_internal/dispatch.py
index 3ad4436..11fe6ed 100644
--- a/python/qpid_dispatch_internal/dispatch.py
+++ b/python/qpid_dispatch_internal/dispatch.py
@@ -61,9 +61,11 @@
         self._prototype(self.qd_dispatch_prepare, None, [self.qd_dispatch_p])
         self._prototype(self.qd_dispatch_configure_listener, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
         self._prototype(self.qd_dispatch_configure_connector, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
+        self._prototype(self.qd_dispatch_configure_ssl_profile, ctypes.c_void_p, [self.qd_dispatch_p, py_object])
 
         self._prototype(self.qd_connection_manager_delete_listener, None, [self.qd_dispatch_p, ctypes.c_void_p])
         self._prototype(self.qd_connection_manager_delete_connector, None, [self.qd_dispatch_p, ctypes.c_void_p])
+        self._prototype(self.qd_connection_manager_delete_ssl_profile, ctypes.c_bool, [self.qd_dispatch_p, ctypes.c_void_p])
 
         self._prototype(self.qd_dispatch_configure_fixed_address, None, [self.qd_dispatch_p, py_object])
         self._prototype(self.qd_dispatch_configure_waypoint, None, [self.qd_dispatch_p, py_object])
diff --git a/python/qpid_dispatch_internal/management/agent.py b/python/qpid_dispatch_internal/management/agent.py
index c8ebf65..6e4b7fc 100644
--- a/python/qpid_dispatch_internal/management/agent.py
+++ b/python/qpid_dispatch_internal/management/agent.py
@@ -52,6 +52,7 @@
 
 ## Threading:
 
+
 The agent is locked to be thread safe, called in the following threads:
 - Reading configuration file in initialization thread (no contention).
 - Management requests arriving in multiple, concurrent connection threads.
@@ -75,7 +76,7 @@
 from subprocess import Popen
 from ..dispatch import IoAdapter, LogAdapter, LOG_INFO, LOG_WARNING, LOG_DEBUG, LOG_ERROR, TREATMENT_ANYCAST_CLOSEST
 from qpid_dispatch.management.error import ManagementError, OK, CREATED, NO_CONTENT, STATUS_TEXT, \
-    BadRequestStatus, InternalServerErrorStatus, NotImplementedStatus, NotFoundStatus
+    BadRequestStatus, InternalServerErrorStatus, NotImplementedStatus, NotFoundStatus, ForbiddenStatus
 from qpid_dispatch.management.entity import camelcase
 from .schema import ValidationError, SchemaEntity, EntityType
 from .qdrouter import QdSchema
@@ -345,6 +346,23 @@
         return "%s:%s" % (entity.attributes['host'], entity.attributes['port'])
 
 
+class SslProfileEntity(EntityAdapter):
+    def create(self):
+        return self._qd.qd_dispatch_configure_ssl_profile(self._dispatch, self)
+
+    def _delete(self):
+        deleted = self._qd.qd_connection_manager_delete_ssl_profile(self._dispatch, self._implementations[0].key)
+        # SSL Profiles cannot be deleted if they are referenced by a connector/listener.
+        if not deleted:
+            raise ForbiddenStatus("SSL Profile is referenced by other listeners/connectors. Delete the associated "
+                                  "listeners/connectors before deleting the SSL Profile")
+
+    def _identifier(self):
+        return self.name
+
+    def __str__(self):
+        return super(SslProfileEntity, self).__str__().replace("Entity(", "SslProfileEntity(")
+
 class ListenerEntity(EntityAdapter):
     def create(self):
         config_listener = self._qd.qd_dispatch_configure_listener(self._dispatch, self)
@@ -653,9 +671,10 @@
                          for t in self._schema.by_type(type)))
 
     def get_annotations(self, request):
-        type = self.requested_type(request)
-        return (OK, dict((t.name, [a.name for a in t.annotations])
-                         for t in self._schema.by_type(type)))
+        """
+        We are not supporting any annotations at the moment.
+        """
+        return (OK, {})
 
     def get_operations(self, request):
         type = self.requested_type(request)
diff --git a/python/qpid_dispatch_internal/management/config.py b/python/qpid_dispatch_internal/management/config.py
index 28ba91b..a7b82c7 100644
--- a/python/qpid_dispatch_internal/management/config.py
+++ b/python/qpid_dispatch_internal/management/config.py
@@ -83,32 +83,6 @@
         sections = json.loads(js_text)
         return sections
 
-
-    def _expand(self, content):
-        """
-        Find annotation sections (defined by schema) in the content,
-        expand references and remove the annotation sections.
-        @param content: ((sectionName:{name:value...}))
-        """
-        def _expand_section(section, annotations):
-            """Expand one section"""
-            attrs = section[1]
-
-            for k in attrs.keys(): # Iterate over keys() because we will modify attr
-                inc = [i[1] for i in annotations if i[0] == k and i[1]['name'] == attrs[k]]
-                if inc:
-                    assert len(inc) == 1
-                    inc = copy(inc[0])
-                    if k == u'sslProfile':
-                        inc[u'sslProfileName'] = inc[u'name']
-                    del inc['name']
-                    attrs.update(inc)
-                    del attrs[k] # Delete the annotation attribute.
-            return section
-        annotations = [s for s in content if self.schema.annotation(s[0], error=False)]
-        return [_expand_section(s, annotations) for s in content
-                if self.schema.is_configuration(self.schema.entity_type(s[0], False))]
-
     def get_config_types(self):
         return self.config_types
 
@@ -128,7 +102,6 @@
             for et in self.get_config_types():
                 if et.singleton and not [s for s in sections if s[0] == et.short_name]:
                     sections.append((et.short_name, {}))
-            sections = self._expand(sections)
             entities = [dict(type=self.schema.long_name(s[0]), **s[1]) for s in sections]
             self.schema.validate_all(entities)
             self.entities = entities
@@ -185,15 +158,15 @@
     policyDir = config.by_type('policy')[0]['policyDir']
     policyDefaultVhost = config.by_type('policy')[0]['defaultVhost']
     # Remaining configuration
-    for t in "fixedAddress", "listener", "connector", "waypoint", "linkRoutePattern", \
+    for t in "sslProfile", "fixedAddress", "listener", "connector", "waypoint", "linkRoutePattern", \
              "router.config.address", "router.config.linkRoute", "router.config.autoLink", \
              "policy", "vhost":
         for a in config.by_type(t):
             configure(a)
-            if t == "listener":
+            if t == "sslProfile":
                 display_file_name = a.get('displayNameFile')
                 if display_file_name:
-                    ssl_profile_name = a.get('sslProfileName')
+                    ssl_profile_name = a.get('name')
                     displayname_service.add(ssl_profile_name, display_file_name)
 
     for e in config.entities:
diff --git a/python/qpid_dispatch_internal/management/schema.py b/python/qpid_dispatch_internal/management/schema.py
index 5338f37..7559c73 100644
--- a/python/qpid_dispatch_internal/management/schema.py
+++ b/python/qpid_dispatch_internal/management/schema.py
@@ -200,8 +200,7 @@
     @ivar value: Fixed value for the attribute. Can be a reference.
     @ivar unique: True if the attribute value is unique.
     @ivar description: Description of the attribute type.
-    @ivar annotation: Annotation section or None
-    @ivar defined_in: Annotation or EntityType in which this attribute is defined.
+    @ivar defined_in: EntityType in which this attribute is defined.
     @ivar create: If true the attribute can be set by CREATE.
     @ivar update: If true the attribute can be modified by UPDATE.
     @ivar graph: If true the attribute could be graphed by a console.
@@ -319,16 +318,14 @@
     @ivar short_name: Un-prefixed short name.
     @ivar attributes: Map of L{AttributeType} for entity.
     @ivar singleton: If true only one entity of this type is allowed.
-    @ivar referential: True if an entity/annotation can be referred to by name.
-    @ivar annotations: List of names of sections annotationd by this entity.
+    @ivar referential: True if an entity can be referred to by name from another entity.
     """
     def __init__(self, name, schema, attributes=None, operations=None, operationDefs=None, description="",
-                 fullName=True, singleton=False, deprecated=False, annotations=None, extends=None, referential=False, **kwargs):
+                 fullName=True, singleton=False, deprecated=False, extends=None, referential=False, **kwargs):
         """
         @param name: name of the entity type.
         @param schema: schema for this type.
         @param singleton: True if entity type is a singleton.
-        @param annotations: List of names of annotation types for this entity.
         @param attributes: Map of attributes {name: {type:, default:, required:, unique:}}
         @param description: Human readable description.
         @param operations: Allowed operations, list of operation names.
@@ -347,11 +344,10 @@
             self.attributes = OrderedDict((k, AttributeType(k, defined_in=self, **v))
                                               for k, v in (attributes or {}).iteritems())
             self.operations = operations or []
-            # Bases and annotations are resolved in self.init()
+            # Bases are resolved in self.init()
             self.base = extends
             self.all_bases = []
-            self.annotations = annotations or []
-            # List of annotations that are singletons
+
             self.references = []
             self.singleton = singleton
             self.deprecated = deprecated
@@ -365,7 +361,7 @@
             raise ValidationError, "%s '%s': %s" % (type(self).__name__, name, msg), trace
 
     def init(self):
-        """Find bases and annotations after all types are loaded."""
+        """Find bases after all types are loaded."""
         if self._init: return
         self._init = True
         if self.base:
@@ -373,12 +369,6 @@
             self.base.init()
             self.all_bases = [self.base] + self.base.all_bases
             self._extend(self.base, 'extend')
-        if self.annotations:
-            self.references = [x for x in self.annotations
-                                if self.schema.annotation(x).referential]
-            self.annotations = [self.schema.annotation(a) for a in self.annotations]
-        for a in self.annotations:
-            self._extend(a, 'be annotated')
 
     def _extend(self, other, how):
         """Add attributes and operations from other"""
@@ -407,7 +397,7 @@
 
     @property
     def my_attributes(self):
-        """Return only attribute types defined in this annotation or entity type"""
+        """Return only attribute types defined in this entity type"""
         return [a for a in self.attributes.itervalues() if a.defined_in == self]
 
     def validate(self, attributes, check_singleton=None, **kwargs):
@@ -483,10 +473,6 @@
     def name_is(self, name):
         return self.name == self.schema.long_name(name)
 
-class Annotation(EntityType):
-    """An annotation defines attributes, operations etc. that can be re-used by multiple EntityTypes."""
-    pass
-
 
 
 class Schema(object):
@@ -496,14 +482,12 @@
 
     @ivar prefix: Prefix to prepend to short entity type names.
     @ivar entityTypes: Map of L{EntityType} by name.
-    @ivar annotations: Map of L{Annotation} by name.
     @ivar description: Text description of schema.
     """
-    def __init__(self, prefix="", annotations=None, entityTypes=None, description=""):
+    def __init__(self, prefix="", entityTypes=None, description=""):
         """
         @param prefix: Prefix for entity names.
-        @param annotations: Map of  { annotationName: {attributeName: value, ... }}
-        @param entity_types: Map of  { entityTypeName: { singleton:, annotation:[...], attributes:{...}}}
+        @param entity_types: Map of  { entityTypeName: { singleton:, attributes:{...}}}
         @param description: Human readable description.
         """
         if prefix:
@@ -517,7 +501,6 @@
             return OrderedDict((self.long_name(k), cls(k, self, **v))
                                for k, v in (defs or {}).iteritems())
 
-        self.annotations = parsedefs(Annotation, annotations)
         self.entity_types = parsedefs(EntityType, entityTypes)
 
         self.all_attributes = set()
@@ -544,8 +527,6 @@
         """Return json-friendly representation"""
         return OrderedDict([
             ('prefix', self.prefix),
-            ('annotations',
-             OrderedDict((a.short_name, a.dump()) for a in self.annotations.itervalues())),
             ('entityTypes',
              OrderedDict((e.short_name, e.dump()) for e in self.entity_types.itervalues()))
         ])
@@ -559,9 +540,6 @@
     def entity_type(self, name, error=True):
         return self._lookup(self.entity_types, name, "No such entity type '%s'", error)
 
-    def annotation(self, name, error=True):
-        return self._lookup(self.annotations, name, "No such annotation '%s'", error)
-
     def validate_entity(self, attributes, check_required=True, add_default=True,
                         check_unique=None, check_singleton=None):
         """
diff --git a/python/qpid_dispatch_internal/management/schema_doc.py b/python/qpid_dispatch_internal/management/schema_doc.py
index 379e04a..ecf2825 100644
--- a/python/qpid_dispatch_internal/management/schema_doc.py
+++ b/python/qpid_dispatch_internal/management/schema_doc.py
@@ -108,7 +108,7 @@
                 self.warn("Warning no description for %s" % entity_type)
             if entity_type.operations:
                 self.para("Operations allowed: `%s`\n\n" % "`, `".join(entity_type.operations))
-            for a in entity_type.annotations: self.attribute_types(a)
+
             self.attribute_types(entity_type)
             if entity_type.operation_defs:
                 self.operation_defs(entity_type)
diff --git a/src/connection_manager.c b/src/connection_manager.c
index 0e95067..9a2b415 100644
--- a/src/connection_manager.c
+++ b/src/connection_manager.c
@@ -31,47 +31,67 @@
 
 static char* HOST_ADDR_DEFAULT = "127.0.0.1";
 
+struct qd_config_ssl_profile_t {
+    DEQ_LINKS(qd_config_ssl_profile_t);
+    uint64_t   identity;
+    char      *name;
+    char      *ssl_password;
+    char      *ssl_trusted_certificate_db;
+    char      *ssl_trusted_certificates;
+    char      *ssl_uid_format;
+    char      *ssl_display_name_file;
+    char      *ssl_certificate_file;
+    char      *ssl_private_key_file;
+    int       ref_count;
+};
+
 struct qd_config_listener_t {
-    bool                is_connector;
-    qd_bind_state_t     state;
-    qd_listener_t      *listener;
-    qd_server_config_t  configuration;
+    bool                     is_connector;
+    qd_bind_state_t          state;
+    qd_listener_t           *listener;
+    qd_config_ssl_profile_t *ssl_profile;
+    qd_server_config_t       configuration;
     DEQ_LINKS(qd_config_listener_t);
 };
 
 DEQ_DECLARE(qd_config_listener_t, qd_config_listener_list_t);
+DEQ_DECLARE(qd_config_ssl_profile_t, qd_config_ssl_profile_list_t);
 
 
 struct qd_config_connector_t {
     bool is_connector;
     DEQ_LINKS(qd_config_connector_t);
-    qd_connector_t     *connector;
-    qd_server_config_t  configuration;
+    qd_connector_t          *connector;
+    qd_server_config_t       configuration;
+    qd_config_ssl_profile_t *ssl_profile;
 };
 
 DEQ_DECLARE(qd_config_connector_t, qd_config_connector_list_t);
 
-
 struct qd_connection_manager_t {
-    qd_log_source_t             *log_source;
-    qd_server_t                 *server;
-    qd_config_listener_list_t    config_listeners;
-    qd_config_connector_list_t   config_connectors;
+    qd_log_source_t              *log_source;
+    qd_server_t                  *server;
+    qd_config_listener_list_t     config_listeners;
+    qd_config_connector_list_t    config_connectors;
+    qd_config_ssl_profile_list_t  config_ssl_profiles;
+    sys_mutex_t                  *ssl_profile_lock;
 };
 
-// True if entity has any of attributes.
-static bool has_attrs(qd_entity_t *entity, const char **attributes, int n) {
-    for (int i = 0; i < n; ++i)
-        if (qd_entity_has(entity, attributes[i])) return true;
-    return false;
+/**
+ * Search the list of config_ssl_profiles for an ssl-profile that matches the passed in name
+ */
+static qd_config_ssl_profile_t *qd_find_ssl_profile(qd_connection_manager_t *cm, char *name)
+{
+    qd_config_ssl_profile_t *ssl_profile = DEQ_HEAD(cm->config_ssl_profiles);
+    while(ssl_profile) {
+        if(strcmp(ssl_profile->name, name)==0)
+            return ssl_profile;
+        ssl_profile = DEQ_NEXT(ssl_profile);
+    }
+
+    return 0;
 }
 
-static const char *ssl_attributes[] = {
-  "certDb", "certFile", "keyFile", "passwordFile", "password"
-};
-
-static const int ssl_attributes_count = sizeof(ssl_attributes)/sizeof(ssl_attributes[0]);
-
 static void qd_server_config_free(qd_server_config_t *cf)
 {
     if (!cf) return;
@@ -80,13 +100,7 @@
     free(cf->name);
     free(cf->role);
     free(cf->sasl_mechanisms);
-    if (cf->ssl_enabled) {
-        free(cf->ssl_certificate_file);
-        free(cf->ssl_private_key_file);
-        free(cf->ssl_password);
-        free(cf->ssl_trusted_certificate_db);
-        free(cf->ssl_trusted_certificates);
-    }
+
     memset(cf, 0, sizeof(*cf));
 }
 
@@ -149,7 +163,7 @@
     assert(config->host);
 }
 
-static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, qd_entity_t* entity)
+static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, qd_entity_t* entity, qd_config_ssl_profile_t **ssl_profile)
 {
     qd_error_clear();
 
@@ -172,8 +186,7 @@
     config->sasl_username        = qd_entity_opt_string(entity, "saslUsername", 0);   CHECK();
     config->sasl_password        = qd_entity_opt_string(entity, "saslPassword", 0);   CHECK();
     config->sasl_mechanisms      = qd_entity_opt_string(entity, "saslMechanisms", 0); CHECK();
-    config->link_capacity        = qd_entity_opt_long(entity, "linkCapacity", 0);     CHECK();
-    config->ssl_enabled          = has_attrs(entity, ssl_attributes, ssl_attributes_count);
+    config->ssl_profile          = qd_entity_opt_string(entity, "sslProfile", 0);     CHECK();
     config->link_capacity        = qd_entity_opt_long(entity, "linkCapacity", 0);     CHECK();
     set_config_host(config, entity);
 
@@ -195,24 +208,25 @@
     config->requireAuthentication = authenticatePeer || depRequirePeerAuth;
     config->requireEncryption     = requireEncryption || !depAllowUnsecured;
 
-    if (config->ssl_enabled) {
+
+    if (config->ssl_profile) {
         config->ssl_required = requireSsl || !depAllowUnsecured;
         config->ssl_require_peer_authentication = config->sasl_mechanisms &&
             strstr(config->sasl_mechanisms, "EXTERNAL") != 0;
-        config->ssl_certificate_file =
-            qd_entity_opt_string(entity, "certFile", 0); CHECK();
-        config->ssl_private_key_file =
-            qd_entity_opt_string(entity, "keyFile", 0); CHECK();
-        config->ssl_password =
-            qd_entity_opt_string(entity, "password", 0); CHECK();
-        config->ssl_trusted_certificate_db =
-            qd_entity_opt_string(entity, "certDb", 0); CHECK();
-        config->ssl_trusted_certificates =
-            qd_entity_opt_string(entity, "trustedCerts", 0); CHECK();
-        config->ssl_uid_format =
-            qd_entity_opt_string(entity, "uidFormat", 0); CHECK();
-        config->ssl_display_name_file =
-            qd_entity_opt_string(entity, "displayNameFile", 0); CHECK();
+
+        *ssl_profile = qd_find_ssl_profile(qd->connection_manager, config->ssl_profile);
+        if(*ssl_profile) {
+            config->ssl_certificate_file = (*ssl_profile)->ssl_certificate_file;
+            config->ssl_private_key_file = (*ssl_profile)->ssl_private_key_file;
+            config->ssl_password = (*ssl_profile)->ssl_password;
+            config->ssl_trusted_certificate_db = (*ssl_profile)->ssl_trusted_certificate_db;
+            config->ssl_trusted_certificates = (*ssl_profile)->ssl_trusted_certificates;
+            config->ssl_uid_format = (*ssl_profile)->ssl_uid_format;
+            config->ssl_display_name_file = (*ssl_profile)->ssl_display_name_file;
+        }
+        sys_mutex_lock(qd->connection_manager->ssl_profile_lock);
+        (*ssl_profile)->ref_count++;
+        sys_mutex_unlock(qd->connection_manager->ssl_profile_lock);
     }
 
     free(stripAnnotations);
@@ -223,6 +237,36 @@
     return qd_error_code();
 }
 
+
+qd_config_ssl_profile_t *qd_dispatch_configure_ssl_profile(qd_dispatch_t *qd, qd_entity_t *entity)
+{
+    qd_error_clear();
+    qd_connection_manager_t *cm = qd->connection_manager;
+
+    qd_config_ssl_profile_t *ssl_profile = NEW(qd_config_ssl_profile_t);
+    DEQ_ITEM_INIT(ssl_profile);
+    DEQ_INSERT_TAIL(cm->config_ssl_profiles, ssl_profile);
+    ssl_profile->name                       = qd_entity_opt_string(entity, "name", 0); CHECK();
+    ssl_profile->ssl_certificate_file       = qd_entity_opt_string(entity, "certFile", 0); CHECK();
+    ssl_profile->ssl_private_key_file       = qd_entity_opt_string(entity, "keyFile", 0); CHECK();
+    ssl_profile->ssl_password               = qd_entity_opt_string(entity, "password", 0); CHECK();
+    ssl_profile->ssl_trusted_certificate_db = qd_entity_opt_string(entity, "certDb", 0); CHECK();
+    ssl_profile->ssl_trusted_certificates   = qd_entity_opt_string(entity, "trustedCerts", 0); CHECK();
+    ssl_profile->ssl_uid_format             = qd_entity_opt_string(entity, "uidFormat", 0); CHECK();
+    ssl_profile->ssl_display_name_file      = qd_entity_opt_string(entity, "displayNameFile", 0); CHECK();
+    sys_mutex_lock(qd->connection_manager->ssl_profile_lock);
+    ssl_profile->ref_count                  = 0;
+    sys_mutex_unlock(qd->connection_manager->ssl_profile_lock);
+    qd_log(cm->log_source, QD_LOG_INFO, "Created SSL Profile with name %s ", ssl_profile->name);
+    return ssl_profile;
+
+    error:
+        qd_log(cm->log_source, QD_LOG_ERROR, "Unable to create ssl profile: %s", qd_error_message());
+        free(ssl_profile);
+        return 0;
+}
+
+
 qd_config_listener_t *qd_dispatch_configure_listener(qd_dispatch_t *qd, qd_entity_t *entity)
 {
     qd_error_clear();
@@ -231,17 +275,22 @@
     cl->is_connector = false;
     cl->state = QD_BIND_NONE;
     cl->listener = 0;
-    if (load_server_config(qd, &cl->configuration, entity) != QD_ERROR_NONE) {
+    qd_config_ssl_profile_t *ssl_profile = 0;
+    if (load_server_config(qd, &cl->configuration, entity, &ssl_profile) != QD_ERROR_NONE) {
         qd_log(cm->log_source, QD_LOG_ERROR, "Unable to create config listener: %s", qd_error_message());
-        qd_config_listener_free(cl);
+        qd_config_listener_free(qd->connection_manager, cl);
         return 0;
     }
+    cl->ssl_profile = ssl_profile;
     DEQ_ITEM_INIT(cl);
     DEQ_INSERT_TAIL(cm->config_listeners, cl);
-    qd_log(cm->log_source, QD_LOG_INFO, "Configured Listener: %s:%s proto=%s role=%s",
+
+    qd_log(cm->log_source, QD_LOG_INFO, "Configured Listener: %s:%s proto=%s, role=%s%s%s",
            cl->configuration.host, cl->configuration.port,
            cl->configuration.protocol_family ? cl->configuration.protocol_family : "any",
-           cl->configuration.role);
+           cl->configuration.role,
+           cl->ssl_profile ? ", sslProfile=":"",
+           cl->ssl_profile ? cl->ssl_profile->name:"");
 
     return cl;
 }
@@ -267,18 +316,21 @@
     ZERO(cc);
 
     cc->is_connector = true;
-    if (load_server_config(qd, &cc->configuration, entity) != QD_ERROR_NONE) {
+    qd_config_ssl_profile_t *ssl_profile = 0;
+    if (load_server_config(qd, &cc->configuration, entity, &ssl_profile) != QD_ERROR_NONE) {
         qd_log(cm->log_source, QD_LOG_ERROR, "Unable to create config connector: %s", qd_error_message());
-        qd_config_connector_free(cc);
+        qd_config_connector_free(qd->connection_manager, cc);
         return 0;
     }
-
+    cc->ssl_profile = ssl_profile;
     DEQ_ITEM_INIT(cc);
     DEQ_INSERT_TAIL(cm->config_connectors, cc);
-    qd_log(cm->log_source, QD_LOG_INFO, "Configured Connector: %s:%s proto=%s role=%s",
-           cc->configuration.host, cc->configuration.port,
-           cc->configuration.protocol_family ? cc->configuration.protocol_family : "any",
-           cc->configuration.role);
+    qd_log(cm->log_source, QD_LOG_INFO, "Configured Connector: %s:%s proto=%s, role=%s %s%s",
+            cc->configuration.host, cc->configuration.port,
+            cc->configuration.protocol_family ? cc->configuration.protocol_family : "any",
+            cc->configuration.role,
+            cc->ssl_profile ? ", sslProfile=":"",
+            cc->ssl_profile ? cc->ssl_profile->name:"");
 
     return cc;
 }
@@ -291,9 +343,11 @@
         return 0;
 
     cm->log_source = qd_log_source("CONN_MGR");
+    cm->ssl_profile_lock = sys_mutex();
     cm->server     = qd->server;
     DEQ_INIT(cm->config_listeners);
     DEQ_INIT(cm->config_connectors);
+    DEQ_INIT(cm->config_ssl_profiles);
 
     return cm;
 }
@@ -319,6 +373,15 @@
         free(cc);
         cc = DEQ_HEAD(cm->config_connectors);
     }
+
+    qd_config_ssl_profile_t *sslp = DEQ_HEAD(cm->config_ssl_profiles);
+    while (sslp) {
+        DEQ_REMOVE_HEAD(cm->config_ssl_profiles);
+        qd_config_ssl_profile_free(cm, sslp);
+        sslp = DEQ_HEAD(cm->config_ssl_profiles);
+    }
+
+    sys_mutex_free(cm->ssl_profile_lock);
 }
 
 
@@ -347,25 +410,62 @@
 }
 
 
-void qd_config_connector_free(qd_config_connector_t *cc)
+void qd_config_connector_free(qd_connection_manager_t *cm, qd_config_connector_t *cc)
 {
     if (cc->connector)
         qd_server_connector_free(cc->connector);
+
+    if (cc->ssl_profile) {
+        sys_mutex_lock(cm->ssl_profile_lock);
+        cc->ssl_profile->ref_count--;
+        sys_mutex_unlock(cm->ssl_profile_lock);
+    }
+
     free(cc);
 }
 
 
-void qd_config_listener_free(qd_config_listener_t *cl)
+void qd_config_listener_free(qd_connection_manager_t *cm, qd_config_listener_t *cl)
 {
     if (cl->listener) {
         qd_server_listener_close(cl->listener);
         qd_server_listener_free(cl->listener);
         cl->listener = 0;
     }
+
+    if (cl->ssl_profile) {
+        sys_mutex_lock(cm->ssl_profile_lock);
+        cl->ssl_profile->ref_count--;
+        sys_mutex_unlock(cm->ssl_profile_lock);
+    }
+
     free(cl);
 }
 
 
+bool qd_config_ssl_profile_free(qd_connection_manager_t *cm, qd_config_ssl_profile_t *ssl_profile)
+{
+    sys_mutex_lock(cm->ssl_profile_lock);
+    if (ssl_profile->ref_count != 0) {
+        sys_mutex_unlock(cm->ssl_profile_lock);
+        return false;
+    }
+    sys_mutex_unlock(cm->ssl_profile_lock);
+
+    free(ssl_profile->name);
+    free(ssl_profile->ssl_password);
+    free(ssl_profile->ssl_trusted_certificate_db);
+    free(ssl_profile->ssl_trusted_certificates);
+    free(ssl_profile->ssl_uid_format);
+    free(ssl_profile->ssl_display_name_file);
+    free(ssl_profile->ssl_certificate_file);
+    free(ssl_profile->ssl_private_key_file);
+    free(ssl_profile);
+    return true;
+
+}
+
+
 void qd_connection_manager_delete_listener(qd_dispatch_t *qd, void *impl)
 {
     qd_config_listener_t *cl = (qd_config_listener_t*) impl;
@@ -373,18 +473,34 @@
     if (cl) {
         qd_server_listener_close(cl->listener);
         DEQ_REMOVE(qd->connection_manager->config_listeners, cl);
-        qd_config_listener_free(cl);
+        qd_config_listener_free(qd->connection_manager, cl);
     }
 }
 
 
+/**
+ * Only those SSL Profiles that are not being referenced from other listeners/connectors can be deleted
+ */
+bool qd_connection_manager_delete_ssl_profile(qd_dispatch_t *qd, void *impl)
+{
+    qd_config_ssl_profile_t *ssl_profile = (qd_config_ssl_profile_t*) impl;
+    if(ssl_profile) {
+        bool freed = qd_config_ssl_profile_free(qd->connection_manager, ssl_profile);
+        if (freed)
+            DEQ_REMOVE(qd->connection_manager->config_ssl_profiles, ssl_profile);
+        return freed;
+    }
+    return false;
+}
+
+
 void qd_connection_manager_delete_connector(qd_dispatch_t *qd, void *impl)
 {
     qd_config_connector_t *cc = (qd_config_connector_t*) impl;
 
     if (cc) {
         DEQ_REMOVE(qd->connection_manager->config_connectors, cc);
-        qd_config_connector_free(cc);
+        qd_config_connector_free(qd->connection_manager, cc);
     }
 }
 
diff --git a/src/server.c b/src/server.c
index 55e2ea9..0787022 100644
--- a/src/server.c
+++ b/src/server.c
@@ -400,6 +400,10 @@
 }
 
 
+qd_error_t qd_entity_refresh_sslProfile(qd_entity_t* entity, void *impl)
+{
+    return QD_ERROR_NONE;
+}
 
 
 qd_error_t qd_entity_refresh_connection(qd_entity_t* entity, void *impl)
@@ -647,7 +651,7 @@
         }
 
         // Set up SSL if configured
-        if (config->ssl_enabled) {
+        if (config->ssl_profile) {
             qd_log(qd_server->log_source, QD_LOG_TRACE, "Configuring SSL on %s",
                    log_incoming(logbuf, sizeof(logbuf), cxtr));
             if (listener_setup_ssl(ctx, config, tport) != QD_ERROR_NONE) {
@@ -1229,7 +1233,7 @@
     //
     // Set up SSL if appropriate
     //
-    if (config->ssl_enabled) {
+    if (config->ssl_profile) {
         pn_ssl_domain_t *domain = pn_ssl_domain(PN_SSL_MODE_CLIENT);
 
         if (!domain) {
diff --git a/tests/management/qdrouter.py b/tests/management/qdrouter.py
index b6285b4..46455ef 100644
--- a/tests/management/qdrouter.py
+++ b/tests/management/qdrouter.py
@@ -92,10 +92,10 @@
         ]
         self.assertEqual(content, expect)
 
-        content = conf._expand(content)
         expect = [
             [u'router', {u'mode': u'standalone', u'id': u'QDR'}],
-            [u'listener', {u'password': u'secret', u'name': u'l0', u'sslProfileName': u'test-profile', u'saslMechanisms': u'ANONYMOUS'}],
+            [u'sslProfile', {u'password': u'secret', u'name': u'test-profile'}],
+            [u'listener', {u'name': u'l0', u'sslProfile': u'test-profile', u'saslMechanisms': u'ANONYMOUS'}],
             [u'listener', {u'port': u'1234', u'identity': u'l1', u'saslMechanisms': u'ANONYMOUS'}],
             [u'listener', {u'port': u'4567', u'saslMechanisms': u'ANONYMOUS'}]
         ]
diff --git a/tests/management/schema.py b/tests/management/schema.py
index 6c32f89..9ab3fcf 100644
--- a/tests/management/schema.py
+++ b/tests/management/schema.py
@@ -35,22 +35,10 @@
 
 SCHEMA_1 = {
     "prefix": "org.example",
-    "annotations": {
-        "entityId": {
-            "attributes": {
-                "name": {"type": "string",
-                         "required": True,
-                         "unique": True},
-                "type": {"type":"string",
-                         "required": True}
-            }
-        }
-    },
     "entityTypes": {
         "container": {
             "deprecated": True,
             "singleton": True,
-            "annotations": ["entityId"],
             "attributes": {
                 "workerThreads": {"type": "integer", "default": 1},
                 "routerId": {
@@ -60,20 +48,28 @@
                     "deprecated": True,
                     "create": True
                 },
+                "name": {"type": "string",
+                         "required": True,
+                         "unique": True},
+                "type": {"type":"string",
+                         "required": True}
             }
         },
         "listener": {
-            "annotations": ["entityId"],
             "attributes": {
-                "host": {
-                    "type": "string"
-                }
+                "host": {"type": "string"},
+                "name": {"type": "string", "required": True, "unique": True},
+                "type": {"type":"string",  "required": True}
             }
         },
         "connector": {
-            "annotations": ["entityId"],
             "attributes": {
-                "host": {"type": "string"}
+                "host": {"type": "string"},
+                "name": {"type": "string",
+                         "required": True,
+                         "unique": True},
+                "type": {"type":"string",
+                         "required": True}
             }
         }
     }
@@ -125,23 +121,17 @@
         self.assertRaises(ValidationError, a.validate, None)
         self.assertRaises(ValidationError, a.validate, "xxx")
 
-
     def test_entity_type(self):
-        s = Schema(annotations={
-            'i1':{'attributes': { 'foo1': {'type':'string', 'default':'FOO1'}}},
-            'i2':{'attributes': { 'foo2': {'type':'string', 'default':'FOO2'}}}})
+        s = Schema()
 
         e = EntityType('MyEntity', s, attributes={
             'foo': {'type':'string', 'default':'FOO'},
             'req': {'type':'integer', 'required':True},
             'e': {'type':['x', 'y']}})
+
         e.init()
         self.assertRaises(ValidationError, e.validate, {}) # Missing required 'req'
         self.assertEqual(e.validate({'req':42}), {'foo': 'FOO', 'req': 42})
-        # Try with an annotation
-        e = EntityType('e2', s, attributes={'x':{'type':'integer'}}, annotations=['i1', 'i2'])
-        e.init()
-        self.assertEqual(e.validate({'x':1}), {'x':1, 'foo1': 'FOO1', 'foo2': 'FOO2'})
 
     def test_schema_validate(self):
         s = Schema(**SCHEMA_1)
@@ -162,8 +152,8 @@
         s = Schema(**SCHEMA_1)
         self.assertRaises(ValidationError, s.entity, {'type': 'nosuch'})
         self.assertRaises(ValidationError, s.entity, {'type': 'listener', 'nosuch': 'x'})
-        e = s.entity({'type': 'listener', 'name':'x', 'host':'foo'})
-        self.assertEqual(e.attributes, {'type': 'org.example.listener', 'name':'x', 'host':'foo'})
+        e = s.entity({'host':'foo', 'type': 'listener', 'name': 'listener-1'})
+        self.assertEqual(e.attributes, {'host': 'foo', 'name': 'listener-1', 'type': 'org.example.listener'})
         self.assertEqual(e['host'], 'foo')
         self.assertRaises(ValidationError, e.__setitem__, 'nosuch', 'x')
 
diff --git a/tests/system_tests_qdmanage.py b/tests/system_tests_qdmanage.py
index adcbe66..319a9cb 100644
--- a/tests/system_tests_qdmanage.py
+++ b/tests/system_tests_qdmanage.py
@@ -18,6 +18,7 @@
 #
 
 import re, json, unittest, os
+from time import sleep
 from system_test import TestCase, Process, Qdrouterd, main_module, TIMEOUT, DIR, wait_port
 from subprocess import PIPE, STDOUT
 from qpid_dispatch_internal.compat import OrderedDict, dictify
@@ -165,6 +166,17 @@
         actual = self.run_qdmanage("get-schema")
         self.assertEquals(schema, dictify(json.loads(actual)))
 
+    def test_get_annotations(self):
+        """
+        The qdmanage GET-ANNOTATIONS call must return an empty dict since we don't support annotations at the moment.
+        """
+        out = json.loads(self.run_qdmanage("get-annotations"))
+        self.assertTrue(len(out) == 0)
+
+    def test_get_types(self):
+        out = json.loads(self.run_qdmanage("get-types"))
+        self.assertEqual(len(out), 27)
+
     def test_get_log(self):
         log = json.loads(self.run_qdmanage("get-log limit=1"))[0]
         self.assertEquals(['AGENT', 'trace'], log[0:2])
@@ -363,5 +375,63 @@
                 created = True
         self.assertTrue(created)
 
+    def test_create_delete_ssl_profile(self):
+        """
+
+        """
+        long_type = 'org.apache.qpid.dispatch.sslProfile'
+        ssl_profile_name = 'ssl-profile-test'
+        ssl_create_command = 'CREATE --type=' + long_type + ' certFile=' + self.ssl_file('server-certificate.pem') + \
+                         ' keyFile=' + self.ssl_file('server-private-key.pem') + ' password=server-password' + \
+                         ' name=' + ssl_profile_name + ' certDb=' + self.ssl_file('ca-certificate.pem')
+
+        output = json.loads(self.run_qdmanage(ssl_create_command))
+        name = output['name']
+        self.assertEqual(name, ssl_profile_name)
+
+        long_type = 'org.apache.qpid.dispatch.listener'
+        listener_name = 'sslListener'
+        port = self.get_port()
+        listener_create_command = 'CREATE --type=' + long_type + ' --name=sslListener host=127.0.0.1 port=' + str(port) + \
+                                  ' saslMechanisms=EXTERNAL sslProfile=' + ssl_profile_name + \
+                                  ' requireSsl=yes authenticatePeer=yes'
+        output = json.loads(self.run_qdmanage(listener_create_command))
+        name = output['name']
+        self.assertEqual(name, listener_name)
+
+        sleep(1)
+        query_command = 'QUERY --type=listener'
+
+        # Query on the port that was created by the preceding listener create
+        output = json.loads(self.run_qdmanage(query_command, address="127.0.0.1:"+str(port)))
+
+        ssl_listener_present = False
+
+        for out in output:
+            if out['name'] == 'sslListener':
+                ssl_listener_present = True
+                self.assertEqual(out['sslProfile'], 'ssl-profile-test')
+
+        self.assertEqual(len(output), 3)
+        self.assertTrue(ssl_listener_present)
+
+        # Delete the SSL Profile. This will fail because there is a listener referencing the SSL profile.
+        delete_command = 'DELETE --type=sslProfile --name=' + ssl_profile_name
+        cannot_delete = False
+        try:
+            json.loads(self.run_qdmanage(delete_command))
+        except Exception as e:
+            cannot_delete = True
+            self.assertTrue('ForbiddenStatus: SSL Profile is referenced by other listeners/connectors' in e.message)
+
+        self.assertTrue(cannot_delete)
+
+        # Deleting the listener first and then the SSL profile must work.
+        delete_command = 'DELETE --type=listener --name=' + listener_name
+        self.run_qdmanage(delete_command)
+
+        delete_command = 'DELETE --type=sslProfile --name=' + ssl_profile_name
+        self.run_qdmanage(delete_command)
+
 if __name__ == '__main__':
     unittest.main(main_module())
diff --git a/tests/system_tests_sasl_plain.py b/tests/system_tests_sasl_plain.py
index 7da5ca7..d009235 100644
--- a/tests/system_tests_sasl_plain.py
+++ b/tests/system_tests_sasl_plain.py
@@ -17,9 +17,10 @@
 # under the License.
 #
 
-import unittest, os, time
-from subprocess import PIPE, Popen
-from system_test import TestCase, Qdrouterd, main_module, DIR, TIMEOUT
+import unittest, os, json
+from time import sleep
+from subprocess import PIPE, Popen, STDOUT
+from system_test import TestCase, Qdrouterd, main_module, DIR, TIMEOUT, Process
 
 from qpid_dispatch.management.client import Node
 
@@ -394,6 +395,8 @@
     def ssl_file(name):
         return os.path.join(DIR, 'ssl_certs', name)
 
+    x_listener_port = None
+
     @classmethod
     def setUpClass(cls):
         """
@@ -409,6 +412,7 @@
         cls.routers = []
 
         x_listener_port = cls.tester.get_port()
+        RouterTestVerifyHostNameNo.x_listener_port = x_listener_port
         y_listener_port = cls.tester.get_port()
 
         super(RouterTestVerifyHostNameNo, cls).router('X', [
@@ -433,7 +437,9 @@
         super(RouterTestVerifyHostNameNo, cls).router('Y', [
                      # This router will act like a client. First an SSL connection will be established and then
                      # we will have SASL plain authentication over SSL.
-                     ('connector', {'addr': '127.0.0.1', 'role': 'inter-router', 'port': x_listener_port,
+                     ('connector', {'name': 'connectorToX',
+                                    'addr': '127.0.0.1', 'role': 'inter-router',
+                                    'port': x_listener_port,
                                     'sslProfile': 'client-ssl-profile',
                                     # Provide a sasl user name and password to connect to QDR.X
                                     'saslMechanisms': 'PLAIN',
@@ -442,7 +448,7 @@
                      ('router', {'workerThreads': 1,
                                  'mode': 'interior',
                                  'routerId': 'QDR.Y'}),
-                     ('listener', {'addr': '0.0.0.0', 'role': 'normal', 'port': y_listener_port}),
+                     ('listener', {'host': '0.0.0.0', 'role': 'normal', 'port': y_listener_port}),
                      ('sslProfile', {'name': 'client-ssl-profile',
                                      'certDb': cls.ssl_file('ca-certificate.pem'),
                                      'certFile': cls.ssl_file('client-certificate.pem'),
@@ -454,20 +460,26 @@
         cls.routers[1].wait_ports()
         cls.routers[1].wait_router_connected('QDR.X')
 
-    def test_inter_router_plain_over_ssl_exists(self):
-        """
-        Tests to make sure that an inter-router connection exists between the routers since verifyHostName is 'no'.
-        """
-        local_node = Node.connect(self.routers[1].addresses[0], timeout=TIMEOUT)
+    @staticmethod
+    def ssl_file(name):
+        return os.path.join(DIR, 'ssl_certs', name)
 
-        results = local_node.query(type='org.apache.qpid.dispatch.connection').results
+    def run_qdmanage(self, cmd, input=None, expect=Process.EXIT_OK, address=None):
+        p = self.popen(
+            ['qdmanage'] + cmd.split(' ') + ['--bus', address or self.address(), '--indent=-1', '--timeout',
+                                             str(TIMEOUT)], stdin=PIPE, stdout=PIPE, stderr=STDOUT, expect=expect)
+        out = p.communicate(input)[0]
+        try:
+            p.teardown()
+        except Exception, e:
+            raise Exception("%s\n%s" % (e, out))
+        return out
 
-        self.assertEqual(4, len(results))
-
+    def common_asserts(self, results):
         search = "QDR.X"
         found = False
 
-        for N in range(0,3):
+        for N in range(0, len(results)):
             if results[N][0] == search:
                 found = True
                 break
@@ -486,6 +498,110 @@
         # user must be test@domain.com
         self.assertEqual(u'test@domain.com', results[N][16])
 
+    def test_inter_router_plain_over_ssl_exists(self):
+        """
+        Tests to make sure that an inter-router connection exists between the routers since verifyHostName is 'no'.
+        """
+        local_node = Node.connect(self.routers[1].addresses[0], timeout=TIMEOUT)
+
+        results = local_node.query(type='org.apache.qpid.dispatch.connection').results
+
+        self.common_asserts(results)
+
+    def test_zzz_delete_create_connector(self):
+        """
+        Delete an ssl profile before deleting the connector and make sure it fails.
+        Delete an ssl profile after deleting the connector and make sure it succeeds.
+        Re-add the deleted connector and associate it with an ssl profile and make sure
+        that the two routers are able to communicate over the connection.
+        """
+
+        ssl_profile_name = 'client-ssl-profile'
+
+        delete_command = 'DELETE --type=sslProfile --name=' + ssl_profile_name
+
+        cannot_delete = False
+        try:
+            json.loads(self.run_qdmanage(delete_command, address=self.routers[1].addresses[0]))
+        except Exception as e:
+            cannot_delete = True
+            self.assertTrue('ForbiddenStatus: SSL Profile is referenced by other listeners/connectors' in e.message)
+
+        self.assertTrue(cannot_delete)
+
+        # Deleting the connector
+        delete_command = 'DELETE --type=connector --name=connectorToX'
+        self.run_qdmanage(delete_command, address=self.routers[1].addresses[0])
+
+        #Assert here that the connection to QDR.X is gone
+
+        # Re-add connector
+        connector_create_command = 'CREATE --type=connector name=connectorToX host=127.0.0.1 port=' + \
+                                   str(RouterTestVerifyHostNameNo.x_listener_port) + \
+                                   ' saslMechanisms=PLAIN sslProfile=' + ssl_profile_name + \
+                                   ' role=inter-router verifyHostName=no saslUsername=test@domain.com' \
+                                   ' saslPassword=password'
+
+        json.loads(self.run_qdmanage(connector_create_command, address=self.routers[1].addresses[0]))
+        sleep(1)
+        local_node = Node.connect(self.routers[1].addresses[0], timeout=TIMEOUT)
+        results = local_node.query(type='org.apache.qpid.dispatch.connection').results
+        self.common_asserts(results)
+
+    def test_zzz_delete_create_ssl_profile(self):
+        """
+        Deletes a connector and its corresponding ssl profile and recreates both
+        """
+
+        ssl_profile_name = 'client-ssl-profile'
+
+        # Deleting the connector first and then its SSL profile must work.
+        delete_command = 'DELETE --type=connector --name=connectorToX'
+        self.run_qdmanage(delete_command, address=self.routers[1].addresses[0])
+
+        # Delete the connector's associated ssl profile
+        delete_command = 'DELETE --type=sslProfile --name=' + ssl_profile_name
+        self.run_qdmanage(delete_command, address=self.routers[1].addresses[0])
+
+        local_node = Node.connect(self.routers[1].addresses[0], timeout=TIMEOUT)
+        results = local_node.query(type='org.apache.qpid.dispatch.connection').results
+        search = "QDR.X"
+        found = False
+
+        for N in range(0, 3):
+            if results[N][0] == search:
+                found = True
+                break
+
+        self.assertFalse(found)
+
+        # re-create the ssl profile
+        long_type = 'org.apache.qpid.dispatch.sslProfile'
+        ssl_create_command = 'CREATE --type=' + long_type + ' certFile=' + self.ssl_file('client-certificate.pem') + \
+                             ' keyFile=' + self.ssl_file('client-private-key.pem') + ' password=client-password' + \
+                             ' name=' + ssl_profile_name + ' certDb=' + self.ssl_file('ca-certificate.pem')
+
+        output = json.loads(self.run_qdmanage(ssl_create_command, address=self.routers[1].addresses[0]))
+        name = output['name']
+        self.assertEqual(name, ssl_profile_name)
+
+        # Re-add connector
+        connector_create_command = 'CREATE --type=connector name=connectorToX host=127.0.0.1 port=' + \
+                                   str(RouterTestVerifyHostNameNo.x_listener_port) + \
+                                   ' saslMechanisms=PLAIN sslProfile=' + ssl_profile_name + \
+                                   ' role=inter-router verifyHostName=no saslUsername=test@domain.com' \
+                                   ' saslPassword=password'
+
+        json.loads(self.run_qdmanage(connector_create_command, address=self.routers[1].addresses[0]))
+
+        sleep(1)
+
+        local_node = Node.connect(self.routers[1].addresses[0], timeout=TIMEOUT)
+        results = local_node.query(type='org.apache.qpid.dispatch.connection').results
+
+        self.common_asserts(results)
+
+
 if __name__ == '__main__':
     unittest.main(main_module())
 
diff --git a/tests/system_tests_two_routers.py b/tests/system_tests_two_routers.py
index 4e81500..fdc5534 100644
--- a/tests/system_tests_two_routers.py
+++ b/tests/system_tests_two_routers.py
@@ -17,9 +17,10 @@
 # under the License.
 #
 
-import unittest, os
+import unittest, os, json
+from subprocess import PIPE, STDOUT
 from proton import Message, PENDING, ACCEPTED, REJECTED, RELEASED, SSLDomain, SSLUnavailable, Timeout
-from system_test import TestCase, Qdrouterd, main_module, DIR
+from system_test import TestCase, Qdrouterd, main_module, DIR, TIMEOUT, Process
 from proton.handlers import MessagingHandler
 from proton.reactor import Container, AtMostOnce, AtLeastOnce
 
@@ -32,6 +33,8 @@
 
 class RouterTest(TestCase):
 
+    inter_router_port = None
+
     @staticmethod
     def ssl_config(client_server, connection):
         return [] # Over-ridden by RouterTestSsl
@@ -72,10 +75,8 @@
         router('A', 'server',
                ('listener', {'role': 'inter-router', 'port': inter_router_port}))
         router('B', 'client',
-               ('connector',
-                {'role': 'inter-router',
-                 'port': inter_router_port,
-                 'verifyHostName': 'no'}))
+               ('connector', {'name': 'connectorToA', 'role': 'inter-router', 'port': inter_router_port,
+                              'verifyHostName': 'no'}))
 
         cls.routers[0].wait_router_connected('QDR.B')
         cls.routers[1].wait_router_connected('QDR.A')
@@ -1099,28 +1100,58 @@
     def run(self):
         Container(self).run()
 
-
-
 try:
     SSLDomain(SSLDomain.MODE_CLIENT)
 
     class RouterTestSsl(RouterTest):
 
         @staticmethod
+        def ssl_file(name):
+            return os.path.join(DIR, 'ssl_certs', name)
+
+        def run_qdmanage(self, cmd, input=None, expect=Process.EXIT_OK, address=None):
+            p = self.popen(
+                ['qdmanage'] + cmd.split(' ') + ['--bus', address or self.address(), '--indent=-1', '--timeout',
+                                                 str(TIMEOUT)], stdin=PIPE, stdout=PIPE, stderr=STDOUT, expect=expect)
+            out = p.communicate(input)[0]
+            try:
+                p.teardown()
+            except Exception, e:
+                raise Exception("%s\n%s" % (e, out))
+            return out
+
+        @staticmethod
         def ssl_config(client_server, connection):
                 connection[1]['sslProfile'] = 'test-ssl'
 
-                def ssl_file(name):
-                    return os.path.join(DIR, 'ssl_certs', name)
                 return [
                     ('sslProfile', {
                         'name': 'test-ssl',
-                        'certDb': ssl_file('ca-certificate.pem'),
-                        'certFile': ssl_file(client_server+'-certificate.pem'),
-                        'keyFile': ssl_file(client_server+'-private-key.pem'),
+                        'certDb': RouterTestSsl.ssl_file('ca-certificate.pem'),
+                        'certFile': RouterTestSsl.ssl_file(client_server+'-certificate.pem'),
+                        'keyFile': RouterTestSsl.ssl_file(client_server+'-private-key.pem'),
                         'password': client_server+'-password'})]
 
+        def test_zzz_delete_ssl_profile(self):
+            """
+            Delete an ssl profile before deleting the connector and make sure it fails.
+            """
+            delete_command = 'DELETE --type=sslProfile --name=test-ssl'
+            cannot_delete = False
+            try:
+                json.loads(self.run_qdmanage(delete_command, address=self.routers[1].addresses[0]))
+            except Exception as e:
+                cannot_delete = True
+                self.assertTrue('ForbiddenStatus: SSL Profile is referenced by other listeners/connectors' in e.message)
 
+            self.assertTrue(cannot_delete)
+
+            # Deleting the listener first and then the SSL profile must work.
+            delete_command = 'DELETE --type=connector --name=connectorToA'
+            self.run_qdmanage(delete_command, address=self.routers[1].addresses[0])
+
+            delete_command = 'DELETE --type=sslProfile --name=test-ssl'
+            self.run_qdmanage(delete_command, address=self.routers[1].addresses[0])
 
 except SSLUnavailable:
     class RouterTestSsl(TestCase):