From 868ce7469262d6fd2fe3f2e7f04cfe7af654d59f Mon Sep 17 00:00:00 2001 From: Kim van der Riet Date: Mon, 27 Aug 2012 15:40:33 +0000 Subject: QPID-3858: Updated code to include recent refactoring by Gordon (gsim) - see QPID-4178. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1377715 13f79535-47bb-0310-9956-ffa450edef68 --- java/.gitignore | 18 ++ java/amqp-1-0-client-jms/README.txt | 12 + java/amqp-1-0-client-jms/build.xml | 11 + .../rest/ConfiguredObjectToMapConverter.java | 132 ++++++++++ .../plugin/servlet/rest/RestServlet.java | 143 ++++------- .../plugin/servlet/rest/StructureServlet.java | 2 +- .../src/main/java/resources/showBroker.html | 20 ++ .../rest/AuthenticationProviderRestTest.java | 20 ++ .../plugin/servlet/rest/BindingRestTest.java | 20 ++ .../rest/ConfiguredObjectToMapConverterTest.java | 141 +++++++++++ .../plugin/servlet/rest/ExchangeRestTest.java | 20 ++ .../plugin/servlet/rest/PortRestTest.java | 20 ++ .../plugin/servlet/rest/SaslRestTest.java | 20 ++ .../plugin/servlet/rest/UserRestTest.java | 20 ++ .../server/jmx/MBeanInvocationHandlerImpl.java | 131 ++++++---- .../qpid/server/jmx/ManagementLogActorTest.java | 170 +++++++++++++ java/broker/etc/broker_example.acl | 25 +- .../server/logging/actors/ManagementActor.java | 50 ++-- .../java/org/apache/qpid/server/model/Model.java | 62 ++--- .../server/logging/actors/ManagementActorTest.java | 72 +++++- java/build.deps | 2 +- .../org/apache/qpid/client/AMQBrokerDetails.java | 11 +- .../java/org/apache/qpid/jms/BrokerDetails.java | 6 +- .../client/BrokerDetails/BrokerDetailsTest.java | 24 ++ java/client/test/bin/IBM-JNDI-Setup.bat | 69 ----- java/client/test/bin/IBM-JNDI-Setup.sh | 27 -- java/client/test/bin/IBM-Publisher.bat | 62 ----- java/client/test/bin/IBM-Publisher.sh | 22 -- java/client/test/bin/IBM-PutGet.bat | 62 ----- java/client/test/bin/IBM-PutGet.sh | 21 -- java/client/test/bin/IBM-README.txt | 19 -- java/client/test/bin/IBM-Receiver.bat | 62 ----- java/client/test/bin/IBM-Receiver.sh | 22 -- java/client/test/bin/IBM-Sender.bat | 62 ----- java/client/test/bin/IBM-Sender.sh | 22 -- java/client/test/bin/IBM-Subscriber.bat | 62 ----- java/client/test/bin/IBM-Subscriber.sh | 22 -- java/client/test/bin/headersListener.sh | 22 -- java/client/test/bin/headersListenerGroup.sh | 25 -- java/client/test/bin/headersPublisher.sh | 22 -- java/client/test/bin/run_many.sh | 30 --- java/client/test/bin/serviceProvidingClient.sh | 24 -- java/client/test/bin/serviceRequestingClient.sh | 27 -- java/client/test/bin/testService.sh | 22 -- java/client/test/bin/topicListener.sh | 23 -- java/client/test/bin/topicPublisher.sh | 22 -- java/client/test/etc/ApacheDS.properties | 24 -- java/client/test/example_build.xml | 104 -------- java/common.xml | 3 +- .../qpid/configuration/ClientProperties.java | 13 +- .../qpid/configuration/CommonProperties.java | 41 +++ .../java/org/apache/qpid/transport/Connection.java | 26 +- .../apache/qpid/transport/ConnectionSettings.java | 22 +- .../qpid/transport/ProtocolViolationException.java | 35 --- .../transport/network/io/IoNetworkTransport.java | 7 +- java/ivy.retrieve.xml | 2 +- java/ivysettings.retrieve.xml | 1 - java/lib/poms/je-5.0.55.xml | 22 -- java/lib/poms/je-5.0.58.xml | 22 ++ .../1021-AcknowledgementModes-AutoAck.chartdef | 33 --- .../1021-AcknowledgementModes-Persistent.chartdef | 35 +++ .../1022-AcknowledgementModes-Transacted.chartdef | 32 --- .../1022-AcknowledgementModes-Transient.chartdef | 32 +++ java/perftests/etc/testdefs/Topic-AckModes.js | 21 ++ .../etc/testdefs/Topic-NumberOfConsumers.js | 21 ++ .../perftests/etc/testdefs/Topic-NumberOfTopics.js | 21 ++ java/perftests/etc/testdefs/Topic-Persistence.js | 20 ++ java/perftests/example/perftests.js | 21 +- java/perftests/src/main/java/test-utils.js | 20 ++ .../qpid/disttest/charting/writer/ChartWriter.java | 9 + .../charting/writer/expected-chart-summary.html | 6 + java/systests/etc/log.properties | 19 ++ .../qpid/server/queue/PersistentTestManual.java | 277 --------------------- .../python_tests/Java010PythonExcludes | 1 + 74 files changed, 1248 insertions(+), 1545 deletions(-) create mode 100644 java/amqp-1-0-client-jms/README.txt create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java create mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java delete mode 100644 java/client/test/bin/IBM-JNDI-Setup.bat delete mode 100755 java/client/test/bin/IBM-JNDI-Setup.sh delete mode 100644 java/client/test/bin/IBM-Publisher.bat delete mode 100755 java/client/test/bin/IBM-Publisher.sh delete mode 100644 java/client/test/bin/IBM-PutGet.bat delete mode 100755 java/client/test/bin/IBM-PutGet.sh delete mode 100644 java/client/test/bin/IBM-README.txt delete mode 100644 java/client/test/bin/IBM-Receiver.bat delete mode 100755 java/client/test/bin/IBM-Receiver.sh delete mode 100644 java/client/test/bin/IBM-Sender.bat delete mode 100755 java/client/test/bin/IBM-Sender.sh delete mode 100644 java/client/test/bin/IBM-Subscriber.bat delete mode 100755 java/client/test/bin/IBM-Subscriber.sh delete mode 100755 java/client/test/bin/headersListener.sh delete mode 100755 java/client/test/bin/headersListenerGroup.sh delete mode 100755 java/client/test/bin/headersPublisher.sh delete mode 100755 java/client/test/bin/run_many.sh delete mode 100755 java/client/test/bin/serviceProvidingClient.sh delete mode 100755 java/client/test/bin/serviceRequestingClient.sh delete mode 100755 java/client/test/bin/testService.sh delete mode 100755 java/client/test/bin/topicListener.sh delete mode 100755 java/client/test/bin/topicPublisher.sh delete mode 100644 java/client/test/etc/ApacheDS.properties delete mode 100644 java/client/test/example_build.xml create mode 100644 java/common/src/main/java/org/apache/qpid/configuration/CommonProperties.java delete mode 100644 java/common/src/main/java/org/apache/qpid/transport/ProtocolViolationException.java delete mode 100644 java/lib/poms/je-5.0.55.xml create mode 100644 java/lib/poms/je-5.0.58.xml delete mode 100644 java/perftests/etc/chartdefs/1021-AcknowledgementModes-AutoAck.chartdef create mode 100644 java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef delete mode 100644 java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transacted.chartdef create mode 100644 java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef mode change 100644 => 100755 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html delete mode 100644 java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTestManual.java (limited to 'java') diff --git a/java/.gitignore b/java/.gitignore index 36097e3820..417b51f12d 100644 --- a/java/.gitignore +++ b/java/.gitignore @@ -1,2 +1,20 @@ +# +# 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. +# *.swp eclipse-projects/* diff --git a/java/amqp-1-0-client-jms/README.txt b/java/amqp-1-0-client-jms/README.txt new file mode 100644 index 0000000000..eac8344aac --- /dev/null +++ b/java/amqp-1-0-client-jms/README.txt @@ -0,0 +1,12 @@ +Documentation +============= + +You can access documentation for the client via our website at: +http://qpid.apache.org/documentation + +and via our wiki at: +http://cwiki.apache.org/confluence/display/qpid/Qpid+Java+Documentation + +The client uses the Java Message Service (JMS) 1.1 API, information on which is +widely available using your favoured search engine. + diff --git a/java/amqp-1-0-client-jms/build.xml b/java/amqp-1-0-client-jms/build.xml index 82d5aa5c7a..cfc6e0babe 100644 --- a/java/amqp-1-0-client-jms/build.xml +++ b/java/amqp-1-0-client-jms/build.xml @@ -22,8 +22,19 @@ + + + + + + + + + + + diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java new file mode 100644 index 0000000000..03dd7c66a8 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java @@ -0,0 +1,132 @@ +/* + * 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. + * + */ +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.Statistics; + +public class ConfiguredObjectToMapConverter +{ + /** Name of the key used for the statistics map */ + public static final String STATISTICS_MAP_KEY = "statistics"; + + private Model _model = Model.getInstance(); + + public Map convertObjectToMap(final ConfiguredObject confObject, + Class clazz, + int depth) + { + Map object = new LinkedHashMap(); + + incorporateAttributesIntoMap(confObject, object); + incorporateStatisticsIntoMap(confObject, object); + + if(depth > 0) + { + incorporateChildrenIntoMap(confObject, clazz, depth, object); + } + return object; + } + + /** + * Used for unit test only. + */ + void setModel(Model model) + { + _model = model; + } + + private void incorporateAttributesIntoMap( + final ConfiguredObject confObject, Map object) + { + for(String name : confObject.getAttributeNames()) + { + Object value = confObject.getAttribute(name); + if(value instanceof ConfiguredObject) + { + object.put(name, ((ConfiguredObject) value).getName()); + } + else if(value != null) + { + object.put(name, value); + } + } + } + + private void incorporateStatisticsIntoMap( + final ConfiguredObject confObject, Map object) + { + Statistics statistics = confObject.getStatistics(); + Map statMap = new HashMap(); + + if (statistics != null) + { + for(String name : statistics.getStatisticNames()) + { + Object value = statistics.getStatistic(name); + if(value != null) + { + statMap.put(name, value); + } + } + + if(!statMap.isEmpty()) + { + object.put(STATISTICS_MAP_KEY, statMap); + } + } + } + + private void incorporateChildrenIntoMap( + final ConfiguredObject confObject, + Class clazz, int depth, + Map object) + { + for(Class childClass : _model.getChildTypes(clazz)) + { + Collection children = confObject.getChildren(childClass); + if(children != null) + { + List> childObjects = new ArrayList>(); + + for(ConfiguredObject child : children) + { + childObjects.add(convertObjectToMap(child, childClass, depth-1)); + } + + if(!childObjects.isEmpty()) + { + object.put(childClass.getSimpleName().toLowerCase()+"s",childObjects); + } + } + } + } + + + +} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java index 593377beed..6a79916d07 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java @@ -16,9 +16,9 @@ */ package org.apache.qpid.server.management.plugin.servlet.rest; +import java.io.BufferedWriter; import java.io.IOException; -import java.io.PrintWriter; -import java.net.SocketAddress; +import java.io.Writer; import java.util.*; import javax.servlet.ServletConfig; import javax.servlet.ServletException; @@ -49,6 +49,8 @@ public class RestServlet extends AbstractServlet private volatile boolean initializationRequired = false; + private final ConfiguredObjectToMapConverter _objectConverter = new ConfiguredObjectToMapConverter(); + public RestServlet() { super(); @@ -133,7 +135,7 @@ public class RestServlet extends AbstractServlet for(int i = 0; i < _hierarchy.length; i++) { - if(i == 0 || Model.getChildTypes(_hierarchy[i - 1]).contains(_hierarchy[i])) + if(i == 0 || Model.getInstance().getChildTypes(_hierarchy[i - 1]).contains(_hierarchy[i])) { for(ConfiguredObject parent : parents) @@ -257,7 +259,7 @@ public class RestServlet extends AbstractServlet ConfiguredObject child) { Collection ancestors = new HashSet(); - Collection> parentTypes = Model.getParentTypes(childType); + Collection> parentTypes = Model.getInstance().getParentTypes(childType); for(Class parentClazz : parentTypes) { @@ -282,119 +284,33 @@ public class RestServlet extends AbstractServlet return ancestors; } - - protected Map convertObjectToMap(final ConfiguredObject confObject, - Class clazz, - int depth) - { - Map object = new LinkedHashMap(); - - for(String name : confObject.getAttributeNames()) - { - Object value = confObject.getAttribute(name); - if(value instanceof ConfiguredObject) - { - object.put(name, ((ConfiguredObject) value).getName()); - } - else if(value != null) - { - object.put(name, value); - } - } - - Statistics statistics = confObject.getStatistics(); - Map statMap = new HashMap(); - for(String name : statistics.getStatisticNames()) - { - Object value = statistics.getStatistic(name); - if(value != null) - { - statMap.put(name, value); - } - } - - if(!statMap.isEmpty()) - { - object.put("statistics", statMap); - } - - if(depth > 0) - { - for(Class childClass : Model.getChildTypes(clazz)) - { - Collection children = confObject.getChildren(childClass); - if(children != null) - { - List> childObjects = new ArrayList>(); - - for(ConfiguredObject child : children) - { - childObjects.add(convertObjectToMap(child, childClass, depth-1)); - } - - if(!childObjects.isEmpty()) - { - object.put(childClass.getSimpleName().toLowerCase()+"s",childObjects); - } - } - } - } - return object; - } - @Override protected void onGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); - response.setHeader("Cache-Control","no-cache"); - response.setHeader("Pragma","no-cache"); - response.setDateHeader ("Expires", 0); + setCachingHeadersOnResponse(response); Collection allObjects = getObjects(request); - @SuppressWarnings("unchecked") - Map params = new HashMap(request.getParameterMap()); - - int depth = 1; - try - { - depth = Integer.parseInt(String.valueOf(params.remove("depth"))); - } - catch (NumberFormatException e) - { - // Ignore - } + // TODO - sort special params, everything else should act as a filter + int depth = getDepthParameterFromRequest(request); List> output = new ArrayList>(); - - // TODO - depth and sort special params, everything else should act as a filter - if(request.getParameter(DEPTH_PARAM)!=null) - { - try - { - depth = Integer.parseInt(request.getParameter(DEPTH_PARAM)); - } - catch (NumberFormatException e) - { - - } - } - for(ConfiguredObject configuredObject : allObjects) { - output.add(convertObjectToMap(configuredObject, getConfiguredClass(),depth)); + output.add(_objectConverter.convertObjectToMap(configuredObject, getConfiguredClass(), + depth)); } - final PrintWriter writer = response.getWriter(); + final Writer writer = new BufferedWriter(response.getWriter()); ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); mapper.writeValue(writer, output); response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); - } private Class getConfiguredClass() @@ -462,7 +378,7 @@ public class RestServlet extends AbstractServlet { for(int j = i-1; j >=0; j--) { - if(Model.getChildTypes(_hierarchy[j]).contains(_hierarchy[i])) + if(Model.getInstance().getChildTypes(_hierarchy[j]).contains(_hierarchy[i])) { for(ConfiguredObject parent : objects[j]) { @@ -482,7 +398,7 @@ public class RestServlet extends AbstractServlet } List parents = new ArrayList(); Class objClass = getConfiguredClass(); - Collection> parentClasses = Model.getParentTypes(objClass); + Collection> parentClasses = Model.getInstance().getParentTypes(objClass); for(int i = _hierarchy.length-2; i >=0 ; i--) { if(parentClasses.contains(_hierarchy[i])) @@ -565,9 +481,7 @@ public class RestServlet extends AbstractServlet response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); - response.setHeader("Cache-Control","no-cache"); - response.setHeader("Pragma","no-cache"); - response.setDateHeader ("Expires", 0); + setCachingHeadersOnResponse(response); try { Collection allObjects = getObjects(request); @@ -583,4 +497,31 @@ public class RestServlet extends AbstractServlet setResponseStatus(response, e); } } + + private void setCachingHeadersOnResponse(HttpServletResponse response) + { + response.setHeader("Cache-Control","no-cache"); + response.setHeader("Pragma","no-cache"); + response.setDateHeader ("Expires", 0); + } + + private int getDepthParameterFromRequest(HttpServletRequest request) + { + int depth = 1; + final String depthString = request.getParameter(DEPTH_PARAM); + if(depthString!=null) + { + try + { + depth = Integer.parseInt(depthString); + } + catch (NumberFormatException e) + { + LOGGER.warn("Could not parse " + depthString + " as integer"); + } + } + return depth; + } + + } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java index e4ba374f89..60f977ca66 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java @@ -73,7 +73,7 @@ public class StructureServlet extends AbstractServlet structure.put("id", object.getId()); structure.put("name", object.getName()); - for(Class childClass : Model.getChildTypes(clazz)) + for(Class childClass : Model.getInstance().getChildTypes(clazz)) { Collection children = object.getChildren(childClass); if(children != null) diff --git a/java/broker-plugins/management-http/src/main/java/resources/showBroker.html b/java/broker-plugins/management-http/src/main/java/resources/showBroker.html index a39e334c40..f8d80faba8 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/showBroker.html +++ b/java/broker-plugins/management-http/src/main/java/resources/showBroker.html @@ -1,3 +1,23 @@ +
Name:
diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java index 37bc2733b0..5e6d9a998a 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java @@ -1,3 +1,23 @@ +/* + * + * 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. + * + */ package org.apache.qpid.server.management.plugin.servlet.rest; import java.util.List; diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java index 527eb16927..1ed0d97185 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java @@ -1,3 +1,23 @@ +/* + * + * 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. + * + */ package org.apache.qpid.server.management.plugin.servlet.rest; import java.net.HttpURLConnection; diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java new file mode 100644 index 0000000000..8e5c5e1c10 --- /dev/null +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java @@ -0,0 +1,141 @@ +/* + * 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. + * + */ +package org.apache.qpid.server.management.plugin.servlet.rest; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.apache.qpid.server.management.plugin.servlet.rest.ConfiguredObjectToMapConverter.STATISTICS_MAP_KEY; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.Statistics; + +public class ConfiguredObjectToMapConverterTest extends TestCase +{ + private ConfiguredObjectToMapConverter _converter = new ConfiguredObjectToMapConverter(); + private ConfiguredObject _configuredObject = mock(ConfiguredObject.class); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + } + + public void testConfiguredObjectWithSingleStatistics() throws Exception + { + final String statisticName = "statisticName"; + final int statisticValue = 10; + + Statistics mockStatistics = createMockStatistics(statisticName, statisticValue); + when(_configuredObject.getStatistics()).thenReturn(mockStatistics); + + Map resultMap = _converter.convertObjectToMap(_configuredObject, ConfiguredObject.class, 0); + Map statsAsMap = (Map) resultMap.get(STATISTICS_MAP_KEY); + assertNotNull("Statistics should be part of map", statsAsMap); + assertEquals("Unexpected number of statistics", 1, statsAsMap.size()); + assertEquals("Unexpected statistic value", statisticValue, statsAsMap.get(statisticName)); + } + + public void testConfiguredObjectWithSingleNonConfiguredObjectAttribute() throws Exception + { + final String attributeName = "attribute"; + final String attributeValue = "value"; + configureMockToReturnOneAttribute(_configuredObject, attributeName, attributeValue); + + Map resultMap = _converter.convertObjectToMap(_configuredObject, ConfiguredObject.class, 0); + assertEquals("Unexpected number of attributes", 1, resultMap.size()); + assertEquals("Unexpected attribute value", attributeValue, resultMap.get(attributeName)); + } + + /* + * For now, it is the name of the configured object is returned as the attribute value, rather than the + * configured object itself + */ + public void testConfiguredObjectWithSingleConfiguredObjectAttribute() throws Exception + { + final String attributeName = "attribute"; + final ConfiguredObject attributeValue = mock(ConfiguredObject.class); + when(attributeValue.getName()).thenReturn("attributeConfiguredObjectName"); + + configureMockToReturnOneAttribute(_configuredObject, attributeName, attributeValue); + + Map resultMap = _converter.convertObjectToMap(_configuredObject, ConfiguredObject.class, 0); + assertEquals("Unexpected number of attributes", 1, resultMap.size()); + assertEquals("Unexpected attribute value", "attributeConfiguredObjectName", resultMap.get(attributeName)); + } + + public void testConfiguredObjectWithChildAndDepth1() + { + final String childAttributeName = "childattribute"; + final String childAttributeValue = "childvalue"; + + Model model = createTestModel(); + _converter.setModel(model); + + TestChild mockChild = mock(TestChild.class); + configureMockToReturnOneAttribute(mockChild, childAttributeName, childAttributeValue); + when(_configuredObject.getChildren(TestChild.class)).thenReturn(Arrays.asList(mockChild)); + + Map resultMap = _converter.convertObjectToMap(_configuredObject, ConfiguredObject.class, 1); + assertEquals("Unexpected parent map size", 1, resultMap.size()); + + final List> childList = (List>) resultMap.get("testchilds"); + assertEquals("Unexpected number of children", 1, childList.size()); + final Map childMap = childList.get(0); + assertEquals("Unexpected child map size", 1, childMap.size()); + assertNotNull(childMap); + + assertEquals("Unexpected child attribute value", childAttributeValue, childMap.get(childAttributeName)); + } + + private Model createTestModel() + { + Model model = mock(Model.class); + final List> list = new ArrayList>(); + list.add(TestChild.class); + when(model.getChildTypes(ConfiguredObject.class)).thenReturn(list); + return model; + } + + private void configureMockToReturnOneAttribute(ConfiguredObject mockConfiguredObject, String attributeName, Object attributeValue) + { + when(mockConfiguredObject.getAttributeNames()).thenReturn(Arrays.asList(attributeName)); + when(mockConfiguredObject.getAttribute(attributeName)).thenReturn(attributeValue); + } + + private Statistics createMockStatistics(String statName, int statValue) + { + Statistics mockStatistics = mock(Statistics.class); + when(mockStatistics.getStatisticNames()).thenReturn(Arrays.asList(statName)); + when(mockStatistics.getStatistic(statName)).thenReturn(statValue); + return mockStatistics; + } + + private static interface TestChild extends ConfiguredObject + { + } +} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java index 59936427f9..4904d2adf3 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java @@ -1,3 +1,23 @@ +/* + * + * 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. + * + */ package org.apache.qpid.server.management.plugin.servlet.rest; import java.net.URLDecoder; diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java index 49f163baae..739ef5c737 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java @@ -1,3 +1,23 @@ +/* + * + * 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. + * + */ package org.apache.qpid.server.management.plugin.servlet.rest; import java.net.URLDecoder; diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java index 943466eda7..b504c9fa60 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java @@ -1,3 +1,23 @@ +/* + * + * 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. + * + */ package org.apache.qpid.server.management.plugin.servlet.rest; import java.util.List; diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java index 378b349a99..e56fa27e21 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java @@ -1,3 +1,23 @@ +/* + * + * 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. + * + */ package org.apache.qpid.server.management.plugin.servlet.rest; import java.net.HttpURLConnection; diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java index 49f06d5121..a2a0d2d093 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.jmx; import org.apache.log4j.Logger; +import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.ManagementActor; import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; @@ -38,6 +39,7 @@ import javax.management.MBeanServer; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectName; +import javax.management.RuntimeErrorException; import javax.management.remote.JMXConnectionNotification; import javax.management.remote.JMXPrincipal; import javax.management.remote.MBeanServerForwarder; @@ -48,6 +50,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.security.AccessControlContext; import java.security.AccessController; +import java.util.Arrays; import java.util.Map; import java.util.Set; @@ -157,77 +160,98 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati // Save the subject SecurityManager.setThreadSubject(subject); - - // Get the component, type and impact, which may be null - String type = getType(method, args); - String vhost = getVirtualHost(method, args); - int impact = getImpact(method, args); - - // Get the security manager for the virtual host (if set) - SecurityManager security; - if (vhost == null) + CurrentActor.set(_logActor); + try { - security = _appRegistry.getSecurityManager(); + return authoriseAndInvoke(method, args); } - else + finally { - security = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager(); + CurrentActor.remove(); } + } + catch (InvocationTargetException e) + { + Throwable targetException = e.getCause(); + logTargetException(method, args, targetException); + throw targetException; + } + } - methodName = getMethodName(method, args); - if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO) - { - // Check for read-only method invocation permission - if (!security.authoriseMethod(Operation.ACCESS, type, methodName)) - { - throw new SecurityException("Permission denied: Access " + methodName); - } - } - else - { - // Check for setting properties permission - if (!security.authoriseMethod(Operation.UPDATE, type, methodName)) - { - throw new SecurityException("Permission denied: Update " + methodName); - } - } + private void logTargetException(Method method, Object[] args, Throwable targetException) + { + Throwable error = null; + if (targetException instanceof RuntimeErrorException) + { + error = ((RuntimeErrorException)targetException).getCause(); + } + else if (targetException instanceof Error) + { + error = targetException; + } + if (error == null) + { + _logger.debug("Exception was thrown on invoking of " + method + " with arguments " + Arrays.toString(args), targetException); + } + else + { + _logger.error("Unexpected error occured on invoking of " + method + " with arguments " + Arrays.toString(args), targetException); + } + } - boolean oldAccessChecksDisabled = false; - if(_managementRightsInferAllAccess) - { - oldAccessChecksDisabled = SecurityManager.setAccessChecksDisabled(true); - } + private Object authoriseAndInvoke(Method method, Object[] args) throws IllegalAccessException, InvocationTargetException + { + String methodName; + // Get the component, type and impact, which may be null + String type = getType(method, args); + String vhost = getVirtualHost(method, args); + int impact = getImpact(method, args); + + // Get the security manager for the virtual host (if set) + SecurityManager security; + if (vhost == null) + { + security = _appRegistry.getSecurityManager(); + } + else + { + security = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager(); + } - try + methodName = getMethodName(method, args); + if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO) + { + // Check for read-only method invocation permission + if (!security.authoriseMethod(Operation.ACCESS, type, methodName)) { - return doInvokeWrappingWithManagementActor(method, args); + throw new SecurityException("Permission denied: Access " + methodName); } - finally + } + else + { + // Check for setting properties permission + if (!security.authoriseMethod(Operation.UPDATE, type, methodName)) { - if(_managementRightsInferAllAccess) - { - SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled); - } + throw new SecurityException("Permission denied: Update " + methodName); } } - catch (InvocationTargetException e) + + boolean oldAccessChecksDisabled = false; + if(_managementRightsInferAllAccess) { - throw e.getTargetException(); + oldAccessChecksDisabled = SecurityManager.setAccessChecksDisabled(true); } - } - private Object doInvokeWrappingWithManagementActor(Method method, - Object[] args) throws IllegalAccessException, - InvocationTargetException - { try { - CurrentActor.set(_logActor); return method.invoke(_mbs, args); } finally { - CurrentActor.remove(); + if(_managementRightsInferAllAccess) + { + SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled); + } } } @@ -368,14 +392,17 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati user = splitConnectionId[1]; } + // use a separate instance of actor as subject is not set on connect/disconnect + // we need to pass principal name explicitly into log actor + LogActor logActor = new ManagementActor(_appRegistry.getRootMessageLogger(), user); if (JMXConnectionNotification.OPENED.equals(type)) { - _logActor.message(ManagementConsoleMessages.OPEN(user)); + logActor.message(ManagementConsoleMessages.OPEN(user)); } else if (JMXConnectionNotification.CLOSED.equals(type) || JMXConnectionNotification.FAILED.equals(type)) { - _logActor.message(ManagementConsoleMessages.CLOSE(user)); + logActor.message(ManagementConsoleMessages.CLOSE(user)); } } } diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java new file mode 100644 index 0000000000..c1df9afc5d --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java @@ -0,0 +1,170 @@ +/* + * + * 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. + * + */ +package org.apache.qpid.server.jmx; + +import java.util.HashMap; +import java.util.Map; + +import javax.management.JMException; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.XMLConfiguration; +import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.security.Result; +import org.apache.qpid.server.security.SecurityPlugin; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.util.TestApplicationRegistry; +import org.apache.qpid.test.utils.QpidTestCase; + +public class ManagementLogActorTest extends QpidTestCase +{ + private ApplicationRegistry _registry; + private JMXManagedObjectRegistry _objectRegistry; + private int _registryPort; + private int _connectorPort; + private TestPlugin _plugin; + + @Override + public void setUp() throws Exception + { + super.setUp(); + + _registryPort = findFreePort(); + _connectorPort = getNextAvailable(_registryPort + 1); + XMLConfiguration config = new XMLConfiguration(); + config.addProperty(ServerConfiguration.MGMT_JMXPORT_REGISTRYSERVER, _registryPort + ""); + config.addProperty(ServerConfiguration.MGMT_JMXPORT_CONNECTORSERVER, _connectorPort + ""); + _registry = new TestApplicationRegistry(new ServerConfiguration(config)); + ApplicationRegistry.initialise(_registry); + + _plugin = new TestPlugin(); + _registry.getSecurityManager().addHostPlugin(_plugin); + + _objectRegistry = new JMXManagedObjectRegistry(); + new TestMBean(_objectRegistry); + _objectRegistry.start(); + } + + public void tearDown() throws Exception + { + _objectRegistry.close(); + ApplicationRegistry.remove(); + super.tearDown(); + } + + public void testPrincipalInLogMessage() throws Throwable + { + Map environment = new HashMap(); + environment.put(JMXConnector.CREDENTIALS, new String[] { "admin", "admin" }); + String urlString = "service:jmx:rmi:///jndi/rmi://localhost:" + _registryPort + "/jmxrmi"; + JMXServiceURL url = new JMXServiceURL(urlString); + JMXConnector jmxConnector = JMXConnectorFactory.connect(url, environment); + MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); + ObjectName mbeanObject = new ObjectName("org.apache.qpid:type=TestMBean,name=test"); + + String actorLogMessage = (String) mbsc.getAttribute(mbeanObject, "ActorLogMessage"); + + assertTrue("Unexpected log principal in security plugin", _plugin.getLogMessage().startsWith("[mng:admin")); + assertTrue("Unexpected log principal in MBean", actorLogMessage.startsWith("[mng:admin")); + } + + public static class TestMBean extends DefaultManagedObject implements CurrentActorRetriever + { + + public TestMBean(ManagedObjectRegistry registry) throws JMException + { + super(CurrentActorRetriever.class, "TestMBean", registry); + register(); + } + + @Override + public String getObjectInstanceName() + { + return "test"; + } + + @Override + public ManagedObject getParentObject() + { + return null; + } + + @Override + public String getActorLogMessage() + { + return CurrentActor.get().getLogMessage(); + } + + } + + public static interface CurrentActorRetriever + { + String getActorLogMessage(); + } + + public static class TestPlugin implements SecurityPlugin + { + private String _logMessage; + + @Override + public void configure(ConfigurationPlugin config) throws ConfigurationException + { + } + + @Override + public Result getDefault() + { + return Result.ALLOWED; + } + + @Override + public Result access(ObjectType objectType, Object instance) + { + return Result.ALLOWED; + } + + @Override + public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) + { + // set thread name to work around logic in MangementActor + Thread.currentThread().setName("RMI TCP Connection(1)-" + System.currentTimeMillis()); + _logMessage = CurrentActor.get().getLogMessage(); + return Result.ALLOWED; + } + + public String getLogMessage() + { + return _logMessage; + } + + } + +} diff --git a/java/broker/etc/broker_example.acl b/java/broker/etc/broker_example.acl index 1f32f8463e..45a48bda09 100644 --- a/java/broker/etc/broker_example.acl +++ b/java/broker/etc/broker_example.acl @@ -18,6 +18,7 @@ # ### EXAMPLE ACL V2 FILE +### NOTE: Rules are considered from top to bottom, and the first matching rule governs the decision. ### DEFINE GROUPS ### @@ -27,30 +28,30 @@ GROUP messaging-users client server #Define a group for management web console users GROUP webadmins webadmin -### MANAGEMENT #### +### JMX MANAGEMENT #### # Allow everyone to perform read operations on the ServerInformation mbean # This is used for items such as querying the management API and broker release versions. -ACL ALLOW-LOG ALL ACCESS METHOD component="ServerInformation" +ACL ALLOW ALL ACCESS METHOD component="ServerInformation" -# Allow 'admin' all management operations +# Allow 'admin' all management operations. To reduce log file noise, only non-read-only operations are logged. +ACL ALLOW admin ACCESS METHOD ACL ALLOW-LOG admin ALL METHOD +# Allow 'guest' to view logger levels, and use getter methods on LoggingManagement +ACL ALLOW guest ACCESS METHOD component="LoggingManagement" name="viewEffectiveRuntimeLoggerLevels" +ACL ALLOW guest ACCESS METHOD component="LoggingManagement" name="get*" + # Deny access to Shutdown, UserManagement, ConfigurationManagement and LoggingManagement for all other users -# You could grant specific users access to these beans by adding ALLOW-LOG rules above for them +# You could grant specific users access to these beans by adding rules above to allow them ACL DENY-LOG ALL ACCESS METHOD component="Shutdown" ACL DENY-LOG ALL ACCESS METHOD component="UserManagement" ACL DENY-LOG ALL ACCESS METHOD component="ConfigurationManagement" ACL DENY-LOG ALL ACCESS METHOD component="LoggingManagement" -# Allow 'guest' to view logger levels, and use getter methods on LoggingManagement -# These are examples of redundant rules! The DENY-LOG rule above will be invoked -# first and will deny the access to all methods of LoggingManagement for guest -ACL ALLOW-LOG guest ACCESS METHOD component="LoggingManagement" name="viewEffectiveRuntimeLoggerLevels" -ACL ALLOW-LOG guest ACCESS METHOD component="LoggingManagement" name="get*" - -# Allow everyone to perform all read operations on the mbeans not listened in the DENY-LOG rules above -ACL ALLOW-LOG ALL ACCESS METHOD +# Allow everyone to perform all read operations (using ALLOW rather than ALLOW-LOG to reduce log file noise) +# on the mbeans not listed in the DENY rules above +ACL ALLOW ALL ACCESS METHOD ### MESSAGING ### diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java index 9cd3c66629..a2f3506502 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java @@ -30,16 +30,7 @@ import java.text.MessageFormat; import java.util.Set; /** - * NOTE: This actor is not thread safe. - * - * Sharing of a ManagementActor instance between threads may result in an - * incorrect actor value being logged. - * - * This is due to the fact that calls to message will dynamically query the - * thread name and use that to set the log format during each message() call. - * - * This is currently not an issue as each MBean operation creates a new Actor - * that is unique for each operation. + * Management actor to use in {@link MBeanInvocationHandlerImpl} to log all management operational logging. */ public class ManagementActor extends AbstractActor { @@ -66,38 +57,45 @@ public class ManagementActor extends AbstractActor /** * The logString to be used for logging */ - private String _logString; + private String _logStringContainingPrincipal; + + /** used when the principal name cannot be discovered from the Subject */ + private final String _fallbackPrincipalName; /** @param rootLogger The RootLogger to use for this Actor */ public ManagementActor(RootMessageLogger rootLogger) { super(rootLogger); + _fallbackPrincipalName = UNKNOWN_PRINCIPAL; + } + + public ManagementActor(RootMessageLogger rootLogger, String principalName) + { + super(rootLogger); + _fallbackPrincipalName = principalName; } - private void updateLogString() + private synchronized String getAndCacheLogString() { String currentName = Thread.currentThread().getName(); String actor; + String logString = _logStringContainingPrincipal; + // Record the last thread name so we don't have to recreate the log string - if (!currentName.equals(_lastThreadName)) + if (_logStringContainingPrincipal == null || !currentName.equals(_lastThreadName)) { _lastThreadName = currentName; + String principalName = getPrincipalName(); // Management Thread names have this format. // RMI TCP Connection(2)-169.24.29.116 // This is true for both LocalAPI and JMX Connections // However to be defensive lets test. - String[] split = currentName.split("\\("); if (split.length == 2) { String ip = currentName.split("-")[1]; - String principalName = getPrincipalName(); - if (principalName == null) - { - principalName = UNKNOWN_PRINCIPAL; - } actor = MessageFormat.format(MANAGEMENT_FORMAT, principalName, ip); } else @@ -111,9 +109,14 @@ public class ManagementActor extends AbstractActor actor = currentName; } - _logString = "[" + actor + "] "; + logString = "[" + actor + "] "; + if(principalName != UNKNOWN_PRINCIPAL ) + { + _logStringContainingPrincipal = logString; + } } + return logString; } /** @@ -121,9 +124,9 @@ public class ManagementActor extends AbstractActor * * @return principal name or null if principal can not be found */ - protected String getPrincipalName() + private String getPrincipalName() { - String identity = null; + String identity = _fallbackPrincipalName; // retrieve Subject from current AccessControlContext final Subject subject = Subject.getSubject(AccessController.getContext()); @@ -142,8 +145,7 @@ public class ManagementActor extends AbstractActor public String getLogMessage() { - updateLogString(); - return _logString; + return getAndCacheLogString(); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/java/broker/src/main/java/org/apache/qpid/server/model/Model.java index fd429321c8..36179fc105 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Model.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Model.java @@ -29,33 +29,20 @@ import java.util.Map; public class Model { - private static final Map, Collection>> - PARENTS = new HashMap, Collection>>(); + private static final Model MODEL_INSTANCE = new Model(); + private final Map, Collection>> + _parents = new HashMap, Collection>>(); - private static final Map, Collection>> - CHILDREN = new HashMap, Collection>>(); + private final Map, Collection>> + _children = new HashMap, Collection>>(); - static void addRelationship(Class parent, Class child) + public static Model getInstance() { - Collection> parents = PARENTS.get(child); - if(parents == null) - { - parents = new ArrayList>(); - PARENTS.put(child, parents); - } - parents.add(parent); - - Collection> children = CHILDREN.get(parent); - if(children == null) - { - children = new ArrayList>(); - CHILDREN.put(parent, children); - } - children.add(child); + return MODEL_INSTANCE; } - static + private Model() { addRelationship(Broker.class, VirtualHost.class); addRelationship(Broker.class, Port.class); @@ -78,20 +65,39 @@ public class Model addRelationship(Session.class, Consumer.class); addRelationship(Session.class, Publisher.class); - } - public static Collection> getParentTypes(Class child) + public Collection> getParentTypes(Class child) { - Collection> parentTypes = PARENTS.get(child); - return parentTypes == null ? Collections.EMPTY_LIST + Collection> parentTypes = _parents.get(child); + return parentTypes == null ? Collections.>emptyList() : Collections.unmodifiableCollection(parentTypes); } - public static Collection> getChildTypes(Class parent) + public Collection> getChildTypes(Class parent) { - Collection> childTypes = CHILDREN.get(parent); - return childTypes == null ? Collections.EMPTY_LIST + Collection> childTypes = _children.get(parent); + return childTypes == null ? Collections.>emptyList() : Collections.unmodifiableCollection(childTypes); } + + private void addRelationship(Class parent, Class child) + { + Collection> parents = _parents.get(child); + if(parents == null) + { + parents = new ArrayList>(); + _parents.put(child, parents); + } + parents.add(parent); + + Collection> children = _children.get(parent); + if(children == null) + { + children = new ArrayList>(); + _children.put(parent, children); + } + children.add(child); + } + } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java index b431047d66..cb866245f0 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java @@ -26,15 +26,6 @@ import java.security.PrivilegedAction; import java.util.Collections; import java.util.List; -/** - * Test : AMQPManagementActorTest - * Validate the AMQPManagementActor class. - * - * The test creates a new AMQPActor and then logs a message using it. - * - * The test then verifies that the logged message was the only one created and - * that the message contains the required message. - */ public class ManagementActorTest extends BaseActorTestCase { @@ -131,4 +122,67 @@ public class ManagementActorTest extends BaseActorTestCase assertTrue("Message contains the [mng: prefix", logMessage.contains("[mng:guest(" + IP + ")")); } + public void testGetLogMessageWithSubject() + { + assertLogMessageInRMIThreadWithPrincipal("RMI TCP Connection(" + CONNECTION_ID + ")-" + IP, "my_principal"); + } + + public void testGetLogMessageWithoutSubjectButWithActorPrincipal() + { + String principalName = "my_principal"; + _amqpActor = new ManagementActor(_rootLogger, principalName); + String message = _amqpActor.getLogMessage(); + assertEquals("Unexpected log message", "[mng:" + principalName + "(" + IP + ")] ", message); + } + + /** It's necessary to test successive calls because ManagementActor caches its log message based on thread and principal name */ + public void testGetLogMessageCaching() + { + String originalThreadName = "RMI TCP Connection(1)-" + IP; + assertLogMessageInRMIThreadWithoutPrincipal(originalThreadName); + assertLogMessageInRMIThreadWithPrincipal(originalThreadName, "my_principal"); + assertLogMessageInRMIThreadWithPrincipal("RMI TCP Connection(2)-" + IP, "my_principal"); + } + + public void testGetLogMessageAfterRemovingSubject() + { + assertLogMessageInRMIThreadWithPrincipal("RMI TCP Connection(1)-" + IP, "my_principal"); + + Thread.currentThread().setName("RMI TCP Connection(2)-" + IP ); + String message = _amqpActor.getLogMessage(); + assertEquals("Unexpected log message", "[mng:N/A(" + IP + ")] ", message); + + assertLogMessageWithoutPrincipal("TEST"); + } + + private void assertLogMessageInRMIThreadWithoutPrincipal(String threadName) + { + Thread.currentThread().setName(threadName ); + String message = _amqpActor.getLogMessage(); + assertEquals("Unexpected log message", "[mng:N/A(" + IP + ")] ", message); + } + + private void assertLogMessageWithoutPrincipal(String threadName) + { + Thread.currentThread().setName(threadName ); + String message = _amqpActor.getLogMessage(); + assertEquals("Unexpected log message", "[" + threadName +"] ", message); + } + + private void assertLogMessageInRMIThreadWithPrincipal(String threadName, String principalName) + { + Thread.currentThread().setName(threadName); + Subject subject = new Subject(true, Collections.singleton(new JMXPrincipal(principalName)), Collections.EMPTY_SET, + Collections.EMPTY_SET); + + final String message = Subject.doAs(subject, new PrivilegedAction() + { + public String run() + { + return _amqpActor.getLogMessage(); + } + }); + + assertEquals("Unexpected log message", "[mng:" + principalName + "(" + IP + ")] ", message); + } } diff --git a/java/build.deps b/java/build.deps index 52ae277ce4..4742ec1a8c 100644 --- a/java/build.deps +++ b/java/build.deps @@ -106,7 +106,7 @@ jca.libs=${geronimo-j2ee} ${geronimo-jta} ${geronimo-jms} ${test.libs} ${geronim jca.test.libs=${test.libs} # optional bdbstore module deps -bdb-je=lib/bdbstore/je-5.0.55.jar +bdb-je=lib/bdbstore/je-5.0.58.jar bdbstore.libs=${bdb-je} bdbstore.test.libs=${test.libs} diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java index 987404cb80..89273599b9 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java @@ -245,13 +245,13 @@ public class AMQBrokerDetails implements BrokerDetails _options.put(key, value); } - public long getTimeout() + private int lookupConnectTimeout() { if (_options.containsKey(OPTIONS_CONNECT_TIMEOUT)) { try { - return Long.parseLong(_options.get(OPTIONS_CONNECT_TIMEOUT)); + return Integer.parseInt(_options.get(OPTIONS_CONNECT_TIMEOUT)); } catch (NumberFormatException nfe) { @@ -290,11 +290,6 @@ public class AMQBrokerDetails implements BrokerDetails } } - public void setTimeout(long timeout) - { - setProperty(OPTIONS_CONNECT_TIMEOUT, Long.toString(timeout)); - } - public String toString() { StringBuffer sb = new StringBuffer(); @@ -460,6 +455,8 @@ public class AMQBrokerDetails implements BrokerDetails getBooleanProperty(BrokerDetails.OPTIONS_TCP_NO_DELAY,true)); } + conSettings.setConnectTimeout(lookupConnectTimeout()); + return conSettings; } } diff --git a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java index 71d7ffd2a3..4a7fca1efa 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java +++ b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java @@ -59,7 +59,7 @@ public interface BrokerDetails public static final String URL_FORMAT_EXAMPLE = "://[:][?