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