summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Rudyy <orudyy@apache.org>2013-03-18 18:12:57 +0000
committerAlex Rudyy <orudyy@apache.org>2013-03-18 18:12:57 +0000
commit592669bad63f5579d3516f41ea143c9a549a261a (patch)
tree616e60ac1fceeb5bbe44e4103dde0d9f166cca2b
parent248116abe95421844fed3dc086895230e3f3fb74 (diff)
downloadqpid-python-592669bad63f5579d3516f41ea143c9a549a261a.tar.gz
QPID-4657: Add UI into java broker web management console to add/edit/delete ports
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1457903 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html81
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css4
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js30
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js304
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java1
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java47
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java9
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java24
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java21
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java2
13 files changed, 507 insertions, 22 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html
new file mode 100644
index 0000000000..fddd52138b
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html
@@ -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.
+ -
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Port'" id="addPort">
+ <form id="formAddPort" method="post" dojoType="dijit.form.Form">
+ <div id="formAddPort:fields">
+ <input type="text" required="true" name="name" id="formAddPort.name" placeholder="Port Name"
+ data-dojo-props="label: 'Port Name*:'" dojoType="dijit.form.ValidationTextBox"
+ missingMessage="A name must be supplied" />
+ <input data-dojo-type="dijit.form.NumberSpinner" id="formAddPort.port" data-dojo-props="label: 'Port*:'"
+ name="port" value="5672" smallDelta="1" constraints="{min:1,max:65535,places:0, pattern: '#####'}" />
+ <select id="formAddPort.transport" data-dojo-type="dijit.form.FilteringSelect"
+ data-dojo-props="name: 'transport',label: 'Transport:',searchAttr: 'name',required:false,placeHolder: 'Select Transports', value: '' "
+ style="margin: 0;">
+ <option value="TCP">TCP</option>
+ <option value="SSL">SSL</option>
+ </select>
+ <select id="formAddPort.authenticationProvider" data-dojo-type="dijit.form.FilteringSelect" style="margin: 0;"
+ data-dojo-props="name:'authenticationProvider',label:'Authentication Provider:', searchAttr: 'name', required: false, placeHolder: 'Select Authentication', value: '' "
+ missingMessage="Transport must be supplied">
+ </select>
+ <select id="formAddPort.type" data-dojo-type="dijit.form.FilteringSelect"
+ data-dojo-props="name: 'type', value: '',placeHolder: 'Select Port Type', label: 'Port Type:'">
+ <option value="AMQP" selected="selected">AMQP</option>
+ <option value="JMX">JMX</option>
+ <option value="HTTP">HTTP</option>
+ </select>
+ </div>
+ <div id="formAddPort:fieldsAMQP">
+ <input id="formAddPort.bindingAddress" type="text" name="bindingAddress"
+ dojoType="dijit.form.TextBox" data-dojo-props="label: 'Binding address:'"/>
+ <input id="formAddPort.protocolsDefault" type="checkbox" name="protocolsDefault" checked="checked"
+ dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Use broker default AMQP protocols:'"/>
+ <select id="formAddPort.protocolsAMQP" name="protocols" data-dojo-type="dijit.form.MultiSelect" multiple="true"
+ data-dojo-props="name: 'protocols', value: '', placeHolder: 'Select Protocols', label: 'AMQP protocols:'"
+ missingMessage="AMQP protocol(s) must be supplied">
+ <option value="AMQP_0_8">AMQP 0.8</option>
+ <option value="AMQP_0_9">AMQP 0.9</option>
+ <option value="AMQP_0_9_1">AMQP 0.9.1</option>
+ <option value="AMQP_0_10">AMQP 0.10</option>
+ <option value="AMQP_1_0">AMQP 1.0</option>
+ </select>
+ </div>
+ <div id="formAddPort:fieldsJMX">
+ <select id="formAddPort.protocolsJMX" name="protocols" data-dojo-type="dijit.form.FilteringSelect"
+ data-dojo-props="name: 'protocols', value: '', label: 'JMX protocols*:'" missingMessage="JMX protocol must be supplied">
+ <option value="RMI">RMI</option>
+ <option value="JMX_RMI">JMX RMI</option>
+ </select>
+ </div>
+ <div id="formAddPort:fieldsHTTP">
+ <select id="formAddPort.protocolsHTTP" name="protocols" data-dojo-type="dijit.form.FilteringSelect"
+ data-dojo-props="name: 'protocols', value: '', label: 'HTTP protocols*:'" missingMessage="HTTP protocol must be supplied">
+ <option value="HTTP">HTTP</option>
+ <option value="HTTPS">HTTPS</option>
+ </select>
+ </div>
+ <input type="hidden" id="formAddPort.id" name="id"/>
+ <!-- submit buttons -->
+ <input type="submit" value="Save Port" label="Save Port" dojoType="dijit.form.Button" />
+ </form>
+ </div>
+</div>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
index 78780edcd9..f5ca3e68dd 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -89,4 +89,8 @@ h1 {
div .messages {
width: 100%;
height: 350px;
+}
+
+.formLabel-labelCell {
+ font-weight: bold;
} \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
index 84a0d8ca68..98d442bf14 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js
@@ -30,12 +30,13 @@ define(["dojo/_base/xhr",
"dijit/registry",
"qpid/management/addAuthenticationProvider",
"qpid/management/addVirtualHost",
+ "qpid/management/addPort",
"dojox/grid/enhanced/plugins/Pagination",
"dojox/grid/enhanced/plugins/IndirectSelection",
"dijit/layout/AccordionContainer",
"dijit/layout/AccordionPane",
"dojo/domReady!"],
- function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, addAuthenticationProvider, addVirtualHost) {
+ function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, addAuthenticationProvider, addVirtualHost, addPort) {
function Broker(name, parent, controller) {
this.name = name;
@@ -94,6 +95,20 @@ define(["dojo/_base/xhr",
"Deletion of virtual will delete the message store data.\n\n Are you sure you want to delete virtual host");
}
);
+
+ var addPortButton = query(".addPort", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(addPortButton), "onClick", function(evt){ addPort.show(null, that.brokerUpdater.brokerData.authenticationproviders); });
+
+ var deletePort = query(".deletePort", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(deletePort), "onClick",
+ function(evt){
+ util.deleteGridSelections(
+ that.brokerUpdater,
+ that.brokerUpdater.portsGrid.grid,
+ "rest/port",
+ "Are you sure you want to delete port");
+ }
+ );
}});
};
@@ -155,9 +170,12 @@ define(["dojo/_base/xhr",
that.portsGrid =
new UpdatableStore(that.brokerData.ports, query(".broker-ports")[0],
- [ { name: "Address", field: "bindingAddress", width: "70px"},
- { name: "Port", field: "port", width: "70px"},
- { name: "Transports", field: "transports", width: "150px"},
+ [ { name: "Name", field: "name", width: "150px"},
+ { name: "State", field: "state", width: "60px"},
+ { name: "Authentication", field: "authenticationProvider", width: "100px"},
+ { name: "Address", field: "bindingAddress", width: "70px"},
+ { name: "Port", field: "port", width: "50px"},
+ { name: "Transports", field: "transports", width: "100px"},
{ name: "Protocols", field: "protocols", width: "100%"}
], function(obj) {
connect.connect(obj.grid, "onRowDblClick", obj.grid,
@@ -165,9 +183,9 @@ define(["dojo/_base/xhr",
var idx = evt.rowIndex,
theItem = this.getItem(idx);
var name = obj.dataStore.getValue(theItem,"name");
- that.controller.show("port", name, brokerObj);
+ addPort.show(name, that.brokerData.authenticationproviders);
});
- });
+ }, gridProperties, EnhancedGrid);
gridProperties = {
keepSelection: true,
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js
new file mode 100644
index 0000000000..dec04e604e
--- /dev/null
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js
@@ -0,0 +1,304 @@
+/*
+ *
+ * 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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/_base/window",
+ "dijit/registry",
+ "dojo/parser",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ 'dojo/_base/json',
+ "dojo/store/Memory",
+ "dijit/form/FilteringSelect",
+ "dojo/dom-style",
+ "dojo/_base/lang",
+ /* dojox/ validate resources */
+ "dojox/validate/us",
+ "dojox/validate/web",
+ /* basic dijit classes */
+ "dijit/Dialog",
+ "dijit/form/CheckBox",
+ "dijit/form/Textarea",
+ "dijit/form/TextBox",
+ "dijit/form/ValidationTextBox",
+ "dijit/form/DateTextBox",
+ "dijit/form/TimeTextBox",
+ "dijit/form/Button",
+ "dijit/form/RadioButton",
+ "dijit/form/Form",
+ "dijit/form/DateTextBox",
+ "dijit/form/MultiSelect",
+ "dijit/form/Select",
+ "dijit/form/NumberSpinner",
+ /* basic dojox classes */
+ "dojox/form/BusyButton",
+ "dojo/domReady!"],
+ function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, FilteringSelect, domStyle, lang) {
+
+ var addPort = {};
+
+ var node = construct.create("div", null, win.body(), "last");
+
+ var convertToPort = function convertToPort(formValues)
+ {
+ var newPort = {};
+ newPort.name = dijit.byId("formAddPort.name").value;
+ var id = dojo.byId("formAddPort.id").value;
+ if (id)
+ {
+ newPort.id = id;
+ }
+ for(var propName in formValues)
+ {
+ if(formValues.hasOwnProperty(propName))
+ {
+ if (propName === "type" || propName === "protocolsDefault")
+ {
+ continue;
+ }
+
+ if (propName === "protocols")
+ {
+ var val = formValues[propName];
+ if (!lang.isArray(val))
+ {
+ val = [ val ];
+ }
+ newPort[ propName ] = val;
+ }
+ else if(formValues[ propName ] !== "")
+ {
+ newPort[ propName ] = formValues[propName];
+ }
+
+ }
+ }
+ return newPort;
+ };
+
+
+ xhr.get({url: "addPort.html",
+ sync: true,
+ load: function(data) {
+ var theForm;
+ node.innerHTML = data;
+ addPort.dialogNode = dom.byId("addPort");
+ parser.instantiate([addPort.dialogNode]);
+
+ registry.byId("formAddPort.protocolsDefault").on("change", function(isChecked) {
+ dijit.byId("formAddPort.protocolsAMQP").set("disabled", isChecked);
+ });
+
+ registry.byId("formAddPort.type").on("change", function(newValue) {
+ var typeWidget = registry.byId("formAddPort.type");
+ var store = typeWidget.store;
+ store.data.forEach(function(option){
+ registry.byId("formAddPort.protocols" + option.value).set("disabled", true);
+ registry.byId("formAddPort:fields" + option.value).domNode.style.display = "none";
+ });
+ registry.byId("formAddPort:fields" + newValue).domNode.style.display = "block";
+ var defaultsAMQPProtocols = registry.byId("formAddPort.protocolsDefault");
+ defaultsAMQPProtocols.set("disabled", "AMQP" != newValue)
+ var protocolsWidget = registry.byId("formAddPort.protocols" + newValue);
+ var transportWidget = registry.byId("formAddPort.transport");
+ if (protocolsWidget)
+ {
+ if ("AMQP" == newValue && defaultsAMQPProtocols.checked)
+ {
+ protocolsWidget.set("disabled", true);
+ transportWidget.set("required", false);
+ }
+ else
+ {
+ // the transport has to be set for a management port
+ // disabling the default option
+ transportWidget.set("required", true);
+ protocolsWidget.set("disabled", false);
+ }
+ transportWidget.startup();
+ }
+ });
+ theForm = registry.byId("formAddPort");
+
+ theForm.on("submit", function(e) {
+
+ event.stop(e);
+ if(theForm.validate()){
+
+ var newPort = convertToPort(theForm.getValues());
+ var that = this;
+
+ xhr.put({url: "rest/port/"+encodeURIComponent(newPort.name), sync: true, handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.toJson(newPort),
+ load: function(x) {that.success = true; },
+ error: function(error) {that.success = false; that.failureReason = error;}});
+
+ if(this.success === true)
+ {
+ registry.byId("addPort").hide();
+ }
+ else
+ {
+ alert("Error:" + this.failureReason);
+ }
+
+ return false;
+
+
+ }else{
+ alert('Form contains invalid data. Please correct first');
+ return false;
+ }
+
+ });
+ }});
+
+ addPort.show = function(portName, providers) {
+
+ if (!addPort.fields)
+ {
+ var labelWidthValue = "300";
+ addPort.fields = new dojox.layout.TableContainer( {
+ cols: 1,
+ labelWidth: labelWidthValue,
+ showLabels: true,
+ orientation: "horiz",
+ customClass: "formLabel"
+ }, dom.byId("formAddPort:fields"));
+ addPort.fields.startup();
+ addPort.fieldsAMQP = new dojox.layout.TableContainer( {
+ cols: 1,
+ labelWidth: labelWidthValue,
+ showLabels: true,
+ orientation: "horiz",
+ customClass: "formLabel"
+ }, dom.byId("formAddPort:fieldsAMQP"));
+ addPort.fieldsAMQP.startup();
+ addPort.fieldsJMX = new dojox.layout.TableContainer( {
+ cols: 1,
+ labelWidth: labelWidthValue,
+ showLabels: true,
+ orientation: "horiz",
+ customClass: "formLabel"
+ }, dom.byId("formAddPort:fieldsJMX"));
+ addPort.fieldsJMX.startup();
+ addPort.fieldsHTTP = new dojox.layout.TableContainer( {
+ cols: 1,
+ labelWidth: labelWidthValue,
+ showLabels: true,
+ orientation: "horiz",
+ customClass: "formLabel"
+ }, dom.byId("formAddPort:fieldsHTTP"));
+ addPort.fieldsHTTP.startup();
+ }
+ registry.byId("formAddPort").reset();
+ dojo.byId("formAddPort.id").value = "";
+
+ var providerWidget = registry.byId("formAddPort.authenticationProvider");
+ if (providers)
+ {
+ var data = [];
+ for (var i=0; i< providers.length; i++)
+ {
+ data.push( {id: providers[i].name, name: providers[i].name} );
+ }
+ var providersStore = new Memory({ data: data });
+ providerWidget.set("store", providersStore);
+ providerWidget.startup();
+ }
+
+ if (portName)
+ {
+ xhr.get({
+ url: "rest/port/" + encodeURIComponent(portName),
+ handleAs: "json"
+ }).then(
+ function(data){
+ var port = data[0];
+ var nameField = registry.byId("formAddPort.name");
+ nameField.set("value", port.name);
+ nameField.set("disabled", true);
+ dom.byId("formAddPort.id").value=port.id;
+ providerWidget.set("value", port.authenticationProvider ? port.authenticationProvider : "");
+ registry.byId("formAddPort.transport").set("value", port.transports ? port.transports[0] : "");
+ registry.byId("formAddPort.port").set("value", port.port);
+ var protocols = port.protocols;
+ var typeWidget = registry.byId("formAddPort.type");
+ var store = typeWidget.store;
+ store.data.forEach(function(option){
+ registry.byId("formAddPort.protocols" + option.value).set("disabled", true);
+ registry.byId("formAddPort:fields" + option.value).domNode.style.display = "none";
+ });
+
+ // identify the type of port using first protocol specified in protocol field if provided
+ if ( !protocols || protocols.length == 0 || protocols[0].indexOf("AMQP") == 0)
+ {
+ typeWidget.set("value", "AMQP");
+ var amqpProtocolsWidget = registry.byId("formAddPort.protocolsAMQP");
+ var defaultProtocolsWidget = registry.byId("formAddPort.protocolsDefault");
+ var addressWidget = registry.byId("formAddPort.bindingAddress");
+ addressWidget.set("value", port.bindingAddress);
+ amqpProtocolsWidget.set("disabled", false);
+ if (protocols)
+ {
+ amqpProtocolsWidget.set("value", protocols)
+ amqpProtocolsWidget.set("disabled", false)
+ defaultProtocolsWidget.set("checked", false);
+ }
+ else
+ {
+ defaultProtocolsWidget.set("checked", true);
+ amqpProtocolsWidget.set("disabled", true)
+ }
+ }
+ else if (protocols[0].indexOf("RMI") != -1)
+ {
+ var jmxProtocolsWidget = registry.byId("formAddPort.protocolsJMX");
+ jmxProtocolsWidget.set("disabled", false);
+ jmxProtocolsWidget.set("value", protocols[0]);
+ typeWidget.set("value", "JMX");
+ }
+ else if (protocols[0].indexOf("HTTP") == 0)
+ {
+ var httpProtocolsWidget = registry.byId("formAddPort.protocolsHTTP");
+ httpProtocolsWidget.set("disabled", false);
+ httpProtocolsWidget.set("value", protocols[0])
+ typeWidget.set("value", "HTTP");
+ }
+ registry.byId("formAddPort:fields" + typeWidget.value).domNode.style.display = "block";
+ typeWidget.set("disabled", true);
+ registry.byId("addPort").show();
+ });
+ }
+ else
+ {
+ var typeWidget = registry.byId("formAddPort.type");
+ typeWidget.set("disabled", false);
+ typeWidget.set("value", "AMQP");
+ registry.byId("formAddPort.name").set("disabled", false);
+ registry.byId("addPort").show();
+ }
+ };
+
+ return addPort;
+ }); \ No newline at end of file
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html
index 527d38c333..60c514e262 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html
@@ -36,6 +36,8 @@
<br/>
<div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Ports'">
<div class="broker-ports"></div>
+ <button data-dojo-type="dijit.form.Button" class="addPort">Add Port</button>
+ <button data-dojo-type="dijit.form.Button" class="deletePort">Delete Port</button>
</div>
<br/>
<div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Authentication Providers'">
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
index 793c259769..1492982708 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
@@ -474,6 +474,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
Port port = _portFactory.createPort(UUID.randomUUID(), this, attributes);
addPort(port);
+ port.setDesiredState(State.INITIALISING, State.ACTIVE);
return port;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
index c3d2c3d791..63063ff58c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
@@ -31,6 +31,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
@@ -68,6 +69,7 @@ public class PortAdapter extends AbstractAdapter implements Port
private final Broker _broker;
private AuthenticationProvider _authenticationProvider;
+ private AtomicReference<State> _state;
/*
* TODO register PortAceptor as a listener. For supporting multiple
@@ -78,6 +80,8 @@ public class PortAdapter extends AbstractAdapter implements Port
{
super(id, defaults, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor);
_broker = broker;
+ State state = MapValueConverter.getEnumAttribute(State.class, STATE, attributes, State.INITIALISING);
+ _state = new AtomicReference<State>(state);
addParent(Broker.class, broker);
}
@@ -173,12 +177,7 @@ public class PortAdapter extends AbstractAdapter implements Port
@Override
public State getActualState()
{
- State state = (State)super.getAttribute(STATE);
- if (state == null)
- {
- return State.ACTIVE;
- }
- return state;
+ return _state.get();
}
@Override
@@ -288,19 +287,41 @@ public class PortAdapter extends AbstractAdapter implements Port
@Override
public boolean setState(State currentState, State desiredState)
{
+ State state = _state.get();
if (desiredState == State.DELETED)
{
- return true;
+ if (state == State.STOPPED || state == State.QUIESCED)
+ {
+ return _state.compareAndSet(state, State.DELETED);
+ }
+ else
+ {
+ throw new IllegalStateException("Cannot delete port in " + state + " state");
+ }
}
else if (desiredState == State.ACTIVE)
{
- onActivate();
- return true;
+ if ((state == State.INITIALISING || state == State.QUIESCED) && _state.compareAndSet(state, State.ACTIVE))
+ {
+ onActivate();
+ return true;
+ }
+ else
+ {
+ throw new IllegalStateException("Cannot activate port in " + state + " state");
+ }
}
else if (desiredState == State.STOPPED)
{
- onStop();
- return true;
+ if (_state.compareAndSet(state, State.STOPPED))
+ {
+ onStop();
+ return true;
+ }
+ else
+ {
+ throw new IllegalStateException("Cannot stop port in " + state + " state");
+ }
}
return false;
}
@@ -329,6 +350,10 @@ public class PortAdapter extends AbstractAdapter implements Port
@Override
protected void changeAttributes(Map<String, Object> attributes)
{
+ if (getActualState() == State.ACTIVE)
+ {
+ throw new IllegalStateException("Cannot change attributes for an active port");
+ }
super.changeAttributes(MapValueConverter.convert(attributes, ATTRIBUTE_TYPES));
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
index 9d501115b7..1872f3e2ee 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
@@ -112,6 +112,15 @@ public class PortFactory
throw new IllegalConfigurationException("Only one protocol can be used on non AMQP port");
}
Protocol protocol = protocols.iterator().next();
+ Collection<Port> existingPorts = broker.getPorts();
+ for (Port existingPort : existingPorts)
+ {
+ Collection<Protocol> portProtocols = existingPort.getProtocols();
+ if (portProtocols != null && portProtocols.contains(protocol))
+ {
+ throw new IllegalConfigurationException("Port for protocol " + protocol + " already exist. Only one management port per protocol can be created");
+ }
+ }
defaults.put(Port.NAME, portValue + "-" + protocol.name());
port = new PortAdapter(id, broker, attributes, defaults, broker.getTaskExecutor());
}
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
index 14c5c265c9..0c496dfd9b 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.model.adapter;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collection;
@@ -209,4 +210,27 @@ public class PortFactoryTest extends QpidTestCase
// pass
}
}
+
+ public void testCreateRMIPortWhenAnotherRMIPortAlreadyExists()
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(Port.PORT, 1);
+ attributes.put(Port.NAME, getTestName());
+ attributes.put(Port.TRANSPORTS, Collections.singleton(Transport.TCP));
+ attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.RMI));
+
+ Port rmiPort = mock(Port.class);
+ when(rmiPort.getProtocols()).thenReturn(Collections.singleton(Protocol.RMI));
+ when(_broker.getPorts()).thenReturn(Collections.singletonList(rmiPort));
+
+ try
+ {
+ _portFactory.createPort(_portId, _broker, attributes);
+ fail("RMI port creation should fail as another one olready exist");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ // pass
+ }
+ }
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java
index 4db83387e5..63691e9915 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java
@@ -62,7 +62,7 @@ public class BrokerRestTest extends QpidRestTestCase
@SuppressWarnings("unchecked")
List<Map<String, Object>> ports = (List<Map<String, Object>>) brokerDetails.get(BROKER_PORTS_ATTRIBUTE);
- assertEquals("Unexpected number of ports", 4, ports.size());
+ assertEquals("Unexpected number of ports", 2, ports.size());
for (Map<String, Object> port : ports)
{
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
index a9b6657dbd..9302ac88de 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
@@ -40,7 +40,7 @@ public class PortRestTest extends QpidRestTestCase
{
List<Map<String, Object>> ports = getRestTestHelper().getJsonAsList("/rest/port/");
assertNotNull("Port data cannot be null", ports);
- assertEquals("Unexpected number of ports", 4, ports.size());
+ assertEquals("Unexpected number of ports", 2, ports.size());
String httpPortName = TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT;
Map<String, Object> portData = getRestTestHelper().find(Port.NAME, httpPortName, ports);
@@ -57,7 +57,7 @@ public class PortRestTest extends QpidRestTestCase
{
List<Map<String, Object>> ports = getRestTestHelper().getJsonAsList("/rest/port/");
assertNotNull("Ports data cannot be null", ports);
- assertEquals("Unexpected number of ports", 4, ports.size());
+ assertEquals("Unexpected number of ports", 2, ports.size());
for (Map<String, Object> portMap : ports)
{
String portName = (String) portMap.get(Port.NAME);
@@ -115,6 +115,15 @@ public class PortRestTest extends QpidRestTestCase
portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
assertNotNull("Port details cannot be null", portDetails);
assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size());
+
+ // try to add a second RMI port
+ attributes = new HashMap<String, Object>();
+ attributes.put(Port.NAME, portName + 2);
+ attributes.put(Port.PORT, findFreePort());
+ attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.RMI));
+
+ responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
+ assertEquals("Adding of a second RMI port should fail", 409, responseCode);
}
public void testPutCreateAndUpdateAmqpPort() throws Exception
@@ -145,7 +154,13 @@ public class PortRestTest extends QpidRestTestCase
attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.AMQP_0_9_1));
responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
- assertEquals("Unexpected response code for port update", 200, responseCode);
+ assertEquals("Port cannot be updated in non management mode", 409, responseCode);
+
+ stopBroker();
+ startBroker(DEFAULT_PORT, true);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
+ assertEquals("Port should be allwed to update in a management mode", 200, responseCode);
portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
assertNotNull("Port details cannot be null", portDetails);
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java
index 671bdd7eb8..e2b73aa2b5 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java
@@ -75,6 +75,8 @@ public class QpidRestTestCase extends QpidBrokerTestCase
TestBrokerConfiguration config = getBrokerConfiguration();
config.addHttpManagementConfiguration();
config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.PORT, _restTestHelper.getHttpPort());
+ config.removeObjectConfiguration(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT);
+ config.removeObjectConfiguration(TestBrokerConfiguration.ENTRY_NAME_RMI_PORT);
}
public RestTestHelper getRestTestHelper()
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
index 427934fac2..f5e326f90b 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
@@ -41,7 +41,7 @@ public class StructureRestTest extends QpidRestTestCase
@SuppressWarnings("unchecked")
List<Map<String, Object>> ports = (List<Map<String, Object>>) structure.get("ports");
- assertEquals("Unexpected number of ports", 4, ports.size());
+ assertEquals("Unexpected number of ports", 2, ports.size());
@SuppressWarnings("unchecked")
List<Map<String, Object>> providers = (List<Map<String, Object>>) structure.get("authenticationproviders");