text:
package org.apache.commons.jcs3.auxiliary.remote.server;

import java.io.IOException;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.RMISocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.jcs3.access.exception.CacheException;
import org.apache.commons.jcs3.auxiliary.remote.behavior.IRemoteCacheListener;
import org.apache.commons.jcs3.auxiliary.remote.server.behavior.IRemoteCacheServer;
import org.apache.commons.jcs3.auxiliary.remote.server.behavior.IRemoteCacheServerAttributes;
import org.apache.commons.jcs3.auxiliary.remote.server.behavior.RemoteType;
import org.apache.commons.jcs3.engine.CacheEventQueueFactory;
import org.apache.commons.jcs3.engine.CacheListeners;
import org.apache.commons.jcs3.engine.behavior.ICacheElement;
import org.apache.commons.jcs3.engine.behavior.ICacheEventQueue;
import org.apache.commons.jcs3.engine.behavior.ICacheListener;
import org.apache.commons.jcs3.engine.control.CompositeCache;
import org.apache.commons.jcs3.engine.control.CompositeCacheManager;
import org.apache.commons.jcs3.engine.logging.CacheEvent;
import org.apache.commons.jcs3.engine.logging.behavior.ICacheEvent;
import org.apache.commons.jcs3.engine.logging.behavior.ICacheEventLogger;
import org.apache.commons.jcs3.log.Log;
import org.apache.commons.jcs3.log.LogManager;
import org.apache.commons.jcs3.utils.timing.ElapsedTimer;

/**
 * This class provides remote cache services. The remote cache server propagates events from local
 * caches to other local caches. It can also store cached data, making it available to new clients.
 *

 * Remote cache servers can be clustered. If the cache used by this remote cache is configured to
 * use a remote cache of type cluster, the two remote caches will communicate with each other.
 * Remote and put requests can be sent from one remote to another. If they are configured to
 * broadcast such event to their client, then remove an puts can be sent to all locals in the
 * cluster.
 *

 * Get requests are made between clustered servers if AllowClusterGet is true. You can setup several
 * clients to use one remote server and several to use another. The get local will be distributed
 * between the two servers. Since caches are usually high get and low put, this should allow you to
 * scale.
 */
public class RemoteCacheServer<K, V>
    extends UnicastRemoteObject
    implements IRemoteCacheServer<K, V>, Unreferenced
{
    public static final String DFEAULT_REMOTE_CONFIGURATION_FILE = "/remote.cache.ccf";

    /** For serialization. Don't change. */
    private static final long serialVersionUID = -8072345435941473116L;

    /** log instance */
    private static final Log log = LogManager.getLog( RemoteCacheServer.class );

    /** Number of puts into the cache. */
    private int puts;

    /** Maps cache name to CacheListeners object. association of listeners (regions). */
    private final transient ConcurrentMap<String, CacheListeners<K, V>> cacheListenersMap =
        new ConcurrentHashMap<>();

    /** maps cluster listeners to regions. */
    private final transient ConcurrentMap<String, CacheListeners<K, V>> clusterListenersMap =
        new ConcurrentHashMap<>();

    /** The central hub */
    private transient CompositeCacheManager cacheManager;

    /** relates listener id with a type */
    private final ConcurrentMap<Long, RemoteType> idTypeMap = new ConcurrentHashMap<>();

    /** relates listener id with an ip address */
    private final ConcurrentMap<Long, String> idIPMap = new ConcurrentHashMap<>();

    /** Used to get the next listener id. */
    private final int[] listenerId = new int[1];

    /** Configuration settings. */
    // package protected for access by unit test code
    final IRemoteCacheServerAttributes remoteCacheServerAttributes;

    /** The interval at which we will log updates. */
    private final int logInterval = 100;

    /** An optional event logger */
    private transient ICacheEventLogger cacheEventLogger;

    /**
     * Constructor for the RemoteCacheServer object. This initializes the server with the values
     * from the properties object.
     *

     * @param rcsa
     * @param config cache hub configuration
     * @throws RemoteException
     */
    protected RemoteCacheServer( final IRemoteCacheServerAttributes rcsa, final Properties config )
        throws RemoteException
    {
        super( rcsa.getServicePort() );
        this.remoteCacheServerAttributes = rcsa;
        init( config );
    }

    /**
     * Constructor for the RemoteCacheServer object. This initializes the server with the values
     * from the properties object.
     *

     * @param rcsa
     * @param config cache hub configuration
     * @param customRMISocketFactory
     * @throws RemoteException
     */
    protected RemoteCacheServer( final IRemoteCacheServerAttributes rcsa, final Properties config, final RMISocketFactory customRMISocketFactory )
        throws RemoteException
    {
        super( rcsa.getServicePort(), customRMISocketFactory, customRMISocketFactory );
        this.remoteCacheServerAttributes = rcsa;
        init( config );
    }

    /**
     * Initialize the RMI Cache Server from a properties object.
     *

     * @param prop the configuration properties
     * @throws RemoteException if the configuration of the cache manager instance fails
     */
    private void init( final Properties prop ) throws RemoteException
    {
        try
        {
            cacheManager = createCacheManager( prop );
        }
        catch (final CacheException e)
        {
            throw new RemoteException(e.getMessage(), e);
        }

        // cacheManager would have created a number of ICache objects.
        // Use these objects to set up the cacheListenersMap.
        cacheManager.getCacheNames().forEach(name -> {
            final CompositeCache<K, V> cache = cacheManager.getCache( name );
            cacheListenersMap.put( name, new CacheListeners<>( cache ) );
        });
    }

    /**
     * Subclass can override this method to create the specific cache manager.
     *

     * @param prop the configuration object.
     * @return The cache hub configured with this configuration.
     *
     * @throws CacheException if the configuration cannot be loaded
     */
    private CompositeCacheManager createCacheManager( final Properties prop ) throws CacheException
    {
        final CompositeCacheManager hub = CompositeCacheManager.getUnconfiguredInstance();
        hub.configure( prop );
        return hub;
    }

    /**
     * Puts a cache bean to the remote cache and notifies all listeners which

     *

     *
have a different listener id than the originating host;

     *
are currently subscribed to the related cache.

     *

     *

     * @param item
     * @throws IOException
     */
    public void put( final ICacheElement<K, V> item )
        throws IOException
    {
        update( item );
    }

    /**
     * @param item
     * @throws IOException
     */
    @Override
    public void update( final ICacheElement<K, V> item )
        throws IOException
    {
        update( item, 0 );
    }

    /**
     * The internal processing is wrapped in event logging calls.
     *

     * @param item
     * @param requesterId
     * @throws IOException
     */
    @Override
    public void update( final ICacheElement<K, V> item, final long requesterId )
        throws IOException
    {
        final ICacheEvent<ICacheElement<K, V>> cacheEvent = createICacheEvent( item, requesterId, ICacheEventLogger.UPDATE_EVENT );
        try
        {
            processUpdate( item, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * An update can come from either a local cache's remote auxiliary, or it can come from a remote
     * server. A remote server is considered a a source of type cluster.
     *

     * If the update came from a cluster, then we should tell the cache manager that this was a
     * remote put. This way, any lateral and remote auxiliaries configured for the region will not
     * be updated. This is basically how a remote listener works when plugged into a local cache.
     *

     * If the cluster is configured to keep local cluster consistency, then all listeners will be
     * updated. This allows cluster server A to update cluster server B and then B to update its
     * clients if it is told to keep local cluster consistency. Otherwise, server A will update
     * server B and B will not tell its clients. If you cluster using lateral caches for instance,
     * this is how it will work. Updates to a cluster node, will never get to the leaves. The remote
     * cluster, with local cluster consistency, allows you to update leaves. This basically allows
     * you to have a failover remote server.
     *

     * Since currently a cluster will not try to get from other cluster servers, you can scale a bit
     * with a cluster configuration. Puts and removes will be broadcasted to all clients, but the
     * get load on a remote server can be reduced.
     *

     * @param item
     * @param requesterId
     */
    private void processUpdate( final ICacheElement<K, V> item, final long requesterId )
    {
        final ElapsedTimer timer = new ElapsedTimer();
        logUpdateInfo( item );

        try
        {
            final CacheListeners<K, V> cacheDesc = getCacheListeners( item.getCacheName() );
            final boolean fromCluster = isRequestFromCluster( requesterId );

            log.debug( "In update, requesterId = [{0}] fromCluster = {1}", requesterId, fromCluster );

            // ordered cache item update and notification.
            synchronized ( cacheDesc )
            {
                try
                {
                    final CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

                    // If the source of this request was not from a cluster,
                    // then consider it a local update. The cache manager will
                    // try to
                    // update all auxiliaries.
                    //
                    // This requires that two local caches not be connected to
                    // two clustered remote caches. The failover runner will
                    // have to make sure of this. ALos, the local cache needs
                    // avoid updating this source. Will need to pass the source
                    // id somehow. The remote cache should update all local
                    // caches
                    // but not update the cluster source. Cluster remote caches
                    // should only be updated by the server and not the
                    // RemoteCache.
                    if ( fromCluster )
                    {
                        log.debug( "Put FROM cluster, NOT updating other auxiliaries for region. "
                                + " requesterId [{0}]", requesterId );
                        c.localUpdate( item );
                    }
                    else
                    {
                        log.debug( "Put NOT from cluster, updating other auxiliaries for region. "
                                + " requesterId [{0}]", requesterId );
                        c.update( item );
                    }
                }
                catch ( final IOException ce )
                {
                    // swallow
                    log.info( "Exception caught updating item. requesterId [{0}]: {1}",
                            requesterId, ce.getMessage() );
                }

                // UPDATE LOCALS IF A REQUEST COMES FROM A CLUSTER
                // IF LOCAL CLUSTER CONSISTENCY IS CONFIGURED
                if (!fromCluster || fromCluster && remoteCacheServerAttributes.isLocalClusterConsistency())
                {
                    final ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, requesterId );
                    log.debug( "qlist.length = {0}", qlist.length );
                    for (final ICacheEventQueue<K, V> element : qlist) {
                        element.addPutEvent( item );
                    }
                }
            }
        }
        catch ( final IOException e )
        {
            if ( cacheEventLogger != null )
            {
                cacheEventLogger.logError( "RemoteCacheServer", ICacheEventLogger.UPDATE_EVENT, e.getMessage()
                    + " REGION: " + item.getCacheName() + " ITEM: " + item );
            }

            log.error( "Trouble in Update. requesterId [{0}]", requesterId, e );
        }

        // TODO use JAMON for timing
        log.debug( "put took {0} ms.", timer::getElapsedTime);
    }

    /**
     * Log some details.
     *

     * @param item
     */
    private void logUpdateInfo( final ICacheElement<K, V> item )
    {
        // not thread safe, but it doesn't have to be 100% accurate
        puts++;

        if ( log.isInfoEnabled() && (puts % logInterval == 0) )
        {
            log.info( "puts = {0}", puts );
        }

        log.debug( "In update, put [{0}] in [{1}]",
                item::getKey, item::getCacheName);
    }

    /**
     * Returns a cache value from the specified remote cache; or null if the cache or key does not
     * exist.
     *

     * @param cacheName
     * @param key
     * @return ICacheElement
     * @throws IOException
     */
    @Override
    public ICacheElement<K, V> get( final String cacheName, final K key )
        throws IOException
    {
        return this.get( cacheName, key, 0 );
    }

    /**
     * Returns a cache bean from the specified cache; or null if the key does not exist.
     *

     * Adding the requestor id, allows the cache to determine the source of the get.
     *

     * The internal processing is wrapped in event logging calls.
     *

     * @param cacheName
     * @param key
     * @param requesterId
     * @return ICacheElement
     * @throws IOException
     */
    @Override
    public ICacheElement<K, V> get( final String cacheName, final K key, final long requesterId )
        throws IOException
    {
        ICacheElement<K, V> element = null;
        final ICacheEvent<K> cacheEvent = createICacheEvent( cacheName, key, requesterId, ICacheEventLogger.GET_EVENT );
        try
        {
            element = processGet( cacheName, key, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
        return element;
    }

    /**
     * Returns a cache bean from the specified cache; or null if the key does not exist.
     *

     * Adding the requester id, allows the cache to determine the source of the get.
     *

     * @param cacheName
     * @param key
     * @param requesterId
     * @return ICacheElement
     */
    private ICacheElement<K, V> processGet( final String cacheName, final K key, final long requesterId )
    {
        final boolean fromCluster = isRequestFromCluster( requesterId );

        log.debug( "get [{0}] from cache [{1}] requesterId = [{2}] fromCluster = {3}",
                key, cacheName, requesterId, fromCluster );

        final CacheListeners<K, V> cacheDesc = getCacheListeners( cacheName );

        return getFromCacheListeners( key, fromCluster, cacheDesc, null );
    }

    /**
     * Gets the item from the associated cache listeners.
     *

     * @param key
     * @param fromCluster
     * @param cacheDesc
     * @param element
     * @return ICacheElement
     */
    private ICacheElement<K, V> getFromCacheListeners( final K key, final boolean fromCluster, final CacheListeners<K, V> cacheDesc,
                                                 final ICacheElement<K, V> element )
    {
        ICacheElement<K, V> returnElement = element;

        if ( cacheDesc != null )
        {
            final CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

            // If we have a get come in from a client and we don't have the item
            // locally, we will allow the cache to look in other non local sources,
            // such as a remote cache or a lateral.
            //
            // Since remote servers never get from clients and clients never go
            // remote from a remote call, this
            // will not result in any loops.
            //
            // This is the only instance I can think of where we allow a remote get
            // from a remote call. The purpose is to allow remote cache servers to
            // talk to each other. If one goes down, you want it to be able to get
            // data from those that were up when the failed server comes back o
            // line.

            if ( !fromCluster && this.remoteCacheServerAttributes.isAllowClusterGet() )
            {
                log.debug( "NonLocalGet. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );
                returnElement = c.get( key );
            }
            else
            {
                // Gets from cluster type remote will end up here.
                // Gets from all clients will end up here if allow cluster get is
                // false.
                log.debug( "LocalGet. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );
                returnElement = c.localGet( key );
            }
        }

        return returnElement;
    }

    /**
     * Gets all matching items.
     *

     * @param cacheName
     * @param pattern
     * @return Map of keys and wrapped objects
     * @throws IOException
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMatching( final String cacheName, final String pattern )
        throws IOException
    {
        return getMatching( cacheName, pattern, 0 );
    }

    /**
     * Retrieves all matching keys.
     *

     * @param cacheName
     * @param pattern
     * @param requesterId
     * @return Map of keys and wrapped objects
     * @throws IOException
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMatching( final String cacheName, final String pattern, final long requesterId )
        throws IOException
    {
        final ICacheEvent<String> cacheEvent = createICacheEvent( cacheName, pattern, requesterId,
                                                    ICacheEventLogger.GETMATCHING_EVENT );
        try
        {
            return processGetMatching( cacheName, pattern, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * Retrieves all matching keys.
     *

     * @param cacheName
     * @param pattern
     * @param requesterId
     * @return Map of keys and wrapped objects
     */
    protected Map<K, ICacheElement<K, V>> processGetMatching( final String cacheName, final String pattern, final long requesterId )
    {
        final boolean fromCluster = isRequestFromCluster( requesterId );

        log.debug( "getMatching [{0}] from cache [{1}] requesterId = [{2}] fromCluster = {3}",
                pattern, cacheName, requesterId, fromCluster );

        CacheListeners<K, V> cacheDesc = null;
        try
        {
            cacheDesc = getCacheListeners( cacheName );
        }
        catch ( final Exception e )
        {
            log.error( "Problem getting listeners.", e );

            if ( cacheEventLogger != null )
            {
                cacheEventLogger.logError( "RemoteCacheServer", ICacheEventLogger.GETMATCHING_EVENT, e.getMessage()
                    + cacheName + " pattern: " + pattern );
            }
        }

        return getMatchingFromCacheListeners( pattern, fromCluster, cacheDesc );
    }

    /**
     * Gets the item from the associated cache listeners.
     *

     * @param pattern
     * @param fromCluster
     * @param cacheDesc
     * @return Map of keys to results
     */
    private Map<K, ICacheElement<K, V>> getMatchingFromCacheListeners( final String pattern, final boolean fromCluster, final CacheListeners<K, V> cacheDesc )
    {
        Map<K, ICacheElement<K, V>> elements = null;
        if ( cacheDesc != null )
        {
            final CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

            // We always want to go remote and then merge the items.  But this can lead to inconsistencies after
            // failover recovery.  Removed items may show up.  There is no good way to prevent this.
            // We should make it configurable.

            if ( !fromCluster && this.remoteCacheServerAttributes.isAllowClusterGet() )
            {
                log.debug( "NonLocalGetMatching. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );
                elements = c.getMatching( pattern );
            }
            else
            {
                // Gets from cluster type remote will end up here.
                // Gets from all clients will end up here if allow cluster get is
                // false.

                log.debug( "LocalGetMatching. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );
                elements = c.localGetMatching( pattern );
            }
        }
        return elements;
    }

    /**
     * Gets multiple items from the cache based on the given set of keys.
     *

     * @param cacheName
     * @param keys
     * @return a map of K key to ICacheElement<K, V> element, or an empty map if there is no
     *         data in cache for any of these keys
     * @throws IOException
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMultiple( final String cacheName, final Set<K> keys )
        throws IOException
    {
        return this.getMultiple( cacheName, keys, 0 );
    }

    /**
     * Gets multiple items from the cache based on the given set of keys.
     *

     * The internal processing is wrapped in event logging calls.
     *

     * @param cacheName
     * @param keys
     * @param requesterId
     * @return a map of K key to ICacheElement<K, V> element, or an empty map if there is no
     *         data in cache for any of these keys
     * @throws IOException
     */
    @Override
    public Map<K, ICacheElement<K, V>> getMultiple( final String cacheName, final Set<K> keys, final long requesterId )
        throws IOException
    {
        final ICacheEvent<Serializable> cacheEvent = createICacheEvent( cacheName, (Serializable) keys, requesterId,
                                                    ICacheEventLogger.GETMULTIPLE_EVENT );
        try
        {
            return processGetMultiple( cacheName, keys, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * Gets multiple items from the cache based on the given set of keys.
     *

     * @param cacheName
     * @param keys
     * @param requesterId
     * @return a map of K key to ICacheElement<K, V> element, or an empty map if there is no
     *         data in cache for any of these keys
     */
    private Map<K, ICacheElement<K, V>> processGetMultiple( final String cacheName, final Set<K> keys, final long requesterId )
    {
        final boolean fromCluster = isRequestFromCluster( requesterId );

        log.debug( "getMultiple [{0}] from cache [{1}] requesterId = [{2}] fromCluster = {3}",
                keys, cacheName, requesterId, fromCluster );

        final CacheListeners<K, V> cacheDesc = getCacheListeners( cacheName );
        return getMultipleFromCacheListeners( keys, null, fromCluster, cacheDesc );
    }

    /**
     * Since a non-receiving remote cache client will not register a listener, it will not have a
     * listener id assigned from the server. As such the remote server cannot determine if it is a
     * cluster or a normal client. It will assume that it is a normal client.
     *

     * @param requesterId
     * @return true is from a cluster.
     */
    private boolean isRequestFromCluster( final long requesterId )
    {
        final RemoteType remoteTypeL = idTypeMap.get( Long.valueOf( requesterId ) );
        return remoteTypeL == RemoteType.CLUSTER;
    }

    /**
     * Gets the items from the associated cache listeners.
     *

     * @param keys
     * @param elements
     * @param fromCluster
     * @param cacheDesc
     * @return Map
     */
    private Map<K, ICacheElement<K, V>> getMultipleFromCacheListeners( final Set<K> keys, final Map<K, ICacheElement<K, V>> elements, final boolean fromCluster, final CacheListeners<K, V> cacheDesc )
    {
        Map<K, ICacheElement<K, V>> returnElements = elements;

        if ( cacheDesc != null )
        {
            final CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

            // If we have a getMultiple come in from a client and we don't have the item
            // locally, we will allow the cache to look in other non local sources,
            // such as a remote cache or a lateral.
            //
            // Since remote servers never get from clients and clients never go
            // remote from a remote call, this
            // will not result in any loops.
            //
            // This is the only instance I can think of where we allow a remote get
            // from a remote call. The purpose is to allow remote cache servers to
            // talk to each other. If one goes down, you want it to be able to get
            // data from those that were up when the failed server comes back on
            // line.

            if ( !fromCluster && this.remoteCacheServerAttributes.isAllowClusterGet() )
            {
                log.debug( "NonLocalGetMultiple. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );

                returnElements = c.getMultiple( keys );
            }
            else
            {
                // Gets from cluster type remote will end up here.
                // Gets from all clients will end up here if allow cluster get is
                // false.

                log.debug( "LocalGetMultiple. fromCluster [{0}] AllowClusterGet [{1}]",
                        fromCluster, this.remoteCacheServerAttributes.isAllowClusterGet() );

                returnElements = c.localGetMultiple( keys );
            }
        }

        return returnElements;
    }

    /**
     * Return the keys in the cache.
     *

     * @param cacheName the name of the cache region
     * @see org.apache.commons.jcs3.auxiliary.AuxiliaryCache#getKeySet()
     */
    @Override
    public Set<K> getKeySet(final String cacheName) throws IOException
    {
        return processGetKeySet( cacheName );
    }

    /**
     * Gets the set of keys of objects currently in the cache.
     *

     * @param cacheName
     * @return Set
     */
    protected Set<K> processGetKeySet( final String cacheName )
    {
        final CacheListeners<K, V> cacheDesc = getCacheListeners( cacheName );

        if ( cacheDesc == null )
        {
            return Collections.emptySet();
        }

        final CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;
        return c.getKeySet();
    }

    /**
     * Removes the given key from the specified remote cache. Defaults the listener id to 0.
     *

     * @param cacheName
     * @param key
     * @throws IOException
     */
    @Override
    public void remove( final String cacheName, final K key )
        throws IOException
    {
        remove( cacheName, key, 0 );
    }

    /**
     * Remove the key from the cache region and don't tell the source listener about it.
     *

     * The internal processing is wrapped in event logging calls.
     *

     * @param cacheName
     * @param key
     * @param requesterId
     * @throws IOException
     */
    @Override
    public void remove( final String cacheName, final K key, final long requesterId )
        throws IOException
    {
        final ICacheEvent<K> cacheEvent = createICacheEvent( cacheName, key, requesterId, ICacheEventLogger.REMOVE_EVENT );
        try
        {
            processRemove( cacheName, key, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * Remove the key from the cache region and don't tell the source listener about it.
     *

     * @param cacheName
     * @param key
     * @param requesterId
     * @throws IOException
     */
    private void processRemove( final String cacheName, final K key, final long requesterId )
        throws IOException
    {
        log.debug( "remove [{0}] from cache [{1}]", key, cacheName );

        final CacheListeners<K, V> cacheDesc = cacheListenersMap.get( cacheName );

        final boolean fromCluster = isRequestFromCluster( requesterId );

        if ( cacheDesc != null )
        {
            // best attempt to achieve ordered cache item removal and
            // notification.
            synchronized ( cacheDesc )
            {
                boolean removeSuccess = false;

                // No need to notify if it was not cached.
                final CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

                if ( fromCluster )
                {
                    log.debug( "Remove FROM cluster, NOT updating other auxiliaries for region" );
                    removeSuccess = c.localRemove( key );
                }
                else
                {
                    log.debug( "Remove NOT from cluster, updating other auxiliaries for region" );
                    removeSuccess = c.remove( key );
                }

                log.debug( "remove [{0}] from cache [{1}] success (was it found) = {2}",
                        key, cacheName, removeSuccess );

                // UPDATE LOCALS IF A REQUEST COMES FROM A CLUSTER
                // IF LOCAL CLUSTER CONSISTENCY IS CONFIGURED
                if (!fromCluster || fromCluster && remoteCacheServerAttributes.isLocalClusterConsistency())
                {
                    final ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, requesterId );

                    for (final ICacheEventQueue<K, V> element : qlist) {
                        element.addRemoveEvent( key );
                    }
                }
            }
        }
    }

    /**
     * Remove all keys from the specified remote cache.
     *

     * @param cacheName
     * @throws IOException
     */
    @Override
    public void removeAll( final String cacheName )
        throws IOException
    {
        removeAll( cacheName, 0 );
    }

    /**
     * Remove all keys from the specified remote cache.
     *

     * The internal processing is wrapped in event logging calls.
     *

     * @param cacheName
     * @param requesterId
     * @throws IOException
     */
    @Override
    public void removeAll( final String cacheName, final long requesterId )
        throws IOException
    {
        final ICacheEvent<String> cacheEvent = createICacheEvent( cacheName, "all", requesterId, ICacheEventLogger.REMOVEALL_EVENT );
        try
        {
            processRemoveAll( cacheName, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * Remove all keys from the specified remote cache.
     *

     * @param cacheName
     * @param requesterId
     * @throws IOException
     */
    private void processRemoveAll( final String cacheName, final long requesterId )
        throws IOException
    {
        final CacheListeners<K, V> cacheDesc = cacheListenersMap.get( cacheName );

        final boolean fromCluster = isRequestFromCluster( requesterId );

        if ( cacheDesc != null )
        {
            // best attempt to achieve ordered cache item removal and
            // notification.
            synchronized ( cacheDesc )
            {
                // No need to broadcast, or notify if it was not cached.
                final CompositeCache<K, V> c = (CompositeCache<K, V>) cacheDesc.cache;

                if ( fromCluster )
                {
                    log.debug( "RemoveALL FROM cluster, NOT updating other auxiliaries for region" );
                    c.localRemoveAll();
                }
                else
                {
                    log.debug( "RemoveALL NOT from cluster, updating other auxiliaries for region" );
                    c.removeAll();
                }

                // update registered listeners
                if (!fromCluster || fromCluster && remoteCacheServerAttributes.isLocalClusterConsistency())
                {
                    final ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, requesterId );

                    for (final ICacheEventQueue<K, V> q : qlist)
                    {
                        q.addRemoveAllEvent();
                    }
                }
            }
        }
    }

    /**
     * How many put events have we received.
     *

     * @return puts
     */
    // Currently only intended for use by unit tests
    int getPutCount()
    {
        return puts;
    }

    /**
     * Frees the specified remote cache.
     *

     * @param cacheName
     * @throws IOException
     */
    @Override
    public void dispose( final String cacheName )
        throws IOException
    {
        dispose( cacheName, 0 );
    }

    /**
     * Frees the specified remote cache.
     *

     * @param cacheName
     * @param requesterId
     * @throws IOException
     */
    public void dispose( final String cacheName, final long requesterId )
        throws IOException
    {
        final ICacheEvent<String> cacheEvent = createICacheEvent( cacheName, "none", requesterId, ICacheEventLogger.DISPOSE_EVENT );
        try
        {
            processDispose( cacheName, requesterId );
        }
        finally
        {
            logICacheEvent( cacheEvent );
        }
    }

    /**
     * @param cacheName
     * @param requesterId
     * @throws IOException
     */
    private void processDispose( final String cacheName, final long requesterId )
        throws IOException
    {
        log.info( "Dispose request received from listener [{0}]", requesterId );

        final CacheListeners<K, V> cacheDesc = cacheListenersMap.get( cacheName );

        // this is dangerous
        if ( cacheDesc != null )
        {
            // best attempt to achieve ordered free-cache-op and notification.
            synchronized ( cacheDesc )
            {
                final ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, requesterId );

                for (final ICacheEventQueue<K, V> element : qlist) {
                    element.addDisposeEvent();
                }
                cacheManager.freeCache( cacheName );
            }
        }
    }

    /**
     * Frees all remote caches.
     *

     * @throws IOException
     */
    @Override
    public void release()
        throws IOException
    {
        for (final CacheListeners<K, V> cacheDesc : cacheListenersMap.values())
        {
            final ICacheEventQueue<K, V>[] qlist = getEventQList( cacheDesc, 0 );

            for (final ICacheEventQueue<K, V> element : qlist) {
                element.addDisposeEvent();
            }
        }
        cacheManager.release();
    }

    /**
     * Returns the cache listener for the specified cache. Creates the cache and the cache
     * descriptor if they do not already exist.
     *

     * @param cacheName
     * @return The cacheListeners value
     */
    protected CacheListeners<K, V> getCacheListeners( final String cacheName )
    {

        return cacheListenersMap.computeIfAbsent(cacheName, key -> {
            final CompositeCache<K, V> cache = cacheManager.getCache(key);
            return new CacheListeners<>( cache );
        });
    }

    /**
     * Gets the clusterListeners attribute of the RemoteCacheServer object.
     *

     * TODO may be able to remove this
     * @param cacheName
     * @return The clusterListeners value
     */
    protected CacheListeners<K, V> getClusterListeners( final String cacheName )
    {

        return clusterListenersMap.computeIfAbsent(cacheName, key -> {
            final CompositeCache<K, V> cache = cacheManager.getCache( cacheName );
            return new CacheListeners<>( cache );
        });
    }

    /**
     * Gets the eventQList attribute of the RemoteCacheServer object. This returns the event queues
     * stored in the cacheListeners object for a particular region, if the queue is not for this
     * requester.
     *

     * Basically, this makes sure that a request from a particular local cache, identified by its
     * listener id, does not result in a call to that same listener.
     *

     * @param cacheListeners
     * @param requesterId
     * @return The eventQList value
     */
    @SuppressWarnings("unchecked") // No generic arrays in java
    private ICacheEventQueue<K, V>[] getEventQList( final CacheListeners<K, V> cacheListeners, final long requesterId )
    {
        final ICacheEventQueue<K, V>[] list = cacheListeners.eventQMap.values().toArray( new ICacheEventQueue[0] );
        int count = 0;
        // Set those not qualified to null; Count those qualified.
        for ( int i = 0; i < list.length; i++ )
        {
            final ICacheEventQueue<K, V> q = list[i];
            if ( q.isWorking() && q.getListenerId() != requesterId )
            {
                count++;
            }
            else
            {
                list[i] = null;
            }
        }
        if ( count == list.length )
        {
            // All qualified.
            return list;
        }

        // Returns only the qualified.
        final ICacheEventQueue<K, V>[] qq = new ICacheEventQueue[count];
        count = 0;
        for (final ICacheEventQueue<K, V> element : list) {
            if ( element != null )
            {
                qq[count++] = element;
            }
        }
        return qq;
    }

    /**
     * Removes dead event queues. Should clean out deregistered listeners.
     *

     * @param eventQMap
     */
    private static <KK, VV> void cleanupEventQMap( final Map<Long, ICacheEventQueue<KK, VV>> eventQMap )
    {
        // this does not care if the q is alive (i.e. if
        // there are active threads; it cares if the queue
        // is working -- if it has not encountered errors
        // above the failure threshold
        eventQMap.entrySet().removeIf(e -> !e.getValue().isWorking());
    }

    /**
     * Subscribes to the specified remote cache.
     *

     * If the client id is 0, then the remote cache server will increment it's local count and
     * assign an id to the client.
     *

     * @param cacheName the specified remote cache.
     * @param listener object to notify for cache changes. must be synchronized since there are
     *            remote calls involved.
     * @throws IOException
     */
    @Override
    @SuppressWarnings("unchecked") // Need to cast to specific return type from getClusterListeners()
    public <KK, VV> void addCacheListener( final String cacheName, final ICacheListener<KK, VV> listener )
        throws IOException
    {
        if ( cacheName == null || listener == null )
        {
            throw new IllegalArgumentException( "cacheName and listener must not be null" );
        }
        final CacheListeners<KK, VV> cacheListeners;

        final IRemoteCacheListener<KK, VV> ircl = (IRemoteCacheListener<KK, VV>) listener;

        final String listenerAddress = ircl.getLocalHostAddress();

        final RemoteType remoteType = ircl.getRemoteType();
        if ( remoteType == RemoteType.CLUSTER )
        {
            log.debug( "adding cluster listener, listenerAddress [{0}]", listenerAddress );
            cacheListeners = (CacheListeners<KK, VV>)getClusterListeners( cacheName );
        }
        else
        {
            log.debug( "adding normal listener, listenerAddress [{0}]", listenerAddress );
            cacheListeners = (CacheListeners<KK, VV>)getCacheListeners( cacheName );
        }
        final Map<Long, ICacheEventQueue<KK, VV>> eventQMap = cacheListeners.eventQMap;
        cleanupEventQMap( eventQMap );

        // synchronized ( listenerId )
        synchronized ( ICacheListener.class )
        {
            long id = 0;
            try
            {
                id = listener.getListenerId();
                // clients probably shouldn't do this.
                if ( id == 0 )
                {
                    // must start at one so the next gets recognized
                    final long listenerIdB = nextListenerId();
                    log.debug( "listener id={0} addded for cache [{1}], listenerAddress [{2}]",
                            listenerIdB & 0xff, cacheName, listenerAddress );
                    listener.setListenerId( listenerIdB );
                    id = listenerIdB;

                    // in case it needs synchronization
                    final String message = "Adding vm listener under new id = [" + listenerIdB + "], listenerAddress ["
                        + listenerAddress + "]";
                    logApplicationEvent( "RemoteCacheServer", "addCacheListener", message );
                    log.info( message );
                }
                else
                {
                    final String message = "Adding listener under existing id = [" + id + "], listenerAddress ["
                        + listenerAddress + "]";
                    logApplicationEvent( "RemoteCacheServer", "addCacheListener", message );
                    log.info( message );
                    // should confirm the the host is the same as we have on
                    // record, just in case a client has made a mistake.
                }

                // relate the type to an id
                this.idTypeMap.put( Long.valueOf( id ), remoteType);
                if ( listenerAddress != null )
                {
                    this.idIPMap.put( Long.valueOf( id ), listenerAddress );
                }
            }
            catch ( final IOException ioe )
            {
                final String message = "Problem setting listener id, listenerAddress [" + listenerAddress + "]";
                log.error( message, ioe );

                if ( cacheEventLogger != null )
                {
                    cacheEventLogger.logError( "RemoteCacheServer", "addCacheListener", message + " - "
                        + ioe.getMessage() );
                }
            }

            final CacheEventQueueFactory<KK, VV> fact = new CacheEventQueueFactory<>();
            final ICacheEventQueue<KK, VV> q = fact.createCacheEventQueue( listener, id, cacheName, remoteCacheServerAttributes
                .getEventQueuePoolName(), remoteCacheServerAttributes.getEventQueueType() );

            eventQMap.put(Long.valueOf(listener.getListenerId()), q);

            log.info( cacheListeners );
        }
    }

    /**
     * Subscribes to all remote caches.
     *

     * @param listener The feature to be added to the CacheListener attribute
     * @throws IOException
     */
    @Override
    public <KK, VV> void addCacheListener( final ICacheListener<KK, VV> listener )
        throws IOException
    {
        for (final String cacheName : cacheListenersMap.keySet())
        {
            addCacheListener( cacheName, listener );

            log.debug( "Adding listener for cache [{0}]", cacheName );
        }
    }

    /**
     * Unsubscribe this listener from this region. If the listener is registered, it will be removed
     * from the event queue map list.
     *

     * @param cacheName
     * @param listener
     * @throws IOException
     */
    @Override
    public <KK, VV> void removeCacheListener( final String cacheName, final ICacheListener<KK, VV> listener )
        throws IOException
    {
        removeCacheListener( cacheName, listener.getListenerId() );
    }

    /**
     * Unsubscribe this listener from this region. If the listener is registered, it will be removed
     * from the event queue map list.
     *

     * @param cacheName
     * @param listenerId
     */
    public void removeCacheListener( final String cacheName, final long listenerId )
    {
        final String message = "Removing listener for cache region = [" + cacheName + "] and listenerId [" + listenerId + "]";
        logApplicationEvent( "RemoteCacheServer", "removeCacheListener", message );
        log.info( message );

        final boolean isClusterListener = isRequestFromCluster( listenerId );

        CacheListeners<K, V> cacheDesc = null;

        if ( isClusterListener )
        {
            cacheDesc = getClusterListeners( cacheName );
        }
        else
        {
            cacheDesc = getCacheListeners( cacheName );
        }
        final Map<Long, ICacheEventQueue<K, V>> eventQMap = cacheDesc.eventQMap;
        cleanupEventQMap( eventQMap );
        final ICacheEventQueue<K, V> q = eventQMap.remove( Long.valueOf( listenerId ) );

        if ( q != null )
        {
            log.debug( "Found queue for cache region = [{0}] and listenerId [{1}]",
                    cacheName, listenerId );
            q.destroy();
            cleanupEventQMap( eventQMap );
        }
        else
        {
            log.debug( "Did not find queue for cache region = [{0}] and listenerId [{1}]",
                    cacheName, listenerId );
        }

        // cleanup
        idTypeMap.remove( Long.valueOf( listenerId ) );
        idIPMap.remove( Long.valueOf( listenerId ) );

        log.info( "After removing listener [{0}] cache region {1} listener size [{2}]",
                listenerId, cacheName, eventQMap.size() );
    }

    /**
     * Unsubscribes from all remote caches.
     *

     * @param listener
     * @throws IOException
     */
    @Override
    public <KK, VV> void removeCacheListener( final ICacheListener<KK, VV> listener )
        throws IOException
    {
        for (final String cacheName : cacheListenersMap.keySet())
        {
            removeCacheListener( cacheName, listener );

            log.info( "Removing listener for cache [{0}]", cacheName );
        }
    }

    /**
     * Shuts down the remote server.
     *

     * @throws IOException
     */
    @Override
    public void shutdown()
        throws IOException
    {
        shutdown("", Registry.REGISTRY_PORT);
    }

    /**
     * Shuts down a server at a particular host and port. Then it calls shutdown on the cache
     * itself.
     *

     * @param host
     * @param port
     * @throws IOException
     */
    @Override
    public void shutdown( final String host, final int port )
        throws IOException
    {
        log.info( "Received shutdown request. Shutting down server." );

        synchronized (listenerId)
        {
            for (final String cacheName : cacheListenersMap.keySet())
            {
                for (int i = 0; i <= listenerId[0]; i++)
                {
                    removeCacheListener( cacheName, i );
                }

                log.info( "Removing listener for cache [{0}]", cacheName );
            }

            cacheListenersMap.clear();
            clusterListenersMap.clear();
        }
        RemoteCacheServerFactory.shutdownImpl( host, port );
        this.cacheManager.shutDown();
    }

    /**
     * Called by the RMI runtime sometime after the runtime determines that the reference list, the
     * list of clients referencing the remote object, becomes empty.
     */
    // TODO: test out the DGC.
    @Override
    public void unreferenced()
    {
        log.info( "*** Server now unreferenced and subject to GC. ***" );
    }

    /**
     * Returns the next generated listener id [0,255].
     *

     * @return the listener id of a client. This should be unique for this server.
     */
    private long nextListenerId()
    {
        long id = 0;
        if ( listenerId[0] == Integer.MAX_VALUE )
        {
            synchronized ( listenerId )
            {
                id = listenerId[0];
                listenerId[0] = 0;
                // TODO: record & check if the generated id is currently being
                // used by a valid listener. Currently if the id wraps after
                // Long.MAX_VALUE,
                // we just assume it won't collide with an existing listener who
                // is live.
            }
        }
        else
        {
            synchronized ( listenerId )
            {
                id = ++listenerId[0];
            }
        }
        return id;
    }

    /**
     * Gets the stats attribute of the RemoteCacheServer object.
     *

     * @return The stats value
     * @throws IOException
     */
    @Override
    public String getStats()
        throws IOException
    {
        return cacheManager.getStats();
    }

    /**
     * Logs an event if an event logger is configured.
     *

     * @param item
     * @param requesterId
     * @param eventName
     * @return ICacheEvent
     */
    private ICacheEvent<ICacheElement<K, V>> createICacheEvent( final ICacheElement<K, V> item, final long requesterId, final String eventName )
    {
        if ( cacheEventLogger == null )
        {
            return new CacheEvent<>();
        }
        final String ipAddress = getExtraInfoForRequesterId( requesterId );
        return cacheEventLogger
            .createICacheEvent( "RemoteCacheServer", item.getCacheName(), eventName, ipAddress, item );
    }

    /**
     * Logs an event if an event logger is configured.
     *

     * @param cacheName
     * @param key
     * @param requesterId
     * @param eventName
     * @return ICacheEvent
     */
    private <T> ICacheEvent<T> createICacheEvent( final String cacheName, final T key, final long requesterId, final String eventName )
    {
        if ( cacheEventLogger == null )
        {
            return new CacheEvent<>();
        }
        final String ipAddress = getExtraInfoForRequesterId( requesterId );
        return cacheEventLogger.createICacheEvent( "RemoteCacheServer", cacheName, eventName, ipAddress, key );
    }

    /**
     * Logs an event if an event logger is configured.
     *

     * @param source
     * @param eventName
     * @param optionalDetails
     */
    protected void logApplicationEvent( final String source, final String eventName, final String optionalDetails )
    {
        if ( cacheEventLogger != null )
        {
            cacheEventLogger.logApplicationEvent( source, eventName, optionalDetails );
        }
    }

    /**
     * Logs an event if an event logger is configured.
     *

     * @param cacheEvent
     */
    protected <T> void logICacheEvent( final ICacheEvent<T> cacheEvent )
    {
        if ( cacheEventLogger != null )
        {
            cacheEventLogger.logICacheEvent( cacheEvent );
        }
    }

    /**
     * Ip address for the client, if one is stored.
     *

     * Protected for testing.
     *

     * @param requesterId
     * @return String
     */
    protected String getExtraInfoForRequesterId( final long requesterId )
    {
        return idIPMap.get( Long.valueOf( requesterId ) );
    }

    /**
     * Allows it to be injected.
     *

     * @param cacheEventLogger
     */
    public void setCacheEventLogger( final ICacheEventLogger cacheEventLogger )
    {
        this.cacheEventLogger = cacheEventLogger;
    }
}


text:
package com.kimboo.giffy.server.rest;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.AbstractClientHttpResponse;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StringUtils;

/**
 * {@link ClientHttpResponse} implementation that uses standard J2SE facilities.
 * Obtained via {@link SimpleBufferingClientHttpRequest#execute()} and
 * {@link SimpleStreamingClientHttpRequest#execute()}.
 *
 * @author Arjen Poutsma
 * @author Roy Clarkson
 * @since 1.0
 */
final class SimpleClientHttpResponse extends AbstractClientHttpResponse {

	private static final String AUTHENTICATION_ERROR = "Received authentication challenge is null";

	private final HttpURLConnection connection;

	private HttpHeaders headers;

	SimpleClientHttpResponse(HttpURLConnection connection) {
		this.connection = connection;
	}

	public int getRawStatusCode() throws IOException {
		return this.connection.getResponseCode();
	}

	@Override
	public HttpStatus getStatusCode() throws IOException {
		try {
			return HttpStatus.valueOf(getRawStatusCode());
		} catch (IOException ex) {
			/*
			 * If credentials are incorrect or not provided for Basic Auth, then
			 * Android throws this exception when an HTTP 401 is received. Checking
			 * for this response and returning the proper status.
			 */
			if (ex.getLocalizedMessage().equals(AUTHENTICATION_ERROR)) {
				return HttpStatus.UNAUTHORIZED;
			} else {
				throw ex;
			}
		}
	}

	public String getStatusText() throws IOException {
		try {
			return this.connection.getResponseMessage();
		} catch (IOException ex) {
			/*
			 * If credentials are incorrect or not provided for Basic Auth, then
			 * Android throws this exception when an HTTP 401 is received. Checking
			 * for this response and returning the proper status.
			 */
			if (ex.getLocalizedMessage().equals(AUTHENTICATION_ERROR)) {
				return HttpStatus.UNAUTHORIZED.getReasonPhrase();
			} else {
				throw ex;
			}
		}
	}

	public HttpHeaders getHeaders() {
		if (this.headers == null) {
			this.headers = new HttpHeaders();
			// Header field 0 is the status line for most HttpURLConnections, but not on GAE
			String name = this.connection.getHeaderFieldKey(0);
			if (StringUtils.hasLength(name)) {
				this.headers.add(name, this.connection.getHeaderField(0));
			}
			int i = 1;
			while (true) {
				name = this.connection.getHeaderFieldKey(i);
				if (!StringUtils.hasLength(name)) {
					break;
				}
				this.headers.add(name, this.connection.getHeaderField(i));
				i++;
			}
		}
		return this.headers;
	}

	@Override
	protected InputStream getBodyInternal() throws IOException {
		InputStream errorStream = this.connection.getErrorStream();
		return (errorStream != null ? errorStream : this.connection.getInputStream());
	}

	@Override
	protected void closeInternal() {
		this.connection.disconnect();
	}

}

redpajama_set_name: RedPajamaGithub


text:
using System;
using System.IO.Compression;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        if(args.Length < 2)
        {
            Console.WriteLine(@"Usage: cszip [sourceDirectoryName] [destinationArchiveFileName]");
            return;
        }

        var src = args[0];
        var dst = args[1];
        ZipFile.CreateFromDirectory(src, dst, CompressionLevel.Optimal, true, Encoding.UTF8);
    }
}


text:
<!DOCTYPE html>

    <title></title>

Here are some example for you to paste in the console for testing :

specialConsole.writeWarning("lets {0} this {1}","hope","works");

specialConsole.writeError("lets {0} this {1}","hope","works");

specialConsole.writeLine("lets {0} this {1}","hope","works");

specialConsole.writeLine("lets {0} try {0} to {0} add something more than once","not","haviing axtra arguments shoud work just fine");


text:
module Thinkspace; module Authorization
class ThinkspacePubSub < ::Totem::Settings.authorization.platforms.thinkspace.cancan.classes.ability_engine

  def process; call_private_methods; end

  private

  def pub_sub
    pub_sub = get_class 'Thinkspace::PubSub::ServerEvent'
    return if pub_sub.blank?
    server_event = Thinkspace::PubSub::ServerEvent
    can [:manage], server_event
  end

end; end; end


text:
package com.google.appengine.datanucleus.test.jdo;

import java.util.*;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.datanucleus.annotations.Unowned;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable
public class Issue290Parent {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;

  @Persistent
  private String name;

  @Persistent
  @Unowned
  private List<Issue290Child> children = new ArrayList();

  public Issue290Parent(String name) {
    super();
    this.name = name;
  }

  public Key getKey() {
    return key;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public List<Issue290Child> getChildren() {
    return children;
  }
}


text:
from Queue import Queue
from base64 import b64encode
from hashlib import sha1
from optparse import OptionParser
from SimpleHTTPServer import SimpleHTTPRequestHandler
from threading  import Thread
import traceback
import BaseHTTPServer
import os
import json
import struct
import ssl

q = Queue()

class WebSocketHandler(object):
    _ws_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' #'e47b2610-3ce1-4dd6-9ef0-760a026014eb'
    _opcode_continu = 0x0
    _opcode_text = 0x1
    _opcode_binary = 0x2
    _opcode_close = 0x8
    _opcode_ping = 0x9
    _opcode_pong = 0xa

    def __init__(self, requestHandler, msgHandler):
        self.__request_handler = requestHandler
        self.__msg_handler = msgHandler

    def run(self):
        self.__handshake()
        self.__read_messages()
        self.__close()

    def __handshake(self):
        rh = self.__request_handler
        headers = rh.headers
        key = headers['Sec-WebSocket-Key']
        digest = b64encode(sha1(key + self._ws_GUID).hexdigest().decode('hex'))
        rh.send_response(101, 'Switching Protocols')
        rh.send_header('Upgrade', 'websocket')
        rh.send_header('Connection', 'Upgrade')
        rh.send_header('Sec-WebSocket-Accept', str(digest))
        rh.end_headers()

    def __close(self):
        try:
            self.__send_close()
        except Exception, e:
            self.__request_handler.log_message('ignore exception while closing WebSocket: %s.' % e)

    def __send_close(self):
        msg = bytearray()
        msg.append(0x80 + self._opcode_close)
        msg.append(0x00)
        self.__request_handler.request.send(msg)

    def __read_messages(self):
        try:
            while self.__read_next_message():
                pass
        except Exception, e:
            traceback.print_exc()
            self.__request_handler.log_error("closing WebSocket on exception: %s" % e)

    def __read_next_message(self):
        rfile = self.__request_handler.rfile
        #rfile.read(n) is blocking.
        #it returns however immediately when the socket is closed.
        opcode = ord(rfile.read(1)) & 0x0F
        length = ord(rfile.read(1)) & 0x7F
        if length == 126:
            length = struct.unpack(">H", rfile.read(2))[0]
        elif length == 127:
            length = struct.unpack(">Q", rfile.read(8))[0]
        masks = [ord(byte) for byte in rfile.read(4)]
        decoded = ""
        for char in rfile.read(length):
            decoded += chr(ord(char) ^ masks[len(decoded) % 4])

        return self.__on_message(opcode, decoded)

    def __on_message(self, opcode, decoded):
        if opcode == self._opcode_close:
            return False

        if opcode == self._opcode_ping:
            self.__send_message(self._opcode_pong, message)
        elif opcode == self._opcode_pong:
            pass
        elif (opcode == self._opcode_continu or
                opcode == self._opcode_text or
                opcode == self._opcode_binary):
            self.__msg_handler(decoded)
        return True

    def __send_message(self, opcode, message):
        request = self.__request_handler.request
        request.send(chr(0x80 + opcode))
        length = len(message)
        if length <= 125:
            request.send(chr(length))
        elif length >= 126 and length <= 65535:
            request.send(chr(126))
            request.send(struct.pack(">H", length))
        else:
            request.send(chr(127))
            request.send(struct.pack(">Q", length))
        if length > 0:
            request.send(message)

class ServerHandler(SimpleHTTPRequestHandler):
    def do_GET(self):
        if self.headers.get("Upgrade", None) == "websocket":
            WebSocketHandler(self, lambda msg: self.__handle_websocket_message(msg)).run()
            #This handler is in websocket mode now.
            #do_GET only returns after client close or socket error.
        else:
            SimpleHTTPRequestHandler.do_GET(self)

    def __handle_websocket_message(self, msg):
        try:
            r = json.loads(msg)
            for i in r:
                q.put(i)
        except Exception, x:
            print("error: %s" % x)

def run(options):
    port = options.port
    print('serving at port: %d' % port)
    httpd = BaseHTTPServer.HTTPServer(('', port), ServerHandler)

    if options.certfile:
        try:
            httpd.socket = ssl.wrap_socket(httpd.socket, certfile=options.certfile, server_side=True)
        except Exception, e:
            print("ssl error: %s" % e)
            return

    httpd.serve_forever()

def notify(msg):
    if os.name != 'nt':
        print(msg);
        return

    import ctypes
    MessageBox = ctypes.windll.user32.MessageBoxA

    MB_SYSTEMMODAL = 0x1000
    MessageBox(None, msg, 'Warning!', MB_SYSTEMMODAL)

def main(options):
    t = Thread(target=run, args=([options]))
    t.daemon = True # thread dies with the program
    t.start()

    while True:
        i = 0
        try:
            i = q.get(True, 5)
        except Exception:
            notify('no signal detected');

        if i > options.sensitivity:
            notify('Incoming!')

            # clear queue (without analyzing) after notification is shown
            while not q.empty():
                q.get()

parser = OptionParser()
parser.add_option("-p", "--port", default=8000, type=int, dest="port",
                  help="serve at HTTP port [default: %default]")
parser.add_option("-s", "--sensitivity", default=100000, type=int, dest="sensitivity",
                  help="motion sensitivity [default: %default]")
parser.add_option("-c", "--certfile", default=None, dest="certfile",
                  help="use SSL with certificate file (path to .pem)")
(options, args) = parser.parse_args()

main(options)


text:
///////////////////////////////////////////////////////////////////////////////
//PROJECT:       MicroNuclei detection project
//-----------------------------------------------------------------------------
//
// AUTHOR:       Nico Stuurman
//
// COPYRIGHT:    Regents of the University of California 2015
//
// LICENSE:      This file is distributed under the BSD license.
//               License text is included with the source distribution.
//
//               This file is distributed in the hope that it will be useful,
//               but WITHOUT ANY WARRANTY; without even the implied warranty
//               of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
//               IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//               CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//               INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.

package org.micromanager.micronuclei;

import org.micromanager.micronuclei.gui.ResultsListener;
import org.micromanager.micronuclei.gui.DragDropUtil;
import org.micromanager.micronuclei.analysisinterface.AnalysisModule;
import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.gui.PolygonRoi;
import ij.gui.Roi;
import ij.io.Opener;
import ij.measure.ResultsTable;
import ij.plugin.ImageCalculator;
import ij.text.TextPanel;
import ij.text.TextWindow;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.prefs.Preferences;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import mmcorej.TaggedImage;
import net.miginfocom.swing.MigLayout;
import org.json.JSONException;
import org.json.JSONObject;
import org.micromanager.acquisition.MMAcquisition;
import org.micromanager.api.MMWindow;
import org.micromanager.api.MultiStagePosition;
import org.micromanager.api.PositionList;
import org.micromanager.api.ScriptInterface;
import org.micromanager.micronuclei.analysis.MicroNucleiAnalysisModule;
import org.micromanager.micronuclei.analysisinterface.AnalysisProperty;
import org.micromanager.micronuclei.analysisinterface.PropertyException;
import org.micromanager.micronuclei.gui.PropertyGUI;
import org.micromanager.projector.ProjectorControlForm;
import org.micromanager.utils.FileDialogs;
import org.micromanager.utils.ImageUtils;
import org.micromanager.utils.MMFrame;
import org.micromanager.utils.MMScriptException;
import org.micromanager.utils.ReportingUtils;

/**
 *
 * @author nico
 */
public class MicroNucleiForm extends MMFrame {

   private final ScriptInterface gui_;
   private final Font arialSmallFont_;
   private final Dimension buttonSize_;
   private final JTextField saveTextField_;
   private String imagingChannel_;
   private final JComboBox channelComboBox_;
   private String secondImagingChannel_;
   private final JComboBox secondChannelComboBox_;
   private String zapChannel_;
   private final JComboBox zapChannelComboBox_;
   private String afterZapChannel_;
   private final JComboBox AfterZapChannelComboBox_;
   private final JCheckBox doZap_;
   private final JCheckBox showMasks_;
   private final JTextField backgroundTextField_;
   private final JTextField flatfieldTextField_;
   private final Preferences prefs_;

   private ImagePlus background_;
   private ImagePlus flatfield_;

   private final String SAVELOCATION = "SaveLocation";
   private final String IMAGINGCHANNEL = "ImagingChannel";
   private final String SECONDIMAGINGCHANNEL = "SecondImagingChannel";
   private final String ZAPCHANNEL = "ZapChannel";
   private final String AFTERZAPCHANNEL = "AfterZapChannel";
   private final String DOZAP = "DoZap";
   private final String SHOWMASKS = "ShowMasks";
   private final String BACKGROUNDLOCATION = "BackgroundLocation";
   private final String FLATFIELDLOCATION = "FlatfieldLocation";

   private final AtomicBoolean stop_ = new AtomicBoolean(false);

   private final AnalysisModule analysisModule_;

   public MicroNucleiForm(ScriptInterface gui) {
      gui_ = gui;
      loadAndRestorePosition(100, 100, 200, 200);
      prefs_ = Preferences.userNodeForPackage(this.getClass());

      // TODO: make this user selectable from available modules
      analysisModule_ = new MicroNucleiAnalysisModule();

      arialSmallFont_ = new Font("Arial", Font.PLAIN, 12);
      buttonSize_ = new Dimension(70, 21);

      this.setLayout(new MigLayout("flowx, fill, insets 8"));
      this.setTitle("MicroNuclei Analyze");

      JPanel acqPanel = new JPanel(new MigLayout(
              "flowx, fill, insets 8"));

      acqPanel.add(myLabel(arialSmallFont_,"Save here:"));

      saveTextField_ = new JTextField();
      saveTextField_.setText(prefs_.get(SAVELOCATION, ""));
      saveTextField_.setMinimumSize(new Dimension(200, 12));
      acqPanel.add(saveTextField_);

      final JButton dirButton = myButton(buttonSize_, arialSmallFont_, "...");
      dirButton.addActionListener(new java.awt.event.ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            dirActionPerformed(e);
         }
      });
      acqPanel.add(dirButton, "wrap");

      acqPanel.add(myLabel(arialSmallFont_, "Imaging Channel: "));
      channelComboBox_ = new JComboBox();
      imagingChannel_ = prefs_.get(IMAGINGCHANNEL, imagingChannel_);
      updateChannels(channelComboBox_, imagingChannel_, false);
      channelComboBox_.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent ae) {
            channelActionPerformed(ae);
         }
      } );
      acqPanel.add(channelComboBox_, "span 2, left, wrap");

      acqPanel.add(myLabel(arialSmallFont_, "2nd Imaging Channel: "));
      secondChannelComboBox_ = new JComboBox();
      secondImagingChannel_ = prefs_.get(SECONDIMAGINGCHANNEL, secondImagingChannel_);
      updateChannels(secondChannelComboBox_, secondImagingChannel_, true);
      secondChannelComboBox_.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent ae) {
            secondChannelActionPerformed(ae);
         }
      } );
      acqPanel.add(secondChannelComboBox_, "span 2, left, wrap");

      acqPanel.add(myLabel(arialSmallFont_, "Zap Channel: "));
      zapChannelComboBox_ = new JComboBox();
      zapChannel_ = prefs_.get(ZAPCHANNEL, zapChannel_);
      updateChannels(zapChannelComboBox_, zapChannel_, false);
      zapChannelComboBox_.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent ae) {
            zapChannelActionPerformed(ae);
         }
      } );
      acqPanel.add(zapChannelComboBox_, "span 2, left, wrap");

      acqPanel.add(myLabel(arialSmallFont_, "After Zap Channel: "));
      AfterZapChannelComboBox_ = new JComboBox();
      afterZapChannel_ = prefs_.get(AFTERZAPCHANNEL, afterZapChannel_);
      updateChannels(AfterZapChannelComboBox_, afterZapChannel_, false);
      AfterZapChannelComboBox_.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent ae) {
            afterZapChannelActionPerformed(ae);
         }
      } );
      acqPanel.add(AfterZapChannelComboBox_, "span 2, left, wrap");
      acqPanel.setBorder(makeTitledBorder("Acquisition Settings"));

      add(acqPanel, "span 3, center, wrap");

      JPanel analysisPanel = new JPanel(new MigLayout(
              "flowx, fill, insets 8"));
      analysisPanel.setBorder(makeTitledBorder("Analysis Settings"));

      analysisPanel.add(new JLabel("Background: "));
      backgroundTextField_ = new JTextField();
      backgroundTextField_.setText(prefs_.get(BACKGROUNDLOCATION, ""));
      backgroundTextField_.setMinimumSize(new Dimension(250, 12));
      backgroundTextField_.setMaximumSize(new Dimension(250, 20));
      backgroundTextField_.addActionListener(new java.awt.event.ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            if (prefs_ != null)
               prefs_.put(BACKGROUNDLOCATION, backgroundTextField_.getText());
         }
      });
      analysisPanel.add(backgroundTextField_);
      DropTarget dropTarget = new DropTarget(backgroundTextField_,
              new DragDropUtil(backgroundTextField_));
      final JButton backgroundButton = myButton(buttonSize_, arialSmallFont_, "...");
      backgroundButton.addActionListener(new java.awt.event.ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            fileActionPerformed(e,
                  backgroundTextField_, "Background Image", BACKGROUNDLOCATION);
         }
      });
      analysisPanel.add(backgroundButton, "wrap");

      analysisPanel.add(new JLabel("Flatfield: "));
      flatfieldTextField_ = new JTextField();
      flatfieldTextField_.setText(prefs_.get(FLATFIELDLOCATION, ""));
      flatfieldTextField_.setMinimumSize(new Dimension(250, 12));
      flatfieldTextField_.setMaximumSize(new Dimension(250, 20));
      flatfieldTextField_.addActionListener(new java.awt.event.ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
             if (prefs_ != null)
               prefs_.put( FLATFIELDLOCATION, flatfieldTextField_.getText());
         }
      });
      analysisPanel.add(flatfieldTextField_);
      dropTarget = new DropTarget(flatfieldTextField_,
              new DragDropUtil(flatfieldTextField_));
      final JButton flatfieldButton = myButton(buttonSize_, arialSmallFont_, "...");
      flatfieldButton.addActionListener(new java.awt.event.ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            fileActionPerformed(e,
                  flatfieldTextField_, "Flatfield Image", FLATFIELDLOCATION);
         }
      });
      analysisPanel.add(flatfieldButton, "wrap");

      add(analysisPanel, "span 3, center, wrap");

      JPanel modulePanel = new JPanel(new MigLayout(
              "flowx, fill, insets 8"));
      modulePanel.setBorder(makeTitledBorder(analysisModule_.name()));

      for (AnalysisProperty ap : analysisModule_.getAnalysisProperties()) {
         modulePanel.add(new JLabel(ap.getDescription()));
         modulePanel.add(new PropertyGUI(ap).getJComponent(), "wrap");
      }

      add(modulePanel, "span 3, center, wrap");

      doZap_ = new JCheckBox("Zap");
      doZap_.setSelected(prefs_.getBoolean(DOZAP, false));
      doZap_.setFont(arialSmallFont_);
      doZap_.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent ae) {
              prefs_.putBoolean(DOZAP, doZap_.isSelected());
         }
      });
      add (doZap_);

      showMasks_  = new JCheckBox("Show Masks");
      showMasks_.setSelected (prefs_.getBoolean(SHOWMASKS, false));
      showMasks_.setFont(arialSmallFont_);
      showMasks_.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent ae) {
              prefs_.putBoolean(SHOWMASKS, showMasks_.isSelected());
         }
      });
      add (showMasks_, "wrap");

      final JButton runButton = myButton(buttonSize_, arialSmallFont_, "Run");
      runButton.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            RunAll myThread = new RunAll();
            myThread.init(false);

         }
      });
      add(runButton, "span 3, split 3, center");

      final JButton stopButton = myButton(buttonSize_, arialSmallFont_, "Stop");
      stopButton.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            stop_.set(true);
         }
      } );
      add(stopButton, "center");

      final JButton testButton = myButton(buttonSize_, arialSmallFont_, "Test");
      testButton.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            RunAll myThread = new RunAll();
            myThread.init(true);
         }
      } );
      add(testButton, "center, wrap");

      loadAndRestorePosition(100, 100, 350, 250);

      pack();

      this.setResizable(false);

   }

   @Override
   public void dispose() {
      super.dispose();
   }

   private JButton myButton(Dimension buttonSize, Font font, String text) {
      JButton button = new JButton();
      button.setPreferredSize(buttonSize);
      button.setMinimumSize(buttonSize);
      button.setFont(font);
      button.setMargin(new Insets(0, 0, 0, 0));
      button.setText(text);

      return button;
   }

   private JLabel myLabel(Font font, String text) {
      JLabel label = new JLabel(text);
      label.setFont(font);
      return label;
   }

   private void updateChannels(JComboBox box, String selectedChannel,
           boolean addEmpty) {
      box.removeAllItems();
      if (addEmpty) {
         box.addItem("");
      }
      try {
         String channelGroup = gui_.getMMCore().getChannelGroup();
         String[] channels = gui_.getMMCore().getAvailableConfigs(channelGroup).toArray();
         for (String channel : channels) {
            box.addItem(channel);
         }
      } catch (Exception ex) {
         ReportingUtils.logError(ex);
      }
      box.setSelectedItem(selectedChannel);
   }

   private void dirActionPerformed(java.awt.event.ActionEvent evt) {
      File f = FileDialogs.openDir(this, "Save location",
              new FileDialogs.FileType("Dir", "Save Location",
              saveTextField_.getText(), true, "") );
      if (f != null) {
         saveTextField_.setText(f.getAbsolutePath());
         if (prefs_ != null)
               prefs_.put(SAVELOCATION, f.getAbsolutePath());
      }
   }

   private void fileActionPerformed(java.awt.event.ActionEvent evt,
           JTextField textField, String title, String prefKey) {
      File f = FileDialogs.openFile(this, title,
              new FileDialogs.FileType("File", title,
              textField.getText(), true, "tif", "tiff") );
      if (f != null) {
         textField.setText(f.getAbsolutePath());
         if (prefs_ != null)
               prefs_.put(prefKey, f.getAbsolutePath());
      }
   }

   private void channelActionPerformed(ActionEvent evt) {
      imagingChannel_ = (String) channelComboBox_.getSelectedItem();
      if (prefs_ != null)
         prefs_.put(IMAGINGCHANNEL, imagingChannel_);
   }

   private void secondChannelActionPerformed(ActionEvent evt) {
      secondImagingChannel_ = (String) secondChannelComboBox_.getSelectedItem();
      if (prefs_ != null)
         prefs_.put(SECONDIMAGINGCHANNEL, secondImagingChannel_);
   }

   private void zapChannelActionPerformed(ActionEvent evt) {
      zapChannel_ = (String) zapChannelComboBox_.getSelectedItem();
      if (prefs_ != null)
         prefs_.put(ZAPCHANNEL, zapChannel_);
   }

   private void afterZapChannelActionPerformed(ActionEvent evt) {
      afterZapChannel_ = (String) AfterZapChannelComboBox_.getSelectedItem();
      if (prefs_ != null)
        prefs_.put(AFTERZAPCHANNEL, afterZapChannel_);
   }

   private class RunAll implements Runnable {
      private boolean running_ = false;
      private boolean testing_ = false;
      public RunAll() {
      }
      @Override
      public void run() {
         try {
            running_ = true;
            Opener opener = new Opener();
            if (!backgroundTextField_.getText().equals(""))
               background_ = opener.openImage(backgroundTextField_.getText());
            if (!flatfieldTextField_.getText().equals(""))
               flatfield_ = opener.openImage(flatfieldTextField_.getText());
            if (!testing_) {
               warnAboutMissingCorrections(background_, flatfield_);
               runAnalysisAndZapping(saveTextField_.getText());
               warnAboutMissingCorrections(background_, flatfield_);
            } else {
               warnAboutMissingCorrections(background_, flatfield_);
               runTest();
            }

         } catch (MMScriptException ex) {
            ReportingUtils.showError(ex, "Error during acquisition");
         } catch (Exception ex) {
            ReportingUtils.showError(ex, "Error during acquisition");
         } finally {
            running_ = false;
         }
      }

      public void init(boolean testing) {
         if (running_) {
            return;
         }
         testing_ = testing;
         stop_.set(false);
         Thread t = new Thread(this);
         t.start();
      }
   }

   /**
    * Runs the selected analysis test on the currently selected image
    * If this is a Micro-Manager window, the code will be run on all positions
    * otherwise only on the current image
    * Results will be shown in an ImageJ ResultsTable which has graphical feedback
    * to the original image
    *
    * @throws MMScriptException
    * @throws JSONException
    * @throws org.micromanager.micronuclei.analysisinterface.PropertyException
    */
   public void runTest() throws MMScriptException, JSONException, PropertyException {
      ImagePlus ip;
      try {
         ip = IJ.getImage();
      } catch (Exception ex) {
         return;
      }

      ResultsTable outTable = new ResultsTable();
      String outTableName = Terms.RESULTTABLENAME;
      Window oldOutTable = WindowManager.getWindow(outTableName);
      if (oldOutTable != null) {
         WindowManager.removeWindow(oldOutTable);
         oldOutTable.dispose();
      }

      JSONObject parms = analysisSettings(showMasks_.isSelected());

      MMWindow mw = new MMWindow(ip);
      if (!mw.isMMWindow()) {
         TaggedImage tImg = ImageUtils.makeTaggedImage(ip.getProcessor());
         tImg.tags.put("PixelSizeUm", ip.getCalibration().pixelWidth);
         normalize(tImg, background_, flatfield_);
         Roi[] zapRois = analysisModule_.analyze(tImg, parms);
         for (Roi roi : zapRois) {
            outTable.incrementCounter();
            Rectangle bounds = roi.getBounds();
            int x = bounds.x + (int) (0.5 * bounds.width);
            int y = bounds.y + (int) (0.5 * bounds.height);
            outTable.addValue(Terms.X, x);
            outTable.addValue(Terms.Y, y);
            outTable.show(outTableName);
         }

      } else { // MMImageWindow
         int nrPositions = mw.getNumberOfPositions();
         for (int p = 1; p < nrPositions && !stop_.get(); p++) {
            try {
               if (nrPositions > 1)
                  mw.setPosition(p);
            } catch (MMScriptException ms) {
               ReportingUtils.showError(ms, "Error setting position in MMWindow");
            }
            try {
               if (nrPositions == 1 || mw.getImageMetadata(0, 0, 0, p) != null) {
                  TaggedImage tImg = ImageUtils.makeTaggedImage(ip.getProcessor());
                  tImg.tags.put("PixelSizeUm", ip.getCalibration().pixelWidth);
                  normalize(tImg, background_, flatfield_);
                  Roi[] zapRois = analysisModule_.analyze(tImg, parms);
                  for (Roi roi : zapRois) {
                     outTable.incrementCounter();
                     Rectangle bounds = roi.getBounds();
                     int x = bounds.x + (int) (0.5 * bounds.width);
                     int y = bounds.y + (int) (0.5 * bounds.height);
                     outTable.addValue(Terms.X, x);
                     outTable.addValue(Terms.Y, y);
                     outTable.addValue(Terms.POSITION, p);
                  }
                  outTable.show(outTableName);
               }
            } catch (JSONException ex) {
            } catch (MMScriptException ex) {
            } catch (NullPointerException npe) {
               ij.IJ.log("Null pointer exception at position : " + p);
            }
         }
      }

      // we have the ROIs, the rest is just reporting

      // add listeners to our ResultsTable that let user click on row and go
      // to cell that was found
      TextPanel tp;
      TextWindow win;
      Window frame = WindowManager.getWindow(outTableName);
      if (frame != null && frame instanceof TextWindow) {
         win = (TextWindow) frame;
         tp = win.getTextPanel();

         ResultsListener myk = new ResultsListener(ip, outTable, win);
         tp.addKeyListener(myk);
         tp.addMouseListener(myk);
         frame.toFront();
         frame.setVisible(true);
      }

      ij.IJ.log("Analyzed " + parms.getString(AnalysisModule.CELLCOUNT) +
              " nuclei, found " + parms.getString(AnalysisModule.OBJECTCOUNT) +
                      " nuclei with micronuclei" );

   }

   public void runAnalysisAndZapping(String saveLocation) throws IOException, MMScriptException, Exception {

      // Analysis class, in the future we could have a choice of these

      String channelGroup = gui_.getMMCore().getChannelGroup();

      //TODO: error checking for file IO!
      gui_.closeAllAcquisitions();
      new File(saveLocation).mkdirs();
      File resultsFile = new File(saveLocation + File.separator + "results.txt");
      resultsFile.createNewFile();
      BufferedWriter resultsWriter = new BufferedWriter(new FileWriter(resultsFile));

      PositionList posList = gui_.getPositionList();
      MultiStagePosition[] positions = posList.getPositions();
      String currentWell = "";
      int nrChannels = 1;
      if (secondImagingChannel_ != null && secondImagingChannel_.length() > 1) {
         nrChannels = 2;
      }

      ResultsTable outTable = new ResultsTable();
      String outTableName = Terms.RESULTTABLENAME;
      Window oldOutTable = WindowManager.getWindow(outTableName);
      if (oldOutTable != null) {
         WindowManager.removeWindow(oldOutTable);
         oldOutTable.dispose();
      }

      int nrImagesPerWell = 0;
      int wellCount = 0;

      // figure out how many sites per there are, we actually get that number
      // from the last well
      for (MultiStagePosition msp : positions) {
         String label = msp.getLabel();
         String well = label.split("-")[0];
         if (!currentWell.equals(well)) {
            currentWell = well;
            wellCount++;
            nrImagesPerWell = 1;
         } else
            nrImagesPerWell++;
      }
      gui_.message("Images per well: " + nrImagesPerWell);

      // start cycling through the sites and group everything by well
      int count = 0;
      int siteCount = 0;
      JSONObject parms = analysisSettings(showMasks_.isSelected());
      currentWell = "";
      for (MultiStagePosition msp : positions) {
         if (stop_.get()) {
            resultsWriter.close();
            return;
         }
         String label = msp.getLabel();
         String well = label.split("-")[0];
         if (!currentWell.equals(well)) {
            // new well
            gui_.message("Starting well: " + well);
            if (!currentWell.equals("")) {
               recordResults(resultsWriter, currentWell, parms);
            }
            currentWell = well;
            siteCount = 0;
            gui_.openAcquisition(well, saveLocation, 1, nrChannels + 1, 1, nrImagesPerWell, true, true);
            analysisModule_.reset();
            // reset cell and object counters
            parms.put(AnalysisModule.CELLCOUNT, 0);
            parms.put(AnalysisModule.OBJECTCOUNT, 0);
         }
         MultiStagePosition.goToPosition(msp, gui_.getMMCore());
         gui_.getMMCore().waitForSystem();
         gui_.message("Site: " + msp.getLabel() + ", x: " + msp.get(0).x + ", y: " + msp.get(0).y) ;
         gui_.getMMCore().setConfig(channelGroup, imagingChannel_);
         gui_.getMMCore().snapImage();
         TaggedImage tImg = gui_.getMMCore().getTaggedImage();
         gui_.addImageToAcquisition(well, 0, 0, 0, siteCount, tImg);
         try {
            MMAcquisition acqObject = gui_.getAcquisition(well);
            acqObject.setChannelName(0, imagingChannel_);
         } catch (MMScriptException ex) {
            // ignore since we do not want to crash our acquisition
         }
         if (nrChannels == 2) {
            gui_.getMMCore().setConfig(channelGroup, secondImagingChannel_);
            gui_.getMMCore().snapImage();
            TaggedImage t2Img = gui_.getMMCore().getTaggedImage();
            gui_.addImageToAcquisition(well, 0, 1, 0, siteCount, t2Img);
            MMAcquisition acqObject = gui_.getAcquisition(well);
            try {
               acqObject.setChannelColor(1, new Color(0, 0, 255).getRGB());
               acqObject.setChannelName(1, secondImagingChannel_);
            } catch (MMScriptException ex) {
               // ignore since we do not want to crash our acquisition
            }
         }
         gui_.getMMCore().setConfig(channelGroup, zapChannel_);

         // analyze the second channel if that is the one we took

         // Analyze and zap
         normalize(tImg, background_, flatfield_);
         Roi[] zapRois = analysisModule_.analyze(tImg, parms);
         if (zapRois != null) {
            zap(zapRois);
            for (Roi roi : zapRois) {
               outTable.incrementCounter();
               Rectangle bounds = roi.getBounds();
               int x = bounds.x + (int) (0.5 * bounds.width);
               int y = bounds.y + (int) (0.5 * bounds.height);
               outTable.addValue(Terms.X, x);
               outTable.addValue(Terms.Y, y);
               outTable.addValue(Terms.POSITION, siteCount);
            }
            outTable.show(outTableName);

            if (zapRois.length > 0) {
               String acq2 = msp.getLabel();
               gui_.message("Imaging zapped cells at site: " + acq2);
               // take the red image and save it
               gui_.getMMCore().setConfig(channelGroup, afterZapChannel_);
               gui_.getMMCore().snapImage();
               TaggedImage tImg2 = gui_.getMMCore().getTaggedImage();
               gui_.addImageToAcquisition(well, 0, nrChannels, 0, siteCount, tImg2);
               MMAcquisition acqObject = gui_.getAcquisition(well);
               try {
                  acqObject.setChannelColor(nrChannels, new Color(255, 0, 0).getRGB());
                  acqObject.setChannelName(nrChannels, "zapped");
               } catch (Exception ex) {
                  // ignore since we do not want to crash our acquisition
               }
            }
         }
         siteCount++;
         count++;
      }

      // add listeners to our ResultsTable that let user click on row and go
      // to cell that was found
      TextPanel tp;
      TextWindow win;
      Window frame = WindowManager.getWindow(outTableName);
      if (frame != null && frame instanceof TextWindow) {
         win = (TextWindow) frame;
         tp = win.getTextPanel();

         ResultsListener myk = new ResultsListener(IJ.getImage(), outTable, win);
         tp.addKeyListener(myk);
         tp.addMouseListener(myk);
         frame.toFront();
         frame.setVisible(true);
      }

      // record the results from the last well:
      recordResults(resultsWriter, currentWell, parms);

      resultsWriter.close();
      String msg = "Analyzed " + count + " images, in " + wellCount + " wells.";
      gui_.message(msg);
      ReportingUtils.showMessage(msg);
   }

   private void recordResults(BufferedWriter resultsWriter, String currentWell,
           final JSONObject parms) throws IOException, MMScriptException {
      resultsWriter.write(currentWell + "\t" +
              parms.optInt(AnalysisModule.CELLCOUNT) + "\t" +
              parms.optInt(AnalysisModule.OBJECTCOUNT) );
      resultsWriter.newLine();
      resultsWriter.flush();
      gui_.message(currentWell + " " + parms.optInt(AnalysisModule.CELLCOUNT) +
              "    " + parms.optInt(AnalysisModule.OBJECTCOUNT) );
   }

   /**
    * Generates an initialized JSONObject to be used to communicate analysis settings
    * @param showMask - whether or not to show the masks during analysis
    * @return initialized JSONObject with default analysis settings
    * @throws JSONException
    */
   private JSONObject analysisSettings(boolean showMask) throws JSONException {
      JSONObject parms = new JSONObject();
      parms.put(AnalysisModule.SHOWMASKS, showMask);
      parms.put(AnalysisModule.CELLCOUNT, 0);
      parms.put(AnalysisModule.OBJECTCOUNT, 0);
      return parms;
   }

   /**
    * Photoconverts the provided ROIs
    * @param rois
    * @throws MMScriptException
    */
   private void zap(Roi[] rois) throws MMScriptException {
      if (rois == null)
         return;
      ProjectorControlForm pcf
              = ProjectorControlForm.showSingleton(gui_.getMMCore(), gui_);
      int i;
      // convert zapRois in a Roi[] of Polygon Rois
      for (i = 0; i < rois.length; i++) {
         Polygon poly = rois[i].getConvexHull();
         rois[i] = new PolygonRoi(poly, Roi.POLYGON);
      }

      // send to the galvo device and zap them for real
      pcf.setNrRepetitions(5);
      for (i = 0; i < rois.length; i++) {
         gui_.message("Zapping " + (i + 1) + " of " + rois.length);
         Roi[] theRois = {rois[i]};
         pcf.setROIs(theRois);
         pcf.updateROISettings();
         pcf.getDevice().waitForDevice();
         pcf.runRois();
         pcf.getDevice().waitForDevice();
      }

   }

   /**
    * makes border with centered title text
    * @param title
    * @return
    */
   public static TitledBorder makeTitledBorder(String title) {
      TitledBorder myBorder = BorderFactory.createTitledBorder(
              BorderFactory.createLineBorder(Color.gray), title);
      myBorder.setTitleJustification(TitledBorder.CENTER);
      return myBorder;
   }

   /**
    * Normalize input image as follows:  (image - background) / flatfield
    * Flatfield image should have been background subtracted and normalized
    * at 1.0 for the average pixels values to stay the same
    * @param input Image to be normalized
    * @param background image
    * @param flatField image with average value of 1.0 representing flatness of field
    * @return normalized image
    */
   public static TaggedImage normalize(TaggedImage input, ImagePlus background,
           ImagePlus flatField) {
      ImageCalculator ic = new ImageCalculator();
      // TODO: deal with image of incompatible size and/or type
      if (flatField != null) {
         ImagePlus imp = new ImagePlus("tmp", ImageUtils.makeProcessor(input));
         if (background != null) {
            ic.run("Subtract", imp, background);
         }
         imp = ic.run("Divide, float, 32", imp, flatField);
         IJ.run(imp, "16-bit", "");
         TaggedImage tImg = new TaggedImage(imp.getProcessor().getPixels(),
                 input.tags);
         return tImg;
      }

      return input;
   }

   private static void warnAboutMissingCorrections(ImagePlus background,
           ImagePlus flatfield) {
      if (background == null) {
         ij.IJ.log("No background correction applied because of missing background image");
      }
      if (flatfield == null) {
         ij.IJ.log("No flatfield correction applied because of missing flatfield image");
      }
   }

}


text:
package org.apache.storm.redis.trident;

import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.LocalCluster.LocalTopology;
import org.apache.storm.StormSubmitter;
import org.apache.storm.generated.StormTopology;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;
import org.apache.storm.redis.common.mapper.RedisDataTypeDescription;
import org.apache.storm.redis.trident.state.RedisMapState;
import org.apache.storm.redis.common.config.JedisPoolConfig;
import org.apache.storm.trident.Stream;
import org.apache.storm.trident.TridentState;
import org.apache.storm.trident.TridentTopology;
import org.apache.storm.trident.operation.builtin.MapGet;
import org.apache.storm.trident.operation.builtin.Sum;
import org.apache.storm.trident.state.StateFactory;
import org.apache.storm.trident.testing.FixedBatchSpout;

public class WordCountTridentRedisMap {
    public static StormTopology buildTopology(String redisHost, Integer redisPort){
        Fields fields = new Fields("word", "count");
        FixedBatchSpout spout = new FixedBatchSpout(fields, 4,
                new Values("storm", 1),
                new Values("trident", 1),
                new Values("needs", 1),
                new Values("javadoc", 1)
        );
        spout.setCycle(true);

        JedisPoolConfig poolConfig = new JedisPoolConfig.Builder()
                                        .setHost(redisHost).setPort(redisPort)
                                        .build();

        RedisDataTypeDescription dataTypeDescription = new RedisDataTypeDescription(
                RedisDataTypeDescription.RedisDataType.HASH, "test");
        StateFactory factory = RedisMapState.transactional(poolConfig, dataTypeDescription);

        TridentTopology topology = new TridentTopology();
        Stream stream = topology.newStream("spout1", spout);

        TridentState state = stream.groupBy(new Fields("word"))
                .persistentAggregate(factory, new Fields("count"), new Sum(), new Fields("sum"));

        stream.stateQuery(state, new Fields("word"), new MapGet(), new Fields("sum"))
                .each(new Fields("word", "sum"), new PrintFunction(), new Fields());
        return topology.build();
    }

    public static void main(String[] args) throws Exception {
        if (args.length != 3) {
            System.out.println("Usage: WordCountTrident 0(storm-local)|1(storm-cluster) redis-host redis-port");
            System.exit(1);
        }

        Integer flag = Integer.valueOf(args[0]);
        String redisHost = args[1];
        Integer redisPort = Integer.valueOf(args[2]);

        Config conf = new Config();
        conf.setMaxSpoutPending(5);
        if (flag == 0) {
            try (LocalCluster cluster = new LocalCluster();
                LocalTopology topo = cluster.submitTopology("test_wordCounter_for_redis", conf, buildTopology(redisHost, redisPort))) {
                Thread.sleep(60 * 1000);
            }
            System.exit(0);
        } else if(flag == 1) {
            conf.setNumWorkers(3);
            StormSubmitter.submitTopology("test_wordCounter_for_redis", conf, buildTopology(redisHost, redisPort));
        } else {
            System.out.println("Usage: WordCountTrident 0(storm-local)|1(storm-cluster) redis-host redis-port");
        }
    }

}


text:
class empty
{
};

int main()
{
    std::string name = boost::typeindex::ctti_type_index::type_id<empty>().pretty_name();
    BOOST_TEST(name.find("empty") != std::string::npos);
    return boost::report_errors();
}


text:
<?php

return [

	/*
	|--------------------------------------------------------------------------
	| Admin Page Reminder Language Lines
	|--------------------------------------------------------------------------
	|
	| The following language lines are the english lines for admin page.
	|
	*/

	"AllRequests" => "All requests",
	"User" => "User",
	"Template" => "Template",
	"details" => "details",
	"NoRequests" => "No requests",
	"AllUsers" => "All users",
	"User" => "User",
	"NoUsers" => "No users",

];


text:
TODO: Write a description here

## Installation

TODO: Write installation instructions here

## Usage

TODO: Write usage instructions here

## Development

TODO: Write development instructions here

## Contributing

1. Fork it ( https://github.com/[your-github-name]/SocketBroker/fork )
2. Create your feature branch (git checkout -b my-new-feature)
3. Commit your changes (git commit -am 'Add some feature')
4. Push to the branch (git push origin my-new-feature)
5. Create a new Pull Request

## Contributors

- [[your-github-name]](https://github.com/[your-github-name]) Christopher Ostrowski - creator, maintainer