Coverage Report - org.apache.turbine.services.assemblerbroker.TurbineAssemblerBrokerService
 
Classes in this File Line Coverage Branch Coverage Complexity
TurbineAssemblerBrokerService
81%
60/74
75%
27/36
5,667
 
 1  
 package org.apache.turbine.services.assemblerbroker;
 2  
 
 3  
 
 4  
 /*
 5  
  * Licensed to the Apache Software Foundation (ASF) under one
 6  
  * or more contributor license agreements.  See the NOTICE file
 7  
  * distributed with this work for additional information
 8  
  * regarding copyright ownership.  The ASF licenses this file
 9  
  * to you under the Apache License, Version 2.0 (the
 10  
  * "License"); you may not use this file except in compliance
 11  
  * with the License.  You may obtain a copy of the License at
 12  
  *
 13  
  *   http://www.apache.org/licenses/LICENSE-2.0
 14  
  *
 15  
  * Unless required by applicable law or agreed to in writing,
 16  
  * software distributed under the License is distributed on an
 17  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 18  
  * KIND, either express or implied.  See the License for the
 19  
  * specific language governing permissions and limitations
 20  
  * under the License.
 21  
  */
 22  
 
 23  
 
 24  
 import java.util.HashMap;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 import java.util.Map;
 28  
 import java.util.Vector;
 29  
 
 30  
 import org.apache.commons.collections.map.LRUMap;
 31  
 import org.apache.commons.configuration.Configuration;
 32  
 import org.apache.commons.logging.Log;
 33  
 import org.apache.commons.logging.LogFactory;
 34  
 import org.apache.turbine.Turbine;
 35  
 import org.apache.turbine.TurbineConstants;
 36  
 import org.apache.turbine.modules.Assembler;
 37  
 import org.apache.turbine.modules.Loader;
 38  
 import org.apache.turbine.services.InitializationException;
 39  
 import org.apache.turbine.services.TurbineBaseService;
 40  
 import org.apache.turbine.services.assemblerbroker.util.AssemblerFactory;
 41  
 import org.apache.turbine.util.TurbineException;
 42  
 
 43  
 /**
 44  
  * TurbineAssemblerBrokerService allows assemblers (like screens,
 45  
  * actions and layouts) to be loaded from one or more AssemblerFactory
 46  
  * classes.  AssemblerFactory classes are registered with this broker
 47  
  * by adding them to the TurbineResources.properties file.
 48  
  *
 49  
  * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
 50  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 51  
  * @version $Id: TurbineAssemblerBrokerService.java 1078552 2011-03-06 19:58:46Z tv $
 52  
  */
 53  58
 public class TurbineAssemblerBrokerService
 54  
         extends TurbineBaseService
 55  
         implements AssemblerBrokerService
 56  
 {
 57  
     /** Logging */
 58  58
     private static Log log
 59  
             = LogFactory.getLog(TurbineAssemblerBrokerService.class);
 60  
 
 61  
     /** A structure that holds the registered AssemblerFactories */
 62  58
     private Map<String, List<AssemblerFactory>> factories = null;
 63  
 
 64  
     /** A cache that holds the generated Assemblers */
 65  58
     private Map<String, Assembler> assemblerCache = null;
 66  
 
 67  
     /** A cache that holds the Loaders */
 68  58
     private Map<String, Loader> loaderCache = null;
 69  
 
 70  
     /** Caching on/off */
 71  
     private boolean isCaching;
 72  
 
 73  
     /**
 74  
      * Get a list of AssemblerFactories of a certain type
 75  
      *
 76  
      * @param type type of Assembler
 77  
      * @return list of AssemblerFactories
 78  
      */
 79  
     private List<AssemblerFactory> getFactoryGroup(String type)
 80  
     {
 81  1672
         if (!factories.containsKey(type))
 82  
         {
 83  564
             factories.put(type, new Vector<AssemblerFactory>());
 84  
         }
 85  1672
         return factories.get(type);
 86  
     }
 87  
 
 88  
     /**
 89  
      * Utiltiy method to register all factories for a given type.
 90  
      *
 91  
      * @param type type of Assembler
 92  
      * @throws TurbineException
 93  
      */
 94  
     private void registerFactories(String type)
 95  
         throws TurbineException
 96  
     {
 97  564
         List names = getConfiguration().getList(type);
 98  
 
 99  564
         log.info("Registering " + names.size() + " " + type + " factories.");
 100  
 
 101  564
         for (Iterator it = names.iterator(); it.hasNext(); )
 102  
         {
 103  564
             String factory = (String) it.next();
 104  
             try
 105  
             {
 106  564
                 Object o = Class.forName(factory).newInstance();
 107  564
                 registerFactory(type, (AssemblerFactory) o);
 108  
             }
 109  
             // these must be passed to the VM
 110  0
             catch (ThreadDeath e)
 111  
             {
 112  0
                 throw e;
 113  
             }
 114  0
             catch (OutOfMemoryError e)
 115  
             {
 116  0
                 throw e;
 117  
             }
 118  
             // when using Class.forName(), NoClassDefFoundErrors are likely
 119  
             // to happen (missing jar files)
 120  0
             catch (Throwable t)
 121  
             {
 122  0
                 throw new TurbineException("Failed registering " + type
 123  
                         + " factory: " + factory, t);
 124  564
             }
 125  564
         }
 126  564
     }
 127  
 
 128  
     /**
 129  
      * Initializes the AssemblerBroker and loads the AssemblerFactory
 130  
      * classes registered in TurbineResources.Properties.
 131  
      *
 132  
      * @throws InitializationException
 133  
      */
 134  
     @SuppressWarnings("unchecked") // as long as commons-collections does not use generics
 135  
     @Override
 136  
     public void init()
 137  
         throws InitializationException
 138  
     {
 139  94
         factories = new HashMap<String, List<AssemblerFactory>>();
 140  
 
 141  
         try
 142  
         {
 143  94
             Configuration conf = getConfiguration();
 144  
 
 145  94
             for (Iterator i = conf.getKeys(); i.hasNext();)
 146  
             {
 147  658
                 String type = (String)i.next();
 148  
 
 149  658
                 if (!"classname".equalsIgnoreCase(type))
 150  
                 {
 151  564
                     registerFactories(type);
 152  
                 }
 153  658
             }
 154  
         }
 155  0
         catch (TurbineException e)
 156  
         {
 157  0
             throw new InitializationException(
 158  
                     "AssemblerBrokerService failed to initialize", e);
 159  94
         }
 160  
 
 161  94
         isCaching = Turbine.getConfiguration()
 162  
             .getBoolean(TurbineConstants.MODULE_CACHE_KEY,
 163  
                         TurbineConstants.MODULE_CACHE_DEFAULT);
 164  
 
 165  94
         if (isCaching)
 166  
         {
 167  34
             int cacheSize = Turbine.getConfiguration()
 168  
                 .getInt(TurbineConstants.MODULE_CACHE_SIZE_KEY,
 169  
                         TurbineConstants.MODULE_CACHE_SIZE_DEFAULT);
 170  
 
 171  34
             assemblerCache = new LRUMap(cacheSize);
 172  34
             loaderCache = new LRUMap(cacheSize);
 173  
         }
 174  
 
 175  94
         setInit(true);
 176  94
     }
 177  
 
 178  
     /**
 179  
      * Register a new AssemblerFactory under a certain type
 180  
      *
 181  
      * @param type type of Assembler
 182  
      * @param factory factory to register
 183  
      */
 184  
     public void registerFactory(String type, AssemblerFactory factory)
 185  
     {
 186  564
         getFactoryGroup(type).add(factory);
 187  564
     }
 188  
 
 189  
     /**
 190  
      * Attempt to retrieve an Assembler of a given type with
 191  
      * a name.  Cycle through all the registered AssemblerFactory
 192  
      * classes of type and return the first non-null assembly
 193  
      * found.  If an assembly was not found return null.
 194  
      *
 195  
      * @param type type of Assembler
 196  
      * @param name name of the requested Assembler
 197  
      * @return an Assembler or null
 198  
      * @throws TurbineException
 199  
      */
 200  
     public Assembler getAssembler(String type, String name)
 201  
         throws TurbineException
 202  
     {
 203  212
         String key = type + ":" + name;
 204  212
         Assembler assembler = null;
 205  
 
 206  212
         if (isCaching && assemblerCache.containsKey(key))
 207  
         {
 208  0
             assembler = assemblerCache.get(key);
 209  0
             log.debug("Found " + key + " in the cache!");
 210  
         }
 211  
         else
 212  
         {
 213  212
             log.debug("Loading " + key);
 214  212
             List<AssemblerFactory> facs = getFactoryGroup(type);
 215  
 
 216  212
             for (Iterator<AssemblerFactory> it = facs.iterator(); (assembler == null) && it.hasNext();)
 217  
             {
 218  212
                 AssemblerFactory fac = it.next();
 219  
 
 220  
                 try
 221  
                 {
 222  212
                     assembler = fac.getAssembler(name);
 223  
                 }
 224  0
                 catch (Exception e)
 225  
                 {
 226  0
                     throw new TurbineException("Failed to load an assembler for "
 227  
                                                + name + " from the "
 228  
                                                + type + " factory "
 229  
                                                + fac.getClass().getName(), e);
 230  212
                 }
 231  
 
 232  212
                 if (isCaching && assembler != null)
 233  
                 {
 234  0
                     assemblerCache.put(key, assembler);
 235  
                 }
 236  212
             }
 237  
         }
 238  
 
 239  212
         return assembler;
 240  
     }
 241  
 
 242  
     /**
 243  
      * Get a Loader for the given assembler type
 244  
      *
 245  
      * @param type The Type of the Assembler
 246  
      * @return A Loader instance for the requested type
 247  
      */
 248  
     public Loader getLoader(String type)
 249  
     {
 250  1100
         Loader loader = null;
 251  
 
 252  1100
         if (isCaching && loaderCache.containsKey(type))
 253  
         {
 254  204
             loader = loaderCache.get(type);
 255  204
             log.debug("Found " + type + " loader in the cache!");
 256  
         }
 257  
         else
 258  
         {
 259  896
             log.debug("Getting Loader for " + type);
 260  896
             List facs = getFactoryGroup(type);
 261  
 
 262  896
             for (Iterator it = facs.iterator(); (loader == null) && it.hasNext();)
 263  
             {
 264  896
                 AssemblerFactory fac = (AssemblerFactory) it.next();
 265  
 
 266  896
                 loader = fac.getLoader();
 267  896
             }
 268  
 
 269  896
             if (isCaching && loader != null)
 270  
             {
 271  170
                 loaderCache.put(type, loader);
 272  
             }
 273  
         }
 274  
 
 275  1100
         if (loader == null)
 276  
         {
 277  0
             log.warn("Loader for " + type + " is null.");
 278  
         }
 279  
 
 280  1100
         return loader;
 281  
     }
 282  
 }