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 2009/06/19 13:27:34 UTC
svn commit: r786459 - in /activemq/sandbox/activemq-flow:
activemq-broker/src/main/java/org/apache/activemq/apollo/broker/
activemq-broker/src/main/java/org/apache/activemq/filter/
activemq-broker/src/test/java/org/apache/activemq/filter/ activemq-util...
Author: chirino
Date: Fri Jun 19 11:27:33 2009
New Revision: 786459
URL: http://svn.apache.org/viewvc?rev=786459&view=rev
Log:
ported the 5.x DestinationMap impl over.
Added:
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/AnyChildDestinationNode.java
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/CompositeDestinationFilter.java (with props)
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationFilter.java (with props)
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMap.java (with props)
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapEntry.java
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapNode.java (with props)
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationNode.java
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationPath.java (with props)
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/PrefixDestinationFilter.java (with props)
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/SimpleDestinationFilter.java (with props)
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/WildcardDestinationFilter.java (with props)
activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/
activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapMemoryTest.java
activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTempDestinationTest.java
activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTest.java (with props)
Modified:
activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/apollo/broker/Destination.java
activemq/sandbox/activemq-flow/activemq-util/src/main/java/org/apache/activemq/protobuf/Buffer.java
activemq/sandbox/activemq-flow/webgen/src/todo.page
Modified: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/apollo/broker/Destination.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/apollo/broker/Destination.java?rev=786459&r1=786458&r2=786459&view=diff
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/apollo/broker/Destination.java (original)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/apollo/broker/Destination.java Fri Jun 19 11:27:33 2009
@@ -75,17 +75,10 @@
setDomain(new AsciiBuffer(domain));
}
- // public ActiveMQDestination asActiveMQDestination() {
- // if(domain.equals(Router.TOPIC_DOMAIN))
- // {
- // return new ActiveMQTopic(name.toString());
- // }
- // else if(domain.equals(Router.QUEUE_DOMAIN))
- // {
- // return new ActiveMQQueue(name.toString());
- // }
- // return null;
- // }
+ @Override
+ public String toString() {
+ return ""+domain+":"+name;
+ }
}
public class MultiDestination implements Destination {
@@ -117,11 +110,11 @@
{
destinations.remove(d);
}
-
- // public ActiveMQDestination asActiveMQDestination() {
- // throw new UnsupportedOperationException("Not yet implemented");
- // }
-
+
+ @Override
+ public String toString() {
+ return destinations.toString();
+ }
}
}
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/AnyChildDestinationNode.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/AnyChildDestinationNode.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/AnyChildDestinationNode.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/AnyChildDestinationNode.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,120 @@
+/**
+ * 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.filter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * An implementation of {@link DestinationNode} which navigates all the children of the given node
+ * ignoring the name of the current path (so for navigating using * in a wildcard).
+ *
+ * @version $Revision: 563921 $
+ */
+public class AnyChildDestinationNode<Value> implements DestinationNode<Value> {
+ private DestinationNode<Value> node;
+
+ public AnyChildDestinationNode(DestinationNode<Value> node) {
+ this.node = node;
+ }
+
+ public void appendMatchingValues(Set<Value> answer, String[] paths, int startIndex) {
+ for (DestinationNode<Value> child : getChildNodes()) {
+ child.appendMatchingValues(answer, paths, startIndex);
+ }
+ }
+
+
+ public void appendMatchingWildcards(Set<Value> answer, String[] paths, int startIndex) {
+ for (DestinationNode<Value> child : getChildNodes()) {
+ child.appendMatchingWildcards(answer, paths, startIndex);
+ }
+ }
+
+
+ public void appendDescendantValues(Set<Value> answer) {
+ for (DestinationNode<Value> child : getChildNodes()) {
+ child.appendDescendantValues(answer);
+ }
+ }
+
+ public DestinationNode<Value> getChild(String path) {
+ final Collection<DestinationNode<Value>> list = new ArrayList<DestinationNode<Value>>();
+ for (DestinationNode<Value> child : getChildNodes()) {
+ DestinationNode<Value> answer = child.getChild(path);
+ if (answer != null) {
+ list.add(answer);
+ }
+ }
+ if (!list.isEmpty()) {
+ return new AnyChildDestinationNode<Value>(this) {
+ protected Collection<DestinationNode<Value>> getChildNodes() {
+ return list;
+ }
+ };
+ }
+ return null;
+ }
+
+ public Collection<Value> getDesendentValues() {
+ Collection<Value> answer = new ArrayList<Value>();
+ for (DestinationNode<Value> child : getChildNodes()) {
+ answer.addAll(child.getDesendentValues());
+ }
+ return answer;
+ }
+
+ public Collection<Value> getValues() {
+ Collection<Value> answer = new ArrayList<Value>();
+ for (DestinationNode<Value> child : getChildNodes()) {
+ answer.addAll(child.getValues());
+ }
+ return answer;
+ }
+
+
+ public Collection<DestinationNode<Value>> getChildren() {
+ Collection<DestinationNode<Value>> answer = new ArrayList<DestinationNode<Value>> ();
+ for (DestinationNode<Value> child : getChildNodes()) {
+ answer.addAll(child.getChildren());
+ }
+ return answer;
+ }
+
+ public Collection<Value> removeDesendentValues() {
+ Collection<Value> answer = new ArrayList<Value>();
+ for (DestinationNode<Value> child : getChildNodes()) {
+ answer.addAll(child.removeDesendentValues());
+ }
+ return answer;
+ }
+
+ public Collection<Value> removeValues() {
+ Collection<Value> answer = new ArrayList<Value>();
+ for (DestinationNode<Value> child : getChildNodes()) {
+ answer.addAll(child.removeValues());
+ }
+ return answer;
+ }
+
+ protected Collection<DestinationNode<Value>> getChildNodes() {
+ return node.getChildren();
+ }
+}
+
+
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/CompositeDestinationFilter.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/CompositeDestinationFilter.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/CompositeDestinationFilter.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/CompositeDestinationFilter.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,54 @@
+/**
+ * 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.filter;
+
+import java.util.Collection;
+
+import org.apache.activemq.apollo.broker.Destination;
+
+
+/**
+ * A {@link DestinationFilter} used for composite destinations
+ *
+ * @version $Revision: 1.3 $
+ */
+public class CompositeDestinationFilter extends DestinationFilter {
+
+ private DestinationFilter filters[];
+
+ public CompositeDestinationFilter(Destination destination) {
+ Collection<Destination> destinations = destination.getDestinations();
+ filters = new DestinationFilter[destinations.size()];
+ int i=0;
+ for (Destination childDestination : destinations) {
+ filters[i++] = DestinationFilter.parseFilter(childDestination);
+ }
+ }
+
+ public boolean matches(Destination destination) throws FilterException {
+ for (int i = 0; i < filters.length; i++) {
+ if (filters[i].matches(destination)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isWildcard() {
+ return true;
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/CompositeDestinationFilter.java
------------------------------------------------------------------------------
svn:executable = *
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationFilter.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationFilter.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationFilter.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationFilter.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,69 @@
+/**
+ * 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.filter;
+
+import java.util.Collection;
+
+import org.apache.activemq.apollo.broker.Destination;
+
+
+/**
+ * Represents a filter which only operates on Destinations
+ *
+ * @version $Revision: 1.3 $
+ */
+public abstract class DestinationFilter implements BooleanExpression {
+
+ public static final String ANY_DESCENDENT = ">";
+ public static final String ANY_CHILD = "*";
+
+ public boolean matches(MessageEvaluationContext message) throws FilterException {
+ Destination destination = message.getDestination();
+ return matches(destination);
+ }
+ public Object evaluate(MessageEvaluationContext message) throws FilterException {
+ return matches(message) ? Boolean.TRUE : Boolean.FALSE;
+ }
+
+ public abstract boolean matches(Destination destination) throws FilterException;
+
+ public static DestinationFilter parseFilter(Destination destination) {
+ Collection<Destination> destinations = destination.getDestinations();
+ if (destinations!=null) {
+ return new CompositeDestinationFilter(destination);
+ }
+ String[] paths = DestinationPath.getDestinationPaths(destination);
+ int idx = paths.length - 1;
+ if (idx >= 0) {
+ String lastPath = paths[idx];
+ if (lastPath.equals(ANY_DESCENDENT)) {
+ return new PrefixDestinationFilter(paths);
+ } else {
+ while (idx >= 0) {
+ lastPath = paths[idx--];
+ if (lastPath.equals(ANY_CHILD)) {
+ return new WildcardDestinationFilter(paths);
+ }
+ }
+ }
+ }
+
+ // if none of the paths contain a wildcard then use equality
+ return new SimpleDestinationFilter(destination);
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationFilter.java
------------------------------------------------------------------------------
svn:executable = *
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMap.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMap.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMap.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMap.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,163 @@
+/**
+ * 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.filter;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.activemq.apollo.broker.Destination;
+
+/**
+ * A Map-like data structure allowing values to be indexed by
+ * {@link Destination} and retrieved by destination - supporting both *
+ * and > style of wildcard as well as composite destinations. <br>
+ * This class assumes that the index changes rarely but that fast lookup into
+ * the index is required. So this class maintains a pre-calculated index for
+ * destination steps. So looking up the values for "TEST.*" or "*.TEST" will be
+ * pretty fast. <br>
+ * Looking up of a value could return a single value or a List of matching
+ * values if a wildcard or composite destination is used.
+ *
+ * @version $Revision: 1.3 $
+ */
+public class DestinationMap<Value> {
+ protected static final String ANY_DESCENDENT = DestinationFilter.ANY_DESCENDENT;
+ protected static final String ANY_CHILD = DestinationFilter.ANY_CHILD;
+
+ private DestinationMapNode<Value> root = new DestinationMapNode<Value>(null);
+
+ /**
+ * Looks up the value(s) matching the given Destination key. For simple
+ * destinations this is typically a List of one single value, for wild cards
+ * or composite destinations this will typically be a List of matching
+ * values.
+ *
+ * @param key the destination to lookup
+ * @return a List of matching values or an empty list if there are no
+ * matching values.
+ */
+ public synchronized Set<Value> get(Destination key) {
+ Collection<Destination> destinations = key.getDestinations();
+ if (destinations!=null) {
+ HashSet<Value> answer = new HashSet<Value>(destinations.size());
+ for (Destination childDestination : destinations) {
+ answer.addAll(get(childDestination));
+ }
+ return answer;
+ }
+ return findWildcardMatches(key);
+ }
+
+ public synchronized void put(Destination key, Value value) {
+ Collection<Destination> destinations = key.getDestinations();
+ if (destinations!=null) {
+ for (Destination childDestination : destinations) {
+ put(childDestination, value);
+ }
+ return;
+ }
+ String[] paths = DestinationPath.getDestinationPaths(key);
+ getRootNode(key).add(paths, 0, value);
+ }
+
+ /**
+ * Removes the value from the associated destination
+ */
+ public synchronized void remove(Destination key, Value value) {
+ Collection<Destination> destinations = key.getDestinations();
+ if (destinations!=null) {
+ for (Destination childDestination : destinations) {
+ remove(childDestination, value);
+ }
+ return;
+ }
+ String[] paths = DestinationPath.getDestinationPaths(key);
+ getRootNode(key).remove(paths, 0, value);
+
+ }
+
+ public DestinationMapNode<Value> getRootNode() {
+ return root;
+ }
+
+ // Implementation methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * A helper method to allow the destination map to be populated from a
+ * dependency injection framework such as Spring
+ */
+ @SuppressWarnings("unchecked")
+ protected void setEntries(List<DestinationMapEntry> entries) {
+ for (DestinationMapEntry entry : entries) {
+ put(entry.getDestination(), (Value) entry);
+ }
+ }
+
+ protected Set<Value> findWildcardMatches(Destination key) {
+ String[] paths = DestinationPath.getDestinationPaths(key);
+ HashSet<Value> answer = new HashSet<Value>();
+ getRootNode(key).appendMatchingValues(answer, paths, 0);
+ return answer;
+ }
+
+ /**
+ * @param key
+ * @return
+ */
+ public Set<Value> removeAll(Destination key) {
+ HashSet<Value> rc = new HashSet<Value>();
+ Collection<Destination> destinations = key.getDestinations();
+ if (destinations!=null) {
+ for (Destination childDestination : destinations) {
+ rc.addAll(removeAll(childDestination));
+ }
+ return rc;
+ }
+ String[] paths = DestinationPath.getDestinationPaths(key);
+ getRootNode(key).removeAll(rc, paths, 0);
+ return rc;
+ }
+
+ /**
+ * Returns the value which matches the given destination or null if there is
+ * no matching value. If there are multiple values, the results are sorted
+ * and the last item (the biggest) is returned.
+ *
+ * @param destination the destination to find the value for
+ * @return the largest matching value or null if no value matches
+ */
+ public Value chooseValue(Destination destination) {
+ Set<Value> set = get(destination);
+ if (set == null || set.isEmpty()) {
+ return null;
+ }
+ SortedSet<Value> sortedSet = new TreeSet<Value>(set);
+ return sortedSet.last();
+ }
+
+ /**
+ * Returns the root node for the given destination type
+ */
+ protected DestinationMapNode<Value> getRootNode(Destination key) {
+ return root;
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMap.java
------------------------------------------------------------------------------
svn:executable = *
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapEntry.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapEntry.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapEntry.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapEntry.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,84 @@
+/**
+ * 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.filter;
+
+import org.apache.activemq.apollo.broker.Destination;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * A base class for entry objects used to construct a destination based policy
+ * map.
+ *
+ * @version $Revision: 1.1 $
+ */
+public abstract class DestinationMapEntry implements InitializingBean, Comparable<DestinationMapEntry> {
+
+ private Destination destination;
+
+ public int compareTo(DestinationMapEntry that) {
+ if( that == null )
+ return 1;
+ return compare(destination, that.destination);
+ }
+
+ public static int compare(Destination destination, Destination destination2) {
+ if (destination == destination2) {
+ return 0;
+ }
+ if (destination == null) {
+ return -1;
+ } else if (destination2 == null) {
+ return 1;
+ } else {
+ int rc = destination.getDomain().compareTo(destination2.getDomain());
+ if( rc == 0 ) {
+ rc = destination.getName().compareTo(destination2.getName());;
+ }
+ return rc;
+ }
+ }
+
+
+// /**
+// * A helper method to set the destination from a configuration file
+// */
+// public void setQueue(String name) {
+// setDestination(new ActiveMQQueue(name));
+// }
+//
+// /**
+// * A helper method to set the destination from a configuration file
+// */
+// public void setTopic(String name) {
+// setDestination(new ActiveMQTopic(name));
+// }
+
+ public Destination getDestination() {
+ return destination;
+ }
+
+ public void setDestination(Destination destination) {
+ this.destination = destination;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ if (destination == null) {
+ throw new IllegalArgumentException("You must specify the 'destination' property");
+ }
+ }
+
+}
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapNode.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapNode.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapNode.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapNode.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,274 @@
+/**
+ * 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.filter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An implementation class used to implement {@link DestinationMap}
+ *
+ * @version $Revision: 1.2 $
+ */
+public class DestinationMapNode<Value> implements DestinationNode<Value> {
+ protected static final String ANY_CHILD = DestinationMap.ANY_CHILD;
+ protected static final String ANY_DESCENDENT = DestinationMap.ANY_DESCENDENT;
+
+ // we synchornize at the DestinationMap level
+ private DestinationMapNode<Value> parent;
+ private List<Value> values = new ArrayList<Value>();
+ private Map<String, DestinationNode<Value>> childNodes = new HashMap<String, DestinationNode<Value>>();
+ private String path = "Root";
+ // private DestinationMapNode anyChild;
+ private int pathLength;
+
+ public DestinationMapNode(DestinationMapNode<Value> parent) {
+ this.parent = parent;
+ if (parent == null) {
+ pathLength = 0;
+ } else {
+ pathLength = parent.pathLength + 1;
+ }
+ }
+
+ /**
+ * Returns the child node for the given named path or null if it does not
+ * exist
+ */
+ public DestinationMapNode<Value> getChild(String path) {
+ return (DestinationMapNode<Value>)childNodes.get(path);
+ }
+
+ /**
+ * Returns the child nodes
+ */
+ public Collection<DestinationNode<Value>> getChildren() {
+ return childNodes.values();
+ }
+
+ public int getChildCount() {
+ return childNodes.size();
+ }
+
+ /**
+ * Returns the child node for the given named path, lazily creating one if
+ * it does not yet exist
+ */
+ public DestinationMapNode<Value> getChildOrCreate(String path) {
+ DestinationMapNode<Value> answer = (DestinationMapNode<Value>)childNodes.get(path);
+ if (answer == null) {
+ answer = createChildNode();
+ answer.path = path;
+ childNodes.put(path, answer);
+ }
+ return answer;
+ }
+
+ /**
+ * Returns the node which represents all children (i.e. the * node)
+ */
+ // public DestinationMapNode getAnyChildNode() {
+ // if (anyChild == null) {
+ // anyChild = createChildNode();
+ // }
+ // return anyChild;
+ // }
+ /**
+ * Returns a mutable List of the values available at this node in the tree
+ */
+ public List<Value> getValues() {
+ return values;
+ }
+
+ /**
+ * Returns a mutable List of the values available at this node in the tree
+ */
+ public List<Value> removeValues() {
+ ArrayList<Value> v = new ArrayList<Value>(values);
+ // parent.getAnyChildNode().getValues().removeAll(v);
+ values.clear();
+ pruneIfEmpty();
+ return v;
+ }
+
+ public Set<Value> removeDesendentValues() {
+ Set<Value> answer = new HashSet<Value>();
+ removeDesendentValues(answer);
+ return answer;
+ }
+
+ protected void removeDesendentValues(Set<Value> answer) {
+ // if (anyChild != null) {
+ // anyChild.removeDesendentValues(answer);
+ // }
+ answer.addAll(removeValues());
+ }
+
+ /**
+ * Returns a list of all the values from this node down the tree
+ */
+ public Set<Value> getDesendentValues() {
+ Set<Value> answer = new HashSet<Value>();
+ appendDescendantValues(answer);
+ return answer;
+ }
+
+ public void add(String[] paths, int idx, Value value) {
+ if (idx >= paths.length) {
+ values.add(value);
+ } else {
+ // if (idx == paths.length - 1) {
+ // getAnyChildNode().getValues().add(value);
+ // }
+ // else {
+ // getAnyChildNode().add(paths, idx + 1, value);
+ // }
+ getChildOrCreate(paths[idx]).add(paths, idx + 1, value);
+ }
+ }
+
+ public void remove(String[] paths, int idx, Value value) {
+ if (idx >= paths.length) {
+ values.remove(value);
+ pruneIfEmpty();
+ } else {
+ // if (idx == paths.length - 1) {
+ // getAnyChildNode().getValues().remove(value);
+ // }
+ // else {
+ // getAnyChildNode().remove(paths, idx + 1, value);
+ // }
+ getChildOrCreate(paths[idx]).remove(paths, ++idx, value);
+ }
+ }
+
+ public void removeAll(Set<Value> answer, String[] paths, int startIndex) {
+ DestinationNode<Value> node = this;
+ int size = paths.length;
+ for (int i = startIndex; i < size && node != null; i++) {
+
+ String path = paths[i];
+ if (path.equals(ANY_DESCENDENT)) {
+ answer.addAll(node.removeDesendentValues());
+ break;
+ }
+
+ node.appendMatchingWildcards(answer, paths, i);
+ if (path.equals(ANY_CHILD)) {
+ // node = node.getAnyChildNode();
+ node = new AnyChildDestinationNode<Value>(node);
+ } else {
+ node = node.getChild(path);
+ }
+ }
+
+ if (node != null) {
+ answer.addAll(node.removeValues());
+ }
+
+ }
+
+ public void appendDescendantValues(Set<Value> answer) {
+ answer.addAll(values);
+
+ // lets add all the children too
+ for (DestinationNode<Value> child : childNodes.values()) {
+ child.appendDescendantValues(answer);
+ }
+
+ // TODO???
+ // if (anyChild != null) {
+ // anyChild.appendDescendantValues(answer);
+ // }
+ }
+
+ /**
+ * Factory method to create a child node
+ */
+ protected DestinationMapNode<Value> createChildNode() {
+ return new DestinationMapNode<Value>(this);
+ }
+
+ /**
+ * Matches any entries in the map containing wildcards
+ */
+ public void appendMatchingWildcards(Set<Value> answer, String[] paths, int idx) {
+ if (idx - 1 > pathLength) {
+ return;
+ }
+ DestinationMapNode<Value> wildCardNode = getChild(ANY_CHILD);
+ if (wildCardNode != null) {
+ wildCardNode.appendMatchingValues(answer, paths, idx + 1);
+ }
+ wildCardNode = getChild(ANY_DESCENDENT);
+ if (wildCardNode != null) {
+ answer.addAll(wildCardNode.getDesendentValues());
+ }
+ }
+
+ public void appendMatchingValues(Set<Value> answer, String[] paths, int startIndex) {
+ DestinationNode<Value> node = this;
+ boolean couldMatchAny = true;
+ int size = paths.length;
+ for (int i = startIndex; i < size && node != null; i++) {
+ String path = paths[i];
+ if (path.equals(ANY_DESCENDENT)) {
+ answer.addAll(node.getDesendentValues());
+ couldMatchAny = false;
+ break;
+ }
+
+ node.appendMatchingWildcards(answer, paths, i);
+
+ if (path.equals(ANY_CHILD)) {
+ node = new AnyChildDestinationNode<Value>(node);
+ } else {
+ node = node.getChild(path);
+ }
+ }
+ if (node != null) {
+ answer.addAll(node.getValues());
+ if (couldMatchAny) {
+ // lets allow FOO.BAR to match the FOO.BAR.> entry in the map
+ DestinationNode<Value> child = node.getChild(ANY_DESCENDENT);
+ if (child != null) {
+ answer.addAll(child.getValues());
+ }
+ }
+ }
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ protected void pruneIfEmpty() {
+ if (parent != null && childNodes.isEmpty() && values.isEmpty()) {
+ parent.removeChild(this);
+ }
+ }
+
+ protected void removeChild(DestinationMapNode<Value> node) {
+ childNodes.remove(node.getPath());
+ pruneIfEmpty();
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationMapNode.java
------------------------------------------------------------------------------
svn:executable = *
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationNode.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationNode.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationNode.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationNode.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,45 @@
+/**
+ * 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.filter;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Represents a node in the {@link DestinationMap} tree
+ *
+ * @version $Revision: 563921 $
+ */
+public interface DestinationNode<Value> {
+ void appendMatchingValues(Set<Value> answer, String[] paths, int startIndex);
+
+ void appendMatchingWildcards(Set<Value> answer, String[] paths, int startIndex);
+
+ void appendDescendantValues(Set<Value> answer);
+
+ Collection<Value> getDesendentValues();
+
+ DestinationNode<Value> getChild(String path);
+
+ Collection<Value> getValues();
+
+ Collection<DestinationNode<Value>> getChildren();
+
+ Collection<Value> removeDesendentValues();
+
+ Collection<Value> removeValues();
+}
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationPath.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationPath.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationPath.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationPath.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,80 @@
+/**
+ * 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.filter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.activemq.apollo.broker.Destination;
+
+/**
+ * Helper class for decomposing a Destination into a number of paths
+ *
+ * @version $Revision: 1.3 $
+ */
+public final class DestinationPath {
+ protected static final char SEPARATOR = '.';
+
+ private DestinationPath() {
+ }
+
+ public static String[] getDestinationPaths(String subject) {
+ List<String> list = new ArrayList<String>();
+ int previous = 0;
+ int lastIndex = subject.length() - 1;
+ while (true) {
+ int idx = subject.indexOf(SEPARATOR, previous);
+ if (idx < 0) {
+ list.add(subject.substring(previous, lastIndex + 1));
+ break;
+ }
+ list.add(subject.substring(previous, idx));
+ previous = idx + 1;
+ }
+ String[] answer = new String[list.size()];
+ list.toArray(answer);
+ return answer;
+ }
+
+ public static String[] getDestinationPaths(Destination destination) {
+ // TODO: avoid converting to string..
+ return getDestinationPaths(destination.getName().toString());
+ }
+
+ /**
+ * Converts the paths to a single String seperated by dots.
+ *
+ * @param paths
+ * @return
+ */
+ public static String toString(String[] paths) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < paths.length; i++) {
+ if (i > 0) {
+ buffer.append(SEPARATOR);
+ }
+ String path = paths[i];
+ if (path == null) {
+ buffer.append("*");
+ } else {
+ buffer.append(path);
+ }
+ }
+ return buffer.toString();
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/DestinationPath.java
------------------------------------------------------------------------------
svn:executable = *
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/PrefixDestinationFilter.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/PrefixDestinationFilter.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/PrefixDestinationFilter.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/PrefixDestinationFilter.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,67 @@
+/**
+ * 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.filter;
+
+import org.apache.activemq.apollo.broker.Destination;
+
+
+/**
+ * Matches messages which match a prefix like "A.B.>"
+ *
+ * @version $Revision: 1.2 $
+ */
+public class PrefixDestinationFilter extends DestinationFilter {
+
+ private String[] prefixes;
+
+ /**
+ * An array of paths, the last path is '>'
+ *
+ * @param prefixes
+ */
+ public PrefixDestinationFilter(String[] prefixes) {
+ this.prefixes = prefixes;
+ }
+
+ public boolean matches(Destination destination) {
+ String[] path = DestinationPath.getDestinationPaths(destination);
+ int length = prefixes.length;
+ if (path.length >= length) {
+ int size = length - 1;
+ for (int i = 0; i < size; i++) {
+ if (!prefixes[i].equals(path[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public String getText() {
+ return DestinationPath.toString(prefixes);
+ }
+
+ public String toString() {
+ return super.toString() + "[destination: " + getText() + "]";
+ }
+
+ public boolean isWildcard() {
+ return true;
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/PrefixDestinationFilter.java
------------------------------------------------------------------------------
svn:executable = *
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/SimpleDestinationFilter.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/SimpleDestinationFilter.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/SimpleDestinationFilter.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/SimpleDestinationFilter.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,43 @@
+/**
+ * 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.filter;
+
+import org.apache.activemq.apollo.broker.Destination;
+
+
+/**
+ * Matches messages sent to an exact destination
+ *
+ * @version $Revision: 1.3 $
+ */
+public class SimpleDestinationFilter extends DestinationFilter {
+
+ private Destination destination;
+
+ public SimpleDestinationFilter(Destination destination) {
+ this.destination = destination;
+ }
+
+ public boolean matches(Destination destination) {
+ return this.destination.equals(destination);
+ }
+
+ public boolean isWildcard() {
+ return false;
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/SimpleDestinationFilter.java
------------------------------------------------------------------------------
svn:executable = *
Added: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/WildcardDestinationFilter.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/WildcardDestinationFilter.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/WildcardDestinationFilter.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/WildcardDestinationFilter.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,75 @@
+/**
+ * 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.filter;
+
+import org.apache.activemq.apollo.broker.Destination;
+
+
+
+/**
+ * Matches messages which contain wildcards like "A.B.*.*"
+ *
+ * @version $Revision: 1.2 $
+ */
+public class WildcardDestinationFilter extends DestinationFilter {
+
+ private String[] prefixes;
+
+ /**
+ * An array of paths containing * characters
+ *
+ * @param prefixes
+ */
+ public WildcardDestinationFilter(String[] prefixes) {
+ this.prefixes = new String[prefixes.length];
+ for (int i = 0; i < prefixes.length; i++) {
+ String prefix = prefixes[i];
+ if (!prefix.equals("*")) {
+ this.prefixes[i] = prefix;
+ }
+ }
+ }
+
+ public boolean matches(Destination destination) {
+ String[] path = DestinationPath.getDestinationPaths(destination);
+ int length = prefixes.length;
+ if (path.length == length) {
+ for (int i = 0; i < length; i++) {
+ String prefix = prefixes[i];
+ if (prefix != null && !prefix.equals(path[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ public String getText() {
+ return DestinationPath.toString(prefixes);
+ }
+
+ public String toString() {
+ return super.toString() + "[destination: " + getText() + "]";
+ }
+
+ public boolean isWildcard() {
+ return true;
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/main/java/org/apache/activemq/filter/WildcardDestinationFilter.java
------------------------------------------------------------------------------
svn:executable = *
Added: activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapMemoryTest.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapMemoryTest.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapMemoryTest.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapMemoryTest.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,51 @@
+/**
+ * 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.filter;
+
+import junit.framework.TestCase;
+
+import org.apache.activemq.apollo.broker.Destination;
+import org.apache.activemq.apollo.broker.Router;
+import org.apache.activemq.protobuf.AsciiBuffer;
+
+public class DestinationMapMemoryTest extends TestCase {
+
+ public void testLongDestinationPath() throws Exception {
+ Destination d1 = new Destination.SingleDestination(Router.TOPIC_DOMAIN, new AsciiBuffer("1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18"));
+ DestinationMap<String> map = new DestinationMap<String>();
+ map.put(d1, "test");
+ }
+
+ public void testVeryLongestinationPaths() throws Exception {
+
+ for (int i = 1; i < 100; i++) {
+ String name = "1";
+ for (int j = 2; j <= i; j++) {
+ name += "." + j;
+ }
+ // System.out.println("Checking: " + name);
+ try {
+ Destination d1 = new Destination.SingleDestination(Router.TOPIC_DOMAIN, new AsciiBuffer(name));
+ DestinationMap<String> map = new DestinationMap<String>();
+ map.put(d1, "test");
+ } catch (Throwable e) {
+ fail("Destination name too long: " + name + " : " + e);
+ }
+ }
+ }
+
+}
Added: activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTempDestinationTest.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTempDestinationTest.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTempDestinationTest.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTempDestinationTest.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,44 @@
+/**
+ * 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.filter;
+
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.apache.activemq.apollo.broker.Destination;
+import org.apache.activemq.apollo.broker.Router;
+import org.apache.activemq.protobuf.AsciiBuffer;
+
+public class DestinationMapTempDestinationTest extends TestCase {
+
+ public void testtestTempDestinations() throws Exception {
+ DestinationMap<Object> map = new DestinationMap<Object>();
+ Object value = new Object();
+ int count = 1000;
+ for (int i = 0; i < count; i++) {
+ Destination queue = new Destination.SingleDestination(Router.TEMP_QUEUE_DOMAIN, new AsciiBuffer("connection:"+i));
+ map.put(queue, value);
+ }
+ for (int i = 0; i < count; i++) {
+ Destination queue = new Destination.SingleDestination(Router.TEMP_QUEUE_DOMAIN, new AsciiBuffer("connection:"+i));
+ map.remove(queue, value);
+ Set<Object> set = map.get(queue);
+ assertTrue(set.isEmpty());
+ }
+ }
+}
\ No newline at end of file
Added: activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTest.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTest.java?rev=786459&view=auto
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTest.java (added)
+++ activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTest.java Fri Jun 19 11:27:33 2009
@@ -0,0 +1,402 @@
+/**
+ * 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.filter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.apache.activemq.apollo.broker.Destination;
+import org.apache.activemq.apollo.broker.Router;
+import org.apache.activemq.protobuf.AsciiBuffer;
+
+public class DestinationMapTest extends TestCase {
+ protected DestinationMap<String> map = new DestinationMap<String>();
+
+ protected Destination d1 = createDestination("TEST.D1");
+ protected Destination d2 = createDestination("TEST.BAR.D2");
+ protected Destination d3 = createDestination("TEST.BAR.D3");
+ protected Destination compositeDestination1 = createDestination("TEST.D1,TEST.BAR.D2");
+ protected Destination compositeDestination2 = createDestination("TEST.D1,TEST.BAR.D3");
+
+ protected String v1 = "value1";
+ protected String v2 = "value2";
+ protected String v3 = "value3";
+ protected String v4 = "value4";
+ protected String v5 = "value5";
+ protected String v6 = "value6";
+
+ public void testCompositeDestinations() throws Exception {
+ Destination d1 = createDestination("TEST.BAR.D2");
+ Destination d2 = createDestination("TEST.BAR.D3");
+ map.put(d1, v1);
+ map.put(d2, v2);
+ map.get(createDestination("TEST.BAR.D2,TEST.BAR.D3"));
+
+ }
+
+ public void testSimpleDestinations() throws Exception {
+ map.put(d1, v1);
+ map.put(d2, v2);
+ map.put(d3, v3);
+
+ assertMapValue(d1, v1);
+ assertMapValue(d2, v2);
+ assertMapValue(d3, v3);
+ }
+
+ public void testSimpleDestinationsWithMultipleValues() throws Exception {
+ map.put(d1, v1);
+ map.put(d2, v2);
+ map.put(d2, v3);
+
+ assertMapValue(d1, v1);
+ assertMapValue("TEST.BAR.D2", v2, v3);
+ assertMapValue(d3, null);
+ }
+
+ public void testSimpleAndCompositeDestinations() throws Exception {
+ map.put(d1, v1);
+ map.put(compositeDestination1, v2);
+ map.put(compositeDestination2, v3);
+
+ Set<String> set = map.get(d1);
+ System.out.println(set);
+
+
+ assertMapValue("TEST.D1", v1, v2, v3);
+ assertMapValue(d2, v2);
+ assertMapValue(d3, v3);
+ assertMapValue(compositeDestination1, v1, v2, v3);
+ assertMapValue(compositeDestination2, v1, v2, v3);
+
+ map.remove(compositeDestination1, v2);
+ map.remove(compositeDestination2, v3);
+
+ assertMapValue("TEST.D1", v1);
+ }
+
+ public void testLookupOneStepWildcardDestinations() throws Exception {
+ map.put(d1, v1);
+ map.put(d2, v2);
+ map.put(d3, v3);
+
+ assertMapValue("TEST.D1", v1);
+ assertMapValue("TEST.*", v1);
+ assertMapValue("*.D1", v1);
+ assertMapValue("*.*", v1);
+
+ assertMapValue("TEST.BAR.D2", v2);
+ assertMapValue("TEST.*.D2", v2);
+ assertMapValue("*.BAR.D2", v2);
+ assertMapValue("*.*.D2", v2);
+
+ assertMapValue("TEST.BAR.D3", v3);
+ assertMapValue("TEST.*.D3", v3);
+ assertMapValue("*.BAR.D3", v3);
+ assertMapValue("*.*.D3", v3);
+
+ assertMapValue("TEST.BAR.D4", null);
+
+ assertMapValue("TEST.BAR.*", v2, v3);
+ }
+
+ public void testLookupMultiStepWildcardDestinations() throws Exception {
+ map.put(d1, v1);
+ map.put(d2, v2);
+ map.put(d3, v3);
+
+ List<String> allValues = Arrays.asList(new String[] {v1, v2, v3});
+
+ assertMapValue(">", allValues);
+ assertMapValue("TEST.>", allValues);
+ assertMapValue("*.>", allValues);
+
+ assertMapValue("FOO.>", null);
+ }
+
+ public void testStoreWildcardWithOneStepPath() throws Exception {
+ put("TEST.*", v1);
+ put("TEST.D1", v2);
+ put("TEST.BAR.*", v2);
+ put("TEST.BAR.D3", v3);
+
+ assertMapValue("FOO", null);
+ assertMapValue("TEST.FOO", v1);
+ assertMapValue("TEST.D1", v1, v2);
+
+ assertMapValue("TEST.FOO.FOO", null);
+ assertMapValue("TEST.BAR.FOO", v2);
+ assertMapValue("TEST.BAR.D3", v2, v3);
+
+ assertMapValue("TEST.*", v1, v2);
+ assertMapValue("*.D1", v1, v2);
+ assertMapValue("*.*", v1, v2);
+ assertMapValue("TEST.*.*", v2, v3);
+ assertMapValue("TEST.BAR.*", v2, v3);
+ assertMapValue("*.*.*", v2, v3);
+ assertMapValue("*.BAR.*", v2, v3);
+ assertMapValue("*.BAR.D3", v2, v3);
+ assertMapValue("*.*.D3", v2, v3);
+ }
+
+ public void testStoreWildcardInMiddleOfPath() throws Exception {
+ put("TEST.*", v1);
+ put("TEST.D1", v2);
+ put("TEST.BAR.*", v2);
+ put("TEST.XYZ.D3", v3);
+ put("TEST.XYZ.D4", v4);
+ put("TEST.BAR.D3", v5);
+ put("TEST.*.D2", v6);
+
+ assertMapValue("TEST.*.D3", v2, v3, v5);
+ assertMapValue("TEST.*.D4", v2, v4);
+
+ assertMapValue("TEST.*", v1, v2);
+ assertMapValue("TEST.*.*", v2, v3, v4, v5, v6);
+ assertMapValue("TEST.*.>", v1, v2, v3, v4, v5, v6);
+ assertMapValue("TEST.>", v1, v2, v3, v4, v5, v6);
+ assertMapValue("TEST.>.>", v1, v2, v3, v4, v5, v6);
+ assertMapValue("*.*.D3", v2, v3, v5);
+ assertMapValue("TEST.BAR.*", v2, v5, v6);
+
+ assertMapValue("TEST.BAR.D2", v2, v6);
+ assertMapValue("TEST.*.D2", v2, v6);
+ assertMapValue("TEST.BAR.*", v2, v5, v6);
+ }
+
+ public void testDoubleWildcardDoesNotMatchLongerPattern() throws Exception {
+ put("TEST.*", v1);
+ put("TEST.BAR.D3", v2);
+
+ assertMapValue("*.*.D3", v2);
+ }
+
+ public void testWildcardAtEndOfPathAndAtBeginningOfSearch() throws Exception {
+ put("TEST.*", v1);
+
+ assertMapValue("*.D1", v1);
+ }
+
+ public void testAnyPathWildcardInMap() throws Exception {
+ put("TEST.FOO.>", v1);
+
+ assertMapValue("TEST.FOO.BAR.WHANOT.A.B.C", v1);
+ assertMapValue("TEST.FOO.BAR.WHANOT", v1);
+ assertMapValue("TEST.FOO.BAR", v1);
+
+ assertMapValue("TEST.*.*", v1);
+ assertMapValue("TEST.BAR", null);
+
+ assertMapValue("TEST.FOO", v1);
+ }
+
+ public void testSimpleAddRemove() throws Exception {
+ put("TEST.D1", v2);
+
+ assertEquals("Root child count", 1, map.getRootNode().getChildCount());
+
+ assertMapValue("TEST.D1", v2);
+
+ remove("TEST.D1", v2);
+
+ assertEquals("Root child count", 0, map.getRootNode().getChildCount());
+ assertMapValue("TEST.D1", null);
+ }
+
+ public void testStoreAndLookupAllWildcards() throws Exception {
+ loadSample2();
+
+ assertSample2();
+
+ // lets remove everything and add it back
+ remove("TEST.FOO", v1);
+
+ assertMapValue("TEST.FOO", v2, v3, v4);
+ assertMapValue("TEST.*", v2, v3, v4, v6);
+ assertMapValue("*.*", v2, v3, v4, v6);
+
+ remove("TEST.XYZ", v6);
+
+ assertMapValue("TEST.*", v2, v3, v4);
+ assertMapValue("*.*", v2, v3, v4);
+
+ remove("TEST.*", v2);
+
+ assertMapValue("TEST.*", v3, v4);
+ assertMapValue("*.*", v3, v4);
+
+ remove(">", v4);
+
+ assertMapValue("TEST.*", v3);
+ assertMapValue("*.*", v3);
+
+ remove("TEST.>", v3);
+ remove("TEST.FOO.BAR", v5);
+
+ assertMapValue("FOO", null);
+ assertMapValue("TEST.FOO", null);
+ assertMapValue("TEST.D1", null);
+
+ assertMapValue("TEST.FOO.FOO", null);
+ assertMapValue("TEST.BAR.FOO", null);
+ assertMapValue("TEST.FOO.BAR", null);
+ assertMapValue("TEST.BAR.D3", null);
+
+ assertMapValue("TEST.*", null);
+ assertMapValue("*.*", null);
+ assertMapValue("*.D1", null);
+ assertMapValue("TEST.*.*", null);
+ assertMapValue("TEST.BAR.*", null);
+
+ loadSample2();
+
+ assertSample2();
+
+ remove(">", v4);
+ remove("TEST.*", v2);
+
+ assertMapValue("FOO", null);
+ assertMapValue("TEST.FOO", v1, v3);
+ assertMapValue("TEST.D1", v3);
+
+ assertMapValue("TEST.FOO.FOO", v3);
+ assertMapValue("TEST.BAR.FOO", v3);
+ assertMapValue("TEST.FOO.BAR", v3, v5);
+ assertMapValue("TEST.BAR.D3", v3);
+
+ assertMapValue("TEST.*", v1, v3, v6);
+ assertMapValue("*.*", v1, v3, v6);
+ assertMapValue("*.D1", v3);
+ assertMapValue("TEST.*.*", v3, v5);
+ assertMapValue("TEST.BAR.*", v3);
+ }
+
+ public void testAddAndRemove() throws Exception {
+
+ put("FOO.A", v1);
+ assertMapValue("FOO.>", v1);
+
+ put("FOO.B", v2);
+ assertMapValue("FOO.>", v1, v2);
+
+ map.removeAll(createDestination("FOO.A"));
+
+ assertMapValue("FOO.>", v2);
+
+ }
+
+ protected void loadSample2() {
+ put("TEST.FOO", v1);
+ put("TEST.*", v2);
+ put("TEST.>", v3);
+ put(">", v4);
+ put("TEST.FOO.BAR", v5);
+ put("TEST.XYZ", v6);
+ }
+
+ protected void assertSample2() {
+ assertMapValue("FOO", v4);
+ assertMapValue("TEST.FOO", v1, v2, v3, v4);
+ assertMapValue("TEST.D1", v2, v3, v4);
+
+ assertMapValue("TEST.FOO.FOO", v3, v4);
+ assertMapValue("TEST.BAR.FOO", v3, v4);
+ assertMapValue("TEST.FOO.BAR", v3, v4, v5);
+ assertMapValue("TEST.BAR.D3", v3, v4);
+
+ assertMapValue("TEST.*", v1, v2, v3, v4, v6);
+ assertMapValue("*.*", v1, v2, v3, v4, v6);
+ assertMapValue("*.D1", v2, v3, v4);
+ assertMapValue("TEST.*.*", v3, v4, v5);
+ assertMapValue("TEST.BAR.*", v3, v4);
+ }
+
+ protected void put(String name, String value) {
+ map.put(createDestination(name), value);
+ }
+
+ protected void remove(String name, String value) {
+ Destination destination = createDestination(name);
+ map.remove(destination, value);
+ }
+
+ protected void assertMapValue(String destinationName, Object expected) {
+ Destination destination = createDestination(destinationName);
+ assertMapValue(destination, expected);
+ }
+
+ protected void assertMapValue(String destinationName, Object expected1, Object expected2) {
+ assertMapValue(destinationName, Arrays.asList(new Object[] {expected1, expected2}));
+ }
+
+ protected void assertMapValue(String destinationName, Object expected1, Object expected2, Object expected3) {
+ assertMapValue(destinationName, Arrays.asList(new Object[] {expected1, expected2, expected3}));
+ }
+
+ protected void assertMapValue(Destination destination, Object expected1, Object expected2, Object expected3) {
+ assertMapValue(destination, Arrays.asList(new Object[] {expected1, expected2, expected3}));
+ }
+
+ protected void assertMapValue(String destinationName, Object expected1, Object expected2, Object expected3, Object expected4) {
+ assertMapValue(destinationName, Arrays.asList(new Object[] {expected1, expected2, expected3, expected4}));
+ }
+
+ protected void assertMapValue(String destinationName, Object expected1, Object expected2, Object expected3, Object expected4, Object expected5) {
+ assertMapValue(destinationName, Arrays.asList(new Object[] {expected1, expected2, expected3, expected4, expected5}));
+ }
+
+ protected void assertMapValue(String destinationName, Object expected1, Object expected2, Object expected3, Object expected4, Object expected5, Object expected6) {
+ assertMapValue(destinationName, Arrays.asList(new Object[] {expected1, expected2, expected3, expected4, expected5, expected6}));
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void assertMapValue(Destination destination, Object expected) {
+ List expectedList = null;
+ if (expected == null) {
+ expectedList = Collections.EMPTY_LIST;
+ } else if (expected instanceof List) {
+ expectedList = (List)expected;
+ } else {
+ expectedList = new ArrayList();
+ expectedList.add(expected);
+ }
+ Collections.sort(expectedList);
+ Set actualSet = map.get(destination);
+ List actual = new ArrayList(actualSet);
+ Collections.sort(actual);
+ assertEquals("map value for destinationName: " + destination, expectedList, actual);
+ }
+
+ protected Destination createDestination(String name) {
+ String[] split = name.split(",");
+ if( split.length == 1 ) {
+ return new Destination.SingleDestination(Router.QUEUE_DOMAIN, new AsciiBuffer(name));
+ } else {
+ Destination.MultiDestination rc = new Destination.MultiDestination();
+ for (int i = 0; i < split.length; i++) {
+ rc.add(createDestination(split[i]));
+ }
+ return rc;
+ }
+ }
+}
Propchange: activemq/sandbox/activemq-flow/activemq-broker/src/test/java/org/apache/activemq/filter/DestinationMapTest.java
------------------------------------------------------------------------------
svn:executable = *
Modified: activemq/sandbox/activemq-flow/activemq-util/src/main/java/org/apache/activemq/protobuf/Buffer.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/activemq-util/src/main/java/org/apache/activemq/protobuf/Buffer.java?rev=786459&r1=786458&r2=786459&view=diff
==============================================================================
--- activemq/sandbox/activemq-flow/activemq-util/src/main/java/org/apache/activemq/protobuf/Buffer.java (original)
+++ activemq/sandbox/activemq-flow/activemq-util/src/main/java/org/apache/activemq/protobuf/Buffer.java Fri Jun 19 11:27:33 2009
@@ -179,6 +179,9 @@
}
public int compareTo(Buffer o) {
+ if( this == o )
+ return 0;
+
int minLength = Math.min(length, o.length);
if (offset == o.offset) {
int pos = offset;
Modified: activemq/sandbox/activemq-flow/webgen/src/todo.page
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-flow/webgen/src/todo.page?rev=786459&r1=786458&r2=786459&view=diff
==============================================================================
--- activemq/sandbox/activemq-flow/webgen/src/todo.page (original)
+++ activemq/sandbox/activemq-flow/webgen/src/todo.page Fri Jun 19 11:27:33 2009
@@ -79,6 +79,8 @@
* InactivityMonitor needs to get inserted for OpenWire on the server side of MultiWireFormat negotiation.
* BIO SSL Transport does not currently pass Client Certificate chain in OpenWire ConnectionInfo command. This used to be done by the SSL transport but this shouldn't have OpenWire dependencies; instead protocol handler should be able to retrieve it from the underlying transport as needed.
+* Add javadoc to all classes
+* Add nice toString() methods to aid when debugging.
h2. General Cleanup / Abstraction Leaks / Smelly Stuff