Clover coverage report - Code Coverage for tapestry release 4.0-alpha-3
Coverage timestamp: Mon May 16 2005 09:05:49 EDT
file stats: LOC: 294   Methods: 10
NCLOC: 158   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
BeanProvider.java 78.9% 85.9% 90% 84%
coverage coverage
 1   
 // Copyright 2004, 2005 The Apache Software Foundation
 2   
 //
 3   
 // Licensed under the Apache License, Version 2.0 (the "License");
 4   
 // you may not use this file except in compliance with the License.
 5   
 // You may obtain a copy of the License at
 6   
 //
 7   
 //     http://www.apache.org/licenses/LICENSE-2.0
 8   
 //
 9   
 // Unless required by applicable law or agreed to in writing, software
 10   
 // distributed under the License is distributed on an "AS IS" BASIS,
 11   
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12   
 // See the License for the specific language governing permissions and
 13   
 // limitations under the License.
 14   
 
 15   
 package org.apache.tapestry.bean;
 16   
 
 17   
 import java.util.Collection;
 18   
 import java.util.Collections;
 19   
 import java.util.HashMap;
 20   
 import java.util.HashSet;
 21   
 import java.util.Iterator;
 22   
 import java.util.List;
 23   
 import java.util.Map;
 24   
 import java.util.Set;
 25   
 
 26   
 import org.apache.commons.logging.Log;
 27   
 import org.apache.commons.logging.LogFactory;
 28   
 import org.apache.hivemind.ApplicationRuntimeException;
 29   
 import org.apache.hivemind.ClassResolver;
 30   
 import org.apache.tapestry.IBeanProvider;
 31   
 import org.apache.tapestry.IComponent;
 32   
 import org.apache.tapestry.IEngine;
 33   
 import org.apache.tapestry.Tapestry;
 34   
 import org.apache.tapestry.event.PageDetachListener;
 35   
 import org.apache.tapestry.event.PageEndRenderListener;
 36   
 import org.apache.tapestry.event.PageEvent;
 37   
 import org.apache.tapestry.spec.BeanLifecycle;
 38   
 import org.apache.tapestry.spec.IBeanSpecification;
 39   
 import org.apache.tapestry.spec.IComponentSpecification;
 40   
 
 41   
 /**
 42   
  * Basic implementation of the {@link IBeanProvider}interface.
 43   
  * 
 44   
  * @author Howard Lewis Ship
 45   
  * @since 1.0.4
 46   
  */
 47   
 
 48   
 public class BeanProvider implements IBeanProvider, PageDetachListener, PageEndRenderListener
 49   
 {
 50   
     private static final Log LOG = LogFactory.getLog(BeanProvider.class);
 51   
 
 52   
     /**
 53   
      * Indicates whether this instance has been registered with its page as a PageDetachListener.
 54   
      * Registration only occurs the first time a bean with lifecycle REQUEST is instantiated.
 55   
      */
 56   
 
 57   
     private boolean _registeredForDetach = false;
 58   
 
 59   
     /**
 60   
      * Indicates whether this instance has been registered as a render listener with the page.
 61   
      */
 62   
 
 63   
     private boolean _registeredForRender = false;
 64   
 
 65   
     /**
 66   
      * The component for which beans are being created and tracked.
 67   
      */
 68   
 
 69   
     private IComponent _component;
 70   
 
 71   
     /**
 72   
      * Used for instantiating classes.
 73   
      */
 74   
 
 75   
     private ClassResolver _resolver;
 76   
 
 77   
     /**
 78   
      * Map of beans, keyed on name.
 79   
      */
 80   
 
 81   
     private Map _beans;
 82   
 
 83   
     /**
 84   
      * Set of bean names provided by this provider.
 85   
      * 
 86   
      * @since 2.2
 87   
      */
 88   
 
 89   
     private Set _beanNames;
 90   
 
 91  55
     public BeanProvider(IComponent component)
 92   
     {
 93  55
         this._component = component;
 94  55
         IEngine engine = component.getPage().getEngine();
 95  55
         _resolver = engine.getClassResolver();
 96   
 
 97  55
         if (LOG.isDebugEnabled())
 98  0
             LOG.debug("Created BeanProvider for " + component);
 99   
 
 100   
     }
 101   
 
 102   
     /** @since 1.0.6 * */
 103   
 
 104  73
     public Collection getBeanNames()
 105   
     {
 106  73
         if (_beanNames == null)
 107   
         {
 108  22
             Collection c = _component.getSpecification().getBeanNames();
 109   
 
 110  22
             if (c == null || c.isEmpty())
 111  0
                 _beanNames = Collections.EMPTY_SET;
 112   
             else
 113  22
                 _beanNames = Collections.unmodifiableSet(new HashSet(c));
 114   
         }
 115   
 
 116  73
         return _beanNames;
 117   
     }
 118   
 
 119   
     /**
 120   
      * @since 1.0.5
 121   
      */
 122   
 
 123  8
     public IComponent getComponent()
 124   
     {
 125  8
         return _component;
 126   
     }
 127   
 
 128  142
     public Object getBean(String name)
 129   
     {
 130  142
         Object bean = null;
 131   
 
 132  142
         if (_beans != null)
 133  87
             bean = _beans.get(name);
 134   
 
 135  142
         if (bean != null)
 136  73
             return bean;
 137   
 
 138  69
         IBeanSpecification spec = _component.getSpecification().getBeanSpecification(name);
 139   
 
 140  69
         if (spec == null)
 141  0
             throw new ApplicationRuntimeException(Tapestry.format(
 142   
                     "BeanProvider.bean-not-defined",
 143   
                     _component.getExtendedId(),
 144   
                     name));
 145   
 
 146  69
         bean = instantiateBean(name, spec);
 147   
 
 148  69
         BeanLifecycle lifecycle = spec.getLifecycle();
 149   
 
 150  69
         if (lifecycle == BeanLifecycle.NONE)
 151  0
             return bean;
 152   
 
 153  69
         if (_beans == null)
 154  55
             _beans = new HashMap();
 155   
 
 156  69
         _beans.put(name, bean);
 157   
 
 158   
         // The first time in a request that a REQUEST lifecycle bean is created,
 159   
         // register with the page to be notified at the end of the
 160   
         // request cycle.
 161   
 
 162  69
         if (lifecycle == BeanLifecycle.REQUEST && !_registeredForDetach)
 163   
         {
 164  54
             _component.getPage().addPageDetachListener(this);
 165  54
             _registeredForDetach = true;
 166   
         }
 167   
 
 168  69
         if (lifecycle == BeanLifecycle.RENDER && !_registeredForRender)
 169   
         {
 170  1
             _component.getPage().addPageEndRenderListener(this);
 171  1
             _registeredForRender = true;
 172   
         }
 173   
 
 174   
         // No need to register if a PAGE lifecycle bean; those can stick around
 175   
         // forever.
 176   
 
 177  69
         return bean;
 178   
     }
 179   
 
 180  69
     private Object instantiateBean(String beanName, IBeanSpecification spec)
 181   
     {
 182  69
         String className = spec.getClassName();
 183  69
         Object bean = null;
 184   
 
 185  69
         if (LOG.isDebugEnabled())
 186  0
             LOG.debug("Instantiating instance of " + className);
 187   
 
 188   
         // Do it the hard way!
 189   
 
 190  69
         try
 191   
         {
 192  69
             Class beanClass = _resolver.findClass(className);
 193   
 
 194  69
             bean = beanClass.newInstance();
 195   
         }
 196   
         catch (Exception ex)
 197   
         {
 198   
 
 199  0
             throw new ApplicationRuntimeException(Tapestry.format(
 200   
                     "BeanProvider.instantiation-error",
 201   
                     new Object[]
 202   
                     { beanName, _component.getExtendedId(), className, ex.getMessage() }), spec
 203   
                     .getLocation(), ex);
 204   
         }
 205   
 
 206   
         // OK, have the bean, have to initialize it.
 207   
 
 208  69
         List initializers = spec.getInitializers();
 209   
 
 210  69
         if (initializers == null)
 211  66
             return bean;
 212   
 
 213  3
         Iterator i = initializers.iterator();
 214  3
         while (i.hasNext())
 215   
         {
 216  8
             IBeanInitializer iz = (IBeanInitializer) i.next();
 217   
 
 218  8
             if (LOG.isDebugEnabled())
 219  0
                 LOG.debug("Initializing property " + iz.getPropertyName());
 220   
 
 221  8
             iz.setBeanProperty(this, bean);
 222   
         }
 223   
 
 224  3
         return bean;
 225   
     }
 226   
 
 227   
     /**
 228   
      * Removes all beans with the REQUEST lifecycle. Beans with the PAGE lifecycle stick around, and
 229   
      * beans with no lifecycle were never stored in the first place.
 230   
      */
 231   
 
 232  114
     public void pageDetached(PageEvent event)
 233   
     {
 234  114
         removeBeans(BeanLifecycle.REQUEST);
 235   
     }
 236   
 
 237   
     /**
 238   
      * Removes any beans with the specified lifecycle.
 239   
      * 
 240   
      * @since 2.2
 241   
      */
 242   
 
 243  115
     private void removeBeans(BeanLifecycle lifecycle)
 244   
     {
 245  115
         if (_beans == null)
 246  0
             return;
 247   
 
 248  115
         IComponentSpecification spec = null;
 249   
 
 250  115
         Iterator i = _beans.entrySet().iterator();
 251  115
         while (i.hasNext())
 252   
         {
 253  69
             Map.Entry e = (Map.Entry) i.next();
 254  69
             String name = (String) e.getKey();
 255   
 
 256  69
             if (spec == null)
 257  62
                 spec = _component.getSpecification();
 258   
 
 259  69
             IBeanSpecification s = spec.getBeanSpecification(name);
 260   
 
 261  69
             if (s.getLifecycle() == lifecycle)
 262   
             {
 263  65
                 Object bean = e.getValue();
 264   
 
 265  65
                 if (LOG.isDebugEnabled())
 266  0
                     LOG.debug("Removing " + lifecycle.getName() + " bean " + name + ": " + bean);
 267   
 
 268  65
                 i.remove();
 269   
             }
 270   
         }
 271   
     }
 272   
 
 273   
     /** @since 1.0.8 * */
 274   
 
 275  0
     public ClassResolver getClassResolver()
 276   
     {
 277  0
         return _resolver;
 278   
     }
 279   
 
 280   
     /** @since 2.2 * */
 281   
 
 282  1
     public void pageEndRender(PageEvent event)
 283   
     {
 284  1
         removeBeans(BeanLifecycle.RENDER);
 285   
     }
 286   
 
 287   
     /** @since 2.2 * */
 288   
 
 289  73
     public boolean canProvideBean(String name)
 290   
     {
 291  73
         return getBeanNames().contains(name);
 292   
     }
 293   
 
 294   
 }