Clover coverage report - Ledge Components - SNAPSHOT
Coverage timestamp: Fri Nov 17 2006 05:13:20 CET
file stats: LOC: 302   Methods: 12
NCLOC: 142   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ConfigurationFactory.java 33.3% 62% 58.3% 58.8%
coverage coverage
 1    //
 2    // Copyright (c) 2003, Caltha - Gajda, Krzewski, Mach, Potempski Sp.J.
 3    // All rights reserved.
 4    //
 5    // Redistribution and use in source and binary forms, with or without modification,
 6    // are permitted provided that the following conditions are met:
 7    //
 8    // * Redistributions of source code must retain the above copyright notice,
 9    // this list of conditions and the following disclaimer.
 10    // * Redistributions in binary form must reproduce the above copyright notice,
 11    // this list of conditions and the following disclaimer in the documentation
 12    // and/or other materials provided with the distribution.
 13    // * Neither the name of the Caltha - Gajda, Krzewski, Mach, Potempski Sp.J.
 14    // nor the names of its contributors may be used to endorse or promote products
 15    // derived from this software without specific prior written permission.
 16    //
 17    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 18    // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19    // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 20    // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 21    // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 22    // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 23    // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 24    // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 25    // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 26    // POSSIBILITY OF SUCH DAMAGE.
 27    //
 28   
 29    package org.objectledge.configuration;
 30   
 31    import java.io.IOException;
 32    import java.net.URL;
 33   
 34    import javax.xml.parsers.ParserConfigurationException;
 35    import javax.xml.parsers.SAXParserFactory;
 36   
 37    import org.jcontainer.dna.Configuration;
 38    import org.jcontainer.dna.impl.SAXConfigurationHandler;
 39    import org.jcontainer.dna.impl.SAXConfigurationSerializer;
 40    import org.objectledge.ComponentInitializationError;
 41    import org.objectledge.filesystem.FileSystem;
 42    import org.objectledge.xml.XMLValidator;
 43    import org.xml.sax.InputSource;
 44    import org.xml.sax.SAXException;
 45    import org.xml.sax.SAXParseException;
 46    import org.xml.sax.XMLReader;
 47   
 48    import com.sun.msv.verifier.Verifier;
 49   
 50    /**
 51    * Returns a configuration for the specific component.
 52    *
 53    * <p>
 54    * Configuration factory plugs into the container using
 55    * {@link org.objectledge.pico.customization component customization} mechanism,
 56    * and provides components that declare a dependency on a DNA Configuration (using a
 57    * <code>org.jcontainer.dna.Configuration</code> component parameter) with an initialized
 58    * configuration object.
 59    * </p>
 60    *
 61    * <p>
 62    * The contents of the configuration object are read from an XML file,
 63    * and verified against a RelaxNG schema.
 64    * </p>
 65    *
 66    * <h3>Functionality anticipated in the future</h3>
 67    * <ul>
 68    * <li>Detecting of components that support runtime reconfiguration (possibly by extending
 69    * <code>org.jcontainer.dna.Configurable</code>interface.</li>
 70    * <li>Triggering of re-reading configuration from files on reconfigurable components</li>
 71    * <li>Programmatic setting of configuration of reconfigurable components.</li>
 72    * </ul>
 73    *
 74    * @author <a href="Rafal.Krzewski">rafal@caltha.pl</a>
 75    * @version $Id: ConfigurationFactory.java,v 1.12 2005/07/29 12:06:21 pablo Exp $
 76    */
 77    public class ConfigurationFactory
 78    {
 79    private FileSystem fileSystem;
 80   
 81    private String directory;
 82   
 83    private XMLValidator xmlValidator;
 84   
 85    private URL relaxngUrl;
 86   
 87    /**
 88    * Creates a new instance of ConfigurationFactory.
 89    *
 90    * @param fileSystem the file system to read configurations from.
 91    * @param xmlValidator the validator for configuration files.
 92    * @param directory the name of the directory where configurations reside.
 93    * @throws IOException if the RelaxNG schema cannot be found in classpath.
 94    */
 95  414 public ConfigurationFactory(FileSystem fileSystem, XMLValidator xmlValidator, String directory)
 96    throws IOException
 97    {
 98  414 this.fileSystem = fileSystem;
 99  414 this.xmlValidator = xmlValidator;
 100  414 this.directory = directory;
 101  414 this.relaxngUrl = fileSystem.getResource(XMLValidator.RELAXNG_SCHEMA);
 102    }
 103   
 104    /**
 105    * Returns the configuration of the specific compoenent in the system.
 106    *
 107    * @param componentName the name of the component
 108    * @param componentClass the implementation class of the component.
 109    * @return the configuration.
 110    */
 111  414 public Configuration getConfig(String componentName, Class componentClass)
 112    {
 113  414 String path = getComponentConfigurationPath(componentName);
 114  414 InputSource source = getConfigurationSource(componentName, componentClass);
 115  414 Configuration configuration;
 116  414 try
 117    {
 118  414 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
 119  414 XMLReader reader = parserFactory.newSAXParser().getXMLReader();
 120  414 SAXConfigurationHandler handler = new SAXConfigurationHandler();
 121  414 reader.setContentHandler(handler);
 122  414 reader.setErrorHandler(handler);
 123  414 reader.parse(source);
 124  414 configuration = handler.getConfiguration();
 125    }
 126    catch(SAXParseException e)
 127    {
 128  0 throw new ComponentInitializationError("parse error in configuration of component "+
 129    componentName+": "+e.getMessage()+" in "+e.getSystemId()+" at line "+
 130    e.getLineNumber(), e);
 131    }
 132    catch(Exception e)
 133    {
 134  0 throw new ComponentInitializationError("configuration file "+
 135    path+" for component "+componentName+" is malformed", e);
 136    }
 137  414 return configuration;
 138    }
 139   
 140    /**
 141    * Returns the configuration of the specific compoenent in the system.
 142    *
 143    * @param componentRole the role of the component.
 144    * @param componentImplementation the implementation class of the component.
 145    * @return the configuration.
 146    */
 147  0 public Configuration getConfig(Class componentRole, Class componentImplementation)
 148    {
 149  0 return getConfig(componentRole.getName(), componentImplementation);
 150    }
 151   
 152    /**
 153    * Returns an input source for reading in the configuration file.
 154    *
 155    * @param componentName the name of the component
 156    * @param componentClass the implementation class of the component.
 157    * @return the input source.
 158    */
 159  414 public InputSource getConfigurationSource(String componentName, Class componentClass)
 160    {
 161  414 String path = getComponentConfigurationPath(componentName);
 162  414 InputSource source = getRawConfigurationSource(componentName);
 163  414 String schema = getComponentConfigurationSchemaPath(componentClass);
 164  414 if(!fileSystem.exists(schema))
 165    {
 166  0 throw new ComponentInitializationError("schema file "+schema+" for component "+
 167    componentName+" not found");
 168    }
 169  414 try
 170    {
 171  414 checkSchema(path, schema);
 172    }
 173    catch(SAXParseException e)
 174    {
 175  0 throw new ComponentInitializationError("parse error in configuration of component "+
 176    componentName+": "+e.getMessage()+" in "+e.getSystemId()+" at line "+
 177    e.getLineNumber(), e);
 178    }
 179    catch(Exception e)
 180    {
 181  0 throw new ComponentInitializationError("configuration file "+
 182    path+" for component "+componentName+" is malformed: '" + e.getMessage() + "'", e);
 183    }
 184  414 return source;
 185    }
 186   
 187    /**
 188    * Return a raw (unchecked) configuration source for a component.
 189    *
 190    * @param componentName the name of the component.
 191    * @return an InputSource for reading the configuration.
 192    */
 193  414 public InputSource getRawConfigurationSource(String componentName)
 194    {
 195  414 String path = getComponentConfigurationPath(componentName);
 196  414 if(!fileSystem.exists(path))
 197    {
 198  0 throw new ComponentInitializationError("configuration file "+path+" for component "+
 199    componentName+" not found");
 200    }
 201  414 return new InputSource(fileSystem.getInputStream(path));
 202    }
 203   
 204    /**
 205    * Checks if a given component has a configration file available.
 206    *
 207    * @param componentName the name of the component.
 208    * @return <code>true</code> if the component has a configration file available.
 209    */
 210  0 public boolean hasConfig(String componentName)
 211    {
 212  0 String path = getComponentConfigurationPath(componentName);
 213  0 return fileSystem.exists(path);
 214    }
 215   
 216    /**
 217    * Returns an input source for reading in the configuration file.
 218    *
 219    * @param componentRole the role of the component
 220    * @param componentClass the implementation class of the component.
 221    * @return the input source.
 222    */
 223  0 public InputSource getConfigurationSource(Class componentRole, Class componentClass)
 224    {
 225  0 return getConfigurationSource(componentRole.getName(), componentClass);
 226    }
 227   
 228    /**
 229    * Returns an InputSource for reading the container composition file.
 230    *
 231    * @return an InputSource for reading the container composition file.
 232    */
 233  0 public InputSource getCompositionSource()
 234    {
 235  0 String path = directory + "/container.xml";
 236  0 if(!fileSystem.exists(path))
 237    {
 238  0 throw new ComponentInitializationError("composition file " + path + " not found");
 239    }
 240  0 return new InputSource(fileSystem.getInputStream(path));
 241    }
 242   
 243    // implemnetation /////////////////////////////////////////////////////////////////////////////
 244   
 245    /**
 246    * Returns the path of the configuration file for the specified key.
 247    *
 248    * @param componentName the name of the component.
 249    * @return path the configuration file path.
 250    */
 251  1242 protected String getComponentConfigurationPath(String componentName)
 252    {
 253  1242 return directory+"/"+componentName+".xml";
 254    }
 255   
 256    /**
 257    * Returns the path of the configuration schema file for the specified key.
 258    *
 259    * @param componentImplementation the implementation class of the component.
 260    * @return path the configuration file path.
 261    */
 262  414 protected String getComponentConfigurationSchemaPath(Class componentImplementation)
 263    {
 264  414 return ((Class)componentImplementation).getName().replace('.','/')+".rng";
 265    }
 266   
 267    /**
 268    * Checks if an xml file fulfills it's associated schema.
 269    *
 270    * @param configuration the configuration.
 271    * @param schemaPath the the schema file path.
 272    * @throws IOException if the configuration, or schema cannot be read.
 273    * @throws SAXException if the configuration, or schema cannot be parsed.
 274    * @throws ParserConfigurationException if the parser is badly configured.
 275    */
 276  0 protected void checkSchema(Configuration configuration, String schemaPath)
 277    throws SAXException, IOException, ParserConfigurationException
 278    {
 279  0 URL schemaUrl = fileSystem.getResource(schemaPath);
 280  0 xmlValidator.validate(schemaUrl, relaxngUrl);
 281  0 Verifier verifier= xmlValidator.getVerifier(schemaUrl);
 282  0 SAXConfigurationSerializer serializer = new SAXConfigurationSerializer();
 283  0 serializer.serialize(configuration, verifier);
 284    }
 285   
 286    /**
 287    * Checks if an xml file fulfills it's associated schema.
 288    *
 289    * @param configuration the configuration file path.
 290    * @param schemaPath the the schema file path.
 291    * @throws IOException if the configuration, or schema cannot be read.
 292    * @throws SAXException if the configuration, or schema cannot be parsed.
 293    * @throws ParserConfigurationException if the parser is badly configured.
 294    */
 295  414 protected void checkSchema(String configuration, String schemaPath)
 296    throws SAXException, IOException, ParserConfigurationException
 297    {
 298  414 URL schemaUrl = fileSystem.getResource(schemaPath);
 299  414 xmlValidator.validate(schemaUrl, relaxngUrl);
 300  414 xmlValidator.validate(fileSystem.getResource(configuration), schemaUrl);
 301    }
 302    }