diff options
author | Alex Rudyy <orudyy@apache.org> | 2013-03-11 18:30:31 +0000 |
---|---|---|
committer | Alex Rudyy <orudyy@apache.org> | 2013-03-11 18:30:31 +0000 |
commit | 3f138e2ddc02857c61e578aaaf12c82d9eefc93c (patch) | |
tree | 3de578ab99d630bc1610a263452c6715a0f0d901 | |
parent | 66de8678fb2ab2af8dc5b6d653402b1efd70779b (diff) | |
download | qpid-python-3f138e2ddc02857c61e578aaaf12c82d9eefc93c.tar.gz |
QPID-4639: Add UI to add/delete virtual hosts into java broker web management console
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1455274 13f79535-47bb-0310-9956-ffa450edef68
17 files changed, 471 insertions, 30 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java index fa82632dc1..3c6fb1c44d 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java @@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.qpid.server.management.plugin.servlet.rest.action.ListAuthenticationProviderAttributes; +import org.apache.qpid.server.management.plugin.servlet.rest.action.ListMessageStoreTypes; import org.apache.qpid.server.model.Broker; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; @@ -50,6 +51,8 @@ public class HelperServlet extends AbstractServlet _actions = new HashMap<String, Action>(); Action listProviderAttributes = new ListAuthenticationProviderAttributes(); _actions.put(listProviderAttributes.getName(), listProviderAttributes); + Action listMessageStoreTypes = new ListMessageStoreTypes(); + _actions.put(listMessageStoreTypes.getName(), listMessageStoreTypes); } @Override diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListMessageStoreTypes.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListMessageStoreTypes.java new file mode 100644 index 0000000000..4166736c01 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/action/ListMessageStoreTypes.java @@ -0,0 +1,23 @@ +package org.apache.qpid.server.management.plugin.servlet.rest.action; + +import java.util.Map; + +import org.apache.qpid.server.management.plugin.servlet.rest.Action; +import org.apache.qpid.server.model.Broker; + +public class ListMessageStoreTypes implements Action +{ + + @Override + public String getName() + { + return ListMessageStoreTypes.class.getSimpleName(); + } + + @Override + public Object perform(Map<String, Object> request, Broker broker) + { + return broker.getAttribute(Broker.SUPPORTED_STORE_TYPES); + } + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHost.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHost.html new file mode 100644 index 0000000000..d66e0e1b03 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addVirtualHost.html @@ -0,0 +1,71 @@ +<!-- + - + - 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:'Add Virtual Host'" id="addVirtualHost"> + <form id="formAddVirtualHost" method="post" dojoType="dijit.form.Form"> + <table class="tableContainer-table tableContainer-table-horiz"> + <tr> + <td class="tableContainer-labelCell" style="width: 300px;"><strong>Name*: </strong></td> + <td class="tableContainer-valueCell"> + <input type="text" required="true" name="name" id="formAddVirtualHost.name" + placeholder="Virtual Host Name" dojoType="dijit.form.ValidationTextBox" + missingMessage="A name must be supplied" /> + </td> + </tr> + </table> + <br /> + <div>Specify either a store type and location, or an XML configuration file location, but not both.</div> + <div style="height: 300px;" id="addVirtualHost.variants"> + <div id="addVirtualHost.configPathDiv"> + <table class="tableContainer-table tableContainer-table-horiz"> + <tr> + <td class="tableContainer-labelCell" style="width: 300px;"><strong>Path to virtual host configuration file*: </strong></td> + <td class="tableContainer-valueCell"> + <input dojoType="dijit.form.ValidationTextBox" id="formAddVirtualHost.configPath" + name="configPath" placeholder="/path/to/virtualhost.xml" /> + </td> + </tr> + </table> + </div> + <div id="addVirtualHost.attributesDiv"> + <table class="tableContainer-table tableContainer-table-horiz"> + <tr> + <td class="tableContainer-labelCell" style="width: 300px;"><strong>Store Type*: </strong></td> + <td class="tableContainer-valueCell" ><div id="addVirtualHost.selectStoreType"></div></td> + </tr> + <tr> + <td class="tableContainer-labelCell" style="width: 300px;"><strong>Path to store location*: </strong></td> + <td class="tableContainer-valueCell"> + <input dojoType="dijit.form.ValidationTextBox" id="formAddVirtualHost.storePath" + name="storePath" placeholder="/path/to/message/store" /> + </td> + </tr> + </table> + </div> + </div> + + <br/> + <!-- submit buttons --> + <input type="submit" value="Save" label="Save" dojoType="dijit.form.Button" /> + <input type="hidden" id="formAddVirtualHost.id" name="id"/> + </form> + </div> +</div> 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 9b4e7aa3f9..84a0d8ca68 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 @@ -29,10 +29,13 @@ define(["dojo/_base/xhr", "dojox/grid/EnhancedGrid", "dijit/registry", "qpid/management/addAuthenticationProvider", + "qpid/management/addVirtualHost", "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) { + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, registry, addAuthenticationProvider, addVirtualHost) { function Broker(name, parent, controller) { this.name = name; @@ -78,6 +81,19 @@ define(["dojo/_base/xhr", } ); + var addHostButton = query(".addVirtualHost", contentPane.containerNode)[0]; + connect.connect(registry.byNode(addHostButton), "onClick", function(evt){ addVirtualHost.show(); }); + + var deleteHostButton = query(".deleteVirtualHost", contentPane.containerNode)[0]; + connect.connect(registry.byNode(deleteHostButton), "onClick", + function(evt){ + util.deleteGridSelections( + that.brokerUpdater, + that.brokerUpdater.vhostsGrid.grid, + "rest/virtualhost", + "Deletion of virtual will delete the message store data.\n\n Are you sure you want to delete virtual host"); + } + ); }}); }; @@ -105,6 +121,22 @@ define(["dojo/_base/xhr", util.flattenStatistics( that.brokerData); that.updateHeader(); + + var gridProperties = { + height: 400, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + }}; + that.vhostsGrid = new UpdatableStore(that.brokerData.vhosts, query(".broker-virtualhosts")[0], [ { name: "Virtual Host", field: "name", width: "120px"}, @@ -119,7 +151,7 @@ define(["dojo/_base/xhr", var name = obj.dataStore.getValue(theItem,"name"); that.controller.show("virtualhost", name, brokerObj); }); - }); + }, gridProperties, EnhancedGrid); that.portsGrid = new UpdatableStore(that.brokerData.ports, query(".broker-ports")[0], @@ -137,7 +169,7 @@ define(["dojo/_base/xhr", }); }); - var gridProperties = { + gridProperties = { keepSelection: true, plugins: { indirectSelection: true diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js index 2efc46476d..ceab5640d3 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js @@ -134,7 +134,10 @@ define(["dojo/_base/xhr", "bytesInRateUnits", "msgOutRate", "bytesOutRate", - "bytesOutRateUnits"]); + "bytesOutRateUnits", + "storeType", + "storePath", + "configPath"]); this.query = "rest/virtualhost/"+ encodeURIComponent(vhost.name); @@ -143,6 +146,11 @@ define(["dojo/_base/xhr", xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) { that.vhostData = data[0]; + if (!that.vhostData.hasOwnProperty("configPath")) + { + var node = findNode("configPathDiv"); + node.style.display = "none"; + } // flatten statistics into attributes util.flattenStatistics( that.vhostData ); @@ -233,8 +241,9 @@ define(["dojo/_base/xhr", this.state.innerHTML = this.vhostData[ "state" ]; this.durable.innerHTML = this.vhostData[ "durable" ]; this.lifetimePolicy.innerHTML = this.vhostData[ "lifetimePolicy" ]; - - + this.storeType.innerHTML = this.vhostData[ "storeType" ]; + this.storePath.innerHTML = this.vhostData[ "storePath" ]; + this.configPath.innerHTML = this.vhostData[ "configPath" ]; }; Updater.prototype.update = function() diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHost.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHost.js new file mode 100644 index 0000000000..9c04c3014f --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHost.js @@ -0,0 +1,211 @@ +/* + * + * 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/_base/connect", + "dojo/dom-style", + "dijit/form/NumberSpinner", // required by the form + /* dojox/ validate resources */ + "dojox/validate/us", "dojox/validate/web", + /* basic dijit classes */ + "dijit/Dialog", + "dijit/form/CheckBox", "dijit/form/Textarea", + "dijit/form/FilteringSelect", "dijit/form/TextBox", + "dijit/form/ValidationTextBox", "dijit/form/DateTextBox", + "dijit/form/TimeTextBox", "dijit/form/Button", + "dijit/form/RadioButton", "dijit/form/Form", + "dijit/form/DateTextBox", + /* basic dojox classes */ + "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect", + "dojox/layout/TableContainer", + "dijit/layout/AccordionContainer", + "dijit/layout/AccordionPane", + "dojo/domReady!"], + function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, FilteringSelect, connect, domStyle) { + + var addVirtualHost = {}; + + var node = construct.create("div", null, win.body(), "last"); + + var convertToVirtualHost = function convertToVirtualHost(formValues) + { + var newVirtualHost = {}; + var id = dojo.byId("formAddVirtualHost.id").value; + if (id) + { + newVirtualHost.id = id; + } + for(var propName in formValues) + { + if(formValues.hasOwnProperty(propName)) + { + if(formValues[ propName ] !== "") { + newVirtualHost[ propName ] = formValues[propName]; + } + + } + } + + return newVirtualHost; + } + + if (!dijit.registry["addVirtualHost"]) + { + var that = this; + xhr.get({url: "addVirtualHost.html", + sync: true, + load: function(data) { + var theForm; + node.innerHTML = data; + addVirtualHost.dialogNode = dom.byId("addVirtualHost"); + parser.instantiate([addVirtualHost.dialogNode]); + + var configPathPane = new dijit.layout.AccordionPane({ + title: "Configuration File" + }, "addVirtualHost.configPathDiv"); + + var attributesPane = new dijit.layout.AccordionPane({ + title: "Store Attributes", + selected: true + }, "addVirtualHost.attributesDiv"); + + var aContainer = new dijit.layout.AccordionContainer({ + style: "height: 150px" + }, + "addVirtualHost.variants"); + + aContainer.addChild(attributesPane); + aContainer.addChild(configPathPane); + aContainer.startup(); + + theForm = registry.byId("formAddVirtualHost"); + theForm.on("submit", function(e) { + + event.stop(e); + if(theForm.validate()){ + + var formValues = theForm.getValues(); + if (formValues.configPath == "" && formValues.storeType == "") + { + alert("Please specify either configuration or store type for the virtual host"); + return false; + } + if (formValues.configPath != "" && formValues.storeType != "") + { + alert("Either configuration or store type with path have to be specified!"); + return false; + } + var newVirtualHost = convertToVirtualHost(formValues); + var that = this; + + xhr.put({url: "rest/virtualhost/" + encodeURIComponent(newVirtualHost.name), + sync: true, handleAs: "json", + headers: { "Content-Type": "application/json"}, + putData: json.toJson(newVirtualHost), + load: function(x) {that.success = true; }, + error: function(error) {that.success = false; that.failureReason = error;}}); + + if(this.success === true) + { + registry.byId("addVirtualHost").hide(); + } + else + { + alert("Error:" + this.failureReason); + } + return false; + }else{ + alert('Form contains invalid data. Please correct first'); + return false; + } + }); + }}); + } + + addVirtualHost.show = function(virtualHostName) { + var that = this; + registry.byId("formAddVirtualHost").reset(); + dojo.byId("formAddVirtualHost.id").value=""; + if (!that.hasOwnProperty("storeTypeChooser")) + { + xhr.get({ + sync: true, + url: "rest/helper?action=ListMessageStoreTypes", + handleAs: "json" + }).then( + function(data) { + var storeTypes = data; + var storeTypesData = []; + for (var i =0 ; i < storeTypes.length; i++) + { + storeTypesData[i]= {id: storeTypes[i], name: storeTypes[i]}; + } + var storeTypesStore = new Memory({ data: storeTypesData }); + var storeTypesDiv = dom.byId("addVirtualHost.selectStoreType"); + var input = construct.create("input", {id: "addStoreType", required: false}, storeTypesDiv); + that.storeTypeChooser = new FilteringSelect({ id: "addVirtualHost.storeType", + name: "storeType", + store: storeTypesStore, + searchAttr: "name", required: false}, input); + }); + } + if (virtualHostName) + { + xhr.get({ + url: "rest/virtualhost/" + encodeURIComponent(virtualHostName), + handleAs: "json" + }).then( + function(data) { + var host = data[0]; + var nameField = dijit.byId("formAddVirtualHost.name"); + nameField.set("value", host.name); + dojo.byId("formAddVirtualHost.id").value=host.id; + var configPath = host.configPath; + if (configPath) + { + var configPathField = dijit.byId("formAddVirtualHost.configPath"); + configPathField.set("value", host.configPath); + } + else + { + that.storeTypeChooser.set("value", host.storeType.toLowerCase()); + var storePathField = dijit.byId("formAddVirtualHost.storePath"); + storePathField.set("value", host.storePath); + } + registry.byId("addVirtualHost").show(); + }); + } + else + { + registry.byId("addVirtualHost").show(); + } + } + return addVirtualHost; + });
\ 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 f656124a2a..527d38c333 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 @@ -30,6 +30,8 @@ <br/> <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Virtual Hosts'"> <div class="broker-virtualhosts"></div> + <button data-dojo-type="dijit.form.Button" class="addVirtualHost">Add Virtual Host</button> + <button data-dojo-type="dijit.form.Button" class="deleteVirtualHost">Delete Virtual Host</button> </div> <br/> <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Ports'"> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html index 73c912e0d4..14833e0d2e 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showVirtualHost.html @@ -39,6 +39,13 @@ <span class="bytesOutRate" style="position:absolute; right: 3.3em"></span> <span class="bytesOutRateUnits" style="position:absolute; right: 0em; width: 3em"></span> <br/> + <span style="">Store Type:</span><span style="position:absolute; left:6em" class="storeType"></span> + <span style="position:absolute; left:26em">Store Path:</span> + <span class="storePath" style="position:absolute; right: 1em"></span> + <div class="configPathDiv"> + <span style="">ConfigPath:</span><span style="position:absolute; left:6em" class="configPath"></span> + </div> + <br/> <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Exchanges'"> <div class="exchanges"></div> diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java index d725dc4dc3..3342aea4fb 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java @@ -297,12 +297,27 @@ public class JMXManagement extends AbstractPluginAdapter implements Configuratio } catch(JMException e) { - LOGGER.error("Error creating mbean", e); + LOGGER.error("Error unregistering user management mbean: " + child.getName(), e); + //TODO - report error on removing child MBean + } + } + } + else if (child instanceof VirtualHost) + { + AMQManagedObject mbean = _children.remove(child); + if(mbean != null) + { + try + { + mbean.unregister(); + } + catch(JMException e) + { + LOGGER.error("Error unregistering virtual host mbean :" + child.getName(), e); //TODO - report error on removing child MBean } } } - } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java index 4bfa0ca7a3..48d80592f6 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java @@ -51,6 +51,7 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> StoreConfigurationChangeListener storeChangeListener = new StoreConfigurationChangeListener(entry.getStore()); BrokerAdapter broker = new BrokerAdapter(entry.getId(), entry.getAttributes(), _statisticsGatherer, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _portFactory, _taskExecutor); + broker.addChangeListener(storeChangeListener); Map<String, Collection<ConfigurationEntry>> childEntries = entry.getChildren(); for (String type : childEntries.keySet()) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java index d053dd3fe2..5528a05360 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java @@ -24,6 +24,7 @@ import org.apache.log4j.Logger; import org.apache.log4j.spi.ErrorHandler; import org.apache.log4j.spi.Filter; import org.apache.log4j.spi.LoggingEvent; +import org.apache.log4j.spi.ThrowableInformation; public class LogRecorder implements Appender, Iterable<LogRecorder.Record> { @@ -54,7 +55,34 @@ public class LogRecorder implements Appender, Iterable<LogRecorder.Record> _timestamp = event.timeStamp; _threadName = event.getThreadName(); _level = event.getLevel().toString(); - _message = event.getRenderedMessage(); + StringBuilder message = new StringBuilder(); + String renderedMessage = event.getRenderedMessage(); + if (renderedMessage != null) + { + message.append(renderedMessage); + } + ThrowableInformation ti = event.getThrowableInformation(); + if (ti != null) + { + Throwable t = ti.getThrowable(); + if (t != null) + { + if (message.length() > 0) + { + message.append(":"); + } + String exceptionMessage = t.getMessage(); + if (exceptionMessage != null && !"".equals(exceptionMessage)) + { + message.append(t.getMessage()); + } + else + { + message.append(t.getClass().getName()); + } + } + } + _message = message.toString(); } public long getId() 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 6b7cf98c8a..628ba5a099 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 @@ -63,6 +63,7 @@ import org.apache.qpid.server.security.group.GroupPrincipalAccessor; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.MessageStoreCreator; import org.apache.qpid.server.util.MapValueConverter; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; @@ -168,6 +169,8 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private final UUID _defaultKeyStoreId; private final UUID _defaultTrustStoreId; + private Collection<String> _supportedStoreTypes; + public BrokerAdapter(UUID id, Map<String, Object> attributes, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, AuthenticationProviderFactory authenticationProviderFactory, PortFactory portFactory, TaskExecutor taskExecutor) @@ -185,6 +188,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat _defaultKeyStoreId = UUIDGenerator.generateBrokerChildUUID(KeyStore.class.getSimpleName(), DEFAULT_KEY_STORE_NAME); _defaultTrustStoreId = UUIDGenerator.generateBrokerChildUUID(TrustStore.class.getSimpleName(), DEFAULT_TRUST_STORE_NAME); createBrokerChildrenFromAttributes(); + _supportedStoreTypes = new MessageStoreCreator().getStoreTypes(); } /* @@ -646,7 +650,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat } else if(SUPPORTED_STORE_TYPES.equals(name)) { - // TODO + return _supportedStoreTypes; } else if(SUPPORTED_AUTHENTICATION_PROVIDERS.equals(name)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java index 40af67f211..8680911000 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -115,9 +115,9 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual public VirtualHostAdapter(UUID id, Map<String, Object> attributes, Broker broker, StatisticsGatherer brokerStatisticsGatherer, TaskExecutor taskExecutor) { super(id, null, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); - validateAttributes(); _broker = broker; _brokerStatisticsGatherer = brokerStatisticsGatherer; + validateAttributes(); addParent(Broker.class, broker); } @@ -145,11 +145,22 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { invalidAttributes = true; } + } if (invalidAttributes) { throw new IllegalConfigurationException("Please specify either the 'configPath' attribute or 'storeType' and 'storePath' attributes"); } + + // pre-load the configuration in order to validate + try + { + createVirtualHostConfiguration(name); + } + catch(ConfigurationException e) + { + throw new IllegalConfigurationException("Failed to validate configuration", e); + } } private void populateExchanges() @@ -504,11 +515,19 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { if(childClass == Exchange.class) { - return (C) createExchange(attributes); + createExchange(attributes); + + // return null to avoid double notification of VirtualHostMBean + // as we already notify it in the exchangeRegistered + return null; } else if(childClass == Queue.class) { - return (C) createQueue(attributes); + createQueue(attributes); + + // return null to avoid double notification of VirtualHostMBean + // as we already notify it in the queueRegistered + return null; } else if(childClass == VirtualHostAlias.class) { @@ -969,12 +988,24 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { throw new IntegrityViolationException("Cannot delete default virtual host '" + hostName + "'"); } + String storePath = (String)getAttribute(STORE_PATH); if (_virtualHost != null && _virtualHost.getState() == org.apache.qpid.server.virtualhost.State.ACTIVE) { setDesiredState(currentState, State.STOPPED); } _virtualHost = null; setAttribute(VirtualHost.STATE, getActualState(), State.DELETED); + if (storePath != null) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Deleting store at " + storePath); + } + if (!FileUtils.delete(new File(storePath), true)) + { + LOGGER.warn("Cannot delete " + storePath); + } + } return true; } return false; @@ -1034,6 +1065,10 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual } else { + if (!new File(configurationFile).exists()) + { + throw new IllegalConfigurationException("Configuration file '" + configurationFile + "' does not exist"); + } configuration = new VirtualHostConfiguration(virtualHostName, new File(configurationFile) , _broker); } return configuration; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java index 0bc83c89d2..d67ccfd8a4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java @@ -64,4 +64,9 @@ public class MessageStoreCreator { return Collections.unmodifiableCollection(_factories.values()); } + + public Collection<String> getStoreTypes() + { + return Collections.unmodifiableCollection(_factories.keySet()); + } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java index eb5b2b350f..adb1f81a43 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.configuration.startup; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.io.File; import java.util.HashMap; import java.util.Map; @@ -34,6 +35,7 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.test.utils.TestFileUtils; public class VirtualHostRecovererTest extends TestCase { @@ -43,12 +45,16 @@ public class VirtualHostRecovererTest extends TestCase SecurityManager securityManager = mock(SecurityManager.class); ConfigurationEntry entry = mock(ConfigurationEntry.class); Broker parent = mock(Broker.class); + when(parent.getAttribute(Broker.HOUSEKEEPING_CHECK_PERIOD)).thenReturn(3000l); when(parent.getSecurityManager()).thenReturn(securityManager); VirtualHostRecoverer recoverer = new VirtualHostRecoverer(statisticsGatherer); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(VirtualHost.NAME, getName()); - attributes.put(VirtualHost.CONFIG_PATH, "/path/to/virtualhost.xml"); + String name = getName(); + attributes.put(VirtualHost.NAME, name); + File file = TestFileUtils.createTempFile(this, ".xml", "<virtualhosts><virtualhost><name>" + name + "</name><" + name + + "></" + name + "></virtualhost></virtualhosts>"); + attributes.put(VirtualHost.CONFIG_PATH, file.getAbsolutePath()); when(entry.getAttributes()).thenReturn(attributes); VirtualHost host = recoverer.create(null, entry, parent); @@ -63,6 +69,7 @@ public class VirtualHostRecovererTest extends TestCase SecurityManager securityManager = mock(SecurityManager.class); ConfigurationEntry entry = mock(ConfigurationEntry.class); Broker parent = mock(Broker.class); + when(parent.getAttribute(Broker.HOUSEKEEPING_CHECK_PERIOD)).thenReturn(3000l); when(parent.getSecurityManager()).thenReturn(securityManager); VirtualHostRecoverer recoverer = new VirtualHostRecoverer(statisticsGatherer); diff --git a/qpid/java/systests/etc/config-systests.json b/qpid/java/systests/etc/config-systests.json index a5b85a2050..412bee3f6b 100644 --- a/qpid/java/systests/etc/config-systests.json +++ b/qpid/java/systests/etc/config-systests.json @@ -28,7 +28,7 @@ "trustStorePassword": "password", "authenticationproviders" : [ { "name" : "plain", - "authenticationProviderType" : "PlainPasswordFileAuthenticationProvider", + "type" : "PlainPasswordFileAuthenticationProvider", "path" : "${QPID_HOME}/etc/passwd" } ], "ports" : [ { diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java index 89645507c4..40a1c13718 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java @@ -52,7 +52,7 @@ public class AuthenticationProviderRestTest extends QpidRestTestCase } } - public void testPutCreateNewPlainPrincipalDatabaseProvider() throws Exception + public void testPutCreateSecondPlainPrincipalDatabaseProviderFails() throws Exception { File principalDatabase = getRestTestHelper().createTemporaryPasswdFile(new String[]{"admin2", "guest2", "test2"}); @@ -63,19 +63,7 @@ public class AuthenticationProviderRestTest extends QpidRestTestCase attributes.put(PlainPasswordFileAuthenticationManagerFactory.ATTRIBUTE_PATH, principalDatabase.getAbsolutePath()); int responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + providerName, "PUT", attributes); - assertEquals("Unexpected response code", 201, responseCode); - - List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider/" + providerName); - assertNotNull("Providers details cannot be null", providerDetails); - assertEquals("Unexpected number of providers", 1, providerDetails.size()); - Map<String, Object> provider = providerDetails.get(0); - assertProvider(true, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE, provider); - - // provider should exists after broker restart - restartBroker(); - providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider/" + providerName); - assertNotNull("Providers details cannot be null", providerDetails); - assertEquals("Unexpected number of providers", 1, providerDetails.size()); + assertEquals("Expected to fail because we can have only one password provider", 409, responseCode); } public void testPutCreateNewAnonymousProvider() throws Exception |