summaryrefslogtreecommitdiff
path: root/qpid/java
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/java')
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java3
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java58
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js4
-rw-r--r--qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java14
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/IntegrityViolationException.java37
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java46
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java11
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java80
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java12
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java29
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java83
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java186
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java151
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/util/ParameterizedTypeImpl.java73
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java216
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java114
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java15
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java112
-rwxr-xr-xqpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java21
24 files changed, 1054 insertions, 225 deletions
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
index c2ac675e20..8fa9a59038 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.management.plugin;
import java.io.File;
+import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -120,7 +121,7 @@ public class HttpManagement extends AbstractPluginAdapter
}});
@SuppressWarnings("serial")
- private static final Map<String, Class<?>> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Class<?>>(){{
+ private static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{
put(HTTP_BASIC_AUTHENTICATION_ENABLED, Boolean.class);
put(HTTPS_BASIC_AUTHENTICATION_ENABLED, Boolean.class);
put(HTTP_SASL_AUTHENTICATION_ENABLED, Boolean.class);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
index 3fab26cde5..8b74eb1dce 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
@@ -348,16 +348,7 @@ public class RestServlet extends AbstractServlet
Collection<ConfiguredObject>[] objects = new Collection[_hierarchy.length];
if(_hierarchy.length == 1)
{
- try
- {
- getBroker().createChild(_hierarchy[0], providedObject);
- }
- catch (RuntimeException e)
- {
- setResponseStatus(response, e);
- return;
- }
-
+ createOrUpdate(providedObject, _hierarchy[0], getBroker(), null, response);
}
else
{
@@ -419,40 +410,39 @@ public class RestServlet extends AbstractServlet
ConfiguredObject theParent = parents.remove(0);
ConfiguredObject[] otherParents = parents.toArray(new ConfiguredObject[parents.size()]);
- try
- {
+ createOrUpdate(providedObject, objClass, theParent, otherParents, response);
+ }
+ }
- Collection<? extends ConfiguredObject> existingChildren = theParent.getChildren(objClass);
- for(ConfiguredObject obj: existingChildren)
+ private void createOrUpdate(Map<String, Object> providedObject, Class<? extends ConfiguredObject> objClass,
+ ConfiguredObject theParent, ConfiguredObject[] otherParents, HttpServletResponse response) throws IOException
+ {
+ try
+ {
+ Collection<? extends ConfiguredObject> existingChildren = theParent.getChildren(objClass);
+ for(ConfiguredObject obj: existingChildren)
+ {
+ if((providedObject.containsKey("id") && String.valueOf(providedObject.get("id")).equals(obj.getId().toString()))
+ || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents)))
{
- if((providedObject.containsKey("id") && String.valueOf(providedObject.get("id")).equals(obj.getId().toString()))
- || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents)))
- {
- doUpdate(obj, providedObject);
- response.setStatus(HttpServletResponse.SC_OK);
- return;
- }
+ doUpdate(obj, providedObject);
+ response.setStatus(HttpServletResponse.SC_OK);
+ return;
}
-
- theParent.createChild(objClass, providedObject, otherParents);
- }
- catch (RuntimeException e)
- {
- setResponseStatus(response, e);
- return;
}
+ theParent.createChild(objClass, providedObject, otherParents);
+ response.setStatus(HttpServletResponse.SC_CREATED);
+ }
+ catch (RuntimeException e)
+ {
+ setResponseStatus(response, e);
}
- response.setStatus(HttpServletResponse.SC_CREATED);
}
private void doUpdate(ConfiguredObject obj, Map<String, Object> providedObject)
{
- for(Map.Entry<String,Object> entry : providedObject.entrySet())
- {
- obj.setAttribute(entry.getKey(), obj.getAttribute(entry.getKey()), entry.getValue());
- }
- //TODO - Implement.
+ obj.setAttributes(providedObject);
}
private boolean equalParents(ConfiguredObject obj, ConfiguredObject[] otherParents)
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
index 7613fd5d71..4273ed5b41 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js
@@ -72,6 +72,7 @@ define(["dojo/_base/xhr",
{
this.controller = controller;
this.name = query(".name", node)[0];
+ this.type = query(".type", node)[0];
/*this.state = dom.byId("state");
this.durable = dom.byId("durable");
this.lifetimePolicy = dom.byId("lifetimePolicy");
@@ -89,7 +90,7 @@ define(["dojo/_base/xhr",
that.updateHeader();
- require(["qpid/management/authenticationprovider/"+that.authProviderData.type],
+ require(["qpid/management/authenticationprovider/"+that.authProviderData.category],
function(SpecificProvider) {
that.details = new SpecificProvider(node, authProviderObj, controller);
that.details.update();
@@ -102,6 +103,7 @@ define(["dojo/_base/xhr",
AuthProviderUpdater.prototype.updateHeader = function()
{
this.name.innerHTML = this.authProviderData[ "name" ];
+ this.type.innerHTML = this.authProviderData[ "authenticationProviderType" ];
/* this.state.innerHTML = this.brokerData[ "state" ];
this.durable.innerHTML = this.brokerData[ "durable" ];
this.lifetimePolicy.innerHTML = this.brokerData[ "lifetimePolicy" ];
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 8f087ba50c..f53b369221 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
@@ -22,6 +22,7 @@
package org.apache.qpid.server.jmx;
import java.io.IOException;
+import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -82,7 +83,7 @@ public class JMXManagement extends AbstractPluginAdapter implements Configuratio
}};
@SuppressWarnings("serial")
- private static final Map<String, Class<?>> ATTRIBUTE_TYPES = new HashMap<String, Class<?>>(){{
+ private static final Map<String, Type> ATTRIBUTE_TYPES = new HashMap<String, Type>(){{
put(USE_PLATFORM_MBEAN_SERVER, Boolean.class);
put(NAME, String.class);
put(PluginFactory.PLUGIN_TYPE, String.class);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java
index 813702d0a6..3022898300 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java
@@ -29,10 +29,12 @@ import java.util.UUID;
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
+import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.VirtualHost;
@@ -123,6 +125,18 @@ public class StoreConfigurationChangeListener implements ConfigurationChangeList
{
return Broker.class;
}
+ else if (object instanceof VirtualHost)
+ {
+ return VirtualHost.class;
+ }
+ else if (object instanceof Port)
+ {
+ return Port.class;
+ }
+ else if (object instanceof AuthenticationProvider)
+ {
+ return AuthenticationProvider.class;
+ }
return getConfiguredObjectTypeFromImplementedInterfaces(object.getClass());
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
index 417f6036ab..c7d3aa76af 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
@@ -39,7 +39,8 @@ public interface AuthenticationProvider extends ConfiguredObject
public static final String TIME_TO_LIVE = "timeToLive";
public static final String CREATED = "created";
public static final String UPDATED = "updated";
- public static final String TYPE = "type";
+ public static final String CATEGORY = "category";
+ public static final String TYPE = "authenticationProviderType";
public static final Collection<String> AVAILABLE_ATTRIBUTES =
Collections.unmodifiableList(
@@ -52,6 +53,7 @@ public interface AuthenticationProvider extends ConfiguredObject
TIME_TO_LIVE,
CREATED,
UPDATED,
+ CATEGORY,
TYPE));
//children
Collection<VirtualHostAlias> getVirtualHostPortBindings();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
index bd7da962ba..d20c709e90 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java
@@ -30,8 +30,7 @@ public interface ConfigurationChangeListener
* @param newState the state after the change
*/
void stateChanged(ConfiguredObject object, State oldState, State newState);
-
-
+
void childAdded(ConfiguredObject object, ConfiguredObject child);
void childRemoved(ConfiguredObject object, ConfiguredObject child);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
index d567a3aa44..45e743dbca 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
@@ -257,4 +257,6 @@ public interface ConfiguredObject
<C extends ConfiguredObject> C createChild(Class<C> childClass,
Map<String, Object> attributes,
ConfiguredObject... otherParents);
+
+ void setAttributes(Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/IntegrityViolationException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/IntegrityViolationException.java
new file mode 100644
index 0000000000..def450640a
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/IntegrityViolationException.java
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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.model;
+
+public class IntegrityViolationException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public IntegrityViolationException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public IntegrityViolationException(String message)
+ {
+ super(message);
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
index 73e1f1e970..6b6cce3ffa 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java
@@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.Callable;
import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
@@ -55,14 +56,7 @@ abstract class AbstractAdapter implements ConfiguredObject
_id = id;
if (attributes != null)
{
- Collection<String> names = getAttributeNames();
- for (String name : names)
- {
- if (attributes.containsKey(name))
- {
- _attributes.put(name, attributes.get(name));
- }
- }
+ _attributes.putAll(attributes);
}
if (defaults != null)
{
@@ -319,4 +313,40 @@ abstract class AbstractAdapter implements ConfiguredObject
return _taskExecutor;
}
+ @Override
+ public void setAttributes(final Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ if (getTaskExecutor().isTaskExecutorThread())
+ {
+ changeAttributes(attributes);
+ }
+ else
+ {
+ getTaskExecutor().submitAndWait(new Callable<Void>()
+ {
+
+ @Override
+ public Void call() throws Exception
+ {
+ AbstractAdapter.this.setAttributes(attributes);
+ return null;
+ }
+ });
+ }
+
+ }
+
+ protected void changeAttributes(final Map<String, Object> attributes)
+ {
+ for (Map.Entry<String, Object> attributeEntry : attributes.entrySet())
+ {
+ String name = attributeEntry.getKey();
+ Object desired = attributeEntry.getValue();
+ Object expected = getAttribute(name);
+ if (changeAttribute(name, expected, desired))
+ {
+ attributeSet(name, expected, desired);
+ }
+ }
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java
index 2f7e89bb2b..8ade1369ac 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java
@@ -45,6 +45,7 @@ import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.protocol.AmqpProtocolVersion;
import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
+import org.apache.qpid.server.util.MapValueConverter;
import org.apache.qpid.ssl.SSLContextFactory;
import org.apache.qpid.transport.NetworkTransportConfiguration;
import org.apache.qpid.transport.network.IncomingNetworkTransport;
@@ -189,6 +190,16 @@ public class AmqpPortAdapter extends PortAdapter
return null;
}
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ if (_transport != null)
+ {
+ throw new IllegalStateException("Port " + getAttribute(PORT)
+ + " is already opened. Start broker in management mode to change a port");
+ }
+ super.changeAttributes(MapValueConverter.convert(attributes, ATTRIBUTE_TYPES));
+ }
class ServerNetworkTransportConfiguration implements NetworkTransportConfiguration
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
index ac4b0255d5..afab8a4900 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java
@@ -38,13 +38,18 @@ import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.IllegalStateTransitionException;
+import org.apache.qpid.server.model.IntegrityViolationException;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider;
+import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.Statistics;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.model.User;
import org.apache.qpid.server.model.VirtualHostAlias;
+import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.security.SubjectCreator;
import org.apache.qpid.server.security.access.Operation;
@@ -59,19 +64,19 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana
{
private static final Logger LOGGER = Logger.getLogger(AuthenticationProviderAdapter.class);
- private final T _authManager;
+ protected T _authManager;
protected final Broker _broker;
private GroupPrincipalAccessor _groupAccessor;
- private Object _type;
+ protected String _category;
private AuthenticationProviderAdapter(UUID id, Broker broker, final T authManager, Map<String, Object> attributes)
{
super(id, null, attributes, broker.getTaskExecutor());
_authManager = authManager;
_broker = broker;
- _type = authManager instanceof PrincipalDatabaseAuthenticationManager? PrincipalDatabaseAuthenticationManager.class.getSimpleName() : AuthenticationManager.class.getSimpleName() ;
+ _category = authManager instanceof PrincipalDatabaseAuthenticationManager? PrincipalDatabaseAuthenticationManager.class.getSimpleName() : AuthenticationManager.class.getSimpleName() ;
addParent(Broker.class, broker);
}
@@ -157,9 +162,9 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana
@Override
public Object getAttribute(String name)
{
- if(TYPE.equals(name))
+ if(CATEGORY.equals(name))
{
- return _type;
+ return _category;
}
else if(CREATED.equals(name))
{
@@ -204,6 +209,22 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana
{
if(desiredState == State.DELETED)
{
+ String providerName = getName();
+
+ // verify that provider is not in use
+ if (providerName.equals(_broker.getAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER)))
+ {
+ throw new IntegrityViolationException("Authentication provider '" + providerName + "' is set as default and cannot be deleted");
+ }
+ Collection<Port> ports = new ArrayList<Port>(_broker.getPorts());
+ for (Port port : ports)
+ {
+ if (providerName.equals(port.getAttribute(Port.AUTHENTICATION_MANAGER)))
+ {
+ throw new IntegrityViolationException("Authentication provider '" + providerName + "' is set on port " + port.getName());
+ }
+ }
+
return true;
}
else if(desiredState == State.ACTIVE)
@@ -234,6 +255,21 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana
_groupAccessor = groupAccessor;
}
+ public AuthenticationManager createAuthenticationManager(Map<String, Object> attributes)
+ {
+ QpidServiceLoader<AuthenticationManagerFactory> loader = new QpidServiceLoader<AuthenticationManagerFactory>();
+ Iterable<AuthenticationManagerFactory> factories = loader.atLeastOneInstanceOf(AuthenticationManagerFactory.class);
+ for (AuthenticationManagerFactory factory : factories)
+ {
+ AuthenticationManager manager = factory.createInstance(attributes);
+ if (manager != null)
+ {
+ return manager;
+ }
+ }
+ return null;
+ }
+
public static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter<AuthenticationManager>
{
@@ -250,6 +286,23 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana
{
throw new UnsupportedOperationException();
}
+
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ AuthenticationManager manager = createAuthenticationManager(attributes);
+ if (manager == null)
+ {
+ throw new IllegalConfigurationException("Cannot create authentication manager from " + attributes);
+ }
+ if (manager instanceof PrincipalDatabaseAuthenticationManager)
+ {
+ throw new IllegalConfigurationException("Cannot change the category of the authentication provider");
+ }
+ _authManager = manager;
+ super.changeAttributes(attributes);
+ }
+
}
public static class PrincipalDatabaseAuthenticationManagerAdapter
@@ -377,11 +430,26 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana
}
}
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ AuthenticationManager manager = createAuthenticationManager(attributes);
+ if (manager == null)
+ {
+ throw new IllegalConfigurationException("Cannot create authentication manager from " + attributes);
+ }
+ if (!(manager instanceof PrincipalDatabaseAuthenticationManager))
+ {
+ throw new IllegalConfigurationException("Cannot change the category of the authentication provider");
+ }
+ _authManager = (PrincipalDatabaseAuthenticationManager)manager;
+ super.changeAttributes(attributes);
+ }
+
private class PrincipalAdapter extends AbstractAdapter implements User
{
private final Principal _user;
-
public PrincipalAdapter(Principal user, TaskExecutor taskExecutor)
{
super(UUIDGenerator.generateUserUUID(PrincipalDatabaseAuthenticationManagerAdapter.this.getName(), user.getName()), taskExecutor);
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 533ecfe937..197f70a884 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
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.model.adapter;
+import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.AccessControlException;
@@ -69,7 +70,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
private static final Logger LOGGER = Logger.getLogger(BrokerAdapter.class);
@SuppressWarnings("serial")
- public static final Map<String, Class<?>> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Class<?>>(){{
+ public static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{
put(ALERT_THRESHOLD_MESSAGE_AGE, Long.class);
put(ALERT_THRESHOLD_MESSAGE_COUNT, Long.class);
put(ALERT_THRESHOLD_QUEUE_DEPTH, Long.class);
@@ -312,7 +313,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
synchronized (_vhostAdapters)
{
- _vhostAdapters.remove(vhost);
+ _vhostAdapters.remove(vhost.getName());
}
vhost.removeChangeListener(this);
return true;
@@ -410,7 +411,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
return Collections.emptySet();
}
- //TODO: ACL
@SuppressWarnings("unchecked")
@Override
public <C extends ConfiguredObject> C addChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
@@ -916,4 +916,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat
{
return super.getTaskExecutor();
}
+
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ super.changeAttributes(MapValueConverter.convert(attributes, ATTRIBUTE_TYPES));
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
index c4a531c923..298ff05dd1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java
@@ -21,12 +21,15 @@
package org.apache.qpid.server.model.adapter;
+import java.lang.reflect.Type;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import org.apache.qpid.server.model.AuthenticationProvider;
@@ -41,10 +44,27 @@ import org.apache.qpid.server.model.Statistics;
import org.apache.qpid.server.model.Transport;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.VirtualHostAlias;
+import org.apache.qpid.server.util.MapValueConverter;
+import org.apache.qpid.server.util.ParameterizedTypeImpl;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
public class PortAdapter extends AbstractAdapter implements Port
{
+ @SuppressWarnings("serial")
+ public static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{
+ put(NAME, String.class);
+ put(PROTOCOLS, new ParameterizedTypeImpl(Set.class, Protocol.class));
+ put(TRANSPORTS, new ParameterizedTypeImpl(Set.class, Transport.class));
+ put(PORT, Integer.class);
+ put(TCP_NO_DELAY, Boolean.class);
+ put(RECEIVE_BUFFER_SIZE, Integer.class);
+ put(SEND_BUFFER_SIZE, Integer.class);
+ put(NEED_CLIENT_AUTH, Boolean.class);
+ put(WANT_CLIENT_AUTH, Boolean.class);
+ put(BINDING_ADDRESS, String.class);
+ put(STATE, State.class);
+ put(AUTHENTICATION_MANAGER, String.class);
+ }});
private final Broker _broker;
private AuthenticationProvider _authenticationProvider;
@@ -56,11 +76,9 @@ public class PortAdapter extends AbstractAdapter implements Port
*/
public PortAdapter(UUID id, Broker broker, Map<String, Object> attributes, Map<String, Object> defaults, TaskExecutor taskExecutor)
{
- super(id, defaults, attributes, taskExecutor);
+ super(id, defaults, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor);
_broker = broker;
-
addParent(Broker.class, broker);
-
}
@Override
@@ -308,4 +326,9 @@ public class PortAdapter extends AbstractAdapter implements Port
_authenticationProvider = authenticationProvider;
}
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ super.changeAttributes(MapValueConverter.convert(attributes, ATTRIBUTE_TYPES));
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
index b7441b9f3b..9d501115b7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java
@@ -35,7 +35,6 @@ import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.Protocol.ProtocolType;
-import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.Transport;
import org.apache.qpid.server.util.MapValueConverter;
@@ -78,10 +77,8 @@ public class PortFactory
_defaultProtocols = Collections.unmodifiableCollection(defaultProtocols);
}
- public Port createPort(UUID id, Broker broker, Map<String, Object> objectAttributes)
+ public Port createPort(UUID id, Broker broker, Map<String, Object> attributes)
{
- Map<String, Object> attributes = retrieveAttributes(objectAttributes);
-
final Port port;
Map<String, Object> defaults = new HashMap<String, Object>();
defaults.put(Port.TRANSPORTS, Collections.singleton(DEFAULT_TRANSPORT));
@@ -90,7 +87,8 @@ public class PortFactory
{
throw new IllegalConfigurationException("Port attribute is not specified for port: " + attributes);
}
- if (isAmqpProtocol(attributes))
+ Set<Protocol> protocols = MapValueConverter.getEnumSetAttribute(Port.PROTOCOLS, attributes, Protocol.class);
+ if (isAmqpProtocol(protocols, attributes))
{
Object binding = attributes.get(Port.BINDING_ADDRESS);
if (binding == null)
@@ -109,8 +107,6 @@ public class PortFactory
}
else
{
- @SuppressWarnings("unchecked")
- Collection<Protocol> protocols = (Collection<Protocol>)attributes.get(Port.PROTOCOLS);
if (protocols.size() > 1)
{
throw new IllegalConfigurationException("Only one protocol can be used on non AMQP port");
@@ -122,77 +118,8 @@ public class PortFactory
return port;
}
- private Map<String, Object> retrieveAttributes(Map<String, Object> objectAttributes)
- {
- Map<String, Object> attributes = new HashMap<String, Object>(objectAttributes);
-
- if (objectAttributes.containsKey(Port.PROTOCOLS))
- {
- final Set<Protocol> protocolSet = MapValueConverter.getEnumSetAttribute(Port.PROTOCOLS, objectAttributes, Protocol.class);
- attributes.put(Port.PROTOCOLS, protocolSet);
- }
-
- if (objectAttributes.containsKey(Port.TRANSPORTS))
- {
- final Set<Transport> transportSet = MapValueConverter.getEnumSetAttribute(Port.TRANSPORTS, objectAttributes,
- Transport.class);
- attributes.put(Port.TRANSPORTS, transportSet);
- }
-
- if (objectAttributes.containsKey(Port.PORT))
- {
- Integer port = MapValueConverter.getIntegerAttribute(Port.PORT, objectAttributes);
- attributes.put(Port.PORT, port);
- }
-
- if (objectAttributes.containsKey(Port.TCP_NO_DELAY))
- {
- boolean tcpNoDelay = MapValueConverter.getBooleanAttribute(Port.TCP_NO_DELAY, objectAttributes);
- attributes.put(Port.TCP_NO_DELAY, tcpNoDelay);
- }
-
- if (objectAttributes.containsKey(Port.RECEIVE_BUFFER_SIZE))
- {
- int receiveBufferSize = MapValueConverter.getIntegerAttribute(Port.RECEIVE_BUFFER_SIZE, objectAttributes);
- attributes.put(Port.RECEIVE_BUFFER_SIZE, receiveBufferSize);
- }
-
- if (objectAttributes.containsKey(Port.SEND_BUFFER_SIZE))
- {
- int sendBufferSize = MapValueConverter.getIntegerAttribute(Port.SEND_BUFFER_SIZE, objectAttributes);
- attributes.put(Port.SEND_BUFFER_SIZE, sendBufferSize);
- }
-
- if (objectAttributes.containsKey(Port.NEED_CLIENT_AUTH))
- {
- boolean needClientAuth = MapValueConverter.getBooleanAttribute(Port.NEED_CLIENT_AUTH, objectAttributes);
- attributes.put(Port.NEED_CLIENT_AUTH, needClientAuth);
- }
-
- if (objectAttributes.containsKey(Port.WANT_CLIENT_AUTH))
- {
- boolean wantClientAuth = MapValueConverter.getBooleanAttribute(Port.WANT_CLIENT_AUTH, objectAttributes);
- attributes.put(Port.WANT_CLIENT_AUTH, wantClientAuth);
- }
-
- if (objectAttributes.containsKey(Port.BINDING_ADDRESS))
- {
- String binding = MapValueConverter.getStringAttribute(Port.BINDING_ADDRESS, objectAttributes);
- attributes.put(Port.BINDING_ADDRESS, binding);
- }
-
- if (objectAttributes.containsKey(Port.STATE))
- {
- State state = MapValueConverter.getEnumAttribute(State.class, Port.STATE, objectAttributes);
- attributes.put(Port.STATE, state);
- }
- return attributes;
- }
-
- private boolean isAmqpProtocol(Map<String, Object> portAttributes)
+ private boolean isAmqpProtocol(Set<Protocol> protocols, Map<String, Object> portAttributes)
{
- @SuppressWarnings("unchecked")
- Set<Protocol> protocols = (Set<Protocol>) portAttributes.get(Port.PROTOCOLS);
if (protocols == null || protocols.isEmpty())
{
// defaulting to AMQP if protocol is not specified
@@ -208,7 +135,7 @@ public class PortFactory
if (protocolTypes.size() > 1)
{
throw new IllegalConfigurationException("Found different protocol types '" + protocolTypes
- + "' on port configuration: " + portAttributes);
+ + "' for port configuration: " + portAttributes);
}
return protocolTypes.contains(ProtocolType.AMQP);
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 1d50be279f..cc323694e0 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
@@ -21,6 +21,7 @@
package org.apache.qpid.server.model.adapter;
import java.io.File;
+import java.lang.reflect.Type;
import java.security.AccessControlException;
import java.security.Principal;
import java.util.ArrayList;
@@ -38,6 +39,7 @@ import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
+import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -50,6 +52,7 @@ import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Connection;
import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.IntegrityViolationException;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
@@ -76,14 +79,17 @@ import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.util.MapValueConverter;
import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.util.FileUtils;
public final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, ExchangeRegistry.RegistryChangeListener,
QueueRegistry.RegistryChangeListener,
IConnectionRegistry.RegistryChangeListener
{
+ private static final Logger LOGGER = Logger.getLogger(VirtualHostAdapter.class);
+
@SuppressWarnings("serial")
- public static final Map<String, Class<?>> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Class<?>>(){{
+ public static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{
put(NAME, String.class);
put(STORE_PATH, String.class);
put(STORE_TYPE, String.class);
@@ -124,26 +130,25 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
}
String configurationFile = (String) getAttribute(CONFIG_PATH);
- String storePath = (String) getAttribute(STORE_PATH);
String storeType = (String) getAttribute(STORE_TYPE);
boolean invalidAttributes = false;
if (configurationFile == null)
{
- if (storePath == null || storeType == null)
+ if (storeType == null)
{
invalidAttributes = true;
}
}
else
{
- if (storePath != null || storeType != null)
+ if (storeType != null)
{
invalidAttributes = true;
}
}
if (invalidAttributes)
{
- throw new IllegalConfigurationException("Please specify either the 'configPath' attribute or both 'storePath' and 'storeType' attributes");
+ throw new IllegalConfigurationException("Please specify either the 'configPath' attribute or 'storeType' and 'storePath' attributes");
}
}
@@ -963,10 +968,19 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
else if (desiredState == State.DELETED)
{
//TODO: add ACL check to authorize the operation
+
+ String hostName = getName();
+
+ if (hostName.equals(_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)))
+ {
+ throw new IntegrityViolationException("Cannot delete default virtual host '" + hostName + "'");
+ }
if (_virtualHost != null && _virtualHost.getState() == org.apache.qpid.server.virtualhost.State.ACTIVE)
{
setDesiredState(currentState, State.STOPPED);
}
+ _virtualHost = null;
+ setAttribute(VirtualHost.STATE, getActualState(), State.DELETED);
return true;
}
return false;
@@ -1043,4 +1057,166 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual
return _virtualHost.getMessageStore();
}
+ @Override
+ protected void changeAttributes(Map<String, Object> attributes)
+ {
+ if (State.ACTIVE.equals(getActualState()))
+ {
+ throw new IllegalStateException("Cannot change host attributes on active virtual host. This operation is only supported in management mode.");
+ }
+ Map<String, Object> newAttributes = MapValueConverter.convert(attributes, ATTRIBUTE_TYPES);
+ validateConfigurationAndCopyStoreIntoNewLocationIfRequired(newAttributes);
+ super.changeAttributes(newAttributes);
+ }
+
+ private void validateConfigurationAndCopyStoreIntoNewLocationIfRequired(Map<String, Object> newAttributes)
+ {
+ String name = (String)getAttribute(NAME);
+ String configPath = (String)getAttribute(CONFIG_PATH);
+ String storePath = (String)getAttribute(STORE_PATH);
+ String storeType = (String)getAttribute(STORE_TYPE);
+
+ String newConfigPath = (String)newAttributes.get(CONFIG_PATH);
+ String newStorePath = (String)newAttributes.get(STORE_PATH);
+ String newStoreType = (String)newAttributes.get(STORE_TYPE);
+
+ String newName = (String)newAttributes.get(NAME);
+ if (newName != null && !newName.equals(name))
+ {
+ if (name.equals(_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)))
+ {
+ throw new IntegrityViolationException("Cannot rename virtual host '" + name + "' as it is set as a default." +
+ " Change the broker default virtual host before renaming");
+ }
+ }
+ if (newConfigPath != null)
+ {
+ // try to open new configuration xml and extract information about message store
+ try
+ {
+ Map<String, String> storeDetails = getStoreDetailsFromVirtualHostConfigXml(name, configPath);
+ newStorePath = storeDetails.get(STORE_PATH);
+ newStoreType = storeDetails.get(STORE_TYPE);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalConfigurationException("Cannot open new virtual host configuration at " + newConfigPath, e);
+ }
+ newAttributes.put(STORE_PATH, null);
+ newAttributes.put(STORE_TYPE, null);
+ }
+ else
+ {
+ newAttributes.put(CONFIG_PATH, null);
+ }
+
+ if (configPath != null )
+ {
+ // try to identify store type and location in order to copy old store into a new location
+ try
+ {
+ Map<String, String> storeDetails = getStoreDetailsFromVirtualHostConfigXml(name, configPath);
+ storePath = storeDetails.get(STORE_PATH);
+ storeType = storeDetails.get(STORE_TYPE);
+ }
+ catch (Exception e)
+ {
+ // old configuration might be broken
+ LOGGER.warn("Cannot open virtual host cofiguration at " + configPath + ". Ignoring old broken configuration.", e);
+ }
+ }
+
+ if (storeType != null && storePath != null && newStoreType != null)
+ {
+ File oldStoreLocation = new File(storePath);
+ if (oldStoreLocation.exists())
+ {
+ if (newStoreType.equals(newStoreType))
+ {
+ File newStoreLocation = new File(newStorePath);
+ if (!oldStoreLocation.equals(newStoreLocation))
+ {
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Copying store for virtual host '" + name + "' from '"
+ + oldStoreLocation.getAbsolutePath() + "' into '" + newStoreLocation.getAbsolutePath() + "'");
+ }
+ copyStoreFiles(oldStoreLocation, newStoreLocation);
+ }
+ }
+ else
+ {
+ LOGGER.warn("Requested a message store of different type ("
+ + newStoreType + ") than existing store (" + storeType
+ + "). At the moment, copying of data is not supported for stores of different types."
+ + " As result an empty new store will be created and old data will be lost.");
+ }
+ }
+ else
+ {
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Virtual host '" + name + "' store does not exists at " + oldStoreLocation.getAbsolutePath() + ". Skipping srore copying...");
+ }
+ }
+ }
+ }
+
+ private void copyStoreFiles(File oldStoreLocation, File newStoreLocation)
+ {
+ if (!newStoreLocation.exists() && !newStoreLocation.getParentFile().exists())
+ {
+ newStoreLocation.getParentFile().mkdirs();
+ }
+ try
+ {
+ if (oldStoreLocation.isFile())
+ {
+ if (!newStoreLocation.exists())
+ {
+ newStoreLocation.createNewFile();
+ }
+ FileUtils.copy(oldStoreLocation, newStoreLocation);
+ }
+ else
+ {
+ if (!newStoreLocation.exists())
+ {
+ newStoreLocation.mkdir();
+ }
+ FileUtils.copyRecursive(oldStoreLocation, newStoreLocation);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new IllegalConfigurationException("Cannot copy store data into a new location at " + newStoreLocation, e);
+ }
+ }
+
+ private Map<String, String> getStoreDetailsFromVirtualHostConfigXml(String name, String configPath) throws Exception
+ {
+ Map<String, String> storeDetails = new HashMap<String, String>();
+ VirtualHostConfiguration configuration = new VirtualHostConfiguration(name, new File(configPath) , _broker);
+ String storePath = configuration.getStoreConfiguration().getString("environment-path");
+ String storeType = configuration.getStoreConfiguration().getString("type");
+ if (storeType == null)
+ {
+ String storeClass = configuration.getStoreConfiguration().getString("class");
+ if (storeClass != null)
+ {
+ final Class<?> clazz = Class.forName(storeClass);
+ final Object o = clazz.newInstance();
+
+ if (o instanceof MessageStore)
+ {
+ MessageStore ms = (MessageStore)o;
+ storeType = ms.getStoreType();
+ }
+ }
+ }
+
+ storeDetails.put(STORE_PATH, storePath);
+ storeDetails.put(STORE_TYPE, storeType);
+ return storeDetails;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java
index aa7b4afcae..8c57d04348 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java
@@ -20,7 +20,9 @@
*/
package org.apache.qpid.server.util;
-import java.util.Collection;
+import java.lang.reflect.Array;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -264,93 +266,57 @@ public class MapValueConverter
}
}
- @SuppressWarnings("unchecked")
public static <T extends Enum<T>> Set<T> getEnumSetAttribute(String name, Map<String, Object> attributes, Class<T> clazz)
{
Object obj = attributes.get(name);
- Object[] items = null;
if (obj == null)
{
return null;
}
- else if (obj instanceof Collection)
- {
- Collection<?> data = (Collection<?>) obj;
- items = data.toArray(new Object[data.size()]);
- }
- else if (obj instanceof String[])
- {
- items = (String[]) obj;
- }
- else if (obj instanceof Object[])
- {
- items = (Object[]) obj;
- }
else
{
- throw new IllegalArgumentException("Value for attribute " + name + "[" + obj
- + "] cannot be converted into set of enum of " + clazz);
- }
- Set<T> set = new HashSet<T>();
- for (int i = 0; i < items.length; i++)
- {
- T item = null;
- Object value = items[i];
- if (value instanceof String)
- {
- item = (T) Enum.valueOf(clazz, (String) value);
- }
- else if (clazz.isInstance(value))
- {
- item = (T) value;
- }
- else
- {
- throw new IllegalArgumentException("Cannot convert " + value + " from [" + obj + "] into enum of " + clazz
- + " for attribute " + name);
- }
- set.add(item);
+ return toSet(obj, clazz, name);
}
- return set;
}
- @SuppressWarnings("unchecked")
- public static Map<String, Object> convert(Map<String, Object> configurationAttributes, Map<String, Class<?>> attributeTypes)
+ public static Map<String, Object> convert(Map<String, Object> configurationAttributes, Map<String, Type> attributeTypes)
{
Map<String, Object> attributes = new HashMap<String, Object>();
- for (Map.Entry<String, Class<?>> attributeEntry : attributeTypes.entrySet())
+ for (Map.Entry<String, Type> attributeEntry : attributeTypes.entrySet())
{
String attributeName = attributeEntry.getKey();
if (configurationAttributes.containsKey(attributeName))
{
- Class<?> classObject = attributeEntry.getValue();
+ Type typeObject = attributeEntry.getValue();
Object rawValue = configurationAttributes.get(attributeName);
Object value = null;
- if (classObject == Long.class || classObject == long.class)
- {
- value = toLong(attributeName, rawValue);
- }
- else if (classObject == Integer.class || classObject == int.class)
- {
- value = toInteger(attributeName, rawValue);
- }
- else if (classObject == Boolean.class || classObject == boolean.class)
+ if (typeObject instanceof Class)
{
- value = toBoolean(attributeName, rawValue);
+ Class<?> classObject = (Class<?>)typeObject;
+ value = convert(rawValue, classObject, attributeName);
}
- else if (classObject == String.class)
+ else if (typeObject instanceof ParameterizedType)
{
- value = toString(rawValue);
- }
- else if (Enum.class.isAssignableFrom(classObject))
- {
- @SuppressWarnings("rawtypes")
- Class<Enum> enumType = (Class<Enum>)classObject;
- value = toEnum(attributeName, rawValue, enumType);
+ ParameterizedType parameterizedType= (ParameterizedType)typeObject;
+ Type type = parameterizedType.getRawType();
+ if (type == Set.class)
+ {
+ Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+ if (actualTypeArguments.length != 1)
+ {
+ throw new IllegalArgumentException("Set type argument is not specified");
+ }
+ Class<?> classObject = (Class<?>)actualTypeArguments[0];
+ value = toSet(rawValue, classObject, attributeName);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Convertion into " + parameterizedType + " is not yet supported");
+ }
}
else
{
- throw new IllegalArgumentException("Cannot convert '" + rawValue + "' into " + classObject);
+ throw new IllegalArgumentException("Convertion into " + typeObject + " is not yet supported");
}
attributes.put(attributeName, value);
}
@@ -358,4 +324,65 @@ public class MapValueConverter
return attributes;
}
+ public static <T> Set<T> toSet(Object rawValue, Class<T> setItemClass, String attributeName)
+ {
+ HashSet<T> set = new HashSet<T>();
+ if (rawValue instanceof Iterable)
+ {
+ Iterable<?> iterable = (Iterable<?>)rawValue;
+ for (Object object : iterable)
+ {
+ T converted = convert(object, setItemClass, attributeName);
+ set.add(converted);
+ }
+ }
+ else if (rawValue.getClass().isArray())
+ {
+ int length = Array.getLength(rawValue);
+ for (int i = 0; i < length; i ++)
+ {
+ Object arrayElement = Array.get(rawValue, i);
+ T converted = convert(arrayElement, setItemClass, attributeName);
+ set.add(converted);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot convert '" + rawValue.getClass() + "' into Set<" + setItemClass.getSimpleName() + "> for attribute " + attributeName);
+ }
+ return set;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static <T> T convert(Object rawValue, Class<T> classObject, String attributeName)
+ {
+ Object value;
+ if (classObject == Long.class || classObject == long.class)
+ {
+ value = toLong(attributeName, rawValue);
+ }
+ else if (classObject == Integer.class || classObject == int.class)
+ {
+ value = toInteger(attributeName, rawValue);
+ }
+ else if (classObject == Boolean.class || classObject == boolean.class)
+ {
+ value = toBoolean(attributeName, rawValue);
+ }
+ else if (classObject == String.class)
+ {
+ value = toString(rawValue);
+ }
+ else if (Enum.class.isAssignableFrom(classObject))
+ {
+ value = toEnum(attributeName, rawValue, (Class<Enum>) classObject);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot convert '" + rawValue + "' of type '" + rawValue.getClass()
+ + "' into type " + classObject + " for attribute " + attributeName);
+ }
+ return (T) value;
+ }
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/util/ParameterizedTypeImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/ParameterizedTypeImpl.java
new file mode 100644
index 0000000000..29bc81caab
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/util/ParameterizedTypeImpl.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.util;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+public class ParameterizedTypeImpl implements ParameterizedType
+{
+ private Class<?> _rawType;
+ private Type[] _typeArguments;
+
+ public ParameterizedTypeImpl(Class<?> rawType, Class<?>... typeArguments)
+ {
+ _rawType = rawType;
+ _typeArguments = typeArguments;
+ }
+ @Override
+ public Type[] getActualTypeArguments()
+ {
+ return _typeArguments;
+ }
+
+ @Override
+ public Type getRawType()
+ {
+ return _rawType;
+ }
+
+ @Override
+ public Type getOwnerType()
+ {
+ return _rawType.getDeclaringClass();
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(_rawType.getName());
+ if (_typeArguments != null)
+ {
+ sb.append("<");
+ for (int i = 0; i < _typeArguments.length; i++)
+ {
+ sb.append(_typeArguments[i].getClass().getName());
+ if (i < _typeArguments.length - 1)
+ {
+ sb.append(",");
+ }
+ }
+ sb.append(">");
+ }
+ return sb.toString();
+ }
+}
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 57d219f85f..eb5b2b350f 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
@@ -91,7 +91,7 @@ public class VirtualHostRecovererTest extends TestCase
attributes.put(VirtualHost.NAME, getName());
attributes.put(VirtualHost.STORE_PATH, "/path/to/store");
attributes.put(VirtualHost.STORE_TYPE, "DERBY");
- mandatoryAttributes = new String[]{VirtualHost.NAME, VirtualHost.STORE_PATH, VirtualHost.STORE_TYPE};
+ mandatoryAttributes = new String[]{VirtualHost.NAME, VirtualHost.STORE_TYPE};
checkMandatoryAttributesAreValidated(mandatoryAttributes, attributes);
}
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 a171b4459b..157945f2be 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
@@ -20,17 +20,26 @@
*/
package org.apache.qpid.systest.rest;
+import java.io.File;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.User;
+import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory;
+import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
public class AuthenticationProviderRestTest extends QpidRestTestCase
{
+ private static final String PRINCIPAL_DATABASE_AUTHENTICATION_MANAGER = "PrincipalDatabaseAuthenticationManager";
+ private static final String AUTHENTICATION_MANAGER = "AuthenticationManager";
+
public void testGet() throws Exception
{
List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider");
@@ -38,15 +47,195 @@ public class AuthenticationProviderRestTest extends QpidRestTestCase
assertEquals("Unexpected number of providers", 1, providerDetails.size());
for (Map<String, Object> provider : providerDetails)
{
- assertProvider("PrincipalDatabaseAuthenticationManager", provider);
+ assertProvider(PRINCIPAL_DATABASE_AUTHENTICATION_MANAGER, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE, provider);
Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/authenticationprovider/"
+ provider.get(AuthenticationProvider.NAME));
assertNotNull("Cannot load data for " + provider.get(AuthenticationProvider.NAME), data);
- assertProvider("PrincipalDatabaseAuthenticationManager", data);
+ assertProvider(PRINCIPAL_DATABASE_AUTHENTICATION_MANAGER, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE, data);
+ }
+ }
+
+ public void testPutCreateNewPlainPrincipalDatabaseProvider() throws Exception
+ {
+ File principalDatabase = getRestTestHelper().createTemporaryPasswdFile(new String[]{"admin2", "guest2", "test2"});
+
+ String providerName = "test-provider";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AuthenticationProvider.NAME, providerName);
+ attributes.put(AuthenticationProvider.TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE);
+ 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(PRINCIPAL_DATABASE_AUTHENTICATION_MANAGER, 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());
+ }
+
+ public void testPutCreateNewAnonymousProvider() throws Exception
+ {
+ String providerName = "test-provider";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AuthenticationProvider.NAME, providerName);
+ attributes.put(AuthenticationProvider.TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE);
+
+ 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(AUTHENTICATION_MANAGER, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE, provider);
+ }
+
+ public void testDeleteOfDefaultAuthenticationProviderFails() throws Exception
+ {
+ String providerName = TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER;
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + providerName , "DELETE", null);
+ assertEquals("Unexpected response code", 409, 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());
+ assertProvider(PRINCIPAL_DATABASE_AUTHENTICATION_MANAGER, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE, providerDetails.get(0));
+ }
+
+ public void testDeleteOfUsedAuthenticationProviderFails() throws Exception
+ {
+ // create provider
+ String providerName = "test-provider";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AuthenticationProvider.NAME, providerName);
+ attributes.put(AuthenticationProvider.TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + providerName, "PUT", attributes);
+ assertEquals("Unexpected response code for provider creation", 201, responseCode);
+
+ // create port
+ String portName = "test-port";
+ Map<String, Object> portAttributes = new HashMap<String, Object>();
+ portAttributes.put(Port.NAME, portName);
+ portAttributes.put(Port.AUTHENTICATION_MANAGER, providerName);
+ portAttributes.put(Port.PORT, findFreePort());
+
+ responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", portAttributes);
+ assertEquals("Unexpected response code for port creation", 201, responseCode);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + providerName , "DELETE", null);
+ assertEquals("Unexpected response code for provider deletion", 409, 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());
+ assertProvider(AUTHENTICATION_MANAGER, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE, providerDetails.get(0));
+ }
+
+ public void testDeleteOfUnusedAuthenticationProvider() throws Exception
+ {
+ // create provider
+ String providerName = "test-provider";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AuthenticationProvider.NAME, providerName);
+ attributes.put(AuthenticationProvider.TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE);
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + providerName, "PUT", attributes);
+ assertEquals("Unexpected response code for provider creation", 201, responseCode);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + providerName , "DELETE", null);
+ assertEquals("Unexpected response code for provider deletion", 200, responseCode);
+
+ List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider/" + providerName);
+ assertNotNull("Providers details cannot be null", providerDetails);
+ assertEquals("Unexpected number of providers", 0, providerDetails.size());
+ }
+
+ public void testPutUpdateAuthenticationProvider() throws Exception
+ {
+ File principalDatabase = getRestTestHelper().createTemporaryPasswdFile(new String[]{"admin2", "guest2", "test2"});
+
+ String providerName = "test-provider";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AuthenticationProvider.NAME, providerName);
+ attributes.put(AuthenticationProvider.TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE);
+ 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());
+
+ String[] users = new String[]{"admin3", "guest3", "test3"};
+ File principalDatabase2 = getRestTestHelper().createTemporaryPasswdFile(users);
+
+ Map<String, Object> newAttributes = new HashMap<String, Object>();
+ newAttributes.put(AuthenticationProvider.NAME, providerName);
+ newAttributes.put(AuthenticationProvider.TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE);
+ newAttributes.put(PlainPasswordFileAuthenticationManagerFactory.ATTRIBUTE_PATH, principalDatabase2.getAbsolutePath());
+
+ responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + providerName, "PUT", newAttributes);
+ assertEquals("Unexpected response code", 200, responseCode);
+
+ providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider/" + providerName);
+ assertNotNull("Providers details cannot be null", providerDetails);
+ assertEquals("Unexpected number of providers", 1, providerDetails.size());
+
+ List<Map<String, Object>> userData = getRestTestHelper().getJsonAsList("/rest/user/" + providerName);
+ assertEquals(3, userData.size());
+ for (int i = 0; i < users.length; i++)
+ {
+ boolean userFound = false;
+ for (Map<String, Object> userEntry : userData)
+ {
+ String name = (String)userEntry.get(User.NAME);
+ if (users[i].equals(name))
+ {
+ userFound = true;
+ break;
+ }
+ }
+ assertTrue("User " + users[i] + " is not found", userFound);
}
}
- private void assertProvider(String type, Map<String, Object> provider)
+ public void testPutUpdateAuthenticationProviderToDifferrentCategoryFails() throws Exception
+ {
+ File principalDatabase = getRestTestHelper().createTemporaryPasswdFile(new String[]{"admin2", "guest2", "test2"});
+
+ String providerName = "test-provider";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(AuthenticationProvider.NAME, providerName);
+ attributes.put(AuthenticationProvider.TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE);
+ 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> newAttributes = new HashMap<String, Object>();
+ newAttributes.put(AuthenticationProvider.NAME, providerName);
+ newAttributes.put(AuthenticationProvider.TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + providerName, "PUT", newAttributes);
+ assertEquals("Unexpected response code", 409, responseCode);
+ }
+
+ private void assertProvider(String category, String subType, Map<String, Object> provider)
{
Asserts.assertAttributesPresent(provider, AuthenticationProvider.AVAILABLE_ATTRIBUTES,
AuthenticationProvider.CREATED, AuthenticationProvider.UPDATED, AuthenticationProvider.DESCRIPTION,
@@ -57,17 +246,22 @@ public class AuthenticationProviderRestTest extends QpidRestTestCase
LifetimePolicy.PERMANENT.name(), provider.get(AuthenticationProvider.LIFETIME_POLICY));
assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.DURABLE, Boolean.TRUE,
provider.get(AuthenticationProvider.DURABLE));
- assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.TYPE, type,
+ assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.CATEGORY, category,
+ provider.get(AuthenticationProvider.CATEGORY));
+ assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.TYPE, subType,
provider.get(AuthenticationProvider.TYPE));
- @SuppressWarnings("unchecked")
- List<Map<String, Object>> users = (List<Map<String, Object>>) provider.get("users");
- assertNotNull("Users are not found", users);
- assertTrue("Unexpected number of users", users.size() > 1);
- for (Map<String, Object> user : users)
+ if (PRINCIPAL_DATABASE_AUTHENTICATION_MANAGER.equals(category))
{
- assertNotNull("Attribute " + User.ID, user.get(User.ID));
- assertNotNull("Attribute " + User.NAME, user.get(User.NAME));
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> users = (List<Map<String, Object>>) provider.get("users");
+ assertNotNull("Users are not found", users);
+ assertTrue("Unexpected number of users", users.size() > 1);
+ for (Map<String, Object> user : users)
+ {
+ assertNotNull("Attribute " + User.ID, user.get(User.ID));
+ assertNotNull("Attribute " + User.NAME, user.get(User.NAME));
+ }
}
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
index 578565be05..48fd8f44b1 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
@@ -21,10 +21,17 @@
package org.apache.qpid.systest.rest;
import java.net.URLDecoder;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
+import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory;
import org.apache.qpid.test.utils.TestBrokerConfiguration;
public class PortRestTest extends QpidRestTestCase
@@ -61,4 +68,111 @@ public class PortRestTest extends QpidRestTestCase
}
}
+ public void testPutAmqpPortWithMinimumAttributes() throws Exception
+ {
+ String portName = "test-port";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(Port.NAME, portName);
+ attributes.put(Port.PORT, findFreePort());
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
+ assertEquals("Unexpected response code", 201, responseCode);
+
+ List<Map<String, Object>> portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
+ assertNotNull("Port details cannot be null", portDetails);
+ assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size());
+ Map<String, Object> port = portDetails.get(0);
+ Asserts.assertPortAttributes(port);
+
+ // make sure that port is there after broker restart
+ restartBroker();
+
+ portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
+ assertNotNull("Port details cannot be null", portDetails);
+ assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size());
+ }
+
+ public void testPutRmiPortWithMinimumAttributes() throws Exception
+ {
+ String portName = "test-port";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(Port.NAME, portName);
+ attributes.put(Port.PORT, findFreePort());
+ attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.RMI));
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
+ assertEquals("Unexpected response code", 201, responseCode);
+
+ List<Map<String, Object>> portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
+ assertNotNull("Port details cannot be null", portDetails);
+ assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size());
+ Map<String, Object> port = portDetails.get(0);
+ Asserts.assertPortAttributes(port);
+
+ // make sure that port is there after broker restart
+ restartBroker();
+
+ portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
+ assertNotNull("Port details cannot be null", portDetails);
+ assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size());
+ }
+
+ public void testPutCreateAndUpdateAmqpPort() throws Exception
+ {
+ String portName = "test-port";
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(Port.NAME, portName);
+ attributes.put(Port.PORT, findFreePort());
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
+ assertEquals("Unexpected response code for port creation", 201, responseCode);
+
+ List<Map<String, Object>> portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
+ assertNotNull("Port details cannot be null", portDetails);
+ assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size());
+ Map<String, Object> port = portDetails.get(0);
+ Asserts.assertPortAttributes(port);
+
+ Map<String, Object> authProviderAttributes = new HashMap<String, Object>();
+ authProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE);
+ authProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER);
+
+ responseCode = getRestTestHelper().submitRequest("/rest/authenticationprovider/" + TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER, "PUT", authProviderAttributes);
+ assertEquals("Unexpected response code for authentication provider creation", 201, responseCode);
+
+ attributes = new HashMap<String, Object>(port);
+ attributes.put(Port.AUTHENTICATION_MANAGER, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER);
+ attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.AMQP_0_9_1));
+
+ responseCode = getRestTestHelper().submitRequest("/rest/port/" + portName, "PUT", attributes);
+ assertEquals("Unexpected response code for port update", 200, responseCode);
+
+ portDetails = getRestTestHelper().getJsonAsList("/rest/port/" + portName);
+ assertNotNull("Port details cannot be null", portDetails);
+ assertEquals("Unexpected number of ports with name " + portName, 1, portDetails.size());
+ port = portDetails.get(0);
+
+ assertEquals("Unexpected authentication provider", TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER, port.get(Port.AUTHENTICATION_MANAGER));
+ Object protocols = port.get(Port.PROTOCOLS);
+ assertNotNull("Protocols attribute is not found", protocols);
+ assertTrue("Protocol attribute value is not collection:" + protocols, protocols instanceof Collection);
+ @SuppressWarnings("unchecked")
+ Collection<String> protocolsCollection = ((Collection<String>)protocols);
+ assertEquals("Unexpected protocols size", 1, protocolsCollection.size());
+ assertEquals("Unexpected protocols", Protocol.AMQP_0_9_1.name(), protocolsCollection.iterator().next());
+ }
+
+ public void testPutUpdateOpenedAmqpPortFails() throws Exception
+ {
+ Map<String, Object> port = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT);
+ Integer portValue = (Integer)port.get(Port.PORT);
+
+ port.put(Port.PORT, findFreePort());
+
+ int responseCode = getRestTestHelper().submitRequest("/rest/port/" + TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, "PUT", port);
+ assertEquals("Unexpected response code for port update", 409, responseCode);
+
+ port = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT);
+ assertEquals("Port has been changed", portValue, port.get(Port.PORT));
+ }
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java
index 0db1f7e50d..9628423a00 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java
@@ -422,7 +422,7 @@ public class RestTestHelper
}
}
- private File createTemporaryPasswdFile(String[] users) throws IOException
+ File createTemporaryPasswdFile(String[] users) throws IOException
{
BufferedWriter writer = null;
try
@@ -449,4 +449,17 @@ public class RestTestHelper
}
}
}
+
+ public int submitRequest(String url, String method, Map<String, Object> attributes) throws IOException,
+ JsonGenerationException, JsonMappingException
+ {
+ HttpURLConnection connection = openManagementConnection(url, method);
+ if (attributes != null)
+ {
+ writeJsonRequest(connection, attributes);
+ }
+ int responseCode = connection.getResponseCode();
+ connection.disconnect();
+ return responseCode;
+ }
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java
index fb2c941203..c5dfb84d40 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java
@@ -169,6 +169,112 @@ public class VirtualHostRestTest extends QpidRestTestCase
assertEquals("Host should be deleted", 0, hosts.size());
}
+ public void testDeleteDefaultHostFails() throws Exception
+ {
+ String hostToDelete = TEST1_VIRTUALHOST;
+ int response = getRestTestHelper().submitRequest("/rest/virtualhost/" + hostToDelete, "DELETE", null);
+ assertEquals("Unexpected response code", 409, response);
+
+ restartBroker();
+
+ List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/" + hostToDelete);
+ assertEquals("Host should be deleted", 1, hosts.size());
+ }
+
+ public void testUpdateActiveHostFails() throws Exception
+ {
+ String hostToUpdate = TEST3_VIRTUALHOST;
+ Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate);
+ Asserts.assertVirtualHost(hostToUpdate, hostDetails);
+ String configPath = (String)hostDetails.get(VirtualHost.CONFIG_PATH);
+ assertNotNull("Unexpected host configuration", configPath);
+
+ String storeType = getTestProfileMessageStoreType();
+ String storeLocation = getStoreLocation(hostToUpdate);
+ Map<String, Object> newAttributes = new HashMap<String, Object>();
+ newAttributes.put(VirtualHost.NAME, hostToUpdate);
+ newAttributes.put(VirtualHost.STORE_TYPE, storeType);
+ newAttributes.put(VirtualHost.STORE_PATH, storeLocation);
+
+ int response = getRestTestHelper().submitRequest("/rest/virtualhost/" + hostToUpdate, "PUT", newAttributes);
+ assertEquals("Unexpected response code", 409, response);
+
+ restartBroker();
+
+ hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate);
+ Asserts.assertVirtualHost(hostToUpdate, hostDetails);
+ assertEquals("Unexpected config path", configPath, hostDetails.get(VirtualHost.CONFIG_PATH));
+ }
+
+ public void testUpdateInManagementMode() throws Exception
+ {
+ String hostToUpdate = TEST3_VIRTUALHOST;
+ Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate);
+ Asserts.assertVirtualHost(hostToUpdate, hostDetails);
+ String configPath = (String)hostDetails.get(VirtualHost.CONFIG_PATH);
+ String storeType = (String)hostDetails.get(VirtualHost.STORE_TYPE);
+ assertNotNull("Unexpected host configuration", configPath);
+ assertNotNull("Unexpected store type", storeType);
+
+ String queueName = getTestQueueName();
+ if (isBrokerStorePersistent())
+ {
+ String storePath = (String)hostDetails.get(VirtualHost.STORE_PATH);
+ assertNotNull("Unexpected store path", storePath);
+
+ // add a durable queue to the host
+ // in order to test whether host store is copied into a new location
+ Map<String, Object> queueData = new HashMap<String, Object>();
+ queueData.put(Queue.NAME, queueName);
+ queueData.put(Queue.DURABLE, Boolean.TRUE);
+ int response = getRestTestHelper().submitRequest("/rest/queue/" + hostToUpdate + "/" + queueName, "PUT", queueData);
+ assertEquals("Unexpected response code for queue creation", 201, response);
+ }
+
+ // stop broker as it is running not in management mode
+ stopBroker(0);
+
+ // start broker in management mode
+ startBroker(0, true);
+
+ String newStoreType = getTestProfileMessageStoreType();
+ String newStorePath = getStoreLocation(hostToUpdate);
+ Map<String, Object> newAttributes = new HashMap<String, Object>();
+ newAttributes.put(VirtualHost.NAME, hostToUpdate);
+ newAttributes.put(VirtualHost.STORE_TYPE, newStoreType);
+ newAttributes.put(VirtualHost.STORE_PATH, newStorePath);
+ newAttributes.put(VirtualHost.CONFIG_PATH, null);
+
+ try
+ {
+ int response = getRestTestHelper().submitRequest("/rest/virtualhost/" + hostToUpdate, "PUT", newAttributes);
+ assertEquals("Unexpected response code for virtual host update", 200, response);
+
+ restartBroker();
+
+ hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate);
+ Asserts.assertVirtualHost(hostToUpdate, hostDetails);
+ assertEquals("Unexpected config type", newStoreType, hostDetails.get(VirtualHost.STORE_TYPE));
+
+ if (isBrokerStorePersistent())
+ {
+ assertEquals("Unexpected config path", newStorePath, hostDetails.get(VirtualHost.STORE_PATH));
+
+ // the virtual host store should be copied into a new location
+ // check existence of the queue
+ List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/" + hostToUpdate + "/" + queueName);
+ assertEquals("Queue is not found. Looks like message store was not copied", 1, queues.size());
+ }
+ }
+ finally
+ {
+ if (newStorePath != null)
+ {
+ FileUtils.delete(new File(newStorePath), true);
+ }
+ }
+ }
+
public void testPutCreateQueue() throws Exception
{
String queueName = getTestQueueName();
@@ -519,7 +625,6 @@ public class VirtualHostRestTest extends QpidRestTestCase
private int tryCreateVirtualHost(String hostName, String storeType, String storePath, String configPath) throws IOException,
JsonGenerationException, JsonMappingException
{
- HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/virtualhost/" + hostName, "PUT");
Map<String, Object> hostData = new HashMap<String, Object>();
hostData.put(VirtualHost.NAME, hostName);
@@ -533,10 +638,7 @@ public class VirtualHostRestTest extends QpidRestTestCase
hostData.put(VirtualHost.STORE_TYPE, storeType);
}
- getRestTestHelper().writeJsonRequest(connection, hostData);
- int responseCode = connection.getResponseCode();
- connection.disconnect();
- return responseCode;
+ return getRestTestHelper().submitRequest("/rest/virtualhost/" + hostName, "PUT", hostData);
}
private XMLConfiguration createAndSaveVirtualHostConfiguration(String hostName, File configFile, String storeLocation)
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
index d36f57171f..394fed7d47 100755
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
@@ -418,12 +418,16 @@ public class QpidBrokerTestCase extends QpidTestCase
public void startBroker(int port) throws Exception
{
+ startBroker(port, false);
+ }
+
+ public void startBroker(int port, boolean managementMode) throws Exception
+ {
int actualPort = getPort(port);
TestBrokerConfiguration configuration = getBrokerConfiguration(actualPort);
- startBroker(actualPort, configuration, _testVirtualhosts);
+ startBroker(actualPort, configuration, _testVirtualhosts, managementMode);
}
-
protected File getBrokerCommandLog4JFile()
{
return _logConfigFile;
@@ -437,6 +441,11 @@ public class QpidBrokerTestCase extends QpidTestCase
public void startBroker(int port, TestBrokerConfiguration testConfiguration, XMLConfiguration virtualHosts) throws Exception
{
+ startBroker(port, testConfiguration, virtualHosts, false);
+ }
+
+ public void startBroker(int port, TestBrokerConfiguration testConfiguration, XMLConfiguration virtualHosts, boolean managementMode) throws Exception
+ {
port = getPort(port);
String testConfig = saveTestConfiguration(port, testConfiguration);
String virtualHostsConfig = saveTestVirtualhosts(port, virtualHosts);
@@ -457,6 +466,7 @@ public class QpidBrokerTestCase extends QpidTestCase
options.setConfigurationStoreType(_brokerStoreType);
options.setConfigurationStoreLocation(testConfig);
+ options.setManagementMode(managementMode);
//Set the log config file, relying on the log4j.configuration system property
//set on the JVM by the JUnit runner task in module.xml.
@@ -474,6 +484,13 @@ public class QpidBrokerTestCase extends QpidTestCase
final String qpidWork = getQpidWork(_brokerType, port);
String[] cmd = _brokerCommandHelper.getBrokerCommand(port, testConfig, _brokerStoreType, _logConfigFile);
+ if (managementMode)
+ {
+ String[] newCmd = new String[cmd.length + 1];
+ System.arraycopy(cmd, 0, newCmd, 0, cmd.length);
+ newCmd[cmd.length] = "-mm";
+ cmd = newCmd;
+ }
_logger.info("Starting spawn broker using command: " + StringUtils.join(cmd, ' '));
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);