content: /**
   * 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.broker.region;
  
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Map;
  import java.util.Set;
  import java.util.Timer;
  import java.util.TimerTask;
  
  import org.apache.activemq.broker.ConnectionContext;
  import org.apache.activemq.command.ActiveMQDestination;
  import org.apache.activemq.thread.TaskRunnerFactory;
  import org.apache.activemq.usage.SystemUsage;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * 
   */
  public abstract class AbstractTempRegion extends AbstractRegion {
      private static final Logger LOG = LoggerFactory.getLogger(TempQueueRegion.class);
  
      private Map<CachedDestination, Destination> cachedDestinations = new HashMap<CachedDestination, Destination>();
      private final boolean doCacheTempDestinations;
      private final int purgeTime;
      private Timer purgeTimer;
      private TimerTask purgeTask;
     
  
      /**
       * @param broker
       * @param destinationStatistics
       * @param memoryManager
       * @param taskRunnerFactory
       * @param destinationFactory
       */
      public AbstractTempRegion(RegionBroker broker,
              DestinationStatistics destinationStatistics,
              SystemUsage memoryManager, TaskRunnerFactory taskRunnerFactory,
              DestinationFactory destinationFactory) {
          super(broker, destinationStatistics, memoryManager, taskRunnerFactory,
                  destinationFactory);
          this.doCacheTempDestinations=broker.getBrokerService().isCacheTempDestinations();
          this.purgeTime = broker.getBrokerService().getTimeBeforePurgeTempDestinations();
          if (this.doCacheTempDestinations) {
              this.purgeTimer = new Timer("ActiveMQ Temp destination purge timer", true);
              this.purgeTask = new TimerTask() {
                  public void run() {
                      doPurge();
                  }
      
              };
              this.purgeTimer.schedule(purgeTask, purgeTime, purgeTime);
          }
         
      }
  
      public void stop() throws Exception {
          super.stop();
          if (purgeTimer != null) {
              purgeTimer.cancel();
          }
      }
  
      protected synchronized Destination createDestination(
              ConnectionContext context, ActiveMQDestination destination)
              throws Exception {
          Destination result = cachedDestinations.remove(new CachedDestination(
                  destination));
          if (result == null) {
              result =  destinationFactory.createDestination(context, destination, destinationStatistics);
          }
          return result;
      }
  
      protected final synchronized void dispose(ConnectionContext context,
              Destination dest) throws Exception {
          // add to cache
          if (this.doCacheTempDestinations) {
              cachedDestinations.put(new CachedDestination(dest
                      .getActiveMQDestination()), dest);
          }else {
              try {
                  dest.dispose(context);
                  dest.stop();
              } catch (Exception e) {
                  LOG.warn("Failed to dispose of {}", dest, e);
              }
          }
      }
  
      private void doDispose(Destination dest) {
          ConnectionContext context = new ConnectionContext();
          try {
              dest.dispose(context);
              dest.stop();
          } catch (Exception e) {
              LOG.warn("Failed to dispose of {}", dest, e);
          }
  
      }
  
      private synchronized void doPurge() {
          long currentTime = System.currentTimeMillis();
          if (cachedDestinations.size() > 0) {
              Set<CachedDestination> tmp = new HashSet<CachedDestination>(
                      cachedDestinations.keySet());
              for (CachedDestination key : tmp) {
                  if ((key.timeStamp + purgeTime) < currentTime) {
                      Destination dest = cachedDestinations.remove(key);
                      if (dest != null) {
                          doDispose(dest);
                      }
                  }
              }
          }
      }
  
      static class CachedDestination {
          long timeStamp;
  
          ActiveMQDestination destination;
  
          CachedDestination(ActiveMQDestination destination) {
              this.destination = destination;
              this.timeStamp = System.currentTimeMillis();
          }
  
          public int hashCode() {
              return destination.hashCode();
          }
  
          public boolean equals(Object o) {
              if (o instanceof CachedDestination) {
                  CachedDestination other = (CachedDestination) o;
                  return other.destination.equals(this.destination);
              }
              return false;
          }
  
      }
  
  }
  