Source for gnu.xml.dom.JAXPFactory

   1: /* JAXPFactory.java --
   2:    Copyright (C) 2001 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 gnu.xml.dom;
  39: 
  40: import java.io.IOException;
  41: 
  42: import org.w3c.dom.Document;
  43: import org.w3c.dom.DOMImplementation;
  44: 
  45: import org.xml.sax.EntityResolver;
  46: import org.xml.sax.ErrorHandler;
  47: import org.xml.sax.InputSource;
  48: import org.xml.sax.XMLReader;
  49: import org.xml.sax.SAXException;
  50: import org.xml.sax.SAXParseException;
  51: 
  52: import javax.xml.XMLConstants;
  53: import javax.xml.parsers.DocumentBuilder;
  54: import javax.xml.parsers.DocumentBuilderFactory;
  55: import javax.xml.parsers.ParserConfigurationException;
  56: import javax.xml.parsers.SAXParserFactory;
  57: 
  58: 
  59: /**
  60:  * DOM bootstrapping API, for use with JAXP.
  61:  *
  62:  * @see Consumer
  63:  *
  64:  * @author David Brownell
  65:  */
  66: public final class JAXPFactory
  67:   extends DocumentBuilderFactory
  68: {
  69: 
  70:   private static final String   PROPERTY = "http://xml.org/sax/properties/";
  71:   private static final String   FEATURE = "http://xml.org/sax/features/";
  72: 
  73:   private SAXParserFactory      pf;
  74:   private boolean secureProcessing;
  75: 
  76:   /**
  77:    * Default constructor.
  78:    */
  79:   public JAXPFactory()
  80:   {
  81:   }
  82: 
  83:   /**
  84:    * Constructs a JAXP document builder which uses the default
  85:    * JAXP SAX2 parser and the DOM implementation in this package.
  86:    */
  87:   public DocumentBuilder newDocumentBuilder()
  88:     throws ParserConfigurationException
  89:   {
  90:     if (pf == null)
  91:       {
  92:         // Force use of AElfred2 since not all JAXP parsers
  93:         // conform very well to the SAX2 API spec ...
  94:         pf = new gnu.xml.aelfred2.JAXPFactory();
  95:         // pf = SAXParserFactory.newInstance ();
  96:       }
  97: 
  98:     // JAXP default: false
  99:     pf.setValidating(isValidating());
 100: 
 101:     // FIXME:  this namespace setup may cause errors in some
 102:     // conformant SAX2 parsers, which we CAN patch up by
 103:     // splicing a "NSFilter" stage up front ...
 104: 
 105:     // JAXP default: false
 106:     pf.setNamespaceAware(isNamespaceAware());
 107: 
 108:     try
 109:       {
 110:         // undo rude "namespace-prefixes=false" default
 111:         pf.setFeature(FEATURE + "namespace-prefixes", true);
 112: 
 113:         return new JAXPBuilder(pf.newSAXParser().getXMLReader(), this);
 114:       }
 115:     catch (SAXException e)
 116:       {
 117:         String msg = "can't create JAXP DocumentBuilder: " + e.getMessage();
 118:         throw new ParserConfigurationException(msg);
 119:       }
 120:   }
 121: 
 122:   /** There seems to be no useful specification for attribute names */
 123:   public void setAttribute(String name, Object value)
 124:     throws IllegalArgumentException
 125:   {
 126:     if ("http://java.sun.com/xml/jaxp/properties/schemaLanguage".equals(name))
 127:       {
 128:         // TODO
 129:       }
 130:     else
 131:       {
 132:         throw new IllegalArgumentException(name);
 133:       }
 134:   }
 135: 
 136:   /** There seems to be no useful specification for attribute names */
 137:   public Object getAttribute(String name)
 138:     throws IllegalArgumentException
 139:   {
 140:     throw new IllegalArgumentException(name);
 141:   }
 142: 
 143:   public void setFeature(String name, boolean value)
 144:     throws ParserConfigurationException
 145:   {
 146:     if (name == null)
 147:       throw new NullPointerException();
 148:     if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
 149:       {
 150:         secureProcessing = true;
 151:         return;
 152:       }
 153:     throw new ParserConfigurationException(name);
 154:   }
 155: 
 156:   public boolean getFeature(String name)
 157:     throws ParserConfigurationException
 158:   {
 159:     if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
 160:       return secureProcessing;
 161:     throw new ParserConfigurationException(name);
 162:   }
 163: 
 164:   static final class JAXPBuilder
 165:     extends DocumentBuilder
 166:     implements ErrorHandler
 167:   {
 168: 
 169:     private Consumer    consumer;
 170:     private XMLReader   producer;
 171:     private DomImpl             impl;
 172: 
 173:     JAXPBuilder(XMLReader parser, JAXPFactory factory)
 174:       throws ParserConfigurationException
 175:     {
 176:       impl = new DomImpl();
 177: 
 178:       // set up consumer side
 179:       try
 180:         {
 181:           consumer = new Consumer();
 182:         }
 183:       catch (SAXException e)
 184:         {
 185:           throw new ParserConfigurationException(e.getMessage());
 186:         }
 187: 
 188:       // JAXP defaults: true, noise nodes are good (bleech)
 189:       consumer.setHidingReferences(factory.isExpandEntityReferences());
 190:       consumer.setHidingComments(factory.isIgnoringComments());
 191:       consumer.setHidingWhitespace(factory.isIgnoringElementContentWhitespace());
 192:       consumer.setHidingCDATA(factory.isCoalescing());
 193: 
 194:       // set up producer side
 195:       producer = parser;
 196:       producer.setContentHandler(consumer.getContentHandler());
 197:       producer.setDTDHandler(consumer.getDTDHandler());
 198: 
 199:       try
 200:         {
 201:           String        id;
 202: 
 203:           // if validating, report validity errors, and default
 204:           // to treating them as fatal
 205:           if (factory.isValidating ())
 206:             {
 207:               producer.setFeature(FEATURE + "validation", true);
 208:               producer.setErrorHandler(this);
 209:             }
 210: 
 211:           // always save prefix info, maybe do namespace processing
 212:           producer.setFeature(FEATURE + "namespace-prefixes", true);
 213:           producer.setFeature(FEATURE + "namespaces",
 214:                               factory.isNamespaceAware());
 215: 
 216:           // set important handlers
 217:           id = PROPERTY + "lexical-handler";
 218:           producer.setProperty(id, consumer.getProperty(id));
 219: 
 220:           id = PROPERTY + "declaration-handler";
 221:           producer.setProperty(id, consumer.getProperty(id));
 222: 
 223:         }
 224:       catch (SAXException e)
 225:         {
 226:           throw new ParserConfigurationException(e.getMessage());
 227:         }
 228:     }
 229: 
 230:     public Document parse(InputSource source)
 231:       throws SAXException, IOException
 232:     {
 233:       producer.parse(source);
 234:       Document doc = consumer.getDocument();
 235:       // TODO inputEncoding
 236:       doc.setDocumentURI(source.getSystemId());
 237:       return doc;
 238:     }
 239: 
 240:     public boolean isNamespaceAware()
 241:     {
 242:       try
 243:         {
 244:           return producer.getFeature(FEATURE + "namespaces");
 245:         }
 246:       catch (SAXException e)
 247:         {
 248:           // "can't happen"
 249:           throw new RuntimeException(e.getMessage());
 250:         }
 251:     }
 252: 
 253:     public boolean isValidating()
 254:     {
 255:       try
 256:         {
 257:           return producer.getFeature(FEATURE + "validation");
 258:         }
 259:       catch (SAXException e)
 260:         {
 261:           // "can't happen"
 262:           throw new RuntimeException(e.getMessage());
 263:         }
 264:     }
 265: 
 266:     public void setEntityResolver(EntityResolver resolver)
 267:     {
 268:       producer.setEntityResolver(resolver);
 269:     }
 270: 
 271:     public void setErrorHandler(ErrorHandler handler)
 272:     {
 273:       producer.setErrorHandler(handler);
 274:       consumer.setErrorHandler(handler);
 275:     }
 276: 
 277:     public DOMImplementation getDOMImplementation()
 278:     {
 279:       return impl;
 280:     }
 281: 
 282:     public Document newDocument()
 283:     {
 284:       return new DomDocument();
 285:     }
 286: 
 287:     // implementation of error handler that's used when validating
 288:     public void fatalError(SAXParseException e)
 289:       throws SAXException
 290:     {
 291:       throw e;
 292:     }
 293: 
 294:     public void error(SAXParseException e)
 295:       throws SAXException
 296:     {
 297:       throw e;
 298:     }
 299: 
 300:     public void warning(SAXParseException e)
 301:       throws SAXException
 302:     {
 303:       /* ignore */
 304:     }
 305: 
 306:   }
 307: 
 308: }