| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 1999 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xalan" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 1999, Lotus |
| * Development Corporation., http://www.lotus.com. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| package org.apache.xalan.stree; |
| |
| import java.util.Stack; |
| import java.util.Properties; |
| import java.util.Enumeration; |
| |
| import org.w3c.dom.Node; |
| |
| import org.xml.sax.ContentHandler; |
| |
| import org.apache.xml.dtm.DTM; |
| import org.apache.xml.dtm.DTMManager; |
| import org.apache.xml.utils.DOMBuilder; |
| import org.apache.xml.utils.XMLCharacterRecognizer; |
| import org.apache.xml.utils.BoolStack; |
| import org.apache.xpath.XPathContext; |
| import org.apache.xpath.SourceTreeManager; |
| import org.apache.xalan.transformer.TransformerImpl; |
| import org.apache.xalan.templates.StylesheetRoot; |
| import org.apache.xalan.templates.WhiteSpaceInfo; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.DocumentFragment; |
| |
| import org.xml.sax.Attributes; |
| import org.xml.sax.ext.LexicalHandler; |
| import org.xml.sax.ext.DeclHandler; |
| import org.xml.sax.Locator; |
| import javax.xml.transform.TransformerException; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.DTDHandler; |
| |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerException; |
| import javax.xml.transform.Source; |
| import javax.xml.transform.stream.StreamSource; |
| import javax.xml.transform.sax.TransformerHandler; |
| import javax.xml.transform.Result; |
| import javax.xml.transform.ErrorListener; |
| import javax.xml.transform.dom.DOMSource; |
| |
| |
| /** |
| * This class handles SAX2 parse events to create a source |
| * tree for transformation. |
| */ |
| public class SourceTreeHandler extends org.xml.sax.helpers.DefaultHandler implements TransformerHandler, DeclHandler, DTDHandler |
| { |
| // static int m_idCount = 0; |
| // int m_id; |
| |
| /** |
| * Create a SourceTreeHandler that will start a transformation as |
| * soon as a startDocument occurs. |
| * |
| * @param transformer The transformer this will use to transform a |
| * source tree into a result tree. |
| */ |
| public SourceTreeHandler(TransformerImpl transformer, String baseSystemID) |
| { |
| this(transformer, false, baseSystemID); |
| } |
| |
| /** |
| * Create a SourceTreeHandler that will start a transformation as |
| * soon as a startDocument occurs. |
| * |
| * @param transformer The transformer this will use to transform a |
| * source tree into a result tree. |
| */ |
| public SourceTreeHandler(TransformerImpl transformer, boolean doFragment, |
| String baseSystemID) |
| { |
| // m_id = m_idCount++; |
| m_transformer = transformer; |
| |
| XPathContext xctxt = ((TransformerImpl) transformer).getXPathContext(); |
| |
| xctxt.setDOMHelper(new StreeDOMHelper()); |
| |
| DTMManager mgr = m_transformer.getXPathContext().getDTMManager(); |
| DTM dtm; |
| if(doFragment) |
| { |
| m_root = new DocumentFragmentImpl(1024); |
| m_docFrag = (DocumentFragmentImpl)m_root; |
| } |
| else |
| { |
| m_root = new DocumentImpl(this); |
| } |
| DOMSource ds = new DOMSource(m_root, baseSystemID); |
| dtm = mgr.getDTM(ds, false, transformer, false); |
| |
| m_DTMroot = dtm.getDocument(); |
| |
| m_initedRoot = false; |
| m_shouldCheckWhitespace = |
| transformer.getStylesheet().shouldCheckWhitespace(); |
| } |
| |
| /** |
| * Create a SourceTreeHandler that will start a transformation as |
| * soon as a startDocument occurs. |
| * |
| * @param transformer The transformer this will use to transform a |
| * source tree into a result tree. |
| */ |
| public SourceTreeHandler(TransformerImpl transformer, DTMManager dtm, |
| boolean doFragment) |
| { |
| // m_id = m_idCount++; |
| m_transformer = transformer; |
| |
| XPathContext xctxt = transformer.getXPathContext(); |
| xctxt.setDOMHelper(new StreeDOMHelper()); |
| |
| if(doFragment) |
| { |
| m_root = new DocumentFragmentImpl(1024); |
| m_docFrag = (DocumentFragmentImpl)m_root; |
| } |
| else |
| { |
| m_root = new DocumentImpl(this); |
| } |
| |
| m_initedRoot = false; |
| m_shouldCheckWhitespace = |
| transformer.getStylesheet().shouldCheckWhitespace(); |
| } |
| |
| /** |
| * Create a SourceTreeHandler. |
| */ |
| public SourceTreeHandler() |
| { |
| |
| // if (indexedLookup) |
| // m_root = new IndexedDocImpl(); |
| // else |
| m_root = new DocumentImpl(this); |
| m_initedRoot = false; |
| } |
| |
| /** |
| * The transformer this will use to transform a |
| * source tree into a result tree. |
| */ |
| TransformerImpl m_transformer; |
| |
| /** DOMBuilder object this will use */ |
| private DOMBuilder m_sourceTreeHandler; |
| |
| /** The root of the source document */ |
| private DocImpl m_root; |
| |
| /** The DTM root for the DTM2DOM **/ |
| private int m_DTMroot; |
| |
| /** Get the DTM root for the DTM2DOM **/ |
| public int getDTMRoot() |
| { |
| return m_DTMroot; |
| } |
| |
| /** Set the DTM root for the DTM2DOM **/ |
| public void setDTMRoot(int root) |
| { |
| root = m_DTMroot; |
| } |
| |
| /** If this is non-null, the fragment where the nodes will be added. */ |
| private DocumentFragment m_docFrag; |
| |
| /** No longer used?? */ |
| private boolean m_initedRoot; |
| |
| /** Flag indicating whether we should check whitespaces */ |
| boolean m_shouldCheckWhitespace = false; |
| |
| boolean m_shouldTransformAtEnd = true; |
| |
| public void setShouldTransformAtEnd(boolean b) |
| { |
| m_shouldTransformAtEnd = b; |
| } |
| |
| /** |
| * Get the root document of tree that is being or will be created. |
| * |
| * @return Root document |
| */ |
| public Node getRoot() |
| { |
| return m_root; |
| } |
| |
| /** |
| * Set the root document of tree will be created. |
| * |
| * @param root root document of tree that will be created |
| */ |
| public void setRoot(DocImpl root) |
| { |
| m_root = root; |
| } |
| |
| /** |
| * If an exception was thrown, keep track of it |
| * |
| * |
| * @param e Exception that was thrown |
| */ |
| public void setExceptionThrown(Exception e) |
| { |
| m_root.m_exceptionThrown = e; |
| } |
| |
| /** Source Document */ |
| private Source m_inputSource; |
| |
| /** |
| * Set the Source document |
| * |
| * |
| * @param source source document |
| */ |
| public void setInputSource(Source source) |
| { |
| m_inputSource = source; |
| } |
| |
| /** |
| * Get Source Document. |
| * |
| * |
| * @return source document |
| */ |
| public Source getInputSource() |
| { |
| return m_inputSource; |
| } |
| |
| /** |
| * Implement the setDocumentLocator event. |
| * |
| * @param locator Document locator |
| */ |
| public void setDocumentLocator(Locator locator){} |
| |
| /** |
| * Flag to indicate whether to use multiple threads for the transformation |
| * and the parse. |
| */ |
| private boolean m_useMultiThreading = false; |
| |
| /** |
| * Set whether or not the tree being built should handle |
| * transformation while the parse is still going on. |
| * |
| * @param b Flag to indicate whether to use multiple threads |
| */ |
| public void setUseMultiThreading(boolean b) |
| { |
| m_useMultiThreading = b; |
| } |
| |
| /** |
| * Tell whether or not the tree being built should handle |
| * transformation while the parse is still going on. |
| * |
| * @return Flag to indicate whether to use multiple threads |
| */ |
| public boolean getUseMultiThreading() |
| { |
| return m_useMultiThreading; |
| } |
| |
| /** |
| * Simple count incremented in startDocument and decremented in |
| * endDocument, to make sure this contentHandler isn't being double |
| * entered. |
| */ |
| private int m_entryCount = 0; |
| |
| /** Indicate whether running in Debug mode */ |
| private static final boolean DEBUG = false; |
| |
| /** Flag indicating whether indexed lookup is being used to search the source tree */ |
| private boolean indexedLookup = false; // for now |
| |
| /** |
| * Field to hold the number of tasks on the transform thread |
| * so far waiting for a notify() from the parse thread. |
| */ |
| private int m_eventsCount = 0; |
| |
| /** |
| * Minimum number of waiting tasks before the transform thread |
| * gets a notify() event. |
| */ |
| private int m_maxEventsToNotify = 18; |
| |
| /** |
| * Notify all waiting threads that some events have occured. |
| * Note that we only notify when the predefined number of |
| * have been hit. |
| */ |
| private void notifyWaiters() |
| { |
| |
| if (m_useMultiThreading && (m_eventsCount >= m_maxEventsToNotify)) |
| { |
| Object synchObj = m_root; |
| |
| synchronized (synchObj) |
| { |
| synchObj.notify(); |
| } |
| |
| m_eventsCount = 0; |
| } |
| else |
| m_eventsCount++; |
| } |
| |
| /** |
| * Implement the startDocument event. |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void startDocument() throws org.xml.sax.SAXException |
| { |
| // System.out.println("startDocument: "+m_id); |
| |
| if(m_entryCount != 0) |
| throw new org.xml.sax.SAXException( |
| "startDocument can not be called while within startDocument/endDocument! "+ |
| "Threading problem?"); |
| |
| m_entryCount++; // decremented at the end of endDocument |
| |
| synchronized (m_root) |
| { |
| m_inDTD = false; |
| m_root.setSourceTreeHandler(this); |
| m_root.setUid(1); |
| m_root.setLevel(new Integer(1).shortValue()); |
| m_root.setUseMultiThreading(getUseMultiThreading()); |
| |
| if(null != m_docFrag) |
| { |
| m_sourceTreeHandler = |
| new StreeDOMBuilder(m_root, m_docFrag); |
| } |
| else if (m_root.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) |
| m_sourceTreeHandler = |
| new StreeDOMBuilder(m_root.getOwnerDocument(), (DocumentFragment) m_root); |
| else |
| m_sourceTreeHandler = new StreeDOMBuilder((Document) m_root); |
| |
| pushShouldStripWhitespace(false); |
| m_sourceTreeHandler.startDocument(); |
| } |
| |
| if (m_useMultiThreading && (null != m_transformer)) |
| { |
| if (m_transformer.isParserEventsOnMain()) |
| { |
| // We may need to pass our output properties to the next |
| // transformer. There is a question as to whether or not this should |
| // be done. |
| ContentHandler resultContentHandler = m_transformer.getContentHandler(); |
| if(null != resultContentHandler) |
| { |
| if(resultContentHandler instanceof SourceTreeHandler) |
| { |
| // myProps is a clone of the transformer's output properties. |
| Properties myProps = m_transformer.getOutputProperties(); |
| |
| // Now copy the result content handler keys on top of our keys. |
| SourceTreeHandler resultHandler = (SourceTreeHandler) resultContentHandler; |
| Transformer resultTransformer = resultHandler.getTransformer(); |
| Properties resultProps = resultTransformer.getOutputProperties(); |
| Enumeration myKeys = myProps.keys(); |
| while(myKeys.hasMoreElements()) |
| { |
| Object key = myKeys.nextElement(); |
| |
| // Only add it if it has not been explicitly set. |
| if(null == resultProps.get(key)) |
| { |
| // System.out.println("key: "+key+", value: "+myProps.get(key)); |
| // System.out.println("resultProps.get(key): "+resultProps.get(key)); |
| resultProps.put(key, myProps.get(key)); |
| } |
| } |
| |
| resultTransformer.setOutputProperties(resultProps); |
| |
| } |
| } |
| |
| m_transformer.setSourceTreeDocForThread(m_DTMroot); |
| |
| Thread t = m_transformer.createTransformThread(); |
| |
| m_transformer.setTransformThread(t); |
| |
| int cpriority = Thread.currentThread().getPriority(); |
| |
| t.setPriority(cpriority-1); |
| t.setPriority(cpriority); |
| t.start(); |
| } |
| } |
| |
| notifyWaiters(); |
| } |
| |
| |
| /** |
| * Implement the endDocument event. |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void endDocument() throws org.xml.sax.SAXException |
| { |
| m_eventsCount = m_maxEventsToNotify; |
| |
| // notifyWaiters(); |
| |
| Object synchObj = m_root; |
| |
| synchronized (synchObj) |
| { |
| m_sourceTreeHandler.endDocument(); |
| |
| // System.out.println("endDocument: "+m_id); |
| m_root.setComplete(true); |
| |
| popShouldStripWhitespace(); |
| |
| if (!m_useMultiThreading && (null != m_transformer) && m_shouldTransformAtEnd) |
| { |
| try |
| { |
| m_transformer.transformNode(m_DTMroot); |
| } |
| catch(TransformerException te) |
| { |
| // te.printStackTrace(); |
| throw new org.xml.sax.SAXException(te); |
| } |
| } |
| } |
| |
| m_eventsCount = m_maxEventsToNotify; |
| |
| notifyWaiters(); |
| |
| // printTree(m_root); |
| if (m_useMultiThreading && (null != m_transformer)) |
| { |
| Thread transformThread = m_transformer.getTransformThread(); |
| |
| if (null != transformThread) |
| { |
| try |
| { |
| |
| // This should wait until the transformThread is considered not alive. |
| transformThread.join(); |
| if(!m_transformer.hasTransformThreadErrorCatcher()) |
| { |
| Exception e = m_transformer.getExceptionThrown(); |
| if(null != e) |
| throw new org.xml.sax.SAXException(e); |
| } |
| m_transformer.setTransformThread(null); |
| } |
| catch (InterruptedException ie){} |
| } |
| } |
| m_entryCount--; // incremented at the start of startDocument |
| } |
| |
| /** |
| * Print the tree starting at the specified node. |
| * |
| * |
| * @param n A node in a Document. |
| */ |
| private void printTree(Node n) |
| { |
| |
| System.out.println("node: " + n.getNodeName()); |
| |
| Node child; |
| |
| for (child = n.getFirstChild(); child != null; |
| child = child.getNextSibling()) |
| { |
| printTree(child); |
| } |
| } |
| |
| /** |
| * Implement the startElement event. |
| * |
| * @param ns Namespace of the element |
| * @param localName Local part of the qualified name of the element |
| * @param name Name of the element |
| * @param atts List of attributes associated with the element |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void startElement( |
| String ns, String localName, String name, Attributes atts) |
| throws org.xml.sax.SAXException |
| { |
| if(DEBUG) |
| { |
| System.out.println("SourceTreeHandler - startElement: "+ns+", "+localName+", "+m_root); |
| int n = atts.getLength(); |
| for (int i = 0; i < n; i++) |
| { |
| System.out.println("atts["+i+"]: "+atts.getQName(i)+" = "+atts.getValue(i)); |
| } |
| if(null == ns) |
| { |
| (new RuntimeException(localName+" has a null namespace!")).printStackTrace(); |
| } |
| } |
| |
| synchronized (m_root) |
| { |
| m_shouldStripWhitespaceStack.push(m_shouldStripWS); |
| m_sourceTreeHandler.startElement(ns, localName, name, atts); |
| } |
| |
| notifyWaiters(); |
| } |
| |
| /** |
| * Implement the endElement event. |
| * |
| * @param ns Namespace of the element |
| * @param localName Local part of the qualified name of the element |
| * @param name Name of the element |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void endElement(String ns, String localName, String name) |
| throws org.xml.sax.SAXException |
| { |
| if(DEBUG) |
| { |
| System.out.println("SourceTreeHandler - endElement: "+ns+", "+localName); |
| } |
| |
| synchronized (m_root) |
| { |
| Parent myElement=(Parent)(m_sourceTreeHandler.getCurrentNode()); |
| |
| m_sourceTreeHandler.endElement(ns, localName, name); |
| |
| // Mark as complete only after endElement has had a chance to flush |
| // any pending work (Text nodes in particular) |
| myElement.setComplete(true); |
| |
| m_shouldStripWS = m_shouldStripWhitespaceStack.popAndTop(); |
| |
| } |
| |
| notifyWaiters(); |
| } |
| |
| /** Flag indicating whether we got a CDATA event */ |
| private boolean m_isCData = false; |
| |
| /** |
| * Report the start of a CDATA section. |
| * |
| * <p>The contents of the CDATA section will be reported through |
| * the regular {@link org.xml.sax.ContentHandler#characters |
| * characters} event.</p> |
| * |
| * @throws org.xml.sax.SAXException The application may raise an exception. |
| * @see #endCDATA |
| */ |
| public void startCDATA() throws org.xml.sax.SAXException |
| { |
| m_isCData = true; |
| } |
| |
| /** |
| * Report the end of a CDATA section. |
| * |
| * @throws org.xml.sax.SAXException The application may raise an exception. |
| * @see #startCDATA |
| */ |
| public void endCDATA() throws org.xml.sax.SAXException |
| { |
| m_isCData = false; |
| } |
| |
| /** |
| * Implement the characters event. |
| * |
| * @param ch Character array from the characters event |
| * @param start Start index of characters to process in the array |
| * @param length Number of characters to process in the array |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void characters(char ch[], int start, int length) throws org.xml.sax.SAXException |
| { |
| if(m_inDTD) |
| return; |
| |
| if(DEBUG) |
| { |
| System.out.print("SourceTreeHandler#characters: "); |
| int n = start+length; |
| for (int i = start; i < n; i++) |
| { |
| if(Character.isWhitespace(ch[i])) |
| System.out.print("\\"+((int)ch[i])); |
| else |
| System.out.print(ch[i]); |
| } |
| System.out.println(""); |
| } |
| |
| synchronized (m_root) |
| { |
| // if (m_isCData) |
| // m_sourceTreeHandler.cdata(ch, start, length); |
| // else |
| m_sourceTreeHandler.characters(ch, start, length); |
| } |
| |
| notifyWaiters(); |
| } |
| |
| /** |
| * Implement the characters event. |
| * |
| * @param ch Character array from the characters event |
| * @param start Start index of characters to process in the array |
| * @param length Number of characters to process in the array |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void charactersRaw(char ch[], int start, int length) |
| throws org.xml.sax.SAXException |
| { |
| |
| synchronized (m_root) |
| { |
| m_sourceTreeHandler.charactersRaw(ch, start, length); |
| } |
| |
| notifyWaiters(); |
| } |
| |
| /** |
| * Implement the ignorableWhitespace event. |
| * |
| * @param ch Character array from the characters event |
| * @param start Start index of characters to process in the array |
| * @param length Number of characters to process in the array |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void ignorableWhitespace(char ch[], int start, int length) |
| throws org.xml.sax.SAXException |
| { |
| if(m_inDTD) |
| return; |
| |
| synchronized (m_root) |
| { |
| if (m_shouldStripWS) |
| return; |
| |
| m_sourceTreeHandler.characters(ch, start, length); |
| } |
| |
| notifyWaiters(); |
| } |
| |
| /** |
| * Implement the processingInstruction event. |
| * |
| * @param target Target of PI node |
| * @param data Content of PI node |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void processingInstruction(String target, String data) |
| throws org.xml.sax.SAXException |
| { |
| |
| synchronized (m_root) |
| { |
| m_sourceTreeHandler.processingInstruction(target, data); |
| } |
| |
| notifyWaiters(); |
| } |
| |
| /** |
| * Report an XML comment anywhere in the document. |
| * |
| * <p>This callback will be used for comments inside or outside the |
| * document element, including comments in the external DTD |
| * subset (if read).</p> |
| * |
| * @param ch An array holding the characters in the comment. |
| * @param start The starting position in the array. |
| * @param length The number of characters to use from the array. |
| * @throws org.xml.sax.SAXException The application may raise an exception. |
| */ |
| public void comment(char ch[], int start, int length) throws org.xml.sax.SAXException |
| { |
| if(m_inDTD) |
| return; |
| |
| synchronized (m_root) |
| { |
| m_sourceTreeHandler.comment(ch, start, length); |
| } |
| |
| notifyWaiters(); |
| } |
| |
| /** |
| * Report the beginning of an entity. |
| * |
| * <p>The start and end of the document entity are not reported. |
| * The start and end of the external DTD subset are reported |
| * using the pseudo-name "[dtd]". All other events must be |
| * properly nested within start/end entity events.</p> |
| * |
| * <p>Note that skipped entities will be reported through the |
| * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity} |
| * event, which is part of the ContentHandler interface.</p> |
| * |
| * @param name The name of the entity. If it is a parameter |
| * entity, the name will begin with '%'. |
| * @throws org.xml.sax.SAXException The application may raise an exception. |
| * @see #endEntity |
| * @see org.xml.sax.ext.DeclHandler#internalEntityDecl |
| * @see org.xml.sax.ext.DeclHandler#externalEntityDecl |
| */ |
| public void startEntity(String name) throws org.xml.sax.SAXException |
| { |
| synchronized (m_root) |
| { |
| m_sourceTreeHandler.startEntity(name); |
| } |
| |
| notifyWaiters(); |
| } |
| |
| /** |
| * Report the end of an entity. |
| * |
| * @param name The name of the entity that is ending. |
| * @throws org.xml.sax.SAXException The application may raise an exception. |
| * @see #startEntity |
| */ |
| public void endEntity(String name) throws org.xml.sax.SAXException |
| { |
| |
| synchronized (m_root) |
| { |
| m_sourceTreeHandler.endEntity(name); |
| } |
| |
| notifyWaiters(); |
| } |
| |
| private boolean m_inDTD = false; |
| |
| /** |
| * Report the start of DTD declarations, if any. |
| * |
| * <p>Any declarations are assumed to be in the internal subset |
| * unless otherwise indicated by a {@link #startEntity startEntity} |
| * event.</p> |
| * |
| * @param name The document type name. |
| * @param publicId The declared public identifier for the |
| * external DTD subset, or null if none was declared. |
| * @param systemId The declared system identifier for the |
| * external DTD subset, or null if none was declared. |
| * @throws org.xml.sax.SAXException The application may raise an |
| * exception. |
| * @see #endDTD |
| * @see #startEntity |
| */ |
| public void startDTD(String name, String publicId, String systemId) |
| throws org.xml.sax.SAXException |
| { |
| m_inDTD = true; |
| if (m_root instanceof DocumentImpl) |
| { |
| DocumentImpl doc = ((DocumentImpl)m_root); |
| DocumentTypeImpl dtd = new DocumentTypeImpl(doc, name, publicId, systemId); |
| ((DocumentImpl)m_root).setDoctype(dtd); |
| } |
| } |
| |
| /** |
| * Report the end of DTD declarations. |
| * |
| * @throws org.xml.sax.SAXException The application may raise an exception. |
| * @see #startDTD |
| */ |
| public void endDTD() throws org.xml.sax.SAXException |
| { |
| m_inDTD = false; |
| } |
| |
| /** |
| * Begin the scope of a prefix-URI Namespace mapping. |
| * |
| * <p>The information from this event is not necessary for |
| * normal Namespace processing: the SAX XML reader will |
| * automatically replace prefixes for element and attribute |
| * names when the http://xml.org/sax/features/namespaces |
| * feature is true (the default).</p> |
| * |
| * <p>There are cases, however, when applications need to |
| * use prefixes in character data or in attribute values, |
| * where they cannot safely be expanded automatically; the |
| * start/endPrefixMapping event supplies the information |
| * to the application to expand prefixes in those contexts |
| * itself, if necessary.</p> |
| * |
| * <p>Note that start/endPrefixMapping events are not |
| * guaranteed to be properly nested relative to each-other: |
| * all startPrefixMapping events will occur before the |
| * corresponding startElement event, and all endPrefixMapping |
| * events will occur after the corresponding endElement event, |
| * but their order is not guaranteed.</p> |
| * |
| * @param prefix The Namespace prefix being declared. |
| * @param uri The Namespace URI the prefix is mapped to. |
| * @see #endPrefixMapping |
| * @see #startElement |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void startPrefixMapping(String prefix, String uri) |
| throws org.xml.sax.SAXException |
| { |
| if(DEBUG) |
| System.out.println("SourceTreeHandler - startPrefixMapping("+prefix+", "+uri+");"); |
| |
| synchronized (m_root) |
| { |
| m_sourceTreeHandler.startPrefixMapping(prefix, uri); |
| } |
| } |
| |
| /** |
| * End the scope of a prefix-URI mapping. |
| * |
| * <p>See startPrefixMapping for details. This event will |
| * always occur after the corresponding endElement event, |
| * but the order of endPrefixMapping events is not otherwise |
| * guaranteed.</p> |
| * |
| * @param prefix The prefix that was being mapping. |
| * @see #startPrefixMapping |
| * @see #endElement |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void endPrefixMapping(String prefix) throws org.xml.sax.SAXException |
| { |
| if(DEBUG) |
| System.out.println("SourceTreeHandler - endPrefixMapping("+prefix+");"); |
| |
| m_sourceTreeHandler.endPrefixMapping(prefix); |
| } |
| |
| /** |
| * Receive notification of a skipped entity. |
| * |
| * <p>The Parser will invoke this method once for each entity |
| * skipped. Non-validating processors may skip entities if they |
| * have not seen the declarations (because, for example, the |
| * entity was declared in an external DTD subset). All processors |
| * may skip external entities, depending on the values of the |
| * http://xml.org/sax/features/external-general-entities and the |
| * http://xml.org/sax/features/external-parameter-entities |
| * properties.</p> |
| * |
| * @param name The name of the skipped entity. If it is a |
| * parameter entity, the name will begin with '%'. |
| * |
| * @throws org.xml.sax.SAXException |
| */ |
| public void skippedEntity(String name) throws org.xml.sax.SAXException |
| { |
| } |
| |
| /** Flag indicating whether to strip whitespace nodes */ |
| private boolean m_shouldStripWS = false; |
| |
| /** Stack of flags indicating whether to strip whitespace nodes */ |
| private BoolStack m_shouldStripWhitespaceStack = new BoolStack(); |
| |
| /** |
| * Find out whether or not to strip whispace nodes. |
| * |
| * |
| * @return whether or not to strip whispace nodes. |
| */ |
| boolean getShouldStripWhitespace() |
| { |
| return m_shouldStripWS; |
| } |
| |
| /** |
| * Set whether to strip whitespaces and push in current value of |
| * m_shouldStripWS in m_shouldStripWhitespaceStack. |
| * |
| * @param shouldStrip Flag indicating whether to strip whitespace nodes |
| */ |
| void pushShouldStripWhitespace(boolean shouldStrip) |
| { |
| |
| m_shouldStripWS = shouldStrip; |
| |
| m_shouldStripWhitespaceStack.push(shouldStrip); |
| } |
| |
| /** |
| * Set whether to strip whitespaces at this point by popping out |
| * m_shouldStripWhitespaceStack. |
| * |
| */ |
| void popShouldStripWhitespace() |
| { |
| m_shouldStripWS = m_shouldStripWhitespaceStack.popAndTop(); |
| } |
| |
| /** |
| * Set whether to strip whitespaces and set the top of the stack to |
| * the current value of m_shouldStripWS. |
| * |
| * |
| * @param shouldStrip Flag indicating whether to strip whitespace nodes |
| */ |
| void setShouldStripWhitespace(boolean shouldStrip) |
| { |
| |
| m_shouldStripWS = shouldStrip; |
| |
| m_shouldStripWhitespaceStack.setTop(shouldStrip); |
| } |
| |
| /** |
| * Method setResult allows the user of the TransformerHandler |
| * to set the result of the transform. |
| * |
| * @param result A Result instance, should not be null. |
| * |
| * @throws IllegalArgumentException if result is invalid for some reason. |
| */ |
| public void setResult(Result result) |
| throws IllegalArgumentException |
| { |
| if(null == result) |
| throw new IllegalArgumentException("result should not be null"); |
| try |
| { |
| ContentHandler handler = m_transformer.createResultContentHandler(result); |
| m_transformer.setContentHandler(handler); |
| } |
| catch(TransformerException te) |
| { |
| throw new IllegalArgumentException("result could not be set"); |
| } |
| } |
| |
| /** |
| * Set the base ID (URL or system ID) from where relative |
| * URLs will be resolved. |
| * @param baseID Base URL for the source tree. |
| */ |
| public void setSystemId(String baseID) |
| { |
| m_transformer.setBaseURLOfSource(baseID); |
| |
| XPathContext xctxt = m_transformer.getXPathContext(); |
| SourceTreeManager stm = xctxt.getSourceTreeManager(); |
| |
| m_inputSource = new StreamSource(baseID); |
| |
| stm.putDocumentInCache(m_DTMroot, m_inputSource); |
| } |
| |
| /** |
| * Get the base ID (URI or system ID) from where relative |
| * URLs will be resolved. |
| * @return The systemID that was set with {@link #setSystemId}. |
| */ |
| public String getSystemId() |
| { |
| return m_transformer.getBaseURLOfSource(); |
| } |
| |
| |
| /** |
| * Get the Transformer associated with this handler, which |
| * is needed in order to set parameters and output properties. |
| */ |
| public Transformer getTransformer() |
| { |
| return m_transformer; |
| } |
| |
| /** |
| * Get the Transformer associated with this handler, which |
| * is needed in order to set parameters and output properties. |
| */ |
| TransformerImpl getTransformerImpl() |
| { |
| return m_transformer; |
| } |
| |
| /** |
| * Report an element type declaration. |
| * |
| * <p>The content model will consist of the string "EMPTY", the |
| * string "ANY", or a parenthesised group, optionally followed |
| * by an occurrence indicator. The model will be normalized so |
| * that all whitespace is removed,and will include the enclosing |
| * parentheses.</p> |
| * |
| * @param name The element type name. |
| * @param model The content model as a normalized string. |
| * @throws SAXException The application may raise an exception. |
| */ |
| public void elementDecl (String name, String model) |
| throws org.xml.sax.SAXException |
| { |
| } |
| |
| |
| /** |
| * Report an attribute type declaration. |
| * |
| * <p>Only the effective (first) declaration for an attribute will |
| * be reported. The type will be one of the strings "CDATA", |
| * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY", |
| * "ENTITIES", or "NOTATION", or a parenthesized token group with |
| * the separator "|" and all whitespace removed.</p> |
| * |
| * @param eName The name of the associated element. |
| * @param aName The name of the attribute. |
| * @param type A string representing the attribute type. |
| * @param valueDefault A string representing the attribute default |
| * ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if |
| * none of these applies. |
| * @param value A string representing the attribute's default value, |
| * or null if there is none. |
| * @throws SAXException The application may raise an exception. |
| */ |
| public void attributeDecl (String eName, |
| String aName, |
| String type, |
| String valueDefault, |
| String value) |
| throws org.xml.sax.SAXException |
| { |
| } |
| |
| |
| /** |
| * Report an internal entity declaration. |
| * |
| * <p>Only the effective (first) declaration for each entity |
| * will be reported.</p> |
| * |
| * @param name The name of the entity. If it is a parameter |
| * entity, the name will begin with '%'. |
| * @param value The replacement text of the entity. |
| * @throws SAXException The application may raise an exception. |
| * @see #externalEntityDecl |
| * @see org.xml.sax.DTDHandler#unparsedEntityDecl |
| */ |
| public void internalEntityDecl (String name, String value) |
| throws org.xml.sax.SAXException |
| { |
| } |
| |
| |
| /** |
| * Report a parsed external entity declaration. |
| * |
| * <p>Only the effective (first) declaration for each entity |
| * will be reported.</p> |
| * |
| * @param name The name of the entity. If it is a parameter |
| * entity, the name will begin with '%'. |
| * @param publicId The declared public identifier of the entity, or |
| * null if none was declared. |
| * @param systemId The declared system identifier of the entity. |
| * @throws SAXException The application may raise an exception. |
| * @see #internalEntityDecl |
| * @see org.xml.sax.DTDHandler#unparsedEntityDecl |
| */ |
| public void externalEntityDecl (String name, String publicId, |
| String systemId) |
| throws org.xml.sax.SAXException |
| { |
| } |
| |
| /** |
| * Receive notification of a notation declaration event. |
| * |
| * <p>It is up to the application to record the notation for later |
| * reference, if necessary.</p> |
| * |
| * <p>At least one of publicId and systemId must be non-null. |
| * If a system identifier is present, and it is a URL, the SAX |
| * parser must resolve it fully before passing it to the |
| * application through this event.</p> |
| * |
| * <p>There is no guarantee that the notation declaration will be |
| * reported before any unparsed entities that use it.</p> |
| * |
| * @param name The notation name. |
| * @param publicId The notation's public identifier, or null if |
| * none was given. |
| * @param systemId The notation's system identifier, or null if |
| * none was given. |
| * @throws org.xml.sax.SAXException Any SAX exception, possibly |
| * wrapping another exception. |
| * @see #unparsedEntityDecl |
| * @see org.xml.sax.AttributeList |
| */ |
| public void notationDecl (String name, |
| String publicId, |
| String systemId) |
| throws org.xml.sax.SAXException |
| { |
| } |
| |
| |
| /** |
| * Receive notification of an unparsed entity declaration event. |
| * |
| * <p>Note that the notation name corresponds to a notation |
| * reported by the {@link #notationDecl notationDecl} event. |
| * It is up to the application to record the entity for later |
| * reference, if necessary.</p> |
| * |
| * <p>If the system identifier is a URL, the parser must resolve it |
| * fully before passing it to the application.</p> |
| * |
| * @throws org.xml.sax.SAXException Any SAX exception, possibly |
| * wrapping another exception. |
| * @param name The unparsed entity's name. |
| * @param publicId The entity's public identifier, or null if none |
| * was given. |
| * @param systemId The entity's system identifier. |
| * @param notation name The name of the associated notation. |
| * @see #notationDecl |
| * @see org.xml.sax.AttributeList |
| */ |
| public void unparsedEntityDecl (String name, |
| String publicId, |
| String systemId, |
| String notationName) |
| throws org.xml.sax.SAXException |
| { |
| try |
| { |
| if(null != m_inputSource) |
| systemId = org.apache.xml.utils.SystemIDResolver.getAbsoluteURI(systemId, m_inputSource.getSystemId()); |
| } |
| catch(Exception e) |
| { |
| throw new org.xml.sax.SAXException(e); |
| } |
| EntityImpl entity = new EntityImpl(name, notationName, publicId, systemId); |
| m_root.getDoctype().getEntities().setNamedItem(entity); |
| } |
| |
| } |