File Source: PingConfig.java

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  The ASF licenses this file to You
     4   * under the Apache License, Version 2.0 (the "License"); you may not
     5   * use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.  For additional information regarding
    15   * copyright in this work, please see the NOTICE file in the top level
    16   * directory of this distribution.
    17   */
    18  
    19  package org.apache.roller.weblogger.config;
    20  
    21  import org.apache.commons.logging.Log;
    22  import org.apache.commons.logging.LogFactory;
    23  import org.apache.roller.weblogger.WebloggerException;
    24  import org.apache.roller.weblogger.business.pings.PingTargetManager;
    25  import org.apache.roller.weblogger.business.WebloggerFactory;
    26  import org.apache.roller.weblogger.pojos.PingTarget;
    27  
    28  import java.util.*;
    29  import java.util.regex.Matcher;
    30  import java.util.regex.Pattern;
    31  
    32  // This may need to move to a different package, but it seems appropriate here in the current structure.
    33  // Previous placement in the presentation.pings package introduced the undesirable dependency of the
    34  // business package on the presentation package.
    35  
    36  /**
    37   * Thin wrapper around WebloggerConfig and WebloggerRuntimeConfig for centralizing access to the many configurable
    38   * settings for pings.
    39   * 
    40   * 
    41   * @author <a href="mailto:anil@busybuddha.org">Anil Gangolli</a>
    42   */
    43  public class PingConfig {
             /* 
    P/P       *  Method: org.apache.roller.weblogger.config.PingConfig__static_init
              * 
              *  Postconditions:
              *    init'ed(NESTED_BRACE_PAIR)
              *    configuredVariants == &new HashMap(PingConfig__static_init#1)
              *    init'ed(logger)
              *    new HashMap(PingConfig__static_init#1) num objects == 1
              */
    44      private static final Log logger = LogFactory.getLog(PingConfig.class);
    45  
    46  
    47      // Config property for maximim ping attempts.
    48      static final String MAX_PING_ATTEMPTS_PROP = "pings.maxPingAttempts";
    49      private static final int MAX_PING_ATTEMPTS_DEFAULT = 3;
    50      private static final int MAX_PING_ATTEMPTS_MIN = 1;
    51      private static final int MAX_PING_ATTEMPTS_MAX = 10;
    52  
    53      // Config property for queue processing interval
    54      private static final String QUEUE_PROCESSING_INTERVAL_PROP = "pings.queueProcessingIntervalMins";
    55      private static final int QUEUE_PROCESSING_INTERVAL_DEFAULT = 5;
    56      private static final int QUEUE_PROCESSING_INTERVAL_MIN = 0;
    57      private static final int QUEUE_PROCESSING_INTERVAL_MAX = 120;
    58  
    59      // PingConfig property for logging pings (not actually performing them).  Used for debugging.
    60      private static final String PINGS_LOG_ONLY_PROP = "pings.logOnly";
    61      private static final boolean PINGS_LOG_ONLY_DEFAULT = false;
    62  
    63      // PingConfig property for controlling whether or not to allow custom ping targets
    64      // ("Weblog:Custom Ping Targets" page and actions).  If absent, this defaults to false.
    65      // with the enabledProperty behavior in editor-menu.xml.
    66      // NOTE: If this property name is changed, editor-menu.xml must also be adjusted.
    67      private static final String PINGS_DISALLOW_CUSTOM_TARGETS_PROP = "pings.disallowCustomTargets";
    68      private static final boolean PINGS_DISALLOW_CUSTOM_TARGETS_DEFAULT = false;
    69  
    70      // PingConfig property for controlling whether or not to allow usage of pings
    71      // ("Weblog:Pings" page and actions).  If absent, this defaults to false
    72      // NOTE: If this property name is changed, editor-menu.xml must also be adjusted.
    73      private static final String PINGS_DISABLE_PING_USAGE_PROP = "pings.disablePingUsage";
    74      private static final boolean PINGS_DISABLE_PING_USAGE_DEFAULT = false;
    75  
    76      // PingConfig property for controlling suspending the processing of pings.  If true,
    77      // new auto ping requests are not queued, any existing queued requests are not processed,
    78      // and sending a manual ping results in a  message saying pings have been disabled.
    79      // NOTE: This is a "runtime" property settable on the Admin:PingConfig page, default is false.
    80      private static final String PINGS_SUSPEND_PING_PROCESSING_PROP = "pings.suspendPingProcessing";
    81  
    82      // PingConfig property determining the initial common ping targets.  If the list of common
    83      // ping targets is empty on startup, the value of this property is used to populate initial values.
    84      // The value takes the form of comma-separated ping targets where each ping target is specified in
    85      // the form {{name}{pingurl}}.  If an administrator wants to disable this initialization, in order to
    86      // maintain an empty list of common targets, the administrator can disable the initialization by
    87      // commenting out this property in the config file.
    88      private static final String PINGS_INITIAL_COMMON_TARGETS_PROP = "pings.initialCommonTargets";
    89  
    90  
    91      // PingConfig property determining the known WeblogUpdates.ping variants/bugs
    92      // in popular ping targets, which we are used when invoking pings on those targets.
    93      // The value takes the form of a comma separated list of ping target urls and
    94      // variant options, where each one is in the form {{pingurl}{option[[,option]...]}}.
    95      private static final String PINGS_VARIANT_OPTIONS_PROP = "pings.variantOptions";
    96      // Map of configured ping variants.  Maps a ping target hostname to a set of
    97      // Strings representing variant options to be used when pinging this target.
    98      // This was introduced in order to support certain buggy (but popular) ping
    99      // targets that implement minor variants of the WeblogUpdates.ping call.
   100      // This is initialized once at startup, and referenced when pings are made.
   101      private static final Map configuredVariants = new HashMap();
   102      
   103      // Pattern used to parse common ping targets as well as ping variants.
   104      // Each initial commmon ping target is specified in the format {{name}{url}}
   105      // Ping variants are also specified in a nested brace format {{url}{options}}
   106      private static final Pattern NESTED_BRACE_PAIR = Pattern.compile("\\{\\{(.*?)\\}\\{(.*?)\\}\\}");
   107  
   108  
   109      // Inhibit construction
             /* 
    P/P       *  Method: void org.apache.roller.weblogger.config.PingConfig()
              */
   110      private PingConfig() {
   111      }
   112  
   113      /**
   114       * Get the maximum number of ping attempts that should be made for each ping queue entry before we give up. If we
   115       * get apparently transient failures while trying to perform the ping, the entry is requeued for processing on later
   116       * passes through the queue until this number of attempts has been reached.
   117       *
   118       * @return the configured (or default) maximum number of ping attempts
   119       */
   120      public static int getMaxPingAttempts() {
                 /* 
    P/P           *  Method: int getMaxPingAttempts()
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   121          return getIntegerProperty(MAX_PING_ATTEMPTS_PROP, MAX_PING_ATTEMPTS_DEFAULT, MAX_PING_ATTEMPTS_MIN, MAX_PING_ATTEMPTS_MAX);
   122      }
   123  
   124      /**
   125       * Get the ping queue processing interval in minutes.
   126       *
   127       * @return the configured (or default) queue processing interval in minutes.
   128       */
   129      public static int getQueueProcessingIntervalMins() {
                 /* 
    P/P           *  Method: int getQueueProcessingIntervalMins()
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   130          return getIntegerProperty(QUEUE_PROCESSING_INTERVAL_PROP, QUEUE_PROCESSING_INTERVAL_DEFAULT, QUEUE_PROCESSING_INTERVAL_MIN, QUEUE_PROCESSING_INTERVAL_MAX);
   131      }
   132  
   133  
   134      /**
   135       * Get the logs only setting.  Get configuration value determining whether pings are to be logged only (not sent).
   136       * This configuration setting is used for development and debugging.
   137       *
   138       * @return the configured (or default) value of the logs only setting.
   139       */
   140      public static boolean getLogPingsOnly() {
                 /* 
    P/P           *  Method: bool getLogPingsOnly()
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   141          return getBooleanProperty(PINGS_LOG_ONLY_PROP, PINGS_LOG_ONLY_DEFAULT);
   142      }
   143  
   144      /**
   145       * Determine whether the configuration disallows custom ping targets.  If this is true, users are not allowed to
   146       * create or edit custom ping targets, and any auto ping configs that use them are ignored.
   147       *
   148       * @return the configured (or default) value of the "disallow custom targets" setting.
   149       */
   150      public static boolean getDisallowCustomTargets() {
                 /* 
    P/P           *  Method: bool getDisallowCustomTargets()
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   151          return getBooleanProperty(PINGS_DISALLOW_CUSTOM_TARGETS_PROP, PINGS_DISALLOW_CUSTOM_TARGETS_DEFAULT);
   152      }
   153  
   154      /**
   155       * Determine whether the configuration disables ping usage (configuration of auto pings and sending of manual
   156       * pings).  If this is true, all auto ping configus are removed at startup, the Weblog:Pings UI and the associated
   157       * actions are disabled.
   158       *
   159       * @return the configured (or default) value of the enable ping usage setting.
   160       */
   161      public static boolean getDisablePingUsage() {
                 /* 
    P/P           *  Method: bool getDisablePingUsage()
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   162          return getBooleanProperty(PINGS_DISABLE_PING_USAGE_PROP, PINGS_DISABLE_PING_USAGE_DEFAULT);
   163      }
   164  
   165      /**
   166       * Determine whether ping processing is suspended.  If this is true, new auto ping requests are not
   167       * queued, any existing queued requests are not processed, and sending a manual ping results in a message saying
   168       * pings have been disabled.
   169       *
   170       * @return the configured (or default) value of the suspend ping processing setting.
   171       */
   172      public static boolean getSuspendPingProcessing() {
                 /* 
    P/P           *  Method: bool getSuspendPingProcessing()
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerRuntimeConfig.log != null
                  *    (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider != null
                  *    (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider.webloggerInstance != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   173          return WebloggerRuntimeConfig.getBooleanProperty(PINGS_SUSPEND_PING_PROCESSING_PROP);
   174      }
   175  
   176      /**
   177       * Initialize the common ping targets from the configuration properties. If the current list of common ping targets
   178       * is empty, and the <code>PINGS_INITIAL_COMMON_TARGETS_PROP</code> property is present in the configuration then,
   179       * this method will use that value to initialize the common targets.  This is called on each server startup.
   180       * <p/>
   181       * Note: this is expected to be called during initialization  with transaction demarcation being handled by the
   182       * caller.
   183       *
   184       * @see org.apache.roller.weblogger.ui.core.RollerContext#contextInitialized(javax.servlet.ServletContextEvent)
   185       */
   186      public static void initializeCommonTargets() throws WebloggerException {
                 /* 
    P/P           *  Method: void initializeCommonTargets()
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  *    (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider != null
                  *    (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider.webloggerInstance != null
                  * 
                  *  Presumptions:
                  *    getWeblogger(...).pingTargetManager != null
                  *    getWeblogger(...)@194 init'ed
                  *    javax.persistence.Query:getResultList(...)@177 != null
                  *    org.apache.commons.logging.LogFactory:getLog(...)@44 != null
                  *    pingTargetMgr.strategy != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    java.lang.String:length(...)@188: {1..232-1}, {0}
                  *    java.util.List:isEmpty(...)@195: {1}, {0}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@189: {0}, {1}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@196: {0}, {1}
                  */
   187          String configuredVal = WebloggerConfig.getProperty(PINGS_INITIAL_COMMON_TARGETS_PROP);
   188          if (configuredVal == null || configuredVal.trim().length() == 0) {
   189              if (logger.isDebugEnabled()) {
   190                  logger.debug("No (or empty) value of " + PINGS_INITIAL_COMMON_TARGETS_PROP + " present in the configuration.  Skipping initialization of commmon targets.");
   191              }
   192              return;
   193          }
   194          PingTargetManager pingTargetMgr = WebloggerFactory.getWeblogger().getPingTargetManager();
   195          if (!pingTargetMgr.getCommonPingTargets().isEmpty()) {
   196              if (logger.isDebugEnabled()) {
   197                  logger.debug("Some common ping targets are present in the database already.  Skipping initialization.");
   198              }
   199              return;
   200          }
   201  
   202          String[] configuredTargets = configuredVal.trim().split(",");
+  203          for (int i = 0; i < configuredTargets.length; i++) {
   204              // Trim space around the target spec
+  205              String thisTarget = configuredTargets[i].trim();
   206              // skip empty ones
   207              if (thisTarget.length() == 0) continue;
   208              // parse the ith target and store it
   209              Matcher m = NESTED_BRACE_PAIR.matcher(thisTarget);
   210              if (m.matches() && m.groupCount() == 2) {
   211                  String name = m.group(1).trim();
   212                  String url = m.group(2).trim();
   213                  logger.info("Creating common ping target '" + name + "' from configuration properties.");
   214                  PingTarget pingTarget = new PingTarget(null, name, url, null, false);
   215                  pingTargetMgr.savePingTarget(pingTarget);
   216              } else {
   217                  logger.error("Unable to parse configured initial ping target '" + thisTarget + "'. Skipping this target. Check your setting of the property " + PINGS_INITIAL_COMMON_TARGETS_PROP);
   218              }
   219          }
   220      }
   221  
   222      /**
   223       * Initialize known ping variants from the configuration.
   224       */
   225      public static void initializePingVariants() {
                 /* 
    P/P           *  Method: void initializePingVariants()
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  * 
                  *  Presumptions:
                  *    org.apache.commons.logging.LogFactory:getLog(...)@44 != null
                  * 
                  *  Test Vectors:
                  *    java.lang.String:length(...)@227: {1..232-1}, {0}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@228: {0}, {1}
                  */
   226          String configuredVal = WebloggerConfig.getProperty(PINGS_VARIANT_OPTIONS_PROP);
   227          if (configuredVal == null || configuredVal.trim().length() == 0) {
   228              if (logger.isDebugEnabled()) {
   229                  logger.debug("No (or empty) value of " + PINGS_VARIANT_OPTIONS_PROP + " present in the configuration.  Skipping initialization of ping variants.");
   230              }
   231              return;
   232          }
   233          String[] variants = configuredVal.trim().split(",");
+  234          for (int i = 0; i < variants.length; i++) {
+  235              String thisVariant = variants[i].trim();
   236              if (thisVariant.length() == 0) continue;
   237              Matcher m = NESTED_BRACE_PAIR.matcher(thisVariant);
   238              if (m.matches() && m.groupCount() == 2) {
   239                  String url = m.group(1).trim();
   240                  String optionsList = m.group(2).trim();
   241                  Set variantOptions = new HashSet();
   242                  String[] options = optionsList.split(",");
   243                  for (int j = 0; j < options.length; j++) {
   244                      String option = options[j].trim().toLowerCase();
   245                      if (option.length() > 0) {
   246                          variantOptions.add(option);
   247                      }
   248                  }
   249                  if (!variantOptions.isEmpty()) {
   250                      configuredVariants.put(url, variantOptions);
   251                  } else {
   252                      logger.warn("Ping variant entry for url '" + url + "' has an empty variant options list.  Ignored.");
   253                  }
   254              } else {
   255                  logger.error("Unable to parse configured ping variant '" + thisVariant + "'. Skipping this variant. Check your setting of the property " + PINGS_VARIANT_OPTIONS_PROP);
   256              }
   257          }
   258      }
   259  
   260      /**
   261       * Get the set of variant options configured for the given ping target url.
   262       *
   263       * @param pingTargetUrl
   264       * @return the set of variant options configured for the given ping target url, or
   265       *         the empty set if there are no variants configured.
   266       */
   267      public static Set getVariantOptions(String pingTargetUrl) {
                 /* 
    P/P           *  Method: Set getVariantOptions(String)
                  * 
                  *  Presumptions:
                  *    init'ed(java.util.Collections.EMPTY_SET)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    java.util.Map:get(...)@268: Inverse{null}, Addr_Set{null}
                  */
   268          Set variantOptions = (Set) configuredVariants.get(pingTargetUrl);
   269          if (variantOptions == null) {
   270              variantOptions = Collections.EMPTY_SET;
   271          }
   272          return variantOptions;
   273      }
   274  
   275  
   276      // TODO: Refactor functionality below to WebloggerConfig?
   277  
   278      /**
   279       * Get the value of an integer configuration property.
   280       *
   281       * @param propName     the property name
   282       * @param defaultValue the default value if the property is not present
   283       * @param min          the minimum allowed value
   284       * @param max          the maximum allowed value
   285       * @return the value as an integer; the default value if no configured value is present or if the configured value
   286       *         is out of the specified range.
   287       */
   288      private static int getIntegerProperty(String propName, int defaultValue, int min, int max) {
                 /* 
    P/P           *  Method: int getIntegerProperty(String, int, int, int)
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  * 
                  *  Presumptions:
                  *    org.apache.commons.logging.LogFactory:getLog(...)@44 != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@291: {0}, {1}
                  */
   289          String configuredVal = WebloggerConfig.getProperty(propName);
   290          if (configuredVal == null) {
   291              if (logger.isDebugEnabled()) {
   292                  logger.debug("PingConfig property '" + propName + "' is not present in the configuration.  Using default value: " + defaultValue);
   293              }
   294              return defaultValue;
   295          }
   296  
   297          int val;
   298          try {
   299              val = Integer.parseInt(configuredVal);
   300          } catch (NumberFormatException ex) {
   301              logger.error("ERROR: PingConfig property '" + propName + "' is not an integer value.  Using default value: " + defaultValue);
   302              return defaultValue;
   303          }
   304  
   305          if (val < min || val > max) {
   306              logger.error("ERROR: PingConfig property '" + propName + "' is outside the required range (" + min + ", " + max + ").  Using default value: " + defaultValue);
   307              return defaultValue;
   308          }
   309  
   310          return val;
   311      }
   312  
   313      /**
   314       * Get the value of a boolean property with specified default.
   315       *
   316       * @param propName     the property name
   317       * @param defaultValue the default value if the property is not present
   318       * @return the configured value or the default if it the configured value is not present.
   319       */
   320      private static boolean getBooleanProperty(String propName, boolean defaultValue) {
                 /* 
    P/P           *  Method: bool getBooleanProperty(String, bool)
                  * 
                  *  Preconditions:
                  *    org/apache/roller/weblogger/config/WebloggerConfig.config != null
                  *    org/apache/roller/weblogger/config/WebloggerConfig.log != null
                  * 
                  *  Presumptions:
                  *    java.lang.Boolean:valueOf(...)@328 != null
                  *    org.apache.commons.logging.LogFactory:getLog(...)@44 != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@323: {0}, {1}
                  */
   321          String configuredVal = WebloggerConfig.getProperty(propName);
   322          if (configuredVal == null) {
   323              if (logger.isDebugEnabled()) {
   324                  logger.debug("PingConfig property '" + propName + "' is not present in the configuration.  Using default value: " + defaultValue);
   325              }
   326              return defaultValue;
   327          }
   328          return Boolean.valueOf(configuredVal).booleanValue();
   329      }
   330  
   331  
   332  }








SofCheck Inspector Build Version : 2.18479
PingConfig.java 2009-Jan-02 14:25:00
PingConfig.class 2009-Sep-04 03:12:32