You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2011/08/11 19:07:08 UTC

svn commit: r1156680 - in /activemq/activemq-apollo/trunk: apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/ apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ apollo-dto/src/test/java/org/apache/activemq/apollo/dto/ apollo-dto/src/...

Author: chirino
Date: Thu Aug 11 17:07:07 2011
New Revision: 1156680

URL: http://svn.apache.org/viewvc?rev=1156680&view=rev
Log:
Making it possible to configure and update custom services. Also support holding additional configuration elements in key points in the broker configuration model.

Added:
    activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/CustomServiceFactory.scala
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/CustomServiceDTO.java
      - copied, changed from r1156679, activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java
Modified:
    activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ConnectorDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/DurableSubscriptionDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/QueueDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ServiceDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/StringIdDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/TopicDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/VirtualHostDTO.java
    activemq/activemq-apollo/trunk/apollo-dto/src/test/java/org/apache/activemq/apollo/dto/XmlCodecTest.java
    activemq/activemq-apollo/trunk/apollo-dto/src/test/resources/org/apache/activemq/apollo/dto/XmlCodecTest.xml

Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/Broker.scala Thu Aug 11 17:07:07 2011
@@ -33,6 +33,7 @@ import FileSupport._
 import management.ManagementFactory
 import org.apache.activemq.apollo.dto._
 import javax.management.ObjectName
+import org.fusesource.hawtdispatch.TaskTracker._
 
 /**
  * <p>
@@ -247,7 +248,7 @@ class Broker() extends BaseService {
   var security_log:Log  = Broker
   var connection_log:Log = Broker
   var console_log:Log = Broker
-  var services = List[Service]()
+  var services = Map[String, (CustomServiceDTO, Service)]()
 
   override def toString() = "broker: "+id
 
@@ -296,10 +297,10 @@ class Broker() extends BaseService {
     val tracker = new LoggingTracker("broker shutdown", console_log, SERVICE_TIMEOUT)
 
     // Stop the services...
-    services.foreach( x=>
-      tracker.stop(x)
+    services.values.foreach( x=>
+      tracker.stop(x._2)
     )
-    services = Nil
+    services = Map()
 
     // Stop accepting connections..
     connectors.values.foreach( x=>
@@ -439,32 +440,50 @@ class Broker() extends BaseService {
       }
     }
 
-    val set1 = (services.map{x => x.getClass.getName}).toSet
-    diff(set1, config.services.toSet) match { case (added, updated, removed) =>
+    val t:Seq[(String, CustomServiceDTO)] = asScalaBuffer(config.services).map(x => (x.id ->x) )
+    val services_config = Map(t: _*)
+    diff(services.keySet, services_config.keySet) match { case (added, updated, removed) =>
       removed.foreach { id =>
-        for( service <- services.find(_.getClass.getName == id) ) {
-          services = services.filterNot( _ == service )
-          tracker.stop(service)
+        for( service <- services.get(id) ) {
+          services -= id
+          tracker.stop(service._2)
         }
       }
 
-      // Not much to do on updates..
-
-      added.foreach { clazz=>
-
-        val service = Broker.class_loader.loadClass(clazz).newInstance().asInstanceOf[Service]
+      // Handle the updates.
+      added.foreach { id=>
+        for( new_dto <- services_config.get(id); (old_dto, service) <- services.get(id) ) {
+          if( new_dto != old_dto ) {
 
-        // Try to inject the broker via reflection..
-        type BrokerAware = {var broker: Broker}
-        try {
-          service.asInstanceOf[BrokerAware].broker = this
-        } catch {
-          case _ =>
+            // restart.. needed.
+            val task = tracker.task("restart "+service)
+            service.stop(dispatch_queue.runnable {
+
+              // create with the new config..
+              val service = CustomServiceFactory.create(this, new_dto)
+              if( service == null ) {
+                console_log.warn("Could not create service: "+new_dto.id);
+              } else {
+                // start it again..
+                services += new_dto.id -> (new_dto, service)
+                service.start(task)
+              }
+            })
+          }
         }
+      }
 
-        services ::= service
-
-        tracker.start(service)
+      // Create the new services..
+      added.foreach { id=>
+        for( dto <- services_config.get(id) ) {
+          val service = CustomServiceFactory.create(this, dto)
+          if( service == null ) {
+            console_log.warn("Could not create service: "+dto.id);
+          } else {
+            services += dto.id -> (dto, service)
+            tracker.start(service)
+          }
+        }
       }
     }
 

Added: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/CustomServiceFactory.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/CustomServiceFactory.scala?rev=1156680&view=auto
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/CustomServiceFactory.scala (added)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/CustomServiceFactory.scala Thu Aug 11 17:07:07 2011
@@ -0,0 +1,86 @@
+/**
+ * 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.activemq.apollo.broker
+
+import org.apache.activemq.apollo.dto.CustomServiceDTO
+import org.apache.activemq.apollo.util.{Log, Service, ClassFinder}
+
+/**
+ * <p>
+ * </p>
+ *
+ * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
+ */
+object CustomServiceFactory {
+
+  trait Provider {
+    def create(broker:Broker, dto:CustomServiceDTO):Service
+  }
+
+  val providers = new ClassFinder[Provider]("META-INF/services/org.apache.activemq.apollo/custom-service-factory.index",classOf[Provider])
+
+  def create(broker:Broker, dto:CustomServiceDTO):Service = {
+    if( dto == null ) {
+      return null
+    }
+    providers.singletons.foreach { provider=>
+      val service = provider.create(broker, dto)
+      if( service!=null ) {
+        return service;
+      }
+    }
+    return null
+  }
+
+}
+
+object ReflectiveCustomServiceFactory extends CustomServiceFactory.Provider with Log {
+
+  def create(broker: Broker, dto: CustomServiceDTO): Service = {
+    if( dto.getClass != classOf[CustomServiceDTO] ) {
+      // don't process sub classes of CustomServiceDTO
+      return null;
+    }
+
+    val service = try {
+      Broker.class_loader.loadClass(dto.kind).newInstance().asInstanceOf[Service]
+    } catch {
+      case e:Throwable =>
+        debug(e, "could not create instance of %d for service %s", dto.kind, dto.id)
+        return null;
+    }
+
+    // Try to inject the broker via reflection..
+    try {
+      type BrokerAware = {var broker: Broker}
+      service.asInstanceOf[BrokerAware].broker = broker
+    } catch {
+      case _ =>
+    }
+
+    // Try to inject the config via reflection..
+    try {
+      type ConfigAware = {var config: CustomServiceDTO}
+      service.asInstanceOf[ConfigAware].config = dto
+    } catch {
+      case _ =>
+    }
+
+    service
+
+  }
+}
\ No newline at end of file

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/BrokerDTO.java Thu Aug 11 17:07:07 2011
@@ -78,7 +78,7 @@ public class BrokerDTO {
      * starts/stops.
      */
     @XmlElement(name="service")
-    public List<String> services = new ArrayList<String>();
+    public List<CustomServiceDTO> services = new ArrayList<CustomServiceDTO>();
 
     @Deprecated
     @XmlAttribute(name="sticky_dispatching")
@@ -90,4 +90,58 @@ public class BrokerDTO {
      */
     @XmlAttribute(name="validation")
     public String validation;
+
+    /**
+     * To hold any other non-matching XML elements
+     */
+    @XmlAnyElement(lax=true)
+    public List<Object> other = new ArrayList<Object>();
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof BrokerDTO)) return false;
+
+        BrokerDTO brokerDTO = (BrokerDTO) o;
+
+        if (acl != null ? !acl.equals(brokerDTO.acl) : brokerDTO.acl != null) return false;
+        if (authentication != null ? !authentication.equals(brokerDTO.authentication) : brokerDTO.authentication != null)
+            return false;
+        if (client_address != null ? !client_address.equals(brokerDTO.client_address) : brokerDTO.client_address != null)
+            return false;
+        if (connectors != null ? !connectors.equals(brokerDTO.connectors) : brokerDTO.connectors != null) return false;
+        if (key_storage != null ? !key_storage.equals(brokerDTO.key_storage) : brokerDTO.key_storage != null)
+            return false;
+        if (log_category != null ? !log_category.equals(brokerDTO.log_category) : brokerDTO.log_category != null)
+            return false;
+        if (notes != null ? !notes.equals(brokerDTO.notes) : brokerDTO.notes != null) return false;
+        if (other != null ? !other.equals(brokerDTO.other) : brokerDTO.other != null) return false;
+        if (services != null ? !services.equals(brokerDTO.services) : brokerDTO.services != null) return false;
+        if (sticky_dispatching != null ? !sticky_dispatching.equals(brokerDTO.sticky_dispatching) : brokerDTO.sticky_dispatching != null)
+            return false;
+        if (validation != null ? !validation.equals(brokerDTO.validation) : brokerDTO.validation != null) return false;
+        if (virtual_hosts != null ? !virtual_hosts.equals(brokerDTO.virtual_hosts) : brokerDTO.virtual_hosts != null)
+            return false;
+        if (web_admins != null ? !web_admins.equals(brokerDTO.web_admins) : brokerDTO.web_admins != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = notes != null ? notes.hashCode() : 0;
+        result = 31 * result + (virtual_hosts != null ? virtual_hosts.hashCode() : 0);
+        result = 31 * result + (connectors != null ? connectors.hashCode() : 0);
+        result = 31 * result + (client_address != null ? client_address.hashCode() : 0);
+        result = 31 * result + (key_storage != null ? key_storage.hashCode() : 0);
+        result = 31 * result + (acl != null ? acl.hashCode() : 0);
+        result = 31 * result + (web_admins != null ? web_admins.hashCode() : 0);
+        result = 31 * result + (authentication != null ? authentication.hashCode() : 0);
+        result = 31 * result + (log_category != null ? log_category.hashCode() : 0);
+        result = 31 * result + (services != null ? services.hashCode() : 0);
+        result = 31 * result + (sticky_dispatching != null ? sticky_dispatching.hashCode() : 0);
+        result = 31 * result + (validation != null ? validation.hashCode() : 0);
+        result = 31 * result + (other != null ? other.hashCode() : 0);
+        return result;
+    }
 }

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ConnectorDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ConnectorDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ConnectorDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ConnectorDTO.java Thu Aug 11 17:07:07 2011
@@ -54,6 +54,12 @@ public class ConnectorDTO extends Servic
     @XmlElement(name="acl")
     public ConnectorAclDTO acl;
 
+    /**
+     * To hold any other non-matching XML elements
+     */
+    @XmlAnyElement(lax=true)
+    public List<Object> other = new ArrayList<Object>();
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -65,6 +71,7 @@ public class ConnectorDTO extends Servic
         if (bind != null ? !bind.equals(that.bind) : that.bind != null) return false;
         if (connection_limit != null ? !connection_limit.equals(that.connection_limit) : that.connection_limit != null)
             return false;
+        if (other != null ? !other.equals(that.other) : that.other != null) return false;
         if (protocol != null ? !protocol.equals(that.protocol) : that.protocol != null) return false;
         if (protocols != null ? !protocols.equals(that.protocols) : that.protocols != null) return false;
 
@@ -78,6 +85,7 @@ public class ConnectorDTO extends Servic
         result = 31 * result + (connection_limit != null ? connection_limit.hashCode() : 0);
         result = 31 * result + (protocols != null ? protocols.hashCode() : 0);
         result = 31 * result + (acl != null ? acl.hashCode() : 0);
+        result = 31 * result + (other != null ? other.hashCode() : 0);
         return result;
     }
 }
\ No newline at end of file

Copied: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/CustomServiceDTO.java (from r1156679, activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java)
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/CustomServiceDTO.java?p2=activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/CustomServiceDTO.java&p1=activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java&r1=1156679&r2=1156680&rev=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/CustomServiceDTO.java Thu Aug 11 17:07:07 2011
@@ -16,28 +16,51 @@
  */
 package org.apache.activemq.apollo.dto;
 
-import org.codehaus.jackson.annotate.JsonTypeInfo;
+
 
 import javax.xml.bind.annotation.*;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
  */
-@XmlType (name = "protocol_type")
-@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
-@XmlRootElement(name="protocol")
+@XmlRootElement(name="service")
 @XmlAccessorType(XmlAccessType.FIELD)
-public class ProtocolDTO {
+public class CustomServiceDTO extends ServiceDTO {
+
+    /**
+     * The class name of the service.
+     */
+    @XmlAttribute
+    public String kind;
+
+    /**
+     * To hold any other non-matching XML elements
+     */
+    @XmlAnyElement(lax=true)
+    public List<Object> other = new ArrayList<Object>();
+
 
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (!(o instanceof ProtocolDTO)) return false;
+        if (!(o instanceof CustomServiceDTO)) return false;
+        if (!super.equals(o)) return false;
+
+        CustomServiceDTO that = (CustomServiceDTO) o;
+
+        if (kind != null ? !kind.equals(that.kind) : that.kind != null) return false;
+        if (other != null ? !other.equals(that.other) : that.other != null) return false;
+
         return true;
     }
 
     @Override
     public int hashCode() {
-        return 31;
+        int result = super.hashCode();
+        result = 31 * result + (kind != null ? kind.hashCode() : 0);
+        result = 31 * result + (other != null ? other.hashCode() : 0);
+        return result;
     }
-}
+}
\ No newline at end of file

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/DurableSubscriptionDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/DurableSubscriptionDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/DurableSubscriptionDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/DurableSubscriptionDTO.java Thu Aug 11 17:07:07 2011
@@ -19,6 +19,8 @@ package org.apache.activemq.apollo.dto;
 
 
 import javax.xml.bind.annotation.*;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
@@ -47,5 +49,35 @@ public class DurableSubscriptionDTO exte
     @XmlAttribute
     public String selector;
 
+    /**
+     * To hold any other non-matching XML elements
+     */
+    @XmlAnyElement(lax=true)
+    public List<Object> other = new ArrayList<Object>();
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof DurableSubscriptionDTO)) return false;
+        if (!super.equals(o)) return false;
+
+        DurableSubscriptionDTO that = (DurableSubscriptionDTO) o;
+
+        if (id_regex != null ? !id_regex.equals(that.id_regex) : that.id_regex != null) return false;
+        if (other != null ? !other.equals(that.other) : that.other != null) return false;
+        if (selector != null ? !selector.equals(that.selector) : that.selector != null) return false;
+        if (topic != null ? !topic.equals(that.topic) : that.topic != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (id_regex != null ? id_regex.hashCode() : 0);
+        result = 31 * result + (topic != null ? topic.hashCode() : 0);
+        result = 31 * result + (selector != null ? selector.hashCode() : 0);
+        result = 31 * result + (other != null ? other.hashCode() : 0);
+        return result;
+    }
 }

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ProtocolDTO.java Thu Aug 11 17:07:07 2011
@@ -19,6 +19,8 @@ package org.apache.activemq.apollo.dto;
 import org.codehaus.jackson.annotate.JsonTypeInfo;
 
 import javax.xml.bind.annotation.*;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
@@ -29,15 +31,26 @@ import javax.xml.bind.annotation.*;
 @XmlAccessorType(XmlAccessType.FIELD)
 public class ProtocolDTO {
 
+    /**
+     * To hold any other non-matching XML elements
+     */
+    @XmlAnyElement(lax=true)
+    public List<Object> other = new ArrayList<Object>();
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (!(o instanceof ProtocolDTO)) return false;
+
+        ProtocolDTO that = (ProtocolDTO) o;
+
+        if (other != null ? !other.equals(that.other) : that.other != null) return false;
+
         return true;
     }
 
     @Override
     public int hashCode() {
-        return 31;
+        return other != null ? other.hashCode() : 0;
     }
 }

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/QueueDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/QueueDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/QueueDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/QueueDTO.java Thu Aug 11 17:07:07 2011
@@ -19,6 +19,8 @@ package org.apache.activemq.apollo.dto;
 
 
 import javax.xml.bind.annotation.*;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
@@ -84,4 +86,49 @@ public class QueueDTO extends StringIdDT
     @XmlElement(name="acl")
     public QueueAclDTO acl;
 
+    /**
+     * To hold any other non-matching XML elements
+     */
+    @XmlAnyElement(lax=true)
+    public List<Object> other = new ArrayList<Object>();
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof QueueDTO)) return false;
+        if (!super.equals(o)) return false;
+
+        QueueDTO queueDTO = (QueueDTO) o;
+
+        if (acl != null ? !acl.equals(queueDTO.acl) : queueDTO.acl != null) return false;
+        if (auto_delete_after != null ? !auto_delete_after.equals(queueDTO.auto_delete_after) : queueDTO.auto_delete_after != null)
+            return false;
+        if (consumer_buffer != null ? !consumer_buffer.equals(queueDTO.consumer_buffer) : queueDTO.consumer_buffer != null)
+            return false;
+        if (other != null ? !other.equals(queueDTO.other) : queueDTO.other != null) return false;
+        if (persistent != null ? !persistent.equals(queueDTO.persistent) : queueDTO.persistent != null) return false;
+        if (queue_buffer != null ? !queue_buffer.equals(queueDTO.queue_buffer) : queueDTO.queue_buffer != null)
+            return false;
+        if (swap != null ? !swap.equals(queueDTO.swap) : queueDTO.swap != null) return false;
+        if (swap_range_size != null ? !swap_range_size.equals(queueDTO.swap_range_size) : queueDTO.swap_range_size != null)
+            return false;
+        if (unified != null ? !unified.equals(queueDTO.unified) : queueDTO.unified != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (auto_delete_after != null ? auto_delete_after.hashCode() : 0);
+        result = 31 * result + (unified != null ? unified.hashCode() : 0);
+        result = 31 * result + (queue_buffer != null ? queue_buffer.hashCode() : 0);
+        result = 31 * result + (consumer_buffer != null ? consumer_buffer.hashCode() : 0);
+        result = 31 * result + (persistent != null ? persistent.hashCode() : 0);
+        result = 31 * result + (swap != null ? swap.hashCode() : 0);
+        result = 31 * result + (swap_range_size != null ? swap_range_size.hashCode() : 0);
+        result = 31 * result + (acl != null ? acl.hashCode() : 0);
+        result = 31 * result + (other != null ? other.hashCode() : 0);
+        return result;
+    }
 }

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ServiceDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ServiceDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ServiceDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/ServiceDTO.java Thu Aug 11 17:07:07 2011
@@ -26,9 +26,8 @@ import javax.xml.bind.annotation.XmlRoot
 /**
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
  */
-@XmlRootElement(name="id")
 @XmlAccessorType(XmlAccessType.FIELD)
-public class ServiceDTO extends StringIdDTO {
+abstract public class ServiceDTO extends StringIdDTO {
 
     /**
      * Should this service be running?
@@ -36,5 +35,23 @@ public class ServiceDTO extends StringId
     @XmlAttribute
     public Boolean enabled;
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof ServiceDTO)) return false;
+        if (!super.equals(o)) return false;
 
+        ServiceDTO that = (ServiceDTO) o;
+
+        if (enabled != null ? !enabled.equals(that.enabled) : that.enabled != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (enabled != null ? enabled.hashCode() : 0);
+        return result;
+    }
 }
\ No newline at end of file

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/StringIdDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/StringIdDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/StringIdDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/StringIdDTO.java Thu Aug 11 17:07:07 2011
@@ -26,7 +26,7 @@ import java.util.List;
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
  */
 @XmlAccessorType(XmlAccessType.FIELD)
-public class StringIdDTO {
+abstract public class StringIdDTO {
 
     /**
      * A unique id of the object within it's container
@@ -40,4 +40,20 @@ public class StringIdDTO {
         this.id = id;
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof StringIdDTO)) return false;
+
+        StringIdDTO that = (StringIdDTO) o;
+
+        if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return id != null ? id.hashCode() : 0;
+    }
 }
\ No newline at end of file

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/TopicDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/TopicDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/TopicDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/TopicDTO.java Thu Aug 11 17:07:07 2011
@@ -19,6 +19,8 @@ package org.apache.activemq.apollo.dto;
 
 
 import javax.xml.bind.annotation.*;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
@@ -44,4 +46,37 @@ public class TopicDTO extends StringIdDT
     @XmlElement(name="acl")
     public TopicAclDTO acl;
 
+    /**
+     * To hold any other non-matching XML elements
+     */
+    @XmlAnyElement(lax=true)
+    public List<Object> other = new ArrayList<Object>();
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof TopicDTO)) return false;
+        if (!super.equals(o)) return false;
+
+        TopicDTO topicDTO = (TopicDTO) o;
+
+        if (acl != null ? !acl.equals(topicDTO.acl) : topicDTO.acl != null) return false;
+        if (auto_delete_after != null ? !auto_delete_after.equals(topicDTO.auto_delete_after) : topicDTO.auto_delete_after != null)
+            return false;
+        if (other != null ? !other.equals(topicDTO.other) : topicDTO.other != null) return false;
+        if (slow_consumer_policy != null ? !slow_consumer_policy.equals(topicDTO.slow_consumer_policy) : topicDTO.slow_consumer_policy != null)
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (auto_delete_after != null ? auto_delete_after.hashCode() : 0);
+        result = 31 * result + (slow_consumer_policy != null ? slow_consumer_policy.hashCode() : 0);
+        result = 31 * result + (acl != null ? acl.hashCode() : 0);
+        result = 31 * result + (other != null ? other.hashCode() : 0);
+        return result;
+    }
 }

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/VirtualHostDTO.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/VirtualHostDTO.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/VirtualHostDTO.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/main/java/org/apache/activemq/apollo/dto/VirtualHostDTO.java Thu Aug 11 17:07:07 2011
@@ -17,6 +17,7 @@
 package org.apache.activemq.apollo.dto;
 
 import java.util.ArrayList;
+import java.util.List;
 
 import javax.xml.bind.annotation.*;
 
@@ -81,4 +82,58 @@ public class VirtualHostDTO extends Serv
 
     @XmlElement(name="log_category")
     public LogCategoryDTO log_category;
+
+    /**
+     * To hold any other non-matching XML elements
+     */
+    @XmlAnyElement(lax=true)
+    public List<Object> other = new ArrayList<Object>();
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof VirtualHostDTO)) return false;
+        if (!super.equals(o)) return false;
+
+        VirtualHostDTO that = (VirtualHostDTO) o;
+
+        if (acl != null ? !acl.equals(that.acl) : that.acl != null) return false;
+        if (authentication != null ? !authentication.equals(that.authentication) : that.authentication != null)
+            return false;
+        if (auto_create_destinations != null ? !auto_create_destinations.equals(that.auto_create_destinations) : that.auto_create_destinations != null)
+            return false;
+        if (dsubs != null ? !dsubs.equals(that.dsubs) : that.dsubs != null) return false;
+        if (host_names != null ? !host_names.equals(that.host_names) : that.host_names != null) return false;
+        if (log_category != null ? !log_category.equals(that.log_category) : that.log_category != null) return false;
+        if (other != null ? !other.equals(that.other) : that.other != null) return false;
+        if (purge_on_startup != null ? !purge_on_startup.equals(that.purge_on_startup) : that.purge_on_startup != null)
+            return false;
+        if (queues != null ? !queues.equals(that.queues) : that.queues != null) return false;
+        if (regroup_connections != null ? !regroup_connections.equals(that.regroup_connections) : that.regroup_connections != null)
+            return false;
+        if (router != null ? !router.equals(that.router) : that.router != null) return false;
+        if (store != null ? !store.equals(that.store) : that.store != null) return false;
+        if (topics != null ? !topics.equals(that.topics) : that.topics != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode();
+        result = 31 * result + (host_names != null ? host_names.hashCode() : 0);
+        result = 31 * result + (store != null ? store.hashCode() : 0);
+        result = 31 * result + (auto_create_destinations != null ? auto_create_destinations.hashCode() : 0);
+        result = 31 * result + (purge_on_startup != null ? purge_on_startup.hashCode() : 0);
+        result = 31 * result + (topics != null ? topics.hashCode() : 0);
+        result = 31 * result + (queues != null ? queues.hashCode() : 0);
+        result = 31 * result + (dsubs != null ? dsubs.hashCode() : 0);
+        result = 31 * result + (regroup_connections != null ? regroup_connections.hashCode() : 0);
+        result = 31 * result + (acl != null ? acl.hashCode() : 0);
+        result = 31 * result + (authentication != null ? authentication.hashCode() : 0);
+        result = 31 * result + (router != null ? router.hashCode() : 0);
+        result = 31 * result + (log_category != null ? log_category.hashCode() : 0);
+        result = 31 * result + (other != null ? other.hashCode() : 0);
+        return result;
+    }
 }

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/test/java/org/apache/activemq/apollo/dto/XmlCodecTest.java
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/test/java/org/apache/activemq/apollo/dto/XmlCodecTest.java?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/test/java/org/apache/activemq/apollo/dto/XmlCodecTest.java (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/test/java/org/apache/activemq/apollo/dto/XmlCodecTest.java Thu Aug 11 17:07:07 2011
@@ -39,6 +39,8 @@ public class XmlCodecTest {
         BrokerDTO dto = XmlCodec.decode(BrokerDTO.class, resource("XmlCodecTest.xml"));
         assertNotNull(dto);
 
+        assertEquals(1, dto.other.size());
+
         VirtualHostDTO host = dto.virtual_hosts.get(0);
         assertNotNull(host.acl);
         assertEquals("vh-local", host.id);

Modified: activemq/activemq-apollo/trunk/apollo-dto/src/test/resources/org/apache/activemq/apollo/dto/XmlCodecTest.xml
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-dto/src/test/resources/org/apache/activemq/apollo/dto/XmlCodecTest.xml?rev=1156680&r1=1156679&r2=1156680&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-dto/src/test/resources/org/apache/activemq/apollo/dto/XmlCodecTest.xml (original)
+++ activemq/activemq-apollo/trunk/apollo-dto/src/test/resources/org/apache/activemq/apollo/dto/XmlCodecTest.xml Thu Aug 11 17:07:07 2011
@@ -34,4 +34,6 @@
 
   </virtual_host>
 
+  <topic id="topic1"/>
+
 </broker>