1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22package com.sun.org.apache.xalan.internal.xsltc.dom; 23 24import javax.xml.stream.XMLEventReader; 25import javax.xml.stream.XMLStreamReader; 26import javax.xml.transform.Source; 27import javax.xml.transform.dom.DOMSource; 28import javax.xml.transform.sax.SAXSource; 29import javax.xml.transform.stream.StreamSource; 30import javax.xml.transform.stax.StAXSource; 31 32import com.sun.org.apache.xml.internal.dtm.DTM; 33import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase; 34import com.sun.org.apache.xml.internal.dtm.DTMException; 35import com.sun.org.apache.xml.internal.dtm.DTMWSFilter; 36import com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault; 37import com.sun.org.apache.xml.internal.res.XMLErrorResources; 38import com.sun.org.apache.xml.internal.res.XMLMessages; 39import com.sun.org.apache.xml.internal.utils.SystemIDResolver; 40import com.sun.org.apache.xalan.internal.xsltc.trax.DOM2SAX; 41import com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX; 42import com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX; 43 44import org.xml.sax.InputSource; 45import org.xml.sax.SAXNotRecognizedException; 46import org.xml.sax.SAXNotSupportedException; 47import org.xml.sax.XMLReader; 48 49/** 50 * The default implementation for the DTMManager. 51 */ 52public class XSLTCDTMManager extends DTMManagerDefault 53{ 54 55 /** Set this to true if you want a dump of the DTM after creation */ 56 private static final boolean DUMPTREE = false; 57 58 /** Set this to true if you want basic diagnostics */ 59 private static final boolean DEBUG = false; 60 61 /** 62 * Constructor DTMManagerDefault 63 * 64 */ 65 public XSLTCDTMManager() 66 { 67 super(); 68 } 69 70 /** 71 * Obtain a new instance of a <code>DTMManager</code>. 72 * This static method creates a new factory instance. 73 * The current implementation just returns a new XSLTCDTMManager instance. 74 */ 75 public static XSLTCDTMManager newInstance() 76 { 77 return new XSLTCDTMManager(); 78 } 79 80 /** 81 * Creates a new instance of the XSLTC DTM Manager service. 82 * Creates a new instance of the default class 83 * <code>com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager</code>. 84 */ 85 public static XSLTCDTMManager createNewDTMManagerInstance() { 86 return newInstance(); 87 } 88 89 /** 90 * Get an instance of a DTM, loaded with the content from the 91 * specified source. If the unique flag is true, a new instance will 92 * always be returned. Otherwise it is up to the DTMManager to return a 93 * new instance or an instance that it already created and may be being used 94 * by someone else. 95 * (I think more parameters will need to be added for error handling, and 96 * entity resolution). 97 * 98 * @param source the specification of the source object. 99 * @param unique true if the returned DTM must be unique, probably because it 100 * is going to be mutated. 101 * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may 102 * be null. 103 * @param incremental true if the DTM should be built incrementally, if 104 * possible. 105 * @param doIndexing true if the caller considers it worth it to use 106 * indexing schemes. 107 * 108 * @return a non-null DTM reference. 109 */ 110 @Override 111 public DTM getDTM(Source source, boolean unique, 112 DTMWSFilter whiteSpaceFilter, boolean incremental, 113 boolean doIndexing) 114 { 115 return getDTM(source, unique, whiteSpaceFilter, incremental, 116 doIndexing, false, 0, true, false); 117 } 118 119 /** 120 * Get an instance of a DTM, loaded with the content from the 121 * specified source. If the unique flag is true, a new instance will 122 * always be returned. Otherwise it is up to the DTMManager to return a 123 * new instance or an instance that it already created and may be being used 124 * by someone else. 125 * (I think more parameters will need to be added for error handling, and 126 * entity resolution). 127 * 128 * @param source the specification of the source object. 129 * @param unique true if the returned DTM must be unique, probably because it 130 * is going to be mutated. 131 * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may 132 * be null. 133 * @param incremental true if the DTM should be built incrementally, if 134 * possible. 135 * @param doIndexing true if the caller considers it worth it to use 136 * indexing schemes. 137 * @param buildIdIndex true if the id index table should be built. 138 * 139 * @return a non-null DTM reference. 140 */ 141 public DTM getDTM(Source source, boolean unique, 142 DTMWSFilter whiteSpaceFilter, boolean incremental, 143 boolean doIndexing, boolean buildIdIndex) 144 { 145 return getDTM(source, unique, whiteSpaceFilter, incremental, 146 doIndexing, false, 0, buildIdIndex, false); 147 } 148 149 /** 150 * Get an instance of a DTM, loaded with the content from the 151 * specified source. If the unique flag is true, a new instance will 152 * always be returned. Otherwise it is up to the DTMManager to return a 153 * new instance or an instance that it already created and may be being used 154 * by someone else. 155 * (I think more parameters will need to be added for error handling, and 156 * entity resolution). 157 * 158 * @param source the specification of the source object. 159 * @param unique true if the returned DTM must be unique, probably because it 160 * is going to be mutated. 161 * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may 162 * be null. 163 * @param incremental true if the DTM should be built incrementally, if 164 * possible. 165 * @param doIndexing true if the caller considers it worth it to use 166 * indexing schemes. 167 * @param buildIdIndex true if the id index table should be built. 168 * @param newNameTable true if we want to use a separate ExpandedNameTable 169 * for this DTM. 170 * 171 * @return a non-null DTM reference. 172 */ 173 public DTM getDTM(Source source, boolean unique, 174 DTMWSFilter whiteSpaceFilter, boolean incremental, 175 boolean doIndexing, boolean buildIdIndex, 176 boolean newNameTable) 177 { 178 return getDTM(source, unique, whiteSpaceFilter, incremental, 179 doIndexing, false, 0, buildIdIndex, newNameTable); 180 } 181 182 /** 183 * Get an instance of a DTM, loaded with the content from the 184 * specified source. If the unique flag is true, a new instance will 185 * always be returned. Otherwise it is up to the DTMManager to return a 186 * new instance or an instance that it already created and may be being used 187 * by someone else. 188 * (I think more parameters will need to be added for error handling, and 189 * entity resolution). 190 * 191 * @param source the specification of the source object. 192 * @param unique true if the returned DTM must be unique, probably because it 193 * is going to be mutated. 194 * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may 195 * be null. 196 * @param incremental true if the DTM should be built incrementally, if 197 * possible. 198 * @param doIndexing true if the caller considers it worth it to use 199 * indexing schemes. 200 * @param hasUserReader true if <code>source</code> is a 201 * <code>SAXSource</code> object that has an 202 * <code>XMLReader</code>, that was specified by the 203 * user. 204 * @param size Specifies initial size of tables that represent the DTM 205 * @param buildIdIndex true if the id index table should be built. 206 * 207 * @return a non-null DTM reference. 208 */ 209 public DTM getDTM(Source source, boolean unique, 210 DTMWSFilter whiteSpaceFilter, boolean incremental, 211 boolean doIndexing, boolean hasUserReader, int size, 212 boolean buildIdIndex) 213 { 214 return getDTM(source, unique, whiteSpaceFilter, incremental, 215 doIndexing, hasUserReader, size, 216 buildIdIndex, false); 217 } 218 219 /** 220 * Get an instance of a DTM, loaded with the content from the 221 * specified source. If the unique flag is true, a new instance will 222 * always be returned. Otherwise it is up to the DTMManager to return a 223 * new instance or an instance that it already created and may be being used 224 * by someone else. 225 * (I think more parameters will need to be added for error handling, and 226 * entity resolution). 227 * 228 * @param source the specification of the source object. 229 * @param unique true if the returned DTM must be unique, probably because it 230 * is going to be mutated. 231 * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may 232 * be null. 233 * @param incremental true if the DTM should be built incrementally, if 234 * possible. 235 * @param doIndexing true if the caller considers it worth it to use 236 * indexing schemes. 237 * @param hasUserReader true if <code>source</code> is a 238 * <code>SAXSource</code> object that has an 239 * <code>XMLReader</code>, that was specified by the 240 * user. 241 * @param size Specifies initial size of tables that represent the DTM 242 * @param buildIdIndex true if the id index table should be built. 243 * @param newNameTable true if we want to use a separate ExpandedNameTable 244 * for this DTM. 245 * 246 * @return a non-null DTM reference. 247 */ 248 public DTM getDTM(Source source, boolean unique, 249 DTMWSFilter whiteSpaceFilter, boolean incremental, 250 boolean doIndexing, boolean hasUserReader, int size, 251 boolean buildIdIndex, boolean newNameTable) 252 { 253 if(DEBUG && null != source) { 254 System.out.println("Starting "+ 255 (unique ? "UNIQUE" : "shared")+ 256 " source: "+source.getSystemId()); 257 } 258 259 int dtmPos = getFirstFreeDTMID(); 260 int documentID = dtmPos << IDENT_DTM_NODE_BITS; 261 262 if ((null != source) && source instanceof StAXSource) { 263 final StAXSource staxSource = (StAXSource)source; 264 StAXEvent2SAX staxevent2sax = null; 265 StAXStream2SAX staxStream2SAX = null; 266 if (staxSource.getXMLEventReader() != null) { 267 final XMLEventReader xmlEventReader = staxSource.getXMLEventReader(); 268 staxevent2sax = new StAXEvent2SAX(xmlEventReader); 269 } else if (staxSource.getXMLStreamReader() != null) { 270 final XMLStreamReader xmlStreamReader = staxSource.getXMLStreamReader(); 271 staxStream2SAX = new StAXStream2SAX(xmlStreamReader); 272 } 273 274 SAXImpl dtm; 275 276 if (size <= 0) { 277 dtm = new SAXImpl(this, source, documentID, 278 whiteSpaceFilter, null, doIndexing, 279 DTMDefaultBase.DEFAULT_BLOCKSIZE, 280 buildIdIndex, newNameTable); 281 } else { 282 dtm = new SAXImpl(this, source, documentID, 283 whiteSpaceFilter, null, doIndexing, 284 size, buildIdIndex, newNameTable); 285 } 286 287 dtm.setDocumentURI(source.getSystemId()); 288 289 addDTM(dtm, dtmPos, 0); 290 291 try { 292 if (staxevent2sax != null) { 293 staxevent2sax.setContentHandler(dtm); 294 staxevent2sax.parse(); 295 } 296 else if (staxStream2SAX != null) { 297 staxStream2SAX.setContentHandler(dtm); 298 staxStream2SAX.parse(); 299 } 300 301 } 302 catch (RuntimeException re) { 303 throw re; 304 } 305 catch (Exception e) { 306 throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e); 307 } 308 309 return dtm; 310 }else if ((null != source) && source instanceof DOMSource) { 311 final DOMSource domsrc = (DOMSource) source; 312 final org.w3c.dom.Node node = domsrc.getNode(); 313 final DOM2SAX dom2sax = new DOM2SAX(node); 314 315 SAXImpl dtm; 316 317 if (size <= 0) { 318 dtm = new SAXImpl(this, source, documentID, 319 whiteSpaceFilter, null, doIndexing, 320 DTMDefaultBase.DEFAULT_BLOCKSIZE, 321 buildIdIndex, newNameTable); 322 } else { 323 dtm = new SAXImpl(this, source, documentID, 324 whiteSpaceFilter, null, doIndexing, 325 size, buildIdIndex, newNameTable); 326 } 327 328 dtm.setDocumentURI(source.getSystemId()); 329 330 addDTM(dtm, dtmPos, 0); 331 332 dom2sax.setContentHandler(dtm); 333 334 try { 335 dom2sax.parse(); 336 } 337 catch (RuntimeException re) { 338 throw re; 339 } 340 catch (Exception e) { 341 throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e); 342 } 343 344 return dtm; 345 } 346 else 347 { 348 boolean isSAXSource = (null != source) 349 ? (source instanceof SAXSource) : true; 350 boolean isStreamSource = (null != source) 351 ? (source instanceof StreamSource) : false; 352 353 if (isSAXSource || isStreamSource) { 354 XMLReader reader; 355 InputSource xmlSource; 356 357 if (null == source) { 358 xmlSource = null; 359 reader = null; 360 hasUserReader = false; // Make sure the user didn't lie 361 } 362 else { 363 reader = getXMLReader(source); 364 xmlSource = SAXSource.sourceToInputSource(source); 365 366 String urlOfSource = xmlSource.getSystemId(); 367 368 if (null != urlOfSource) { 369 try { 370 urlOfSource = SystemIDResolver.getAbsoluteURI(urlOfSource); 371 } 372 catch (Exception e) { 373 // %REVIEW% Is there a better way to send a warning? 374 System.err.println("Can not absolutize URL: " + urlOfSource); 375 } 376 377 xmlSource.setSystemId(urlOfSource); 378 } 379 } 380 381 // Create the basic SAX2DTM. 382 SAXImpl dtm; 383 if (size <= 0) { 384 dtm = new SAXImpl(this, source, documentID, whiteSpaceFilter, 385 null, doIndexing, 386 DTMDefaultBase.DEFAULT_BLOCKSIZE, 387 buildIdIndex, newNameTable); 388 } else { 389 dtm = new SAXImpl(this, source, documentID, whiteSpaceFilter, 390 null, doIndexing, size, buildIdIndex, newNameTable); 391 } 392 393 // Go ahead and add the DTM to the lookup table. This needs to be 394 // done before any parsing occurs. Note offset 0, since we've just 395 // created a new DTM. 396 addDTM(dtm, dtmPos, 0); 397 398 if (null == reader) { 399 // Then the user will construct it themselves. 400 return dtm; 401 } 402 403 reader.setContentHandler(dtm.getBuilder()); 404 405 if (!hasUserReader || null == reader.getDTDHandler()) { 406 reader.setDTDHandler(dtm); 407 } 408 409 if(!hasUserReader || null == reader.getErrorHandler()) { 410 reader.setErrorHandler(dtm); 411 } 412 413 try { 414 reader.setProperty("http://xml.org/sax/properties/lexical-handler", dtm); 415 } 416 catch (SAXNotRecognizedException e){} 417 catch (SAXNotSupportedException e){} 418 419 try { 420 reader.parse(xmlSource); 421 } 422 catch (RuntimeException re) { 423 throw re; 424 } 425 catch (Exception e) { 426 throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e); 427 } finally { 428 if (!hasUserReader) { 429 releaseXMLReader(reader); 430 } 431 } 432 433 if (DUMPTREE) { 434 System.out.println("Dumping SAX2DOM"); 435 dtm.dumpDTM(System.err); 436 } 437 438 return dtm; 439 } 440 else { 441 // It should have been handled by a derived class or the caller 442 // made a mistake. 443 throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_NOT_SUPPORTED, new Object[]{source})); 444 } 445 } 446 } 447} 448