AbstractListener.java

  1. package gov.usgs.earthquake.product;

  2. import gov.usgs.util.Config;
  3. import gov.usgs.util.DefaultConfigurable;
  4. import gov.usgs.util.StringUtils;

  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import java.util.logging.Logger;

  8. /**
  9.  * A base listener implementation for both NotificationListener and
  10.  * IndexerListener implementations.
  11.  *
  12.  * The AbstractListener implements the Configurable interface and defines the
  13.  * following configuration parameters:
  14.  *
  15.  * <dl>
  16.  * <dt>includeTypes</dt>
  17.  * <dd>(Optional) A comma separated list of product types to include. If this
  18.  * list is defined it constitutes an "allow" list, and only types in this list
  19.  * are allowed.</dd>
  20.  *
  21.  * <dt>excludeTypes</dt>
  22.  * <dd>(Optional) A comma separated list of product types to exclude. If this
  23.  * list is defined it constitutes a "block" list, and types in this list are not
  24.  * allowed.</dd>
  25.  *
  26.  * <dt>includeSources</dt>
  27.  * <dd>(Optional) A comma separated list of product types to include. If this
  28.  * list is defined it constitutes an "allow" list, and only types in this list
  29.  * are allowed.</dd>
  30.  *
  31.  * <dt>excludeSources</dt>
  32.  * <dd>(Optional) A comma separated list of product types to exclude. If this
  33.  * list is defined it constitutes a "block" list, and types in this list are not
  34.  * allowed.</dd>
  35.  *
  36.  * <dt>includeTests</dt>
  37.  * <dd>(Optional, Default false) Flag to indicate test products should be
  38.  * accepted. Set to "true" or "yes" to enable.</dd>
  39.  *
  40.  * <dt>includeScenarios</dt>
  41.  * <dd>(Optional, Default false) Flag to indicate scenario products should be
  42.  * accepted. Set to "true" or "yes" to enable.</dd>
  43.  *
  44.  * <dt>includeActuals</dt>
  45.  * <dd>(Optional, Default true) Flag to indicate Actual products should be
  46.  * accepted. Set to "true" or "yes" to enable.</dd>
  47.  *
  48.  * <dt>includeInternals</dt>
  49.  * <dd>(Optional, Default false) Flag to indicate internal products should be
  50.  * accepted. Set to "true" or "yes" to enable.</dd>
  51.  *
  52.  * <dt>includeDevelopments</dt>
  53.  * <dd>(Optional, Default false) Flag to indicate development products should be
  54.  * accepted. Set to "true" or "yes" to enable.</dd>
  55.  *
  56.  * <dt>maxTries</dt>
  57.  * <dd>(Optional, Default 1) Number of times to attempt delivery of each
  58.  * notification, if the listener throws a ContinuableListenerException during
  59.  * onNotification(). A value &lt;= 1 means do not re-attempt.</dd>
  60.  *
  61.  * <dt>timeout</dt>
  62.  * <dd>(Optional, Default 0) Number of milliseconds before thread running
  63.  * onNotification() is interrupted. A value &lt;= 0 means never interrupt.</dd>
  64.  *
  65.  * <dt>retryDelay</dt>
  66.  * <dd>(Optional, Default 0) Number of milliseconds to wait before re-attempting
  67.  * processing of a notification, if the listener throws a
  68.  * ContinuableListenerException during onNotification().
  69.  * A value &lt;= 0 means no delay.</dd>
  70.  * </dl>
  71.  *
  72.  * <p>
  73.  * When excludeTypes (or sources) and includeTypes (or sources) are defined,
  74.  * excludes are processed first. This is usually not recommended.
  75.  * </p>
  76.  */
  77. public class AbstractListener extends DefaultConfigurable {

  78.     /** Logging object. */
  79.     private static final Logger LOGGER = Logger
  80.             .getLogger(AbstractListener.class.getName());

  81.     // --------------------------------------------------
  82.     // Configurable property names
  83.     // --------------------------------------------------

  84.     /** Configuration parameter for include types list. */
  85.     public static final String INCLUDE_TYPES_PROPERTY = "includeTypes";

  86.     /** Configuration parameter for exclude types list. */
  87.     public static final String EXCLUDE_TYPES_PROPERTY = "excludeTypes";

  88.     /** Configuration parameter for include sources list. */
  89.     public static final String INCLUDE_SOURCES_PROPERTY = "includeSources";

  90.     /** Configuration parameter for exclude sources list. */
  91.     public static final String EXCLUDE_SOURCES_PROPERTY = "excludeSources";

  92.     /** Flag to indicate if scenario type products should be included **/
  93.     public static final String INCLUDE_TESTS_PROPERTY = "includeTests";

  94.     /** Flag to indicate if scenario type products should be included **/
  95.     public static final String INCLUDE_SCENARIOS_PROPERTY = "includeScenarios";
  96.    
  97.     /** Flag to indicate if actual type products should be included **/
  98.     public static final String INCLUDE_ACTUALS_PROPERTY = "includeActuals";

  99.     /** Flag to indicate if scenario type products should be included **/
  100.     public static final String INCLUDE_INTERNALS_PROPERTY = "includeInternals";

  101.     /** Flag to indicate if scenario type products should be included **/
  102.     public static final String INCLUDE_DEVELOPMENTS_PROPERTY = "includeDevelopments";

  103.     /**
  104.      * Configuration parameters for attemptCount.
  105.      *
  106.      * @deprecated Use MAX_TRIES_PROPERTY instead.
  107.      */
  108.     public static final String ATTEMPT_COUNT_PROPERTY = "attemptCount";

  109.     /** Configuration parameters for maxTries. */
  110.     public static final String MAX_TRIES_PROPERTY = "maxTries";

  111.     /** Configuration parameter for timeout. */
  112.     public static final String TIMEOUT_PROPERTY = "timeout";

  113.     /** Configuration parameter for retryDelay. */
  114.     public static final String RETRY_DELAY_PROPERTY = "retryDelay";

  115.     // --------------------------------------------------
  116.     // Default values for configurable settings
  117.     // --------------------------------------------------

  118.     // Default setting for include/exclude types/sources variables are to
  119.     // remain empty lists. Default interpretation of this setting is defined in
  120.     // the "accept" method and will accept all types/sources. This can be
  121.     // overridden in a subclass.

  122.     /** Default, do not include tests */
  123.     private static final boolean DEFAULT_INCLUDE_TESTS = false;

  124.     /** Default, do not include scenarios */
  125.     private static final boolean DEFAULT_INCLUDE_SCENARIOS = false;
  126.    
  127.     /** Default, do include actuals */
  128.     private static final boolean DEFAULT_INCLUDE_ACTUALS = true;

  129.     /** Default, do not include internals */
  130.     private static final boolean DEFAULT_INCLUDE_INTERNALS = false;

  131.     /** Default, do not include developments */
  132.     private static final boolean DEFAULT_INCLUDE_DEVELOPMENTS = false;

  133.     /** Default attempt count value is 1 = don't retry. */
  134.     public static final int DEFAULT_ATTEMPT_COUNT = 1;

  135.     /** Default timeout is 0 = infinity. */
  136.     public static final long DEFAULT_TIMEOUT = 0L;

  137.     /** Default delay is 300000ms = 5 minute delay. */
  138.     public static final long DEFAULT_RETRY_DELAY = 300000L;

  139.     // --------------------------------------------------
  140.     // Member variables
  141.     // --------------------------------------------------

  142.     /** Types of products to allow. */
  143.     private final ArrayList<String> includeTypes = new ArrayList<String>();

  144.     /** Types of products to block. */
  145.     private final ArrayList<String> excludeTypes = new ArrayList<String>();

  146.     /** Sources of products to allow. */
  147.     private final ArrayList<String> includeSources = new ArrayList<String>();

  148.     /** Sources of products to block. */
  149.     private final ArrayList<String> excludeSources = new ArrayList<String>();

  150.     /** Whether or not to include test type products */
  151.     private boolean includeTests = DEFAULT_INCLUDE_TESTS;

  152.     /** Whether or not to include scenario type products */
  153.     private boolean includeScenarios = DEFAULT_INCLUDE_SCENARIOS;
  154.    
  155.     /** Whether or not to include actual type products */
  156.     private boolean includeActuals = DEFAULT_INCLUDE_ACTUALS;

  157.     /** Whether or not to include internal type products */
  158.     private boolean includeInternals = DEFAULT_INCLUDE_INTERNALS;

  159.     /** Whether or not to include development type products */
  160.     private boolean includeDevelopments = DEFAULT_INCLUDE_DEVELOPMENTS;

  161.     /** Number of retries when a continuable listener exception is thrown. */
  162.     private int maxTries = DEFAULT_ATTEMPT_COUNT;

  163.     /** Number of milliseconds before the onNotification thread is interrupted. */
  164.     private long timeout = DEFAULT_TIMEOUT;

  165.     /** Number of milliseconds before retries, after the first attempt fails. */
  166.     private long retryDelay = DEFAULT_RETRY_DELAY;

  167.     /**
  168.      * Determines if a listener accepts a message based on the incoming product
  169.      * id.
  170.      *
  171.      * @param id
  172.      *            The incoming id of the product that triggered the message.
  173.      *
  174.      * @return True if the message should be processed, false otherwise.
  175.      */
  176.     public boolean accept(ProductId id) {
  177.         String type = id.getType();
  178.         String source = id.getSource();

  179.         // excluded type
  180.         if (excludeTypes.size() > 0 && excludeTypes.contains(type)) {
  181.             LOGGER.finer("[" + getName() + "] product type '" + type
  182.                     + "' excluded");
  183.             return false;
  184.         }

  185.         // not included type
  186.         if (includeTypes.size() > 0 && !includeTypes.contains(type)) {
  187.             LOGGER.finer("[" + getName() + "] product type '" + type
  188.                     + "' not included");
  189.             return false;
  190.         }

  191.         // excluded source
  192.         if (excludeSources.size() > 0 && excludeSources.contains(source)) {
  193.             LOGGER.finer("[" + getName() + "] product source '" + source
  194.                     + "' excluded");
  195.             return false;
  196.         }

  197.         // not included source
  198.         if (includeSources.size() > 0 && !includeSources.contains(source)) {
  199.             LOGGER.finer("[" + getName() + "] product source '" + source
  200.                     + "' not included");
  201.             return false;
  202.         }

  203.         if (type.endsWith("-test") && !includeTests) {
  204.             LOGGER.finer("[" + getName()
  205.                     + "] product type was test. Not included.");
  206.             return false;
  207.         }

  208.         if (type.endsWith("-scenario") && !includeScenarios) {
  209.             LOGGER.finer("[" + getName()
  210.                     + "] product type was scenario. Not included.");
  211.             return false;
  212.         }
  213.        
  214.         if (!includeActuals &&
  215.                 !type.endsWith("-scenario") &&
  216.                 !type.startsWith("internal-") &&
  217.                 !type.endsWith("-devel")
  218.             ) {
  219.             LOGGER.finer("[" + getName()
  220.                     + "] product type was actual. Not included.");
  221.             return false;
  222.         }

  223.         if (type.startsWith("internal-") && !includeInternals) {
  224.             LOGGER.finer("[" + getName()
  225.                     + "] product type was internal. Not included.");
  226.             return false;
  227.         }

  228.         if (type.endsWith("-devel") && !includeDevelopments) {
  229.             LOGGER.finer("[" + getName()
  230.                     + "] product type was development version. Not included.");
  231.             return false;
  232.         }

  233.         // otherwise accept
  234.         return true;
  235.     }

  236.     /**
  237.      * Read the include and exclude types from config.
  238.      */
  239.     public void configure(final Config config) throws Exception {
  240.         String includeTypeNames = config.getProperty(INCLUDE_TYPES_PROPERTY);
  241.         if (includeTypeNames != null) {
  242.             includeTypes.addAll(StringUtils.split(includeTypeNames, ","));
  243.             LOGGER.config("[" + getName() + "] includeTypes = "
  244.                     + includeTypeNames);
  245.         }
  246.         String excludeTypeNames = config.getProperty(EXCLUDE_TYPES_PROPERTY);
  247.         if (excludeTypeNames != null) {
  248.             excludeTypes.addAll(StringUtils.split(excludeTypeNames, ","));
  249.             LOGGER.config("[" + getName() + "] excludeTypes = "
  250.                     + excludeTypeNames);
  251.         }

  252.         String includeSourceNames = config
  253.                 .getProperty(INCLUDE_SOURCES_PROPERTY);
  254.         if (includeSourceNames != null) {
  255.             includeSources.addAll(StringUtils.split(includeSourceNames, ","));
  256.             LOGGER.config("[" + getName() + "] includeSources = "
  257.                     + includeSourceNames);
  258.         }
  259.         String excludeSourceNames = config
  260.                 .getProperty(EXCLUDE_SOURCES_PROPERTY);
  261.         if (excludeSourceNames != null) {
  262.             excludeSources.addAll(StringUtils.split(excludeSourceNames, ","));
  263.             LOGGER.config("[" + getName() + "] excludeSources = "
  264.                     + excludeSourceNames);
  265.         }

  266.         String includeFlag = config.getProperty(INCLUDE_TESTS_PROPERTY);
  267.         if (includeFlag != null) {
  268.             includeTests = (includeFlag.equalsIgnoreCase("yes") ||
  269.                     includeFlag.equalsIgnoreCase("true"));
  270.             LOGGER.config("[" + getName() + "] includeTests = "
  271.                     + includeTests);
  272.         } else {
  273.             includeDevelopments = DEFAULT_INCLUDE_TESTS;
  274.         }

  275.         includeFlag = config.getProperty(INCLUDE_SCENARIOS_PROPERTY);
  276.         if (includeFlag != null) {
  277.             includeScenarios = (includeFlag.equalsIgnoreCase("yes") ||
  278.                     includeFlag.equalsIgnoreCase("true"));
  279.             LOGGER.config("[" + getName() + "] includeScenarios = "
  280.                     + includeScenarios);
  281.         } else {
  282.             includeDevelopments = DEFAULT_INCLUDE_SCENARIOS;
  283.         }
  284.        
  285.         includeFlag = config.getProperty(INCLUDE_ACTUALS_PROPERTY);
  286.         if (includeFlag != null) {
  287.             includeActuals = !(includeFlag.equalsIgnoreCase("no") ||
  288.                     includeFlag.equalsIgnoreCase("false"));
  289.             LOGGER.config("[" + getName() + "] includeActuals = "
  290.                     + includeActuals);
  291.         }

  292.         includeFlag = config.getProperty(INCLUDE_INTERNALS_PROPERTY);
  293.         if (includeFlag != null) {
  294.             includeInternals = (includeFlag.equalsIgnoreCase("yes") ||
  295.                     includeFlag.equalsIgnoreCase("true"));
  296.             LOGGER.config("[" + getName() + "] includeInternals = "
  297.                     + includeInternals);
  298.         } else {
  299.             includeDevelopments = DEFAULT_INCLUDE_INTERNALS;
  300.         }

  301.         includeFlag = config.getProperty(INCLUDE_DEVELOPMENTS_PROPERTY);
  302.         if (includeFlag != null) {
  303.             includeDevelopments = (includeFlag.equalsIgnoreCase("yes") ||
  304.                     includeFlag.equalsIgnoreCase("true"));
  305.             LOGGER.config("[" + getName() + "] includeDevelopments = "
  306.                     + includeDevelopments);
  307.         } else {
  308.             includeDevelopments = DEFAULT_INCLUDE_DEVELOPMENTS;
  309.         }

  310.         String maxTriesStr = config.getProperty(ATTEMPT_COUNT_PROPERTY);
  311.         if (maxTriesStr != null) {
  312.             maxTries = Integer.parseInt(maxTriesStr);
  313.             LOGGER.config("[" + getName() + "] Configured using deprecated '" +
  314.                     ATTEMPT_COUNT_PROPERTY +
  315.                     "' property. Prefer to use the new '" + MAX_TRIES_PROPERTY +
  316.                     "' instead. Support for the deprecated property may be " +
  317.                     "removed in a subsequent release.");
  318.         }
  319.         LOGGER.config("[" + getName() + "] maxTries = " + maxTries);

  320.         // By checking for this parameter after the ATTEMPT_COUNT_PROPERTY, the
  321.         // value of the MAX_TRIES_PROPERTY (if specified) will take precedence.
  322.         maxTriesStr = config.getProperty(MAX_TRIES_PROPERTY);
  323.         if (maxTriesStr != null) {
  324.             maxTries = Integer.parseInt(maxTriesStr);
  325.         }
  326.         LOGGER.config("[" + getName() + "] maxTries = " + maxTries);

  327.         String timeoutStr = config.getProperty(TIMEOUT_PROPERTY);
  328.         if (timeoutStr != null) {
  329.             timeout = Long.parseLong(timeoutStr);
  330.         }
  331.         LOGGER.config("[" + getName() + "] timeout = " + timeout + "ms");

  332.         String retryDelayStr = config.getProperty(RETRY_DELAY_PROPERTY);
  333.         if (retryDelayStr != null) {
  334.             retryDelay = Long.parseLong(retryDelayStr);
  335.         }
  336.         LOGGER.config("[" + getName() + "] retry delay = " + retryDelay + "ms");
  337.     }

  338.     /**
  339.      * @return the includeTypes
  340.      */
  341.     public List<String> getIncludeTypes() {
  342.         return includeTypes;
  343.     }

  344.     /**
  345.      * @return the excludeTypes
  346.      */
  347.     public List<String> getExcludeTypes() {
  348.         return excludeTypes;
  349.     }

  350.     /**
  351.      * @return the includeSources
  352.      */
  353.     public List<String> getIncludeSources() {
  354.         return includeSources;
  355.     }

  356.     /**
  357.      * @return the excludeSources
  358.      */
  359.     public List<String> getExcludeSources() {
  360.         return excludeSources;
  361.     }

  362.     /**
  363.      * Number of tries to deliver notification, when an Exception is thrown
  364.      * during onNotification().
  365.      *
  366.      * @return the attemptCount. A value &lt; 1 means never try to deliver.
  367.      */
  368.     public int getMaxTries() {
  369.         return maxTries;
  370.     }

  371.     /**
  372.      * Set the maxTries.
  373.      *
  374.      * @param maxTries
  375.      *            the maxTries. A value &lt; 1 means never try to deliver.
  376.      */
  377.     public void setMaxTries(final int maxTries) {
  378.         this.maxTries = maxTries;
  379.     }

  380.     /**
  381.      * Number of milliseconds onNotification is allowed to run before being
  382.      * interrupted.
  383.      *
  384.      * @return the timeout in milliseconds. A value &lt;= 0 means never timeout.
  385.      */
  386.     public long getTimeout() {
  387.         return timeout;
  388.     }

  389.     /**
  390.      * Set the timeout.
  391.      *
  392.      * @param timeout
  393.      *            the timeout in milliseconds. A value &lt;= 0 means never timeout.
  394.      */
  395.     public void setTimeout(final long timeout) {
  396.         this.timeout = timeout;
  397.     }

  398.     /**
  399.      * @return the includeTests
  400.      */
  401.     public boolean isIncludeTests() {
  402.         return includeTests;
  403.     }

  404.     /**
  405.      * @param includeTests the includeTests to set
  406.      */
  407.     public void setIncludeTests(boolean includeTests) {
  408.         this.includeTests = includeTests;
  409.     }

  410.     /**
  411.      * @return the includeScenarios
  412.      */
  413.     public boolean isIncludeScenarios() {
  414.         return includeScenarios;
  415.     }

  416.     /**
  417.      * @param includeScenarios the includeScenarios to set
  418.      */
  419.     public void setIncludeScenarios(boolean includeScenarios) {
  420.         this.includeScenarios = includeScenarios;
  421.     }
  422.    
  423.     /**
  424.      * @return the includeActuals
  425.      */
  426.     public boolean isIncludeActuals() {
  427.         return includeActuals;
  428.     }

  429.     /**
  430.      * @param includeActuals the includeActuals to set
  431.      */
  432.     public void setIncludeActuals(boolean includeActuals) {
  433.         this.includeActuals = includeActuals;
  434.     }

  435.     /**
  436.      * @return the includeInternals
  437.      */
  438.     public boolean isIncludeInternals() {
  439.         return includeInternals;
  440.     }

  441.     /**
  442.      * @param includeInternals the includeInternals to set
  443.      */
  444.     public void setIncludeInternals(boolean includeInternals) {
  445.         this.includeInternals = includeInternals;
  446.     }

  447.     /**
  448.      * @return the includeDevelopments
  449.      */
  450.     public boolean isIncludeDevelopments() {
  451.         return includeDevelopments;
  452.     }

  453.     /**
  454.      * @param includeDevelopments the includeDevelopments to set
  455.      */
  456.     public void setIncludeDevelopments(boolean includeDevelopments) {
  457.         this.includeDevelopments = includeDevelopments;
  458.     }

  459.     /**
  460.      * @return the retryDelay
  461.      */
  462.     public long getRetryDelay() {
  463.         return retryDelay;
  464.     }

  465.     /**
  466.      * @param retryDelay the retryDelay to set
  467.      */
  468.     public void setRetryDelay(long retryDelay) {
  469.         this.retryDelay = retryDelay;
  470.     }

  471. }