text:
package org.apache.geode.cache.client.internal;

import static org.apache.commons.lang.StringUtils.isEmpty;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.logging.log4j.Logger;

import org.apache.geode.CancelCriterion;
import org.apache.geode.CancelException;
import org.apache.geode.StatisticsFactory;
import org.apache.geode.SystemFailure;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.NoSubscriptionServersAvailableException;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionService;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.ServerConnectivityException;
import org.apache.geode.cache.client.SubscriptionNotEnabledException;
import org.apache.geode.cache.client.internal.pooling.ConnectionManager;
import org.apache.geode.cache.client.internal.pooling.ConnectionManagerImpl;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.internal.DefaultQueryService;
import org.apache.geode.cache.wan.GatewaySender;
import org.apache.geode.distributed.PoolCancelledException;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.ServerLocation;
import org.apache.geode.internal.ScheduledThreadPoolExecutorWithKeepAlive;
import org.apache.geode.internal.admin.ClientStatsManager;
import org.apache.geode.internal.cache.EventID;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.PoolFactoryImpl;
import org.apache.geode.internal.cache.PoolManagerImpl;
import org.apache.geode.internal.cache.PoolStats;
import org.apache.geode.internal.cache.tier.sockets.AcceptorImpl;
import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
import org.apache.geode.internal.i18n.LocalizedStrings;
import org.apache.geode.internal.logging.InternalLogWriter;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.logging.log4j.LocalizedMessage;
import org.apache.geode.internal.statistics.DummyStatisticsFactory;

/**
 * Manages the client side of client to server connections and client queues.
 *
 * @since GemFire 5.7
 */
public class PoolImpl implements InternalPool {

  public static final String ON_DISCONNECT_CLEAR_PDXTYPEIDS =
      DistributionConfig.GEMFIRE_PREFIX + "ON_DISCONNECT_CLEAR_PDXTYPEIDS";

  private static final Logger logger = LogService.getLogger();

  private static final int HANDSHAKE_TIMEOUT =
      Integer.getInteger(DistributionConfig.GEMFIRE_PREFIX + "PoolImpl.HANDSHAKE_TIMEOUT",
          AcceptorImpl.DEFAULT_HANDSHAKE_TIMEOUT_MS);

  public static final long SHUTDOWN_TIMEOUT =
      Long.getLong(DistributionConfig.GEMFIRE_PREFIX + "PoolImpl.SHUTDOWN_TIMEOUT", 30000);

  private static final int BACKGROUND_TASK_POOL_SIZE = Integer
      .getInteger(DistributionConfig.GEMFIRE_PREFIX + "PoolImpl.BACKGROUND_TASK_POOL_SIZE", 20);

  private static final int BACKGROUND_TASK_POOL_KEEP_ALIVE = Integer.getInteger(
      DistributionConfig.GEMFIRE_PREFIX + "PoolImpl.BACKGROUND_TASK_POOL_KEEP_ALIVE", 1000);

  /**
   * For durable client tests only. Connection Sources read this flag and return an empty list of
   * servers.
   */
  public volatile static boolean TEST_DURABLE_IS_NET_DOWN = false;

  private final String name;
  private final int freeConnectionTimeout;
  private final int loadConditioningInterval;
  private final int socketBufferSize;
  private final boolean threadLocalConnections;
  private final int readTimeout;
  private final boolean subscriptionEnabled;
  private final boolean prSingleHopEnabled;
  private final int subscriptionRedundancyLevel;
  private final int subscriptionMessageTrackingTimeout;
  private final int subscriptionAckInterval;
  private final String serverGroup;
  private final List<InetSocketAddress> locators;
  private final List<InetSocketAddress> servers;
  private final boolean startDisabled;
  private final boolean usedByGateway;
  private final int maxConnections;
  private final int minConnections;
  private final int retryAttempts;
  private final long idleTimeout;
  private final long pingInterval;
  private final int statisticInterval;
  private final boolean multiuserSecureModeEnabled;

  private final ConnectionSource source;
  private final ConnectionManager manager;
  private QueueManager queueManager;
  protected final EndpointManager endpointManager;
  private final PoolManagerImpl pm;
  protected final InternalLogWriter securityLogWriter;
  protected volatile boolean destroyed;
  private final PoolStats stats;
  private ScheduledExecutorService backgroundProcessor;
  private final OpExecutorImpl executor;
  private final RegisterInterestTracker riTracker = new RegisterInterestTracker();
  private final InternalDistributedSystem dsys;

  private final ClientProxyMembershipID proxyId;
  protected final CancelCriterion cancelCriterion;
  private final ConnectionFactoryImpl connectionFactory;

  private final ArrayList<ProxyCache> proxyCacheList;

  private final GatewaySender gatewaySender;

  private boolean keepAlive = false;
  private static Object simpleLock = new Object();

  public static final int PRIMARY_QUEUE_NOT_AVAILABLE = -2;
  public static final int PRIMARY_QUEUE_TIMED_OUT = -1;
  private AtomicInteger primaryQueueSize = new AtomicInteger(PRIMARY_QUEUE_NOT_AVAILABLE);

  public static PoolImpl create(PoolManagerImpl pm, String name, Pool attributes) {
    PoolImpl pool = new PoolImpl(pm, name, attributes);
    pool.finishCreate(pm);
    return pool;
  }

  public boolean isUsedByGateway() {
    return usedByGateway;
  }

  /**
   * @since GemFire 5.7
   */
  protected void finishCreate(PoolManagerImpl pm) {
    pm.register(this);
    try {
      start();
    } catch (RuntimeException e) {
      try {
        destroy(false);
      } catch (RuntimeException ignore) {
        // do nothing
      }
      throw e;
    }
  }

  protected PoolImpl(PoolManagerImpl pm, String name, Pool attributes) {
    this.pm = pm;
    this.name = name;
    this.freeConnectionTimeout = attributes.getFreeConnectionTimeout();
    this.loadConditioningInterval = attributes.getLoadConditioningInterval();
    this.socketBufferSize = attributes.getSocketBufferSize();
    this.threadLocalConnections = attributes.getThreadLocalConnections();
    this.readTimeout = attributes.getReadTimeout();
    this.minConnections = attributes.getMinConnections();
    this.maxConnections = attributes.getMaxConnections();
    this.retryAttempts = attributes.getRetryAttempts();
    this.idleTimeout = attributes.getIdleTimeout();
    this.pingInterval = attributes.getPingInterval();
    this.statisticInterval = attributes.getStatisticInterval();
    this.subscriptionEnabled = attributes.getSubscriptionEnabled();
    this.prSingleHopEnabled = attributes.getPRSingleHopEnabled();
    this.subscriptionRedundancyLevel = attributes.getSubscriptionRedundancy();
    this.subscriptionMessageTrackingTimeout = attributes.getSubscriptionMessageTrackingTimeout();
    this.subscriptionAckInterval = attributes.getSubscriptionAckInterval();
    this.serverGroup = attributes.getServerGroup();
    this.multiuserSecureModeEnabled = attributes.getMultiuserAuthentication();
    this.locators = attributes.getLocators();
    this.servers = attributes.getServers();
    this.startDisabled =
        ((PoolFactoryImpl.PoolAttributes) attributes).startDisabled || !pm.isNormal();
    this.usedByGateway = ((PoolFactoryImpl.PoolAttributes) attributes).isGateway();
    this.gatewaySender = ((PoolFactoryImpl.PoolAttributes) attributes).getGatewaySender();
    // if (this.subscriptionEnabled && this.multiuserSecureModeEnabled) {
    // throw new IllegalStateException(
    // "subscription-enabled and multiuser-authentication both cannot be true.");
    // }
    InternalDistributedSystem ds = InternalDistributedSystem.getAnyInstance();
    if (ds == null) {
      throw new IllegalStateException(
          LocalizedStrings.PoolImpl_DISTRIBUTED_SYSTEM_MUST_BE_CREATED_BEFORE_CREATING_POOL
              .toLocalizedString());
    }
    this.securityLogWriter = ds.getSecurityInternalLogWriter();
    if (!ds.getConfig().getStatisticSamplingEnabled() && this.statisticInterval > 0) {
      logger.info(LocalizedMessage.create(
          LocalizedStrings.PoolImpl_STATISTIC_SAMPLING_MUST_BE_ENABLED_FOR_SAMPLING_RATE_OF_0_TO_TAKE_AFFECT,
          this.statisticInterval));
    }
    this.dsys = ds;
    this.cancelCriterion = new Stopper();
    if (Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "SPECIAL_DURABLE")) {
      ClientProxyMembershipID.setPoolName(name);
      this.proxyId = ClientProxyMembershipID.getNewProxyMembership(ds);
      ClientProxyMembershipID.setPoolName(null);
    } else {
      this.proxyId = ClientProxyMembershipID.getNewProxyMembership(ds);
    }
    StatisticsFactory statFactory = null;
    if (this.gatewaySender != null) {
      statFactory = new DummyStatisticsFactory();
    } else {
      statFactory = ds;
    }
    this.stats = this.startDisabled ? null
        : new PoolStats(statFactory, getName() + "->"
            + (isEmpty(serverGroup) ? "[any servers]" : "[" + getServerGroup() + "]"));

    source = getSourceImpl(((PoolFactoryImpl.PoolAttributes) attributes).locatorCallback);
    endpointManager = new EndpointManagerImpl(name, ds, this.cancelCriterion, this.stats);
    connectionFactory = new ConnectionFactoryImpl(source, endpointManager, ds, socketBufferSize,
        HANDSHAKE_TIMEOUT, readTimeout, proxyId, this.cancelCriterion, usedByGateway, gatewaySender,
        pingInterval, multiuserSecureModeEnabled, this);
    if (subscriptionEnabled) {
      queueManager = new QueueManagerImpl(this, endpointManager, source, connectionFactory,
          subscriptionRedundancyLevel, pingInterval, securityLogWriter, proxyId);
    }

    manager = new ConnectionManagerImpl(name, connectionFactory, endpointManager, maxConnections,
        minConnections, idleTimeout, loadConditioningInterval, securityLogWriter, pingInterval,
        cancelCriterion, getStats());
    // Fix for 43468 - make sure we check the cache cancel criterion if we get
    // an exception, by passing in the poolOrCache stopper
    executor = new OpExecutorImpl(manager, queueManager, endpointManager, riTracker, retryAttempts,
        freeConnectionTimeout, threadLocalConnections, new PoolOrCacheStopper(), this);
    if (this.multiuserSecureModeEnabled) {
      this.proxyCacheList = new ArrayList<ProxyCache>();
    } else {
      this.proxyCacheList = null;
    }
  }

  /**
   * Return true if the given Pool is compatible with these attributes. Currently this does what
   * equals would but in the future we might decide to weaken the compatibility contract.
   *
   * @since GemFire 6.5
   */
  public boolean isCompatible(Pool p) {
    if (p == null)
      return false;
    return getFreeConnectionTimeout() == p.getFreeConnectionTimeout()
        && getLoadConditioningInterval() == p.getLoadConditioningInterval()
        && getSocketBufferSize() == p.getSocketBufferSize()
        && getMinConnections() == p.getMinConnections()
        && getMaxConnections() == p.getMaxConnections() && getIdleTimeout() == p.getIdleTimeout()
        && getPingInterval() == p.getPingInterval()
        && getStatisticInterval() == p.getStatisticInterval()
        && getRetryAttempts() == p.getRetryAttempts()
        && getThreadLocalConnections() == p.getThreadLocalConnections()
        && getReadTimeout() == p.getReadTimeout()
        && getSubscriptionEnabled() == p.getSubscriptionEnabled()
        && getPRSingleHopEnabled() == p.getPRSingleHopEnabled()
        && getSubscriptionRedundancy() == p.getSubscriptionRedundancy()
        && getSubscriptionMessageTrackingTimeout() == p.getSubscriptionMessageTrackingTimeout()
        && getSubscriptionAckInterval() == p.getSubscriptionAckInterval()
        && getServerGroup().equals(p.getServerGroup())
        && getMultiuserAuthentication() == p.getMultiuserAuthentication()
        && getLocators().equals(p.getLocators()) && getServers().equals(p.getServers());
  }

  private void start() {
    if (this.startDisabled)
      return;

    final boolean isDebugEnabled = logger.isDebugEnabled();
    if (isDebugEnabled) {
      List locators = getLocators();
      if (!locators.isEmpty()) {
        logger.debug("PoolImpl - starting pool with locators: {}", locators);
      } else {
        logger.debug("PoolImpl -starting pool with servers: {}", getServers());
      }
    }

    final String timerName = "poolTimer-" + getName() + "-";
    backgroundProcessor = new ScheduledThreadPoolExecutorWithKeepAlive(BACKGROUND_TASK_POOL_SIZE,
        BACKGROUND_TASK_POOL_KEEP_ALIVE, TimeUnit.MILLISECONDS, new ThreadFactory() {
          AtomicInteger threadNum = new AtomicInteger();

          public Thread newThread(final Runnable r) {
            Thread result = new Thread(r, timerName + threadNum.incrementAndGet());
            result.setDaemon(true);
            return result;
          }
        });
    ((ScheduledThreadPoolExecutorWithKeepAlive) backgroundProcessor)
        .setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
    ((ScheduledThreadPoolExecutorWithKeepAlive) backgroundProcessor)
        .setExecuteExistingDelayedTasksAfterShutdownPolicy(false);

    source.start(this);
    connectionFactory.start(backgroundProcessor);
    endpointManager.addListener(new InstantiatorRecoveryListener(backgroundProcessor, this));
    endpointManager.addListener(new DataSerializerRecoveryListener(backgroundProcessor, this));
    if (Boolean.getBoolean(ON_DISCONNECT_CLEAR_PDXTYPEIDS)) {
      endpointManager.addListener(new PdxRegistryRecoveryListener(this));
    }
    endpointManager.addListener(new LiveServerPinger(this));

    manager.start(backgroundProcessor);
    if (queueManager != null) {
      if (isDebugEnabled) {
        logger.debug("starting queueManager");
      }
      queueManager.start(backgroundProcessor);
    }
    if (isDebugEnabled) {
      logger.debug("scheduling pings every {} milliseconds", pingInterval);
    }

    if (this.statisticInterval > 0 && this.dsys.getConfig().getStatisticSamplingEnabled()) {
      backgroundProcessor.scheduleWithFixedDelay(new PublishClientStatsTask(), statisticInterval,
          statisticInterval, TimeUnit.MILLISECONDS);
    }
    // LOG: changed from config to info
    logger.info(LocalizedMessage.create(
        LocalizedStrings.PoolImpl_POOL_0_STARTED_WITH_MULTIUSER_SECURE_MODE_ENABLED_1,
        new Object[] {this.name, this.multiuserSecureModeEnabled}));
  }

  /**
   * Returns the cancellation criterion for this proxy
   *
   * @return the cancellation criterion
   */
  public CancelCriterion getCancelCriterion() {
    return this.cancelCriterion;
  }

  public void releaseThreadLocalConnection() {
    executor.releaseThreadLocalConnection();
  }

  public void setupServerAffinity(boolean allowFailover) {
    executor.setupServerAffinity(allowFailover);
  }

  public void releaseServerAffinity() {
    executor.releaseServerAffinity();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.apache.geode.cache.Pool#getName()
   */
  public String getName() {
    return this.name;
  }

  public int getFreeConnectionTimeout() {
    return this.freeConnectionTimeout;
  }

  public int getLoadConditioningInterval() {
    return this.loadConditioningInterval;
  }

  public int getMaxConnections() {
    return maxConnections;
  }

  public int getMinConnections() {
    return minConnections;
  }

  public int getRetryAttempts() {
    return retryAttempts;
  }

  public long getIdleTimeout() {
    return idleTimeout;
  }

  public long getPingInterval() {
    return pingInterval;
  }

  public int getStatisticInterval() {
    return this.statisticInterval;
  }

  public int getSocketBufferSize() {
    return this.socketBufferSize;
  }

  public boolean getThreadLocalConnections() {
    return this.threadLocalConnections;
  }

  public int getReadTimeout() {
    return this.readTimeout;
  }

  public boolean getSubscriptionEnabled() {
    return this.subscriptionEnabled;
  }

  public boolean getPRSingleHopEnabled() {
    return this.prSingleHopEnabled;
  }

  public int getSubscriptionRedundancy() {
    return this.subscriptionRedundancyLevel;
  }

  public int getSubscriptionMessageTrackingTimeout() {
    return this.subscriptionMessageTrackingTimeout;
  }

  public int getSubscriptionAckInterval() {
    return subscriptionAckInterval;
  }

  public String getServerGroup() {
    return this.serverGroup;
  }

  public boolean getMultiuserAuthentication() {
    return this.multiuserSecureModeEnabled;
  }

  public List<InetSocketAddress> getLocators() {
    return this.locators;
  }

  @Override
  public List<InetSocketAddress> getOnlineLocators() {
    return this.source.getOnlineLocators();
  }

  public List<InetSocketAddress> getServers() {
    return this.servers;
  }

  public GatewaySender getGatewaySender() {
    return gatewaySender;
  }

  public InternalLogWriter getSecurityInternalLogWriter() {
    return this.securityLogWriter;
  }

  public void destroy() {
    destroy(false);
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(100);
    sb.append(this.getClass().getSimpleName()).append('@').append(System.identityHashCode(this))
        .append(" name=").append(getName());
    return sb.toString();
  }

  public void destroy(boolean keepAlive) {
    int cnt = getAttachCount();
    this.keepAlive = keepAlive;
    boolean SPECIAL_DURABLE =
        Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "SPECIAL_DURABLE");
    if (cnt > 0) {
      // special case to allow closing durable client pool under the keep alive flag
      // closing regions prior to closing pool can cause them to unregister interest
      if (SPECIAL_DURABLE) {
        synchronized (simpleLock) {
          try {
            if (!CacheFactory.getAnyInstance().isClosed()
                && this.getPoolOrCacheCancelInProgress() == null) {
              Set<Region<?, ?>> regions = CacheFactory.getInstance(dsys).rootRegions();
              for (Region<?, ?> roots : regions) {
                Set<Region<?, ?>> subregions = roots.subregions(true);
                for (Region<?, ?> subroots : subregions) {
                  if (!subroots.isDestroyed() && subroots.getAttributes().getPoolName() != null
                      && subroots.getAttributes().getPoolName().equals(this.name)) {
                    if (logger.isDebugEnabled()) {
                      logger.debug(
                          "PoolImpl.destroy[ Region connected count:{} Region subroot closing:{} Pool Name:{} ]",
                          cnt, subroots.getName(), this.name);
                    }
                    subroots.close();
                  }
                }

                if (!roots.isDestroyed() && roots.getAttributes().getPoolName() != null
                    && roots.getAttributes().getPoolName().equals(this.name)) {
                  if (logger.isDebugEnabled()) {
                    logger.debug(
                        "PoolImpl.destroy[ Region connected count:{} Region root closing:{} Pool Name:{} ]",
                        cnt, roots.getName(), this.name);
                  }
                  roots.close();
                }
              }
            }
          } catch (CacheClosedException ccex) {
            if (logger.isDebugEnabled()) {
              logger.debug(ccex.getMessage(), ccex);
            }
          } catch (Exception ex) {
            if (logger.isDebugEnabled()) {
              logger.debug(ex.getMessage(), ex);
            }
          }
        }
      } // end special case

      cnt = getAttachCount();
      if (cnt > 0) {
        throw new IllegalStateException(
            LocalizedStrings.PoolImpl_POOL_COULD_NOT_BE_DESTROYED_BECAUSE_IT_IS_STILL_IN_USE_BY_0_REGIONS
                .toLocalizedString(cnt));
      }
    }
    if (this.pm.unregister(this)) {
      basicDestroy(keepAlive);
    }
  }

  /**
   * Destroys this pool but does not unregister it. This is used by the PoolManagerImpl when it
   * wants to close all its pools.
   */
  public synchronized void basicDestroy(boolean keepAlive) {
    if (!isDestroyed()) {
      this.destroyed = true;
      this.keepAlive = keepAlive;
      // LOG: changed from config to info
      logger.info(
          LocalizedMessage.create(LocalizedStrings.PoolImpl_DESTROYING_CONNECTION_POOL_0, name));

      try {
        if (backgroundProcessor != null) {
          backgroundProcessor.shutdown();
          if (!backgroundProcessor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS)) {
            logger.warn(LocalizedMessage.create(
                LocalizedStrings.PoolImpl_TIMEOUT_WAITING_FOR_BACKGROUND_TASKS_TO_COMPLETE));
          }
        }
      } catch (RuntimeException e) {
        logger.error(LocalizedMessage.create(
            LocalizedStrings.PoolImpl_ERROR_ENCOUNTERED_WHILE_STOPPING_BACKGROUNDPROCESSOR), e);
      } catch (InterruptedException e) {
        logger.error(LocalizedMessage
            .create(LocalizedStrings.PoolImpl_INTERRUPTED_WHILE_STOPPING_BACKGROUNDPROCESSOR), e);
      }

      try {
        if (this.source != null) {
          this.source.stop();
        }
      } catch (RuntimeException e) {
        logger.error(LocalizedMessage.create(
            LocalizedStrings.PoolImpl_ERROR_ENCOUNTERED_WHILE_STOPPING_CONNECTION_SOURCE), e);
      }

      try {
        if (this.queueManager != null) {
          queueManager.close(keepAlive);
        }
      } catch (RuntimeException e) {
        logger.error(
            LocalizedMessage.create(
                LocalizedStrings.PoolImpl_ERROR_ENCOUNTERED_WHILE_STOPPING_SUBSCRIPTION_MANAGER),
            e);
      }

      try {
        if (this.manager != null) {
          manager.close(keepAlive);
        }
      } catch (RuntimeException e) {
        logger.error(LocalizedMessage.create(
            LocalizedStrings.PoolImpl_ERROR_ENCOUNTERED_WHILE_STOPPING_CONNECTION_MANAGER), e);
      }

      try {
        endpointManager.close();
      } catch (RuntimeException e) {
        logger.error(LocalizedMessage.create(
            LocalizedStrings.PoolImpl_ERROR_ENCOUNTERED_WHILE_STOPPING_ENDPOINT_MANAGER), e);
      }

      try {
        if (this.stats != null) {
          this.stats.close();
        }
      } catch (RuntimeException e) {
        logger.error(
            LocalizedMessage.create(LocalizedStrings.PoolImpl_ERROR_WHILE_CLOSING_STATISTICS), e);
      }
    }
  }

  public boolean isDestroyed() {
    return destroyed;
  }

  private ConnectionSource getSourceImpl(LocatorDiscoveryCallback locatorDiscoveryCallback) {
    List<InetSocketAddress> locators = getLocators();
    if (locators.isEmpty()) {
      return new ExplicitConnectionSourceImpl(getServers());
    } else {
      AutoConnectionSourceImpl source =
          new AutoConnectionSourceImpl(locators, getServerGroup(), HANDSHAKE_TIMEOUT);
      if (locatorDiscoveryCallback != null) {
        source.setLocatorDiscoveryCallback(locatorDiscoveryCallback);
      }
      return source;
    }
  }

  /**
   * Used internally by xml parsing code.
   */
  public void sameAs(Object obj) {
    if (!(obj instanceof PoolImpl)) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl__0_IS_NOT_THE_SAME_AS_1_BECAUSE_IT_SHOULD_HAVE_BEEN_A_POOLIMPL
              .toLocalizedString(new Object[] {this, obj}));
    }
    PoolImpl other = (PoolImpl) obj;
    if (!getName().equals(other.getName())) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_ARE_DIFFERENT.toLocalizedString("names"));
    }
    if (getFreeConnectionTimeout() != other.getFreeConnectionTimeout()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("connectionTimeout"));
    }
    if (getLoadConditioningInterval() != other.getLoadConditioningInterval()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("connectionLifetime"));
    }
    if (getSocketBufferSize() != other.getSocketBufferSize()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("socketBufferSize"));
    }
    if (getThreadLocalConnections() != other.getThreadLocalConnections()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("threadLocalConnections"));
    }
    if (getReadTimeout() != other.getReadTimeout()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("readTimeout"));
    }
    if (getMinConnections() != other.getMinConnections()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("MinConnections"));
    }
    if (getMaxConnections() != other.getMaxConnections()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("MaxConnections"));
    }
    if (getRetryAttempts() != other.getRetryAttempts()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("RetryAttempts"));
    }
    if (getIdleTimeout() != other.getIdleTimeout()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("IdleTimeout"));
    }
    if (getPingInterval() != other.getPingInterval()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("PingInterval"));
    }
    if (getStatisticInterval() != other.getStatisticInterval()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("StatisticInterval"));
    }
    if (getSubscriptionAckInterval() != other.getSubscriptionAckInterval()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("subscriptionAckInterval"));
    }
    if (getSubscriptionEnabled() != other.getSubscriptionEnabled()) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("subscriptionEnabled"));
    }
    if (getSubscriptionMessageTrackingTimeout() != other.getSubscriptionMessageTrackingTimeout()) {
      throw new RuntimeException(LocalizedStrings.PoolImpl_0_IS_DIFFERENT
          .toLocalizedString("subscriptionMessageTrackingTimeout"));
    }
    if (getSubscriptionRedundancy() != other.getSubscriptionRedundancy()) {
      throw new RuntimeException(LocalizedStrings.PoolImpl_0_IS_DIFFERENT
          .toLocalizedString("subscriptionRedundancyLevel"));
    }
    if (!getServerGroup().equals(other.getServerGroup())) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_IS_DIFFERENT.toLocalizedString("serverGroup"));
    }
    if (!getLocators().equals(other.getLocators())) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_ARE_DIFFERENT.toLocalizedString("locators"));
    }
    if (!getServers().equals(other.getServers())) {
      throw new RuntimeException(
          LocalizedStrings.PoolImpl_0_ARE_DIFFERENT.toLocalizedString("servers"));
    }
    // ignore startDisabled
  }

  public PoolStats getStats() {
    return this.stats;
  }

  /**
   * Execute the given op on the servers that this pool connects to. This method is responsible for
   * retrying the op if an attempt fails. It will only execute it once and on one server.
   *
   * @param op the operation to execute
   * @return the result of execution if any; null if not
   * @since GemFire 5.7
   */
  public Object execute(Op op) {
    // if(multiuser)
    // get a server from threadlocal cache else throw cacheWriterException
    // executeOn(ServerLocation server, Op op, boolean accessed,boolean onlyUseExistingCnx)

    // Retries are ignored here. FIX IT - FIXED.
    // But this may lead to a user getting authenticated on all servers, even if
    // a single server could have serviced all its requests.
    authenticateIfRequired(op);
    return executor.execute(op);
  }

  /**
   * Execute the given op on the servers that this pool connects to. This method is responsible for
   * retrying the op if an attempt fails. It will only execute it once and on one server.
   *
   * @param op the operation to execute
   * @param retries how many times to retry the operation
   * @return the result of execution if any; null if not
   * @since GemFire 5.7
   */
  public Object execute(Op op, int retries) {
    authenticateIfRequired(op);
    return executor.execute(op, retries);
  }

  /**
   * Execute the given op on the given server.
   *
   * @param server the server to do the execution on
   * @param op the operation to execute
   * @return the result of execution if any; null if not
   */
  public Object executeOn(ServerLocation server, Op op) {
    authenticateIfRequired(server, op);
    return executor.executeOn(server, op);
  }

  /**
   * Execute the given op on the given server.
   *
   * @param server the server to do the execution on
   * @param op the operation to execute
   * @param accessed true if the connection is accessed by this execute
   * @return the result of execution if any; null if not
   */
  public Object executeOn(ServerLocation server, Op op, boolean accessed,
      boolean onlyUseExistingCnx) {
    authenticateIfRequired(server, op);
    return executor.executeOn(server, op, accessed, onlyUseExistingCnx);
  }

  /**
   * Execute the given op on the given connection.
   *
   * @param con the connection to do the execution on
   * @param op the operation to execute
   * @return the result of execution if any; null if not
   */
  public Object executeOn(Connection con, Op op) {
    authenticateIfRequired(con.getServer(), op);
    return executor.executeOn(con, op);
  }

  public Object executeOn(Connection con, Op op, boolean timeoutFatal) {
    return executor.executeOn(con, op, timeoutFatal);
  }

  /**
   * Execute the given op on all the servers that have server-to-client queues for this pool
   *
   * @param op the operation to execute
   * @return the result of execution if any; null if not
   * @since GemFire 5.7
   */
  public Object executeOnQueuesAndReturnPrimaryResult(Op op) {
    authenticateOnAllServers(op);
    return executor.executeOnQueuesAndReturnPrimaryResult(op);
  }

  public void executeOnAllQueueServers(Op op)
      throws NoSubscriptionServersAvailableException, SubscriptionNotEnabledException {
    authenticateOnAllServers(op);
    executor.executeOnAllQueueServers(op);
  }

  /**
   * Execute the given op on the current primary server.
   *
   * @param op the operation to execute
   * @return the result of execution if any; null if not
   */
  public Object executeOnPrimary(Op op) {
    return executor.executeOnPrimary(op);
  }

  public Map<ServerLocation, Endpoint> getEndpointMap() {
    return endpointManager.getEndpointMap();
  }

  public ScheduledExecutorService getBackgroundProcessor() {
    return backgroundProcessor;
  }

  public RegisterInterestTracker getRITracker() {
    return this.riTracker;
  }

  /**
   * Test hook that returns the number of servers we currently have connections to.
   */
  public int getConnectedServerCount() {
    return this.endpointManager.getConnectedServerCount();
  }

  /**
   * Test hook. Verify if this EventId is already present in the map or not. If it is already
   * present then return true.
   *
   * @param eventId the EventId of the incoming event
   * @return true if it is already present
   * @since GemFire 5.1
   */
  public boolean verifyIfDuplicate(EventID eventId) {
    return ((QueueStateImpl) this.queueManager.getState()).verifyIfDuplicate(eventId);
  }

  public boolean verifyIfDuplicate(EventID eventId, boolean addToMap) {
    return ((QueueStateImpl) this.queueManager.getState()).verifyIfDuplicate(eventId);
  }

  /**
   * Borrows a connection from the pool.. Used by gateway and tests. Any connection that is acquired
   * using this method must be returned using returnConnection, even if it is destroyed.
   *
   */
  public Connection acquireConnection() {
    return manager.borrowConnection(45000L);
  }

  /**
   * Hook to return connections that were acquired using acquireConnection.
   */
  public void returnConnection(Connection conn) {
    manager.returnConnection(conn);
  }

  /**
   * Test hook that acquires and returns a connection from the pool with a given ServerLocation.
   */
  public Connection acquireConnection(ServerLocation loc) {
    return manager.borrowConnection(loc, 15000L, false);
  }

  /**
   * Test hook that returns an unnmodifiable list of the current blacklisted servers
   */
  public Set getBlacklistedServers() {
    return connectionFactory.getBlackList().getBadServers();
  }

  /**
   * Test hook to handle an exception that happened on the given connection
   */
  public void processException(Throwable e, Connection con) {
    executor.handleException(e, con, 0, false);
  }

  /**
   * Test hook that returns the ThreadIdToSequenceIdMap
   */
  public Map getThreadIdToSequenceIdMap() {
    if (this.queueManager == null)
      return Collections.emptyMap();
    if (this.queueManager.getState() == null)
      return Collections.emptyMap();
    return this.queueManager.getState().getThreadIdToSequenceIdMap();
  }

  /**
   * Test hook that returns true if we have a primary and its updater thread is alive.
   */
  public boolean isPrimaryUpdaterAlive() {
    return ((QueueManagerImpl) this.queueManager).isPrimaryUpdaterAlive();
  }

  /**
   * Test hook used to simulate a kill of the primaryEndpoint
   */
  public void killPrimaryEndpoint() // throws ServerException
  {
    boolean ok = false;
    if (this.queueManager != null) {
      QueueManager.QueueConnections cons = this.queueManager.getAllConnections();
      Connection con = cons.getPrimary();
      if (con != null) {
        final String msg = "killing primary endpoint";
        logger.info("<ExpectedException action=add>{}</ExpectedException>", msg);
        Exception e = new Exception(msg);
        try {
          processException(e, con);
        } catch (ServerConnectivityException ignore) {
        } finally {
          logger.info("<ExpectedException action=remove>{}</ExpectedException>", msg);
        }
        // do some validation here that we are no longer connected to "sl"
        ok = true;
      }
    }
    if (!ok) {
      throw new IllegalStateException("primaryEndpoint was null");
    }
  }

  // Pool that are declared in a cache.xml will set this property to true.
  private boolean declaredInXML;

  public void setDeclaredInXML(boolean v) {
    this.declaredInXML = v;
  }

  public boolean getDeclaredInXML() {
    return this.declaredInXML;
  }

  // used by unit tests to confirm if readyForEvents has been called on a pool
  private boolean readyForEventsCalled;

  public boolean getReadyForEventsCalled() {
    return this.readyForEventsCalled;
  }

  public void readyForEvents(InternalDistributedSystem system) {
    if (!isDurableClient() || queueManager == null) {
      return;
    }
    this.readyForEventsCalled = true;
    queueManager.readyForEvents(system);

  }

  public boolean isDurableClient() {
    boolean isDurable = false;
    InternalDistributedSystem system = InternalDistributedSystem.getAnyInstance();
    DistributionConfig config = system.getConfig();
    String durableClientId = config.getDurableClientId();
    isDurable = durableClientId != null && durableClientId.length() > 0;
    return isDurable;
  }

  /**
   * Test hook that returns a string consisting of the host name and port of the primary server.
   * Null is returned if we have no primary.
   */
  public String getPrimaryName() {
    String result = null;
    ServerLocation sl = getPrimary();
    if (sl != null) {
      result = sl.getHostName() + sl.getPort();
    }
    return result;
  }

  /**
   * Test hook that returns an int which the port of the primary server. -1 is returned if we have
   * no primary.
   */
  public int getPrimaryPort() {
    int result = -1;
    ServerLocation sl = getPrimary();
    if (sl != null) {
      result = sl.getPort();
    }
    return result;
  }

  /**
   * Test hook that returns a string consisting of the host name and port of the primary server.
   * Null is returned if we have no primary.
   */
  public ServerLocation getPrimary() {
    ServerLocation result = null;
    if (this.queueManager != null) {
      QueueManager.QueueConnections cons = this.queueManager.getAllConnections();
      Connection con = cons.getPrimary();
      result = con.getServer();
    }
    return result;
  }

  /**
   * Test hook to get a connection to the primary server.
   */
  public Connection getPrimaryConnection() {
    if (this.queueManager != null) {
      QueueManager.QueueConnections cons = this.queueManager.getAllConnections();
      return cons.getPrimary();
    }
    return null;
  }

  /**
   * Test hook that returns a list of strings. Each string consists of the host name and port of a
   * redundant server. An empty list is returned if we have no redundant servers.
   */
  public List<String> getRedundantNames() {
    List result = Collections.emptyList();
    if (this.queueManager != null) {
      QueueManager.QueueConnections cons = this.queueManager.getAllConnections();
      List<Connection> backupCons = cons.getBackups();
      if (backupCons.size() > 0) {
        result = new ArrayList(backupCons.size());
        Iterator<Connection> it = backupCons.iterator();
        while (it.hasNext()) {
          Connection con = it.next();
          ServerLocation sl = con.getServer();
          result.add(sl.getHostName() + sl.getPort());
        }
      }
    }
    return result;
  }

  /**
   * Test hook that returns a list of ServerLocation instances. Each ServerLocation describes a
   * redundant server. An empty list is returned if we have no redundant servers.
   */
  public List<ServerLocation> getRedundants() {
    List result = Collections.emptyList();
    if (this.queueManager != null) {
      QueueManager.QueueConnections cons = this.queueManager.getAllConnections();
      List<Connection> backupCons = cons.getBackups();
      if (backupCons.size() > 0) {
        result = new ArrayList(backupCons.size());
        Iterator<Connection> it = backupCons.iterator();
        while (it.hasNext()) {
          Connection con = it.next();
          result.add(con.getServer());
        }
      }
    }
    return result;
  }

  /**
   * Test hook to find out current number of connections this pool has.
   */
  public int getConnectionCount() {
    return manager.getConnectionCount();
  }

  /**
   * Atomic counter used to keep track of services using this pool.
   *
   * @since GemFire 5.7
   */
  private final AtomicInteger attachCount = new AtomicInteger();
  public static volatile boolean IS_INSTANTIATOR_CALLBACK = false;

  /**
   * Returns number of services currently using/attached to this pool.
   * <p>
   * Made public so it can be used by tests
   *
   * @since GemFire 5.7
   */
  public int getAttachCount() {
    return this.attachCount.get();
  }

  /**
   * This needs to be called when a service (like a Region or CQService) starts using a pool.
   *
   * @since GemFire 5.7
   */
  public void attach() {
    this.attachCount.getAndIncrement();
  }

  /**
   * This needs to be called when a service (like a Region or CQService) stops using a pool.
   *
   * @since GemFire 5.7
   */
  public void detach() {
    this.attachCount.getAndDecrement();
  }

  /**
   * Get the connection held by this thread if we're using thread local connections
   *
   * This is a a hook for hydra code to pass thread local connections between threads.
   *
   * @return the connection from the thread local, or null if there is no thread local connection.
   */
  public Connection getThreadLocalConnection() {
    return executor.getThreadLocalConnection();
  }

  /**
   * Returns a list of ServerLocation instances; one for each server we are currently connected to.
   */
  public List<ServerLocation> getCurrentServers() {
    ArrayList result = new ArrayList();
    Map endpointMap = endpointManager.getEndpointMap();
    result.addAll(endpointMap.keySet());
    return result;
  }

  /**
   * Test hook that returns a list of server names (host+port); one for each server we are currently
   * connected to.
   */
  public List<String> getCurrentServerNames() {
    List<ServerLocation> servers = getCurrentServers();
    ArrayList<String> result = new ArrayList(servers.size());
    Iterator it = servers.iterator();
    while (it.hasNext()) {
      ServerLocation sl = (ServerLocation) it.next();
      String name = sl.getHostName() + sl.getPort();
      result.add(name);
    }
    return result;
  }

  public EndpointManager getEndpointManager() {
    return endpointManager;
  }

  /**
   * Fetch the connection source for this pool
   *
   * @return the source
   */
  public ConnectionSource getConnectionSource() {
    return source;
  }

  private static void setTEST_DURABLE_IS_NET_DOWN(boolean v) {
    TEST_DURABLE_IS_NET_DOWN = v;
  }

  /**
   * test hook
   */
  public void endpointsNetDownForDUnitTest() {
    logger.debug("PoolImpl - endpointsNetDownForDUnitTest");
    setTEST_DURABLE_IS_NET_DOWN(true);
    try {
      Thread.sleep(this.pingInterval * 2);
    } catch (java.lang.InterruptedException ignore) {
      // do nothing.
    }

    Map endpoints = endpointManager.getEndpointMap();
    for (Iterator itr = endpoints.values().iterator(); itr.hasNext();) {
      Endpoint endpoint = (Endpoint) itr.next();
      logger.debug("PoolImpl Simulating crash of endpoint {}", endpoint);
      endpointManager.serverCrashed(endpoint);
    }
  }

  /**
   * test hook
   */
  public void endpointsNetUpForDUnitTest() {
    setTEST_DURABLE_IS_NET_DOWN(false);
    try {
      Thread.sleep(this.pingInterval * 2);
    } catch (java.lang.InterruptedException ignore) {
      // do nothing.
    }
  }

  /**
   * test hook
   */
  public int getInvalidateCount() {
    return ((QueueStateImpl) this.queueManager.getState()).getInvalidateCount();
  }

  /**
   * Set the connection held by this thread if we're using thread local connections
   *
   * This is a a hook for hydra code to pass thread local connections between threads.
   */
  public void setThreadLocalConnection(Connection conn) {
    executor.setThreadLocalConnection(conn);
  }

  public ServerLocation getServerAffinityLocation() {
    return executor.getServerAffinityLocation();
  }

  public void setServerAffinityLocation(ServerLocation serverLocation) {
    executor.setServerAffinityLocation(serverLocation);
  }

  public ServerLocation getNextOpServerLocation() {
    return executor.getNextOpServerLocation();
  }

  /**
   * Test hook for getting the client proxy membership id from this proxy.
   */
  public ClientProxyMembershipID getProxyID() {
    return proxyId;
  }

  public void emergencyClose() {
    destroyed = true;
    manager.emergencyClose();
    queueManager.emergencyClose();
  }

  ///////////////////// start test hooks ///////////////////////
  /**
   * A debug flag used for testing used in ClientServerObserver
   */
  public static volatile boolean AFTER_PRIMARY_IDENTIFICATION_FROM_BACKUP_CALLBACK_FLAG = false;

  /**
   * A debug flag used for testing used in ClientServerObserver
   */
  public static volatile boolean BEFORE_REGISTER_CALLBACK_FLAG = false;

  /**
   * A debug flag used for testing used in ClientServerObserver
   */
  public static volatile boolean BEFORE_RECOVER_INTEREST_CALLBACK_FLAG = false;

  /**
   * A debug flag used for testing used in ClientServerObserver
   */
  public static volatile boolean AFTER_REGISTER_CALLBACK_FLAG = false;

  /**
   * A debug flag used for testing used in ClientServerObserver
   */
  public static volatile boolean BEFORE_PRIMARY_IDENTIFICATION_FROM_BACKUP_CALLBACK_FLAG = false;

  /**
   * A debug flag used for testing used in ClientServerObserver
   */
  public static volatile boolean BEFORE_SENDING_CLIENT_ACK_CALLBACK_FLAG = false;
  /**
   * A debug flag used for testing used in ClientServerObserver
   */
  public static volatile boolean AFTER_QUEUE_DESTROY_MESSAGE_FLAG = false;

  /**
   * Test hook flag to notify observer(s) that a primary is recovered either from a backup or from a
   * new connection.
   */
  public static volatile boolean AFTER_PRIMARY_RECOVERED_CALLBACK_FLAG = false;

  public static abstract class PoolTask implements Runnable {

    public void run() {
      try {
        run2();
      } catch (VirtualMachineError e) {
        SystemFailure.initiateFailure(e);
        throw e;
      } catch (CancelException ignore) {
        if (logger.isDebugEnabled()) {
          logger.debug("Pool task <{}> cancelled", this);
        }
      } catch (Throwable t) {
        logger.error(LocalizedMessage
            .create(LocalizedStrings.PoolImpl_UNEXPECTED_ERROR_IN_POOL_TASK_0, this), t);
      }

    }

    public abstract void run2();
  }

  ///////////////////// end test hooks ///////////////////////

  protected class PublishClientStatsTask extends PoolTask {
    @Override
    public void run2() {
      ClientStatsManager.publishClientStats(PoolImpl.this);
    }
  }

  /**
   * A cancel criterion that checks both the pool and the cache for canceled status.
   */
  protected class PoolOrCacheStopper extends CancelCriterion {

    @Override
    public String cancelInProgress() {
      return getPoolOrCacheCancelInProgress();
    }

    @Override
    public RuntimeException generateCancelledException(Throwable e) {
      return generatePoolOrCacheCancelledException(e);
    }

  }

  /**
   * A cancel criterion that checks only if this pool has been closed. This is necessary because
   * there are some things that we want to allow even after the cache has started closing.
   */
  protected class Stopper extends CancelCriterion {

    @Override
    public String cancelInProgress() {
      if (destroyed) {
        return "Pool " + PoolImpl.this + " is shut down";
      } else {
        return null;
      }
    }

    @Override
    public RuntimeException generateCancelledException(Throwable t) {
      String reason = cancelInProgress();
      if (reason == null) {
        return null;
      }
      return new PoolCancelledException(reason, t);
    }
  }

  public static void loadEmergencyClasses() {
    QueueManagerImpl.loadEmergencyClasses();
    ConnectionManagerImpl.loadEmergencyClasses();
    EndpointManagerImpl.loadEmergencyClasses();
  }

  /**
   * Returns the QueryService, that can be used to execute Query functions on the servers associated
   * with this pool.
   *
   * @return the QueryService
   */
  public QueryService getQueryService() {
    Cache cache = CacheFactory.getInstance(InternalDistributedSystem.getAnyInstance());
    DefaultQueryService queryService = new DefaultQueryService((InternalCache) cache);
    queryService.setPool(this);
    return queryService;
  }

  public RegionService createAuthenticatedCacheView(Properties properties) {
    if (!this.multiuserSecureModeEnabled) {
      throw new UnsupportedOperationException(
          "Operation not supported when multiuser-authentication is false.");
    }
    if (properties == null || properties.isEmpty()) {
      throw new IllegalArgumentException("Security properties cannot be empty.");
    }
    Cache cache = CacheFactory.getInstance(InternalDistributedSystem.getAnyInstance());

    Properties props = new Properties();
    for (Entry<Object, Object> entry : properties.entrySet()) {
      props.setProperty((String) entry.getKey(), (String) entry.getValue());
    }
    ProxyCache proxy = new ProxyCache(props, (InternalCache) cache, this);
    synchronized (this.proxyCacheList) {
      this.proxyCacheList.add(proxy);
    }
    return proxy;
  }

  private volatile CancelCriterion cacheCriterion = null;

  private RuntimeException generatePoolOrCacheCancelledException(Throwable e) {
    RuntimeException re = getCancelCriterion().generateCancelledException(e);
    if (re != null) {
      return re;
    }
    InternalCache cache = GemFireCacheImpl.getInstance();
    if (cache == null) {
      if (cacheCriterion != null) {
        return cacheCriterion.generateCancelledException(e);
      }
    } else {
      if (cacheCriterion == null || cacheCriterion != cache.getCancelCriterion()) {
        cacheCriterion = cache.getCancelCriterion();
      }
      return cacheCriterion.generateCancelledException(e);
    }
    return null;
  }

  public String getPoolOrCacheCancelInProgress() {
    String reason = null;
    try {
      reason = getCancelCriterion().cancelInProgress();
      if (reason != null) {
        return reason;
      }
      InternalCache cache = GemFireCacheImpl.getInstance();
      if (cache == null) {
        if (cacheCriterion != null) {
          return cacheCriterion.cancelInProgress();
        }
        return null;
      } else {
        if (cacheCriterion == null) {
          cacheCriterion = cache.getCancelCriterion();
        } else if (cacheCriterion != cache.getCancelCriterion()) {
          /*
           * If the cache instance has somehow changed, we need to get a reference to the new
           * criterion. This is pretty unlikely because the cache closes all the pools when it shuts
           * down, but I wanted to be safe.
           */
          cacheCriterion = cache.getCancelCriterion();
        }
        return cacheCriterion.cancelInProgress();
      }
    } catch (CancelException cce) {
      if (cce.getMessage() != null) {
        return cce.getMessage();
      } else {
        return "cache is closed";
      }
    }
  }

  public boolean getKeepAlive() {
    InternalCache cache = GemFireCacheImpl.getInstance();
    if (cache == null) {
      return keepAlive;
    }

    return cache.keepDurableSubscriptionsAlive();
  }

  public ArrayList<ProxyCache> getProxyCacheList() {
    return this.proxyCacheList;
  }

  private void authenticateIfRequired(Op op) {
    authenticateIfRequired(null, op);
  }

  /**
   * Assert thread-local var is not null, if it has multiuser-authentication set to true.
   *
   * If serverLocation is non-null, check if the the user is authenticated on that server. If not,
   * authenticate it and return.
   *
   * @param serverLocation
   * @param op
   */
  private void authenticateIfRequired(ServerLocation serverLocation, Op op) {
    if (this.multiuserSecureModeEnabled && op instanceof AbstractOp
        && ((AbstractOp) op).needsUserId()) {
      UserAttributes userAttributes = UserAttributes.userAttributes.get();
      if (userAttributes == null) {
        throw new UnsupportedOperationException(
            LocalizedStrings.MultiUserSecurityEnabled_USE_POOL_API.toLocalizedString());
      }
      if (serverLocation != null) {
        if (!userAttributes.getServerToId().containsKey(serverLocation)) {
          Long userId = (Long) AuthenticateUserOp.executeOn(serverLocation, this,
              userAttributes.getCredentials());
          if (userId != null) {
            userAttributes.setServerToId(serverLocation, userId);
          }
        }
      }
    }
  }

  private void authenticateOnAllServers(Op op) {
    if (this.multiuserSecureModeEnabled && ((AbstractOp) op).needsUserId()) {
      UserAttributes userAttributes = UserAttributes.userAttributes.get();
      if (userAttributes != null) {
        ConcurrentHashMap<ServerLocation, Long> map = userAttributes.getServerToId();

        if (this.queueManager == null) {
          throw new SubscriptionNotEnabledException();
        }
        Connection primary = this.queueManager.getAllConnectionsNoWait().getPrimary();
        if (primary != null && !map.containsKey(primary.getServer())) {
          Long userId = (Long) AuthenticateUserOp.executeOn(primary.getServer(), this,
              userAttributes.getCredentials());
          if (userId != null) {
            map.put(primary.getServer(), userId);
          }
        }

        List<Connection> backups = this.queueManager.getAllConnectionsNoWait().getBackups();
        for (int i = 0; i < backups.size(); i++) {
          Connection conn = backups.get(i);
          if (!map.containsKey(conn.getServer())) {
            Long userId = (Long) AuthenticateUserOp.executeOn(conn.getServer(), this,
                userAttributes.getCredentials());
            if (userId != null) {
              map.put(conn.getServer(), userId);
            }
          }
        }
      } else {
        throw new UnsupportedOperationException(
            LocalizedStrings.MultiUserSecurityEnabled_USE_POOL_API.toLocalizedString());
      }
    }
  }

  public void setPendingEventCount(int count) {
    this.primaryQueueSize.set(count);
  }

  public int getPendingEventCount() {
    if (!isDurableClient() || this.queueManager == null) {
      throw new IllegalStateException(
          LocalizedStrings.PoolManagerImpl_ONLY_DURABLE_CLIENTS_SHOULD_CALL_GETPENDINGEVENTCOUNT
              .toLocalizedString());
    }
    if (this.readyForEventsCalled) {
      throw new IllegalStateException(
          LocalizedStrings.PoolManagerImpl_GETPENDINGEVENTCOUNT_SHOULD_BE_CALLED_BEFORE_INVOKING_READYFOREVENTS
              .toLocalizedString());
    }
    return this.primaryQueueSize.get();
  }
}


text:
Thank you for your interest in contributing to gophish! It is our goal to make the best simulated phishing framework possible, and we are excited you want to help out.

This guide details how to contribute to gophish in a way that is efficient for everyone involved.

Gophish currently only comes in one flavor, gophish Community Edition (CE), which is our free and open source edition. In the future, we reserve the right to create an Enterprise Edition, though we're currently pouring our effort into create a rock-solid open source platform. This document will be updated if an EE edition is created.

## Contributor license agreement

By submitting code as an individual you agree to the
[individual contributor license agreement](doc/individual_contributor_license_agreement.md).
By submitting code as an entity you agree to the
[corporate contributor license agreement](doc/corporate_contributor_license_agreement.md).

## Security vulnerability disclosure

Please report suspected security vulnerabilities in private to
`security@getgophish.com`.
Please do **NOT** create publicly viewable issues for suspected security
vulnerabilities.

## Closing policy for issues and merge requests

It is our goal that gophish will become a popular tool for the infosec community. If this were to happen, we may begin receiving more issues and merge requests than we can keep up with.

Out of respect for our volunteers, issues and merge requests not in line with the guidelines listed in this document may be closed without notice. It will always be our goal to try and provide at least a reason why the issue is closed as much as possible.

Please treat our volunteers with courtesy and respect, it will go a long way
towards getting your issue resolved.

Issues and merge requests should be in English and contain appropriate language
for audiences of all ages.

## I want to contribute!

**Awesome!** We're excited to have your help. If you want to contribute to gophish, but are not sure where to start,
look for [issues with the label `contributor-friendly`][contributor-friendly]. These issues
will be of reasonable size and challenge, as well as not requiring a ton of internal plumbing on the gophish source code.

## Have Questions?
If you ever have questions, please don't hesitate to reach out to us directly at `support@getgophish.com`

[contributor-friendly]: https://github.com/vanhecke/gophish/labels/contributor-friendly

redpajama_set_name: RedPajamaGithub


text:
import { ILivechatDepartment } from '../../../../../../definition/ILivechatDepartment';
import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi';

export type LivechatDepartmentsByUnit = {
	GET: (params: {
		text: string;
		offset: number;
		count: number;
	}) => {
		departments: ObjectFromApi<ILivechatDepartment>[];
		total: number;
	};
};


text:
import {Component} from '@angular/core';
@Component({
  selector: 'app-root',
  template: `
        Home
        Product Detail
        <router-outlet></router-outlet>
    `
})
export class AppComponent {
  productId = 1234; // as if the product ID was selected from a list of product
}


text:
package ethanjones.cubes.graphics.hud;

import ethanjones.cubes.graphics.assets.Assets;

import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;

public class ImageButtons {

  public static ImageButton.ImageButtonStyle jumpButton() {
    TextureRegionDrawable t = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/JumpButton.png"));
    return new ImageButton.ImageButtonStyle(t, t, null, null, null, null);
  }

  public static ImageButton.ImageButtonStyle descendButton() {
    TextureRegionDrawable t = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/DescendButton.png"));
    return new ImageButton.ImageButtonStyle(t, t, null, null, null, null);
  }

  public static ImageButton.ImageButtonStyle blocksButton() {
    TextureRegionDrawable up = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/BlocksButtonUp.png"));
    TextureRegionDrawable down = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/BlocksButtonDown.png"));
    return new ImageButton.ImageButtonStyle(up, down, null, null, null, null);
  }

  public static ImageButton.ImageButtonStyle chatButton() {
    TextureRegionDrawable up = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/ChatButtonUp.png"));
    TextureRegionDrawable down = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/ChatButtonDown.png"));
    return new ImageButton.ImageButtonStyle(up, down, null, null, null, null);
  }

  public static ImageButton.ImageButtonStyle debugButton() {
    TextureRegionDrawable up = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/DebugButtonUp.png"));
    TextureRegionDrawable down = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/DebugButtonDown.png"));
    return new ImageButton.ImageButtonStyle(up, down, null, null, null, null);
  }

  public static ImageButton.ImageButtonStyle inventoryModifierButton() {
    TextureRegionDrawable up = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/InventoryModifierButtonUp.png"));
    TextureRegionDrawable down = new TextureRegionDrawable(Assets.getTextureRegion("core:hud/touch/InventoryModifierButtonDown.png"));
    return new ImageButton.ImageButtonStyle(up, down, null, null, null, null);
  }
}


text:
<?php

namespace Square1\MobileBill;

use Guzzle\Http\Client;

/**
 * Api
 *
 * This is the main class that sets the inital auth settings.
 * It will build the request array and will trigger the API request.
 *
 * Example usage:
 *
 * $charge = Api::create('username', 'password')
 *     ->content('999999', 'The content description goes here')
 *     ->phone('35387123456')
 *     ->charge('100', 'This is a test transaction')
 *     ->send();
 *
 * @package MobileBill
 * @author  Ciaran Maher
 * @since   1.0.0
 */
class Api
{
    /**
     * The Base URL for the API
     *
     * @const string
     */
    const BASE_URL = 'https://www.allpointsmessaging.com/mno/api';

    /**
     * The Guzzle object
     *
     * @type \Guzzle\Http\Client
     */
    private $client;

    /**
     * The Request object
     *
     * @type \Square1\MobileBill\Request
     */
    private $request;

    /**
     * 2Bill Construtor
     *
     * @param \Guzzle\Http\Client         $client  The Guzzle client
     * @param \Square1\MobileBill\Request $request The request object
     */
    public function __construct(Client $client, Request $request)
    {
        $this->request = $request;
        $this->client = $client;
        $this->client->setBaseUrl(self::BASE_URL);
    }

    /**
     * This is a easy-to-use facade for using this class.
     *
     * @param string $username  The 2Bill username
     * @param string $password  The 2Bill password
     *
     * @return \Square1\MobileBill\Api
     */
    public static function create($username, $password)
    {
        //Guzzle client
        $client = new Client();

        //Request object
        $request = new Request($client);

        $request->set('USERNAME', $username);
        $request->set('PASSWORD', $password);

        return new Api($client, $request);
    }

    /**
     * Set the content id and description
     *
     * @param int    $contentId          The content id
     * @param string $contentDescription The content description
     *
     * @return \Square1\MobileBill\Api
     */
    public function content($contentId, $contentDescription)
    {
        //Set client id and description
        $this->request->set('CONTENTID', $contentId);
        $this->request->set('CONTENTDESCRIPTION', $contentDescription);

        return $this;
    }

    /**
     * Set the users phone number (& optional operator id)
     *
     * @param int $phoneNumber The 12 digit mobile number, ie '353871234567'
     * @param int $operatorId  The operator id (optional)
     *
     * @return \Square1\MobileBill\Api
     */
    public function phone($phoneNumber, $operatorId = '')
    {
        $this->request->set('MSISDN', $phoneNumber);

        //Set operator id
        if (!empty($operatorId)) {
            $this->request->set('OPERATORID', $operatorId);
        }

        return $this;
    }

    /**
     * Charge a mobile phone
     *
     * @param int    $amount    The transaction amount in cents (max '3000')
     * @param string $reference The user reference
     * @param int    $channel   The payment channel (default '1')
     * @param string $currency  The currecny code (default 'EUR')
     *
     * @return \Square1\MobileBill\Api
     */
    public function charge($amount, $reference, $channel = '1', $currency = 'EUR')
    {
        $charge = new ChargeApi($this->request);

        $charge->create(
            array(
                'TRANSACTIONAMOUNT' => $amount,
                'REFERENCE'         => $reference,
                'CHANNEL'           => $channel,
                'CURRENCYCODE'      => $currency
            )
        );

        return $this;
    }

    /**
     * Trigger the API request
     *
     * @return array response array
     */
    public function send()
    {
        return $this->request->send();
    }
}


text:
/*
 Blender Options:
 -b or --background <file>	Load <file> in background (often used for UI-less rendering)
 -a or --render-anim 	Render frames from start to end (inclusive)
 -S or --scene <name>	Set the active scene <name> for rendering
 -f or --render-frame <frame>	Render frame <frame> and save it.	+<frame> start frame relative, -<frame> end frame relative.
 -s or --frame-start <frame>	Set start to frame <frame> (use before the -a argument)
 -e or --frame-end <frame>	Set end to frame <frame> (use before the -a argument)
 -j or --frame-jump <frames>	Set number of frames to step forward after each rendered frame
 -o or --render-output <path>	Set the render path and file name.	Use // at the start of the path to
 render relative to the blend file.	The # characters are replaced by the frame number, and used to define zero padding.
 ani_##_test.png becomes ani_01_test.png
 test-######.png becomes test-000001.png
 When the filename does not contain #, The suffix #### is added to the filename	The frame number will be added at the end of the filename.
 eg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a
 //render_ becomes //render_####, writing frames as //render_0001.png//
 -E or --engine <engine>	Specify the render engine	use -E help to list available engines

 Format Options:
 -F or --render-format <format>	Set the render format, Valid options are...
 TGA IRIS JPEG MOVIE IRIZ RAWTGA
 AVIRAW AVIJPEG PNG BMP FRAMESERVER	(formats that can be compiled into blender, not available on all systems)
 HDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS
 -x or --use-extension <bool>	Set option to add the file extension to the end of the file
 -t or --threads <threads>	Use amount of <threads> for rendering in background	[1-64], 0 for systems processor count.

 Animation Playback Options:
 -a <options> <file(s)>	Playback <file(s)>, only operates this way when not running in background.
 -p <sx> <sy>	Open with lower left corner at <sx>, <sy>
 -m		Read from disk (Don't buffer)
 -f <fps> <fps-base>		Specify FPS to start with
 -j <frame>	Set frame step to <frame>

 Window Options:
 -w or --window-border 	Force opening with borders (default)
 -W or --window-borderless 	Force opening without borders
 -p or --window-geometry <sx> <sy> <w> <h>	Open with lower left corner at <sx>, <sy> and width and height as <w>, <h>
 -con or --start-console 	Start with the console window open (ignored if -b is set)

 Game Engine Specific Options:
 -g Game Engine specific options
 -g fixedtime		Run on 50 hertz without dropping frames
 -g vertexarrays		Use Vertex Arrays for rendering (usually faster)
 -g nomipmap		No Texture Mipmapping
 -g linearmipmap		Linear Texture Mipmapping instead of Nearest (default)

 Misc Options:
 -d or --debug 	Turn debugging on
 * Prints every operator call and their arguments
 * Disables mouse grab (to interact with a debugger in some cases)
 * Keeps python sys.stdin rather than setting it to None
 --debug-fpe 	Enable floating point exceptions
 --debug-ffmpeg 	Enable debug messages from FFmpeg library
 --debug-libmv 	Enable debug messages from libmv library

 --factory-startup 	Skip reading the "startup.blend" in the users home directory

 --env-system-datafiles 	Set the BLENDER_SYSTEM_DATAFILES environment variable
 --env-system-scripts 	Set the BLENDER_SYSTEM_SCRIPTS environment variable
 --env-system-python 	Set the BLENDER_SYSTEM_PYTHON environment variable

 -nojoystick 	Disable joystick support
 -noglsl 	Disable GLSL shading
 -noaudio 	Force sound system to None
 -setaudio 	Force sound system to a specific device	NULL SDL OPENAL JACK

 -h or --help 	Print this help text and exit

 -y or --enable-autoexec 	Enable automatic python script execution, (default)
 -Y or --disable-autoexec 	Disable automatic python script execution (pydrivers & startup scripts)

 -P or --python <filename>	Run the given Python script (filename or Blender Text)
 --python-console 	Run blender with an interactive console
 --addons 	Comma separated list of addons (no spaces)
 -v or --version 	Print Blender version and exit
 -- 	Ends option processing, following arguments passed unchanged. Access via python's sys.argv
 Other Options:
 /? 	Print this help text and exit (windows only)
 --debug-python 	Enable debug messages for python
 --debug-events 	Enable debug messages for the event system
 --debug-wm 	Enable debug messages for the window manager
 --debug-all 	Enable all debug messages (excludes libmv)
 --debug-value <value>	Set debug value of <value> on startup

 --debug-jobs 	Enable time profiling for background jobs.
 --verbose <verbose>	Set logging verbosity level.
 -R 	Register .blend extension, then exit (Windows only)
 -r 	Silently register .blend extension, then exit (Windows only)
 Argument Parsing:	arguments must be separated by white space. eg
 "blender -ba test.blend"
 ...will ignore the 'a'
 "blender -b test.blend -f8"
 ...will ignore 8 because there is no space between the -f and the frame value
 Argument Order:
 Arguments are executed in the order they are given. eg
 "blender --background test.blend --render-frame 1 --render-output /tmp"
 ...will not render to /tmp because '--render-frame 1' renders before the output path is set
 "blender --background --render-output /tmp test.blend --render-frame 1"
 ...will not render to /tmp because loading the blend file overwrites the render output that was set
 "blender --background test.blend --render-output /tmp --render-frame 1" works as expected.

 Environment Variables:
 $BLENDER_USER_CONFIG      Directory for user configuration files.
 $BLENDER_USER_SCRIPTS     Directory for user scripts.
 $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.
 $Directory for user data files (icons, translations, ..).
 $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.
 $BLENDER_SYSTEM_PYTHON    Directory for system python libraries.
 $TMP or $TMPDIR           Store temporary files here.
 $SDL_AUDIODRIVER          LibSDL audio driver - alsa, esd, dma.
 $PYTHONHOME               Path to the python directory, eg. /usr/lib/python.

 blender/config
 blender/scripts
 blender/userscripts
 */
package com.jme3.gde.blender;

import com.jme3.gde.blender.scripts.Scripts;
import java.awt.Frame;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.modules.InstalledFileLocator;
import org.openide.modules.Places;
import org.openide.util.Exceptions;
import org.openide.util.Utilities;
import org.openide.windows.WindowManager;

/**
 *
 * @author normenhansen
 */
public class BlenderTool {

    public static final String TEMP_SUFFIX = "blend";
    private static final String mainFolderName = "blender";
    private static final String configFolderName = mainFolderName + "/config";
    private static final String scriptsFolderName = mainFolderName + "/scripts";
    private static final String jmeScriptsFolderName = mainFolderName + "/jmescripts";
    private static final String userScriptsFolderName = mainFolderName + "/userscripts";
    private static final String tempFolderName = mainFolderName + "/temp";
    private static final Logger logger = Logger.getLogger(BlenderTool.class.getName());
    private static final AtomicBoolean blenderOpened = new AtomicBoolean(false);

    private static String getBlenderExeName() {
        if (Utilities.isWindows()) {
            return "blender.exe";
        } else {
            return "blender";
        }
    }

    private static String getBlenderOsPath() {
        if (Utilities.isMac()) {
            return "../blender/blender.app/Contents/MacOS";
        } else {
            return "../blender";
        }
    }

    private static String getBlenderOsSettingsPath() {
        if (Utilities.isMac()) {
            return "../blender/blender.app/Contents/Resources";
        } else {
            return "../blender";
        }
    }

    /**
     * We create a lot of own directories to place our scripts inside, have config/preferences files stored there etc.
     * That's the place were we check for their existance and create them if necessary
     * Note: We don't use config/scripts folder's anymore in favour of the blender internal paths.
     * @return
     */
    private static boolean checkBlenderFolders() {
        String jmpDir = Places.getUserDirectory().getAbsolutePath();
        FileObject fileObject = FileUtil.toFileObject(new File(jmpDir));
        if (fileObject != null) {
            //FileObject configFileObject = fileObject.getFileObject(configFolderName);
            //FileObject scriptsFileObject = fileObject.getFileObject(scriptsFolderName);
            FileObject jmeScriptsFileObject = fileObject.getFileObject(jmeScriptsFolderName);
            FileObject userScriptsFileObject = fileObject.getFileObject(userScriptsFolderName);
            /* if (configFileObject == null) {
                try {
                    configFileObject = FileUtil.createFolder(fileObject, configFolderName);
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                    return false;
                }
            }
            if (scriptsFileObject == null) {
                try {
                    scriptsFileObject = FileUtil.createFolder(fileObject, scriptsFolderName);
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                    return false;
                }
            }*/
            if (jmeScriptsFileObject == null) {
                try {
                    jmeScriptsFileObject = FileUtil.createFolder(fileObject, jmeScriptsFolderName);
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                    return false;
                }
            }
            if (userScriptsFileObject == null) {
                try {
                    userScriptsFileObject = FileUtil.createFolder(fileObject, userScriptsFolderName);
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                    return false;
                }
            }
            Scripts.copyToFolder(jmeScriptsFileObject); /* Unpack our converter scripts */
        } else {
            logger.log(Level.SEVERE, "No global settings folder found!");
            return false;
        }
        return true;
    }

    /**
     * This is the Path where blender will store all changes to the config.
     * Note that this is not the blender default so you'll see different settings when launching blender from inside the SDK
     * Why? Good question actually.
     * @return
     */
    private static String getConfigEnv() {
        String ret = Places.getUserDirectory().getAbsolutePath() + "/" + configFolderName;
        ret = ret.replace("/", File.separator);
        return ret;
    }

    /**
     * This is the Path where blender itself stores it's scripts.
     * The plan was to take those scripts and reside them into a folder along with all the other scripts (UserScripts, ...),
     * We don't do this anymore because there's no real reason to copy all the scripts or even maintain them on your own.
     * Blender automatically takes care.
     * @return
     */
    private static String getSystemScriptsEnv() {
        //TODO: using installed blender scripts folder
        String ret = getBlenderSettingsFolder().getAbsolutePath() + "/" + "scripts";
        //String ret = System.getProperty("netbeans.user") + "/" + scriptsFolderName;
        ret = ret.replace("/", File.separator);
        return ret;
    }

    /**
     * This is the Path where we put custom userscripts inside.
     * They would be available inside blender (examples would be some jmonkey-animation-helper-addon)
     * @return The directory where the user scripts are
     */
    private static String getUserScriptsEnv() {
        String ret = Places.getUserDirectory().getAbsolutePath() + "/" + userScriptsFolderName;
        ret = ret.replace("/", File.separator);
        return ret;
    }

    /**
     * Get the full path to that script.
     * Those are the scripts that come with jMonkeyEngine (so neither user nor system)
     * @param scriptName The name of the Script
     * @param prefix The prefix like "import" or "tool"
     * @return The whole absolute path to that script
     */
    private static String getScriptPath(String scriptName, String prefix) {
        String ret = Places.getUserDirectory().getAbsolutePath() + "/" + jmeScriptsFolderName + "/" + prefix + "_" + scriptName + ".py";
        ret = ret.replace("/", File.separator);
        return ret;
    }

    private static File getBlenderExecutable() {
        File blender = InstalledFileLocator.getDefault().locate(getBlenderOsPath() + "/" + getBlenderExeName(), null, false);
        if (blender == null) {
            DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender executable"));
            logger.log(Level.SEVERE, "Error finding Blender executable");
        }
        return blender;
    }

    /**
     * Get the main folder of blender where all resources are found:
     * System Scripts, Bundled Python, etc.
     * We don't need this anymore see {@link #getSystemScriptsEnv() }
     * @return
     */
    private static File getBlenderSettingsFolder() {
        File blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.76", null, false); /* Update this every new Blender Version you use */
        if (blender == null) {
            blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.75", null, false);
        }
        if (blender == null) {
            blender = InstalledFileLocator.getDefault().locate(getBlenderOsSettingsPath() + "/2.69", null, false);
        }
        if (blender == null) {
            DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender settings"));
            logger.log(Level.SEVERE, "Error finding Blender settings");
        }
        return blender;
    }

    private static File getBlenderRootFolder() {
        File blender = InstalledFileLocator.getDefault().locate(getBlenderOsPath(), null, false);
        if (blender == null) {
            DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender root folder"));
            logger.log(Level.SEVERE, "Error finding Blender root folder");
        }
        return blender;
    }

    /**
     * Run Blender to convert .fbx or similar files to a blender file which can then be imported to .j3o
     * @param type The Filetype (extension)
     * @param input The FileObject (Input). It will be placed the same but with .blend
     * @return Success or not.
     */
    public static boolean runConversionScript(String type, FileObject input) {
        if (!checkBlenderFolders()) {
            logger.log(Level.SEVERE, "Could not create blender settings folders!");
            return false;
        }
        final File exe = getBlenderExecutable();
        if (exe == null) {
            logger.log(Level.SEVERE, "Could not find blender executable!");
            return false;
        }
        logger.log(Level.INFO, "Running blender as converter for file {0}", input.getPath());
        String scriptPath = getScriptPath(type, "import");
        String inputPath = input.getPath().replace("/", File.separator);
        String inputFolder = input.getParent().getPath().replace("/", File.separator) + File.separator;
        String outputPath = inputFolder + input.getName() + "." + TEMP_SUFFIX;
        try {
            String command = exe.getAbsolutePath();
            ProcessBuilder buildr = new ProcessBuilder(command, "-b",
                    "--factory-startup",
                    "-P", scriptPath,
                    "--",
                    "-i", inputPath,
                    "-o", outputPath);
            buildr.directory(getBlenderRootFolder());
            //buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
            //buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getSystemScriptsEnv());
            buildr.environment().put("BLENDER_USER_SCRIPTS", getUserScriptsEnv());
            Process proc = buildr.start();
            OutputReader outReader = new OutputReader(proc.getInputStream());
            OutputReader errReader = new OutputReader(proc.getErrorStream());
            outReader.start();
            errReader.start();
            try {
                proc.waitFor();
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            }
            if (proc.exitValue() != 0) {
                logger.log(Level.SEVERE, "Error running blender!");
                return false;
            }
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
        return true;
    }

    /**
     * This will run a tool instead of an importer.
     * See {@link #runConversionScript(java.lang.String, org.openide.filesystems.FileObject) }
     * @param toolName The tool to use
     * @param input The file to process
     * @return sucess?
     */
    public static boolean runToolScript(String toolName, FileObject input) {
        if (!checkBlenderFolders()) {
            logger.log(Level.SEVERE, "Could not create blender settings folders!");
            return false;
        }
        final File exe = getBlenderExecutable();
        if (exe == null) {
            logger.log(Level.SEVERE, "Could not find blender executable!");
            return false;
        }
        logger.log(Level.INFO, "Running blender as {0} tool for file {1}", new Object[]{toolName, input.getPath()});
        String scriptPath = getScriptPath(toolName, "tool");
        String inputPath = input.getPath().replace("/", File.separator);
        try {
            String command = exe.getAbsolutePath();
            ProcessBuilder buildr = new ProcessBuilder(command, "-b",
                    "--factory-startup",
                    "-P", scriptPath,
                    "--",
                    "-i", inputPath);
            buildr.directory(getBlenderRootFolder());
            //buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
            //buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getSystemScriptsEnv());
            buildr.environment().put("BLENDER_USER_SCRIPTS", getUserScriptsEnv());
            Process proc = buildr.start();
            OutputReader outReader = new OutputReader(proc.getInputStream());
            OutputReader errReader = new OutputReader(proc.getErrorStream());
            outReader.start();
            errReader.start();
            try {
                proc.waitFor();
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            }
            if (proc.exitValue() != 0) {
                logger.log(Level.SEVERE, "Error running blender!");
                return false;
            }
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
        return true;
    }

    /**
     * Simply open that Blender File
     * @param file The file/path to open
     * @param async Should this method lock until blender has finished?
     * @return sucess?
     */
    private static boolean runBlender(final String file, boolean async) {
        if (!checkBlenderFolders()) {
            logger.log(Level.SEVERE, "Could not create blender settings folders!");
            return false;
        }
        logger.log(Level.INFO, "Running blender with options {0}", file);
        if (blenderOpened.getAndSet(true)) {
            logger.log(Level.WARNING, "Blender seems to be running already.");
            return false;
        }
        final AtomicBoolean successful = new AtomicBoolean(true);
        final File exe = getBlenderExecutable();
        if (exe == null) {
            logger.log(Level.SEVERE, "Could not find blender executable!");
            blenderOpened.set(false);
            return false;
        }
        final Frame mainWin = WindowManager.getDefault().getMainWindow();
        assert (mainWin != null);
        mainWin.setExtendedState(Frame.ICONIFIED);
        Runnable r = new Runnable() {
            public void run() {
                try {
                    String command = exe.getAbsolutePath();
                    ProcessBuilder buildr = new ProcessBuilder(command, file);
                    buildr.directory(getBlenderRootFolder()); /* Set working Directory to where the executables are */
                    //buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
                    //buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getSystemScriptsEnv());
                    buildr.environment().put("BLENDER_USER_SCRIPTS", getUserScriptsEnv());
                    Process proc = buildr.start();
                    OutputReader outReader = new OutputReader(proc.getInputStream());
                    OutputReader errReader = new OutputReader(proc.getErrorStream());
                    outReader.start();
                    errReader.start();
                    try {
                        proc.waitFor();
                    } catch (InterruptedException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                    if (proc.exitValue() == 0) {
                        successful.set(true);
                    }
                } catch (Exception ex) {
                    Exceptions.printStackTrace(ex);
                    successful.set(false);
                } finally {
                    blenderOpened.set(false);
                    java.awt.EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            mainWin.setExtendedState(Frame.NORMAL);
                            mainWin.requestFocus();
                        }
                    });
                }
            }
        };
        if (async) {
            new Thread(r).start();
        } else {
            r.run();
        }
        return successful.get();
    }

    /**
     * Open the file in Blender.
     * Note: Path Seperators are automatically converted, so always use the unix "/" way.
     * @param file The File to open
     * @return Whether we had success or not
     */
    public static boolean openInBlender(FileObject file) {
        String path = file.getPath().replace("/", File.separator);
        return runBlender(path, true);
    }

    /**
     * Simply just run Blender
     */
    public static void runBlender() {
        if (!runBlender(null, true)) {
            logger.log(Level.INFO, "Could not run blender, already running? Trying to focus window.");
            DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Blender is already running!"));
        }
    }
}


text:
<?php
namespace Litter\Tests;

use Litter\Litter;

class LitterTest extends \PHPUnit_Framework_TestCase {
	function testArrayIteration() {
		$array = array("foo" => "bar", "baz" => "buz");
		$l = new Litter($array);
		$this->assertEquals($array, array_map("strval", iterator_to_array($l)));
	}
	function testTraversableIteration() {
		$dom = simplexml_load_string('
			<root>
				<child>value1</child>
				<child>value2</child>
			</root>');
		$l = new Litter($dom->child);
		$this->assertEquals(
			array("value1", "value2"),
			array_map("strval", iterator_to_array($l, FALSE)));
	}
	function testStdClassIteration() {
		$array = array("foo" => "bar", "baz" => "buz");
		$l = new Litter((object)$array);
		$this->assertEquals($array, array_map("strval", iterator_to_array($l)));
	}
	function testCount() {
		$this->assertEquals(5, $this->provider()->count());

		$l = new Litter("foobar");
		$this->assertEquals(6, $l->count());
	}
	function testLength() {
		$l = $this->provider();
		$this->assertEquals($l->count(), $l->length());
	}
	function testIndex() {
		$i = 0;
		foreach ($this->provider() as $v) {
			$this->assertEquals(++$i, $v->index()->raw());
		}

		$i = 0;
		foreach ($this->provider() as $v) {
			$this->assertEquals($i++, $v->index(TRUE)->raw());
		}
	}
	/**
	 *	@expectedException Litter\Exception
	 */
	function testIndexOutsideLoopError() {
		$this->provider()->index();
	}
	/**
	 *	Remember that suhosin.executor.include.whitelist must allow data as protocol
	 *	and allow_url_include must be turned on in php.ini
	 */
	function testStringSource() {
		$this->assertEquals(
			include Litter::stringSource("<?php return 5; ?>"),
			5);
	}
	function testCycle() {
		$r = array();
		foreach ($this->provider() as $p) {
			$r[] = $p->cycle(array("a", "b", "c"))->raw();
		}
		$this->assertEquals($r, array("a", "b", "c", "a", "b"));
	}
	/**
	 *	@expectedException Litter\Exception
	 */
	function testCycleOutsideLoopError() {
		$this->provider()->cycle(array(1, 2));
	}
	function testUpper() {
		$l = new Litter("Törst");
		$this->assertEquals("TÖRST", $l->upper()->raw());
	}
	function testLower() {
		$l = new Litter("TÖRST");
		$this->assertEquals("törst", $l->lower()->raw());
	}
	function testReplace() {
		$l = new Litter("Törst");
		$this->assertEquals(
			"Torsk",
			$l->replace(array("ö" => "o", "t" => "k"))->raw());
	}
	function testSlice() {
		$l = $this->provider();
		$this->assertEquals(
			array("3", "4"),
			array_map("strval", iterator_to_array($l->slice(3), FALSE)));
	}
	function testEncode() {
		$l = new Litter("<&");
		$l = $l->encode("HTML-ENTITIES");
		$this->assertEquals("<&", $l->raw());
		$this->assertEquals("<&", $l->encode("UTF-8")->raw());

		$l = new Litter("åäö");
		$latin = $l->encode("ISO-8859-1");
		$this->assertEquals(3, strlen($latin->raw()));
		$this->assertEquals(6, strlen($latin->encode("UTF-8")->raw()));
	}
	/**
	 *	@expectedException \InvalidArgumentException
	 */
	function testInvalidEncodingException() {
		$this->provider()->encode("klingon");
	}
	function testToString() {
		$l = new Litter("<täst/>");
		$this->assertEquals("<täst/>", (string)$l);
	}
	/**
	 *	@depends testCount
	 */
	function testTruncate() {
		$l = new Litter("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
		$this->assertEquals("ABCDEF", $l->truncate(6)->raw());
		$this->assertEquals("ABC...", $l->truncate(6, "...")->raw());
		$this->assertEquals($l->count(), $l->truncate($l->count())->count());
	}
	function testJoin() {
		$l = new Litter("Test");
		$this->assertEquals("T,e,s,t", $l->join(",")->raw());

		$this->assertEquals("0,1,2,3,4", $this->provider()->join(",")->raw());
	}
	function testClone() {
		$l = $this->provider();
		$this->assertEquals($l, clone $l);
	}
	function testInnerIterator() {
		$iter = new \ArrayIterator(array(1, 2, 3));
		$l = new Litter($iter);
		$this->assertEquals($l->getInnerIterator(), $iter);
	}
	function testGroup() {
		$r = array();
		foreach($this->provider()->group(2) as $v) {
			$r[] = array_map("strval", iterator_to_array($v, FALSE));
		}
		$this->assertEquals(
			$r,
			array(
				array("0", "1"),
				array("2", "3"),
				array("4")));
	}
	/**
	 *	@expectedException Litter\Exception
	 */
	function testNonIterableValueError() {
		$l = new Litter(FALSE);
		foreach ($l as $v) { }
	}

	// Test array access
	function testArrayAccessGet() {
		$l = new Litter(array("test" => "foobar"));
		$this->assertEquals("foobar", $l["test"]->raw());

		$l = new Litter("foobar");
		$this->assertEquals("b", $l[3]->raw());

		$obj = new \stdClass;
		$obj->test = "foobar";
		$l = new Litter($obj);
		$this->assertEquals("foobar", $l["test"]->raw());
	}
	function testArrayAccessIsset() {
		$l = new Litter(array("test" => "foobar"));
		$this->assertTrue(isset($l["test"]));
		$this->assertTrue(!isset($l["baz"]));

		$l = new Litter("foobar");
		$this->assertTrue(isset($l[3]));
		$this->assertTrue(!isset($l[6]));

		$obj = new \stdClass;
		$obj->test = "foobar";
		$l = new Litter($obj);
		$this->assertTrue(isset($l["test"]));
		$this->assertTrue(!isset($l["baz"]));
	}
	/**
	 *	@expectedException Litter\ReadOnlyException
	 */
	function testArrayAccessSet() {
		$l = new Litter(array("test" => "foobar"));
		$l["test"] = "baz";
	}
	/**
	 *	@expectedException Litter\ReadOnlyException
	 */
	function testArrayAccessUnset() {
		$l = new Litter(array("test" => "foobar"));
		unset($l["test"]);
	}
	/**
	 *	@expectedException \InvalidArgumentException
	 */
	function testArrayAccessStringNonIntegerIssetError() {
		$l = new Litter("foobar");
		isset($l["3"]);
	}
	/**
	 *	@expectedException \InvalidArgumentException
	 */
	function testArrayAccessStringNonIntegerGetError() {
		$l = new Litter("foobar");
		$l["3"];
	}
	/**
	 *	@expectedException Litter\NotImplementedException
	 */
	function testArrayAccessUnsupportedGetError() {
		$l = new Litter(FALSE);
		$l[0];
	}
	/**
	 *	@expectedException Litter\NotImplementedException
	 */
	function testArrayAccessUnsupportedIssetError() {
		$l = new Litter(FALSE);
		isset($l[0]);
	}

	// Test object access
	function testObjectGet() {
		$l = new Litter(array("test" => "foobar"));
		$this->assertEquals("foobar", $l->test->raw());

		$obj = new \stdClass;
		$obj->test = "foobar";
		$l = new Litter($obj);
		$this->assertEquals("foobar", $l->test->raw());
	}
	function testObjectIsset() {
		$l = new Litter(array("test" => "foobar"));
		$this->assertTrue(isset($l->test));
		$this->assertTrue(!isset($l->foo));
	}
	/**
	 *	@expectedException Litter\ReadOnlyException
	 */
	function testObjectSet() {
		$l = new Litter(array("test" => "foobar"));
		$l->test = "baz";
	}
	/**
	 *	@expectedException Litter\ReadOnlyException
	 */
	function testObjectUnset() {
		$l = new Litter(array("test" => "foobar"));
		unset($l->test);
	}
	/**
	 *	@expectedException Litter\NotImplementedException
	 */
	function testObjectUnsupportedGetError() {
		$l = new Litter(FALSE);
		$l->foo;
	}

	/**
	 *	@group   templating
	 *	@depends testStringSource
	 */
	function testTemplatingBaseFile() {
		ob_start();
		$l = new Litter;

		include Litter::stringSource(
			'foo<?php $l->block("baz"); ?>bar<?php $l->end(); ?>');

		$this->assertEquals("foobar", ob_get_clean());
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 */
	function testTemplatingSingleLevelInheritance() {
		ob_start();
		$l = new Litter;
		$base_src = Litter::stringSource(
			'foo<?php $l->block("baz"); ?>bar<?php $l->end(); ?>');

		$l->extending($base_src);
			$l->block("baz");
				echo "biz";
			$l->end();
		$l->done();

		$this->assertEquals("foobiz", ob_get_clean());
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 */
	function testTemplatingSingleLevelSuperInheritance() {
		ob_start();
		$l = new Litter;
		$base_src = Litter::stringSource(
			'foo<?php $l->block("baz"); ?>bar<?php $l->end(); ?>');

		$l->extending($base_src);
			$l->block("baz");
				echo "biz";
				$l->super();
			$l->end();
		$l->done();
		$this->assertEquals("foobizbar", ob_get_clean());
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 */
	function testTemplatingMultipleLevelInheritance() {
		ob_start();
		$l = new Litter;
		$second_src = Litter::stringSource(
			'<?php
				$base_src = $l->stringSource(
					\'foo<?php $l->block("baz"); ?>bar<?php $l->end(); ?>\');
				$l->extending($base_src);
					$l->block("baz");
						echo "biz";
					$l->end();
				$l->done();
			?>');

		$l->extending($second_src);
			$l->block("baz");
				echo "baz";
			$l->end();
		$l->done();

		$this->assertEquals("foobaz", ob_get_clean());
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 */
	function testTemplatingMultipleLevelSuperInheritance() {
		ob_start();
		$l = new Litter;
		$second_src = Litter::stringSource(
			'<?php
				$base_src = $l->stringSource(
					\'foo<?php $l->block("baz"); ?>bar<?php $l->end(); ?>\');
				$l->extending($base_src);
					$l->block("baz");
						echo "biz";
						$l->super();
					$l->end();
				$l->done();
			?>');

		$l->extending($second_src);
			$l->block("baz");
				$l->super();
				echo "baz";
			$l->end();
		$l->done();

		$this->assertEquals("foobizbarbaz", ob_get_clean());
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testStrayEndError() {
		$l = new Litter;
		$l->end();
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testStrayDoneError() {
		$l = new Litter;
		$l->done();
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testNestedBlocksWhenExtendingError() {
		$l = new Litter;
		$l->extending(Litter::stringSource(""))->block("parent")->block("child");
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testDoneWhenOpenBlockError() {
		$l = new Litter;
		$l->extending(Litter::stringSource(""))->block("parent")->done();
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testExtendWhenExtendingError() {
		$l = new Litter;
		$l->extending(Litter::stringSource(""))->extending(Litter::stringSource(""));
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testExtendWithinBlockError() {
		$l = new Litter;
		$l->block("dummy")->extending(Litter::stringSource(""));
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testMultipleSuperWithinBlockError() {
		$l = new Litter;
		$l->extending(Litter::stringSource(""))->block("dummy")->super()->super();
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testBaseTemplateSuperError() {
		$l = new Litter;
		$l->block("dummy")->super();
	}
	/**
	 *	@group   templating
	 *	@depends testStringSource
	 *	@expectedException Litter\Exception
	 */
	function testStraySuperError() {
		$l = new Litter;
		$l->super();
	}

	function provider() {
		return new Litter(5);
	}
}


text:
class CreateFeAddresses < ActiveRecord::Migration
  def change
    create_table :fe_addresses do |t|
      t.datetime :startdate
      t.datetime :enddate
      t.string :address1
      t.string :address2
      t.string :address3
      t.string :address4
      t.string :address_type
      t.string :city
      t.string :state
      t.string :zip
      t.string :country
      t.integer :person_id

      t.timestamps
    end
  end
end