Coverage report

  %line %branch
org.apache.turbine.services.BaseInitableBroker
0% 
0% 

 1  
 package org.apache.turbine.services;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License")
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import java.util.Hashtable;
 20  
 import java.util.Stack;
 21  
 
 22  
 import org.apache.commons.logging.Log;
 23  
 import org.apache.commons.logging.LogFactory;
 24  
 
 25  
 /**
 26  
  * A generic implementation of <code>InitableBroker</code>.
 27  
  * Functionality provided by the broker includes:
 28  
  *
 29  
  * <ul>
 30  
  *
 31  
  * <li>Maintaining single instance of each <code>Initable</code> in
 32  
  * the system.</li>
 33  
  *
 34  
  * <li>Early initialization of <code>Initables</code> during system
 35  
  * startup.</li>
 36  
  *
 37  
  * <li>Late initialization of <code>Initables</code> before they are
 38  
  * used.</li>
 39  
  *
 40  
  * <li>Providing instances of <code>Initables</code> to requesting
 41  
  * parties.</li>
 42  
  *
 43  
  * <li>Maintaining dependencies between <code>Initables</code> during
 44  
  * early initalization phases, including circular dependencies
 45  
  * detection.</li>
 46  
  *
 47  
  * </ul>
 48  
  *
 49  
  * @author <a href="mailto:burton@apache.org">Kevin Burton</a>
 50  
  * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a>
 51  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 52  
  * @version $Id: BaseInitableBroker.java 264148 2005-08-29 14:21:04Z henning $
 53  
  */
 54  
 public abstract class BaseInitableBroker
 55  
         implements InitableBroker
 56  
 {
 57  
     /** A repository of Initable instances. */
 58  0
     protected Hashtable initables = new Hashtable();
 59  
 
 60  
     /**
 61  
      * Names of classes being early-initialized are pushed onto this
 62  
      * stack.  A name appearing twice indicates a circular dependency
 63  
      * chain.
 64  
      */
 65  0
     protected Stack stack = new Stack();
 66  
 
 67  
     /** Logging */
 68  0
     private Log log = LogFactory.getLog(this.getClass());
 69  
 
 70  
     /**
 71  
      * Default constructor of InitableBroker.
 72  
      *
 73  
      * This constructor does nothing. Your brokers should be
 74  
      * singletons, therefore their constructors should be
 75  
      * private. They should also have public YourBroker getInstance()
 76  
      * methods.
 77  
      */
 78  
     protected BaseInitableBroker()
 79  0
     {
 80  0
     }
 81  
 
 82  
     /**
 83  
      * Performs early initialization of an Initable class.
 84  
      *
 85  
      * @param className The name of the class to be initialized.
 86  
      * @param data An Object to be used for initialization activities.
 87  
      * @exception InitializationException Initialization was not successful.
 88  
      */
 89  
     public void initClass(String className, Object data)
 90  
             throws InitializationException
 91  
     {
 92  
         // make sure that only one thread calls this method recursively
 93  0
         synchronized (stack)
 94  
         {
 95  0
             int pos = stack.search(className);
 96  0
             if (pos != -1)
 97  
             {
 98  0
                 StringBuffer msg = new StringBuffer().append(className)
 99  
                         .append(" couldn't be initialized because of circular depency chain:\n");
 100  0
                 for (int i = pos; i > 0; i--)
 101  
                 {
 102  0
                     msg.append((String) stack.elementAt(stack.size() - i - 1) + "->");
 103  
                 }
 104  0
                 msg.append(className).append('\n');
 105  
 
 106  0
                 throw new InitializationException(msg.toString());
 107  
             }
 108  
             try
 109  
             {
 110  0
                 stack.push(className);
 111  0
                 Initable instance = getInitableInstance(className);
 112  0
                 if (!instance.getInit())
 113  
                 {
 114  
                     // this call might result in an indirect recursion
 115  0
                     instance.init(data);
 116  
                 }
 117  
             }
 118  
             finally
 119  
             {
 120  
                 // Succeeded or not, make sure the name gets off the stack.
 121  0
                 stack.pop();
 122  0
             }
 123  0
         }
 124  0
     }
 125  
 
 126  
     /**
 127  
      * Shuts down an <code>Initable</code>.
 128  
      *
 129  
      * This method is used to release resources allocated by an
 130  
      * <code>Initable</code>, and return it to its initial (uninitailized)
 131  
      * state.
 132  
      *
 133  
      * @param className The name of the class to be uninitialized.
 134  
      */
 135  
     public void shutdownClass(String className)
 136  
     {
 137  
         try
 138  
         {
 139  0
             Initable initable = getInitableInstance(className);
 140  0
             if (initable.getInit())
 141  
             {
 142  0
                 initable.shutdown();
 143  0
                 ((BaseInitable) initable).setInit(false);
 144  
             }
 145  
         }
 146  0
         catch (InstantiationException e)
 147  
         {
 148  
             // Shutdown of a nonexistent class was requested.
 149  
             // This does not hurt anything, so we log the error and continue.
 150  0
             log.error("Shutdown of a nonexistent class " +
 151  
                     className + " was requested", e);
 152  0
         }
 153  0
     }
 154  
 
 155  
     /**
 156  
      * Provides an instance of Initable class ready to work.
 157  
      *
 158  
      * If the requested class couldn't be instatiated or initialized,
 159  
      * an InstantiationException will be thrown. You needn't handle
 160  
      * this exception in your code, since it indicates fatal
 161  
      * misconfigurtion of the system.
 162  
      *
 163  
      * @param className The name of the Initable requested.
 164  
      * @return An instance of the requested Initable.
 165  
      * @exception InstantiationException if there was a problem
 166  
      * during instantiation or initialization of the Initable.
 167  
      */
 168  
     public Initable getInitable(String className)
 169  
             throws InstantiationException
 170  
     {
 171  
         Initable initable;
 172  
         try
 173  
         {
 174  0
             initable = getInitableInstance(className);
 175  0
             if (!initable.getInit())
 176  
             {
 177  0
                 synchronized (initable.getClass())
 178  
                 {
 179  0
                     if (!initable.getInit())
 180  
                     {
 181  0
                         initable.init();
 182  
                     }
 183  0
                     if (!initable.getInit())
 184  
                     {
 185  
                         // this exception will be caught & rethrown by this
 186  
                         // very method. getInit() returning false indicates
 187  
                         // some initialization issue, which in turn prevents
 188  
                         // the InitableBroker from passing a working
 189  
                         // instance of the initable to the client.
 190  0
                         throw new InitializationException(
 191  
                                 "init() failed to initialize class "
 192  
                                 + className);
 193  
                     }
 194  0
                 }
 195  
             }
 196  0
             return initable;
 197  
         }
 198  0
         catch (InitializationException e)
 199  
         {
 200  0
             throw new InstantiationException("Class " + className +
 201  
                     " failed to initialize", e);
 202  
         }
 203  
     }
 204  
 
 205  
     /**
 206  
      * Retrieves an instance of an Initable from the repository.
 207  
      *
 208  
      * If the requested class is not present in the repository, it is
 209  
      * instantiated and passed a reference to the broker, saved and
 210  
      * then returned.
 211  
      *
 212  
      * @param className The name of the class to be instantiated.
 213  
      * @exception InstantiationException if the requested class can't
 214  
      * be instantiated.
 215  
      */
 216  
     protected Initable getInitableInstance(String className)
 217  
             throws InstantiationException
 218  
     {
 219  0
         Initable initable = (Initable) initables.get(className);
 220  
 
 221  0
         if (initable == null)
 222  
         {
 223  
             try
 224  
             {
 225  0
                 initable = (Initable) Class.forName(className).newInstance();
 226  
             }
 227  
 
 228  
                     // those two errors must be passed to the VM
 229  0
             catch (ThreadDeath t)
 230  
             {
 231  0
                 throw t;
 232  
             }
 233  0
             catch (OutOfMemoryError t)
 234  
             {
 235  0
                 throw t;
 236  
             }
 237  
 
 238  0
             catch (Throwable t)
 239  
             {
 240  
                 // Used to indicate error condition.
 241  0
                 String msg = null;
 242  
 
 243  0
                 if (t instanceof NoClassDefFoundError)
 244  
                 {
 245  0
                     msg = "A class referenced by " + className +
 246  
                             " is unavailable. Check your jars and classes.";
 247  
                 }
 248  0
                 else if (t instanceof ClassNotFoundException)
 249  
                 {
 250  0
                     msg = "Class " + className +
 251  
                             " is unavailable. Check your jars and classes.";
 252  
                 }
 253  0
                 else if (t instanceof ClassCastException)
 254  
                 {
 255  0
                     msg = "Class " + className +
 256  
                             " doesn't implement Initable.";
 257  
                 }
 258  
                 else
 259  
                 {
 260  0
                     msg = "Failed to instantiate " + className;
 261  
                 }
 262  
 
 263  0
                 throw new InstantiationException(msg, t);
 264  0
             }
 265  
 
 266  0
             initable.setInitableBroker(this);
 267  0
             initables.put(className, initable);
 268  
         }
 269  
 
 270  0
         return initable;
 271  
     }
 272  
 
 273  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.