Package org.hornetq.core.postoffice.impl

Source Code of org.hornetq.core.postoffice.impl.WildcardAddressManager

/*
* Copyright 2005-2014 Red Hat, Inc.
* Red Hat 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.hornetq.core.postoffice.impl;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.hornetq.api.core.SimpleString;
import org.hornetq.core.postoffice.Address;
import org.hornetq.core.postoffice.Binding;
import org.hornetq.core.postoffice.Bindings;
import org.hornetq.core.postoffice.BindingsFactory;
import org.hornetq.core.transaction.Transaction;

/**
* extends the simple manager to allow wildcard addresses to be used.
*
* @author <a href="mailto:andy.taylor@jboss.org">Andy Taylor</a>
*/
public class WildcardAddressManager extends SimpleAddressManager
{
   static final char SINGLE_WORD = '*';

   static final char ANY_WORDS = '#';

   static final char DELIM = '.';

   static final SimpleString SINGLE_WORD_SIMPLESTRING = new SimpleString("*");

   static final SimpleString ANY_WORDS_SIMPLESTRING = new SimpleString("#");

   /**
    * These are all the addresses, we use this so we can link back from the actual address to its linked wilcard addresses
    * or vice versa
    */
   private final Map<SimpleString, Address> addresses = new ConcurrentHashMap<SimpleString, Address>();

   private final Map<SimpleString, Address> wildCardAddresses = new ConcurrentHashMap<SimpleString, Address>();

   public WildcardAddressManager(final BindingsFactory bindingsFactory)
   {
      super(bindingsFactory);
   }

   @Override
   public Bindings getBindingsForRoutingAddress(final SimpleString address) throws Exception
   {
      Bindings bindings = super.getBindingsForRoutingAddress(address);

      // this should only happen if we're routing to an address that has no mappings when we're running checkAllowable
      if (bindings == null && !wildCardAddresses.isEmpty())
      {
         Address add = addAndUpdateAddressMap(address);
         if (!add.containsWildCard())
         {
            for (Address destAdd : add.getLinkedAddresses())
            {
               Bindings b = super.getBindingsForRoutingAddress(destAdd.getAddress());
               if (b != null)
               {
                  Collection<Binding> theBindings = b.getBindings();
                  for (Binding theBinding : theBindings)
                  {
                     super.addMappingInternal(address, theBinding);
                  }
               }
            }
         }
         bindings = super.getBindingsForRoutingAddress(address);
      }
      return bindings;
   }

   /**
    * If the address to add the binding to contains a wildcard then a copy of the binding (with the same underlying queue)
    * will be added to the actual mappings. Otherwise the binding is added as normal.
    *
    * @param binding the binding to add
    * @return true if the address was a new mapping
    */
   @Override
   public boolean addBinding(final Binding binding) throws Exception
   {
      boolean exists = super.addBinding(binding);
      if (!exists)
      {
         Address add = addAndUpdateAddressMap(binding.getAddress());
         if (add.containsWildCard())
         {
            for (Address destAdd : add.getLinkedAddresses())
            {
               super.addMappingInternal(destAdd.getAddress(), binding);
            }
         }
         else
         {
            for (Address destAdd : add.getLinkedAddresses())
            {
               Bindings bindings = super.getBindingsForRoutingAddress(destAdd.getAddress());
               for (Binding b : bindings.getBindings())
               {
                  super.addMappingInternal(binding.getAddress(), b);
               }
            }
         }
      }
      return exists;
   }

   /**
    * If the address is a wild card then the binding will be removed from the actual mappings for any linked address.
    * otherwise it will be removed as normal.
    *
    * @param uniqueName the name of the binding to remove
    * @return true if this was the last mapping for a specific address
    */
   @Override
   public Binding removeBinding(final SimpleString uniqueName, Transaction tx) throws Exception
   {
      Binding binding = super.removeBinding(uniqueName, tx);
      if (binding != null)
      {
         Address add = getAddress(binding.getAddress());
         if (add.containsWildCard())
         {
            for (Address theAddress : add.getLinkedAddresses())
            {
               super.removeBindingInternal(theAddress.getAddress(), uniqueName);
            }
         }
         removeAndUpdateAddressMap(add);
      }
      return binding;
   }

   @Override
   public void clear()
   {
      super.clear();
      addresses.clear();
      wildCardAddresses.clear();
   }

   private Address getAddress(final SimpleString address)
   {
      Address add = new AddressImpl(address);
      Address actualAddress;
      if (add.containsWildCard())
      {
         actualAddress = wildCardAddresses.get(address);
      }
      else
      {
         actualAddress = addresses.get(address);
      }
      return actualAddress != null ? actualAddress : add;
   }

   private synchronized Address addAndUpdateAddressMap(final SimpleString address)
   {
      Address add = new AddressImpl(address);
      Address actualAddress;
      if (add.containsWildCard())
      {
         actualAddress = wildCardAddresses.get(address);
      }
      else
      {
         actualAddress = addresses.get(address);
      }
      if (actualAddress == null)
      {
         actualAddress = add;
         addAddress(address, actualAddress);
      }
      if (actualAddress.containsWildCard())
      {
         for (Address destAdd : addresses.values())
         {
            if (destAdd.matches(actualAddress))
            {
               destAdd.addLinkedAddress(actualAddress);
               actualAddress.addLinkedAddress(destAdd);
            }
         }
      }
      else
      {
         for (Address destAdd : wildCardAddresses.values())
         {
            if (actualAddress.matches(destAdd))
            {
               destAdd.addLinkedAddress(actualAddress);
               actualAddress.addLinkedAddress(destAdd);

            }
         }
      }
      return actualAddress;
   }

   private void addAddress(final SimpleString address, final Address actualAddress)
   {
      if (actualAddress.containsWildCard())
      {
         wildCardAddresses.put(address, actualAddress);
      }
      else
      {
         addresses.put(address, actualAddress);
      }
   }

   private synchronized void removeAndUpdateAddressMap(final Address address) throws Exception
   {
      // we only remove if there are no bindings left
      Bindings bindings = super.getBindingsForRoutingAddress(address.getAddress());
      if (bindings == null || bindings.getBindings().size() == 0)
      {
         List<Address> addresses = address.getLinkedAddresses();
         for (Address address1 : addresses)
         {
            address1.removeLinkedAddress(address);
            Bindings linkedBindings = super.getBindingsForRoutingAddress(address1.getAddress());
            if (linkedBindings == null || linkedBindings.getBindings().size() == 0)
            {
               removeAddress(address1);
            }
         }
         removeAddress(address);
      }
   }

   private void removeAddress(final Address add)
   {
      if (add.containsWildCard())
      {
         wildCardAddresses.remove(add.getAddress());
      }
      else
      {
         addresses.remove(add.getAddress());
      }
   }
}
TOP

Related Classes of org.hornetq.core.postoffice.impl.WildcardAddressManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.