You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rg...@apache.org on 2014/08/22 21:36:41 UTC

svn commit: r1619918 - in /qpid/trunk/qpid/java: bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/ bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/ bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/ber...

Author: rgodfrey
Date: Fri Aug 22 19:36:40 2014
New Revision: 1619918

URL: http://svn.apache.org/r1619918
Log:
QPID-6036 : [Java Broker] Allow complete virtual host initial configuration to be passed in on creation of a virtualhost node

Modified:
    qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
    qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
    qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
    qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
    qpid/trunk/qpid/java/broker-core/src/main/resources/initial-config.json
    qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
    qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
    qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java

Modified: qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java Fri Aug 22 19:36:40 2014
@@ -26,6 +26,7 @@ import java.text.MessageFormat;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -63,6 +64,8 @@ import org.apache.qpid.server.model.Stat
 import org.apache.qpid.server.model.StateTransition;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
 import org.apache.qpid.server.store.DurableConfigurationStore;
 import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer;
 import org.apache.qpid.server.store.berkeleydb.BDBConfigurationStore;
@@ -434,41 +437,40 @@ public class BDBHAVirtualHostNodeImpl ex
                 {
                     LOGGER.debug("Creating new virtualhost with name : " + getGroupName());
                 }
-
-                boolean hasBlueprint = getContextKeys(false).contains(VIRTUALHOST_BLUEPRINT_CONTEXT_VAR);
-                boolean blueprintUtilised = getContext().containsKey(VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR)
-                                            && Boolean.parseBoolean(String.valueOf(getContext().get(
-                        VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR)));
-
-                Map<String, Object> hostAttributes = new HashMap<>();
-                if (hasBlueprint && !blueprintUtilised)
+                ConfiguredObjectRecord[] initialRecords = getInitialRecords();
+                if(initialRecords != null && initialRecords.length > 0)
                 {
-                    Map<String, Object> virtualhostBlueprint =
-                            getContextValue(Map.class, VIRTUALHOST_BLUEPRINT_CONTEXT_VAR);
-
-                    if (LOGGER.isDebugEnabled())
+                    getConfigurationStore().update(true, initialRecords);
+                    getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.RECOVERY_START());
+                    upgraderAndRecoverer = new VirtualHostStoreUpgraderAndRecoverer(this);
+                    upgraderAndRecoverer.perform(getConfigurationStore());
+                    getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.RECOVERY_COMPLETE());
+                    setAttribute(VIRTUALHOST_INITIAL_CONFIGURATION, getVirtualHostInitialConfiguration(), "{}" );
+                    host = getVirtualHost();
+                    if(host != null)
                     {
-                        LOGGER.debug("Using virtualhost blueprint " + virtualhostBlueprint);
+                        final VirtualHost<?,?,?> recoveredHost = host;
+                        Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>()
+                        {
+                            @Override
+                            public Object run()
+                            {
+                                recoveredHost.open();
+                                return null;
+                            }
+                        });
                     }
-
-                    hostAttributes.putAll(virtualhostBlueprint);
-
-
                 }
-
-                hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION);
-                hostAttributes.put(VirtualHost.NAME, getGroupName());
-                hostAttributes.put(VirtualHost.TYPE, BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE);
-                host = createChild(VirtualHost.class, hostAttributes);
-
-                if (hasBlueprint && !blueprintUtilised)
+                else
                 {
-                    // Update the context with the utilised flag
-                    Map<String, String> actualContext = (Map<String, String>) getActualAttributes().get(CONTEXT);
-                    Map<String, String> context = new HashMap<>(actualContext);
-                    context.put(VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR, Boolean.TRUE.toString());
-                    setAttribute(CONTEXT, getContext(), context);
+                    Map<String, Object> hostAttributes = new HashMap<>();
+
+                    hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION);
+                    hostAttributes.put(VirtualHost.NAME, getGroupName());
+                    hostAttributes.put(VirtualHost.TYPE, BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE);
+                    host = createChild(VirtualHost.class, hostAttributes);
                 }
+
             }
             else
             {
@@ -706,6 +708,17 @@ public class BDBHAVirtualHostNodeImpl ex
         return _groupLogSubject;
     }
 
+    @Override
+    protected ConfiguredObjectRecord enrichInitialVirtualHostRootRecord(final ConfiguredObjectRecord vhostRecord)
+    {
+        Map<String,Object> hostAttributes = new LinkedHashMap<>(vhostRecord.getAttributes());
+        hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION);
+        hostAttributes.put(VirtualHost.NAME, getGroupName());
+        hostAttributes.put(VirtualHost.TYPE, BDBHAVirtualHostImpl.VIRTUAL_HOST_TYPE);
+        return new ConfiguredObjectRecordImpl(vhostRecord.getId(), vhostRecord.getType(),
+                                              hostAttributes, vhostRecord.getParents());
+    }
+
     private class RemoteNodesDiscoverer implements ReplicationGroupListener
     {
         @Override

Modified: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java Fri Aug 22 19:36:40 2014
@@ -20,7 +20,6 @@
  */
 package org.apache.qpid.server.store.berkeleydb;
 
-import static java.util.Collections.*;
 import static org.mockito.Mockito.when;
 
 import java.io.File;
@@ -29,7 +28,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -48,12 +46,10 @@ import org.apache.qpid.server.model.Virt
 import org.apache.qpid.server.store.DurableConfigurationStore;
 import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHost;
 import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl;
-import org.apache.qpid.server.virtualhostnode.AbstractVirtualHostNode;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNode;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNodeImpl;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeTestHelper;
-import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeImpl;
 import org.apache.qpid.test.utils.QpidTestCase;
 
 public class BDBHAVirtualHostNodeTest extends QpidTestCase
@@ -94,20 +90,6 @@ public class BDBHAVirtualHostNodeTest ex
         context.put(ReplicationConfig.REP_STREAM_TIMEOUT, repStreamTimeout);
         BDBHAVirtualHostNode<?> node = _helper.createHaVHN(attributes);
 
-        final CountDownLatch virtualHostAddedLatch = new CountDownLatch(1);
-        node.addChangeListener(new NoopConfigurationChangeListener()
-        {
-            @Override
-            public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child)
-            {
-                if (child instanceof VirtualHost)
-                {
-                    child.addChangeListener(this);
-                    virtualHostAddedLatch.countDown();
-                }
-            }
-        });
-
         node.start();
         _helper.assertNodeRole(node, "MASTER", "REPLICA");
 
@@ -128,7 +110,7 @@ public class BDBHAVirtualHostNodeTest ex
         assertEquals("SYNC,NO_SYNC,SIMPLE_MAJORITY", environment.getConfig().getDurability().toString());
         assertEquals("Unexpected JE replication stream timeout", repStreamTimeout, replicationConfig.getConfigParam(ReplicationConfig.REP_STREAM_TIMEOUT));
 
-        assertTrue("Virtual host child has not been added", virtualHostAddedLatch.await(30, TimeUnit.SECONDS));
+        _helper.awaitForVirtualhost(node, 30000);
         VirtualHost<?, ?, ?> virtualHost = node.getVirtualHost();
         assertNotNull("Virtual host child was not added", virtualHost);
         assertEquals("Unexpected virtual host name", groupName, virtualHost.getName());
@@ -314,25 +296,11 @@ public class BDBHAVirtualHostNodeTest ex
         Map<String, Object> nodeAttributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber);
         BDBHAVirtualHostNode<?> node = _helper.createHaVHN(nodeAttributes);
 
-        final CountDownLatch virtualHostAddedLatch = new CountDownLatch(1);
-        node.addChangeListener(new NoopConfigurationChangeListener()
-        {
-            @Override
-            public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child)
-            {
-                if (child instanceof VirtualHost)
-                {
-                    child.addChangeListener(this);
-                    virtualHostAddedLatch.countDown();
-                }
-            }
-        });
-
         node.start();
         _helper.assertNodeRole(node, "MASTER", "REPLICA");
         assertEquals("Unexpected node state", State.ACTIVE, node.getState());
 
-        assertTrue("Virtual host child has not been added", virtualHostAddedLatch.await(30, TimeUnit.SECONDS));
+        _helper.awaitForVirtualhost(node,30000);
         BDBHAVirtualHostImpl virtualHost = (BDBHAVirtualHostImpl)node.getVirtualHost();
         assertNotNull("Virtual host is not created", virtualHost);
 
@@ -500,4 +468,4 @@ public class BDBHAVirtualHostNodeTest ex
         assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(20, TimeUnit.SECONDS));
     }
 
-}
\ No newline at end of file
+}

Modified: qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java (original)
+++ qpid/trunk/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java Fri Aug 22 19:36:40 2014
@@ -38,10 +38,19 @@ import java.util.Set;
 import java.util.UUID;
 
 import com.sleepycat.je.rep.ReplicationConfig;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
 
 import org.apache.qpid.server.configuration.updater.TaskExecutor;
 import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
-import org.apache.qpid.server.model.*;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFactory;
+import org.apache.qpid.server.model.RemoteReplicationNode;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostNode;
 import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
 import org.apache.qpid.server.store.UnresolvedConfiguredObject;
 import org.apache.qpid.server.util.BrokerTestHelper;
@@ -50,8 +59,6 @@ import org.apache.qpid.server.virtualhos
 import org.apache.qpid.server.virtualhostnode.AbstractVirtualHostNode;
 import org.apache.qpid.test.utils.QpidTestCase;
 import org.apache.qpid.util.FileUtils;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
 
 /**
  * Helper class to make the tests of BDB HA Virtual Host Nodes simpler and more concise.
@@ -281,7 +288,7 @@ public class BDBHAVirtualHostNodeTestHel
         if (ports != null)
         {
             String bluePrint = getBlueprint(ports);
-            context.put(AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_CONTEXT_VAR, bluePrint);
+            node1Attributes.put(AbstractVirtualHostNode.VIRTUALHOST_INITIAL_CONFIGURATION, bluePrint);
         }
 
         node1Attributes.put(BDBHAVirtualHostNode.CONTEXT, context);
@@ -307,4 +314,24 @@ public class BDBHAVirtualHostNodeTestHel
         return writer.toString();
     }
 
+    public void awaitForVirtualhost(final VirtualHostNode<?> node, final int wait)
+    {
+        long endTime = System.currentTimeMillis() + wait;
+        do
+        {
+            if(node.getVirtualHost() != null)
+            {
+                return;
+            }
+            try
+            {
+                Thread.sleep(100);
+            }
+            catch (InterruptedException e)
+            {
+                // ignore
+            }
+        }
+        while(System.currentTimeMillis() < endTime);
+    }
 }

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java (original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java Fri Aug 22 19:36:40 2014
@@ -27,6 +27,16 @@ import org.apache.qpid.server.store.Dura
 @ManagedObject(category=true, managesChildren=false)
 public interface VirtualHostNode<X extends VirtualHostNode<X>> extends ConfiguredObject<X>
 {
+    String VIRTUALHOST_INITIAL_CONFIGURATION = "virtualHostInitialConfiguration";
+
+    String VIRTUALHOST_BLUEPRINT_CONTEXT_VAR = "virtualhostBlueprint";
+
+    @ManagedContextDefault(name = VIRTUALHOST_BLUEPRINT_CONTEXT_VAR)
+    String DEFAULT_INITIAL_CONFIGURATION = "{}";
+
+    @ManagedAttribute( defaultValue = "${" + VIRTUALHOST_BLUEPRINT_CONTEXT_VAR + "}")
+    String getVirtualHostInitialConfiguration();
+
     VirtualHost<?,?,?> getVirtualHost();
 
     DurableConfigurationStore getConfigurationStore();

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java (original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java Fri Aug 22 19:36:40 2014
@@ -29,6 +29,8 @@ import org.apache.qpid.server.store.hand
 
 public abstract class NullMessageStore implements MessageStore, DurableConfigurationStore, MessageStoreProvider
 {
+    private ConfiguredObjectRecord[] _initialRecords;
+
     @Override
     public MessageStore getMessageStore()
     {
@@ -40,6 +42,7 @@ public abstract class NullMessageStore i
                                        final boolean overwrite,
                                        final ConfiguredObjectRecord... initialRecords)
     {
+        _initialRecords = initialRecords;
     }
 
     @Override
@@ -121,6 +124,18 @@ public abstract class NullMessageStore i
     @Override
     public void visitConfiguredObjectRecords(ConfiguredObjectRecordHandler handler) throws StoreException
     {
+        handler.begin();
+        if(_initialRecords != null)
+        {
+            for(ConfiguredObjectRecord record : _initialRecords)
+            {
+                if(!handler.handle(record))
+                {
+                    break;
+                }
+            }
+        }
+        handler.end();
     }
 
     @Override

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java (original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java Fri Aug 22 19:36:40 2014
@@ -136,13 +136,4 @@ public class Handler extends URLStreamHa
             return new ByteArrayInputStream(_content);
         }
     }
-
-    public static void main(String[] args) throws IOException
-    {
-        register();
-        URL url = new URL("data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7");
-        InputStream is = url.openStream();
-        url = new URL("data:,A%20brief%20note");
-        is = url.openStream();
-    }
 }

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java (original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java Fri Aug 22 19:36:40 2014
@@ -20,24 +20,27 @@
  */
 package org.apache.qpid.server.virtualhostnode;
 
+import java.io.IOException;
 import java.security.PrivilegedAction;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import javax.security.auth.Subject;
 
 import org.apache.log4j.Logger;
 
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
 import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerModel;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.RemoteReplicationNode;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.model.VirtualHostNode;
 import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
 import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer;
 
 public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandardVirtualHostNode<X>> extends AbstractVirtualHostNode<X>
@@ -71,7 +74,20 @@ public abstract class AbstractStandardVi
             LOGGER.debug("Activating virtualhost node " + this);
         }
 
-        getConfigurationStore().openConfigurationStore(this, false);
+        try
+        {
+            ConfiguredObjectRecord[] initialRecords = getInitialRecords();
+            getConfigurationStore().openConfigurationStore(this, false, initialRecords);
+            if(initialRecords != null && initialRecords.length > 0)
+            {
+                setAttribute(VIRTUALHOST_INITIAL_CONFIGURATION, getVirtualHostInitialConfiguration(), "{}");
+            }
+        }
+        catch (IOException e)
+        {
+            throw new IllegalConfigurationException("Could not process initial configuration", e);
+        }
+
         getConfigurationStore().upgradeStoreStructure();
 
         getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.CREATED());
@@ -87,47 +103,7 @@ public abstract class AbstractStandardVi
 
         VirtualHost<?,?,?>  host = getVirtualHost();
 
-        if (host == null)
-        {
-
-            boolean hasBlueprint = getContextKeys(false).contains(VIRTUALHOST_BLUEPRINT_CONTEXT_VAR);
-            boolean blueprintUtilised = getContext().containsKey(VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR)
-                    && Boolean.parseBoolean(String.valueOf(getContext().get(VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR)));
-
-            if (hasBlueprint && !blueprintUtilised)
-            {
-                Map<String, Object> virtualhostBlueprint = getContextValue(Map.class, VIRTUALHOST_BLUEPRINT_CONTEXT_VAR);
-
-                if (LOGGER.isDebugEnabled())
-                {
-                    LOGGER.debug("Using virtualhost blueprint " + virtualhostBlueprint);
-                }
-
-                Map<String, Object> virtualhostAttributes = new HashMap<>();
-                virtualhostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION);
-                virtualhostAttributes.put(VirtualHost.NAME, getName());
-                virtualhostAttributes.putAll(virtualhostBlueprint);
-
-                if (LOGGER.isDebugEnabled())
-                {
-                    LOGGER.debug("Creating new virtualhost named " + virtualhostAttributes.get(VirtualHost.NAME));
-                }
-
-                host = createChild(VirtualHost.class, virtualhostAttributes);
-
-                if (LOGGER.isDebugEnabled())
-                {
-                    LOGGER.debug("Created new virtualhost: " + host);
-                }
-
-                // Update the context with the utilised flag
-                Map<String, String> actualContext = (Map<String, String>) getActualAttributes().get(CONTEXT);
-                Map<String, String> context = new HashMap<>(actualContext);
-                context.put(VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR, Boolean.TRUE.toString());
-                setAttribute(CONTEXT, getContext(), context);
-            }
-        }
-        else
+        if (host != null)
         {
             final VirtualHost<?,?,?> recoveredHost = host;
             Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>()
@@ -142,6 +118,44 @@ public abstract class AbstractStandardVi
         }
     }
 
+
+    @Override
+    protected ConfiguredObjectRecord enrichInitialVirtualHostRootRecord(final ConfiguredObjectRecord vhostRecord)
+    {
+        ConfiguredObjectRecord replacementRecord;
+        if (vhostRecord.getAttributes().get(ConfiguredObject.NAME) == null)
+        {
+            Map<String, Object> updatedAttributes = new LinkedHashMap<>(vhostRecord.getAttributes());
+            updatedAttributes.put(ConfiguredObject.NAME, getName());
+            if (!updatedAttributes.containsKey(VirtualHost.MODEL_VERSION))
+            {
+                updatedAttributes.put(VirtualHost.MODEL_VERSION, getBroker().getModelVersion());
+            }
+            replacementRecord = new ConfiguredObjectRecordImpl(vhostRecord.getId(),
+                                                               vhostRecord.getType(),
+                                                               updatedAttributes,
+                                                               vhostRecord.getParents());
+        }
+        else if (vhostRecord.getAttributes().get(VirtualHost.MODEL_VERSION) == null)
+        {
+            Map<String, Object> updatedAttributes = new LinkedHashMap<>(vhostRecord.getAttributes());
+
+            updatedAttributes.put(VirtualHost.MODEL_VERSION, getBroker().getModelVersion());
+
+            replacementRecord = new ConfiguredObjectRecordImpl(vhostRecord.getId(),
+                                                               vhostRecord.getType(),
+                                                               updatedAttributes,
+                                                               vhostRecord.getParents());
+        }
+        else
+        {
+            replacementRecord = vhostRecord;
+        }
+
+        return replacementRecord;
+    }
+
+
     protected abstract void writeLocationEventLog();
 
     @Override

Modified: qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java (original)
+++ qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java Fri Aug 22 19:36:40 2014
@@ -20,36 +20,61 @@
  */
 package org.apache.qpid.server.virtualhostnode;
 
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
+
 import org.apache.log4j.Logger;
+
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.logging.EventLogger;
 import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
 import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Exchange;
 import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.StateTransition;
 import org.apache.qpid.server.model.SystemConfig;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.model.VirtualHostNode;
 import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.server.store.ConfiguredObjectRecordConverter;
+import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
 import org.apache.qpid.server.store.DurableConfigurationStore;
-
-import java.security.AccessControlException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
+import org.apache.qpid.server.util.urlstreamhandler.data.Handler;
 
 public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<X>> extends AbstractConfiguredObject<X> implements VirtualHostNode<X>
 {
 
-    public static final String VIRTUALHOST_BLUEPRINT_CONTEXT_VAR = "virtualhostBlueprint";
-    public static final String VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR = "virtualhostBlueprintUtilised";
     private static final Logger LOGGER = Logger.getLogger(AbstractVirtualHostNode.class);
 
+
+    static
+    {
+        Handler.register();
+    }
+
     private final Broker<?> _broker;
     private final AtomicReference<State> _state = new AtomicReference<State>(State.UNINITIALIZED);
     private final EventLogger _eventLogger;
@@ -58,6 +83,9 @@ public abstract class AbstractVirtualHos
 
     private MessageStoreLogSubject _configurationStoreLogSubject;
 
+    @ManagedAttributeField
+    private String _virtualHostInitialConfiguration;
+
     public AbstractVirtualHostNode(Broker<?> parent, Map<String, Object> attributes)
     {
         super(Collections.<Class<? extends ConfiguredObject>,ConfiguredObject<?>>singletonMap(Broker.class, parent),
@@ -241,8 +269,152 @@ public abstract class AbstractVirtualHos
         }
     }
 
+    @Override
+    public String getVirtualHostInitialConfiguration()
+    {
+        return _virtualHostInitialConfiguration;
+    }
+
     protected abstract DurableConfigurationStore createConfigurationStore();
 
     protected abstract void activate();
 
+
+
+    protected abstract ConfiguredObjectRecord enrichInitialVirtualHostRootRecord(final ConfiguredObjectRecord vhostRecord);
+
+    protected final ConfiguredObjectRecord[] getInitialRecords() throws IOException
+    {
+        ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(getModel());
+
+        Collection<ConfiguredObjectRecord> records =
+                new ArrayList<>(converter.readFromJson(VirtualHost.class,this,getInitialConfigReader()));
+
+        if(!records.isEmpty())
+        {
+            ConfiguredObjectRecord vhostRecord = null;
+            for(ConfiguredObjectRecord record : records)
+            {
+                if(record.getType().equals(VirtualHost.class.getSimpleName()))
+                {
+                    vhostRecord = record;
+                    break;
+                }
+            }
+            if(vhostRecord != null)
+            {
+                records.remove(vhostRecord);
+                vhostRecord = enrichInitialVirtualHostRootRecord(vhostRecord);
+                records.add(vhostRecord);
+            }
+            else
+            {
+                // this should be impossible as the converter should always generate a parent record
+                throw new IllegalConfigurationException("Somehow the initial configuration has records but "
+                                                        + "not a VirtualHost. This must be a coding error in Qpid");
+            }
+            addStandardExchangesIfNecessary(records, vhostRecord);
+            enrichWithAuditInformation(records);
+        }
+
+
+        return records.toArray(new ConfiguredObjectRecord[records.size()]);
+    }
+
+    private void enrichWithAuditInformation(final Collection<ConfiguredObjectRecord> records)
+    {
+        List<ConfiguredObjectRecord> replacements = new ArrayList<>(records.size());
+
+        for(ConfiguredObjectRecord record : records)
+        {
+            replacements.add(new ConfiguredObjectRecordImpl(record.getId(), record.getType(),
+                                                            enrichAttributesWithAuditInformation(record.getAttributes()),
+                                                            record.getParents()));
+        }
+        records.clear();
+        records.addAll(replacements);
+    }
+
+    private Map<String, Object> enrichAttributesWithAuditInformation(final Map<String, Object> attributes)
+    {
+        LinkedHashMap<String,Object> enriched = new LinkedHashMap<>(attributes);
+        final AuthenticatedPrincipal currentUser = org.apache.qpid.server.security.SecurityManager.getCurrentUser();
+
+        if(currentUser != null)
+        {
+            enriched.put(ConfiguredObject.LAST_UPDATED_BY, currentUser.getName());
+            enriched.put(ConfiguredObject.CREATED_BY, currentUser.getName());
+        }
+        long currentTime = System.currentTimeMillis();
+        enriched.put(ConfiguredObject.LAST_UPDATED_TIME, currentTime);
+        enriched.put(ConfiguredObject.CREATED_TIME, currentTime);
+
+        return enriched;
+    }
+
+    private void addStandardExchangesIfNecessary(final Collection<ConfiguredObjectRecord> records,
+                                                 final ConfiguredObjectRecord vhostRecord)
+    {
+        addExchangeIfNecessary(ExchangeDefaults.FANOUT_EXCHANGE_CLASS, ExchangeDefaults.FANOUT_EXCHANGE_NAME, records, vhostRecord);
+        addExchangeIfNecessary(ExchangeDefaults.HEADERS_EXCHANGE_CLASS, ExchangeDefaults.HEADERS_EXCHANGE_NAME, records, vhostRecord);
+        addExchangeIfNecessary(ExchangeDefaults.TOPIC_EXCHANGE_CLASS, ExchangeDefaults.TOPIC_EXCHANGE_NAME, records, vhostRecord);
+        addExchangeIfNecessary(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, ExchangeDefaults.DIRECT_EXCHANGE_NAME, records, vhostRecord);
+    }
+
+    private void addExchangeIfNecessary(final String exchangeClass,
+                                        final String exchangeName,
+                                        final Collection<ConfiguredObjectRecord> records,
+                                        final ConfiguredObjectRecord vhostRecord)
+    {
+        boolean found = false;
+
+        for(ConfiguredObjectRecord record : records)
+        {
+            if(Exchange.class.getSimpleName().equals(record.getType())
+               && exchangeName.equals(record.getAttributes().get(ConfiguredObject.NAME)))
+            {
+                found = true;
+                break;
+            }
+        }
+
+        if(!found)
+        {
+            final Map<String, Object> exchangeAttributes = new HashMap<>();
+            exchangeAttributes.put(ConfiguredObject.NAME, exchangeName);
+            exchangeAttributes.put(ConfiguredObject.TYPE, exchangeClass);
+
+            records.add(new ConfiguredObjectRecordImpl(UUID.randomUUID(), Exchange.class.getSimpleName(),
+                                                       exchangeAttributes, Collections.singletonMap(VirtualHost.class.getSimpleName(), vhostRecord.getId())));
+        }
+    }
+
+    protected final Reader getInitialConfigReader() throws IOException
+    {
+        Reader initialConfigReader;
+        if(getVirtualHostInitialConfiguration() != null)
+        {
+            String initialContextString = getVirtualHostInitialConfiguration();
+
+
+            try
+            {
+                URL url = new URL(initialContextString);
+
+                initialConfigReader =new InputStreamReader(url.openStream());
+            }
+            catch (MalformedURLException e)
+            {
+                initialConfigReader = new StringReader(initialContextString);
+            }
+
+        }
+        else
+        {
+            LOGGER.warn("No initial configuration found for the virtual host");
+            initialConfigReader = new StringReader("{}");
+        }
+        return initialConfigReader;
+    }
+
 }

Modified: qpid/trunk/qpid/java/broker-core/src/main/resources/initial-config.json
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/resources/initial-config.json?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/main/resources/initial-config.json (original)
+++ qpid/trunk/qpid/java/broker-core/src/main/resources/initial-config.json Fri Aug 22 19:36:40 2014
@@ -55,9 +55,7 @@
   "virtualhostnodes" : [ {
     "name" : "default",
     "type" : "JSON",
-    "context" : {
-        "virtualhostBlueprint" : "{ \"type\" : \"DERBY\" }"
-    }
+    "virtualHostInitialConfiguration" : "{ \"type\" : \"DERBY\" }"
   } ],
   "plugins" : [ {
     "type" : "MANAGEMENT-HTTP",

Modified: qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java (original)
+++ qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java Fri Aug 22 19:36:40 2014
@@ -91,6 +91,7 @@ public class BrokerTestHelper
         when(broker.getSecurityManager()).thenReturn(new SecurityManager(broker, false));
         when(broker.getObjectFactory()).thenReturn(objectFactory);
         when(broker.getModel()).thenReturn(objectFactory.getModel());
+        when(broker.getModelVersion()).thenReturn(BrokerModel.MODEL_VERSION);
         when(broker.getEventLogger()).thenReturn(eventLogger);
         when(broker.getCategoryClass()).thenReturn(Broker.class);
         when(broker.getParent(SystemConfig.class)).thenReturn(systemConfig);

Modified: qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java (original)
+++ qpid/trunk/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java Fri Aug 22 19:36:40 2014
@@ -139,7 +139,7 @@ public class AbstractStandardVirtualHost
      */
     public void testActivateVHNWithVHBlueprint_StoreHasNoVH() throws Exception
     {
-        DurableConfigurationStore configStore = configStoreThatProducesNoRecords();
+        DurableConfigurationStore configStore = new NullMessageStore() {};
 
         String vhBlueprint = String.format("{ \"type\" : \"%s\", \"name\" : \"%s\"}",
                                            TestMemoryVirtualHost.VIRTUAL_HOST_TYPE,
@@ -162,18 +162,12 @@ public class AbstractStandardVirtualHost
         assertEquals("Unexpected virtual host state", State.ACTIVE, virtualHost.getState());
         assertNotNull("Unexpected virtual host id", virtualHost.getId());
 
-        Map<String, String> updatedContext = node.getContext();
-
-        assertTrue("Context should now have utilised flag", updatedContext.containsKey(
-                AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR));
-        assertEquals("Utilised flag should be true",
-                     Boolean.TRUE.toString(),
-                     updatedContext.get(AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR));
+        assertEquals("Initial configuration should be empty", "{}", node.getVirtualHostInitialConfiguration());
     }
 
     /**
      *  Tests activating a virtualhostnode with blueprint context variable and the
-     *  marked utilised flag.  Config store does not specify a virtualhost.
+     *  but the virtualhostInitialConfiguration set to empty.  Config store does not specify a virtualhost.
      *  Checks virtualhost is not recreated from the blueprint.
      */
     public void testActivateVHNWithVHBlueprintUsed_StoreHasNoVH() throws Exception
@@ -185,12 +179,12 @@ public class AbstractStandardVirtualHost
                                            TEST_VIRTUAL_HOST_NAME);
         Map<String, String> context = new HashMap<>();
         context.put(AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_CONTEXT_VAR, vhBlueprint);
-        context.put(AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR, Boolean.TRUE.toString());
 
         Map<String, Object> nodeAttributes = new HashMap<>();
         nodeAttributes.put(VirtualHostNode.NAME, TEST_VIRTUAL_HOST_NODE_NAME);
         nodeAttributes.put(VirtualHostNode.ID, _nodeId);
         nodeAttributes.put(VirtualHostNode.CONTEXT, context);
+        nodeAttributes.put(VirtualHostNode.VIRTUALHOST_INITIAL_CONFIGURATION, "{}");
 
         VirtualHostNode<?> node = new TestVirtualHostNode(_broker, nodeAttributes, configStore);
         node.open();

Modified: qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java?rev=1619918&r1=1619917&r2=1619918&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java (original)
+++ qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java Fri Aug 22 19:36:40 2014
@@ -350,7 +350,7 @@ public class RestServlet extends Abstrac
         Writer writer = getOutputWriter(request, response);
         ObjectMapper mapper = new ObjectMapper();
         mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
-        mapper.writeValue(writer, output);
+        mapper.writeValue(writer, extractInitialConfig && output.size() == 1 ? output.get(0) : output);
 
         response.setContentType("application/json");
         response.setStatus(HttpServletResponse.SC_OK);



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