Source for javax.xml.parsers.DocumentBuilderFactory

   1: /* DocumentBuilderFactory.java -- 
   2:    Copyright (C) 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package javax.xml.parsers;
  39: 
  40: import java.io.BufferedReader;
  41: import java.io.File;
  42: import java.io.FileInputStream;
  43: import java.io.InputStream;
  44: import java.io.InputStreamReader;
  45: import java.io.IOException;
  46: import java.util.Properties;
  47: import javax.xml.validation.Schema;
  48: 
  49: /**
  50:  * Factory for obtaining document builders.
  51:  * Instances of this class are <em>not</em> guaranteed to be thread safe.
  52:  *
  53:  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
  54:  */
  55: public abstract class DocumentBuilderFactory
  56: {
  57: 
  58:   private boolean namespaceAware;
  59:   private boolean validating;
  60:   private boolean ignoringElementContentWhitespace;
  61:   private boolean expandEntityReferences = true;
  62:   private boolean ignoringComments;
  63:   private boolean coalescing;
  64:   private Schema schema;
  65:   private boolean xIncludeAware;
  66: 
  67:   protected DocumentBuilderFactory()
  68:   {
  69:   }
  70: 
  71:   /**
  72:    * Creates a new factory instance.
  73:    * The implementation class to load is the first found in the following
  74:    * locations:
  75:    * <ol>
  76:    * <li>the <code>javax.xml.parsers.DocumentBuilderFactory</code> system
  77:    * property</li>
  78:    * <li>the above named property value in the
  79:    * <code><i>$JAVA_HOME</i>/lib/jaxp.properties</code> file</li>
  80:    * <li>the class name specified in the
  81:    * <code>META-INF/services/javax.xml.parsers.DocumentBuilderFactory</code>
  82:    * system resource</li>
  83:    * <li>the default factory class</li>
  84:    * </ol>
  85:    */
  86:   public static DocumentBuilderFactory newInstance()
  87:   {
  88:     ClassLoader loader = Thread.currentThread().getContextClassLoader();
  89:     if (loader == null)
  90:       {
  91:         loader = DocumentBuilderFactory.class.getClassLoader();
  92:       }
  93:     String className = null;
  94:     int count = 0;
  95:     do
  96:       {
  97:         className = getFactoryClassName(loader, count++);
  98:         if (className != null)
  99:           {
 100:             try
 101:               {
 102:                 Class t = (loader != null) ? loader.loadClass(className) :
 103:                   Class.forName(className);
 104:                 return (DocumentBuilderFactory) t.newInstance();
 105:               }
 106:             catch (ClassNotFoundException e)
 107:               {
 108:                 className = null;
 109:               }
 110:             catch (Exception e)
 111:               {
 112:                 throw new FactoryConfigurationError(e,
 113:                     "error instantiating class " + className);
 114:               } 
 115:           }
 116:       }
 117:     while (className == null && count < 3);
 118:     return new gnu.xml.dom.DomDocumentBuilderFactory();
 119:   }
 120:   
 121:   private static String getFactoryClassName(ClassLoader loader, int attempt)
 122:   {
 123:     final String propertyName = "javax.xml.parsers.DocumentBuilderFactory";
 124:     switch (attempt)
 125:       {
 126:         case 0:
 127:           return System.getProperty(propertyName);
 128:         case 1:
 129:           try
 130:             {
 131:               File file = new File(System.getProperty("java.home"));
 132:               file = new File(file, "lib");
 133:               file = new File(file, "jaxp.properties");
 134:               InputStream in = new FileInputStream(file);
 135:               Properties props = new Properties();
 136:               props.load(in);
 137:               in.close();
 138:               return props.getProperty(propertyName);
 139:             }
 140:           catch (IOException e)
 141:             {
 142:               return null;
 143:             }
 144:         case 2: 
 145:           try
 146:             {
 147:               String serviceKey = "/META-INF/services/" + propertyName;
 148:               InputStream in = (loader != null) ?
 149:                 loader.getResourceAsStream(serviceKey) :
 150:                 DocumentBuilderFactory.class.getResourceAsStream(serviceKey);
 151:               if (in != null)
 152:                 {
 153:                   BufferedReader r =
 154:                     new BufferedReader(new InputStreamReader(in));
 155:                   String ret = r.readLine();
 156:                   r.close();
 157:                   return ret;
 158:                 }
 159:             }
 160:           catch (IOException e)
 161:             {
 162:             }
 163:           return null;
 164:         default:
 165:           return null;
 166:       }
 167:   }
 168: 
 169:   /**
 170:    * Creates a new document builder instance using the currently specified
 171:    * factory configuration.
 172:    * @exception ParserConfigurationException if the specified configuration
 173:    * is not supported
 174:    */
 175:   public abstract DocumentBuilder newDocumentBuilder()
 176:     throws ParserConfigurationException;
 177: 
 178:   /**
 179:    * Sets whether document builders obtained from this factory will be XML
 180:    * Namespace aware.
 181:    */
 182:   public void setNamespaceAware(boolean awareness)
 183:   {
 184:     namespaceAware = awareness;
 185:   }
 186: 
 187:   /**
 188:    * Sets whether document builders obtained from this factory will validate
 189:    * their input.
 190:    */
 191:   public void setValidating(boolean validating)
 192:   {
 193:     this.validating = validating;
 194:   }
 195: 
 196:   /**
 197:    * Sets whether document builders obtained from this factory will
 198:    * eliminate whitespace within elements that have an element-only content
 199:    * model.
 200:    */
 201:   public void setIgnoringElementContentWhitespace(boolean whitespace)
 202:   {
 203:     ignoringElementContentWhitespace = whitespace;
 204:   }
 205: 
 206:   /**
 207:    * Sets whether document builders obtained from this factory will expand
 208:    * entity reference nodes.
 209:    */
 210:   public void setExpandEntityReferences(boolean expandEntityRef)
 211:   {
 212:     expandEntityReferences = expandEntityRef;
 213:   }
 214: 
 215:   /**
 216:    * Sets whether document builders obtained from this factory will discard
 217:    * comment nodes.
 218:    */
 219:   public void setIgnoringComments(boolean ignoreComments)
 220:   {
 221:     ignoringComments = ignoreComments;
 222:   }
 223: 
 224:   /**
 225:    * Sets whether document builders obtained from this factory will convert
 226:    * CDATA sections to text nodes and normalize adjacent text nodes into a
 227:    * single text node.
 228:    */
 229:   public void setCoalescing(boolean coalescing)
 230:   {
 231:     this.coalescing = coalescing;
 232:   }
 233: 
 234:   /**
 235:    * Indicates whether document builders obtained from this factory will be
 236:    * XML Namespace aware.
 237:    */
 238:   public boolean isNamespaceAware()
 239:   {
 240:     return namespaceAware;
 241:   }
 242: 
 243:   /**
 244:    * Indicates whether document builders obtained from this factory will
 245:    * validate their input.
 246:    */
 247:   public boolean isValidating()
 248:   {
 249:     return validating;
 250:   }
 251: 
 252:   /**
 253:    * Indicates whether document builders obtained from this factory will
 254:    * eliminate whitespace within elements that have an element-only content
 255:    * model.
 256:    */
 257:   public boolean isIgnoringElementContentWhitespace()
 258:   {
 259:     return ignoringElementContentWhitespace;
 260:   }
 261: 
 262:   /**
 263:    * Indicates whether document builders obtained from this factory will
 264:    * expand entity reference nodes.
 265:    */
 266:   public boolean isExpandEntityReferences()
 267:   {
 268:     return expandEntityReferences;
 269:   }
 270: 
 271:   /**
 272:    * Indicates whether document builders obtained from this factory will
 273:    * discard comment nodes.
 274:    */
 275:   public boolean isIgnoringComments()
 276:   {
 277:     return ignoringComments;
 278:   }
 279: 
 280:   /**
 281:    * Indicates whether document builders obtained from this factory will
 282:    * convert CDATA sections to text nodes and normalize adjacent text nodes
 283:    * into a single text node.
 284:    */
 285:   public boolean isCoalescing()
 286:   {
 287:     return coalescing;
 288:   }
 289: 
 290:   /**
 291:    * Set the named attribute on the underlying implementation.
 292:    * @param name the name of the attribute
 293:    * @param value the new value
 294:    * @exception IllegalArgumentException if the attribute is not recognized
 295:    */
 296:   public abstract void setAttribute(String name, Object value) 
 297:     throws IllegalArgumentException;
 298: 
 299:   /**
 300:    * Retrieves the named attribute value from the underlying implementation.
 301:    * @param name the name of the attribute
 302:    * @exception IllegalArgumentException if the attribute is not recognized
 303:    */
 304:   public abstract Object getAttribute(String name) 
 305:     throws IllegalArgumentException;
 306: 
 307:   // -- JAXP 1.3 methods --
 308: 
 309:   /**
 310:    * Returns the schema.
 311:    * @see #setSchema
 312:    * @since 1.5
 313:    */
 314:   public Schema getSchema()
 315:   {
 316:     return schema;
 317:   }
 318: 
 319:   /**
 320:    * Sets the schema.
 321:    * @see #getSchema
 322:    * @since 1.5
 323:    */
 324:   public void setSchema(Schema schema)
 325:   {
 326:     this.schema = schema;
 327:   }
 328: 
 329:   /**
 330:    * Indicates whether parsers obtained from this factory will be XInclude
 331:    * aware.
 332:    * @since 1.5
 333:    */
 334:   public boolean isXIncludeAware()
 335:   {
 336:     return xIncludeAware;
 337:   }
 338: 
 339:   /**
 340:    * Sets whether parsers obtained from this factory will be XInclude aware.
 341:    * @since 1.5
 342:    */
 343:   public void setXIncludeAware(boolean state)
 344:   {
 345:     xIncludeAware = state;
 346:   }
 347: 
 348:   /**
 349:    * Sets the value of the specified feature.
 350:    * @param name the feature name (URI)
 351:    * @param value whether to enable the feature or not
 352:    * @exception ParserConfigurationException if the feature is not
 353:    * supported.
 354:    * @since 1.5
 355:    */
 356:   public abstract void setFeature(String name, boolean value)
 357:     throws ParserConfigurationException;
 358: 
 359:   /**
 360:    * Returns the value of the specified feature.
 361:    * @param name the feature name (URI)
 362:    * @exception ParserConfigurationException if the feature is not
 363:    * supported.
 364:    * @since 1.5
 365:    */
 366:   public abstract boolean getFeature(String name)
 367:     throws ParserConfigurationException;
 368:   
 369: }