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 |