Source for javax.xml.stream.XMLInputFactory

   1: /* XMLInputFactory.java -- 
   2:    Copyright (C) 2005,2006  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.stream;
  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.io.Reader;
  47: import java.io.Writer;
  48: import java.util.Properties;
  49: import javax.xml.stream.util.XMLEventAllocator;
  50: import javax.xml.transform.Source;
  51: 
  52: /**
  53:  * Factory for creating stream and event readers from various kinds of input
  54:  * source.
  55:  * <h3>Parameters</h3>
  56:  * <table>
  57:  * <tr>
  58:  * <th>Name</th>
  59:  * <th>Description</th>
  60:  * <th>Type</th>
  61:  * <th>Default</th>
  62:  * <th>Required</th>
  63:  * </tr>
  64:  * <tr>
  65:  * <td>javax.xml.stream.isValidating</td>
  66:  * <td>Controls DTD validation</td>
  67:  * <td>Boolean</td>
  68:  * <td>Boolean.FALSE</td>
  69:  * <td>no</td>
  70:  * </tr>
  71:  * <tr>
  72:  * <td>javax.xml.stream.isNamespaceAware</td>
  73:  * <td>Controls namespace processing for XML 1.0</td>
  74:  * <td>Boolean</td>
  75:  * <td>Boolean.TRUE</td>
  76:  * <td>true is required, false is optional</td>
  77:  * </tr>
  78:  * <tr>
  79:  * <td>javax.xml.stream.isCoalescing</td>
  80:  * <td>Controls coalescing (normalization of adjacent character data)</td>
  81:  * <td>Boolean</td>
  82:  * <td>Boolean.FALSE</td>
  83:  * <td>yes</td>
  84:  * </tr>
  85:  * <tr>
  86:  * <td>javax.xml.stream.isReplacingEntityReferences</td>
  87:  * <td>Controls replacement of entity references with their replacement
  88:  * text</td>
  89:  * <td>Boolean</td>
  90:  * <td>Boolean.TRUE</td>
  91:  * <td>yes</td>
  92:  * </tr>
  93:  * <tr>
  94:  * <td>javax.xml.stream.isSupportingExternalEntities</td>
  95:  * <td>Controls whether to resolve external entities</td>
  96:  * <td>Boolean</td>
  97:  * <td>not specified</td>
  98:  * <td>yes</td>
  99:  * </tr>
 100:  * <tr>
 101:  * <td>javax.xml.stream.supportDTD</td>
 102:  * <td>Controls whether to support DTDs</td>
 103:  * <td>Boolean</td>
 104:  * <td>Boolean.TRUE</td>
 105:  * <td>yes</td>
 106:  * </tr>
 107:  * <tr>
 108:  * <td>javax.xml.stream.reporter</td>
 109:  * <td></td>
 110:  * <td>javax.xml.stream.XMLReporter</td>
 111:  * <td></td>
 112:  * <td>yes</td>
 113:  * </tr>
 114:  * <tr>
 115:  * <td>javax.xml.stream.resolver</td>
 116:  * <td></td>
 117:  * <td>javax.xml.stream.XMLResolver</td>
 118:  * <td></td>
 119:  * <td>yes</td>
 120:  * </tr>
 121:  * <tr>
 122:  * <td>javax.xml.stream.allocator</td>
 123:  * <td></td>
 124:  * <td>javax.xml.stream.util.XMLEventAllocator</td>
 125:  * <td></td>
 126:  * <td>yes</td>
 127:  * </tr>
 128:  * </table>
 129:  */
 130: public abstract class XMLInputFactory
 131: {
 132: 
 133:   /**
 134:    * Property used to control namespace support.
 135:    */
 136:   public static final String IS_NAMESPACE_AWARE = 
 137:     "javax.xml.stream.isNamespaceAware";
 138: 
 139:   /**
 140:    * Property used to control DTD validation.
 141:    */
 142:   public static final String IS_VALIDATING = "javax.xml.stream.isValidating";
 143: 
 144:   /**
 145:    * Property used to control whether to coalesce adjacent text events.
 146:    */
 147:   public static final String IS_COALESCING = "javax.xml.stream.isCoalescing";
 148: 
 149:   /**
 150:    * Property used to control whether to replace entity references with
 151:    * their replacement text.
 152:    */
 153:   public static final String IS_REPLACING_ENTITY_REFERENCES =
 154:     "javax.xml.stream.isReplacingEntityReferences";
 155: 
 156:   /**
 157:    * Property used to control whether to resolve external entities.
 158:    */
 159:   public static final String IS_SUPPORTING_EXTERNAL_ENTITIES =
 160:     "javax.xml.stream.isSupportingExternalEntities";
 161: 
 162:   /**
 163:    * Property used to indicate whether to support DTDs.
 164:    */
 165:   public static final String SUPPORT_DTD = "javax.xml.stream.supportDTD";
 166: 
 167:   /**
 168:    * Property used to control the error reporter implementation.
 169:    */
 170:   public static final String REPORTER = "javax.xml.stream.reporter";
 171: 
 172:   /**
 173:    * Property used to control the entity resolver implementation.
 174:    */
 175:   public static final String RESOLVER = "javax.xml.stream.resolver";
 176: 
 177:   /**
 178:    * Property used to control the event allocator implementation.
 179:    */
 180:   public static final String ALLOCATOR = "javax.xml.stream.allocator";
 181: 
 182:   protected XMLInputFactory()
 183:   {
 184:   }
 185: 
 186:   /**
 187:    * Creates a new factory instance.
 188:    * @see #newInstance(String,ClassLoader)
 189:    */
 190:   public static XMLInputFactory newInstance()
 191:     throws FactoryConfigurationError
 192:   {
 193:     return newInstance(null, null);
 194:   }
 195: 
 196:   /**
 197:    * Creates a new factory instance.
 198:    * The implementation class to load is the first found in the following
 199:    * locations:
 200:    * <ol>
 201:    * <li>the <code>javax.xml.stream.XMLInputFactory</code> system
 202:    * property</li>
 203:    * <li>the above named property value in the
 204:    * <code><i>$JAVA_HOME</i>/lib/stax.properties</code> file</li>
 205:    * <li>the class name specified in the
 206:    * <code>META-INF/services/javax.xml.stream.XMLInputFactory</code>
 207:    * system resource</li>
 208:    * <li>the default factory class</li>
 209:    * </ol>
 210:    */
 211:   public static XMLInputFactory newInstance(String factoryId,
 212:                                             ClassLoader classLoader)
 213:     throws FactoryConfigurationError
 214:   {
 215:     ClassLoader loader = classLoader;
 216:     if (loader == null)
 217:       {
 218:         loader = Thread.currentThread().getContextClassLoader();
 219:       }
 220:     if (loader == null)
 221:       {
 222:         loader = XMLInputFactory.class.getClassLoader();
 223:       }
 224:     String className = null;
 225:     int count = 0;
 226:     do
 227:       {
 228:         className = getFactoryClassName(loader, count++);
 229:         if (className != null)
 230:           {
 231:             try
 232:               {
 233:                 Class t = (loader != null) ? loader.loadClass(className) :
 234:                   Class.forName(className);
 235:                 return (XMLInputFactory) t.newInstance();
 236:               }
 237:             catch (ClassNotFoundException e)
 238:               {
 239:                 className = null;
 240:               }
 241:             catch (Exception e)
 242:               {
 243:                 throw new FactoryConfigurationError(e,
 244:                      "error instantiating class " + className);
 245:               }
 246:           }
 247:       }
 248:     while (className == null && count < 3);
 249:     return new gnu.xml.stream.XMLInputFactoryImpl();
 250:   }
 251: 
 252:   private static String getFactoryClassName(ClassLoader loader, int attempt)
 253:   {
 254:     final String propertyName = "javax.xml.stream.XMLInputFactory";
 255:     switch (attempt)
 256:       {
 257:         case 0:
 258:           return System.getProperty(propertyName);
 259:         case 1:
 260:           try
 261:             {
 262:               File file = new File(System.getProperty("java.home"));
 263:               file = new File(file, "lib");
 264:               file = new File(file, "stax.properties");
 265:               InputStream in = new FileInputStream(file);
 266:               Properties props = new Properties();
 267:               props.load(in);
 268:               in.close();
 269:               return props.getProperty(propertyName);
 270:             }
 271:           catch (IOException e)
 272:             {
 273:               return null;
 274:             }
 275:         case 2:
 276:           try
 277:             {
 278:               String serviceKey = "/META-INF/services/" + propertyName;
 279:               InputStream in = (loader != null) ?
 280:                  loader.getResourceAsStream(serviceKey) :
 281:                 XMLInputFactory.class.getResourceAsStream(serviceKey);
 282:               if (in != null)
 283:                 {
 284:                   BufferedReader r =
 285:                      new BufferedReader(new InputStreamReader(in));
 286:                   String ret = r.readLine();
 287:                   r.close();
 288:                   return ret;
 289:                 }
 290:             }
 291:           catch (IOException e)
 292:             {
 293:             }
 294:           return null;
 295:         default:
 296:           return null;
 297:       }
 298:   }
 299: 
 300:   /**
 301:    * Creates a new stream reader.
 302:    */
 303:   public abstract XMLStreamReader createXMLStreamReader(Reader reader)
 304:     throws XMLStreamException;
 305: 
 306:   /**
 307:    * Creates a new stream reader.
 308:    */
 309:   public abstract XMLStreamReader createXMLStreamReader(Source source)
 310:     throws XMLStreamException;
 311: 
 312:   /**
 313:    * Creates a new stream reader.
 314:    */
 315:   public abstract XMLStreamReader createXMLStreamReader(InputStream stream)
 316:     throws XMLStreamException;
 317: 
 318:   /**
 319:    * Creates a new stream reader.
 320:    */
 321:   public abstract XMLStreamReader createXMLStreamReader(InputStream stream,
 322:                                                         String encoding)
 323:     throws XMLStreamException;
 324: 
 325:   /**
 326:    * Creates a new stream reader.
 327:    */
 328:   public abstract XMLStreamReader createXMLStreamReader(String systemId,
 329:                                                         InputStream stream)
 330:     throws XMLStreamException;
 331: 
 332:   /**
 333:    * Creates a new stream reader.
 334:    */
 335:   public abstract XMLStreamReader createXMLStreamReader(String systemId,
 336:                                                         Reader reader)
 337:     throws XMLStreamException;
 338: 
 339:   /**
 340:    * Creates a new event reader.
 341:    */
 342:   public abstract XMLEventReader createXMLEventReader(Reader reader)
 343:     throws XMLStreamException;
 344: 
 345:   /**
 346:    * Creates a new event reader.
 347:    */
 348:   public abstract XMLEventReader createXMLEventReader(String systemId,
 349:                                                       Reader reader)
 350:     throws XMLStreamException;
 351:   
 352:   /**
 353:    * Creates a new event reader.
 354:    */
 355:   public abstract XMLEventReader createXMLEventReader(XMLStreamReader reader)
 356:     throws XMLStreamException;
 357: 
 358:   /**
 359:    * Creates a new event reader.
 360:    */
 361:   public abstract XMLEventReader createXMLEventReader(Source source)
 362:     throws XMLStreamException;
 363: 
 364:   /**
 365:    * Creates a new event reader.
 366:    */
 367:   public abstract XMLEventReader createXMLEventReader(InputStream stream)
 368:     throws XMLStreamException;
 369: 
 370:   /**
 371:    * Creates a new event reader.
 372:    */
 373:   public abstract XMLEventReader createXMLEventReader(InputStream stream,
 374:                                                       String encoding)
 375:     throws XMLStreamException;
 376: 
 377:   /**
 378:    * Creates a new event reader.
 379:    */
 380:   public abstract XMLEventReader createXMLEventReader(String systemId,
 381:                                                       InputStream stream)
 382:     throws XMLStreamException;
 383: 
 384:   /**
 385:    * Create a new filtered reader.
 386:    */
 387:   public abstract XMLStreamReader createFilteredReader(XMLStreamReader reader,
 388:                                                        StreamFilter filter)
 389:     throws XMLStreamException;
 390: 
 391:   /**
 392:    * Create a new filtered reader.
 393:    */
 394:   public abstract XMLEventReader createFilteredReader(XMLEventReader reader,
 395:                                                       EventFilter filter)
 396:     throws XMLStreamException;
 397: 
 398:   /**
 399:    * Returns the entity resolver.
 400:    */
 401:   public abstract XMLResolver getXMLResolver();
 402: 
 403:   /**
 404:    * Sets the entity resolver.
 405:    */
 406:   public abstract void setXMLResolver(XMLResolver resolver);
 407: 
 408:   /**
 409:    * Returns the error reporter.
 410:    */
 411:   public abstract XMLReporter getXMLReporter();
 412: 
 413:   /**
 414:    * Sets the error reporter.
 415:    */
 416:   public abstract void setXMLReporter(XMLReporter reporter);
 417: 
 418:   /**
 419:    * Sets the implementation-specific property of the given name.
 420:    * @exception IllegalArgumentException if the property is not supported
 421:    */
 422:   public abstract void setProperty(String name, Object value)
 423:     throws IllegalArgumentException;
 424: 
 425:   /**
 426:    * Returns the implementation-specific property of the given name.
 427:    * @exception IllegalArgumentException if the property is not supported
 428:    */
 429:   public abstract Object getProperty(String name)
 430:     throws IllegalArgumentException;
 431: 
 432:   /**
 433:    * Indicates whether the specified property is supported.
 434:    */
 435:   public abstract boolean isPropertySupported(String name);
 436: 
 437:   /**
 438:    * Sets the event allocator.
 439:    */
 440:   public abstract void setEventAllocator(XMLEventAllocator allocator);
 441: 
 442:   /**
 443:    * Returns the event allocator.
 444:    */
 445:   public abstract XMLEventAllocator getEventAllocator();
 446: 
 447: }