You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ea...@apache.org on 2017/11/29 19:58:29 UTC

[1/4] qpid-dispatch git commit: DISPATCH-886 Use pre-npm css files

Repository: qpid-dispatch
Updated Branches:
  refs/heads/master 58ecc97bc -> 55d7bd34b


DISPATCH-886 Use pre-npm css files


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/79ae73f9
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/79ae73f9
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/79ae73f9

Branch: refs/heads/master
Commit: 79ae73f9dd768005f6f8f7d4ecadc4000a97f0ae
Parents: 58ecc97
Author: Ernest Allen <ea...@redhat.com>
Authored: Wed Nov 29 14:54:42 2017 -0500
Committer: Ernest Allen <ea...@redhat.com>
Committed: Wed Nov 29 14:54:42 2017 -0500

----------------------------------------------------------------------
 .../src/main/webapp/plugin/css/dispatch.css     | 727 +++++++++++++-
 .../src/main/webapp/plugin/css/plugin.css       | 995 ++++++++++++++++++-
 2 files changed, 1720 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/79ae73f9/console/hawtio/src/main/webapp/plugin/css/dispatch.css
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/css/dispatch.css b/console/hawtio/src/main/webapp/plugin/css/dispatch.css
deleted file mode 120000
index f3dbfa0..0000000
--- a/console/hawtio/src/main/webapp/plugin/css/dispatch.css
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/css/dispatch.css
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/css/dispatch.css b/console/hawtio/src/main/webapp/plugin/css/dispatch.css
new file mode 100644
index 0000000..5c946bd
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/css/dispatch.css
@@ -0,0 +1,726 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+svg {
+  background-color: transparent;
+  cursor: default;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  -o-user-select: none;
+  user-select: none;
+}
+
+svg:not(.active):not(.ctrl) {
+  cursor: crosshair;
+}
+#end-arrow-selected, #start-arrow-selected {
+	stroke: #33F;
+	fill: #33F;
+}
+path.link.selected {
+  stroke-dasharray: 10,2;
+  stroke: #33F  !important;
+}
+
+path.link {
+  fill: #000;
+  stroke: #000;
+  stroke-width: 4px;
+  cursor: default;
+}
+
+svg:not(.active):not(.ctrl) path.link {
+  cursor: pointer;
+}
+
+path.link.small {
+  stroke-width: 2.5;
+  stroke: darkgray;
+}
+path.link.highlighted {
+    stroke: #6F6 !important;
+}
+marker#start-arrow-highlighted,
+marker#end-arrow-highlighted {
+    fill: #6F6;
+}
+marker#start-arrow-small,
+marker#end-arrow-small {
+    fill: darkgray;
+}
+
+path.link.dragline {
+  pointer-events: none;
+}
+
+path.link.hidden {
+  stroke-width: 0;
+}
+
+circle.node {
+  stroke-width: 1.5px;
+  cursor: pointer;
+  stroke: darkgray;
+}
+
+circle.node.reflexive {
+  stroke: #F00 !important;
+  stroke-width: 2.5px;
+}
+circle.node.selected {
+  stroke: #6F6 !important;
+  stroke-width: 2px;
+  fill: #e0e0ff !important;
+}
+circle.node.highlighted {
+  stroke: #6F6;
+}
+circle.node.inter-router {
+    fill: #EAEAEA;
+}
+circle.node.normal.in {
+    fill: #F0F000;
+}
+circle.node.normal.out {
+    fill: #C0F0C0;
+}
+circle.node.on-demand {
+    fill: #C0FFC0;
+}
+circle.node.on-demand.artemis {
+	fill: #FCC;
+	/*opacity: 0.2; */
+}
+
+circle.node.fixed {
+    stroke-dasharray: 10,2;
+}
+text {
+  font: 12px sans-serif;
+  pointer-events: none;
+  /*font-family: monospace;*/
+
+}
+
+.tooltipsy
+{
+    padding: 10px;
+/*    max-width: 320px;*/
+    color: #303030;
+    background-color: #fcfcfe;
+    border: 1px solid #deca7e;
+    border-radius: 5px;
+}
+
+.tiptable {
+
+}
+.tiptable tr {
+	border-bottom: 1px solid #ccc;
+}
+
+.tiptable tr:last-child {
+	border-bottom: 0px;
+}
+
+.tiptable tr:nth-child(even) {
+	background: #fcfcfe;
+}
+.tiptable tr:nth-child(odd) {
+	background: #FFF
+}
+
+text.id {
+  text-anchor: middle;
+  font-weight: bold;
+}
+
+text.label {
+  text-anchor: start;
+  font-weight: bold;
+}
+
+.row-fluid.tertiary {
+  position: relative;
+  left: 20px;
+}
+
+.row-fluid.tertiary.left {
+  float: left;
+}
+
+.row-fluid.tertiary.panel {
+  width: 410px;
+  /*height: 100%; */
+}
+
+div#topologyForm .ngViewport, div#topologyForm .gridStyle {
+  height: auto !important;
+  min-height: initial !important;
+  overflow: initial;
+}
+
+div#multiple_details, div#link_details {
+	height: 300px;
+	width: 700px;
+	display: none;
+	padding: 0.5em;
+    border: 1px solid;
+	position: absolute;
+	background-color: white;
+	max-height: 330px !important;
+    overflow: hidden;
+}
+div#multiple_details div.ngRow.selected {
+	background-color: #c9dde1 !important;
+}
+
+div.grid-values {
+	text-align: right;
+}
+
+div.grid-values.ngCellText span {
+	padding-right: 4px;
+}
+
+.panel-adjacent {
+  margin-left: 430px;
+}
+
+#topologyForm.selected {
+  border: 1px solid blue;
+}
+#topologyForm {
+  border-right: 1px solid lightgray;
+  border-bottom: 1px solid lightgray;
+    /*border: 1px solid white;*/
+    padding: 2px;
+    /* position: relative; */
+    /* top: -8px; */
+}
+div.qdr-topology.pane.left .ngViewport {
+    /* border: 1px solid lightgray; */
+}
+
+#topologyForm > div {
+  width:396px;
+}
+
+/* globe */
+.land {
+  fill: #999;
+  stroke-opacity: 1;
+}
+
+.graticule {
+  fill: none;
+  stroke: black;
+  stroke-width:.5;
+  opacity:.1;
+}
+
+.labels {
+    font: 18px sans-serif;
+    fill: black;
+    opacity: .85;
+	text-anchor: middle;
+}
+
+.noclicks { pointer-events:none; }
+
+.point {  opacity:.6; }
+
+.arcs {
+  opacity:.7;
+  stroke: darkgreen;
+  stroke-width: 3;
+}
+.flyers {
+  stroke-width:1;
+  opacity: 0;
+  stroke: darkred;
+}
+.arc, .flyer {
+  stroke-linejoin: round;
+  fill:none;
+}
+.arc { }
+.arc:hover {
+  stroke: darkred;
+}
+.flyer { }
+.flyer:hover {
+  stroke: darkgreen;
+}
+.arc.inter-router {
+  stroke: darkblue;
+}
+
+#addNodeForm {
+  padding: 1em;
+}
+
+
+li.currentStep {
+  font-weight: bold;
+}
+
+.qdrTopology div.panel {
+  position: absolute;
+}
+/*
+.ui-dialog-titlebar {
+    border: 0;
+    background: transparent;
+}
+*/
+
+/*
+.ui-tabs.ui-tabs-vertical {
+    padding: 0;
+    width: 48em;
+}
+.ui-tabs.ui-tabs-vertical .ui-widget-header {
+    border: none;
+}
+.ui-tabs.ui-tabs-vertical .ui-tabs-nav {
+    float: left;
+    width: 10em;
+    background: #CCC;
+    border-radius: 4px 0 0 4px;
+    border-right: 1px solid gray;
+}
+.ui-tabs.ui-tabs-vertical .ui-tabs-nav li {
+    clear: left;
+    width: 100%;
+    margin: 0.1em 0;
+    border: 1px solid gray;
+    border-width: 1px 0 1px 1px;
+    border-radius: 4px 0 0 4px;
+    overflow: hidden;
+    position: relative;
+    right: -2px;
+    z-index: 2;
+}
+.ui-tabs.ui-tabs-vertical .ui-tabs-nav li a {
+    display: block;
+    width: 100%;
+    padding: 0.1em 1em;
+}
+.ui-tabs.ui-tabs-vertical .ui-tabs-nav li a:hover {
+    cursor: pointer;
+}
+.ui-tabs.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active {
+    margin-bottom: 0.2em;
+    padding-bottom: 0;
+    border-right: 1px solid white;
+}
+.ui-tabs.ui-tabs-vertical .ui-tabs-nav li:last-child {
+    margin-bottom: 10px;
+}
+.ui-tabs.ui-tabs-vertical .ui-tabs-panel {
+    float: left;
+    width: 34em;
+    border-left: 1px solid gray;
+    border-radius: 0;
+    position: relative;
+    left: -1px;
+}
+
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected {
+    right: -3px !important;
+}
+
+.ui-tabs li i.ui-icon {
+    display: inline-block;
+}
+*/
+.ui-tabs .ui-tabs-panel {
+    /* padding-top: 0 !important; */
+}
+
+.ui-widget-content fieldset {
+  float: left;
+  padding: 0 1em 0 0;
+}
+
+.entity-description {
+  color: #960;
+  font-size: 90%;
+}
+
+.attr-description {
+  padding-top: 1.5em;
+  float: right;
+  width: 17em;
+}
+.attr-annotations {
+    padding-top: 2.5em;
+    clear: both;
+}
+.attr-annotations > span {
+    padding-top: 0.5em;
+    border-top: 1px dashed darkgray;
+    display: block;
+}
+
+.attr-type {
+    color: #990;
+    font-size: 85%;
+}
+.attr-required {
+    color: red;
+    font-size: 85%;
+}
+.attr-unique {
+    color: green;
+    font-size: 85%;
+}
+
+#tabs.nodeEntities {
+  border: 0;
+}
+
+#tabs ul.nodeTabs {
+  background: #fff;
+}
+
+#tabs #Container {
+  border-left: 1px solid #aaa;
+}
+
+#tabs.ui-tabs .ui-tabs-nav li {
+  border-bottom: 1px solid #aaa !important;
+}
+
+.entity-fields {
+  /* height: 400px; */
+  overflow-y: scroll;
+  overflow-x: hidden;
+}
+
+div.boolean label:first-child {
+    float: left;
+    margin-right: 1em;
+}
+div.boolean {
+    padding-bottom: 1em;
+}
+
+.entity-fields label {
+    font-weight: 600;
+    margin-top: 0.5em;
+	display: inline;
+}
+
+.aggregate {
+	text-align: right;
+}
+
+.aggregate i {
+	float: right;
+    margin: 3px 3px 3px 8px;
+}
+
+.aggregate .hastip {
+	padding: 5px;
+}
+
+.subTip .tipsy-inner {
+	background-color: white;
+	color: black;
+	font-size: 1.3em;
+	border: 1px solid black;
+}
+
+.subTip .tipsy-arrow-n { border-bottom-color: black; }
+.subTip .tipsy-arrow-s { border-top-color: black; }
+.subTip .tipsy-arrow-e { border-left-color: black; }
+.subTip .tipsy-arrow-w { border-right-color: black; }
+
+
+.contextMenu {
+    display:none;
+	position:absolute;
+	left:30px;
+	top:-30px;
+	z-index:999;
+	/* width:300px; */
+}
+.contextMenu ul {
+	width:300px;
+	margin:0;
+	padding-left:0;
+	list-style:none;
+	background:#fff;
+	color:#333;
+    font-weight: 600;
+	/* -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px; */
+	-moz-box-shadow:5px 5px 5px #ddd; -webkit-box-shadow:5px 5px 5px #999; box-shadow:5px 5px 5px #ddd;
+	border: 1px solid #aaa;
+}
+.contextMenu ul li {
+	padding:5px 10px;
+	/* border-bottom: solid 1px #ccc; */
+}
+.contextMenu ul li:hover {
+	background:#4a90d9; color:#fff;
+}
+.contextMenu ul li:last-child {
+    border:none;
+}
+
+.na {
+    display: none;
+}
+.contextMenu ul li.new {
+    display: block;
+}
+.contextMenu ul li.adding, .contextMenu ul li.adding + li {
+    display: block;
+}
+.contextMenu ul li.force-display {
+    display: block;
+}
+.contextMenu ul li.context-separator {
+    background-color: lightgray;
+    height: 1px;
+    padding: 0;
+}
+
+.ui-tabs.ui-tabs-vertical .ui-tabs-nav li.separated {
+    margin-top: 1em;
+}
+
+#crosssection {
+    display: none;
+    position: absolute;
+    top: 200px;
+    left: 600px;
+}
+
+.node circle {
+/*  fill: rgb(31, 119, 180);
+  fill-opacity: .25; */
+  fill: #cfe2f3;
+  fill-opacity: .98;
+  stroke: black;
+  stroke-width: 3px;
+}
+
+circle.subcircle {
+    stroke-width: 1px;
+    /* stroke-dasharray: 2; */
+    fill-opacity: 0;
+    stroke: darkgray;
+}
+
+.leaf circle {
+  fill: #6fa8dc;
+  fill-opacity: 0.95;
+  stroke-width: 3px;
+}
+
+.leaf circle[title] {
+    font-family: monospace;
+
+}
+
+#svg_legend {
+    position: absolute;
+    top: 110px;
+    right: 0;
+    border: 1px solid #ccc;
+    border-radius: 5px;
+    background-color: #fcfcfc;
+    margin-right: 1.3em;
+	padding: 1em;
+}
+
+#svg_legend svg {
+    height: 235px;
+    width: 180px;
+}
+
+#multiple_details div.gridStyle {
+/*	height: 50em; */
+	min-height: 70px !important;
+	height: auto !important;
+}
+
+#multiple_details .ngViewport {
+    height: auto !important;
+}
+
+#multiple_details .gridCellButton button, #link_details .gridCellButton button {
+    margin: .25em .4em;
+    font-size: 12px;
+    height: 2em;
+	padding-top: .1em;
+}
+
+#linkFilter {
+	display: none;
+	padding: 0.5em;
+	border: 1px solid grey;
+	background-color: #F0F0F0;
+	position: absolute;
+	z-index: 100;
+	right: 1em;
+}
+div.formLine label, div.formLine input {
+	display: inline-block;
+	padding: 0 8px;
+}
+
+span.filter-icon {
+	padding-left: 1em;
+}
+
+button.filter-close {
+    width: 15px;
+    height: 20px;
+    padding: 0;
+    position: absolute;
+    right: 4px;
+    top: 4px;
+}
+
+div.filter-title h6 {
+	margin: 0 0 0.5em 0;
+}
+
+.links button.btn-filter {
+	padding: 0 1em 0 0;
+    margin-left: 1em;
+    font-size: 1em;
+}
+
+button.btn-filter {
+	float: right;
+}
+span.dynatree-expanded button.btn-filter,
+a.dynatree-title:hover button.btn-filter {
+ 	visibility: visible;
+}
+
+div.hdash-button a {
+	color: white;
+}
+
+.linkDirIn {
+	color: red;
+	background-color: #f3f3f3;
+}
+
+.linkDirOut {
+	color: blue;
+	background-color: white;
+}
+
+div.topoGrid .ui-grid-viewport {
+	overflow: hidden !important;
+}
+
+@-moz-document url-prefix() {
+    .btn {padding: 2px 12px 8px !important;}
+    #overview-controller .btn {padding: 4px 12px !important;}
+    #overview-controller .btn.filter-close {padding: 0 !important;}
+}
+
+.ui-fancytree.fancytree-container {
+	font-size: 14px;
+}
+
+.grid-title {
+    background-color: #FAFAFA;
+    background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
+    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));
+    background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
+    background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
+    background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
+    background-repeat: repeat-x;
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFF', endColorstr='#F2F2F2', GradientType=0);
+    border-bottom: 1px solid #d4d4d4;
+    text-shadow: 0 1px 0 #FFFFFF;
+    border-top-left-radius: 5px;
+    border-top-right-radius: 5px;
+	margin: 0 0 10px 0;
+    padding-bottom: 4px;
+}
+
+.expand-collapse {
+	float: right;
+	margin-right: 0.5em;
+}
+
+.pane-viewport {
+	top: 24px !important;
+}
+.dynatree-node.loading {
+  position: initial;
+}
+
+.hideLeft {
+  position: absolute;
+  right: 0.5em;
+  top: 1em;
+  border: 0;
+}
+
+.showLeft {
+  position: absolute;
+  top: 1em;
+  left: 0.5em;
+  border: 0;
+}
+
+.newChart {
+  float: right;
+}
+
+select.unique, input.unique {
+  border: 2px solid blue;
+}
+select.required, input.required {
+  border: 2px solid black;
+}
+
+.required-indicator {
+  padding-left: 0.5em;
+  font-size: 0.85em;
+  vertical-align: super;
+}
+
+.required-indicator::before {
+  content: '(required)'
+}
+
+.unique-indicator {
+  padding-left: 0.5em;
+  font-size: 0.85em;
+  vertical-align: super;
+}
+
+.unique-indicator::before {
+  content: '(must be unique if supplied)'
+}
+
+.unique-indicator
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/79ae73f9/console/hawtio/src/main/webapp/plugin/css/plugin.css
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/css/plugin.css b/console/hawtio/src/main/webapp/plugin/css/plugin.css
deleted file mode 120000
index b94a926..0000000
--- a/console/hawtio/src/main/webapp/plugin/css/plugin.css
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/css/plugin.css
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/css/plugin.css b/console/hawtio/src/main/webapp/plugin/css/plugin.css
new file mode 100644
index 0000000..20fd0fb
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/css/plugin.css
@@ -0,0 +1,994 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+main-display > .span8 {
+  height: 100%;
+  position: relative;
+}
+
+ul.qdrListNodes > li > span {
+  padding: 6px 20px; 6px; 6px;
+  display: block;
+}
+
+.qdrList .gridStyle {
+    width: 20em;
+    margin-right: 0;
+    float: left;
+}
+
+
+.qdrList div.gridDetails {
+    width: auto;
+}
+
+div.gridDetails {
+    margin-left: 1em;
+}
+
+.selectedItems {
+    /* margin-left: 21em; */
+}
+
+.qdrListPane {
+    top: 110px;
+}
+
+.qdrListActions {
+    width: auto;
+    margin-left: 1em;
+}
+
+div.listAttrName {
+    padding-top: 5px;
+}
+
+div.listAttrName i.icon-bar-chart {
+    float: right;
+    margin: 3px 5px;
+}
+
+div.listAttrName i.icon-bar-chart.active, div.hastip i.icon-bar-chart.active, li.haschart i {
+    background-color: #AAFFAA;
+}
+
+div#main div ul.nav li a:not(.btn) {
+    background: initial !important;
+}
+
+div#main div ul.nav li.active a {
+    background-color: #f0f0ff !important;
+}
+
+div#main.qdr {
+    margin-top: 56px !important;
+}
+
+div.charts-header {
+  font-size: 1.2em;
+  color: #666666;
+  margin: 1em 0;
+}
+
+.selectedNode, .selectedAction, .selectedEntity {
+    font-weight: 600;
+    color: #606066;
+}
+
+.okButton {
+    text-align: center;
+    margin: 1em;
+}
+
+span.showChartsLink {
+    border: 1px solid blue;
+    padding: 1px 2px;
+}
+
+div.listGraphs p {
+    margin: 1em 0 2em 2em;
+    text-align: center;
+}
+
+div.centered {
+    text-align: center;
+    margin: 4em;
+}
+
+.modal-body.centered {
+	margin: 0;
+}
+
+/* dialog */
+div.aChart {
+    height: 200px;
+    width:  400px;
+    margin: 1em;
+}
+
+/* dashboard */
+div.aChart.hDash {
+	/* width: 21em; */
+	/* height: 17em; */
+	width: 100%;
+	height: 87%;
+	margin: 0;
+	padding: 0;
+
+}
+div.chartContainer {
+    float: left;
+	width: 100%;
+	height: 100%;
+	overflow: hidden;
+}
+
+/* the x and y axis lines */
+.d3Chart g.axis path.domain {
+    stroke-width: 1;
+    stroke: black;
+}
+
+/* the line surrounding the area chart */
+div.d3Chart path {
+/*    stroke: black; */
+    stroke-width: 0;
+/*	opacity: 0.5; */
+}
+
+/* the line above the area chart */
+/* the color gets overridden */
+div.d3Chart path.line {
+    stroke: steelblue;
+    stroke-width: 1.5;
+    fill: none;
+    opacity: 1;
+}
+
+.mo-rect {
+    fill: #ffffdd;
+    stroke: #f0f0f0;
+    stroke-width: 1;
+}
+
+.mo-guide {
+    fill: none;
+    stroke: #d0d0d0;
+    stroke-width: 2;
+    stroke-dasharray: 3,3;
+}
+
+div.d3Chart .title {
+    text-decoration: underline;
+}
+
+
+.axis line, .axis path {
+  fill: none;
+  shape-rendering: crispEdges;
+  stroke-width: 1;
+  stroke: #000000;
+}
+
+.axis line {
+  stroke: #C0C0C0;
+  stroke-dasharray: 1,1;
+  opacity: 0.5;
+}
+
+.y.axis text, .x.axis text, .focus text, div.d3Chart .title {
+    font-size: 12px;
+}
+
+.y.axis path {
+   stroke: #000;
+ }
+
+.overlay {
+   fill: none;
+   pointer-events: all;
+ }
+
+.focus circle {
+   fill: none;
+   stroke: steelblue;
+ }
+.focus .fo-table {
+	/* box-shadow: 2px 2px 3px #EEE; */
+}
+
+div.d3Chart {
+    padding: 1em 0;
+    border: 1px solid #C0C0C0;
+}
+div.d3Chart.hDash {
+    border: 0px;
+}
+
+div.d3Chart .axis path {
+	display: inherit;
+}
+.c3-circle {
+	display: none;
+}
+
+.fo-table {
+	border: 1px solid darkgray;
+	background-color: white;
+	font-size: .85em;
+}
+
+.fo-table td {
+	padding: 4px;
+	border-left: 1px solid darkgray;
+}
+.fo-table tr.detail td {
+	padding: 1px 4px;
+}
+.fo-title {
+	color: white;
+	background-color: darkgray;
+}
+
+.fo-table-legend {
+	width: 8px;
+	height: 8px;
+	border: 1px solid black;
+	margin: 0 4px;
+	display: inline-block;
+}
+
+svg .legend {
+	dominant-baseline: central;
+}
+
+div.chartContainer div.aChart {
+    margin-top: 0.5em;
+}
+
+#list-controller .tree-header {
+    position: absolute;
+    height: auto;
+}
+
+#list-controller select {
+  height: 25px;
+  float: left;
+  padding: 0;
+}
+
+
+div#main.qdr div ul.nav li.active a {
+  background-color: #e0e0ff !important;
+  color: #000000;
+}
+
+div#main.qdr .selected, .box.selected {
+  color: #000000;
+  text-shadow: none;
+}
+
+/* the selected node on the list page */
+div.qdrList li.active, ul.qdrListNodes li.active {
+    background-color: #e0e0ff;
+}
+
+div.qdr-attributes span.dynatree-selected a {
+    background-color: #e0e0ff;
+}
+div.qdr-attributes.pane, div.qdr-topology.pane {
+	position: absolute;
+	margin-left: 10px;
+}
+div.qdr-overview.pane {
+	position: absolute;
+}
+div.qdr-topology.pane.left {
+	width: auto;
+  /*border-right: 1px solid lightgray; */
+}
+
+/* the selected row in the name table */
+div#main.qdr div.qdrList div.selected {
+  background-color: #e0e0ff !important;
+}
+
+#dialogChart, #dialogEditChart {
+    height: 200px;
+}
+
+.chartOptions .modal-body {
+  overflow-y: initial;
+}
+
+div.qdrCharts p.chartLabels button {
+    float: right;
+}
+
+div.qdrCharts p.chartLabels {
+     padding-right: 1em;;
+ }
+
+p.dialogHeader {
+    text-align: center;
+}
+
+p.dialogHeader input {
+    margin-top: 10px;
+    width: 480px;
+}
+
+.ui-slider-tick {
+  position: absolute;
+  background-color: #666;
+  width: 2px;
+  height: 8px;
+  top: 12px;
+  z-index: -1;
+}
+
+label.rateGroup {
+    float: left;
+}
+
+div.chartOptions div.dlg-slider {
+    float: left;
+    width: 28em;
+    font-size: 14px;
+}
+
+div.chartOptions div.duration {
+  width: 35em !important;
+}
+
+div.chartOptions .slider {
+    margin-top: 1em;
+    margin-bottom: 1em;
+}
+
+input[type="radio"] {
+    margin-top: 0 !important;
+}
+
+div.chartOptions legend {
+    font-size: 1.2em;
+    font-weight: bold;
+    margin-bottom: 10px;
+}
+
+div.chartOptions tab > div {
+  margin-left: 1em;
+}
+
+div.chartOptions span.minicolors-swatch {
+    width: 14px;
+    height: 14px;
+}
+
+.minicolors-input {
+    width: 4em;
+    padding: 0 0 0 24px !important;
+}
+
+div.colorPicker div.colorText {
+	display: inline-block;
+	width: 10em;
+}
+div.colorPicker div:nth-of-type(1), /* first span under div.colorPicker */
+ div.minicolors{
+    float:left;
+    margin-right: 0.5em;
+}
+
+div.chartOptions p.sep {
+    height: 1em;
+}
+
+ul.nav-tabs {
+    border-bottom: 1px solid #ddd !important;
+}
+
+.chartOptions ul.nav-tabs {
+    margin-bottom: 0px !important;
+}
+
+div.tabbable div.tab-content {
+    overflow: visible;
+}
+
+div.tabbable ul.nav-tabs > .active > a {
+  background-color: #f8f8f8;
+  border: 1px solid #ddd;
+  border-bottom-color: transparent;
+}
+
+
+div.tabbable .tab-pane {
+    background-color: #f8f8f8;
+    padding: 12px;
+    border-right: 1px solid #ddd;
+    border-left: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+}
+div.dlg-large div.tabbable .tab-pane {
+	margin-left: 11em;
+}
+
+div.tabbable ul.nav-tabs {
+  margin-bottom: 0;
+}
+
+ul.qdrTopoModes {
+    position: relative;
+    top: -10px;
+}
+.overview.section {
+	/* width: 35em; */
+}
+.overview.section .ngGrid {
+	height: 12em !important;
+	min-height: 12em !important;
+}
+
+.overview.routers.section .ngGrid {
+ 	height: 16em !important;
+ 	min-height: 16em !important;
+}
+.overview.routers.section {
+ 	/*width: 15em; */
+ }
+
+.grid-align-value {
+	text-align: right;
+}
+
+.grid-align-value .ngCellText {
+	padding-right: 10px;
+}
+
+.overview .ngRow:hover {
+	background:#e0e0ff;
+}
+
+.overview-cell .ngCell:hover {
+	background:#e0e0ff;
+}
+.overview-cell .ngCell.col0:hover, .overview-cell .ngCell.col1:hover {
+	background: initial;
+}
+
+
+.qdr-overview.pane.left, .qdr-attributes.pane.left {
+	top: 104px;
+}
+.qdr-topology.pane.left {
+	top: 104px;
+}
+.qdr-overview.pane.left, .qdr-attributes.pane.left, .qdr-topology.pane.left {
+	left: 10px;
+}
+
+.treeContainer {
+	width: 100%;
+	float: left;
+}
+
+.pane-content {
+	overflow: auto;
+}
+
+#entityNames {
+    width: 20em;
+    float: left;
+}
+
+.treeDetails {
+	margin-left: 260px;
+}
+
+.gridStyle:not(.noHighlight) .ui-grid-row:hover .ui-grid-cell-contents {
+	background-color: #e0e0ff;
+}
+
+.ngCellText {
+	padding: 4px 0 0 4px;
+}
+
+.overview {
+	border-bottom: 1px solid #d4d4d4;
+}
+
+.ui-grid-row.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {
+  background-color: #e0e0ff;
+}
+
+.tab-content .tab-pane {
+    background-color: #f8f8f8;
+    padding: 12px;
+    border-right: 1px solid #ddd;
+    border-left: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+}
+
+div.chartOptions ul.nav-tabs > .active > a {
+  background-color: #f8f8f8;
+  border: 1px solid #ddd;
+  border-bottom-color: transparent;
+}
+
+div.chartOptions label:nth-of-type(2) {
+    margin-left: 1em;
+}
+div.chartOptions label {
+	font-weight: normal;
+	display: inline-block;
+}
+
+/*
+.form-horizontal .control-label {
+    float: left;
+    width: 160px;
+    padding-top: 5px;
+    text-align: right;
+}
+
+.form-horizontal .controls {
+    margin-left: 180px;
+}
+
+.form-horizontal input,  {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+}
+
+input[type="text"], input[type="number"], input[type="password"] {
+    background-color: #ffffff;
+    border: 1px solid #cccccc;
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+    -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+    -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+    -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+    -o-transition: border linear 0.2s, box-shadow linear 0.2s;
+    transition: border linear 0.2s, box-shadow linear 0.2s;
+}
+
+input[type="text"], input[type="number"], input[type="password"] {
+    display: inline-block;
+    width: 200px;
+    padding: 4px 6px;
+    margin-bottom: 10px;
+    font-size: 14px;
+    line-height: 20px;
+    color: #555555;
+    vertical-align: middle;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+}
+
+.login input[type="checkbox"] {
+	margin-top: 0.75em;
+}
+*/
+
+#dispatch-login-container {
+	/* width: 18.5em; */
+	margin-top: 2em;
+}
+/*
+div.login.container {
+	width: 550px;
+}
+*/
+
+
+#overtree .fancytree-container {
+	border: 0px;
+}
+
+#overtree span.fancytree-alert-icon.ui-icon-refresh {
+	background-position: -64px -80px;
+}
+#overtree span.fancytree-alert-icon.ui-icon-transfer-e-w {
+	background-position: -112px -80px;
+}
+
+#alerts {
+	position: fixed;
+	right: 0;
+	top: 0;
+	z-index: 100;
+}
+
+.alert-enter,
+.alert-leave,
+.alert-move {
+  -webkit-transition: 1s linear all;
+  -moz-transition: 1s linear all;
+  -o-transition: 1s linear all;
+  transition: 1s linear all;
+  position:relative;
+}
+
+.alert-enter {
+  left:-10px;
+  opacity:0;
+}
+.alert-enter.alert-enter-active {
+  left:0;
+  opacity:1;
+}
+
+.alert-leave {
+  left:0;
+  opacity:1;
+}
+.alert-leave.alert-leave-active {
+  left:-10px;
+  opacity:0;
+}
+
+.alert-move {
+  opacity:0.5;
+}
+.alert-move.alert-move-active {
+  opacity:1;
+}
+
+.overview .table-striped tr:hover  td {
+	background-color: #e0e0ff !important;
+}
+
+#entityNames div.ngViewport {
+	overflow-x: hidden;
+}
+
+.connect-column.connect-form {
+	width: 20em;
+}
+
+.chartLabels button a {
+	text-decoration: none;
+}
+
+.fancytree-ico-c.router .fancytree-icon {
+
+}
+
+.tabs-left .nav-tabs {
+	float: left;
+}
+.tabs-left .nav-tabs > li {
+/*	float: initial; */
+}
+
+div.modal.dlg-large {
+	width: 53em;
+}
+
+button.hdash-button a {
+	text-decoration: none;
+	color: #fff;
+}
+
+div.widget-body > div {
+	height: 100%;
+}
+
+div.qdrCharts {
+	height: 100%;
+}
+
+ul.dispatch-view {
+	margin-bottom: 0 !important;
+}
+
+.qdr-overview.pane.left span:not(.dynatree-has-children) .dynatree-icon:before,
+.qdr-attributes.pane.left span:not(.dynatree-has-children) .dynatree-icon:before {
+    color: green;
+}
+
+span:not(.dynatree-has-children).address .dynatree-icon:before,
+span:not(.dynatree-has-children).router\.address .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f0ac";
+}
+span:not(.dynatree-has-children).address.mobile .dynatree-icon:before,
+span:not(.dynatree-has-children).router\.address.mobile .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f109";
+}
+span:not(.dynatree-has-children).address.internal.mobile .dynatree-icon:before,
+span:not(.dynatree-has-children).router\.address.internal.mobile .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f0ac";
+}
+span:not(.dynatree-has-children).address.router .dynatree-icon:before,
+span:not(.dynatree-has-children).router\.address.router .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f047";
+}
+
+span.address-link .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f0ac";
+}
+
+span:not(.dynatree-has-children).connection.external .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f109";
+}
+span:not(.dynatree-has-children).connection.normal .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f08e";
+}
+span:not(.dynatree-has-children).connection.external.quiesced .dynatree-icon:before {
+  font-family: FontAwesome;
+	content: "\f14c";
+	color: red;
+}
+span:not(.dynatree-has-children).connection.inter-router .dynatree-icon:before {
+  font-family: FontAwesome;
+   content: "\f07e";
+}
+span:not(.dynatree-has-children).connection.router-control .dynatree-icon:before {
+  font-family: FontAwesome;
+   content: "\f013";
+}
+span:not(.dynatree-has-children).no-data .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f05e";
+  color: red !important;
+}
+span:not(.dynatree-has-children).loading .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f254";
+}
+span:not(.dynatree-has-children).connector .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f126";
+}
+span:not(.dynatree-has-children).container .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f16c";
+}
+span:not(.dynatree-has-children).log .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f0f6";
+}
+span:not(.dynatree-has-children).router\.node .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f013";
+}
+span:not(.dynatree-has-children).link.inter-router .dynatree-icon:before,
+span:not(.dynatree-has-children).router\.link.inter-router .dynatree-icon:before{
+  font-family: FontAwesome;
+  content: "\f07e";
+}
+span:not(.dynatree-has-children).link.router-control .dynatree-icon:before,
+span:not(.dynatree-has-children).router\.link.router-control .dynatree-icon:before{
+  font-family: FontAwesome;
+  content: "\f013";
+}
+span:not(.dynatree-has-children).link.endpoint .dynatree-icon:before,
+span:not(.dynatree-has-children).router\.link.endpoint .dynatree-icon:before{
+  font-family: FontAwesome;
+  content: "\f109";
+}
+span:not(.dynatree-has-children).link.console .dynatree-icon:before,
+span:not(.dynatree-has-children).router\.link.console .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f108";
+}
+span:not(.dynatree-has-children).listener .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f025";
+}
+span:not(.dynatree-has-children).connection .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f07e";
+}
+span:not(.dynatree-has-children).connection.console .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f108";
+}
+span:not(.dynatree-has-children).waypoint .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f0ec";
+}
+span:not(.dynatree-has-children).router .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f047";
+}
+span:not(.dynatree-has-children).fixedAddress .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f015";
+}
+span:not(.dynatree-has-children).linkRoutePattern .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f039";
+}
+span:not(.dynatree-has-children).allocator .dynatree-icon:before {
+  font-family: FontAwesome;
+  content: "\f170";
+}
+
+.ngCellText {
+/*    color: #333333; */
+}
+
+.changed {
+    color: #339933;
+}
+
+div.dispatch-router div.help {
+    width: auto;
+    padding: 1em;
+    background-color: lavender;
+    border-radius: 6px;
+    margin-top: 1em;
+    text-align: center;
+}
+
+div.operations tr:nth-child(even) {
+	background: #f3f3f3;
+}
+div.operations tr:nth-child(odd), div.operations tr:last-child {
+	background: #fff;
+}
+
+div.operations tr input {
+	margin: 0;
+	padding: 3px 6px;
+}
+div.operations table {
+    width: 100%;
+}
+div.operations th {
+    width: 50%;
+    border-bottom: 1px solid #cccccc;
+    text-align: left;
+}
+div.operations td:nth-child(odd), div.operations th:nth-child(odd) {
+	border-right: 1px solid #cccccc;
+}
+div.operations td:nth-child(odd) {
+	padding-left: 0;
+}
+div.operations td:nth-child(even), div.operations th:nth-child(even) {
+	padding-left: 5px;
+}
+div.operations th {
+	padding: 5px;
+}
+div.operations .tab-pane.active {
+    padding: 12px 12px 12px 0;
+}
+div.operations label {
+    padding-top: 4px;
+    margin-bottom: 4px;
+}
+.qdrListActions .ngGrid {
+	/*min-height: 40em;
+	height: 100%; */
+}
+div.qdrListActions .ngViewport {
+    height: initial !important;
+}
+
+div.operations .boolean {
+    padding-bottom: 0;
+}
+
+table.log-entry {
+    margin-bottom: 1em;
+    border-top: 1px solid black;
+}
+
+table.log-entry pre {
+    background-color: #f5f5f5;
+    color: inherit;
+    margin: 0;
+}
+
+circle.node.normal.console {
+    fill: lightcyan;
+}
+circle.node.artemis {
+    fill: lightgreen;
+}
+circle.node.route-container {
+    fill: orange;
+}
+
+text.console, text.on-demand, text.normal {
+	font-family: FontAwesome;
+	font-weight: normal;
+	font-size: 16px;
+}
+
+@font-face {
+    font-family:"Brokers";
+    src: url("brokers.ttf") /* TTF file for CSS3 browsers */
+}
+
+text.artemis {
+    font-family: Brokers;
+    font-size: 20px;
+    font-weight: bold;
+}
+
+text.qpid-cpp {
+    font-family: Brokers;
+    font-size: 18px;
+    font-weight: bold;
+}
+
+i.red {
+	color: red;
+}
+
+.qdrListActions div.delete {
+    width: 20em;
+    margin: auto;
+    border: 1px solid #eaeaea;
+    height: 5em;
+    padding: 4em;
+    background-color: #fcfcfc;
+}
+
+.btn:focus {
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+}
+
+select:focus, input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus {
+	outline:3px solid rgba(82, 168, 236, 0.6);
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+    outline: 5px auto -webkit-focus-ring-color;
+    outline-offset: -2px;
+}
+
+btn.disabled, .btn[disabled] {
+    opacity: 0.35;
+}
+
+#dispatch-login-container .ng-invalid-range {
+	border-color: #e9322d !important;
+}
+
+div#durationSlider, div#rateSlider {
+	margin-top: 1em;
+}
+
+.list-grid {
+	padding-left: 10px;
+}
+
+.ngViewport.ng-scope {
+  height: auto !important;
+}
+
+div#list-controller {
+    padding-left: 300px;
+}
+
+.listening-on {
+    background-color: #CCFFCC;
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[4/4] qpid-dispatch git commit: DISPATCH-886 Account for / in router name and prevent script injections

Posted by ea...@apache.org.
DISPATCH-886 Account for / in router name and prevent script injections


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/55d7bd34
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/55d7bd34
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/55d7bd34

Branch: refs/heads/master
Commit: 55d7bd34bc14aad781754cab3c987bba79a36b5f
Parents: 79ae73f
Author: Ernest Allen <ea...@redhat.com>
Authored: Wed Nov 29 14:57:56 2017 -0500
Committer: Ernest Allen <ea...@redhat.com>
Committed: Wed Nov 29 14:57:56 2017 -0500

----------------------------------------------------------------------
 .../main/webapp/plugin/js/qdrChartService.js    | 1155 +++++++++++++++-
 .../hawtio/src/main/webapp/plugin/js/qdrList.js |    5 +
 .../src/main/webapp/plugin/js/qdrOverview.js    |    7 +-
 .../src/main/webapp/plugin/js/qdrSchema.js      |   82 +-
 .../src/main/webapp/plugin/js/qdrService.js     | 1233 +++++++++++++++++-
 .../src/main/webapp/plugin/js/qdrSettings.js    |  189 ++-
 .../src/main/webapp/plugin/lib/rhea-min.js      |    7 +-
 7 files changed, 2672 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/55d7bd34/console/hawtio/src/main/webapp/plugin/js/qdrChartService.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrChartService.js b/console/hawtio/src/main/webapp/plugin/js/qdrChartService.js
deleted file mode 120000
index dc5df4c..0000000
--- a/console/hawtio/src/main/webapp/plugin/js/qdrChartService.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/js/qdrChartService.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrChartService.js b/console/hawtio/src/main/webapp/plugin/js/qdrChartService.js
new file mode 100644
index 0000000..cc64981
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrChartService.js
@@ -0,0 +1,1154 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+/**
+ * @module QDR
+ */
+var QDR = (function(QDR) {
+
+  // The QDR chart service handles periodic gathering data for charts and displaying the charts
+  QDR.module.factory("QDRChartService", ['$rootScope', 'QDRService', '$http', '$resource', '$location',
+    function($rootScope, QDRService, $http, $resource, $location) {
+
+      var instance = 0; // counter for chart instances
+      var bases = [];
+      var findBase = function(name, attr, request) {
+        for (var i = 0; i < bases.length; ++i) {
+          var base = bases[i];
+          if (base.equals(name, attr, request))
+            return base;
+        }
+        return null;
+      }
+
+      function ChartBase(name, attr, request) {
+        // the base chart attributes
+        this.name = name; // the record's "name" field
+        this.attr = attr; // the record's attr field to chart
+        this.request = request; // the associated request that fetches the data
+
+        // copy the savable properties to an object
+        this.copyProps = function(o) {
+          o.name = this.name;
+          o.attr = this.attr;
+          this.request.copyProps(o);
+        }
+
+        this.equals = function(name, attr, request) {
+          return (this.name == name && this.attr == attr && this.request.equals(request));
+        }
+      };
+
+      // Object that represents a visible chart
+      // There can be multiple of these per ChartBase (eg. one rate  and one value chart)
+      function Chart(opts, request) { //name, attr, cinstance, request) {
+
+        var base = findBase(opts.name, opts.attr, request);
+        if (!base) {
+          base = new ChartBase(opts.name, opts.attr, request);
+          bases.push(base);
+        }
+        this.base = base;
+        this.instance = angular.isDefined(opts.instance) ? opts.instance : ++instance;
+        this.dashboard = false; // is this chart on the dashboard page
+        this.hdash = false; // is this chart on the hawtio dashboard page
+        this.hreq = false; // has this hdash chart been requested
+        this.type = opts.type ? opts.type : "value"; // value or rate
+        this.rateWindow = opts.rateWindow ? opts.rateWindow : 1000; // calculate the rate of change over this time interval. higher == smother graph
+        this.areaColor = "#cbe7f3"; // the chart's area color when not an empty string
+        this.lineColor = "#058dc7"; // the chart's line color when not an empty string
+        this.visibleDuration = opts.visibleDuration ? opts.visibleDuration : 10; // number of minutes of data to show (<= base.duration)
+        this.userTitle = null; // user title overrides title()
+
+        // generate a unique id for this chart
+        this.id = function() {
+            var name = this.name()
+            var nameparts = name.split('/');
+            if (nameparts.length == 2)
+              name = nameparts[1];
+            var key = QDRService.nameFromId(this.request().nodeId) + this.request().entity + name + this.attr() + "_" + this.instance + "_" + (this.request().aggregate ? "1" : "0");
+            // remove all characters except letters,numbers, and _
+            return key.replace(/[^\w]/gi, '')
+          }
+          // copy the savable properties to an object
+        this.copyProps = function(o) {
+          o.type = this.type;
+          o.rateWindow = this.rateWindow;
+          o.areaColor = this.areaColor;
+          o.lineColor = this.lineColor;
+          o.visibleDuration = this.visibleDuration;
+          o.userTitle = this.userTitle;
+          o.dashboard = this.dashboard;
+          o.hdash = this.hdash;
+          o.instance = this.instance;
+          this.base.copyProps(o);
+        }
+        this.name = function(_) {
+          if (!arguments.length) return this.base.name;
+          this.base.name = _;
+          return this;
+        }
+        this.attr = function(_) {
+          if (!arguments.length) return this.base.attr;
+          this.base.attr = _;
+          return this;
+        }
+        this.nodeId = function(_) {
+          if (!arguments.length) return this.base.request.nodeId;
+          this.base.request.nodeId = _;
+          return this;
+        }
+        this.entity = function(_) {
+          if (!arguments.length) return this.base.request.entity;
+          this.base.request.entity = _;
+          return this;
+        }
+        this.aggregate = function(_) {
+          if (!arguments.length) return this.base.request.aggregate;
+          this.base.request.aggregate = _;
+          return this;
+        }
+        this.request = function(_) {
+          if (!arguments.length) return this.base.request;
+          this.base.request = _;
+          return this;
+        }
+        this.data = function() {
+          return this.base.request.data(this.base.name, this.base.attr); // refernce to chart's data array
+        }
+        this.interval = function(_) {
+          if (!arguments.length) return this.base.request.interval;
+          this.base.request.interval = _;
+          return this;
+        }
+        this.duration = function(_) {
+          if (!arguments.length) return this.base.request.duration;
+          this.base.request.duration = _;
+          return this;
+        }
+        this.title = function(_) {
+          var name = this.request().aggregate ? 'Aggregate' : QDRService.nameFromId(this.nodeId());
+          var computed = name +
+            " " + QDRService.humanify(this.attr()) +
+            " - " + this.name()
+          if (!arguments.length) return this.userTitle || computed;
+
+          // don't store computed title in userTitle
+          if (_ === computed)
+            _ = null;
+          this.userTitle = _;
+          return this;
+        }
+        this.title_short = function(_) {
+          if (!arguments.length) return this.userTitle || this.name();
+          return this;
+        }
+        this.copy = function() {
+            var chart = self.registerChart({
+              nodeId: this.nodeId(),
+              entity: this.entity(),
+              name: this.name(),
+              attr: this.attr(),
+              interval: this.interval(),
+              forceCreate: true,
+              aggregate: this.aggregate(),
+              hdash: this.hdash
+            })
+            chart.type = this.type;
+            chart.areaColor = this.areaColor;
+            chart.lineColor = this.lineColor;
+            chart.rateWindow = this.rateWindow;
+            chart.visibleDuration = this.visibleDuration;
+            chart.userTitle = this.userTitle;
+            return chart;
+          }
+          // compare to a chart
+        this.equals = function(c) {
+          return (c.instance == this.instance &&
+            c.base.equals(this.base.name, this.base.attr, this.base.request) &&
+            c.type == this.type &&
+            c.rateWindow == this.rateWindow &&
+            c.areaColor == this.areaColor &&
+            c.lineColor == this.lineColor)
+        }
+      }
+
+      // Object that represents the management request to fetch and store data for multiple charts
+      function ChartRequest(opts) { //nodeId, entity, name, attr, interval, aggregate) {
+        this.duration = opts.duration || 10; // number of minutes to keep the data
+        this.nodeId = opts.nodeId; // eg amqp:/_topo/0/QDR.A/$management
+        this.entity = opts.entity; // eg .router.address
+        // sorted since the responses will always be sorted
+        this.aggregate = opts.aggregate; // list of nodeIds for aggregate charts
+        this.datum = {}; // object containing array of arrays for each attr
+        // like {attr1: [[date,value],[date,value]...], attr2: [[date,value]...]}
+
+        this.interval = opts.interval || 1000; // number of milliseconds between updates to data
+        this.setTimeoutHandle = null; // used to cancel the next request
+        // copy the savable properties to an object
+
+        this.data = function(name, attr) {
+          if (this.datum[name] && this.datum[name][attr])
+            return this.datum[name][attr]
+          return null;
+        }
+        this.addAttrName = function(name, attr) {
+          if (Object.keys(this.datum).indexOf(name) == -1) {
+            this.datum[name] = {}
+          }
+          if (Object.keys(this.datum[name]).indexOf(attr) == -1) {
+            this.datum[name][attr] = [];
+          }
+        }
+        this.addAttrName(opts.name, opts.attr)
+
+        this.copyProps = function(o) {
+          o.nodeId = this.nodeId;
+          o.entity = this.entity;
+          o.interval = this.interval;
+          o.aggregate = this.aggregate;
+          o.duration = this.duration;
+        }
+
+        this.removeAttr = function(name, attr) {
+          if (this.datum[name]) {
+            if (this.datum[name][attr]) {
+              delete this.datum[name][attr]
+            }
+          }
+          return this.attrs().length;
+        }
+
+        this.equals = function(r, entity, aggregate) {
+          if (arguments.length == 3) {
+            var o = {
+              nodeId: r,
+              entity: entity,
+              aggregate: aggregate
+            }
+            r = o;
+          }
+          return (this.nodeId === r.nodeId && this.entity === r.entity && this.aggregate == r.aggregate)
+        }
+        this.names = function() {
+          return Object.keys(this.datum)
+        }
+        this.attrs = function() {
+          var attrs = {}
+          Object.keys(this.datum).forEach(function(name) {
+            Object.keys(this.datum[name]).forEach(function(attr) {
+              attrs[attr] = 1;
+            })
+          }, this)
+          return Object.keys(attrs);
+        }
+      };
+
+      // Below here are the properties and methods available on QDRChartService
+      var self = {
+        charts: [], // list of charts to gather data for
+        chartRequests: [], // the management request info (multiple charts can be driven off of a single request
+
+        init: function() {
+          self.loadCharts();
+          QDRService.addDisconnectAction(function() {
+            self.charts.forEach(function(chart) {
+              self.unRegisterChart(chart, true)
+            })
+            QDRService.addConnectAction(self.init);
+          })
+        },
+
+        findChartRequest: function(nodeId, entity, aggregate) {
+          var ret = null;
+          self.chartRequests.some(function(request) {
+            if (request.equals(nodeId, entity, aggregate)) {
+              ret = request;
+              return true;
+            }
+          })
+          return ret;
+        },
+
+        findCharts: function(opts) { //name, attr, nodeId, entity, hdash) {
+          if (!opts.hdash)
+            opts.hdash = false; // rather than undefined
+          return self.charts.filter(function(chart) {
+            return (chart.name() == opts.name &&
+              chart.attr() == opts.attr &&
+              chart.nodeId() == opts.nodeId &&
+              chart.entity() == opts.entity &&
+              chart.hdash == opts.hdash)
+          });
+        },
+
+        delChartRequest: function(request) {
+          for (var i = 0; i < self.chartRequests.length; ++i) {
+            var r = self.chartRequests[i];
+            if (request.equals(r)) {
+              QDR.log.debug("removed request: " + request.nodeId + " " + request.entity);
+              self.chartRequests.splice(i, 1);
+              self.stopCollecting(request);
+              return;
+            }
+          }
+        },
+
+        delChart: function(chart, skipSave) {
+          var foundBases = 0;
+          for (var i = 0; i < self.charts.length; ++i) {
+            var c = self.charts[i];
+            if (c.base === chart.base)
+              ++foundBases;
+            if (c.equals(chart)) {
+              self.charts.splice(i, 1);
+              if (chart.dashboard && !skipSave)
+                self.saveCharts();
+            }
+          }
+          if (foundBases == 1) {
+            var baseIndex = bases.indexOf(chart.base)
+            bases.splice(baseIndex, 1);
+          }
+        },
+
+        registerChart: function(opts) { //nodeId, entity, name, attr, interval, instance, forceCreate, aggregate, hdash) {
+          var request = self.findChartRequest(opts.nodeId, opts.entity, opts.aggregate);
+          if (request) {
+            // add any new attr or name to the list
+            request.addAttrName(opts.name, opts.attr)
+          } else {
+            // the nodeId/entity did not already exist, so add a new request and chart
+            QDR.log.debug("added new request: " + opts.nodeId + " " + opts.entity);
+            request = new ChartRequest(opts); //nodeId, entity, name, attr, interval, aggregate);
+            self.chartRequests.push(request);
+            self.startCollecting(request);
+          }
+          var charts = self.findCharts(opts); //name, attr, nodeId, entity, hdash);
+          var chart;
+          if (charts.length == 0 || opts.forceCreate) {
+            if (!opts.use_instance && opts.instance)
+              delete opts.instance;
+            chart = new Chart(opts, request) //opts.name, opts.attr, opts.instance, request);
+            self.charts.push(chart);
+          } else {
+            chart = charts[0];
+          }
+          return chart;
+        },
+
+        // remove the chart for name/attr
+        // if all attrs are gone for this request, remove the request
+        unRegisterChart: function(chart, skipSave) {
+          // remove the chart
+
+          // TODO: how do we remove charts that were added to the hawtio dashboard but then removed?
+          // We don't get a notification that they were removed. Instead, we could just stop sending
+          // the request in the background and only send the request when the chart's tick() event is triggered
+          //if (chart.hdash) {
+          //  chart.dashboard = false;
+          //  self.saveCharts();
+          //    return;
+          //}
+
+          for (var i = 0; i < self.charts.length; ++i) {
+            var c = self.charts[i];
+            if (chart.equals(c)) {
+              var request = chart.request();
+              self.delChart(chart, skipSave);
+              if (request) {
+                // see if any other charts use this attr
+                for (var i = 0; i < self.charts.length; ++i) {
+                  var c = self.charts[i];
+                  if (c.attr() == chart.attr() && c.request().equals(chart.request()))
+                    return;
+                }
+                // no other charts use this attr, so remove it
+                if (request.removeAttr(chart.name(), chart.attr()) == 0) {
+                  self.stopCollecting(request);
+                  self.delChartRequest(request);
+                }
+              }
+            }
+          }
+          if (!skipSave)
+            self.saveCharts();
+        },
+
+        stopCollecting: function(request) {
+          if (request.setTimeoutHandle) {
+            clearTimeout(request.setTimeoutHandle);
+            request.setTimeoutHandle = null;
+          }
+        },
+
+        startCollecting: function(request) {
+          // Using setTimeout instead of setInterval because the response may take longer than interval
+          request.setTimeoutHandle = setTimeout(self.sendChartRequest, request.interval, request);
+        },
+        shouldRequest: function(request) {
+          // see if any of the charts associated with this request have either dialog, dashboard, or hreq
+          return self.charts.some(function(chart) {
+            return (chart.dashboard || chart.hreq) || (!chart.dashboard && !chart.hdash);
+          });
+        },
+        // send the request
+        sendChartRequest: function(request, once) {
+          if (!once && !self.shouldRequest(request)) {
+            request.setTimeoutHandle = setTimeout(self.sendChartRequest, request.interval, request)
+            return;
+          }
+
+          // ensure the response has the name field so we can associate the response values with the correct chart
+          var attrs = request.attrs();
+          if (attrs.indexOf("name") == -1)
+            attrs.push("name");
+
+          // this is called when the response is received
+          var saveResponse = function(nodeId, entity, response) {
+            if (!response || !response.attributeNames)
+              return;
+            //QDR.log.debug("got chart results for " + nodeId + " " + entity);
+            // records is an array that has data for all names
+            var records = response.results;
+            if (!records)
+              return;
+
+            var now = new Date();
+            var cutOff = new Date(now.getTime() - request.duration * 60 * 1000);
+            // index of the "name" attr in the response
+            var nameIndex = response.attributeNames.indexOf("name");
+            if (nameIndex < 0)
+              return;
+
+            var names = request.names();
+            // for each record returned, find the name/attr for this request and save the data with this timestamp
+            for (var i = 0; i < records.length; ++i) {
+              var name = records[i][nameIndex];
+              // if we want to store the values for some attrs for this name
+              if (names.indexOf(name) > -1) {
+                attrs.forEach(function(attr) {
+                  var data = request.data(name, attr) // get a reference to the data array
+                  if (data) {
+                    var attrIndex = response.attributeNames.indexOf(attr)
+                    if (request.aggregate) {
+                      data.push([now, response.aggregates[i][attrIndex].sum, response.aggregates[i][attrIndex].detail])
+                    } else {
+                      data.push([now, records[i][attrIndex]])
+                    }
+                    // expire the old data
+                    while (data[0][0] < cutOff) {
+                      data.shift();
+                    }
+                  }
+                })
+              }
+            }
+          }
+          if (request.aggregate) {
+            var nodeList = QDRService.nodeIdList()
+            QDRService.getMultipleNodeInfo(nodeList, request.entity, attrs, saveResponse, request.nodeId);
+          } else {
+            QDRService.fetchEntity(request.nodeId, request.entity, attrs, saveResponse);
+          }
+          // it is now safe to schedule another request
+          if (once)
+            return;
+          request.setTimeoutHandle = setTimeout(self.sendChartRequest, request.interval, request)
+        },
+
+        numCharts: function() {
+          return self.charts.filter(function(chart) {
+            return chart.dashboard
+          }).length;
+          //return self.charts.length;
+        },
+
+        isAttrCharted: function(nodeId, entity, name, attr) {
+          var charts = self.findCharts({
+              name: name,
+              attr: attr,
+              nodeId: nodeId,
+              entity: entity
+            })
+            // if any of the matching charts are on the dashboard page, return true
+          return charts.some(function(chart) {
+            return (chart.dashboard)
+          });
+        },
+
+        addHDash: function(chart) {
+          chart.hdash = true;
+          self.saveCharts();
+        },
+        delHDash: function(chart) {
+          chart.hdash = false;
+          self.saveCharts();
+        },
+        addDashboard: function(chart) {
+          chart.dashboard = true;
+          self.saveCharts();
+        },
+        delDashboard: function(chart) {
+          chart.dashboard = false;
+          self.saveCharts();
+        },
+        // save the charts to local storage
+        saveCharts: function() {
+          var charts = [];
+          var minCharts = [];
+
+          self.charts.forEach(function(chart) {
+            var minChart = {};
+            // don't save chart unless it is on the dashboard
+            if (chart.dashboard || chart.hdash) {
+              chart.copyProps(minChart);
+              minCharts.push(minChart);
+            }
+          })
+          localStorage["QDRCharts"] = angular.toJson(minCharts);
+        },
+        loadCharts: function() {
+          var charts = angular.fromJson(localStorage["QDRCharts"]);
+          if (charts) {
+            // get array of known ids
+            var nodeList = QDRService.nodeList().map(function(node) {
+              return node.id;
+            })
+            charts.forEach(function(chart) {
+              // if this chart is not in the current list of nodes, skip
+              if (nodeList.indexOf(chart.nodeId) >= 0) {
+                if (!angular.isDefined(chart.instance)) {
+                  chart.instance = ++instance;
+                }
+                if (chart.instance >= instance)
+                  instance = chart.instance + 1;
+                if (!chart.duration)
+                  chart.duration = 10;
+                if (chart.nodeList)
+                  chart.aggregate = true;
+                if (!chart.hdash)
+                  chart.hdash = false;
+                if (!chart.dashboard)
+                  chart.dashboard = false;
+                if (!chart.hdash && !chart.dashboard)
+                  chart.dashboard = true;
+                if (chart.hdash && chart.dashboard)
+                  chart.dashboard = false;
+                chart.forceCreate = true;
+                chart.use_instance = true;
+                var newChart = self.registerChart(chart); //chart.nodeId, chart.entity, chart.name, chart.attr, chart.interval, true, chart.aggregate);
+                newChart.dashboard = chart.dashboard;
+                newChart.hdash = chart.hdash;
+                newChart.hreq = false;
+                newChart.type = chart.type;
+                newChart.rateWindow = chart.rateWindow;
+                newChart.areaColor = chart.areaColor ? chart.areaColor : "#cbe7f3";
+                newChart.lineColor = chart.lineColor ? chart.lineColor : "#058dc7";
+                newChart.duration(chart.duration);
+                newChart.visibleDuration = chart.visibleDuration ? chart.visibleDuration : 10;
+                if (chart.userTitle)
+                  newChart.title(chart.userTitle);
+              }
+            })
+          }
+        },
+
+        AreaChart: function(chart) {
+          if (!chart)
+            return;
+
+          // if this is an aggregate chart, show it stacked
+          var stacked = chart.request().aggregate;
+          this.chart = chart; // reference to underlying chart
+          this.svgchart = null;
+          this.url = $location.absUrl();
+
+          // callback function. called by svgchart when binding data
+          // the variable 'this' refers to the svg and not the AreaChart,
+          // but since we are still in the scope of the AreaChart we have access to the passed in chart argument
+          this.chartData = function() {
+
+            var now = new Date();
+            var visibleDate = new Date(now.getTime() - chart.visibleDuration * 60 * 1000);
+            var data = chart.data();
+            var nodeList = QDRService.nodeIdList();
+
+            if (chart.type == "rate") {
+              var rateData = [];
+              var datalen = data.length;
+              k = 0; // inner loop optimization
+              for (var i = 0; i < datalen; ++i) {
+                var d = data[i];
+                if (d[0] >= visibleDate) {
+                  for (var j = k + 1; j < datalen; ++j) {
+                    var d1 = data[j];
+                    if (d1[0] - d[0] >= chart.rateWindow) { // rateWindow is the timespan to calculate rates
+                      var elapsed = Math.max((d1[0] - d[0]) / 1000, 1); // number of seconds that elapsed
+                      var rd = [d1[0], (d1[1] - d[1]) / elapsed]
+                      k = j; // start here next time
+                      // this is a stacked (aggregate) chart
+                      if (stacked) {
+                        var detail = [];
+                        nodeList.forEach(function(node, nodeIndex) {
+                          if (d1[2][nodeIndex] && d[2][nodeIndex])
+                            detail.push({
+                              node: QDRService.nameFromId(node),
+                              val: (d1[2][nodeIndex].val - d[2][nodeIndex].val) / elapsed
+                            })
+                        })
+                        rd.push(detail)
+                      }
+                      rateData.push(rd);
+                      break;
+                    }
+                  }
+                }
+              }
+              // we need at least a point to chart
+              if (rateData.length == 0) {
+                rateData[0] = [chart.data()[0][0], 0, [{
+                  node: '',
+                  val: 0
+                }]];
+              }
+              return rateData;
+            }
+            if (chart.visibleDuration != chart.duration()) {
+              return data.filter(function(d) {
+                return d[0] >= visibleDate
+              });
+            } else
+              return data;
+          }
+
+          this.zoom = function(id, zoom) {
+            if (this.svgchart) {
+              this.svgchart.attr("zoom", zoom)
+              d3.select('#' + id)
+                .data([this.chartData()])
+                .call(this.svgchart)
+            }
+          }
+
+          // called by the controller on the page that displays the chart
+          // called whenever the controller wants to redraw the chart
+          // note: the data is collected independently of how often the chart is redrawn
+          this.tick = function(id) {
+
+            // can't draw charts that don't have data yet
+            if (this.chart.data().length == 0) {
+              return;
+            }
+
+            // if we haven't created the svg yet
+            if (!this.svgchart) {
+
+              // make sure the dom element exists on the page
+              var div = angular.element('#' + id);
+              if (!div)
+                return;
+
+              var width = div.width();
+              var height = div.height();
+
+              // make sure the dom element has a size. otherwise we wouldn't see anything anyway
+              if (!width)
+                return;
+
+              var tooltipGenerator;
+              // stacked charts have a different tooltip
+              if (stacked) {
+                tooltipGenerator = function(d, color, format) {
+                  var html = "<table class='fo-table'><tbody><tr class='fo-title'>" +
+                    "<td align='center' colspan='2' nowrap>Time: " + d[0].toTimeString().substring(0, 8) + "</td></tr>"
+                  d[2].forEach(function(detail) {
+                    html += "<tr class='detail'><td align='right' nowrap>" + detail.node + "<div class='fo-table-legend' style='background-color: " + color(detail.node) + "'></div>" + "</td><td>" + format(detail.val) + "</td></tr>"
+                  })
+                  html += "</tbody></table>"
+                  return html;
+                }
+              } else {
+                tooltipGenerator = function(d, color, format) {
+                  var html = "<table class='fo-table'><tbody><tr class='fo-title'>" +
+                    "<td align='center'>Time</td><td align='center'>Value</td></tr><tr><td>" +
+                    d[0].toTimeString().substring(0, 8) +
+                    "</td><td>" +
+                    format(d[1]) +
+                    "</td></tr></tbody></table>"
+                  return html;
+                }
+              }
+              // create and initialize the chart
+              this.svgchart = self.timeSeriesStackedChart(id, width, height,
+                  QDRService.humanify(this.chart.attr()),
+                  this.chart.name(),
+                  QDRService.nameFromId(this.chart.nodeId()),
+                  this.chart.entity(),
+                  stacked,
+                  this.chart.visibleDuration)
+                .tooltipGenerator(tooltipGenerator);
+
+            }
+            // in case the chart properties have changed, set the new props
+            this.svgchart
+              .attr("type", this.chart.type)
+              .attr("areaColor", this.chart.areaColor)
+              .attr("lineColor", this.chart.lineColor)
+              .attr("url", this.url)
+              .attr("title", this.chart.userTitle);
+
+            // bind the new data and update the chart
+            d3.select('#' + id) // the div id on the page/dialog
+              .data([this.chartData()])
+              .call(this.svgchart); // the charting function
+          }
+        },
+
+        timeSeriesStackedChart: function(id, width, height, attrName, name, node, entity, stacked, visibleDuration) {
+          var margin = {
+              top: 20,
+              right: 18,
+              bottom: 10,
+              left: 15
+            }
+            // attrs that can be changed after the chart is created by using
+            // chart.attr(<attrname>, <attrvalue>);
+          var attrs = {
+            attrName: attrName, // like Deliveries to Container. Put at top of chart
+            name: name, // like router.address/qdrhello  Put at bottom of chart with node
+            node: node, // put at bottom of chart with name
+            entity: entity, // like .router.address  Not used atm
+            title: "", // user title overrides the node and name at the bottom of the chart
+            url: "", // needed to reference filters and clip because of angular's location service
+            type: "value", // value or rate
+            areaColor: "", // can be set for non-stacked charts
+            lineColor: "", // can be set for non-stacked charts
+            zoom: false, // should the y-axis range start at 0 or the min data value
+            visibleDuration: visibleDuration
+          }
+          var width = width - margin.left - margin.right,
+            height = height - margin.top - margin.bottom,
+            yAxisTransitionDuration = 0
+
+          var x = d3.time.scale()
+          var y = d3.scale.linear()
+            .rangeRound([height, 0]);
+          // The x-accessor for the path generator; xScale * xValue.
+          var X = function(d) {
+              return x(d[0])
+            }
+            // The x-accessor for the path generator; yScale * yValue.
+          var Y = function Y(d) {
+            return y(d[1])
+          }
+
+          var xAxis = d3.svg.axis().scale(x).orient("bottom")
+            .outerTickSize(6)
+            .innerTickSize(-(height - margin.top - margin.bottom))
+            .tickPadding(2)
+            .ticks(d3.time.minutes, 2)
+          var yAxis = d3.svg.axis().scale(y).orient("right")
+            .outerTickSize(8)
+            .innerTickSize(-(width - margin.left - margin.right))
+            .tickPadding(10)
+            .ticks(3)
+            .tickFormat(function(d) {
+              return formatValue(d)
+            })
+
+          var tooltipGenerator = function(d, color, format) {
+            return ""
+          }; // should be overridden to set an appropriate tooltip
+          var formatValue = d3.format(".2s");
+          var formatPrecise = d3.format(",");
+          var bisectDate = d3.bisector(function(d) {
+            return d[0];
+          }).left;
+          var line = d3.svg.line();
+
+          var stack = d3.layout.stack()
+            .offset("zero")
+            .values(function(d) {
+              return d.values;
+            })
+            .x(function(d) {
+              return x(d.date);
+            })
+            .y(function(d) {
+              return d.value;
+            });
+
+          var area = d3.svg.area()
+          if (stacked) {
+            area.interpolate("cardinal")
+              .x(function(d) {
+                return x(d.date);
+              })
+              .y0(function(d) {
+                return y(d.y0);
+              })
+              .y1(function(d) {
+                return y(d.y0 + d.y);
+              });
+          } else {
+            area.interpolate("basis").x(X).y1(Y)
+            line.x(X).y(Y)
+          }
+          var color = d3.scale.category20();
+
+          var sv = d3.select("#" + id).append("svg")
+            .attr("width", width + margin.left + margin.right)
+            .attr("height", height + margin.top + margin.bottom)
+          var svg = sv
+            .append("g")
+            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+          sv.append("linearGradient")
+            .attr("id", id) //"temperature-gradient")
+            .attr("gradientUnits", "userSpaceOnUse")
+            .attr("x1", 0).attr("y1", height * .5)
+            .attr("x2", 0).attr("y2", height * 1.2)
+            .selectAll("stop")
+            .data([{
+              offset: "0%",
+              opacity: 1
+            }, {
+              offset: "100%",
+              opacity: 0
+            }])
+            .enter().append("stop")
+            .attr("offset", function(d) {
+              return d.offset;
+            })
+            .attr("stop-opacity", function(d) {
+              return d.opacity;
+            })
+            .attr("stop-color", function(d) {
+              return "#cbe7f3"
+            });
+          /*
+                      var clip = svg.append("defs").append("svg:clipPath")
+                        .attr("id", "clip")
+                        .append("svg:rect")
+                        .attr("id", "clip-rect")
+                        .attr("x", "0")
+                        .attr("y", "0")
+                        .attr("width", width)
+                        .attr("height", height);
+          */
+          // we want all our areas to appear before the axiis
+          svg.append("g")
+            .attr("class", "section-container")
+
+          svg.append("g")
+            .attr("class", "x axis")
+
+          svg.append("g")
+            .attr("class", "y axis")
+
+          svg.append("text").attr("class", "title")
+            .attr("x", (width / 2) - (margin.left + margin.right) / 2)
+            .attr("y", 0 - (margin.top / 2))
+            .attr("text-anchor", "middle")
+            .text(attrs.attrName);
+
+          svg.append("text").attr("class", "legend")
+            .attr("x", (width / 2) - (margin.left + margin.right) / 2)
+            .attr("y", height + (margin.bottom / 2))
+            .attr("text-anchor", "middle")
+            .text(!stacked ? attrs.node + " " + attrs.name : attrs.name);
+
+          var focus = sv.append("g")
+            .attr("class", "focus")
+            .style("display", "none");
+
+          focus.append("circle")
+            .attr("r", 4.5);
+
+          var focusg = focus.append("g");
+          focusg.append("rect")
+            .attr("class", "mo-guide y")
+            .attr("width", 1)
+            .attr("height", height - (margin.top + margin.bottom));
+          focusg.append("rect")
+            .attr("class", "mo-guide x")
+            .attr("width", width - (margin.left + margin.right))
+            .attr("height", 1);
+          focus.append("foreignObject")
+            .attr('class', 'svg-tooltip')
+            .append("xhtml:span");
+          /*
+                  var transition = d3.select({}).transition()
+                      .duration(2000)
+                      .ease("linear");
+          */
+          function chart(selection) {
+            selection.each(function(data) {
+
+              var seriesArr = []
+              if (stacked) {
+                var detailNames = data[0][2].map(function(detail) {
+                  return detail.node
+                })
+                var revNames = angular.copy(detailNames).reverse();
+                color.domain(revNames);
+
+                var series = {};
+                detailNames.forEach(function(name) {
+                  series[name] = {
+                    name: name,
+                    values: []
+                  };
+                  seriesArr.unshift(series[name]); // insert at beginning
+                });
+
+                data.forEach(function(d) {
+                  detailNames.map(function(name, i) {
+                    series[name].values.push({
+                      date: d[0],
+                      value: d[2][i] ? d[2][i].val : 0
+                    });
+                  });
+                });
+
+                // this decorates seriesArr with x,y,and y0 properties
+                stack(seriesArr);
+              }
+
+              var extent = d3.extent(data, function(d) {
+                return d[0];
+              });
+              //var points = data.length;
+              //var futureDate = new Date(data[points-1][0].getTime() - attrs.visibleDuration * 60 * 1000);
+              //extent = [futureDate, data[points-1][0]]
+              x.domain(extent)
+                .range([0, width - margin.left - margin.right]);
+
+              // Update the y-scale.
+              var min = attrs.zoom ? 0 : d3.min(data, function(d) {
+                return d[1]
+              }) * .99;
+              var max = d3.max(data, function(d) {
+                return d[1]
+              }) * 1.01;
+              var mean = d3.mean(data, function(d) {
+                return d[1]
+              });
+              //max = max * 1.01;
+              var diff = (max - min);
+              if (diff == 0) {
+                max = max + 1;
+                diff = 1;
+              }
+              var ratio = mean != 0 ? diff / mean : 1;
+              if (ratio < .05)
+                formatValue = d3.format(".3s")
+
+              if (stacked) {
+                y.domain([min, max])
+                  .range([height - margin.top - margin.bottom, 0]);
+              } else {
+                y
+                  .domain([min, max])
+                  .range([height - margin.top - margin.bottom, 0]);
+              }
+              if (attrs.type == "rate") {
+                area.interpolate("linear"); // rate charts look better smoothed, but the tooltop is in the wrong place
+                line.interpolate("linear");
+//                area.interpolate("basis"); // rate charts look better smoothed
+//                line.interpolate("basis");
+              } else {
+                area.interpolate("linear"); // don't smooth value charts
+                line.interpolate("linear");
+              }
+
+              // adjust the xaxis based on the range of x values (domain)
+              var timeSpan = (extent[1] - extent[0]) / (1000 * 60); // number of minutes
+              if (timeSpan < 1.5)
+                xAxis.ticks(d3.time.seconds, 10);
+              else if (timeSpan < 3)
+                xAxis.ticks(d3.time.seconds, 30);
+              else if (timeSpan < 8)
+                xAxis.ticks(d3.time.minutes, 1);
+              else
+                xAxis.ticks(d3.time.minutes, 2);
+
+              // adjust the number of yaxis ticks based on the range of y values
+              if (formatValue(min) === formatValue(max))
+                yAxis.ticks(2);
+
+              var container = svg.select('.section-container');
+              container.selectAll('.series').remove();
+              if (stacked) {
+                y.domain([Math.min(min, 0), d3.max(seriesArr, function(c) {
+                  return d3.max(c.values, function(d) {
+                    return d.y0 + d.y;
+                  });
+                })]);
+
+                // creates a .series g path for each section in the detail
+                // since we don't get more sections this selection is only run once
+                var series = container.selectAll(".series")
+                  .data(seriesArr)
+
+                series.enter().append("g")
+                  .attr("class", "series")
+                  .append("path")
+                  .attr("class", "streamPath")
+                  .style("fill", function(d) {
+                    return color(d.name);
+                  })
+                  .style("stroke", "grey");
+
+                series.exit().remove()
+
+                // each time the data is updated, update each section
+                container.selectAll(".series .streamPath").data(seriesArr)
+                  .attr("d", function(d) {
+                    return area(d.values);
+                  })
+              } else {
+                var series = container.selectAll(".series")
+                  .data([data], function(d) {
+                    return d;
+                  })
+
+                var g = series.enter().append("g")
+                  .attr("class", "series")
+
+                g.append("path")
+                  .attr("class", "area")
+                  .style("fill", "url(" + attrs.url + "#" + id + ") " + attrs.areaColor) //temperature-gradient)")
+                  .attr("d", area.y0(y.range()[0]))
+                  .attr("transform", null);
+
+                g.append("path")
+                  .attr("class", "line")
+                  .style("stroke", attrs.lineColor)
+                  .attr("d", line)
+                  /*
+                  debugger;
+                              g.transition()
+                                .duration(2000)
+                                              .attr("transform", "translate(-4)");
+                  */
+                series.exit().remove()
+
+                sv.selectAll("stop")
+                  .attr("stop-color", attrs.areaColor)
+
+              }
+              // Update the x-axis.
+              svg.select(".x.axis")
+                .attr("transform", "translate(0," + (height - margin.top - margin.bottom + 1) + ")")
+                .call(xAxis);
+
+              svg.select(".y.axis")
+                .transition().duration(yAxisTransitionDuration) // animate the y axis
+                .attr("transform", "translate(" + (width - margin.right - margin.left) + ",0)")
+                .call(yAxis);
+              yAxisTransitionDuration = 1000 // only do a transition after the chart is 1st drawn
+
+              // TODO: fix this
+              // need to recreate this every update... not sure why
+              var overlay = sv.select(".overlay");
+              if (!overlay.empty())
+                overlay.remove();
+              sv.append("rect")
+                .attr("class", "overlay")
+                .attr("width", width)
+                .attr("height", height)
+                .on("mouseover", function() {
+                  focus.style("display", null)
+                })
+                .on("mouseout", function() {
+                  focus.style("display", "none")
+                })
+                .on("mousemove", mousemove)
+
+              function mousemove() {
+                var x0 = x.invert(d3.mouse(this)[0] - margin.left);
+                var i = bisectDate(data, x0, 1);
+                if (i < data.length && i > 0) {
+                  var d0 = data[i - 1];
+                  var d1 = data[i];
+                  // set d to the data that is closest to the mouse position
+                  var d = x0 - d0[0] > d1[0] - x0 ? d1 : d0;
+                  focus.attr("transform", "translate(" + (x(d[0]) + margin.left) + "," + (y(d[1]) + margin.top) + ")");
+
+                  var tipFormat = formatPrecise;
+                  if (attrs.type === "rate")
+                    tipFormat = d3.format(".2n")
+                    // set the tooltip html and position it
+                  focus.select('.svg-tooltip span')
+                    .html(tooltipGenerator(d, color, tipFormat))
+
+                  var foBounds = focus.select('table')[0][0].getBoundingClientRect();
+                  var mx = x(d[0]); // mouse x
+                  var my = y(d[1]); // mouse y
+
+                  // perfer to put the tooltip in the nw corner relative to the focus circle
+                  var foy = -foBounds.height;
+                  var fox = -foBounds.width;
+                  // off the left side
+                  if (mx - foBounds.width - margin.left < 0)
+                    fox = 0;
+                  // above the top
+                  if (my - foBounds.height - margin.top < 0)
+                    foy = 0;
+                  // won't fit above or below, just put it at bottom
+                  if (my + foBounds.height > height)
+                    foy = -(foBounds.height - (height - my));
+
+                  focus.select('.svg-tooltip')
+                    .attr('x', fox).attr('y', foy);
+
+                  // position the guide lines
+                  focus.select(".mo-guide.y")
+                    .attr("y", -my);
+                  focus.select(".mo-guide.x")
+                    .attr("x", -mx);
+
+                } else {
+                  focus.attr("transform", "translate(-10,-10)");
+                }
+              }
+
+            })
+          }
+          chart.attr = function(attrName, value) {
+            if (arguments.length < 2)
+              return arguments.length == 1 ? attrs[attrName] : chart;
+            if (angular.isDefined(attrs[attrName]))
+              attrs[attrName] = value;
+            return chart;
+          }
+          chart.tooltipGenerator = function(_) {
+            tooltipGenerator = _;
+            return chart;
+          }
+          return chart;
+        }
+      }
+      return self;
+    }
+  ]);
+
+  return QDR;
+}(QDR || {}));

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/55d7bd34/console/hawtio/src/main/webapp/plugin/js/qdrList.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrList.js b/console/hawtio/src/main/webapp/plugin/js/qdrList.js
index bb1a004..b39c37f 100644
--- a/console/hawtio/src/main/webapp/plugin/js/qdrList.js
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrList.js
@@ -308,6 +308,11 @@ var QDR = (function(QDR) {
         updateDetails(row)  // update the table on the right
       }
       scrollTreeDiv.scrollTop(scrollTop)
+      $('.dynatree-title').each( function (idx) {
+        var unsafe = $(this).html()
+        $(this).html(unsafe.replace(/</g, "&lt;").replace(/>/g, "&gt;"))
+      })
+
     }
 
     var schemaProps = function (entityName, key, currentNode) {

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/55d7bd34/console/hawtio/src/main/webapp/plugin/js/qdrOverview.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrOverview.js b/console/hawtio/src/main/webapp/plugin/js/qdrOverview.js
index 065d5d1..4c0fbcf 100644
--- a/console/hawtio/src/main/webapp/plugin/js/qdrOverview.js
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrOverview.js
@@ -1423,7 +1423,12 @@ QDR.log.debug("newly created node needs to be activated")
           activated(newActive)
         }
       }
-     }
+      $('.dynatree-title').each( function (idx) {
+        //QDR.log.info('found a title of ' + $(this).html())
+        var unsafe = $(this).html()
+        $(this).html(unsafe.replace(/</g, "&lt;").replace(/>/g, "&gt;"))
+      })
+   }
 
     // get saved tree state
     var lastKey = loadActivatedNode();

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/55d7bd34/console/hawtio/src/main/webapp/plugin/js/qdrSchema.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrSchema.js b/console/hawtio/src/main/webapp/plugin/js/qdrSchema.js
deleted file mode 120000
index 5010e61..0000000
--- a/console/hawtio/src/main/webapp/plugin/js/qdrSchema.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/js/qdrSchema.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrSchema.js b/console/hawtio/src/main/webapp/plugin/js/qdrSchema.js
new file mode 100644
index 0000000..7365d5a
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrSchema.js
@@ -0,0 +1,81 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+/**
+ * @module QDR
+ */
+var QDR = (function (QDR) {
+
+  QDR.module.controller("QDR.SchemaController", ['$scope', '$location', '$timeout', 'QDRService', function($scope, $location, $timeout, QDRService) {
+    if (!QDRService.connected) {
+      QDRService.redirectWhenConnected("schema")
+      return;
+    }
+    var onDisconnect = function () {
+      $timeout( function () {QDRService.redirectWhenConnected("schema")})
+    }
+    // we are currently connected. setup a handler to get notified if we are ever disconnected
+    QDRService.addDisconnectAction( onDisconnect )
+
+    var keys2kids = function (tree, obj) {
+      if (obj === Object(obj)) {
+        tree.children = []
+        var keys = Object.keys(obj).sort()
+        for (var i=0; i<keys.length; ++i) {
+          var key = keys[i];
+          var kid = {title: key}
+          if (obj[key] === Object(obj[key])) {
+              kid.isFolder = true
+              keys2kids(kid, obj[key])
+          } else {
+            kid.title += (': ' + JSON.stringify(obj[key],null,2))
+          }
+          tree.children.push(kid)
+        }
+      }
+    }
+
+    var tree = []
+    for (var key in QDRService.schema) {
+      var kid = {title: key}
+      kid.isFolder = true
+      var val = QDRService.schema[key]
+      if (val === Object(val))
+        keys2kids(kid, val)
+      else
+        kid.title += (': ' + JSON.stringify(val,null,2))
+
+      tree.push(kid);
+    }
+    $('#schema').dynatree({
+      minExpandLevel: 2,
+      classNames: {
+        expander: 'fa-angle',
+        connector: 'dynatree-no-connector'
+      },
+      children: tree
+    })
+
+      $scope.$on("$destroy", function(event) {
+        QDRService.delDisconnectAction( onDisconnect )
+      });
+
+  }]);
+
+    return QDR;
+}(QDR || {}));


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[3/4] qpid-dispatch git commit: DISPATCH-886 Account for / in router name and prevent script injections

Posted by ea...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/55d7bd34/console/hawtio/src/main/webapp/plugin/js/qdrService.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrService.js b/console/hawtio/src/main/webapp/plugin/js/qdrService.js
deleted file mode 120000
index 2d2a672..0000000
--- a/console/hawtio/src/main/webapp/plugin/js/qdrService.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/js/qdrService.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrService.js b/console/hawtio/src/main/webapp/plugin/js/qdrService.js
new file mode 100644
index 0000000..73102a7
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrService.js
@@ -0,0 +1,1232 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+*/
+/**
+ * @module QDR
+ */
+var QDR = (function(QDR) {
+
+  // The QDR service handles the connection to
+  // the server in the background
+  QDR.module.factory("QDRService", ['$rootScope', '$http', '$timeout', '$resource', '$location', function($rootScope, $http, $timeout, $resource, $location) {
+    var self = {
+
+      rhea: require("rhea"),
+      timeout: 10,             // seconds to wait before assuming a request has failed
+      updateInterval: 2000,   // milliseconds between background updates
+      connectActions: [],
+      disconnectActions: [],
+      updatedActions: {},
+      updating: false,        // are we updating the node list in the background
+      maxCorrelatorDepth: 10, // max number of outstanding requests to allow
+
+      /*
+       * @property message
+       * The proton message that is used to send commands
+       * and receive responses
+       */
+      sender: undefined,
+      receiver: undefined,
+      version: undefined,
+      sendable: false,
+
+      schema: undefined,
+
+      connected: false,
+      gotTopology: false,
+      errorText: undefined,
+      connectionError: undefined,
+
+      addConnectAction: function(action) {
+        if (angular.isFunction(action)) {
+          self.connectActions.push(action);
+        }
+      },
+      addDisconnectAction: function(action) {
+        if (angular.isFunction(action)) {
+          self.disconnectActions.push(action);
+        }
+      },
+      delDisconnectAction: function(action) {
+        if (angular.isFunction(action)) {
+          var index = self.disconnectActions.indexOf(action)
+          if (index >= 0)
+            self.disconnectActions.splice(index, 1)
+        }
+      },
+      addUpdatedAction: function(key, action) {
+        if (angular.isFunction(action)) {
+          self.updatedActions[key] = action;
+        }
+      },
+      delUpdatedAction: function(key) {
+        if (key in self.updatedActions)
+          delete self.updatedActions[key];
+      },
+
+      executeConnectActions: function() {
+        self.connectActions.forEach(function(action) {
+          try {
+            action.apply();
+          } catch (e) {
+            // in case the page that registered the handler has been unloaded
+            QDR.log.info(e.message)
+          }
+        });
+        self.connectActions = [];
+      },
+      executeDisconnectActions: function() {
+        self.disconnectActions.forEach(function(action) {
+          try {
+            action.apply();
+          } catch (e) {
+            // in case the page that registered the handler has been unloaded
+          }
+        });
+        self.disconnectActions = [];
+      },
+      executeUpdatedActions: function() {
+        for (action in self.updatedActions) {
+//          try {
+            self.updatedActions[action].apply();
+/*          } catch (e) {
+QDR.log.debug("caught error executing updated actions")
+console.dump(e)
+            delete self.updatedActions[action]
+          }
+          */
+        }
+      },
+      redirectWhenConnected: function(org) {
+        $location.path(QDR.pluginRoot + "/connect")
+        $location.search('org', org);
+      },
+
+      notifyTopologyDone: function() {
+        if (!self.gotTopology) {
+          QDR.log.debug("topology was just initialized");
+          //console.dump(self.topology._nodeInfo)
+          self.gotTopology = true;
+          //$rootScope.$apply();
+        } else {
+          //QDR.log.debug("topology model was just updated");
+        }
+        self.executeUpdatedActions();
+
+      },
+
+      isConnected: function() {
+        return self.connected;
+      },
+
+      versionCheck: function (minVer) {
+        var verparts = self.version.split('.')
+        var minparts = minVer.split('.')
+        try {
+          for (var i=0; i<minparts.length; ++i) {
+            if (parseInt(minVer[i] > parseInt(verparts[i])))
+              return false
+          }
+        } catch (e) {
+          QDR.log.debug("error doing version check between: " + self.version + " and " + minVer + " " + e.message)
+          return false
+        }
+        return true
+      },
+
+      correlator: {
+        _objects: {},
+        _correlationID: 0,
+
+        corr: function() {
+          var id = ++this._correlationID + "";
+          this._objects[id] = {
+            resolver: null
+          }
+          return id;
+        },
+        request: function() {
+          //QDR.log.debug("correlator:request");
+          return this;
+        },
+        then: function(id, resolver, error) {
+          //QDR.log.debug("registered then resolver for correlationID: " + id);
+          if (error) {
+            //QDR.log.debug("then received an error. deleting correlator")
+            delete this._objects[id];
+            return;
+          }
+          this._objects[id].resolver = resolver;
+        },
+        // called by receiver's on('message') handler when a response arrives
+        resolve: function(context) {
+          var correlationID = context.message.correlation_id;
+          this._objects[correlationID].resolver(context.message.body, context);
+          delete this._objects[correlationID];
+        },
+        depth: function () {
+          return Object.keys(this._objects).length
+        }
+      },
+
+      onSubscription: function() {
+        self.executeConnectActions();
+        var org = $location.search()
+        if (org)
+          org = org.org
+        if (org && org.length > 0 && org !== "connect") {
+          self.getSchema(function () {
+            self.setUpdateEntities([])
+            self.topology.get()
+            self.addUpdatedAction('onSub', function () {
+              self.delUpdatedAction('onSub')
+              $timeout( function () {
+                $location.path(QDR.pluginRoot + '/' + org)
+                $location.search('org', null)
+                $location.replace()
+              })
+            })
+          });
+        }
+      },
+
+      startUpdating: function() {
+        self.stopUpdating(true);
+        QDR.log.info("startUpdating called")
+        self.updating = true;
+        self.topology.get();
+      },
+      stopUpdating: function(silent) {
+        self.updating = false;
+        if (self.topology._getTimer) {
+          clearTimeout(self.topology._getTimer)
+          self.topology._getTimer = null;
+        }
+        if (self.topology._waitTimer) {
+          clearTimeout(self.topology._waitTimer)
+          self.topology._waitTimer = null;
+        }
+        if (self.topology._gettingTopo) {
+          if (self.topology.q)
+            self.topology.q.abort()
+        }
+        if (!silent)
+          QDR.log.info("stopUpdating called")
+      },
+
+      cleanUp: function() {},
+      error: function(line) {
+        if (line.num) {
+          QDR.log.debug("error - num: ", line.num, " message: ", line.message);
+        } else {
+          QDR.log.debug("error - message: ", line.message);
+        }
+      },
+      disconnected: function(line) {
+        QDR.log.debug("Disconnected from QDR server");
+        self.executeDisconnectActions();
+      },
+
+      nameFromId: function(id) {
+        // the router id looks like 'amqp:/topo/0/routerName/$managemrnt'
+        var parts = id.split('/')
+        // handle cases where the router name contains a /
+        parts.splice(0, 3)  // remove amqp, topo, 0
+        parts.pop()         // remove $management
+        return parts.join('/')
+      },
+
+      humanify: function(s) {
+        if (!s || s.length === 0)
+          return s;
+        var t = s.charAt(0).toUpperCase() + s.substr(1).replace(/[A-Z]/g, ' $&');
+        return t.replace(".", " ");
+      },
+      pretty: function(v) {
+        var formatComma = d3.format(",");
+        if (!isNaN(parseFloat(v)) && isFinite(v))
+          return formatComma(v);
+        return v;
+      },
+
+      nodeNameList: function() {
+        var nl = [];
+        for (var id in self.topology._nodeInfo) {
+          nl.push(self.nameFromId(id));
+        }
+        return nl.sort();
+      },
+
+      nodeIdList: function() {
+        var nl = [];
+        for (var id in self.topology._nodeInfo) {
+          nl.push(id);
+        }
+        return nl.sort();
+      },
+
+      nodeList: function() {
+        var nl = [];
+        for (var id in self.topology._nodeInfo) {
+          nl.push({
+            name: self.nameFromId(id),
+            id: id
+          });
+        }
+        return nl;
+      },
+
+      isLargeNetwork: function () {
+        return Object.keys(self.topology._nodeInfo).length >= 12
+      },
+      isMSIE: function () {
+        return (document.documentMode || /Edge/.test(navigator.userAgent))
+      },
+
+      // given an attribute name array, find the value at the same index in the values array
+      valFor: function(aAr, vAr, key) {
+        var idx = aAr.indexOf(key);
+        if ((idx > -1) && (idx < vAr.length)) {
+          return vAr[idx];
+        }
+        return null;
+      },
+
+      isArtemis: function(d) {
+        return (d.nodeType === 'route-container' || d.nodeType === 'on-demand') && (d.properties && d.properties.product === 'apache-activemq-artemis');
+      },
+
+      isQpid: function(d) {
+        return (d.nodeType === 'route-container' || d.nodeType === 'on-demand') && (d.properties && d.properties.product === 'qpid-cpp');
+      },
+
+      isAConsole: function(properties, connectionId, nodeType, key) {
+        return self.isConsole({
+          properties: properties,
+          connectionId: connectionId,
+          nodeType: nodeType,
+          key: key
+        })
+      },
+      isConsole: function(d) {
+        // use connection properties if available
+        return (d && d['properties'] && d['properties']['console_identifier'] === 'Dispatch console')
+      },
+
+      flatten: function(attributes, result) {
+        var flat = {}
+        attributes.forEach(function(attr, i) {
+          if (result && result.length > i)
+            flat[attr] = result[i]
+        })
+        return flat;
+      },
+      isConsoleLink: function(link) {
+        // find the connection for this link
+        var conns = self.topology.nodeInfo()[link.nodeId]['.connection']
+        var connIndex = conns.attributeNames.indexOf("identity")
+        var linkCons = conns.results.filter(function(conn) {
+          return conn[connIndex] === link.connectionId;
+        })
+        var conn = self.flatten(conns.attributeNames, linkCons[0]);
+
+        return self.isConsole(conn)
+      },
+
+      quiesceLink: function(nodeId, name) {
+        function gotMethodResponse(nodeName, entity, response, context) {
+          var statusCode = context.message.application_properties.statusCode;
+          if (statusCode < 200 || statusCode >= 300) {
+            Core.notification('error', context.message.statusDescription);
+            QDR.log.info('Error ' + context.message.statusDescription)
+          }
+        }
+        var attributes = {
+          adminStatus: 'disabled',
+          name: name
+        };
+        self.sendMethod(nodeId, "router.link", attributes, "UPDATE", undefined, gotMethodResponse)
+      },
+      addr_text: function(addr) {
+        if (!addr)
+          return "-"
+        if (addr[0] == 'M')
+          return addr.substring(2)
+        else
+          return addr.substring(1)
+      },
+      addr_class: function(addr) {
+        if (!addr) return "-"
+        if (addr[0] == 'M') return "mobile"
+        if (addr[0] == 'R') return "router"
+        if (addr[0] == 'A') return "area"
+        if (addr[0] == 'L') return "local"
+        if (addr[0] == 'C') return "link-incoming"
+        if (addr[0] == 'E') return "link-incoming"
+        if (addr[0] == 'D') return "link-outgoing"
+        if (addr[0] == 'F') return "link-outgoing"
+        if (addr[0] == 'T') return "topo"
+        return "unknown: " + addr[0]
+      },
+      identity_clean: function(identity) {
+        if (!identity)
+          return "-"
+        var pos = identity.indexOf('/')
+        if (pos >= 0)
+          return identity.substring(pos + 1)
+        return identity
+      },
+
+      queueDepth: function () {
+        var qdepth = self.maxCorrelatorDepth - self.correlator.depth()
+        if (qdepth <= 0)
+          qdepth = 1;
+//QDR.log.debug("queueDepth requested " + qdepth + "(" + self.correlator.depth() + ")")
+        return qdepth;
+      },
+      // check if all nodes have this entity. if not, get them
+      initEntity: function (entity, callback) {
+        var callNeeded = Object.keys(self.topology._nodeInfo).some( function (node) {
+          return !angular.isDefined(self.topology._nodeInfo[node][entity])
+        })
+        if (callNeeded) {
+          self.loadEntity(entity, callback)
+        } else
+          callback()
+      },
+
+      // get/refresh entities for all nodes
+      loadEntity: function (entities, callback) {
+        if (Object.prototype.toString.call(entities) !== '[object Array]') {
+          entities = [entities]
+        }
+        var q = QDR.queue(self.queueDepth())
+        for (node in self.topology._nodeInfo) {
+          for (var i=0; i<entities.length; ++i) {
+            var entity = entities[i]
+            q.defer(self.ensureNodeInfo, node, entity, [], q)
+          }
+        }
+        q.await(function (error) {
+          clearTimeout(self.topology._waitTimer)
+          callback();
+        })
+      },
+
+      // enusre all the topology nones have all these entities
+      ensureAllEntities: function (entityAttribs, callback, extra) {
+        self.ensureEntities(Object.keys(self.topology._nodeInfo), entityAttribs, callback, extra)
+      },
+
+      // ensure these nodes have all these entities. don't fetch unless forced to
+      ensureEntities: function (nodes, entityAttribs, callback, extra) {
+        if (Object.prototype.toString.call(entityAttribs) !== '[object Array]') {
+          entityAttribs = [entityAttribs]
+        }
+        if (Object.prototype.toString.call(nodes) !== '[object Array]') {
+          nodes = [nodes]
+        }
+        var q = QDR.queue(self.queueDepth())
+        for (var n=0; n<nodes.length; ++n) {
+          for (var i=0; i<entityAttribs.length; ++i) {
+            var ea = entityAttribs[i]
+            // if we don'e already have the entity or we want to force a refresh
+            if (!self.topology._nodeInfo[nodes[n]][ea.entity] || ea.force)
+              q.defer(self.ensureNodeInfo, nodes[n], ea.entity, ea.attrs || [], q)
+          }
+        }
+        q.await(function (error) {
+          clearTimeout(self.topology._waitTimer)
+          callback(extra);
+        })
+      },
+
+      // queue up a request to get certain attributes for one entity for a node and return the results
+      fetchEntity: function (node, entity, attrs, callback) {
+        var results = {}
+        var gotResponse = function (nodeName, dotentity, response) {
+          results = response
+        }
+        var q = QDR.queue(self.queueDepth())
+        q.defer(self.fetchNodeInfo, node, entity, attrs, q, gotResponse)
+        q.await(function (error) {
+          callback(node, entity, results)
+        })
+      },
+
+      // get/refreshes entities for all topology.nodes
+      // call doneCallback when all data is available
+      // optionally supply a resultCallBack that will be called as each result is avaialble
+      // if a resultCallBack is supplied, the calling function is responsible for accumulating the responses
+      //   otherwise the responses will be returned to the doneCallback as an object
+      fetchAllEntities: function (entityAttribs, doneCallback, resultCallback) {
+        var q = QDR.queue(self.queueDepth())
+        var results = {}
+        if (!resultCallback) {
+          resultCallback = function (nodeName, dotentity, response) {
+            if (!results[nodeName])
+              results[nodeName] = {}
+            results[nodeName][dotentity] = angular.copy(response);
+          }
+        }
+        var gotAResponse = function (nodeName, dotentity, response) {
+          resultCallback(nodeName, dotentity, response)
+        }
+        if (Object.prototype.toString.call(entityAttribs) !== '[object Array]') {
+          entityAttribs = [entityAttribs]
+        }
+        var nodes = Object.keys(self.topology._nodeInfo)
+        for (var n=0; n<nodes.length; ++n) {
+          for (var i=0; i<entityAttribs.length; ++i) {
+            var ea = entityAttribs[i]
+            q.defer(self.fetchNodeInfo, nodes[n], ea.entity, ea.attrs || [], q, gotAResponse)
+          }
+        }
+        q.await(function (error) {
+          doneCallback(results);
+        })
+      },
+
+      setUpdateEntities: function (entities) {
+        self.topology._autoUpdatedEntities = entities
+      },
+      addUpdateEntity: function (entity) {
+        if (self.topology._autoUpdatedEntities.indexOf(entity) == -1)
+          self.topology._autoUpdatedEntities.push(entity)
+      },
+      delUpdateEntity: function (entity) {
+        var index = self.topology._autoUpdatedEntities.indexOf(entity)
+        if (index != -1)
+          self.topology._autoUpdatedEntities.splice(index, 1)
+      },
+
+      /*
+       * send the management messages that build up the topology
+       *
+       *
+       */
+      topology: {
+        _gettingTopo: false,
+        _nodeInfo: {},
+        _lastNodeInfo: {},
+        _waitTimer: null,
+        _getTimer: null,
+        _autoUpdatedEntities: [],
+        q: null,
+
+        nodeInfo: function() {
+          return self.topology._nodeInfo
+        },
+
+        get: function() {
+          if (self.topology._gettingTopo) {
+            QDR.log.debug("asked to get topology but was already getting it")
+            if (self.topology.q)
+              self.topology.q.abort()
+          }
+          self.topology.q = null
+          if (!self.connected) {
+            QDR.log.debug("topology get failed because !self.connected")
+            return;
+          }
+          if (self.topology._getTimer) {
+            clearTimeout(self.topology._getTimer)
+            self.topology._getTimer = null
+          }
+
+          //QDR.log.info("starting get topology with correlator.depth of " + self.correlator.depth())
+          self.topology._gettingTopo = true;
+          self.errorText = undefined;
+
+          // get the list of nodes to query.
+          // once this completes, we will get the info for each node returned
+          self.getRemoteNodeInfo(function(response, context) {
+            if (Object.prototype.toString.call(response) === '[object Array]') {
+              // remove dropped nodes
+              var keys = Object.keys(self.topology._nodeInfo)
+              for (var i=0; i<keys.length; ++i) {
+                if (response.indexOf(keys[i]) < 0) {
+                  delete self.topology._nodeInfo[keys[i]]
+                }
+              }
+              // add any new nodes
+              // if there is only one node, it will not be returned
+              if (response.length === 0) {
+                var parts = self.receiver.remote.attach.source.address.split('/')
+                parts[parts.length-1] = '$management'
+                response.push(parts.join('/'))
+                //QDR.log.info("GET-MGMT-NODES returned an empty list. Using ")
+                //console.dump(response)
+              }
+              for (var i=0; i<response.length; ++i) {
+                if (!angular.isDefined(self.topology._nodeInfo[response[i]])) {
+                  self.topology._nodeInfo[angular.copy(response[i])] = {};
+                }
+              }
+              // also refresh any entities that were requested
+              self.topology.q = QDR.queue(self.queueDepth())
+              for (var i=0; i<self.topology._autoUpdatedEntities.length; ++i) {
+                var entity = self.topology._autoUpdatedEntities[i]
+                //QDR.log.debug("queuing requests for all nodes for " + entity)
+                for (node in self.topology._nodeInfo) {
+                  self.topology.q.defer(self.ensureNodeInfo, node, entity, [], self.topology.q)
+                }
+              }
+              self.topology.q.await(function (error) {
+                self.topology._gettingTopo = false;
+                self.topology.q = null
+                self.topology.ondone(error)
+              })
+            };
+          });
+        },
+
+        cleanUp: function(obj) {
+          if (obj)
+            delete obj;
+        },
+        timedOut: function(q) {
+          // a node dropped out. this happens when the get-mgmt-nodex
+          // results contains more nodes than actually respond within
+          // the timeout
+          QDR.log.debug("timed out waiting for management responses");
+          // note: can't use 'this' in a timeout handler
+          self.topology.miniDump("state at timeout");
+          q.abort()
+          //self.topology.onerror(Error("management responses are not consistent"));
+        },
+
+        addNodeInfo: function(id, entity, values, q) {
+          clearTimeout(self.topology._waitTimer)
+          // save the results in the nodeInfo object
+          if (id) {
+            if (!(id in self.topology._nodeInfo)) {
+              self.topology._nodeInfo[id] = {};
+            }
+            // copy the values to allow garbage collector to reclaim their memory
+            self.topology._nodeInfo[id][entity] = angular.copy(values)
+          }
+          self.topology.cleanUp(values);
+        },
+        ondone: function(waserror) {
+          clearTimeout(self.topology._getTimer);
+          clearTimeout(self.topology._waitTimer);
+          self.topology._waitTimer = null;
+          if (self.updating)
+            self.topology._getTimer = setTimeout(self.topology.get, self.updateInterval);
+          //if (!waserror)
+            self.notifyTopologyDone();
+        },
+        dump: function(prefix) {
+          if (prefix)
+            QDR.log.info(prefix);
+          QDR.log.info("---");
+          for (var key in self.topology._nodeInfo) {
+            QDR.log.info(key);
+            console.dump(self.topology._nodeInfo[key]);
+            QDR.log.info("---");
+          }
+        },
+        miniDump: function(prefix) {
+          if (prefix)
+            QDR.log.info(prefix);
+          QDR.log.info("---");
+          console.dump(Object.keys(self.topology._nodeInfo));
+          QDR.log.info("---");
+        },
+        onerror: function(err) {
+          self.topology._gettingTopo = false;
+          QDR.log.debug("Err:" + err);
+          //self.executeDisconnectActions();
+        }
+
+      },
+      getRemoteNodeInfo: function(callback) {
+        //QDR.log.debug("getRemoteNodeInfo called");
+
+        setTimeout(function () {
+          var ret;
+          // first get the list of remote node names
+          self.correlator.request(
+            ret = self.sendMgmtQuery('GET-MGMT-NODES')
+          ).then(ret.id, function(response, context) {
+            callback(response, context);
+            self.topology.cleanUp(response);
+          }, ret.error);
+        }, 1)
+      },
+
+      // sends a request and updates the topology.nodeInfo object with the response
+      // should only be called from a q.defer() statement
+      ensureNodeInfo: function (nodeId, entity, attrs, q, callback) {
+        //QDR.log.debug("queuing request for " + nodeId + " " + entity)
+        self.getNodeInfo(nodeId, entity, attrs, q, function (nodeName, dotentity, response) {
+          //QDR.log.debug("got response for " + nodeId + " " + entity)
+          self.topology.addNodeInfo(nodeName, dotentity, response, q)
+          callback(null)
+        })
+        return {
+          abort: function() {
+            delete self.topology._nodeInfo[nodeId]
+            //self.topology._nodeInfo[nodeId][entity] = {attributeNames: [], results: [[]]};
+          }
+        }
+      },
+
+      // sends request and returns the response
+      // should only be called from a q.defer() statement
+      fetchNodeInfo: function (nodeId, entity, attrs, q, heartbeat, callback) {
+        self.getNodeInfo(nodeId, entity, attrs, q, function (nodeName, dotentity, response) {
+          heartbeat(nodeName, dotentity, response)
+          callback(null)
+        })
+      },
+
+      getMultipleNodeInfo: function(nodeNames, entity, attrs, callback, selectedNodeId, aggregate) {
+        if (!angular.isDefined(aggregate))
+          aggregate = true;
+        var responses = {};
+        var gotNodesResult = function(nodeName, dotentity, response) {
+          responses[nodeName] = response;
+        }
+
+        var q = QDR.queue(self.queueDepth())
+        nodeNames.forEach(function(id) {
+            q.defer(self.fetchNodeInfo, id, '.' + entity, attrs, q, gotNodesResult)
+        })
+        q.await(function (error) {
+          if (aggregate)
+            self.aggregateNodeInfo(nodeNames, entity, selectedNodeId, responses, callback);
+          else {
+            callback(nodeNames, entity, responses)
+          }
+        })
+      },
+
+      aggregateNodeInfo: function(nodeNames, entity, selectedNodeId, responses, callback) {
+        //QDR.log.debug("got all results for  " + entity);
+        // aggregate the responses
+        var newResponse = {};
+        var thisNode = responses[selectedNodeId];
+        newResponse['attributeNames'] = thisNode.attributeNames;
+        newResponse['results'] = thisNode.results;
+        newResponse['aggregates'] = [];
+        for (var i = 0; i < thisNode.results.length; ++i) {
+          var result = thisNode.results[i];
+          var vals = [];
+          result.forEach(function(val) {
+            vals.push({
+              sum: val,
+              detail: []
+            })
+          })
+          newResponse.aggregates.push(vals);
+        }
+        var nameIndex = thisNode.attributeNames.indexOf("name");
+        var ent = self.schema.entityTypes[entity];
+        var ids = Object.keys(responses);
+        ids.sort();
+        ids.forEach(function(id) {
+          var response = responses[id];
+          var results = response.results;
+          results.forEach(function(result) {
+            // find the matching result in the aggregates
+            var found = newResponse.aggregates.some(function(aggregate, j) {
+              if (aggregate[nameIndex].sum === result[nameIndex]) {
+                // result and aggregate are now the same record, add the graphable values
+                newResponse.attributeNames.forEach(function(key, i) {
+                  if (ent.attributes[key] && ent.attributes[key].graph) {
+                    if (id != selectedNodeId)
+                      aggregate[i].sum += result[i];
+                  }
+                  aggregate[i].detail.push({
+                    node: self.nameFromId(id) + ':',
+                    val: result[i]
+                  })
+                })
+                return true; // stop looping
+              }
+              return false; // continute looking for the aggregate record
+            })
+            if (!found) {
+              // this attribute was not found in the aggregates yet
+              // because it was not in the selectedNodeId's results
+              var vals = [];
+              result.forEach(function(val) {
+                vals.push({
+                  sum: val,
+                  detail: [{
+                    node: self.nameFromId(id),
+                    val: val
+                  }]
+                })
+              })
+              newResponse.aggregates.push(vals)
+            }
+          })
+        })
+        callback(nodeNames, entity, newResponse);
+      },
+
+
+      getSchema: function(callback) {
+        //QDR.log.info("getting schema");
+        var ret;
+        self.correlator.request(
+          ret = self.sendMgmtQuery('GET-SCHEMA')
+        ).then(ret.id, function(response) {
+          //QDR.log.info("Got schema response");
+          // remove deprecated
+          for (var entityName in response.entityTypes) {
+            var entity = response.entityTypes[entityName]
+            if (entity.deprecated) {
+              // deprecated entity
+              delete response.entityTypes[entityName]
+            } else {
+              for (var attributeName in entity.attributes) {
+                var attribute = entity.attributes[attributeName]
+                if (attribute.deprecated) {
+                  // deprecated attribute
+                  delete response.entityTypes[entityName].attributes[attributeName]
+                }
+              }
+            }
+          }
+          self.schema = response;
+          callback()
+        }, ret.error);
+      },
+
+      getNodeInfo: function(nodeName, entity, attrs, q, callback) {
+        //QDR.log.debug("getNodeInfo called with nodeName: " + nodeName + " and entity " + entity);
+        var timedOut = function (q) {
+          q.abort()
+        }
+        var atimer = setTimeout(timedOut, self.timeout * 1000, q);
+        var ret;
+        self.correlator.request(
+          ret = self.sendQuery(nodeName, entity, attrs)
+        ).then(ret.id, function(response) {
+          clearTimeout(atimer)
+          callback(nodeName, entity, response);
+        }, ret.error);
+      },
+
+      sendMethod: function(nodeId, entity, attrs, operation, props, callback) {
+        setTimeout(function () {
+          var ret;
+          self.correlator.request(
+            ret = self._sendMethod(nodeId, entity, attrs, operation, props)
+          ).then(ret.id, function(response, context) {
+            callback(nodeId, entity, response, context);
+          }, ret.error);
+        }, 1)
+      },
+
+      _fullAddr: function(toAddr) {
+        var toAddrParts = toAddr.split('/');
+        if (toAddrParts.shift() != "amqp:") {
+          self.topology.error(Error("unexpected format for router address: " + toAddr));
+          return;
+        }
+        var fullAddr = toAddrParts.join('/');
+        return fullAddr;
+      },
+
+      _sendMethod: function(toAddr, entity, attrs, operation, props) {
+        var ret = {
+          id: self.correlator.corr()
+        };
+        var fullAddr = self._fullAddr(toAddr);
+        if (!self.sender || !self.sendable) {
+          ret.error = "no sender"
+          return ret;
+        }
+        try {
+          var application_properties = {
+            operation: operation
+          }
+          if (entity) {
+            var ent = self.schema.entityTypes[entity];
+            var fullyQualifiedType = ent ? ent.fullyQualifiedType : entity;
+            application_properties.type = fullyQualifiedType || entity;
+          }
+          if (attrs.name)
+            application_properties.name = attrs.name;
+          if (props) {
+            jQuery.extend(application_properties, props);
+          }
+          var msg = {
+            body: attrs,
+            to: fullAddr,
+            reply_to: self.receiver.remote.attach.source.address,
+            correlation_id: ret.id,
+            application_properties: application_properties
+          }
+          self.sender.send(msg);
+          //console.dump("------- method called -------")
+          //console.dump(msg)
+        } catch (e) {
+          error = "error sending: " + e;
+          QDR.log.error(error)
+          ret.error = error;
+        }
+        return ret;
+      },
+
+      sendQuery: function(toAddr, entity, attrs, operation) {
+        operation = operation || "QUERY"
+        var fullAddr = self._fullAddr(toAddr);
+
+        var body;
+        if (attrs) {
+          body = {
+            "attributeNames": attrs,
+          }
+        } else {
+          body = {
+            "attributeNames": [],
+          }
+        }
+        if (entity[0] === '.')
+          entity = entity.substr(1, entity.length - 1)
+        var prefix = "org.apache.qpid.dispatch."
+        var configs = ["address", "autoLink", "linkRoute"]
+        if (configs.indexOf(entity) > -1)
+          prefix += "router.config."
+        return self._send(body, fullAddr, operation, prefix + entity);
+      },
+
+      sendMgmtQuery: function(operation) {
+        return self._send([], "/$management", operation);
+      },
+
+      _send: function(body, to, operation, entityType) {
+        var ret = {
+          id: self.correlator.corr()
+        };
+        if (!self.sender || !self.sendable) {
+          ret.error = "no sender"
+          return ret;
+        }
+        try {
+          var application_properties = {
+            operation: operation,
+            type: "org.amqp.management",
+            name: "self"
+          };
+          if (entityType)
+            application_properties.entityType = entityType;
+
+          self.sender.send({
+            body: body,
+            to: to,
+            reply_to: self.receiver.remote.attach.source.address,
+            correlation_id: ret.id,
+            application_properties: application_properties
+          })
+        } catch (e) {
+          error = "error sending: " + e;
+          QDR.log.error(error)
+          ret.error = error;
+        }
+        return ret;
+      },
+
+      disconnect: function() {
+        self.connection.close();
+        self.connected = false
+        self.errorText = "Disconnected."
+      },
+
+      connectionTimer: null,
+
+      testConnect: function (options, timeout, callback) {
+        var connection;
+        var allowDelete = true;
+        var reconnect = angular.isDefined(options.reconnect) ? options.reconnect : false
+        var baseAddress = options.address + ':' + options.port;
+        var protocol = "ws"
+        if ($location.protocol() === "https")
+          protocol = "wss"
+        QDR.log.info("testConnect called with reconnect " + reconnect + " using " + protocol + " protocol")
+        try {
+          var ws = self.rhea.websocket_connect(WebSocket);
+          connection = self.rhea.connect({
+            connection_details: ws(protocol + "://" + baseAddress, ["binary"]),
+            reconnect: reconnect,
+              properties: {
+                console_identifier: 'Dispatch console'
+              }
+            }
+          );
+        } catch (e) {
+          QDR.log.debug("exception caught on test connect " + e)
+          self.errorText = "Connection failed "
+          callback({error: e})
+          return
+        }
+        // called when initial connecting fails, and when connection is dropped after connecting
+        connection.on('disconnected', function(context) {
+          if (allowDelete) {
+            delete connection
+            connection.options.reconnect = false
+            //QDR.log.info("connection.on(disconnected) called")
+            callback({error: "failed to connect"})
+          }
+        })
+        connection.on("connection_open", function (context) {
+          allowDelete = false;
+          callback({connection: connection, context: context})
+        })
+      },
+
+      connect: function(options) {
+        var connection;
+        self.topologyInitialized = false;
+        if (!self.connected) {
+          var okay = {
+            connection: false,
+            sender: false,
+            receiver: false
+          }
+          var sender, receiver
+          self.connectionError = undefined;
+
+          var stop = function(context) {
+            //self.stopUpdating();
+            okay.sender = false;
+            okay.receiver = false;
+            okay.connected = false;
+            self.connected = false;
+            self.sender = null;
+            self.receiver = null;
+            self.sendable = false;
+            self.gotTopology = false;
+          }
+          var maybeStart = function() {
+            if (okay.connection && okay.sender && okay.receiver && self.sendable && !self.connected) {
+              //QDR.log.info("okay to start")
+              self.connected = true;
+              self.connection = connection;
+              self.sender = sender;
+              self.receiver = receiver;
+              self.gotTopology = false;
+              self.onSubscription();
+            }
+          }
+          var onDisconnect = function() {
+            //QDR.log.warn("Disconnected");
+            self.connectionError = true;
+            stop();
+            self.executeDisconnectActions();
+          }
+
+          // called after connection.open event is fired or connection error has happened
+          var connectionCallback = function (options) {
+            //QDR.log.info('connectionCallback called')
+            if (!options.error) {
+              //QDR.log.info('there was no error')
+              connection = options.connection
+              self.version = options.context.connection.properties.version
+              QDR.log.debug("connection_opened")
+              okay.connection = true;
+              okay.receiver = false;
+              okay.sender = false;
+
+              connection.on('disconnected', function(context) {
+                //QDR.log.info("connection.on(disconnected) called")
+                self.errorText = "Unable to connect"
+                onDisconnect();
+              })
+              connection.on('connection_close', function(context) {
+                //QDR.log.info("connection closed")
+                self.errorText = "Disconnected"
+                onDisconnect();
+              })
+
+              sender = connection.open_sender();
+              sender.on('sender_open', function(context) {
+                //QDR.log.info("sender_opened")
+                okay.sender = true
+                maybeStart()
+              })
+              sender.on('sendable', function(context) {
+                //QDR.log.debug("sendable")
+                self.sendable = true;
+                maybeStart();
+              })
+
+              receiver = connection.open_receiver({
+                source: {
+                  dynamic: true
+                }
+              });
+              receiver.on('receiver_open', function(context) {
+                //QDR.log.info("receiver_opened")
+                if (receiver.remote && receiver.remote.attach && receiver.remote.attach.source) {
+                  okay.receiver = true;
+                  maybeStart()
+                }
+              })
+              receiver.on("message", function(context) {
+                self.correlator.resolve(context);
+              });
+            } else {
+              //QDR.log.info("there was an error " + options.error)
+              self.errorText = "Unable to connect"
+              onDisconnect();
+            }
+          }
+
+          QDR.log.debug("****** calling rhea.connect ********")
+          if (!options.connection) {
+            QDR.log.debug("rhea.connect was not passed an existing connection")
+            options.reconnect = true
+            self.testConnect(options, 5000, connectionCallback)
+          } else {
+            QDR.log.debug("rhea.connect WAS passed an existing connection")
+            connectionCallback(options)
+          }
+        }
+      }
+    }
+    return self;
+  }]);
+
+  return QDR;
+
+}(QDR || {}));
+
+(function() {
+  console.dump = function(o) {
+    if (window.JSON && window.JSON.stringify)
+      QDR.log.info(JSON.stringify(o, undefined, 2));
+    else
+      console.log(o);
+  };
+})();
+
+function ngGridFlexibleHeightPlugin (opts) {
+    var self = this;
+    self.grid = null;
+    self.scope = null;
+    self.init = function (scope, grid, services) {
+        self.domUtilityService = services.DomUtilityService;
+        self.grid = grid;
+        self.scope = scope;
+        var recalcHeightForData = function () { setTimeout(innerRecalcForData, 1); };
+        var innerRecalcForData = function () {
+            var gridId = self.grid.gridId;
+            var footerPanelSel = '.' + gridId + ' .ngFooterPanel';
+            if (!self.grid.$topPanel || !self.grid.$canvas)
+              return;
+            var extraHeight = self.grid.$topPanel.height() + $(footerPanelSel).height();
+            var naturalHeight = self.grid.$canvas.height() + 1;
+            if (opts != null) {
+                if (opts.minHeight != null && (naturalHeight + extraHeight) < opts.minHeight) {
+                    naturalHeight = opts.minHeight - extraHeight - 2;
+                }
+                if (opts.maxHeight != null && (naturalHeight + extraHeight) > opts.maxHeight) {
+                    naturalHeight = opts.maxHeight;
+                }
+            }
+
+            var newViewportHeight = naturalHeight + 3;
+            if (!self.scope.baseViewportHeight || self.scope.baseViewportHeight !== newViewportHeight) {
+                self.grid.$viewport.css('height', newViewportHeight + 'px');
+                self.grid.$root.css('height', (newViewportHeight + extraHeight) + 'px');
+                self.scope.baseViewportHeight = newViewportHeight;
+                self.domUtilityService.RebuildGrid(self.scope, self.grid);
+            }
+        };
+        self.scope.catHashKeys = function () {
+            var hash = '',
+                idx;
+            for (idx in self.scope.renderedRows) {
+                hash += self.scope.renderedRows[idx].$$hashKey;
+            }
+            return hash;
+        };
+        self.scope.$watch('catHashKeys()', innerRecalcForData);
+        self.scope.$watch(self.grid.config.data, recalcHeightForData);
+    };
+}
+
+if (!String.prototype.startsWith) {
+  String.prototype.startsWith = function (searchString, position) {
+    return this.substr(position || 0, searchString.length) === searchString
+  }
+}
+
+if (!String.prototype.endsWith) {
+  String.prototype.endsWith = function(searchString, position) {
+      var subjectString = this.toString();
+      if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
+        position = subjectString.length;
+      }
+      position -= searchString.length;
+      var lastIndex = subjectString.lastIndexOf(searchString, position);
+      return lastIndex !== -1 && lastIndex === position;
+  };
+}
+
+// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
+if (!Array.prototype.findIndex) {
+  Object.defineProperty(Array.prototype, 'findIndex', {
+    value: function(predicate) {
+     // 1. Let O be ? ToObject(this value).
+      if (this == null) {
+        throw new TypeError('"this" is null or not defined');
+      }
+
+      var o = Object(this);
+
+      // 2. Let len be ? ToLength(? Get(O, "length")).
+      var len = o.length >>> 0;
+
+      // 3. If IsCallable(predicate) is false, throw a TypeError exception.
+      if (typeof predicate !== 'function') {
+        throw new TypeError('predicate must be a function');
+      }
+
+      // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
+      var thisArg = arguments[1];
+
+      // 5. Let k be 0.
+      var k = 0;
+
+      // 6. Repeat, while k < len
+      while (k < len) {
+        // a. Let Pk be ! ToString(k).
+        // b. Let kValue be ? Get(O, Pk).
+        // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+        // d. If testResult is true, return k.
+        var kValue = o[k];
+        if (predicate.call(thisArg, kValue, k, o)) {
+          return k;
+        }
+        // e. Increase k by 1.
+        k++;
+      }
+
+      // 7. Return -1.
+      return -1;
+    }
+  });
+}

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/55d7bd34/console/hawtio/src/main/webapp/plugin/js/qdrSettings.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrSettings.js b/console/hawtio/src/main/webapp/plugin/js/qdrSettings.js
deleted file mode 120000
index 6861eb2..0000000
--- a/console/hawtio/src/main/webapp/plugin/js/qdrSettings.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/js/qdrSettings.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/js/qdrSettings.js b/console/hawtio/src/main/webapp/plugin/js/qdrSettings.js
new file mode 100644
index 0000000..3f0c109
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/js/qdrSettings.js
@@ -0,0 +1,188 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+/**
+ * @module QDR
+ */
+var QDR = (function(QDR) {
+
+  /**
+   * @method SettingsController
+   * @param $scope
+   * @param QDRServer
+   *
+   * Controller that handles the QDR settings page
+   */
+
+  QDR.module.controller("QDR.SettingsController", ['$scope', 'QDRService', '$timeout', '$location', function($scope, QDRService, $timeout, $location) {
+
+    $scope.connecting = false;
+    $scope.connectionError = false;
+    $scope.connectionErrorText = undefined;
+    $scope.forms = {};
+
+    $scope.formEntity = angular.fromJson(localStorage[QDR.SETTINGS_KEY]) || {
+      address: '',
+      port: '',
+      username: '',
+      password: '',
+      autostart: false
+    };
+
+    $scope.$watch('formEntity', function(newValue, oldValue) {
+      if (newValue !== oldValue) {
+        localStorage[QDR.SETTINGS_KEY] = angular.toJson(newValue);
+      }
+    }, true);
+
+    $scope.buttonText = function() {
+      if (QDRService.isConnected()) {
+        return "Disconnect";
+      } else {
+        return "Connect";
+      }
+    };
+
+    $scope.connect = function() {
+      if (QDRService.connected) {
+        $timeout( function () {
+          QDRService.disconnect();
+        })
+        return;
+      }
+
+      if ($scope.settings.$valid) {
+        $scope.connectionError = false;
+        $scope.connecting = true;
+        // timeout so connecting animation can display
+        $timeout(function () {
+          doConnect()
+        })
+      }
+    }
+
+    var doConnect = function(opts) {
+      if (!$scope.formEntity.address)
+        $scope.formEntity.address = "localhost"
+      if (!$scope.formEntity.port)
+        $scope.formEntity.port = 5673
+
+      var failed = function() {
+        $timeout(function() {
+          QDR.log.debug("disconnect action called");
+          $scope.connecting = false;
+          $scope.connectionErrorText = QDRService.errorText;
+          $scope.connectionError = true;
+        })
+      }
+      QDRService.addDisconnectAction(failed);
+      QDRService.addConnectAction(function() {
+        QDRService.delDisconnectAction(failed)
+        QDRService.getSchema(function () {
+          QDR.log.info("got schema after connection")
+          QDRService.addUpdatedAction("initialized", function () {
+            QDRService.delUpdatedAction("initialized")
+            QDR.log.info("got initial topology")
+            $timeout(function() {
+              $scope.connecting = false;
+              if ($location.path().startsWith(QDR.pluginRoot)) {
+                  var searchObject = $location.search();
+                  var goto = "overview";
+                  if (searchObject.org && searchObject.org !== "connect") {
+                    goto = searchObject.org;
+                  }
+                  $location.search('org', null)
+                  $location.path(QDR.pluginRoot + "/" + goto);
+              }
+            })
+          })
+          QDR.log.info("requesting a topology")
+          QDRService.setUpdateEntities([])
+          QDRService.topology.get()
+        })
+      });
+      var options = {address: $scope.formEntity.address, port: $scope.formEntity.port}
+      // if we have already successfully connected (the test connections succeeded)
+      if (opts && opts.connection) {
+        options.connection = opts.connection
+        options.context = opts.context
+      }
+      QDRService.connect(options);
+    }
+  }]);
+
+
+  QDR.module.directive('posint', function() {
+    return {
+      require: 'ngModel',
+
+      link: function(scope, elem, attr, ctrl) {
+        // input type number allows + and - but we don't want them so filter them out
+        elem.bind('keypress', function(event) {
+          var nkey = !event.charCode ? event.which : event.charCode;
+          var skey = String.fromCharCode(nkey);
+          var nono = "-+.,"
+          if (nono.indexOf(skey) >= 0) {
+            event.preventDefault();
+            return false;
+          }
+          // firefox doesn't filter out non-numeric input. it just sets the ctrl to invalid
+          if (/[\!\@\#\$\%^&*\(\)]/.test(skey) && event.shiftKey || // prevent shift numbers
+            !( // prevent all but the following
+              nkey <= 0 || // arrows
+              nkey == 8 || // delete|backspace
+              nkey == 13 || // enter
+              (nkey >= 37 && nkey <= 40) || // arrows
+              event.ctrlKey || event.altKey || // ctrl-v, etc.
+              /[0-9]/.test(skey)) // numbers
+          ) {
+            event.preventDefault();
+            return false;
+          }
+        })
+          // check the current value of input
+        var _isPortInvalid = function(value) {
+          var port = value + ''
+          var isErrRange = false;
+          // empty string is valid
+          if (port.length !== 0) {
+            var n = ~~Number(port);
+            if (n < 1 || n > 65535) {
+              isErrRange = true;
+            }
+          }
+          ctrl.$setValidity('range', !isErrRange)
+          return isErrRange;
+        }
+
+        //For DOM -> model validation
+        ctrl.$parsers.unshift(function(value) {
+          return _isPortInvalid(value) ? undefined : value;
+        });
+
+        //For model -> DOM validation
+        ctrl.$formatters.unshift(function(value) {
+          _isPortInvalid(value);
+          return value;
+        });
+      }
+    };
+  });
+
+  return QDR;
+}(QDR || {}));


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[2/4] qpid-dispatch git commit: DISPATCH-886 Account for / in router name and prevent script injections

Posted by ea...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/55d7bd34/console/hawtio/src/main/webapp/plugin/lib/rhea-min.js
----------------------------------------------------------------------
diff --git a/console/hawtio/src/main/webapp/plugin/lib/rhea-min.js b/console/hawtio/src/main/webapp/plugin/lib/rhea-min.js
deleted file mode 120000
index 6203ad5..0000000
--- a/console/hawtio/src/main/webapp/plugin/lib/rhea-min.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../stand-alone/plugin/lib/rhea-min.js
\ No newline at end of file
diff --git a/console/hawtio/src/main/webapp/plugin/lib/rhea-min.js b/console/hawtio/src/main/webapp/plugin/lib/rhea-min.js
new file mode 100644
index 0000000..13d8344
--- /dev/null
+++ b/console/hawtio/src/main/webapp/plugin/lib/rhea-min.js
@@ -0,0 +1,6 @@
+require=function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){(function(process,Buffer){"use strict";var errors=require("./errors.js");var frames=require("./frames.js");var log=require("./log.js");var sasl=require("./sasl.js");var util=require("./util.js");var EndpointState=require("./endpoint.js");var Session=require("./session.js");var Transport=require("./transport.js");var net=require("net");var tls=require("tls");var EventEmitter=require("events").EventEmitter;var AMQP_PROTOCOL_ID=0;function get_socket_id(socket){if(socket.get_id_string)return socket.get_id_stri
 ng();return socket.localAddress+":"+socket.localPort+" -> "+socket.remoteAddress+":"+socket.remotePort}function session_per_connection(conn){var ssn=null;return{get_session:function(){if(!ssn){ssn=conn.create_session();ssn.begin()}return ssn}}}function restrict(count,f){if(count){var current=count;var reset;return function(successful_attempts){if(reset!==successful_attempts){current=count;reset=successful_attempts}if(current--)return f(successful_attempts);else return-1}}else{return f}}function backoff(initial,max){var delay=initial;var reset;return function(successful_attempts){if(reset!==successful_attempts){delay=initial;reset=successful_attempts}var current=delay;var next=delay*2;delay=max>next?next:max;return current}}function get_connect_fn(options){if(options.transport===undefined||options.transport==="tcp"){return net.connect}else if(options.transport==="tls"||options.transport==="ssl"){return tls.connect}else{throw Error("Unrecognised transport: "+options.transport)}}functi
 on connection_details(options){var details={};details.connect=options.connect?options.connect:get_connect_fn(options);details.host=options.host?options.host:"localhost";details.port=options.port?options.port:5672;details.options=options;return details}var aliases=["container_id","hostname","max_frame_size","channel_max","idle_time_out","outgoing_locales","incoming_locales","offered_capabilities","desired_capabilities","properties"];function remote_property_shortcut(name){return function(){return this.remote.open?this.remote.open[name]:undefined}}var conn_counter=1;var Connection=function(options,container){this.options={};if(options){for(var k in options){this.options[k]=options[k]}if((options.transport==="tls"||options.transport==="ssl")&&options.servername===undefined&&options.host!==undefined){this.options.servername=options.host}}this.container=container;if(!this.options.id){this.options.id="connection-"+conn_counter++}if(!this.options.container_id){this.options.container_id=con
 tainer?container.id:util.generate_uuid()}if(!this.options.connection_details){var self=this;this.options.connection_details=function(){return connection_details(self.options)}}var reconnect=this.get_option("reconnect",true);if(typeof reconnect==="boolean"&&reconnect){var initial=this.get_option("initial_reconnect_delay",100);var max=this.get_option("max_reconnect_delay",6e4);this.options.reconnect=restrict(this.get_option("reconnect_limit"),backoff(initial,max))}else if(typeof reconnect==="number"){var fixed=this.options.reconnect;this.options.reconnect=restrict(this.get_option("reconnect_limit"),function(){return fixed})}this.registered=false;this.state=new EndpointState;this.local_channel_map={};this.remote_channel_map={};this.local={};this.remote={};this.local.open=frames.open(this.options);this.local.close=frames.close({});this.session_policy=session_per_connection(this);this.amqp_transport=new Transport(this.options.id,AMQP_PROTOCOL_ID,frames.TYPE_AMQP,this);this.sasl_transport
 =undefined;this.transport=this.amqp_transport;this.conn_established_counter=0;this.heartbeat_out=undefined;this.heartbeat_in=undefined;this.abort_idle=false;this.socket_ready=false;this.scheduled_reconnect=undefined;this.default_sender=undefined;for(var i in aliases){var f=aliases[i];Object.defineProperty(this,f,{get:remote_property_shortcut(f)})}Object.defineProperty(this,"error",{get:function(){return this.remote.close?this.remote.close.error:undefined}})};Connection.prototype=Object.create(EventEmitter.prototype);Connection.prototype.constructor=Connection;Connection.prototype.dispatch=function(name){log.events("Connection got event: %s",name);if(this.listeners(name).length){EventEmitter.prototype.emit.apply(this,arguments);return true}else if(this.container){return this.container.dispatch.apply(this.container,arguments)}else{return false}};Connection.prototype.reset=function(){if(this.abort_idle){this.abort_idle=false;this.local.close.error=undefined;this.state=new EndpointState
 ;this.state.open()}this.amqp_transport=new Transport(this.options.id,AMQP_PROTOCOL_ID,frames.TYPE_AMQP,this);this.sasl_transport=undefined;this.transport=this.amqp_transport;this.state.disconnected();this.remote={};this.remote_channel_map={};for(var k in this.local_channel_map){this.local_channel_map[k].reset()}this.socket_ready=false};Connection.prototype.connect=function(){this.is_server=false;this._connect(this.options.connection_details(this.conn_established_counter));this.open();return this};Connection.prototype.reconnect=function(){this.scheduled_reconnect=undefined;log.reconnect("reconnecting...");this.reset();this._connect(this.options.connection_details(this.conn_established_counter));process.nextTick(this._process.bind(this));return this};Connection.prototype._connect=function(details){if(details.connect){this.init(details.connect(details.port,details.host,details.options,this.connected.bind(this)))}else{this.init(get_connect_fn(details)(details.port,details.host,details.o
 ptions,this.connected.bind(this)))}return this};Connection.prototype.accept=function(socket){this.is_server=true;log.io("[%s] client accepted: %s",this.id,get_socket_id(socket));this.socket_ready=true;return this.init(socket)};Connection.prototype.init=function(socket){this.socket=socket;if(this.get_option("tcp_no_delay",false)&&this.socket.setNoDelay){this.socket.setNoDelay(true)}this.socket.on("data",this.input.bind(this));this.socket.on("error",this.on_error.bind(this));this.socket.on("end",this.eof.bind(this));if(this.is_server){var mechs;if(this.container&&Object.getOwnPropertyNames(this.container.sasl_server_mechanisms).length){mechs=this.container.sasl_server_mechanisms}if(this.socket.encrypted&&this.socket.authorized&&this.get_option("enable_sasl_external",false)){mechs=sasl.server_add_external(mechs?util.clone(mechs):{})}if(mechs){if(mechs.ANONYMOUS!==undefined&&!this.get_option("require_sasl",false)){this.sasl_transport=new sasl.Selective(this,mechs)}else{this.sasl_transpo
 rt=new sasl.Server(this,mechs)}}else{if(!this.get_option("disable_sasl",false)){var anon=sasl.server_mechanisms();anon.enable_anonymous();this.sasl_transport=new sasl.Selective(this,anon)}}}else{var mechanisms=this.get_option("sasl_mechanisms");if(!mechanisms){var username=this.get_option("username");var password=this.get_option("password");if(username){mechanisms=sasl.client_mechanisms();if(password)mechanisms.enable_plain(username,password);else mechanisms.enable_anonymous(username)}}if(this.socket.encrypted&&this.options.cert&&this.get_option("enable_sasl_external",false)){if(!mechanisms)mechanisms=sasl.client_mechanisms();mechanisms.enable_external()}if(mechanisms){this.sasl_transport=new sasl.Client(this,mechanisms,this.options.sasl_init_hostname||this.options.servername||this.options.host)}}this.transport=this.sasl_transport?this.sasl_transport:this.amqp_transport;return this};Connection.prototype.attach_sender=function(options){return this.session_policy.get_session().attach_
 sender(options)};Connection.prototype.open_sender=Connection.prototype.attach_sender;Connection.prototype.attach_receiver=function(options){if(this.get_option("tcp_no_delay",true)&&this.socket.setNoDelay){this.socket.setNoDelay(true)}return this.session_policy.get_session().attach_receiver(options)};Connection.prototype.open_receiver=Connection.prototype.attach_receiver;Connection.prototype.get_option=function(name,default_value){if(this.options[name]!==undefined)return this.options[name];else if(this.container)return this.container.get_option(name,default_value);else return default_value};Connection.prototype.send=function(msg){if(this.default_sender===undefined){this.default_sender=this.open_sender({target:{}})}return this.default_sender.send(msg)};Connection.prototype.connected=function(){this.socket_ready=true;this.conn_established_counter++;log.io("[%s] connected %s",this.options.id,get_socket_id(this.socket));this.output()};Connection.prototype.sasl_failed=function(text){this.
 transport_error={condition:"amqp:unauthorized-access",description:text};this._handle_error()};Connection.prototype._is_fatal=function(error_condition){var non_fatal=this.get_option("non_fatal_errors",["amqp:connection:forced"]);return non_fatal.indexOf(error_condition)<0};Connection.prototype._handle_error=function(){var error=this.get_error();if(error){var handled=this.dispatch("connection_error",this._context());handled=this.dispatch("connection_close",this._context())||handled;if(!this._is_fatal(error.condition)){this.open()}else if(!handled){this.dispatch("error",new errors.ConnectionError(error.description,error.condition,this))}return true}else{return false}};Connection.prototype.get_error=function(){if(this.transport_error)return this.transport_error;if(this.remote.close&&this.remote.close.error)return this.remote.close.error;return undefined};Connection.prototype._get_peer_details=function(){var s="";if(this.remote.open&&this.remote.open.container){s+=this.remote.open.contai
 ner+" "}if(this.remote.open&&this.remote.open.properties){s+=JSON.stringify(this.remote.open.properties)}return s};Connection.prototype.output=function(){try{if(this.socket&&this.socket_ready){if(this.heartbeat_out)clearTimeout(this.heartbeat_out);this.transport.write(this.socket);if((this.is_closed()&&this.state.has_settled()||this.abort_idle||this.transport_error)&&!this.transport.has_writes_pending()){this.socket.end()}else if(this.is_open()&&this.remote.open.idle_time_out){this.heartbeat_out=setTimeout(this._write_frame.bind(this),this.remote.open.idle_time_out/2)}}}catch(e){if(e.name==="ProtocolError"){console.error("["+this.options.id+"] error on write: "+e+" "+this._get_peer_details()+" "+e.name);this.dispatch("protocol_error",e)||console.error("["+this.options.id+"] error on write: "+e+" "+this._get_peer_details())}else{this.dispatch("error",e)}this.socket.end()}};function byte_to_hex(value){if(value<16)return"0x0"+Number(value).toString(16);else return"0x"+Number(value).toS
 tring(16)}function buffer_to_hex(buffer){var bytes=[];for(var i=0;i<buffer.length;i++){bytes.push(byte_to_hex(buffer[i]))}return bytes.join(",")}Connection.prototype.input=function(buff){var buffer;try{if(this.heartbeat_in)clearTimeout(this.heartbeat_in);log.io("[%s] read %d bytes",this.options.id,buff.length);if(this.previous_input){buffer=Buffer.concat([this.previous_input,buff],this.previous_input.length+buff.length);this.previous_input=null}else{buffer=buff}var read=this.transport.read(buffer,this);if(read<buffer.length){this.previous_input=buffer.slice(read)}if(this.local.open.idle_time_out)this.heartbeat_in=setTimeout(this.idle.bind(this),this.local.open.idle_time_out);if(this.transport.has_writes_pending()){this.output()}else if(this.is_closed()&&this.state.has_settled()){this.socket.end()}else if(this.is_open()&&this.remote.open.idle_time_out&&!this.heartbeat_out){this.heartbeat_out=setTimeout(this._write_frame.bind(this),this.remote.open.idle_time_out/2)}}catch(e){if(e.name
 ==="ProtocolError"){this.dispatch("protocol_error",e)||console.error("["+this.options.id+"] error on read: "+e+" "+this._get_peer_details()+" (buffer:"+buffer_to_hex(buffer)+")")}else{this.dispatch("error",e)}this.socket.end()}};Connection.prototype.idle=function(){if(this.is_open()){this.abort_idle=true;this.local.close.error={condition:"amqp:resource-limit-exceeded",description:"max idle time exceeded"};this.close()}};Connection.prototype.on_error=function(e){console.warn("["+this.options.id+"] error: "+e);this._disconnected()};Connection.prototype.eof=function(){this._disconnected()};Connection.prototype._disconnected=function(){if(this.heartbeat_out)clearTimeout(this.heartbeat_out);if(this.heartbeat_in)clearTimeout(this.heartbeat_in);if(!this.is_closed()&&this.scheduled_reconnect===undefined){if(!this.dispatch("disconnected",this._context())){console.warn("["+this.options.id+"] disconnected ")}if(!this.is_server&&!this.transport_error&&this.options.reconnect){var delay=this.opti
 ons.reconnect(this.conn_established_counter);if(delay>=0){log.reconnect("Scheduled reconnect in "+delay+"ms");this.scheduled_reconnect=setTimeout(this.reconnect.bind(this),delay)}}}};Connection.prototype.open=function(){if(this.state.open()){this._register()}};Connection.prototype.close=function(error){if(error)this.local.close.error=error;if(this.state.close()){this._register()}};Connection.prototype.is_open=function(){return this.state.is_open()};Connection.prototype.is_closed=function(){return this.state.is_closed()};Connection.prototype.create_session=function(){var i=0;while(this.local_channel_map[i])i++;var session=new Session(this,i);this.local_channel_map[i]=session;return session};Connection.prototype.find_sender=function(filter){return this.find_link(util.sender_filter(filter))};Connection.prototype.find_receiver=function(filter){return this.find_link(util.receiver_filter(filter))};Connection.prototype.find_link=function(filter){for(var channel in this.local_channel_map){v
 ar session=this.local_channel_map[channel];var result=session.find_link(filter);if(result)return result}return undefined};Connection.prototype.each_receiver=function(action,filter){this.each_link(util.receiver_filter(filter))};Connection.prototype.each_sender=function(action,filter){this.each_link(util.sender_filter(filter))};Connection.prototype.each_link=function(action,filter){for(var channel in this.local_channel_map){var session=this.local_channel_map[channel];session.each_link(action,filter)}};Connection.prototype.on_open=function(frame){if(this.state.remote_opened()){this.remote.open=frame.performative;this.open();this.dispatch("connection_open",this._context())}else{throw new errors.ProtocolError("Open already received")}};Connection.prototype.on_close=function(frame){if(this.state.remote_closed()){this.remote.close=frame.performative;this.close();if(this.remote.close.error){this._handle_error()}else{this.dispatch("connection_close",this._context())}if(this.heartbeat_out)cle
 arTimeout(this.heartbeat_out)}else{throw new errors.ProtocolError("Close already received")}};Connection.prototype._register=function(){if(!this.registered){this.registered=true;process.nextTick(this._process.bind(this))}};Connection.prototype._process=function(){this.registered=false;do{if(this.state.need_open()){this._write_open()}for(var k in this.local_channel_map){this.local_channel_map[k]._process()}if(this.state.need_close()){this._write_close()}}while(!this.state.has_settled())};Connection.prototype._write_frame=function(channel,frame,payload){this.amqp_transport.encode(frames.amqp_frame(channel,frame,payload));this.output()};Connection.prototype._write_open=function(){this._write_frame(0,this.local.open.described())};Connection.prototype._write_close=function(){this._write_frame(0,this.local.close.described())};Connection.prototype.on_begin=function(frame){var session;if(frame.performative.remote_channel===null||frame.performative.remote_channel===undefined){session=this.cr
 eate_session();session.local.begin.remote_channel=frame.channel}else{session=this.local_channel_map[frame.performative.remote_channel];if(!session)throw new errors.ProtocolError("Invalid value for remote channel "+frame.performative.remote_channel)}session.on_begin(frame);this.remote_channel_map[frame.channel]=session};Connection.prototype.get_peer_certificate=function(){if(this.socket&&this.socket.getPeerCertificate){return this.socket.getPeerCertificate()}else{return undefined}};Connection.prototype.get_tls_socket=function(){if(this.socket&&(this.options.transport==="tls"||this.options.transport==="ssl")){return this.socket}else{return undefined}};Connection.prototype._context=function(c){var context=c?c:{};context.connection=this;if(this.container)context.container=this.container;return context};function delegate_to_session(name){Connection.prototype["on_"+name]=function(frame){var session=this.remote_channel_map[frame.channel];if(!session){throw new errors.ProtocolError(name+" r
 eceived on invalid channel "+frame.channel)}session["on_"+name](frame)}}delegate_to_session("end");delegate_to_session("attach");delegate_to_session("detach");delegate_to_session("transfer");delegate_to_session("disposition");delegate_to_session("flow");module.exports=Connection}).call(this,require("_process"),require("buffer").Buffer)},{"./endpoint.js":2,"./errors.js":3,"./frames.js":5,"./log.js":7,"./sasl.js":10,"./session.js":11,"./transport.js":13,"./util.js":15,_process:25,buffer:19,events:22,net:18,tls:18}],2:[function(require,module,exports){"use strict";var EndpointState=function(){this.init()};EndpointState.prototype.init=function(){this.local_open=false;this.remote_open=false;this.open_requests=0;this.close_requests=0;this.initialised=false};EndpointState.prototype.open=function(){this.initialised=true;if(!this.local_open){this.local_open=true;this.open_requests++;return true}else{return false}};EndpointState.prototype.close=function(){if(this.local_open){this.local_open=f
 alse;this.close_requests++;return true}else{return false}};EndpointState.prototype.disconnected=function(){var was_open=this.local_open;this.init();if(was_open){this.open()}else{this.close()}};EndpointState.prototype.remote_opened=function(){if(!this.remote_open){this.remote_open=true;return true}else{return false}};EndpointState.prototype.remote_closed=function(){if(this.remote_open){this.remote_open=false;return true}else{return false}};EndpointState.prototype.is_open=function(){return this.local_open&&this.remote_open};EndpointState.prototype.is_closed=function(){return this.initialised&&!this.local_open&&!this.remote_open};EndpointState.prototype.has_settled=function(){return this.open_requests===0&&this.close_requests===0};EndpointState.prototype.need_open=function(){if(this.open_requests>0){this.open_requests--;return true}else{return false}};EndpointState.prototype.need_close=function(){if(this.close_requests>0){this.close_requests--;return true}else{return false}};module.exp
 orts=EndpointState},{}],3:[function(require,module,exports){"use strict";var util=require("util");function ProtocolError(message){Error.call(this);this.message=message;this.name="ProtocolError"}util.inherits(ProtocolError,Error);function TypeError(message){ProtocolError.call(this,message);this.message=message;this.name="TypeError"}util.inherits(TypeError,ProtocolError);function ConnectionError(message,condition,connection){Error.call(this,message);this.message=message;this.name="ConnectionError";this.condition=condition;this.description=message;this.connection=connection}util.inherits(ConnectionError,Error);module.exports={ProtocolError:ProtocolError,TypeError:TypeError,ConnectionError:ConnectionError}},{util:34}],4:[function(require,module,exports){"use strict";var amqp_types=require("./types.js");module.exports={selector:function(s){return{"jms-selector":amqp_types.wrap_described(s,77567109365764)}}}},{"./types.js":14}],5:[function(require,module,exports){"use strict";var types=re
 quire("./types.js");var errors=require("./errors.js");var frames={};var by_descriptor={};frames.read_header=function(buffer){var offset=4;var header={};var name=buffer.toString("ascii",0,offset);if(name!=="AMQP"){throw new errors.ProtocolError("Invalid protocol header for AMQP "+name)}header.protocol_id=buffer.readUInt8(offset++);header.major=buffer.readUInt8(offset++);header.minor=buffer.readUInt8(offset++);header.revision=buffer.readUInt8(offset++);if(header.protocol_id===0&&header.major===0&&header.minor===9&&header.revision===1){throw new errors.ProtocolError("Unsupported AMQP version: 0-9-1")}if(header.protocol_id===1&&header.major===1&&header.minor===0&&header.revision===10){throw new errors.ProtocolError("Unsupported AMQP version: 0-10")}if(header.major!==1||header.minor!==0){throw new errors.ProtocolError("Unsupported AMQP version: "+JSON.stringify(header))}return header};frames.write_header=function(buffer,header){var offset=4;buffer.write("AMQP",0,offset,"ascii");buffer.wr
 iteUInt8(header.protocol_id,offset++);buffer.writeUInt8(header.major,offset++);buffer.writeUInt8(header.minor,offset++);buffer.writeUInt8(header.revision,offset++);return 8};frames.TYPE_AMQP=0;frames.TYPE_SASL=1;frames.read_frame=function(buffer){var reader=new types.Reader(buffer);var frame={};frame.size=reader.read_uint(4);if(reader.remaining<frame.size){return null}var doff=reader.read_uint(1);if(doff<2){throw new errors.ProtocolError("Invalid data offset, must be at least 2 was "+doff)}frame.type=reader.read_uint(1);if(frame.type===frames.TYPE_AMQP){frame.channel=reader.read_uint(2)}else if(frame.type===frames.TYPE_SASL){reader.skip(2)}else{throw new errors.ProtocolError("Unknown frame type "+frame.type)}if(doff>1){reader.skip(doff*4-8)}if(reader.remaining()){frame.performative=reader.read();var c=by_descriptor[frame.performative.descriptor.value];if(c){frame.performative=new c(frame.performative.value)}if(reader.remaining()){frame.payload=reader.read_bytes(reader.remaining())}}
 return frame};frames.write_frame=function(frame){var writer=new types.Writer;writer.skip(4);writer.write_uint(2,1);writer.write_uint(frame.type,1);if(frame.type===frames.TYPE_AMQP){writer.write_uint(frame.channel,2)}else if(frame.type===frames.TYPE_SASL){writer.write_uint(0,2)}else{throw new errors.ProtocolError("Unknown frame type "+frame.type)}if(frame.performative){writer.write(frame.performative);if(frame.payload){writer.write_bytes(frame.payload)}}var buffer=writer.toBuffer();buffer.writeUInt32BE(buffer.length,0);return buffer};frames.amqp_frame=function(channel,performative,payload){return{channel:channel||0,type:frames.TYPE_AMQP,performative:performative,payload:payload}};frames.sasl_frame=function(performative){return{channel:0,type:frames.TYPE_SASL,performative:performative}};function define_frame(type,def){var c=types.define_composite(def);frames[def.name]=c.create;by_descriptor[Number(c.descriptor.numeric).toString(10)]=c;by_descriptor[c.descriptor.symbolic]=c}var open={n
 ame:"open",code:16,fields:[{name:"container_id",type:"string",mandatory:true},{name:"hostname",type:"string"},{name:"max_frame_size",type:"uint",default_value:4294967295},{name:"channel_max",type:"ushort",default_value:65535},{name:"idle_time_out",type:"uint"},{name:"outgoing_locales",type:"symbol",multiple:true},{name:"incoming_locales",type:"symbol",multiple:true},{name:"offered_capabilities",type:"symbol",multiple:true},{name:"desired_capabilities",type:"symbol",multiple:true},{name:"properties",type:"symbolic_map"}]};var begin={name:"begin",code:17,fields:[{name:"remote_channel",type:"ushort"},{name:"next_outgoing_id",type:"uint",mandatory:true},{name:"incoming_window",type:"uint",mandatory:true},{name:"outgoing_window",type:"uint",mandatory:true},{name:"handle_max",type:"uint",default_value:"4294967295"},{name:"offered_capabilities",type:"symbol",multiple:true},{name:"desired_capabilities",type:"symbol",multiple:true},{name:"properties",type:"symbolic_map"}]};var attach={name:"
 attach",code:18,fields:[{name:"name",type:"string",mandatory:true},{name:"handle",type:"uint",mandatory:true},{name:"role",type:"boolean",mandatory:true},{name:"snd_settle_mode",type:"ubyte",default_value:2},{name:"rcv_settle_mode",type:"ubyte",default_value:0},{name:"source",type:"*"},{name:"target",type:"*"},{name:"unsettled",type:"map"},{name:"incomplete_unsettled",type:"boolean",default_value:false},{name:"initial_delivery_count",type:"uint"},{name:"max_message_size",type:"ulong"},{name:"offered_capabilities",type:"symbol",multiple:true},{name:"desired_capabilities",type:"symbol",multiple:true},{name:"properties",type:"symbolic_map"}]};var flow={name:"flow",code:19,fields:[{name:"next_incoming_id",type:"uint"},{name:"incoming_window",type:"uint",mandatory:true},{name:"next_outgoing_id",type:"uint",mandatory:true},{name:"outgoing_window",type:"uint",mandatory:true},{name:"handle",type:"uint"},{name:"delivery_count",type:"uint"},{name:"link_credit",type:"uint"},{name:"available",t
 ype:"uint"},{name:"drain",type:"boolean",default_value:false},{name:"echo",type:"boolean",default_value:false},{name:"properties",type:"symbolic_map"}]};var transfer={name:"transfer",code:20,fields:[{name:"handle",type:"uint",mandatory:true},{name:"delivery_id",type:"uint"},{name:"delivery_tag",type:"binary"},{name:"message_format",type:"uint"},{name:"settled",type:"boolean"},{name:"more",type:"boolean",default_value:false},{name:"rcv_settle_mode",type:"ubyte"},{name:"state",type:"delivery_state"},{name:"resume",type:"boolean",default_value:false},{name:"aborted",type:"boolean",default_value:false},{name:"batchable",type:"boolean",default_value:false}]};var disposition={name:"disposition",code:21,fields:[{name:"role",type:"boolean",mandatory:true},{name:"first",type:"uint",mandatory:true},{name:"last",type:"uint"},{name:"settled",type:"boolean",default_value:false},{name:"state",type:"*"},{name:"batchable",type:"boolean",default_value:false}]};var detach={name:"detach",code:22,field
 s:[{name:"handle",type:"uint",mandatory:true},{name:"closed",type:"boolean",default_value:false},{name:"error",type:"error"}]};var end={name:"end",code:23,fields:[{name:"error",type:"error"}]};var close={name:"close",code:24,fields:[{name:"error",type:"error"}]};define_frame(frames.TYPE_AMQP,open);define_frame(frames.TYPE_AMQP,begin);define_frame(frames.TYPE_AMQP,attach);define_frame(frames.TYPE_AMQP,flow);define_frame(frames.TYPE_AMQP,transfer);define_frame(frames.TYPE_AMQP,disposition);define_frame(frames.TYPE_AMQP,detach);define_frame(frames.TYPE_AMQP,end);define_frame(frames.TYPE_AMQP,close);var sasl_mechanisms={name:"sasl_mechanisms",code:64,fields:[{name:"sasl_server_mechanisms",type:"symbol",multiple:true,mandatory:true}]};var sasl_init={name:"sasl_init",code:65,fields:[{name:"mechanism",type:"symbol",mandatory:true},{name:"initial_response",type:"binary"},{name:"hostname",type:"string"}]};var sasl_challenge={name:"sasl_challenge",code:66,fields:[{name:"challenge",type:"binar
 y",mandatory:true}]};var sasl_response={name:"sasl_response",code:67,fields:[{name:"response",type:"binary",mandatory:true}]};var sasl_outcome={name:"sasl_outcome",code:68,fields:[{name:"code",type:"ubyte",mandatory:true},{name:"additional_data",type:"binary"}]};define_frame(frames.TYPE_SASL,sasl_mechanisms);define_frame(frames.TYPE_SASL,sasl_init);define_frame(frames.TYPE_SASL,sasl_challenge);define_frame(frames.TYPE_SASL,sasl_response);define_frame(frames.TYPE_SASL,sasl_outcome);module.exports=frames},{"./errors.js":3,"./types.js":14}],6:[function(require,module,exports){(function(Buffer){"use strict";var frames=require("./frames.js");var log=require("./log.js");var message=require("./message.js");var terminus=require("./terminus.js");var EndpointState=require("./endpoint.js");var FlowController=function(window){this.window=window};FlowController.prototype.update=function(context){var delta=this.window-context.receiver.credit;if(delta>=this.window/4){context.receiver.flow(delta)}}
 ;function auto_settle(context){context.delivery.settled=true}function auto_accept(context){context.delivery.update(undefined,message.accepted().described())}function LinkError(message,condition,link){Error.call(this);Error.captureStackTrace(this,this.constructor);this.message=message;this.condition=condition;this.description=message;this.link=link}require("util").inherits(LinkError,Error);var EventEmitter=require("events").EventEmitter;var link=Object.create(EventEmitter.prototype);link.dispatch=function(name){log.events("Link got event: %s",name);EventEmitter.prototype.emit.apply(this.observers,arguments);if(this.listeners(name).length){EventEmitter.prototype.emit.apply(this,arguments);return true}else{return this.session.dispatch.apply(this.session,arguments)}};link.set_source=function(fields){this.local.attach.source=terminus.source(fields).described()};link.set_target=function(fields){this.local.attach.target=terminus.target(fields).described()};link.attach=function(){if(this.st
 ate.open()){this.connection._register()}};link.open=link.attach;link.detach=function(){this.local.detach.closed=false;if(this.state.close()){this.connection._register()}};link.close=function(error){if(error)this.local.detach.error=error;this.local.detach.closed=true;if(this.state.close()){this.connection._register()}};link.is_open=function(){return this.session.is_open()&&this.state.is_open()};link.is_closed=function(){return this.session.is_closed()||this.state.is_closed()};link._process=function(){do{if(this.state.need_open()){this.session.output(this.local.attach.described())}if(this.issue_flow){this.session._write_flow(this);this.issue_flow=false}if(this.state.need_close()){this.session.output(this.local.detach.described())}}while(!this.state.has_settled())};link.on_attach=function(frame){if(this.state.remote_opened()){if(!this.remote.handle){this.remote.handle=frame.handle}frame.performative.source=terminus.unwrap(frame.performative.source);frame.performative.target=terminus.un
 wrap(frame.performative.target);this.remote.attach=frame.performative;this.open();this.dispatch(this.is_receiver()?"receiver_open":"sender_open",this._context())}else{throw Error("Attach already received")}};link.prefix_event=function(event){return(this.local.attach.role?"receiver_":"sender_")+event};link.on_detach=function(frame){if(this.state.remote_closed()){this.remote.detach=frame.performative;this.close();var error=this.remote.detach.error;if(error){var handled=this.dispatch(this.prefix_event("error"),this._context());handled=this.dispatch(this.prefix_event("close"),this._context())||handled;if(!handled){EventEmitter.prototype.emit.call(this.connection.container,"error",new LinkError(error.description,error.condition,this))}}else{this.dispatch(this.prefix_event("close"),this._context())}}else{throw Error("Detach already received")}};function is_internal(name){switch(name){case"name":case"handle":case"role":case"initial_delivery_count":return true;default:return false}}var alia
 ses=["snd_settle_mode","rcv_settle_mode","source","target","max_message_size","offered_capabilities","desired_capabilities","properties"];function remote_property_shortcut(name){return function(){return this.remote.attach?this.remote.attach[name]:undefined}}link.init=function(session,name,local_handle,opts,is_receiver){this.session=session;this.connection=session.connection;this.name=name;this.options=opts===undefined?{}:opts;this.state=new EndpointState;this.issue_flow=false;this.local={handle:local_handle};this.local.attach=frames.attach({handle:local_handle,name:name,role:is_receiver});for(var field in this.local.attach){if(!is_internal(field)&&this.options[field]!==undefined){this.local.attach[field]=this.options[field]}}this.local.detach=frames.detach({handle:local_handle,closed:true});this.remote={handle:undefined};this.delivery_count=0;this.credit=0;this.observers=new EventEmitter;for(var i in aliases){var alias=aliases[i];Object.defineProperty(this,alias,{get:remote_property
 _shortcut(alias)})}Object.defineProperty(this,"error",{get:function(){
+return this.remote.detach?this.remote.detach.error:undefined}})};link.reset=function(){this.state.disconnected();this.remote={handle:undefined};this.delivery_count=0;this.credit=0};link.has_credit=function(){return this.credit>0};link.is_receiver=function(){return this.local.attach.role};link.is_sender=function(){return!this.is_receiver()};link._context=function(c){var context=c?c:{};if(this.is_receiver()){context.receiver=this}else{context.sender=this}return this.session._context(context)};link.get_option=function(name,default_value){if(this.options[name]!==undefined)return this.options[name];else return this.session.get_option(name,default_value)};var Sender=function(session,name,local_handle,opts){this.init(session,name,local_handle,opts,false);this._draining=false;this._drained=false;this.local.attach.initial_delivery_count=0;this.tag=0;if(this.get_option("autosettle",true)){this.observers.on("settled",auto_settle)}var sender=this;if(this.get_option("treat_modified_as_released",
 true)){this.observers.on("modified",function(context){sender.dispatch("released",context)})}};Sender.prototype=Object.create(link);Sender.prototype.constructor=Sender;Sender.prototype._get_drain=function(){if(this._draining&&this._drained&&this.credit){while(this.credit){++this.delivery_count;--this.credit}return true}else{return false}};Sender.prototype.set_drained=function(drained){this._drained=drained;if(this._draining&&this._drained){this.issue_flow=true}};Sender.prototype.next_tag=function(){return new Buffer(new String(this.tag++))};Sender.prototype.sendable=function(){return this.credit&&this.session.outgoing.available()};Sender.prototype.on_flow=function(frame){var flow=frame.performative;this.credit=flow.delivery_count+flow.link_credit-this.delivery_count;this._draining=flow.drain;this._drained=this.credit>0;if(this.is_open()){this.dispatch("sender_flow",this._context());if(this._draining){this.dispatch("sender_draining",this._context())}if(this.sendable()){this.dispatch("
 sendable",this._context())}}};Sender.prototype.on_transfer=function(){throw Error("got transfer on sending link")};Sender.prototype.send=function(msg,tag){var delivery=this.session.send(this,tag?tag:this.next_tag(),message.encode(msg),0);if(this.local.attach.snd_settle_mode===1){delivery.settled=true}return delivery};var Receiver=function(session,name,local_handle,opts){this.init(session,name,local_handle,opts,true);this.drain=false;this.set_credit_window(this.get_option("credit_window",1e3));if(this.get_option("autoaccept",true)){this.observers.on("message",auto_accept)}};Receiver.prototype=Object.create(link);Receiver.prototype.constructor=Receiver;Receiver.prototype.on_flow=function(frame){this.dispatch("receiver_flow",this._context());if(frame.performative.drain){if(frame.performative.link_credit>0)console.error("ERROR: received flow with drain set, but non zero credit");else this.dispatch("receiver_drained",this._context())}};Receiver.prototype.flow=function(credit){if(credit>0
 ){this.credit+=credit;this.issue_flow=true;this.connection._register()}};Receiver.prototype.add_credit=Receiver.prototype.flow;Receiver.prototype._get_drain=function(){return this.drain};Receiver.prototype.set_credit_window=function(credit_window){if(credit_window>0){var flow_controller=new FlowController(credit_window);var listener=flow_controller.update.bind(flow_controller);this.observers.on("message",listener);this.observers.on("receiver_open",listener)}};module.exports={Sender:Sender,Receiver:Receiver}}).call(this,require("buffer").Buffer)},{"./endpoint.js":2,"./frames.js":5,"./log.js":7,"./message.js":8,"./terminus.js":12,buffer:19,events:22,util:34}],7:[function(require,module,exports){"use strict";var debug=require("debug");module.exports={frames:debug("rhea:frames"),raw:debug("rhea:raw"),reconnect:debug("rhea:reconnect"),events:debug("rhea:events"),message:debug("rhea:message"),flow:debug("rhea:flow"),io:debug("rhea:io")}},{debug:20}],8:[function(require,module,exports){"us
 e strict";var log=require("./log.js");var types=require("./types.js");var by_descriptor={};var unwrappers={};var wrappers=[];var message={};function define_section(descriptor,unwrap,wrap){unwrap.descriptor=descriptor;unwrappers[descriptor.symbolic]=unwrap;unwrappers[Number(descriptor.numeric).toString(10)]=unwrap;if(wrap){wrappers.push(wrap)}}function define_composite_section(def){var c=types.define_composite(def);message[def.name]=c.create;by_descriptor[Number(c.descriptor.numeric).toString(10)]=c;by_descriptor[c.descriptor.symbolic]=c;var unwrap=function(msg,section){var composite=new c(section.value);for(var i=0;i<def.fields.length;i++){var f=def.fields[i];var v=composite[f.name];if(v!==undefined&&v!==null){msg[f.name]=v}}};var wrap=function(sections,msg){sections.push(c.create(msg).described())};define_section(c.descriptor,unwrap,wrap)}function define_map_section(def){var descriptor={numeric:def.code};descriptor.symbolic="amqp:"+def.name.replace(/_/g,"-")+":map";var unwrap=funct
 ion(msg,section){msg[def.name]=types.unwrap_map_simple(section)};var wrap=function(sections,msg){if(msg[def.name]){sections.push(types.described_nc(types.wrap_ulong(descriptor.numeric),types.wrap_map(msg[def.name])))}};define_section(descriptor,unwrap,wrap)}function Section(typecode,content){this.typecode=typecode;this.content=content}Section.prototype.described=function(){return types.described(types.wrap_ulong(this.typecode),types.wrap(this.content))};define_composite_section({name:"header",code:112,fields:[{name:"durable",type:"boolean",default_value:false},{name:"priority",type:"ubyte",default_value:4},{name:"ttl",type:"uint"},{name:"first_acquirer",type:"boolean",default_value:false},{name:"delivery_count",type:"uint",default_value:0}]});define_map_section({name:"delivery_annotations",code:113});define_map_section({name:"message_annotations",code:114});define_composite_section({name:"properties",code:115,fields:[{name:"message_id",type:"message_id"},{name:"user_id",type:"binary
 "},{name:"to",type:"string"},{name:"subject",type:"string"},{name:"reply_to",type:"string"},{name:"correlation_id",type:"message_id"},{name:"content_type",type:"symbol"},{name:"content_encoding",type:"symbol"},{name:"absolute_expiry_time",type:"timestamp"},{name:"creation_time",type:"timestamp"},{name:"group_id",type:"string"},{name:"group_sequence",type:"uint"},{name:"reply_to_group_id",type:"string"}]});define_map_section({name:"application_properties",code:116});define_section({numeric:117,symbolic:"amqp:data:binary"},function(msg,section){msg.body=new Section(117,types.unwrap(section))});define_section({numeric:118,symbolic:"amqp:amqp-sequence:list"},function(msg,section){msg.body=new Section(118,types.unwrap(section))});define_section({numeric:119,symbolic:"amqp:value:*"},function(msg,section){msg.body=types.unwrap(section)});define_map_section({name:"footer",code:120});function wrap_body(sections,msg){if(msg.body&&msg.body.constructor===Section){sections.push(msg.body.describe
 d())}else{sections.push(types.described(types.wrap_ulong(119),types.wrap(msg.body)))}}wrappers.push(wrap_body);message.data_section=function(data){return new Section(117,data)};message.sequence_section=function(list){return new Section(118,list)};function copy(src,tgt){for(var k in src){var v=src[k];if(typeof v==="object"){copy(v,tgt[k])}else{tgt[k]=v}}}function Message(o){if(o){copy(o,this)}}Message.prototype.toJSON=function(){var o={};for(var key in this){if(typeof this[key]==="function")continue;o[key]=this[key]}return o};Message.prototype.inspect=function(){return JSON.stringify(this.toJSON())};Message.prototype.toString=function(){return JSON.stringify(this.toJSON())};message.encode=function(msg){var sections=[];wrappers.forEach(function(wrapper_fn){wrapper_fn(sections,msg)});var writer=new types.Writer;for(var i=0;i<sections.length;i++){log.message("Encoding section %d of %d: %o",i+1,sections.length,sections[i]);writer.write(sections[i])}var data=writer.toBuffer();log.message(
 "encoded %d bytes",data.length);return data};message.decode=function(buffer){var msg=new Message;var reader=new types.Reader(buffer);while(reader.remaining()){var s=reader.read();log.message("decoding section: %o of type: %o",s,s.descriptor);if(s.descriptor){var unwrap=unwrappers[s.descriptor.value];if(unwrap){unwrap(msg,s)}else{console.warn("WARNING: did not recognise message section with descriptor "+s.descriptor)}}else{console.warn("WARNING: expected described message section got "+JSON.stringify(s))}}return msg};var outcomes={};function define_outcome(def){var c=types.define_composite(def);c.composite_type=def.name;message[def.name]=c.create;outcomes[Number(c.descriptor.numeric).toString(10)]=c;outcomes[c.descriptor.symbolic]=c;message["is_"+def.name]=function(o){if(o&&o.descriptor){var c=outcomes[o.descriptor.value];if(c){return c.descriptor.numeric===def.code}}return false}}message.unwrap_outcome=function(outcome){if(outcome&&outcome.descriptor){var c=outcomes[outcome.descript
 or.value];if(c){return new c(outcome.value)}}console.error("unrecognised outcome: "+JSON.stringify(outcome));return outcome};message.are_outcomes_equivalent=function(a,b){if(a===undefined&&b===undefined)return true;else if(a===undefined||b===undefined)return false;else return a.descriptor.value===b.descriptor.value&&a.descriptor.value===36};define_outcome({name:"received",code:35,fields:[{name:"section_number",type:"uint",mandatory:true},{name:"section_offset",type:"ulong",mandatory:true}]});define_outcome({name:"accepted",code:36,fields:[]});define_outcome({name:"rejected",code:37,fields:[{name:"error",type:"error"}]});define_outcome({name:"released",code:38,fields:[]});define_outcome({name:"modified",code:39,fields:[{name:"delivery_failed",type:"boolean"},{name:"undeliverable_here",type:"boolean"},{name:"message_annotations",type:"map"}]});module.exports=message},{"./log.js":7,"./types.js":14}],9:[function(require,module,exports){"use strict";var url=require("url");var simple_id_g
 enerator={counter:1,next:function(){return this.counter++}};var Client=function(container,address){var u=url.parse(address);this.connection=container.connect({host:u.hostname,port:u.port});this.connection.on("message",this._response.bind(this));this.connection.on("receiver_open",this._ready.bind(this));this.sender=this.connection.attach_sender(u.path.substr(1));this.receiver=this.connection.attach_receiver({source:{dynamic:true}});this.id_generator=simple_id_generator;this.pending=[];this.outstanding={}};Client.prototype._request=function(id,name,args,callback){var request={};request.subject=name;request.body=args;request.message_id=id;request.reply_to=this.receiver.remote.attach.source.address;this.outstanding[id]=callback;this.sender.send(request)};Client.prototype._response=function(context){var id=context.message.correlation_id;var callback=this.outstanding[id];if(callback){if(context.message.subject==="ok"){callback(context.message.body)}else{callback(undefined,{name:context.me
 ssage.subject,description:context.message.body})}}else{console.error("no request pending for "+id+", ignoring response")}};Client.prototype._ready=function(){this._process_pending()};Client.prototype._process_pending=function(){for(var i=0;i<this.pending.length;i++){var r=this.pending[i];this._request(r.id,r.name,r.args,r.callback)}this.pending=[]};Client.prototype.call=function(name,args,callback){var id=this.id_generator.next();if(this.receiver.is_open()&&this.pending.length===0){this._request(id,name,args,callback)}else{this.pending.push({name:name,args:args,callback:callback,id:id})}};Client.prototype.close=function(){this.receiver.close();this.sender.close();this.connection.close()};Client.prototype.define=function(name){this[name]=function(args,callback){this.call(name,args,callback)}};var Cache=function(ttl,purged){this.ttl=ttl;this.purged=purged;this.entries={};this.timeout=undefined};Cache.prototype.clear=function(){if(this.timeout)clearTimeout(this.timeout);this.entries={}
 };Cache.prototype.put=function(key,value){this.entries[key]={value:value,last_accessed:Date.now()};if(!this.timeout)this.timeout=setTimeout(this.purge.bind(this),this.ttl)};Cache.prototype.get=function(key){var entry=this.entries[key];if(entry){entry.last_accessed=Date.now();return entry.value}else{return undefined}};Cache.prototype.purge=function(){var now=Date.now();var expired=[];var live=0;for(var k in this.entries){if(now-this.entries[k].last_accessed>=this.ttl){expired.push(k)}else{live++}}for(var i=0;i<expired.length;i++){var entry=this.entries[expired[i]];delete this.entries[expired[i]];this.purged(entry.value)}if(live&&!this.timeout){this.timeout=setTimeout(this.purge.bind(this),this.ttl)}};var LinkCache=function(factory,ttl){this.factory=factory;this.cache=new Cache(ttl,function(link){link.close()})};LinkCache.prototype.clear=function(){this.cache.clear()};LinkCache.prototype.get=function(address){var link=this.cache.get(address);if(link===undefined){link=this.factory(addr
 ess);this.cache.put(address,link)}return link};var Server=function(container,address,options){this.options=options||{};var u=url.parse(address);this.connection=container.connect({host:u.hostname,port:u.port});this.connection.on("connection_open",this._connection_open.bind(this));this.connection.on("message",this._request.bind(this));this.receiver=this.connection.attach_receiver(u.path.substr(1));this.callbacks={};this._send=undefined;this._clear=undefined};function match(desired,offered){if(offered){if(Array.isArray(offered)){return offered.indexOf(desired)>-1}else{return desired===offered}}else{return false}}Server.prototype._connection_open=function(){if(match("ANONYMOUS-RELAY",this.connection.remote.open.offered_capabilities)){var relay=this.connection.attach_sender({target:{}});this._send=function(msg){relay.send(msg)}}else{var cache=new LinkCache(this.connection.attach_sender.bind(this.connection),this.options.cache_ttl||6e4);this._send=function(msg){var s=cache.get(msg.to);if(
 s)s.send(msg)};this._clear=function(){cache.clear()}}};Server.prototype._respond=function(response){var server=this;return function(result,error){if(error){response.subject=error.name||"error";response.body=error.description||error}else{response.subject="ok";response.body=result}server._send(response)}};Server.prototype._request=function(context){var request=context.message;var response={};response.to=request.reply_to;response.correlation_id=request.message_id;var callback=this.callbacks[request.subject];if(callback){callback(request.body,this._respond(response))}else{response.subject="bad-method";response.body="Unrecognised method "+request.subject;this._send(response)}};Server.prototype.bind_sync=function(f,name){this.callbacks[name||f.name]=function(args,callback){var result=f(args);callback(result)}};Server.prototype.bind=function(f,name){this.callbacks[name||f.name]=f};Server.prototype.close=function(){if(this._clear)this._clear();this.receiver.close();this.connection.close()};
 module.exports={server:function(container,address,options){return new Server(container,address,options)},client:function(connection,address){return new Client(connection,address)}}},{url:30}],10:[function(require,module,exports){(function(Buffer){"use strict";var errors=require("./errors.js");var frames=require("./frames.js");var Transport=require("./transport.js");var sasl_codes={OK:0,AUTH:1,SYS:2,SYS_PERM:3,SYS_TEMP:4};var SASL_PROTOCOL_ID=3;function extract(buffer){var results=[];var start=0;var i=0;while(i<buffer.length){if(buffer[i]===0){if(i>start)results.push(buffer.toString("utf8",start,i));else results.push(null);start=++i}else{++i}}if(i>start)results.push(buffer.toString("utf8",start,i));else results.push(null);return results}var PlainServer=function(callback){this.callback=callback;this.outcome=undefined;this.username=undefined};PlainServer.prototype.start=function(response,hostname){var fields=extract(response);if(fields.length!==3){this.connection.sasl_failed("Unexpecte
 d response in PLAIN, got "+fields.length+" fields, expected 3")}if(this.callback(fields[1],fields[2],hostname)){this.outcome=true;this.username=fields[1]}else{this.outcome=false}};var PlainClient=function(username,password){this.username=username;this.password=password};PlainClient.prototype.start=function(){var response=new Buffer(1+this.username.length+1+this.password.length);response.writeUInt8(0,0);response.write(this.username,1);response.writeUInt8(0,1+this.username.length);response.write(this.password,1+this.username.length+1);return response};var AnonymousServer=function(){this.outcome=undefined;this.username=undefined};AnonymousServer.prototype.start=function(response){this.outcome=true;this.username=response?response.toString("utf8"):"anonymous"};var AnonymousClient=function(name){this.username=name?name:"anonymous"};AnonymousClient.prototype.start=function(){var response=new Buffer(1+this.username.length);response.writeUInt8(0,0);response.write(this.username,1);return resp
 onse};var ExternalServer=function(){this.outcome=undefined;this.username=undefined};ExternalServer.prototype.start=function(){this.outcome=true};var ExternalClient=function(){this.username=undefined};ExternalClient.prototype.start=function(){return""};ExternalClient.prototype.step=function(){return""};var SaslServer=function(connection,mechanisms){this.connection=connection;this.transport=new Transport(connection.amqp_transport.identifier,SASL_PROTOCOL_ID,frames.TYPE_SASL,this);this.next=connection.amqp_transport;this.mechanisms=mechanisms;this.mechanism=undefined;this.outcome=undefined;this.username=undefined;var mechlist=Object.getOwnPropertyNames(mechanisms);this.transport.encode(frames.sasl_frame(frames.sasl_mechanisms({sasl_server_mechanisms:mechlist}).described()))};SaslServer.prototype.do_step=function(challenge){if(this.mechanism.outcome===undefined){this.transport.encode(frames.sasl_frame(frames.sasl_challenge({challenge:challenge}).described()))}else{this.outcome=this.mech
 anism.outcome?sasl_codes.OK:sasl_codes.AUTH;this.transport.encode(frames.sasl_frame(frames.sasl_outcome({code:this.outcome}).described()));if(this.outcome===sasl_codes.OK){this.username=this.mechanism.username;this.transport.write_complete=true;this.transport.read_complete=true}}};SaslServer.prototype.on_sasl_init=function(frame){var f=this.mechanisms[frame.performative.mechanism];if(f){this.mechanism=f();var challenge=this.mechanism.start(frame.performative.initial_response,frame.performative.hostname);this.do_step(challenge)}else{this.outcome=sasl_codes.AUTH;this.transport.encode(frames.sasl_frame(frames.sasl_outcome({code:this.outcome}).described()))}};SaslServer.prototype.on_sasl_response=function(frame){this.do_step(this.mechanism.step(frame.performative.response))};SaslServer.prototype.has_writes_pending=function(){return this.transport.has_writes_pending()||this.next.has_writes_pending()};SaslServer.prototype.write=function(socket){if(this.transport.write_complete&&this.trans
 port.pending.length===0){return this.next.write(socket)}else{return this.transport.write(socket)}};SaslServer.prototype.read=function(buffer){if(this.transport.read_complete){return this.next.read(buffer)}else{return this.transport.read(buffer)}};var SaslClient=function(connection,mechanisms,hostname){this.connection=connection;this.transport=new Transport(connection.amqp_transport.identifier,SASL_PROTOCOL_ID,frames.TYPE_SASL,this);this.next=connection.amqp_transport;this.mechanisms=mechanisms;this.mechanism=undefined;this.mechanism_name=undefined;this.hostname=hostname;this.failed=false};SaslClient.prototype.on_sasl_mechanisms=function(frame){for(var i=0;this.mechanism===undefined&&i<frame.performative.sasl_server_mechanisms.length;i++){var mech=frame.performative.sasl_server_mechanisms[i];var f=this.mechanisms[mech];if(f){this.mechanism=f();this.mechanism_name=mech}}if(this.mechanism){var response=this.mechanism.start();var init={mechanism:this.mechanism_name,initial_response:resp
 onse};if(this.hostname){init.hostname=this.hostname}this.transport.encode(frames.sasl_frame(frames.sasl_init(init).described()))}else{this.failed=true;this.connection.sasl_failed("No suitable mechanism; server supports "+frame.performative.sasl_server_mechanisms)}};SaslClient.prototype.on_sasl_challenge=function(frame){var response=this.mechanism.step(frame.performative.challenge);this.transport.encode(frames.sasl_frame(frames.sasl_response({response:response}).described()))};SaslClient.prototype.on_sasl_outcome=function(frame){switch(frame.performative.code){case sasl_codes.OK:this.transport.read_complete=true;this.transport.write_complete=true;break;default:this.transport.write_complete=true;this.connection.sasl_failed("Failed to authenticate: "+frame.performative.code)}};SaslClient.prototype.has_writes_pending=function(){return this.transport.has_writes_pending()||this.next.has_writes_pending()};SaslClient.prototype.write=function(socket){if(this.transport.write_complete){return 
 this.next.write(socket)}else{return this.transport.write(socket)}};SaslClient.prototype.read=function(buffer){if(this.transport.read_complete){return this.next.read(buffer)}else{return this.transport.read(buffer)}};var SelectiveServer=function(connection,mechanisms){this.header_received=false;this.transports={0:connection.amqp_transport,3:new SaslServer(connection,mechanisms)};this.selected=undefined};SelectiveServer.prototype.has_writes_pending=function(){return this.header_received&&this.selected.has_writes_pending()};SelectiveServer.prototype.write=function(socket){if(this.selected){return this.selected.write(socket)}else{return 0}};SelectiveServer.prototype.read=function(buffer){if(!this.header_received){if(buffer.length<8){return 0}else{this.header_received=frames.read_header(buffer);this.selected=this.transports[this.header_received.protocol_id];if(this.selected===undefined){throw new errors.ProtocolError("Invalid AMQP protocol id "+this.header_received.protocol_id)}}}return t
 his.selected.read(buffer)};var default_server_mechanisms={enable_anonymous:function(){this["ANONYMOUS"]=function(){return new AnonymousServer}},enable_plain:function(callback){this["PLAIN"]=function(){return new PlainServer(callback)}}};var default_client_mechanisms={enable_anonymous:function(name){this["ANONYMOUS"]=function(){return new AnonymousClient(name)}},enable_plain:function(username,password){this["PLAIN"]=function(){return new PlainClient(username,password)}},enable_external:function(){this["EXTERNAL"]=function(){return new ExternalClient}}};module.exports={Client:SaslClient,Server:SaslServer,Selective:SelectiveServer,server_mechanisms:function(){return Object.create(default_server_mechanisms)},client_mechanisms:function(){return Object.create(default_client_mechanisms)},server_add_external:function(mechs){mechs["EXTERNAL"]=function(){return new ExternalServer};return mechs}}}).call(this,require("buffer").Buffer)},{"./errors.js":3,"./frames.js":5,"./transport.js":13,buffer
 :19}],11:[function(require,module,exports){(function(Buffer){"use strict";var frames=require("./frames.js");var link=require("./link.js");var log=require("./log.js");var message=require("./message.js");var types=require("./types.js");var util=require("./util.js");var EndpointState=require("./endpoint.js");var EventEmitter=require("events").EventEmitter;var CircularBuffer=function(capacity){this.capacity=capacity;this.size=0;this.head=0;this.tail=0;this.entries=[]};CircularBuffer.prototype.available=function(){return this.capacity-this.size};CircularBuffer.prototype.push=function(o){if(this.size<this.capacity){this.entries[this.tail]=o;this.tail=(this.tail+1)%this.capacity;this.size++}else{throw Error("circular buffer overflow: head="+this.head+" tail="+this.tail+" size="+this.size+" capacity="+this.capacity)}};CircularBuffer.prototype.pop_if=function(f){var count=0;while(this.size&&f(this.entries[this.head])){this.entries[this.head]=undefined;this.head=(this.head+1)%this.capacity;th
 is.size--;count++}return count};CircularBuffer.prototype.by_id=function(id){if(this.size>0){var gap=id-this.entries[this.head].id;if(gap<this.size){return this.entries[(this.head+gap)%this.capacity]}}return undefined};CircularBuffer.prototype.get_head=function(){return this.size>0?this.entries[this.head]:undefined};function write_dispositions(deliveries){var first,last,next_id,i,delivery;for(i=0;i<deliveries.length;i++){delivery=deliveries[i];if(first===undefined){first=delivery;last=delivery;next_id=delivery.id}if(!message.are_outcomes_equivalent(last.state,delivery.state)||last.settled!==delivery.settled||next_id!==delivery.id){first.link.session.output(frames.disposition({role:first.link.is_receiver(),first:first.id,last:last.id,state:first.state,settled:first.settled}).described());first=delivery;last=delivery;next_id=delivery.id}else{if(last.id!==delivery.id){last=delivery}next_id++}}if(first!==undefined&&last!==undefined){first.link.session.output(frames.disposition({role:firs
 t.link.is_receiver(),first:first.id,last:last.id,state:first.state,settled:first.settled}).described())}}var Outgoing=function(){this.deliveries=new CircularBuffer(2048);this.updated=[];this.pending_dispositions=[];this.next_delivery_id=0;this.next_pending_delivery=0;this.next_transfer_id=0;this.window=types.MAX_UINT;this.remote_next_transfer_id=undefined;this.remote_window=undefined};Outgoing.prototype.available=function(){return this.deliveries.available()};Outgoing.prototype.send=function(sender,tag,data,format){var d={id:this.next_delivery_id++,tag:tag,link:sender,data:data,format:format?format:0,sent:false,settled:false,state:undefined,remote_settled:false,remote_state:undefined};var self=this;d.update=function(settled,state){self.update(d,settled,state)};this.deliveries.push(d);return d};Outgoing.prototype.on_begin=function(fields){this.remote_window=fields.incoming_window};Outgoing.prototype.on_flow=function(fields){this.remote_next_transfer_id=fields.next_incoming_id;this.re
 mote_window=fields.incoming_window};Outgoing.prototype.on_disposition=function(fields){var last=fields.last?fields.last:fields.first;for(var i=fields.first;i<=last;i++){var d=this.deliveries.by_id(i);if(d&&!d.remote_settled){var updated=false;if(fields.settled){d.remote_settled=fields.settled;updated=true}if(fields.state&&fields.state!==d.remote_state){d.remote_state=message.unwrap_outcome(fields.state);updated=true}if(updated){this.updated.push(d)}}}};Outgoing.prototype.update=function(delivery,settled,state){if(delivery){delivery.settled=settled;if(state!==undefined)delivery.state=state;if(!delivery.remote_settled){this.pending_dispositions.push(delivery)}delivery.link.connection._register()}};Outgoing.prototype.transfer_window=function(){if(this.remote_window){return this.remote_window-(this.next_transfer_id-this.remote_next_transfer_id)}else{return 0}};Outgoing.prototype.process=function(){var d;while(this.next_pending_delivery<this.next_delivery_id){d=this.deliveries.by_id(this
 .next_pending_delivery);if(d){if(d.link.has_credit()){d.link.delivery_count++;d.transfers_required=1;if(this.transfer_window()>=d.transfers_required){this.next_transfer_id+=d.transfers_required;this.window-=d.transfers_required;d.link.session.output(frames.transfer({handle:d.link.local.handle,message_format:d.format,delivery_id:d.id,delivery_tag:d.tag,settled:d.settled}).described(),d.data);d.link.credit--;this.next_pending_delivery++}else{log.flow("Incoming window of peer preventing sending further transfers: remote_window=%d, remote_next_transfer_id=%d, next_transfer_id=%d",this.remote_window,this.remote_next_transfer_id,this.next_transfer_id);break}}else{log.flow("Link has no credit");break}}else{console.error("ERROR: Next pending delivery not found: "+this.next_pending_delivery);break}}for(var i=0;i<this.updated.length;i++){d=this.updated[i];if(d.remote_state&&d.remote_state.constructor.composite_type){d.link.dispatch(d.remote_state.constructor.composite_type,d.link._context({de
 livery:d}))}if(d.remote_settled)d.link.dispatch("settled",d.link._context({delivery:d}))}this.updated=[];if(this.pending_dispositions.length){write_dispositions(this.pending_dispositions);this.pending_dispositions=[]}this.deliveries.pop_if(function(d){return d.settled&&d.remote_settled})};var Incoming=function(){this.deliveries=new CircularBuffer(2048);this.updated=[];this.next_transfer_id=0;this.next_delivery_id=undefined;this.window=2048;this.remote_next_transfer_id=undefined;this.remote_window=undefined};Incoming.prototype.update=function(delivery,settled,state){if(delivery){delivery.settled=settled;if(state!==undefined)delivery.state=state;if(!delivery.remote_settled){this.updated.push(delivery)}delivery.link.connection._register()}};Incoming.prototype.on_transfer=function(frame,receiver){this.next_transfer_id++;if(receiver.is_open()){if(this.next_delivery_id===undefined){this.next_delivery_id=frame.performative.delivery_id}var current;var data;var last=this.deliveries.get_head(
 );if(last&&last.incomplete){if(frame.performative.delivery_id!==undefined&&this.next_delivery_id!==frame.performative.delivery_id){throw Error("frame sequence error: delivery "+this.next_delivery_id+" not complete, got "+frame.performative.delivery_id)}current=last;data=Buffer.concat([current.data,frame.payload],current.data.length+frame.payload.length)}else if(this.next_delivery_id===frame.performative.delivery_id){current={id:frame.performative.delivery_id,tag:frame.performative.delivery_tag,link:receiver,settled:false,state:undefined,remote_settled:frame.performative.settled===undefined?false:frame.performative.settled,remote_state:frame.performative.state};var self=this;current.update=function(settled,state){var settled_=settled;if(settled_===undefined){settled_=receiver.local.attach.rcv_settle_mode!==1}self.update(current,settled_,state)};current.accept=function(){this.update(undefined,message.accepted().described())};current.release=function(params){if(params){this.update(unde
 fined,message.modified(params).described())}else{this.update(undefined,message.released().described())}};current.reject=function(error){this.update(true,message.rejected({error:error}).described())};current.modified=function(params){this.update(true,message.modified(params).described())};this.deliveries.push(current);data=frame.payload}else{throw Error("frame sequence error: expected "+this.next_delivery_id+", got "+frame.performative.delivery_id)}current.incomplete=frame.performative.more;if(current.incomplete){current.data=data}else{receiver.credit--;receiver.delivery_count++;this.next_delivery_id++;receiver.dispatch("message",receiver._context({message:message.decode(data),delivery:current}))}}};Incoming.prototype.process=function(){if(this.updated.length>0){write_dispositions(this.updated);this.updated=[]}this.deliveries.pop_if(function(d){return d.settled})};Incoming.prototype.on_begin=function(fields){this.remote_window=fields.outgoing_window};Incoming.prototype.on_flow=functi
 on(fields){this.remote_next_transfer_id=fields.next_outgoing_id;this.remote_window=fields.outgoing_window};Incoming.prototype.on_disposition=function(fields){var last=fields.last?fields.last:fields.first;for(var i=fields.first;i<=last;i++){var d=this.deliveries.by_id(i);if(d&&!d.remote_settled){if(fields.settled){d.remote_settled=fields.settled;d.link.dispatch("settled",d.link._context({delivery:d}))}}}};var Session=function(connection,local_channel){this.connection=connection;this.outgoing=new Outgoing;this.incoming=new Incoming;this.state=new EndpointState;this.local={channel:local_channel,handles:{}};this.local.begin=frames.begin({next_outgoing_id:this.outgoing.next_transfer_id,incoming_window:this.incoming.window,outgoing_window:this.outgoing.window});this.local.end=frames.end();this.remote={handles:{}};this.links={};this.options={}};Session.prototype=Object.create(EventEmitter.prototype);Session.prototype.constructor=Session;Session.prototype.reset=function(){this.state.disconn
 ected();this.outgoing=new Outgoing;this.incoming=new Incoming;this.remote={handles:{}}
+;for(var l in this.links){this.links[l].reset()}};Session.prototype.dispatch=function(name){log.events("Session got event: %s",name);if(this.listeners(name).length){EventEmitter.prototype.emit.apply(this,arguments);return true}else{return this.connection.dispatch.apply(this.connection,arguments)}};Session.prototype.output=function(frame,payload){this.connection._write_frame(this.local.channel,frame,payload)};Session.prototype.create_sender=function(name,opts){return this.create_link(name,link.Sender,opts)};Session.prototype.create_receiver=function(name,opts){return this.create_link(name,link.Receiver,opts)};function attach(factory,args,remote_terminus){var opts=args?args:{};if(typeof args==="string"){opts={};opts[remote_terminus]=args}if(!opts.name)opts.name=util.generate_uuid();var l=factory(opts.name,opts);for(var t in{source:0,target:0}){if(opts[t]){if(typeof opts[t]==="string"){opts[t]={address:opts[t]}}l["set_"+t](opts[t])}}if(l.is_sender()&&opts.source===undefined){opts.sourc
 e=l.set_source({})}if(l.is_receiver()&&opts.target===undefined){opts.target=l.set_target({})}l.attach();return l}Session.prototype.get_option=function(name,default_value){if(this.options[name]!==undefined)return this.options[name];else return this.connection.get_option(name,default_value)};Session.prototype.attach_sender=function(args){return attach(this.create_sender.bind(this),args,"target")};Session.prototype.open_sender=Session.prototype.attach_sender;Session.prototype.attach_receiver=function(args){return attach(this.create_receiver.bind(this),args,"source")};Session.prototype.open_receiver=Session.prototype.attach_receiver;Session.prototype.find_sender=function(filter){return this.find_link(util.sender_filter(filter))};Session.prototype.find_receiver=function(filter){return this.find_link(util.receiver_filter(filter))};Session.prototype.find_link=function(filter){for(var name in this.links){var link=this.links[name];if(filter(link))return link}return undefined};Session.prototy
 pe.each_receiver=function(action,filter){this.each_link(util.receiver_filter(filter))};Session.prototype.each_sender=function(action,filter){this.each_link(util.sender_filter(filter))};Session.prototype.each_link=function(action,filter){for(var name in this.links){var link=this.links[name];if(filter===undefined||filter(link))action(link)}};Session.prototype.create_link=function(name,constructor,opts){var i=0;while(this.local.handles[i])i++;var l=new constructor(this,name,i,opts);this.links[name]=l;this.local.handles[i]=l;return l};Session.prototype.begin=function(){if(this.state.open()){this.connection._register()}};Session.prototype.open=Session.prototype.begin;Session.prototype.end=function(error){if(error)this.local.end.error=error;if(this.state.close()){this.connection._register()}};Session.prototype.close=Session.prototype.end;Session.prototype.is_open=function(){return this.connection.is_open()&&this.state.is_open()};Session.prototype.is_closed=function(){return this.connectio
 n.is_closed()||this.state.is_closed()};Session.prototype._process=function(){do{if(this.state.need_open()){this.output(this.local.begin.described())}this.outgoing.process();this.incoming.process();for(var k in this.links){this.links[k]._process()}if(this.state.need_close()){this.output(this.local.end.described())}}while(!this.state.has_settled())};Session.prototype.send=function(sender,tag,data,format){var d=this.outgoing.send(sender,tag,data,format);this.connection._register();return d};Session.prototype._write_flow=function(link){var fields={next_incoming_id:this.incoming.next_transfer_id,incoming_window:this.incoming.window,next_outgoing_id:this.outgoing.next_transfer_id,outgoing_window:this.outgoing.window};if(link){if(link._get_drain())fields.drain=true;fields.delivery_count=link.delivery_count;fields.handle=link.local.handle;fields.link_credit=link.credit}this.output(frames.flow(fields).described())};Session.prototype.on_begin=function(frame){if(this.state.remote_opened()){if(
 !this.remote.channel){this.remote.channel=frame.channel}this.remote.begin=frame.performative;this.outgoing.on_begin(frame.performative);this.incoming.on_begin(frame.performative);this.open();this.dispatch("session_open",this._context())}else{throw Error("Begin already received")}};Session.prototype.on_end=function(frame){if(this.state.remote_closed()){this.remote.end=frame.performative;this.close();this.dispatch("session_close",this._context())}else{throw Error("End already received")}};Session.prototype.on_attach=function(frame){var name=frame.performative.name;var link=this.links[name];if(!link){link=frame.performative.role?this.create_sender(name):this.create_receiver(name)}this.remote.handles[frame.performative.handle]=link;link.on_attach(frame);link.remote.attach=frame.performative};Session.prototype.on_disposition=function(frame){if(frame.performative.role){log.events("Received disposition for outgoing transfers");this.outgoing.on_disposition(frame.performative)}else{log.event
 s("Received disposition for incoming transfers");this.incoming.on_disposition(frame.performative)}this.connection._register()};Session.prototype.on_flow=function(frame){this.outgoing.on_flow(frame.performative);this.incoming.on_flow(frame.performative);if(frame.performative.handle!==undefined){this._get_link(frame).on_flow(frame)}this.connection._register()};Session.prototype._context=function(c){var context=c?c:{};context.session=this;return this.connection._context(context)};Session.prototype._get_link=function(frame){var handle=frame.performative.handle;var link=this.remote.handles[handle];if(!link){throw Error("Invalid handle "+handle)}return link};Session.prototype.on_detach=function(frame){this._get_link(frame).on_detach(frame);var handle=frame.performative.handle;var link=this.remote.handles[handle];delete this.remote.handles[handle];delete this.local.handles[link.local.handle];delete this.links[link.name]};Session.prototype.on_transfer=function(frame){this.incoming.on_transf
 er(frame,this._get_link(frame))};module.exports=Session}).call(this,require("buffer").Buffer)},{"./endpoint.js":2,"./frames.js":5,"./link.js":6,"./log.js":7,"./message.js":8,"./types.js":14,"./util.js":15,buffer:19,events:22}],12:[function(require,module,exports){"use strict";var types=require("./types.js");var terminus={};var by_descriptor={};function define_terminus(def){var c=types.define_composite(def);terminus[def.name]=c.create;by_descriptor[Number(c.descriptor.numeric).toString(10)]=c;by_descriptor[c.descriptor.symbolic]=c}terminus.unwrap=function(field){if(field&&field.descriptor){var c=by_descriptor[field.descriptor.value];if(c){return new c(field.value)}else{console.warn("Unknown terminus: "+field.descriptor)}}return null};define_terminus({name:"source",code:40,fields:[{name:"address",type:"string"},{name:"durable",type:"uint",default_value:0},{name:"expiry_policy",type:"symbol",default_value:"session-end"},{name:"timeout",type:"uint",default_value:0},{name:"dynamic",type:
 "boolean",default_value:false},{name:"dynamic_node_properties",type:"symbolic_map"},{name:"distribution_mode",type:"symbol"},{name:"filter",type:"symbolic_map"},{name:"default_outcome",type:"*"},{name:"outcomes",type:"symbol",multiple:true},{name:"capabilities",type:"symbol",multiple:true}]});define_terminus({name:"target",code:41,fields:[{name:"address",type:"string"},{name:"durable",type:"uint",default_value:0},{name:"expiry_policy",type:"symbol",default_value:"session-end"},{name:"timeout",type:"uint",default_value:0},{name:"dynamic",type:"boolean",default_value:false},{name:"dynamic_node_properties",type:"symbolic_map"},{name:"capabilities",type:"symbol",multiple:true}]});module.exports=terminus},{"./types.js":14}],13:[function(require,module,exports){(function(Buffer){"use strict";var errors=require("./errors.js");var frames=require("./frames.js");var log=require("./log.js");var Transport=function(identifier,protocol_id,frame_type,handler){this.identifier=identifier;this.protoc
 ol_id=protocol_id;this.frame_type=frame_type;this.handler=handler;this.pending=[];this.header_sent=undefined;this.header_received=undefined;this.write_complete=false;this.read_complete=false};Transport.prototype.has_writes_pending=function(){return this.pending.length>0};Transport.prototype.encode=function(frame){var buffer=frames.write_frame(frame);log.frames("[%s] PENDING: %o",this.identifier,JSON.stringify(frame));this.pending.push(buffer)};Transport.prototype.write=function(socket){if(!this.header_sent){var buffer=new Buffer(8);var header={protocol_id:this.protocol_id,major:1,minor:0,revision:0};frames.write_header(buffer,header);socket.write(buffer);this.header_sent=header}for(var i=0;i<this.pending.length;i++){socket.write(this.pending[i]);log.raw("[%s] SENT: %o",this.identifier,this.pending[i])}this.pending=[]};Transport.prototype.read=function(buffer){var offset=0;if(!this.header_received){if(buffer.length<8){return offset}else{this.header_received=frames.read_header(buffer)
 ;log.frames("[%s] RECV: %o",this.identifier,this.header_received);if(this.header_received.protocol_id!==this.protocol_id){if(this.protocol_id===3&&this.header_received.protocol_id===0){throw new errors.ProtocolError("Expecting SASL layer")}else if(this.protocol_id===0&&this.header_received.protocol_id===3){throw new errors.ProtocolError("SASL layer not enabled")}else{throw new errors.ProtocolError("Invalid AMQP protocol id "+this.header_received.protocol_id+" expecting: "+this.protocol_id)}}offset=8}}while(offset<buffer.length-4&&!this.read_complete){var frame_size=buffer.readUInt32BE(offset);log.io("[%s] got frame of size %d",this.identifier,frame_size);if(buffer.length<offset+frame_size){log.io("[%s] incomplete frame; have only %d of %d",this.identifier,buffer.length-offset,frame_size);break}else{var frame=frames.read_frame(buffer.slice(offset,offset+frame_size));log.frames("[%s] RECV: %o",this.identifier,JSON.stringify(frame));if(frame.type!==this.frame_type){throw new errors.Pro
 tocolError("Invalid frame type: "+frame.type)}offset+=frame_size;if(frame.performative){frame.performative.dispatch(this.handler,frame)}}}return offset};module.exports=Transport}).call(this,require("buffer").Buffer)},{"./errors.js":3,"./frames.js":5,"./log.js":7,buffer:19}],14:[function(require,module,exports){(function(Buffer){"use strict";var errors=require("./errors.js");var CAT_FIXED=1;var CAT_VARIABLE=2;var CAT_COMPOUND=3;var CAT_ARRAY=4;function Typed(type,value,code,descriptor){this.type=type;this.value=value;if(code){this.array_constructor={typecode:code};if(descriptor){this.array_constructor.descriptor=descriptor}}}Typed.prototype.toString=function(){return this.value?this.value.toString():null};Typed.prototype.toLocaleString=function(){return this.value?this.value.toLocaleString():null};Typed.prototype.valueOf=function(){return this.value};Typed.prototype.toJSON=function(){return this.value&&this.value.toJSON?this.value.toJSON():this.value};function TypeDesc(name,typecode,
 props,empty_value){this.name=name;this.typecode=typecode;var subcategory=typecode>>>4;switch(subcategory){case 4:this.width=0;this.category=CAT_FIXED;break;case 5:this.width=1;this.category=CAT_FIXED;break;case 6:this.width=2;this.category=CAT_FIXED;break;case 7:this.width=4;this.category=CAT_FIXED;break;case 8:this.width=8;this.category=CAT_FIXED;break;case 9:this.width=16;this.category=CAT_FIXED;break;case 10:this.width=1;this.category=CAT_VARIABLE;break;case 11:this.width=4;this.category=CAT_VARIABLE;break;case 12:this.width=1;this.category=CAT_COMPOUND;break;case 13:this.width=4;this.category=CAT_COMPOUND;break;case 14:this.width=1;this.category=CAT_ARRAY;break;case 15:this.width=4;this.category=CAT_ARRAY;break;default:break}if(props){if(props.read){this.read=props.read}if(props.write){this.write=props.write}if(props.encoding){this.encoding=props.encoding}}var t=this;if(subcategory===4){this.create=function(){return new Typed(t,empty_value)}}else if(subcategory===14||subcategory
 ===15){this.create=function(v,code,descriptor){return new Typed(t,v,code,descriptor)}}else{this.create=function(v){return new Typed(t,v)}}}TypeDesc.prototype.toString=function(){return this.name+"#"+hex(this.typecode)};function hex(i){return Number(i).toString(16)}var types={by_code:{}};Object.defineProperty(types,"MAX_UINT",{value:4294967295,writable:false,configurable:false});Object.defineProperty(types,"MAX_USHORT",{value:65535,writable:false,configurable:false});function define_type(name,typecode,annotations,empty_value){var t=new TypeDesc(name,typecode,annotations,empty_value);t.create.typecode=t.typecode;types.by_code[t.typecode]=t;types[name]=t.create}function buffer_uint8_ops(){return{read:function(buffer,offset){return buffer.readUInt8(offset)},write:function(buffer,value,offset){buffer.writeUInt8(value,offset)}}}function buffer_uint16be_ops(){return{read:function(buffer,offset){return buffer.readUInt16BE(offset)},write:function(buffer,value,offset){buffer.writeUInt16BE(val
 ue,offset)}}}function buffer_uint32be_ops(){return{read:function(buffer,offset){return buffer.readUInt32BE(offset)},write:function(buffer,value,offset){buffer.writeUInt32BE(value,offset)}}}function buffer_int8_ops(){return{read:function(buffer,offset){return buffer.readInt8(offset)},write:function(buffer,value,offset){buffer.writeInt8(value,offset)}}}function buffer_int16be_ops(){return{read:function(buffer,offset){return buffer.readInt16BE(offset)},write:function(buffer,value,offset){buffer.writeInt16BE(value,offset)}}}function buffer_int32be_ops(){return{read:function(buffer,offset){return buffer.readInt32BE(offset)},write:function(buffer,value,offset){buffer.writeInt32BE(value,offset)}}}function buffer_floatbe_ops(){return{read:function(buffer,offset){return buffer.readFloatBE(offset)},write:function(buffer,value,offset){buffer.writeFloatBE(value,offset)}}}function buffer_doublebe_ops(){return{read:function(buffer,offset){return buffer.readDoubleBE(offset)},write:function(buffer,
 value,offset){buffer.writeDoubleBE(value,offset)}}}var MAX_UINT=4294967296;var MIN_INT=-2147483647;function write_ulong(buffer,value,offset){if(typeof value==="number"||value instanceof Number){var hi=Math.floor(value/MAX_UINT);var lo=value%MAX_UINT;buffer.writeUInt32BE(hi,offset);buffer.writeUInt32BE(lo,offset+4)}else{value.copy(buffer,offset)}}function read_ulong(buffer,offset){var hi=buffer.readUInt32BE(offset);var lo=buffer.readUInt32BE(offset+4);if(hi<2097153){return hi*MAX_UINT+lo}else{return buffer.slice(offset,offset+8)}}function write_long(buffer,value,offset){if(typeof value==="number"||value instanceof Number){var abs=Math.abs(value);var hi=Math.floor(abs/MAX_UINT);var lo=abs%MAX_UINT;buffer.writeInt32BE(hi,offset);buffer.writeUInt32BE(lo,offset+4);if(value<0){var carry=1;for(var i=0;i<8;i++){var index=offset+(7-i);var v=(buffer[index]^255)+carry;buffer[index]=v&255;carry=v>>8}}}else{value.copy(buffer,offset)}}function read_long(buffer,offset){var hi=buffer.readInt32BE(of
 fset);var lo=buffer.readUInt32BE(offset+4);if(hi<2097153&&hi>-2097153){return hi*MAX_UINT+lo}else{return buffer.slice(offset,offset+8)}}define_type("Null",64,undefined,null);define_type("Boolean",86,buffer_uint8_ops());define_type("True",65,undefined,true);define_type("False",66,undefined,false);define_type("Ubyte",80,buffer_uint8_ops());define_type("Ushort",96,buffer_uint16be_ops());define_type("Uint",112,buffer_uint32be_ops());define_type("SmallUint",82,buffer_uint8_ops());define_type("Uint0",67,undefined,0);define_type("Ulong",128,{write:write_ulong,read:read_ulong});define_type("SmallUlong",83,buffer_uint8_ops());define_type("Ulong0",68,undefined,0);define_type("Byte",81,buffer_int8_ops());define_type("Short",97,buffer_int16be_ops());define_type("Int",113,buffer_int32be_ops());define_type("SmallInt",84,buffer_int8_ops());define_type("Long",129,{write:write_long,read:read_long});define_type("SmallLong",85,buffer_int8_ops());define_type("Float",114,buffer_floatbe_ops());define_typ
 e("Double",130,buffer_doublebe_ops());define_type("Decimal32",116);define_type("Decimal64",132);define_type("Decimal128",148);define_type("CharUTF32",115,buffer_uint32be_ops());define_type("Timestamp",131,{write:write_long,read:read_long});define_type("Uuid",152);define_type("Vbin8",160);define_type("Vbin32",176);define_type("Str8",161,{encoding:"utf8"});define_type("Str32",177,{encoding:"utf8"});define_type("Sym8",163,{encoding:"ascii"});define_type("Sym32",179,{encoding:"ascii"});define_type("List0",69,undefined,[]);define_type("List8",192);define_type("List32",208);define_type("Map8",193);define_type("Map32",209);define_type("Array8",224);define_type("Array32",240);function is_one_of(o,typelist){for(var i=0;i<typelist.length;i++){if(o.type.typecode===typelist[i].typecode)return true}return false}function buffer_zero(b,len,neg){for(var i=0;i<len&&i<b.length;i++){if(b[i]!==(neg?255:0))return false}return true}types.is_ulong=function(o){return is_one_of(o,[types.Ulong,types.Ulong0,t
 ypes.SmallUlong])};types.is_string=function(o){return is_one_of(o,[types.Str8,types.Str32])};types.is_symbol=function(o){return is_one_of(o,[types.Sym8,types.Sym32])};types.is_list=function(o){return is_one_of(o,[types.List0,types.List8,types.List32])};types.is_map=function(o){return is_one_of(o,[types.Map8,types.Map32])};types.wrap_boolean=function(v){return v?types.True():types.False()};types.wrap_ulong=function(l){if(Buffer.isBuffer(l)){if(buffer_zero(l,8,false))return types.Ulong0();return buffer_zero(l,7,false)?types.SmallUlong(l[7]):types.Ulong(l)}else{if(l===0)return types.Ulong0();else return l>255?types.Ulong(l):types.SmallUlong(l)}};types.wrap_uint=function(l){if(l===0)return types.Uint0();else return l>255?types.Uint(l):types.SmallUint(l)};types.wrap_ushort=function(l){return types.Ushort(l)};types.wrap_ubyte=function(l){return types.Ubyte(l)};types.wrap_long=function(l){if(Buffer.isBuffer(l)){var negFlag=(l[0]&128)!==0;if(buffer_zero(l,7,negFlag)&&(l[7]&128)===(negFlag?1
 28:0)){return types.SmallLong(negFlag?-((l[7]^255)+1):l[7])}return types.Long(l)}else{return l>127||l<-128?types.Long(l):types.SmallLong(l)}};types.wrap_int=function(l){return l>127||l<-128?types.Int(l):types.SmallInt(l)};types.wrap_short=function(l){return types.Short(l)};types.wrap_byte=function(l){return types.Byte(l)};types.wrap_float=function(l){return types.Float(l)};types.wrap_double=function(l){return types.Double(l)};types.wrap_timestamp=function(l){return types.Timestamp(l)};types.wrap_char=function(v){return types.CharUTF32(v)};types.wrap_uuid=function(v){return types.Uuid(v)};types.wrap_binary=function(s){return s.length>255?types.Vbin32(s):types.Vbin8(s)};types.wrap_string=function(s){return s.length>255?types.Str32(s):types.Str8(s)};types.wrap_symbol=function(s){return s.length>255?types.Sym32(s):types.Sym8(s)};types.wrap_list=function(l){if(l.length===0)return types.List0();var items=l.map(types.wrap);return types.List32(items)};types.wrap_map=function(m,key_wrapper){
 var items=[];for(var k in m){items.push(key_wrapper?key_wrapper(k):types.wrap(k));items.push(types.wrap(m[k]))}return types.Map32(items)};types.wrap_symbolic_map=function(m){return types.wrap_map(m,types.wrap_symbol)};types.wrap_array=function(l,code,descriptors){if(code){return types.Array32(l,code,descriptors)}else{console.trace("An array must specify a type for its elements");throw new errors.TypeError("An array must specify a type for its elements")}};types.wrap=function(o){var t=typeof o;if(t==="string"){return types.wrap_string(o)}else if(t==="boolean"){return o?types.True():types.False()}else if(t==="number"||o instanceof Number){if(isNaN(o)){throw new errors.TypeError("Cannot wrap NaN! "+o)}else if(Math.floor(o)-o!==0){return types.Double(o)}else if(o>0){if(o<MAX_UINT){return types.wrap_uint(o)}else{return types.wrap_ulong(o)}}else{if(o>MIN_INT){return types.wrap_int(o)}else{return types.wrap_long(o)}}}else if(o instanceof Date){return types.wrap_timestamp(o.getTime())}else 
 if(o instanceof Typed){return o}else if(o instanceof Buffer){return types.wrap_binary(o)}else if(t==="undefined"||o===null){return types.Null()}else if(Array.isArray(o)){return types.wrap_list(o)}else{return types.wrap_map(o)}};types.wrap_described=function(value,descriptor){var result=types.wrap(value);if(descriptor){if(typeof descriptor==="string"){result=types.described(types.wrap_string(descriptor),result)}else if(typeof descriptor==="number"||descriptor instanceof Number){result=types.described(types.wrap_ulong(descriptor),result)}}return result};types.wrap_message_id=function(o){var t=typeof o;if(t==="string"){return types.wrap_string(o)}else if(t==="number"||o instanceof Number){return types.wrap_ulong(o)}else{throw new errors.TypeError("invalid message id:"+o)}};function mapify(elements){var result={};for(var i=0;i+1<elements.length;){result[elements[i++]]=elements[i++]}return result}var by_descriptor={};types.unwrap_map_simple=function(o){return mapify(o.value.map(function(
 i){return types.unwrap(i,true)}))};types.unwrap=function(o,leave_described){if(o instanceof Typed){if(o.descriptor){var c=by_descriptor[o.descriptor.value];if(c){return new c(o.value)}else if(leave_described){return o}}var u=types.unwrap(o.value,true);return types.is_map(o)?mapify(u):u}else if(Array.isArray(o)){return o.map(function(i){return types.unwrap(i,true)})}else{return o}};types.described_nc=function(descriptor,o){if(descriptor.length){o.descriptor=descriptor.shift();return types.described(descriptor,o)}else{o.descriptor=descriptor;return o}};types.described=types.described_nc;function get_type(code){var type=types.by_code[code];if(!type){throw new errors.TypeError("Unrecognised typecode: "+hex(code))}return type}types.Reader=function(buffer){this.buffer=buffer;this.position=0};types.Reader.prototype.read_typecode=function(){return this.read_uint(1)};types.Reader.prototype.read_uint=function(width){var current=this.position;this.position+=width;if(width===1){return this.buff
 er.readUInt8(current)}else if(width===2){return this.buffer.readUInt16BE(current)}else if(width===4){return this.buffer.readUInt32BE(current)}else{throw new errors.TypeError("Unexpected width for uint "+width)}};types.Reader.prototype.read_fixed_width=function(type){var current=this.position;this.position+=type.width;if(type.read){return type.read(this.buffer,current)}else{return this.buffer.slice(current,this.position)}};types.Reader.prototype.read_variable_width=function(type){var size=this.read_uint(type.width);var slice=this.read_bytes(size);return type.encoding?slice.toString(type.encoding):slice};types.Reader.prototype.read=function(){var constructor=this.read_constructor();var value=this.read_value(get_type(constructor.typecode));return constructor.descriptor?types.described_nc(constructor.descriptor,value):value};types.Reader.prototype.read_constructor=function(){var code=this.read_typecode();if(code===0){var d=[];d.push(this.read());var c=this.read_constructor();while(c.des
 criptor){d.push(c.descriptor);c=this.read_constructor()}return{typecode:c.typecode,descriptor:d.length===1?d[0]:d}}else{return{typecode:code}}};types.Reader.prototype.read_value=function(type){if(type.width===0){return type.create()}else if(type.category===CAT_FIXED){return type.create(this.read_fixed_width(type))}else if(type.category===CAT_VARIABLE){return type.create(this.read_variable_width(type))}else if(type.category===CAT_COMPOUND){return this.read_compound(type)}else if(type.category===CAT_ARRAY){return this.read_array(type)}else{throw new errors.TypeError("Invalid category for type: "+type)}};types.Reader.prototype.read_array_items=function(n,type){var items=[];while(items.length<n){items.push(this.read_value(type))}return items};types.Reader.prototype.read_n=function(n){var items=new Array(n);for(var i=0;i<n;i++){items[i]=this.read()}return items};types.Reader.prototype.read_size_count=function(width){return{size:this.read_uint(width),count:this.read_uint(width)}};types.Re
 ader.prototype.read_compound=function(type){var limits=this.read_size_count(type.width);return type.create(this.read_n(limits.count))};types.Reader.prototype.read_array=function(type){var limits=this.read_size_count(type.width);var constructor=this.read_constructor();return type.create(this.read_array_items(limits.count,get_type(constructor.typecode)),constructor.typecode,constructor.descriptor)};types.Reader.prototype.toString=function(){var s="buffer@"+this.position;if(this.position)s+=": ";for(var i=this.position;i<this.buffer.length;i++){if(i>0)s+=",";s+="0x"+Number(this.buffer[i]).toString(16)}return s};types.Reader.prototype.reset=function(){this.position=0};types.Reader.prototype.skip=function(bytes){this.position+=bytes};types.Reader.prototype.read_bytes=function(bytes){var current=

<TRUNCATED>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org