Clover coverage report - JBind Project
Coverage timestamp: Fr Mai 28 2004 11:17:36 CEST
file stats: LOC: 498   Methods: 21
NCLOC: 296   Classes: 1
This license of Clover is provided to support the development of JBind only. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover.
 
 Source file Conditionals Statements Methods TOTAL
PrefsConfig.java 59,5% 67,1% 81% 67%
 1   
 /*
 2   
  * JBind
 3   
  *
 4   
  * Copyright (c) by Stefan Wachter. All rights reserved.
 5   
  *
 6   
  * Usage, modification, and redistribution is subject to license terms that are
 7   
  * available at 'http://www.jbind.org'. The JBind license is like the
 8   
  * 'Apache Software License V 1.1'.
 9   
  */
 10   
 package org.jbind.xml;
 11   
 
 12   
 import java.io.InputStream;
 13   
 import java.net.MalformedURLException;
 14   
 import java.net.URL;
 15   
 import java.util.Iterator;
 16   
 import java.util.Map;
 17   
 import java.util.prefs.Preferences;
 18   
 
 19   
 import javax.xml.transform.URIResolver;
 20   
 
 21   
 import com.sun.resolver.Catalog;
 22   
 import com.sun.resolver.tools.CatalogResolver;
 23   
 
 24   
 import org.jbind.base.Console;
 25   
 import org.jbind.base.Countries;
 26   
 import org.jbind.base.Languages;
 27   
 import org.jbind.util.other.Prefs;
 28   
 import org.jbind.xml.core.bridge.IDataImplFactory;
 29   
 import org.jbind.xml.core.bridge.IRegEx;
 30   
 import org.jbind.xml.core.bridge.IRegExFactory;
 31   
 import org.jbind.xml.core.bridge.IXPathFactory;
 32   
 import org.jbind.xml.facade.XercesRegExFactory;
 33   
 import org.jbind.xml.instance.impl.DataImplFactory;
 34   
 import org.jbind.xml.instance.impl.JaxenXPathFactory;
 35   
 import org.jbind.xml.msg.XmlException;
 36   
 import org.jbind.xml.msg.XmlMessages;
 37   
 import org.jbind.xml.schema.compiler.BehaviourClassCartridge;
 38   
 import org.jbind.xml.schema.compiler.BehaviourInterfaceCartridge;
 39   
 import org.jbind.xml.schema.compiler.DataClassCartridge;
 40   
 import org.jbind.xml.schema.compiler.DataInterfaceCartridge;
 41   
 import org.xml.sax.EntityResolver;
 42   
 
 43   
 /**
 44   
  * Configuration of the XML package. Uses {@link Preferences} for storing the
 45   
  * configuration information. The configuration can be managed using the main
 46   
  * method of this class.
 47   
  * <p>
 48   
  * The configuration information is divided into several branches:
 49   
  * <ul>
 50   
  * <li>schema compiler</li>
 51   
  * <li>validation</li>
 52   
  * </ul>
 53   
  * An example preferences file can be obtained by executing the command:<br>
 54   
  * <code>java org.jbind.xml.Config -reset -export config.xml</code>.<br>
 55   
  */
 56   
 public class PrefsConfig extends Prefs implements IConfig {
 57   
 
 58   
   public static final PrefsConfig instance = new PrefsConfig();
 59   
 
 60   
   /**
 61   
    * Relative node path that is used for storing information for the schema compiler
 62   
    * ({@value}).
 63   
    */
 64   
   public static final String SCHEMA_COMPILER = "schemaCompiler";
 65   
 
 66   
   /**
 67   
    * Relative node path that is used for storing namespace to package mappings
 68   
    * ({@value}).
 69   
    */
 70   
   public static final String N2P_MAPPING = SCHEMA_COMPILER + "/namespaceToPackageMapping";
 71   
 
 72   
   /**
 73   
    * Relative node path that is used for storing cartridges
 74   
    * ({@value}).
 75   
    */
 76   
   public static final String CARTRIDGES = SCHEMA_COMPILER + "/cartridges";
 77   
 
 78   
   /**
 79   
    * Relative node path that is used for storing validation information
 80   
    * ({@value}).
 81   
    */
 82   
   public static final String VALIDATION = "validation";
 83   
 
 84   
   /**
 85   
    * Key for a boolean value in the runtime prefences ({@value}).
 86   
    * The default is <code>true</code>. Iff this entry is <code>true</code> then
 87   
          * user classes are instantiated using the context class loader.
 88   
          * Iff this feature is <code>false</code>
 89   
          * then user classes are loaded using the class loader that loaded the JBind
 90   
          * classes.
 91   
    */
 92   
   public static final String USE_CONTEXT_CLASS_LOADER = "useContextClassLoader";
 93   
 
 94   
   /**
 95   
    * Relative node path that is used for storing validation information
 96   
    * ({@value}).
 97   
    */
 98   
   public static final String RUNTIME = "runtime";
 99   
 
 100   
   /**
 101   
    * Key for a boolean value in the validation prefences ({@value}).
 102   
    * The default is "false". The following features are influenced by this
 103   
    * option:
 104   
    * <ul>
 105   
    * <li>Validate that an all group contains only element declaration or references
 106   
    * with a minOccurs and maxOccurs of 1.</li>
 107   
    * </ul>
 108   
    */
 109   
   public static final String STRICT_SCHEMA_VALIDATION = "strictSchemaValidation";
 110   
 
 111   
   /**
 112   
    * Key for a boolean value in the validation prefences ({@value}).
 113   
    * The default is "false".
 114   
    */
 115   
   public static final String CHECK_COUNTRY_CODE = "checkCountryCode";
 116   
 
 117   
   /**
 118   
    * Key for a boolean value in the validation prefences ({@value}).
 119   
    * The default is "false".
 120   
    */
 121   
   public static final String CHECK_LANGUAGE_CODE = "checkLanguageCode";
 122   
 
 123   
   /**
 124   
    * Relative node path that is used for storing country codes.
 125   
    * The value is: <code>{@value}</code>.
 126   
    */
 127   
   public static final String COUNTRY_CODES = VALIDATION + "/countryCodes";
 128   
 
 129   
   /**
 130   
    * Relative node path that is used for storing language codes.
 131   
    * The value is: <code>{@value}</code>.
 132   
    */
 133   
   public static final String LANGUAGE_CODES = VALIDATION + "/languageCodes";
 134   
 
 135   
   /**
 136   
    * Relative node path that is used for storing information about the configurable
 137   
    * modules ({@value}).
 138   
    */
 139   
   public static final String MODULES = "modules";
 140   
 
 141   
   /**
 142   
    * Key to configure a class name in the modules prefences ({@value}).
 143   
    */
 144   
   public static final String XPATH_FACTORY = "xPathFactory";
 145   
 
 146   
   /**
 147   
    * Key to configure a class name in the modules prefences ({@value}).
 148   
    */
 149   
   public static final String REGEX_FACTORY = "regExFactory";
 150   
 
 151   
   /**
 152   
    * Key to configure a class name in the modules prefences ({@value}).
 153   
    */
 154   
   public static final String DATA_FACTORY = "dataFactory";
 155   
 
 156   
   /**
 157   
    * Key to configure a class name in the modules prefences ({@value}).
 158   
    */
 159   
   public static final String ENTITY_RESOLVER = "entityResolver";
 160   
   public static final String DEFAULT_ENTITY_RESOLVER = "defaultEntityResolver";
 161   
 
 162   
   /**
 163   
    * Relative node path ({@value}) that is used to configure XML catalogs that are used
 164   
    * to resolve publicIds, systemIds, and namespaces.
 165   
    * The preference node contains a map mapping catalog names to their load method
 166   
    * (cf. {@link #LOAD_BY_CLASS_LOADER LOAD_BY_CLASS_LOADER}, {@link #LOAD_BY_URL
 167   
    * LOAD_BY_URL}).
 168   
    */
 169   
   public static final String XML_CATALOGS = "xmlCatalogs";
 170   
 
 171   
   /**
 172   
    * Constant that identifies the load method that uses the
 173   
    * <code>Config.class.getResource(String aResourceName)</code> to access a
 174   
    * resource.
 175   
    */
 176   
   public static final String LOAD_BY_CLASS_LOADER = "loadByClassLoader";
 177   
 
 178   
   /**
 179   
    * Constant that identifies a load method that uses a configured URL.
 180   
    * Relative URLs are resolved relative to the current user home directory.
 181   
    */
 182   
   public static final String LOAD_BY_URL = "loadByUrl";
 183   
 
 184   
   /**
 185   
    * JBind XML catalog. ({@value}).
 186   
    */
 187   
   public static final String JBIND_XML_CATALOG = "/org/jbind/catalog.xml";
 188   
 
 189   
   /**
 190   
    * Application XML catalog. ({@value}).
 191   
    */
 192   
   public static final String APPLICATION_XML_CATALOG = "/catalog.xml";
 193   
 
 194   
   /**
 195   
    * User XML catalog. ({@value}).
 196   
    */
 197   
   public static final String USER_XML_CATALOG = ".catalog.xml";
 198   
 
 199   
   /**
 200   
    * System property that determines if the JBind configuration is initialized ({@value}).
 201   
    * The default value is "true".
 202   
    */
 203   
   public static final String JBIND_INIT_CONFIG = "jBindInitConfig";
 204   
 
 205   
   /**
 206   
    * System property to specify a configuration resource ({@value}). If the specified string
 207   
    * contains the substring &quot;://&quot; then it is used as the URL of the
 208   
    * configuration file. Otherwise the class loader of the Config class is used
 209   
    * to access the resource by its {@link Class#getResourceAsStream getResourceAsStream}
 210   
    * method.
 211   
    */
 212   
   public static final String JBIND_CONFIG = "jBindConfig";
 213   
 
 214   
   /**
 215   
    * System property to control whether the user preference tree or the system
 216   
    * preference tree is used ({@value}). The default is &quot;system&quot;.
 217   
    */
 218   
   public static final String JBIND_PREFERENCE_TREE = "jBindPreferenceTree";
 219   
 
 220   
   private URL myUserHome = null;
 221   
   private CatalogResolver myCatalogResolver = null;
 222   
 
 223   
   private IXPathFactory myXPathFactory;
 224   
   private IRegExFactory myRegExFactory;
 225   
   private IDataImplFactory myDataImplFactory;
 226   
   private EntityResolver myEntityResolver;
 227   
 
 228  3
   private PrefsConfig() {
 229  3
     super("system".equals(System.getProperty(JBIND_PREFERENCE_TREE)));
 230  3
     if (!"false".equals(System.getProperty(JBIND_INIT_CONFIG))) {
 231  3
       String jBindConfig = System.getProperty(JBIND_CONFIG);
 232  3
       if (null != jBindConfig) {
 233  0
         InputStream is = null;
 234  0
         try {
 235  0
           if (jBindConfig.indexOf("://") > 0) {
 236  0
             URL url = new URL(jBindConfig);
 237  0
             is = url.openStream();
 238   
           } else {
 239  0
             is = Config.class.getResourceAsStream(jBindConfig);
 240   
           }
 241  0
           Preferences.importPreferences(is);
 242   
         } catch (Exception e) {
 243  0
           e.printStackTrace();
 244  0
           Console.err("JBind configuration could not be imported - using default");
 245  0
           resetPrefs();
 246   
         }
 247   
       } else {
 248  3
         resetPrefs();
 249   
       }
 250   
     }
 251  3
     String userHome = System.getProperty("user.home");
 252  3
     if (null == userHome) {
 253  0
       userHome = System.getProperty("user.dir");
 254   
     }
 255  3
     if (null != userHome) {
 256  3
       try {
 257  3
         myUserHome = new URL("file:" + userHome + "/");
 258   
       } catch (MalformedURLException e) {
 259  0
         e.printStackTrace();
 260   
       }
 261   
     }
 262  3
     if (null == myUserHome) {
 263  0
       Console.out("user home directory not set - configuration resources with relative URLs may not be found");
 264   
     }
 265  3
     System.getProperties().setProperty("xml.catalog.ignoreMissing", "true");
 266   
 
 267  3
     myCatalogResolver = new CatalogResolver();
 268  3
     String[] catalogs = null;
 269  3
     try {
 270  3
       catalogs = getPrefs(XML_CATALOGS).keys();
 271   
     } catch (Exception e) {
 272  0
       e.printStackTrace();
 273  0
       Console.err("could not access XML catalog preferences");
 274  0
       catalogs = new String[]{ JBIND_XML_CATALOG, APPLICATION_XML_CATALOG };
 275   
     }
 276   
 
 277  3
     for (int i = 0; i < catalogs.length; i++) {
 278  9
       try {
 279  9
         String resourceName = catalogs[i];
 280  9
         String loadMode = getPrefs(XML_CATALOGS).get(resourceName, null);
 281  9
         URL url = getConfigurationResourceUrl(resourceName, loadMode);
 282  9
         if (null == url) {
 283  3
           continue;
 284   
         }
 285  6
         try {
 286  6
           InputStream is = url.openStream();
 287  6
           is.close();
 288   
         } catch (Exception e) {
 289  0
           continue;
 290   
         }
 291  6
         addCatalog(url);
 292   
       } catch (Exception e) {
 293  0
         e.printStackTrace();
 294  0
         Console.err("could not parse catalog: " + catalogs[i]);
 295   
       }
 296   
     }
 297   
 
 298  3
     String xPathFactoryName = getPrefs(MODULES).get(XPATH_FACTORY, null);
 299  3
     if (null != xPathFactoryName) {
 300  3
       try {
 301  3
         Class clazz = Class.forName(xPathFactoryName);
 302  3
         myXPathFactory = (IXPathFactory)clazz.newInstance();
 303   
       } catch (Exception e) {
 304  0
         Console.err(e);
 305  0
         Console.err("Could not instantiate XPathFactory '" + xPathFactoryName + "' - using default.");
 306  0
         Console.err("Use the the class " + Config.class.getName() + " to configure the factory.");
 307   
       }
 308   
     }
 309  3
     if (null == myXPathFactory) {
 310  0
       myXPathFactory = new JaxenXPathFactory();
 311   
     }
 312   
 
 313  3
     String dataFactoryName = getPrefs(MODULES).get(DATA_FACTORY, null);
 314  3
     if (null != dataFactoryName) {
 315  3
       try {
 316  3
         Class clazz = Class.forName(dataFactoryName);
 317  3
         myDataImplFactory = (IDataImplFactory)clazz.newInstance();
 318   
       } catch (Exception e) {
 319  0
         Console.err(e);
 320  0
         Console.err("could not instantiate DataFactory '" + dataFactoryName + "' - using default.");
 321  0
         Console.err("Use the the class " + Config.class.getName() + " to configure the factory.");
 322   
       }
 323   
     }
 324  3
     if (null == myDataImplFactory) {
 325  0
       myDataImplFactory = new DataImplFactory();
 326   
     }
 327   
 
 328  3
     String entityResolverName = getPrefs(MODULES).get(ENTITY_RESOLVER, null);
 329  3
     if ((null != entityResolverName) && !entityResolverName.equals(DEFAULT_ENTITY_RESOLVER)) {
 330  0
       try {
 331  0
         Class clazz = Class.forName(entityResolverName);
 332  0
         myEntityResolver = (EntityResolver)clazz.newInstance();
 333   
       } catch (Exception e) {
 334  0
         Console.err(e);
 335  0
         Console.err("could not instantiate entity resolver '" + entityResolverName + "' - using default.");
 336  0
         Console.err("Use the the class " + Config.class.getName() + " to configure the entity resolver.");
 337   
       }
 338   
     }
 339  3
     if (null == myEntityResolver) {
 340  3
       myEntityResolver = getDefaultEntityResolver();
 341   
     }
 342   
 
 343  3
     String regExFactoryName = getPrefs(MODULES).get(REGEX_FACTORY, null);
 344  3
     if (null != regExFactoryName) {
 345  3
       try {
 346  3
         Class clazz = Class.forName(regExFactoryName);
 347  3
         myRegExFactory = (IRegExFactory)clazz.newInstance();
 348   
       } catch (Exception e) {
 349  0
         Console.err(e);
 350  0
         Console.err("could not instantiate RegExFactory '" + regExFactoryName + "' - using default.");
 351  0
         Console.err("Use the the class " + Config.class.getName() + " to configure the factory.");
 352   
       }
 353   
     }
 354  3
     if (null == myRegExFactory) {
 355  0
       myRegExFactory = new XercesRegExFactory();
 356   
     }
 357  3
     myRegExFactory = new org.jbind.xml.facade.XercesRegExFactory();
 358   
 
 359   
   }
 360   
 
 361  9
   private URL getConfigurationResourceUrl(String aResourceName, String aLoadMode) throws Exception {
 362  9
     URL res = null;
 363  9
     if (LOAD_BY_CLASS_LOADER.equals(aLoadMode)) {
 364  6
       res = Config.class.getResource(aResourceName);
 365  3
     } else if (LOAD_BY_URL.equals(aLoadMode)) {
 366  3
       if (null != myUserHome) {
 367  3
         res = new URL(myUserHome, aResourceName);
 368   
       } else {
 369  0
         res = new URL(aResourceName);
 370   
       }
 371   
     } else {
 372  0
       throw new Exception("unknown load mode: " + aLoadMode);
 373   
     }
 374  9
     return res;
 375   
   }
 376   
 
 377  3
   public EntityResolver getDefaultEntityResolver() {
 378  3
     return myCatalogResolver;
 379   
   }
 380  0
   public URIResolver getUriResolver() {
 381  0
     return myCatalogResolver;
 382   
   }
 383   
 
 384  2
   public boolean checkLanguageCode() {
 385  2
     return getPrefs(VALIDATION).getBoolean(CHECK_LANGUAGE_CODE, false);
 386   
   }
 387  1
   public boolean checkCountryCode() {
 388  1
     return getPrefs(VALIDATION).getBoolean(CHECK_COUNTRY_CODE, false);
 389   
   }
 390  19
   public boolean strictSchemaValidation() {
 391  19
     return getPrefs(VALIDATION).getBoolean(STRICT_SCHEMA_VALIDATION, false);
 392   
   }
 393   
 
 394  0
   public String getCountry(String aCode) {
 395  0
     return getPrefs(COUNTRY_CODES).get(aCode, null);
 396   
   }
 397  0
   public String getLanguage(String aCode) {
 398  0
     return getPrefs(LANGUAGE_CODES).get(aCode, null);
 399   
   }
 400   
 
 401  100
   public String getPackageForNamespace(String aNamespace) {
 402  100
     return getPrefs(N2P_MAPPING).get(aNamespace, null);
 403   
   }
 404   
 
 405  2231
   public String resolveUri(String aUri) throws XmlException {
 406  2231
     try {
 407  2231
       return myCatalogResolver.getCatalog().resolveURI(aUri);
 408   
     } catch (Exception e) {
 409  0
       throw new XmlException(e, XmlMessages.wrappedException(e, null));
 410   
     }
 411   
   }
 412   
 
 413  175
   public IXPathFactory getXPathFactory() {
 414  175
     return myXPathFactory;
 415   
   }
 416   
 
 417  397
   public IDataImplFactory getDataImplFactory() {
 418  397
     return myDataImplFactory;
 419   
   }
 420   
 
 421  397
   public EntityResolver getEntityResolver() {
 422  397
     return myEntityResolver;
 423   
   }
 424   
 
 425  175
   public IRegExFactory getRegExFactory() {
 426  175
     return myRegExFactory;
 427   
   }
 428   
 
 429  79
   public IRegEx createRegEx(String aString) throws Exception {
 430  79
     return myRegExFactory.createRegEx(aString);
 431   
   }
 432   
 
 433  3
   public String[] getCartridgeClasses() throws Exception {
 434  3
     return getPrefs(CARTRIDGES).childrenNames();
 435   
   }
 436   
 
 437  3
   protected void doResetPrefs() {
 438  3
     getPrefs(VALIDATION).putBoolean(CHECK_LANGUAGE_CODE, false);
 439  3
     getPrefs(VALIDATION).putBoolean(CHECK_COUNTRY_CODE, false);
 440  3
     getPrefs(VALIDATION).putBoolean(STRICT_SCHEMA_VALIDATION, false);
 441   
 
 442  3
     getPrefs(RUNTIME).putBoolean(USE_CONTEXT_CLASS_LOADER, false);
 443   
 
 444  3
     getPrefs(N2P_MAPPING).put("http://foo.com", "com.foo");
 445   
 
 446  3
     getPrefs(MODULES).put(XPATH_FACTORY, JaxenXPathFactory.class.getName());
 447  3
     getPrefs(MODULES).put(REGEX_FACTORY, XercesRegExFactory.class.getName());
 448  3
     getPrefs(MODULES).put(DATA_FACTORY, DataImplFactory.class.getName());
 449  3
     getPrefs(MODULES).put(ENTITY_RESOLVER, DEFAULT_ENTITY_RESOLVER);
 450   
 
 451  3
     getPrefs(CARTRIDGES).node(DataClassCartridge.class.getName());
 452  3
     getPrefs(CARTRIDGES).node(DataInterfaceCartridge.class.getName());
 453  3
     getPrefs(CARTRIDGES).node(BehaviourClassCartridge.class.getName());
 454  3
     getPrefs(CARTRIDGES).node(BehaviourInterfaceCartridge.class.getName());
 455   
 
 456  3
     getPrefs(XML_CATALOGS).put(JBIND_XML_CATALOG, LOAD_BY_CLASS_LOADER);
 457  3
     getPrefs(XML_CATALOGS).put(APPLICATION_XML_CATALOG, LOAD_BY_CLASS_LOADER);
 458  3
     getPrefs(XML_CATALOGS).put(USER_XML_CATALOG, LOAD_BY_URL);
 459   
 
 460  3
     for (Iterator i = Languages.ourLanguages.entrySet().iterator();
 461  1830
             i.hasNext(); ) {
 462  1827
       Map.Entry e = (Map.Entry)i.next();
 463  1827
       getPrefs(LANGUAGE_CODES).put((String)e.getKey(), (String)e.getValue());
 464   
     }
 465  3
     for (Iterator i = Countries.ourCountries.entrySet().iterator();
 466  720
             i.hasNext(); ) {
 467  717
       Map.Entry e = (Map.Entry)i.next();
 468  717
       getPrefs(COUNTRY_CODES).put((String)e.getKey(), (String)e.getValue());
 469   
     }
 470   
   }
 471   
 
 472   
   /**
 473   
    * Manages the configuration. For a description of the valid arguments
 474   
    * see the {@link #doMain} method.
 475   
    *
 476   
    * @param anArgs <i>(required)</i>.
 477   
    */
 478  0
   public static void main(String[] anArgs) {
 479  0
     instance.doMain(anArgs);
 480  0
     System.exit(0);
 481   
   }
 482   
 
 483  6
   public void addCatalog(URL aUrl) {
 484  6
     try {
 485  6
       Catalog catalog = myCatalogResolver.getCatalog();
 486  6
       catalog.parseCatalog(aUrl);
 487   
     } catch (Exception e) {
 488  0
       e.printStackTrace();
 489  0
       Console.err("could not add catalog: " + aUrl);
 490   
     }
 491   
   }
 492   
 
 493  241
   public boolean useContextClassLoader() {
 494  241
     return getPrefs(RUNTIME).getBoolean(USE_CONTEXT_CLASS_LOADER, false);
 495   
   }
 496   
 
 497   
 }
 498