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