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.util.Date; 58 import java.util.Hashtable; 59 import java.util.Stack; 60 import org.apache.turbine.util.TurbineException; 61 62 /*** 63 * A generic implementation of <code>InitableBroker</code>. 64 * Functionality provided by the broker includes: 65 * 66 * <ul> 67 * 68 * <li>Maintaining single instance of each <code>Initable</code> in 69 * the system.</li> 70 * 71 * <li>Early initialization of <code>Initables</code> during system 72 * startup.</li> 73 * 74 * <li>Late initialization of <code>Initables</code> before they are 75 * used.</li> 76 * 77 * <li>Providing instances of <code>Initables</code> to requesting 78 * parties.</li> 79 * 80 * <li>Maintaining dependencies between <code>Initables</code> during 81 * early initalization phases, including circular dependencies 82 * detection.</li> 83 * 84 * </ul> 85 * 86 * @author <a href="mailto:burton@apache.org">Kevin Burton</a> 87 * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a> 88 * @version $Id: BaseInitableBroker.java,v 1.2 2002/07/11 16:53:29 mpoeschl Exp $ 89 */ 90 public abstract class BaseInitableBroker 91 implements InitableBroker 92 { 93 /*** A repository of Initable instances. */ 94 protected Hashtable initables = new Hashtable(); 95 96 /*** 97 * Names of classes being early-initialized are pushed onto this 98 * stack. A name appearing twice indicates a circular dependency 99 * chain. 100 */ 101 protected Stack stack = new Stack(); 102 103 /*** 104 * Default constructor of InitableBorker. 105 * 106 * This constructor does nothing. Your brokers should be 107 * singletons, therefore their constructors should be 108 * private. They should also have public YourBroker getInstance() 109 * methods. 110 */ 111 protected BaseInitableBroker() 112 { 113 } 114 115 /*** 116 * Performs early initialization of an Initable class. 117 * 118 * @param className The name of the class to be initailized. 119 * @param data An Object to be used for initialization activities. 120 * @exception InitializationException Initialization was not successful. 121 */ 122 public void initClass( String className, 123 Object data ) 124 throws InitializationException 125 { 126 // make sure that only one thread calls this method recursively 127 synchronized(stack) 128 { 129 int pos = stack.search(className); 130 if(pos != -1) 131 { 132 StringBuffer msg = new StringBuffer().append(className) 133 .append(" couldn't be initialized because of circular depency chain:\n"); 134 for(int i=pos; i>0; i--) 135 { 136 msg.append((String)stack.elementAt(stack.size()-i-1)+"->"); 137 } 138 msg.append(className).append('\n'); 139 140 throw new InitializationException(msg.toString()); 141 } 142 try 143 { 144 stack.push(className); 145 Initable instance = getInitableInstance(className); 146 if(!instance.getInit()) 147 { 148 // this call might result in an indirect recursion 149 instance.init(data); 150 } 151 } 152 finally 153 { 154 // Succeeded or not, make sure the name gets off the stack. 155 stack.pop(); 156 } 157 } 158 } 159 160 /*** 161 * Shuts down an <code>Initable</code>. 162 * 163 * This method is used to release resources allocated by an 164 * <code>Initable</code>, and return it to its initial (uninitailized) 165 * state. 166 * 167 * @param className The name of the class to be uninitialized. 168 */ 169 public void shutdownClass( String className ) 170 { 171 try 172 { 173 Initable initable = getInitableInstance(className); 174 if(initable.getInit()) 175 { 176 initable.shutdown(); 177 ((BaseInitable)initable).setInit(false); 178 } 179 } 180 catch( InstantiationException e ) 181 { 182 // Shutdown of a nonexistent class was requested. 183 // This does not hurt anything, so we log the error and continue. 184 error(new TurbineException("Shutdown of a nonexistent class " + 185 className + " was requested", e)); 186 } 187 } 188 189 /*** 190 * Provides an instance of Initable class ready to work. 191 * 192 * If the requested class couldn't be instatiated or initialized, 193 * an InstantiationException will be thrown. You needn't handle 194 * this exception in your code, since it indicates fatal 195 * misconfigurtion of the system. 196 * 197 * @param className The name of the Initable requested. 198 * @return An instance of the requested Initable. 199 * @exception InstantiationException, if there was a problem 200 * during instantiation or initialization of the Initable. 201 */ 202 public Initable getInitable( String className ) 203 throws InstantiationException 204 { 205 Initable initable; 206 try 207 { 208 initable = getInitableInstance(className); 209 if(!initable.getInit()) 210 { 211 synchronized(initable.getClass()) 212 { 213 if(!initable.getInit()) 214 { 215 initable.init(); 216 } 217 if(!initable.getInit()) 218 { 219 // this exception will be caught & rethrown by this very method. 220 // getInit() returning false indicates some initialization issue, 221 // which in turn prevents the InitableBroker from passing a working 222 // instance of the initable to the client. 223 throw new InitializationException( 224 "init() failed to initialize class " + className); 225 } 226 } 227 } 228 return initable; 229 } 230 catch( InitializationException e ) 231 { 232 throw new InstantiationException("Class " + className + 233 " failed to initialize", e); 234 } 235 } 236 237 /*** 238 * Retrieves an instance of an Initable from the repository. 239 * 240 * If the requested class is not present in the repository, it is 241 * instantiated and passed a reference to the broker, saved and 242 * then returned. 243 * 244 * @param className The name of the class to be instantiated. 245 * @exception InstantiationException, if the requested class can't 246 * be instantiated. 247 */ 248 protected Initable getInitableInstance( String className ) 249 throws InstantiationException 250 { 251 Initable initable = (Initable)initables.get(className); 252 253 if(initable == null) 254 { 255 try 256 { 257 initable = (Initable)Class.forName(className).newInstance(); 258 } 259 260 // those two errors must be passed to the VM 261 catch( ThreadDeath t ) 262 { 263 throw t; 264 } 265 catch( OutOfMemoryError t ) 266 { 267 throw t; 268 } 269 270 catch( Throwable t ) 271 { 272 // Used to indicate error condition. 273 String msg = null; 274 275 if(t instanceof NoClassDefFoundError) 276 { 277 msg = "A class referenced by " + className + 278 " is unavailable. Check your jars and classes."; 279 } 280 else if(t instanceof ClassNotFoundException) 281 { 282 msg = "Class " + className + 283 " is unavailable. Check your jars and classes."; 284 } 285 else if(t instanceof ClassCastException) 286 { 287 msg = "Class " + className + 288 " doesn't implement Initable."; 289 } 290 else 291 { 292 msg = "Failed to instantiate " + className; 293 } 294 295 throw new InstantiationException(msg, t); 296 } 297 298 initable.setInitableBroker(this); 299 initables.put(className, initable); 300 } 301 302 return initable; 303 } 304 305 /*** 306 * Output a diagnostic notice. 307 * 308 * This method is used by the service framework classes for producing 309 * tracing mesages that might be useful for debugging (newline terminated). 310 * 311 * <p>The default implementation uses system error stream. When writing 312 * your own, remeber to direct that message to the proper logging 313 * mechanism. 314 * 315 * @param msg the message to print. 316 */ 317 public void notice(String msg) 318 { 319 System.err.println('[' + new Date().toString() + "] " + msg); 320 } 321 322 /*** 323 * Output an error message. 324 * 325 * This method is used by the service framework classes for displaying 326 * stacktraces of any exceptions that might be caught during processing. 327 * 328 * <p>The default implementation uses system error stream. When writing 329 * your own, remeber to direct that message to the proper logging 330 * mechanism. 331 * 332 * @param msg the message to print. 333 */ 334 public void error(Throwable t) 335 { 336 t.printStackTrace(System.err); 337 } 338 }

This page was automatically generated by Maven