2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

Coverage Report - org.apache.shale.test.config.ConfigParser
 
Classes in this File Line Coverage Branch Coverage Complexity
ConfigParser
100%
42/42
N/A
1.27
ConfigParser$ComponentBean
100%
7/7
N/A
1.27
ConfigParser$ComponentRule
100%
7/7
N/A
1.27
ConfigParser$ConverterBean
100%
10/10
N/A
1.27
ConfigParser$ConverterRule
100%
13/13
N/A
1.27
ConfigParser$RenderKitIdRule
100%
1/1
N/A
1.27
ConfigParser$RenderKitRule
100%
6/6
N/A
1.27
ConfigParser$RendererBean
100%
10/10
N/A
1.27
ConfigParser$RendererRule
100%
12/12
N/A
1.27
ConfigParser$ValidatorBean
100%
7/7
N/A
1.27
ConfigParser$ValidatorRule
100%
7/7
N/A
1.27
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to you under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.shale.test.config;
 19  
 
 20  
 import java.io.IOException;
 21  
 import java.net.URL;
 22  
 import javax.faces.FactoryFinder;
 23  
 import javax.faces.application.Application;
 24  
 import javax.faces.application.ApplicationFactory;
 25  
 import javax.faces.render.RenderKit;
 26  
 import javax.faces.render.RenderKitFactory;
 27  
 import javax.faces.render.Renderer;
 28  
 import org.apache.commons.digester.Digester;
 29  
 import org.apache.commons.digester.Rule;
 30  
 import org.apache.shale.test.mock.MockRenderKit;
 31  
 import org.xml.sax.Attributes;
 32  
 import org.xml.sax.SAXException;
 33  
 
 34  
 /**
 35  
  * <p>Utility class to parse JavaServer Faces configuration resources, and
 36  
  * register JSF artifacts with the mock object hierarchy.</p>
 37  
  *
 38  
  * <p>The following artifacts are registered:</p>
 39  
  * <ul>
 40  
  *     <li><code>Converter</code> (by-id and by-class)</li>
 41  
  *     <li><code>RenderKit</code> and <code>Renderer</code></li>
 42  
  *     <li><code>UIComponent</code></li>
 43  
  *     <li><code>Validator</code></li>
 44  
  * </ul>
 45  
  *
 46  
  * <p>Note that any declared <em>factory</em> instances are explicitly
 47  
  * <strong>NOT</strong> registered, allowing the mock object hierarchy
 48  
  * of the Shale Test Framework to manage these APIs.</p>
 49  
  *
 50  
  * <p><strong>USAGE NOTE</strong> - If you are using an instance of this
 51  
  * class within a subclass of <code>AbstractJsfTestCase</code> or
 52  
  * <code>AbstractJmockJsfTestCase</code>, be sure you have completed the
 53  
  * <code>setUp()</code> processing in this base class before calling one
 54  
  * of the <code>parse()</code> methods.</p>
 55  
  *
 56  
  * @since 1.1
 57  
  */
 58  
 public final class ConfigParser {
 59  
     
 60  
 
 61  
     // ------------------------------------------------------------ Constructors
 62  
 
 63  
 
 64  
     /** Creates a new instance of ConfigParser */
 65  3
     public ConfigParser() {
 66  3
     }
 67  
     
 68  
 
 69  
     // ------------------------------------------------------ Manifest Constants
 70  
 
 71  
 
 72  
     /**
 73  
      * <p>Configuration resource URLs for the JSF RI.</p>
 74  
      */
 75  1
     private static final String[] JSFRI_RESOURCES =
 76  
     { "/com/sun/faces/jsf-ri-runtime.xml",
 77  
     };
 78  
 
 79  
 
 80  
     /**
 81  
      * <p>Configuration resource URLs for Apache MyFaces.</p>
 82  
      */
 83  1
     private static final String[] MYFACES_RESOURCES =
 84  
     { "/org/apache/myfaces/resource/standard-faces-config.xml",
 85  
     };
 86  
 
 87  
 
 88  
     // ------------------------------------------------------ Instance Variables
 89  
 
 90  
 
 91  
     /**
 92  
      * <p>The <code>Digester</code> instance we will use for parsing.</p>
 93  
      */
 94  3
     private Digester digester = null;
 95  
 
 96  
 
 97  
     // ------------------------------------------------------- Public Properties
 98  
 
 99  
 
 100  
     /**
 101  
      * <p>Return the URLs of the platform configuration resources for this
 102  
      * application.  The following platforms are currently supported:</p>
 103  
      * <ul>
 104  
      * <li>JavaServer Faces Reference Implementation (version 1.0 - 1.2)</li>
 105  
      * <li>MyFaces (version 1.1)</li>
 106  
      * </ul>
 107  
      *
 108  
      * <p>If MyFaces (version 1.2), currently under development, does not change
 109  
      * the name of the configuration resource, it will be supported as well.</p>
 110  
      */
 111  
     public URL[] getPlatformURLs() {
 112  
 
 113  1
         URL[] urls = translate(JSFRI_RESOURCES);
 114  1
         if (urls[0] == null) {
 115  
             urls = translate(MYFACES_RESOURCES);
 116  
         }
 117  1
         return urls;
 118  
 
 119  
     }
 120  
 
 121  
 
 122  
     // ---------------------------------------------------------- Public Methods
 123  
 
 124  
 
 125  
     /**
 126  
      * <p>Parse the specified JavaServer Faces configuration resource, causing
 127  
      * the appropriate JSF artifacts to be registered with the mock object
 128  
      * hierarchy.</p>
 129  
      *
 130  
      * @param url <code>URL</code> of the configuration resource to parse
 131  
      *
 132  
      * @exception IOException if an input/output error occurs
 133  
      * @exception SAXException if a parsing error occurs
 134  
      */
 135  
     public void parse(URL url) throws IOException, SAXException {
 136  
 
 137  
         // Acquire and configure the Digester instance we will use
 138  2
         Digester digester = digester();
 139  2
         ApplicationFactory factory = (ApplicationFactory)
 140  
           FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
 141  2
         Application application = factory.getApplication();
 142  2
         digester.push(application);
 143  
 
 144  
         // Perform the required parsing
 145  
         try {
 146  2
             digester.parse(url);
 147  
         } finally {
 148  2
             digester.clear();
 149  2
         }
 150  
 
 151  2
     }
 152  
 
 153  
 
 154  
     /**
 155  
      * <p>Parse the specified set of JavaServer Faces configuration resources,
 156  
      * in the listed order, causing the appropriate JSF artifacts to be registered
 157  
      * with the mock object hierarchy.</p>
 158  
      *
 159  
      * @param urls <code>URL</code>s of the configuration resources to parse
 160  
      *
 161  
      * @exception IOException if an input/output error occurs
 162  
      * @exception SAXException if a parsing error occurs
 163  
      */
 164  
     public void parse(URL[] urls) throws IOException, SAXException {
 165  
 
 166  2
         for (int i = 0; i < urls.length; i++) {
 167  1
             parse(urls[i]);
 168  
         }
 169  
 
 170  1
     }
 171  
 
 172  
 
 173  
     // --------------------------------------------------------- Private Methods
 174  
 
 175  
 
 176  
     /**
 177  
      * <p>Return the <code>Digester</code> instance we will use for parsing,
 178  
      * creating and configuring a new instance if necessary.</p>
 179  
      */
 180  
     private Digester digester() {
 181  
 
 182  2
         if (this.digester == null) {
 183  2
             this.digester = new Digester();
 184  2
             digester.addRule("faces-config/component", new ComponentRule());
 185  2
             digester.addCallMethod
 186  
               ("faces-config/component/component-type", "setComponentType", 0);
 187  2
             digester.addCallMethod
 188  
               ("faces-config/component/component-class", "setComponentClass", 0);
 189  2
             digester.addRule("faces-config/converter", new ConverterRule());
 190  2
             digester.addCallMethod
 191  
               ("faces-config/converter/converter-id", "setConverterId", 0);
 192  2
             digester.addCallMethod
 193  
               ("faces-config/converter/converter-class", "setConverterClass", 0);
 194  2
             digester.addCallMethod
 195  
               ("faces-config/converter/converter-for-class", "setConverterForClass", 0);
 196  2
             digester.addRule("faces-config/render-kit", new RenderKitRule());
 197  2
             digester.addRule("faces-config/render-kit/render-kit-id", new RenderKitIdRule());
 198  2
             digester.addRule("faces-config/render-kit/renderer", new RendererRule());
 199  2
             digester.addCallMethod
 200  
               ("faces-config/render-kit/renderer/component-family", "setComponentFamily", 0);
 201  2
             digester.addCallMethod
 202  
               ("faces-config/render-kit/renderer/renderer-class", "setRendererClass", 0);
 203  2
             digester.addCallMethod
 204  
               ("faces-config/render-kit/renderer/renderer-type", "setRendererType", 0);
 205  2
             digester.addRule("faces-config/validator", new ValidatorRule());
 206  2
             digester.addCallMethod
 207  
               ("faces-config/validator/validator-id", "setValidatorId", 0);
 208  2
             digester.addCallMethod
 209  
               ("faces-config/validator/validator-class", "setValidatorClass", 0);
 210  
         }
 211  2
         return this.digester;
 212  
 
 213  
     }
 214  
 
 215  
 
 216  
     /**
 217  
      * <p>Translate an array of resource names into an array of resource URLs.</p>
 218  
      *
 219  
      * @param names Resource names to translate
 220  
      */
 221  
     private URL[] translate(String[] names) {
 222  
 
 223  1
         URL[] results = new URL[names.length];
 224  2
         for (int i = 0; i < names.length; i++) {
 225  1
             results[i] = this.getClass().getResource(names[i]);
 226  
         }
 227  1
         return results;
 228  
         
 229  
     }
 230  
 
 231  
 
 232  
     // --------------------------------------------------------- Private Classes
 233  
 
 234  
 
 235  
     /**
 236  
      * <p>Data bean that stores information related to a component.</p>
 237  
      */
 238  45
     class ComponentBean {
 239  
 
 240  
         private String componentClass;
 241  
         public String getComponentClass() {
 242  45
             return this.componentClass;
 243  
         }
 244  
         public void setComponentClass(String componentClass) {
 245  45
             this.componentClass = componentClass;
 246  45
         }
 247  
 
 248  
         private String componentType;
 249  
         public String getComponentType() {
 250  45
             return this.componentType;
 251  
         }
 252  
         public void setComponentType(String componentType) {
 253  45
             this.componentType = componentType;
 254  45
         }
 255  
 
 256  
     }
 257  
 
 258  
 
 259  
     /**
 260  
      * <p>Digester <code>Rule</code> for processing components.</p>
 261  
      */
 262  2
     class ComponentRule extends Rule {
 263  
 
 264  
         public void begin(String namespace, String name, Attributes attributes) {
 265  45
             getDigester().push(new ComponentBean());
 266  45
         }
 267  
 
 268  
         public void end(String namespace, String name) {
 269  45
             ComponentBean bean = (ComponentBean) getDigester().pop();
 270  45
             Application application = (Application) getDigester().peek();
 271  45
             application.addComponent(bean.getComponentType(), bean.getComponentClass());
 272  45
         }
 273  
 
 274  
     }
 275  
 
 276  
 
 277  
     /**
 278  
      * <p>Data bean that stores information related to a converter.</p>
 279  
      */
 280  26
     class ConverterBean {
 281  
 
 282  
         private String converterClass;
 283  
         public String getConverterClass() {
 284  26
             return this.converterClass;
 285  
         }
 286  
         public void setConverterClass(String converterClass) {
 287  26
             this.converterClass = converterClass;
 288  26
         }
 289  
 
 290  
         private String converterForClass;
 291  
         public String getConverterForClass() {
 292  12
             return this.converterForClass;
 293  
         }
 294  
         public void setConverterForClass(String converterForClass) {
 295  12
             this.converterForClass = converterForClass;
 296  12
         }
 297  
 
 298  
         private String converterId;
 299  
         public String getConverterId() {
 300  40
             return this.converterId;
 301  
         }
 302  
         public void setConverterId(String converterId) {
 303  14
             this.converterId = converterId;
 304  14
         }
 305  
 
 306  
     }
 307  
 
 308  
 
 309  
     /**
 310  
      * <p>Digester <code>Rule</code> for processing converers.</p>
 311  
      */
 312  2
     class ConverterRule extends Rule {
 313  
 
 314  
         public void begin(String namespace, String name, Attributes attributes) {
 315  26
             getDigester().push(new ConverterBean());
 316  26
         }
 317  
 
 318  
         public void end(String namespace, String name) {
 319  26
             ConverterBean bean = (ConverterBean) getDigester().pop();
 320  26
             Application application = (Application) getDigester().peek();
 321  26
             if (bean.getConverterId() != null) {
 322  14
                 application.addConverter(bean.getConverterId(), bean.getConverterClass());
 323  14
             } else {
 324  12
                 Class clazz = null;
 325  
                 try {
 326  12
                     clazz = this.getClass().getClassLoader().loadClass(bean.getConverterForClass());
 327  
                 } catch (ClassNotFoundException e) {
 328  
                     throw new IllegalArgumentException("java.lang.ClassNotFoundException: "
 329  
                         + bean.getConverterForClass());
 330  12
                 }
 331  12
                 application.addConverter(clazz, bean.getConverterClass());
 332  
             }
 333  26
         }
 334  
 
 335  
     }
 336  
 
 337  
 
 338  
     /**
 339  
      * <p>Digester <code>Rule</code> for processing render kits.</p>
 340  
      */
 341  2
     class RenderKitRule extends Rule {
 342  
 
 343  
         public void begin(String namespace, String name, Attributes attributes) {
 344  2
             RenderKitFactory factory = (RenderKitFactory)
 345  
               FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 346  2
             getDigester().push(factory.getRenderKit(null, RenderKitFactory.HTML_BASIC_RENDER_KIT));
 347  2
         }
 348  
 
 349  
         public void end(String namespace, String name) {
 350  2
             getDigester().pop();
 351  2
         }
 352  
 
 353  
     }
 354  
 
 355  
 
 356  
     /**
 357  
      * <p>Digester <code>Rule</code> for processing render kit identifiers.</p>
 358  
      */
 359  2
     class RenderKitIdRule extends Rule {
 360  
 
 361  
         public void body(String namespace, String name, String text) {
 362  
             String renderKitId = text.trim();
 363  
             RenderKitFactory factory = (RenderKitFactory)
 364  
               FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 365  
             RenderKit renderKit = factory.getRenderKit(null, renderKitId);
 366  
             if (renderKit == null) {
 367  
                 renderKit = new MockRenderKit();
 368  
                 factory.addRenderKit(renderKitId, renderKit);
 369  
             }
 370  
             digester.pop();
 371  
             digester.push(renderKit);
 372  
         }
 373  
 
 374  
     }
 375  
 
 376  
 
 377  
     /**
 378  
      * <p>Data bean that stores information related to a renderer.</p>
 379  
      */
 380  26
     class RendererBean {
 381  
 
 382  
         private String componentFamily;
 383  
         public String getComponentFamily() {
 384  26
             return this.componentFamily;
 385  
         }
 386  
         public void setComponentFamily(String componentFamily) {
 387  26
             this.componentFamily = componentFamily;
 388  26
         }
 389  
 
 390  
         private String rendererClass;
 391  
         public String getRendererClass() {
 392  26
             return this.rendererClass;
 393  
         }
 394  
         public void setRendererClass(String rendererClass) {
 395  26
             this.rendererClass = rendererClass;
 396  26
         }
 397  
 
 398  
         private String rendererType;
 399  
         public String getRendererType() {
 400  26
             return this.rendererType;
 401  
         }
 402  
         public void setRendererType(String rendererType) {
 403  26
             this.rendererType = rendererType;
 404  26
         }
 405  
 
 406  
     }
 407  
 
 408  
 
 409  
     /**
 410  
      * <p>Digester <code>Rule</code> for processing renderers.</p>
 411  
      */
 412  2
     class RendererRule extends Rule {
 413  
 
 414  
         public void begin(String namespace, String name, Attributes attributes) {
 415  26
             getDigester().push(new RendererBean());
 416  26
         }
 417  
 
 418  
         public void end(String namespace, String name) {
 419  26
             RendererBean bean = (RendererBean) getDigester().pop();
 420  26
             RenderKit kit = (RenderKit) getDigester().peek();
 421  26
             Renderer renderer = null;
 422  26
             Class clazz = null;
 423  
             try {
 424  26
                 clazz = this.getClass().getClassLoader().loadClass(bean.getRendererClass());
 425  26
                 renderer = (Renderer) clazz.newInstance();
 426  
             } catch (Exception e) {
 427  
                 throw new IllegalArgumentException("Exception while trying to instantiate"
 428  
                     + " renderer class '" + bean.getRendererClass() + "' : "
 429  
                     + e.getMessage());
 430  26
             }
 431  26
             kit.addRenderer(bean.getComponentFamily(), bean.getRendererType(),
 432  
                             renderer);
 433  26
         }
 434  
 
 435  
     }
 436  
 
 437  
 
 438  
     /**
 439  
      * <p>Data bean that stores information related to a validator.</p>
 440  
      */
 441  5
     class ValidatorBean {
 442  
 
 443  
         private String validatorClass;
 444  
         public String getValidatorClass() {
 445  5
             return this.validatorClass;
 446  
         }
 447  
         public void setValidatorClass(String validatorClass) {
 448  5
             this.validatorClass = validatorClass;
 449  5
         }
 450  
 
 451  
         private String validatorId;
 452  
         public String getValidatorId() {
 453  5
             return this.validatorId;
 454  
         }
 455  
         public void setValidatorId(String validatorId) {
 456  5
             this.validatorId = validatorId;
 457  5
         }
 458  
 
 459  
     }
 460  
 
 461  
 
 462  
     /**
 463  
      * <p>Digester <code>Rule</code> for processing validators.</p>
 464  
      */
 465  2
     class ValidatorRule extends Rule {
 466  
 
 467  
         public void begin(String namespace, String name, Attributes attributes) {
 468  5
             getDigester().push(new ValidatorBean());
 469  5
         }
 470  
 
 471  
         public void end(String namespace, String name) {
 472  5
             ValidatorBean bean = (ValidatorBean) getDigester().pop();
 473  5
             Application application = (Application) getDigester().peek();
 474  5
             application.addValidator(bean.getValidatorId(), bean.getValidatorClass());
 475  5
         }
 476  
 
 477  
     }
 478  
 
 479  
 
 480  
 }