View Javadoc
1 package org.apache.turbine.services; 2 3 /* ==================================================================== 4 * The Apache Software License, Version 1.1 5 * 6 * Copyright (c) 2001 The Apache Software Foundation. All rights 7 * reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The end-user documentation included with the redistribution, 22 * if any, must include the following acknowledgment: 23 * "This product includes software developed by the 24 * Apache Software Foundation (http://www.apache.org/)." 25 * Alternately, this acknowledgment may appear in the software itself, 26 * if and wherever such third-party acknowledgments normally appear. 27 * 28 * 4. The names "Apache" and "Apache Software Foundation" and 29 * "Apache Turbine" must not be used to endorse or promote products 30 * derived from this software without prior written permission. For 31 * written permission, please contact apache@apache.org. 32 * 33 * 5. Products derived from this software may not be called "Apache", 34 * "Apache Turbine", nor may "Apache" appear in their name, without 35 * prior written permission of the Apache Software Foundation. 36 * 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This software consists of voluntary contributions made by many 52 * individuals on behalf of the Apache Software Foundation. For more 53 * information on the Apache Software Foundation, please see 54 * <http://www.apache.org/>;. 55 */ 56 57 import java.io.PrintWriter; 58 import java.io.StringWriter; 59 import java.util.Iterator; 60 import java.util.Properties; 61 import java.util.Vector; 62 import javax.servlet.ServletConfig; 63 import org.apache.commons.configuration.Configuration; 64 import org.apache.turbine.services.logging.LoggingService; 65 import org.apache.turbine.services.resources.ResourceService; 66 import org.apache.turbine.services.resources.TurbineResources; 67 68 69 /*** 70 * This is a singleton utility class that acts as a Services broker. 71 * 72 * @author <a href="mailto:greg@shwoop.com">Greg Ritter</a> 73 * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a> 74 * @author <a href="mailto:burton@apache.org">Kevin Burton</a> 75 * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a> 76 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> 77 * @version $Id: TurbineServices.java,v 1.5 2002/07/11 16:53:28 mpoeschl Exp $ 78 */ 79 public class TurbineServices 80 extends BaseServiceBroker 81 { 82 /*** 83 * Servlet initialization parameter name for defining the resources 84 * service implementation to use (<code>resources</code>). 85 */ 86 public final static String RESOURCES_CLASS_KEY = "resources"; 87 88 /*** 89 * Default resources service implementation to use when none explicitly 90 * specified (<code> 91 * org.apache.turbine.services.resources.TurbineResourceService</code>) 92 */ 93 public final static String RESOURCES_CLASS_DEFAULT = 94 "org.apache.turbine.services.resources.TurbineResourceService"; 95 96 /*** Default bootstrap logger implementation */ 97 public final static String LOGGING_CLASS_DEFAULT = 98 "org.apache.turbine.services.logging.TurbineLoggingService"; 99 100 /*** 101 * Servlet initialization parameter name for defining the logging 102 * service implementation to use. 103 */ 104 public final static String LOGGING_CLASS_KEY="logging"; 105 106 /*** 107 * Servlet initialization parameter name for the path to 108 * TurbineResources.properties file used by 109 * {@link org.apache.turbine.services.resources.TurbineResourceService} 110 * (<code>properties</code>). 111 */ 112 public static final String PROPERTIES_PATH_KEY = "properties"; 113 114 /*** 115 * Default value of TurbineResources.properties file path 116 * (<code>/WEB-INF/conf/TurbineResources.properties</code>). 117 */ 118 public static final String PROPERTIES_PATH_DEFAULT = 119 "/WEB-INF/conf/TurbineResources.properties"; 120 121 /*** 122 * A prefix for <code>Service</code> properties in 123 * TurbineResource.properties. 124 */ 125 public static final String SERVICE_PREFIX = "services."; 126 127 /*** 128 * A <code>Service</code> property determining its implementing 129 * class name . 130 */ 131 public static final String CLASSNAME_SUFFIX = ".classname"; 132 133 /*** The single instance of this class. */ 134 protected static ServiceBroker instance = new TurbineServices(); 135 136 /*** True if logging should go throught LoggingService, false if not. */ 137 private boolean enabledLogging = false; 138 139 /*** caches log messages before logging is enabled */ 140 private Vector logCache = new Vector(5); 141 142 /*** the logger */ 143 private LoggingService logger; 144 145 /*** 146 * This constructor is protected to force clients to use 147 * getInstance() to access this class. 148 */ 149 protected TurbineServices() 150 { 151 super(); 152 } 153 154 /*** 155 * The method through which this class is accessed. 156 * 157 * @return The single instance of this class. 158 */ 159 public static ServiceBroker getInstance() 160 { 161 return instance; 162 } 163 164 /*** 165 * Initialize the primary services (Logging and Resources). 166 */ 167 public void initPrimaryServices(ServletConfig config) 168 throws InstantiationException, InitializationException 169 { 170 // Resource service must start as the very first 171 String resourcesClass = config.getInitParameter(RESOURCES_CLASS_KEY); 172 173 try 174 { 175 if (resourcesClass == null) 176 { 177 resourcesClass = RESOURCES_CLASS_DEFAULT; 178 } 179 mapping.setProperty(ResourceService.SERVICE_NAME, resourcesClass); 180 initService(ResourceService.SERVICE_NAME, config); 181 182 // Now logging can be initialized 183 String loggingClass = config.getInitParameter(LOGGING_CLASS_KEY); 184 if (loggingClass == null) 185 { 186 loggingClass = LOGGING_CLASS_DEFAULT; 187 } 188 mapping.setProperty(LoggingService.SERVICE_NAME, loggingClass); 189 try 190 { 191 initService(LoggingService.SERVICE_NAME, config); 192 logger = getLogger(); 193 } 194 catch (InitializationException e) 195 { 196 mapping.clearProperty(LoggingService.SERVICE_NAME); 197 throw e; 198 } 199 catch (InstantiationException e) 200 { 201 mapping.clearProperty(LoggingService.SERVICE_NAME); 202 throw e; 203 } 204 } 205 finally 206 { 207 // All further messages will go through LoggingService 208 // if logging service could not be initialized we still want 209 // to enable logging for further messages to go to console 210 enableLogging(); 211 } 212 // Since we have ResourceService running, real mappings of services 213 // may be loaded now 214 initMapping(); 215 } 216 217 /*** 218 * Creates mapping of Service names to class names. 219 * BaseServiceBroker knows no mappings. 220 */ 221 public void initMapping(Configuration mapping) 222 { 223 this.mapping = mapping; 224 } 225 226 /*** 227 * Creates a mapping between Service names and class names. 228 * 229 * The mapping is built according to settings present in 230 * TurbineResources.properties. The entries should have the 231 * following form: 232 * 233 * <pre> 234 * services.MyService.classname=com.mycompany.MyServiceImpl 235 * services.MyOtherService.classname=com.mycompany.MyOtherServiceImpl 236 * </pre> 237 * 238 * <br> 239 * 240 * Generic ServiceBroker provides no Services. 241 */ 242 protected void initMapping() 243 { 244 int pref = SERVICE_PREFIX.length(); 245 int suff = CLASSNAME_SUFFIX.length(); 246 247 /* 248 * These keys returned in an order that corresponds 249 * to the order the services are listed in 250 * the TR.props. 251 * 252 * When the mapping is created we use a Configuration 253 * object to ensure that the we retain the order 254 * in which the order the keys are returned. 255 * 256 * There's no point in retrieving an ordered set 257 * of keys if they aren't kept in order :-) 258 */ 259 Iterator keys = TurbineResources.getKeys(); 260 while(keys.hasNext()) 261 { 262 String key = (String)keys.next(); 263 if (key.startsWith(SERVICE_PREFIX) && key.endsWith(CLASSNAME_SUFFIX)) 264 { 265 String serviceKey = key.substring(pref, key.length() - suff); 266 notice ("Added Mapping for Service: " + serviceKey); 267 268 if (!mapping.containsKey(serviceKey)) 269 mapping.setProperty(serviceKey, TurbineResources.getString(key)); 270 } 271 } 272 } 273 274 /*** 275 * Returns the properites of a specific service. Properties are 276 * retrieved from TurbineResources.properties provided that you 277 * have the following entries: 278 * 279 * <br> 280 * 281 * services.MyService.greeting=Hello\, I'm Jan B. 282 * 283 * <br> 284 * 285 * services.MyService.defaultAction=beep 286 * 287 * <br> 288 * 289 * Service "MyService" will get a set of two properites: 290 * "greeting" = "Hello, I'm Jan B." and "defaultAction" = "beep". 291 * 292 * <p> Note that this way you will receive a 'collapsed' version 293 * of your resources - multiple entries with the same key will 294 * have only one value stored. Use the {@link #getConfiguration} 295 * or {@link #getResources} method to take advantage of the capabilities 296 * of the {@link org.apache.turbine.services.resources.TurbineResources} 297 * class. 298 * 299 * @param name The name of the service. 300 * @return Properties of requested Service. 301 */ 302 public Properties getProperties( String name ) 303 { 304 Properties properties = new Properties(); 305 306 String servicePrefix = SERVICE_PREFIX + name + '.'; 307 Iterator keys = TurbineResources.getKeys(servicePrefix); 308 309 while(keys.hasNext()) 310 { 311 String key = (String)keys.next(); 312 String value; 313 try 314 { 315 value = TurbineResources.getString(key); 316 } 317 catch (ClassCastException propIsArray) 318 { 319 String[] values = TurbineResources.getStringArray(key); 320 value = values[values.length - 1]; 321 } 322 properties.setProperty(key.substring(servicePrefix.length()), 323 value); 324 } 325 326 return properties; 327 } 328 329 /*** 330 * Returns the Configuration for the specified service. 331 * 332 * @param name The name of the service. 333 */ 334 public Configuration getConfiguration( String name ) 335 { 336 return TurbineResources.getConfiguration(SERVICE_PREFIX + name); 337 } 338 339 /*** 340 * Returns the configuration resources of a specific service. 341 * 342 * This method extracts the configuration options of a service 343 * from global Turbine configuration. The interface 344 * {@link org.apache.turbine.services.resources.ResourceService} 345 * offers significant advantages over plain java.util.Properties - 346 * you can request for exaple you can retrieve <code>int</code>s 347 * <code>boolean</code>s, and vectors of <code>String</code>s. 348 * 349 * <p> Note that the proces extracting the configuration might 350 * be time consuming, it might be a good idea to store the 351 * reference returned by this method in an instance variable 352 * of the service.</p> 353 * 354 * @param name The name of the Service. 355 * @return The configuration resources of the Service. 356 */ 357 public ResourceService getResources( String name ) 358 { 359 return TurbineResources.getResources(SERVICE_PREFIX + name); 360 } 361 362 /*** 363 * Output a diagnostic notice. 364 * 365 * This method is used by the service framework classes for producing 366 * tracing mesages that might be useful for debugging. 367 * 368 * <p>Standard Turbine logging facilities are used. 369 * 370 * @param msg the message to print. 371 */ 372 public void notice(String msg) 373 { 374 if (enabledLogging) 375 { 376 if (logger == null) 377 { 378 System.out.println("(!) NOTICE: " + msg); 379 } 380 else 381 { 382 logger.info(msg); 383 } 384 } 385 else 386 { 387 // cache the message to log as soon as logiing is on 388 logCache.add(msg); 389 } 390 } 391 392 /*** 393 * Output an error message. 394 * 395 * This method is used by the service framework classes for displaying 396 * stacktraces of any exceptions that might be caught during processing. 397 * 398 * <p>Standard Turbine logging facilities are used. 399 * 400 * @param msg the message to print. 401 */ 402 public void error(Throwable t) 403 { 404 if (enabledLogging) 405 { 406 if (logger == null) 407 { 408 System.out.println("(!) ERROR: " + t.getMessage()); 409 } 410 else 411 { 412 logger.error("", t); 413 } 414 } 415 else 416 { 417 // cache the message to log as soon as logiing is on 418 logCache.add("ERROR: " + t.getMessage()); 419 StringWriter sw = new StringWriter(); 420 t.printStackTrace(new PrintWriter(sw)); 421 logCache.add(sw.toString()); 422 } 423 424 } 425 426 /*** 427 * Allows logging using a logging service instead of console 428 * This method should be called after initialization of the logging service 429 */ 430 private void enableLogging() 431 { 432 enabledLogging = true; 433 //log all cached log messages 434 for (int i = 0; i < logCache.size(); i++) 435 { 436 String s = (String) logCache.elementAt(i); 437 notice(s); 438 } 439 //dispose of the cache 440 logCache = null; 441 442 notice("ServiceBroker: LoggingService enabled."); 443 444 } 445 446 /*** 447 * Macro to reduce duplicated code and casting. 448 */ 449 private final LoggingService getLogger() 450 { 451 return (LoggingService) getService(LoggingService.SERVICE_NAME); 452 } 453 }

This page was automatically generated by Maven