Source Code Cross Referenced for XMLDTDScannerImpl.java in  » 6.0-JDK-Modules » sjsxp » com » sun » xml » stream » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » sjsxp » com.sun.xml.stream 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: XMLDTDScannerImpl.java,v 1.4 2006/11/29 22:01:31 spericas Exp $
0003:         */
0004:
0005:        /*
0006:         * The contents of this file are subject to the terms
0007:         * of the Common Development and Distribution License
0008:         * (the License).  You may not use this file except in
0009:         * compliance with the License.
0010:         * 
0011:         * You can obtain a copy of the license at
0012:         * https://glassfish.dev.java.net/public/CDDLv1.0.html.
0013:         * See the License for the specific language governing
0014:         * permissions and limitations under the License.
0015:         * 
0016:         * When distributing Covered Code, include this CDDL
0017:         * Header Notice in each file and include the License file
0018:         * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
0019:         * If applicable, add the following below the CDDL Header,
0020:         * with the fields enclosed by brackets [] replaced by
0021:         * you own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         * 
0024:         * [Name of File] [ver.__] [Date]
0025:         * 
0026:         * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
0027:         */
0028:
0029:        /*
0030:         * The Apache Software License, Version 1.1
0031:         *
0032:         *
0033:         * Copyright (c) 1999-2003 The Apache Software Foundation.
0034:         * All rights reserved.
0035:         *
0036:         * Redistribution and use in source and binary forms, with or without
0037:         * modification, are permitted provided that the following conditions
0038:         * are met:
0039:         *
0040:         * 1. Redistributions of source code must retain the above copyright
0041:         *    notice, this list of conditions and the following disclaimer.
0042:         *
0043:         * 2. Redistributions in binary form must reproduce the above copyright
0044:         *    notice, this list of conditions and the following disclaimer in
0045:         *    the documentation and/or other materials provided with the
0046:         *    distribution.
0047:         *
0048:         * 3. The end-user documentation included with the redistribution,
0049:         *    if any, must include the following acknowledgment:
0050:         *       "This product includes software developed by the
0051:         *        Apache Software Foundation (http://www.apache.org/)."
0052:         *    Alternately, this acknowledgment may appear in the software itself,
0053:         *    if and wherever such third-party acknowledgments normally appear.
0054:         *
0055:         * 4. The names "Xerces" and "Apache Software Foundation" must
0056:         *    not be used to endorse or promote products derived from this
0057:         *    software without prior written permission. For written
0058:         *    permission, please contact apache@apache.org.
0059:         *
0060:         * 5. Products derived from this software may not be called "Apache",
0061:         *    nor may "Apache" appear in their name, without prior written
0062:         *    permission of the Apache Software Foundation.
0063:         *
0064:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0065:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0066:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0067:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0068:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0069:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0070:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0071:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0072:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0073:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0074:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0075:         * SUCH DAMAGE.
0076:         * ====================================================================
0077:         *
0078:         * This software consists of voluntary contributions made by many
0079:         * individuals on behalf of the Apache Software Foundation and was
0080:         * originally based on software copyright (c) 1999, International
0081:         * Business Machines, Inc., http://www.apache.org.  For more
0082:         * information on the Apache Software Foundation, please see
0083:         * <http://www.apache.org/>.
0084:         */
0085:
0086:        package com.sun.xml.stream;
0087:
0088:        import com.sun.xml.stream.dtd.nonvalidating.DTDGrammar;
0089:        import java.io.IOException;
0090:
0091:        import com.sun.xml.stream.xerces.impl.msg.XMLMessageFormatter;
0092:
0093:        import com.sun.xml.stream.xerces.util.SymbolTable;
0094:        import com.sun.xml.stream.xerces.util.XMLAttributesImpl;
0095:        import com.sun.xml.stream.xerces.util.XMLChar;
0096:        import com.sun.xml.stream.xerces.util.XMLStringBuffer;
0097:
0098:        import com.sun.xml.stream.xerces.xni.XMLDTDContentModelHandler;
0099:        import com.sun.xml.stream.xerces.xni.XMLDTDHandler;
0100:        import com.sun.xml.stream.xerces.xni.XMLResourceIdentifier;
0101:        import com.sun.xml.stream.xerces.xni.XMLString;
0102:        import com.sun.xml.stream.xerces.xni.XNIException;
0103:        import com.sun.xml.stream.xerces.xni.parser.XMLComponent;
0104:        import com.sun.xml.stream.xerces.xni.parser.XMLComponentManager;
0105:        import com.sun.xml.stream.xerces.xni.parser.XMLConfigurationException;
0106:        import com.sun.xml.stream.xerces.xni.parser.XMLDTDScanner;
0107:        import com.sun.xml.stream.xerces.xni.parser.XMLInputSource;
0108:
0109:        /**
0110:         * This class is responsible for scanning the declarations found
0111:         * in the internal and external subsets of a DTD in an XML document.
0112:         * The scanner acts as the sources for the DTD information which is
0113:         * communicated to the DTD handlers.
0114:         * <p>
0115:         * This component requires the following features and properties from the
0116:         * component manager that uses it:
0117:         * <ul>
0118:         *  <li>http://xml.org/sax/features/validation</li>
0119:         *  <li>http://apache.org/xml/features/scanner/notify-char-refs</li>
0120:         *  <li>http://apache.org/xml/properties/internal/symbol-table</li>
0121:         *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
0122:         *  <li>http://apache.org/xml/properties/internal/entity-manager</li>
0123:         * </ul>
0124:         *
0125:         * @author Arnaud  Le Hors, IBM
0126:         * @author Andy Clark, IBM
0127:         * @author Glenn Marcy, IBM
0128:         * @author Eric Ye, IBM
0129:         * @author Sunitha Reddy, Sun Microsystems
0130:         *
0131:         * @version $Id: XMLDTDScannerImpl.java,v 1.4 2006/11/29 22:01:31 spericas Exp $
0132:         */
0133:        public class XMLDTDScannerImpl extends XMLScanner implements 
0134:                XMLDTDScanner, XMLComponent, XMLEntityHandler {
0135:
0136:            //
0137:            // Constants
0138:            //
0139:
0140:            // scanner states
0141:
0142:            /** Scanner state: end of input. */
0143:            protected static final int SCANNER_STATE_END_OF_INPUT = 0;
0144:
0145:            /** Scanner state: text declaration. */
0146:            protected static final int SCANNER_STATE_TEXT_DECL = 1;
0147:
0148:            /** Scanner state: markup declaration. */
0149:            protected static final int SCANNER_STATE_MARKUP_DECL = 2;
0150:
0151:            // recognized features and properties
0152:
0153:            /** Recognized features. */
0154:            private static final String[] RECOGNIZED_FEATURES = { VALIDATION,
0155:                    NOTIFY_CHAR_REFS, };
0156:
0157:            /** Feature defaults. */
0158:            private static final Boolean[] FEATURE_DEFAULTS = { null,
0159:                    Boolean.FALSE, };
0160:
0161:            /** Recognized properties. */
0162:            private static final String[] RECOGNIZED_PROPERTIES = {
0163:                    SYMBOL_TABLE, ERROR_REPORTER, ENTITY_MANAGER, };
0164:
0165:            /** Property defaults. */
0166:            private static final Object[] PROPERTY_DEFAULTS = { null, null,
0167:                    null, };
0168:
0169:            // debugging
0170:
0171:            /** Debug scanner state. */
0172:            private static final boolean DEBUG_SCANNER_STATE = false;
0173:
0174:            //
0175:            // Data
0176:            //
0177:
0178:            // handlers
0179:
0180:            /** DTD handler. */
0181:            public XMLDTDHandler fDTDHandler = null;
0182:            //new com.sun.xml.stream.dtd.XMLDTDProcessor();
0183:
0184:            /** DTD content model handler. */
0185:            protected XMLDTDContentModelHandler fDTDContentModelHandler;
0186:
0187:            // state
0188:
0189:            /** Scanner state. */
0190:            protected int fScannerState;
0191:
0192:            /** Standalone. */
0193:            protected boolean fStandalone;
0194:
0195:            /** Seen external DTD. */
0196:            protected boolean fSeenExternalDTD;
0197:
0198:            /** Seen external parameter entity. */
0199:            protected boolean fSeenExternalPE;
0200:
0201:            // private data
0202:
0203:            /** Start DTD called. */
0204:            private boolean fStartDTDCalled;
0205:
0206:            /** Default attribute */
0207:            private XMLAttributesImpl fAttributes = new XMLAttributesImpl();
0208:
0209:            /**
0210:             * Stack of content operators (either '|' or ',') in children
0211:             * content.
0212:             */
0213:            private int[] fContentStack = new int[5];
0214:
0215:            /** Size of content stack. */
0216:            private int fContentDepth;
0217:
0218:            /** Parameter entity stack to check well-formedness. */
0219:            private int[] fPEStack = new int[5];
0220:
0221:            /** Parameter entity stack to report start/end entity calls. */
0222:            private boolean[] fPEReport = new boolean[5];
0223:
0224:            /** Number of opened parameter entities. */
0225:            private int fPEDepth;
0226:
0227:            /** Markup depth. */
0228:            private int fMarkUpDepth;
0229:
0230:            /** Number of opened external entities. */
0231:            private int fExtEntityDepth;
0232:
0233:            /** Number of opened include sections. */
0234:            private int fIncludeSectDepth;
0235:
0236:            // temporary variables
0237:
0238:            /** Array of 3 strings. */
0239:            private String[] fStrings = new String[3];
0240:
0241:            /** String. */
0242:            private XMLString fString = new XMLString();
0243:
0244:            /** String buffer. */
0245:            private XMLStringBuffer fStringBuffer = new XMLStringBuffer();
0246:
0247:            /** String buffer. */
0248:            private XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();
0249:
0250:            /** Literal text. */
0251:            private XMLString fLiteral = new XMLString();
0252:
0253:            /** Literal text. */
0254:            private XMLString fLiteral2 = new XMLString();
0255:
0256:            /** Enumeration values. */
0257:            private String[] fEnumeration = new String[5];
0258:
0259:            /** Enumeration values count. */
0260:            private int fEnumerationCount;
0261:
0262:            /** Ignore conditional section buffer. */
0263:            private XMLStringBuffer fIgnoreConditionalBuffer = new XMLStringBuffer(
0264:                    128);
0265:
0266:            /** Object contains grammar information for a non-validaing parser. */
0267:            DTDGrammar nvGrammarInfo = null;
0268:
0269:            boolean nonValidatingMode = true;
0270:
0271:            //
0272:            // Constructors
0273:            //
0274:
0275:            /** Default constructor. */
0276:            public XMLDTDScannerImpl() {
0277:            } // <init>()
0278:
0279:            /** Constructor for he use of non-XMLComponentManagers. */
0280:            public XMLDTDScannerImpl(SymbolTable symbolTable,
0281:                    XMLErrorReporter errorReporter,
0282:                    XMLEntityManager entityManager) {
0283:                fSymbolTable = symbolTable;
0284:                fErrorReporter = errorReporter;
0285:                fEntityManager = entityManager;
0286:                //entityManager.setProperty(SYMBOL_TABLE, fSymbolTable);
0287:            }
0288:
0289:            //
0290:            // XMLDTDScanner methods
0291:            //
0292:
0293:            /**
0294:             * Sets the input source.
0295:             *
0296:             * @param inputSource The input source or null.
0297:             *
0298:             * @throws IOException Thrown on i/o error.
0299:             */
0300:            public void setInputSource(XMLInputSource inputSource)
0301:                    throws IOException {
0302:                if (inputSource == null) {
0303:                    // no system id was available
0304:                    if (fDTDHandler != null) {
0305:                        fDTDHandler.startDTD(null, null);
0306:                        fDTDHandler.endDTD(null);
0307:                    }
0308:                    if (nonValidatingMode) {
0309:                        nvGrammarInfo.startDTD(null, null);
0310:                        nvGrammarInfo.endDTD(null);
0311:                    }
0312:                    return;
0313:                }
0314:                fEntityManager.setEntityHandler(this );
0315:                fEntityManager.startDTDEntity(inputSource);
0316:            } // setInputSource(XMLInputSource)
0317:
0318:            /**
0319:             * Scans the external subset of the document.
0320:             *
0321:             * @param complete True if the scanner should scan the document
0322:             *                 completely, pushing all events to the registered
0323:             *                 document handler. A value of false indicates that
0324:             *                 that the scanner should only scan the next portion
0325:             *                 of the document and return. A scanner instance is
0326:             *                 permitted to completely scan a document if it does
0327:             *                 not support this "pull" scanning model.
0328:             *
0329:             * @return True if there is more to scan, false otherwise.
0330:             */
0331:            public boolean scanDTDExternalSubset(boolean complete)
0332:                    throws IOException, XNIException {
0333:
0334:                fEntityManager.setEntityHandler(this );
0335:                if (fScannerState == SCANNER_STATE_TEXT_DECL) {
0336:                    fSeenExternalDTD = true;
0337:                    boolean textDecl = scanTextDecl();
0338:                    if (fScannerState == SCANNER_STATE_END_OF_INPUT) {
0339:                        return false;
0340:                    } else {
0341:                        // next state is markup decls regardless of whether there
0342:                        // is a TextDecl or not
0343:                        setScannerState(SCANNER_STATE_MARKUP_DECL);
0344:                        if (textDecl && !complete) {
0345:                            return true;
0346:                        }
0347:                    }
0348:                }
0349:                // keep dispatching "events"
0350:                do {
0351:                    if (!scanDecls(complete)) {
0352:                        return false;
0353:                    }
0354:                } while (complete);
0355:
0356:                // return that there is more to scan
0357:                return true;
0358:
0359:            } // scanDTDExternalSubset(boolean):boolean
0360:
0361:            /**
0362:             * Scans the internal subset of the document.
0363:             *
0364:             * @param complete True if the scanner should scan the document
0365:             *                 completely, pushing all events to the registered
0366:             *                 document handler. A value of false indicates that
0367:             *                 that the scanner should only scan the next portion
0368:             *                 of the document and return. A scanner instance is
0369:             *                 permitted to completely scan a document if it does
0370:             *                 not support this "pull" scanning model.
0371:             * @param standalone True if the document was specified as standalone.
0372:             *                   This value is important for verifying certain
0373:             *                   well-formedness constraints.
0374:             * @param hasExternalDTD True if the document has an external DTD.
0375:             *                       This allows the scanner to properly notify
0376:             *                       the handler of the end of the DTD in the
0377:             *                       absence of an external subset.
0378:             *
0379:             * @return True if there is more to scan, false otherwise.
0380:             */
0381:            public boolean scanDTDInternalSubset(boolean complete,
0382:                    boolean standalone, boolean hasExternalSubset)
0383:                    throws IOException, XNIException {
0384:                // reset entity scanner
0385:                //Venu check
0386:                fEntityScanner = (XMLEntityReaderImpl) fEntityManager
0387:                        .getEntityReader();
0388:                fEntityManager.setEntityHandler(this );
0389:                fStandalone = standalone;
0390:                //System.out.println("state"+fScannerState);
0391:                if (fScannerState == SCANNER_STATE_TEXT_DECL) {
0392:                    // call handler
0393:                    if (fDTDHandler != null) {
0394:                        fDTDHandler.startDTD(fEntityScanner, null);
0395:                        fStartDTDCalled = true;
0396:                    }
0397:
0398:                    if (nonValidatingMode) {
0399:                        fStartDTDCalled = true;
0400:                        nvGrammarInfo.startDTD(fEntityScanner, null);
0401:                    }
0402:                    // set starting state for internal subset
0403:                    setScannerState(SCANNER_STATE_MARKUP_DECL);
0404:                }
0405:                // keep dispatching "events"
0406:                do {
0407:                    if (!scanDecls(complete)) {
0408:                        // call handler
0409:                        if (fDTDHandler != null && hasExternalSubset == false) {
0410:                            fDTDHandler.endDTD(null);
0411:                        }
0412:                        if (nonValidatingMode && hasExternalSubset == false) {
0413:                            nvGrammarInfo.endDTD(null);
0414:                        }
0415:                        // we're done, set starting state for external subset
0416:                        setScannerState(SCANNER_STATE_TEXT_DECL);
0417:                        return false;
0418:                    }
0419:                } while (complete);
0420:
0421:                // return that there is more to scan
0422:                return true;
0423:
0424:            } // scanDTDInternalSubset(boolean,boolean,boolean):boolean
0425:
0426:            //
0427:            // XMLComponent methods
0428:            //
0429:
0430:            /**
0431:             * reset
0432:             *
0433:             * @param componentManager
0434:             */
0435:            public void reset(XMLComponentManager componentManager)
0436:                    throws XMLConfigurationException {
0437:
0438:                super .reset(componentManager);
0439:                init();
0440:
0441:            } // reset(XMLComponentManager)
0442:
0443:            // this is made for something like XMLDTDLoader--XMLComponentManager-free operation...
0444:            public void reset() {
0445:                //super.reset();
0446:                init();
0447:            }
0448:
0449:            public void reset(PropertyManager props) {
0450:                setPropertyManager(props);
0451:                super .reset(props);
0452:
0453:                if (!fAttributeCacheInitDone) {
0454:                    for (int i = 0; i < initialCacheCount; i++) {
0455:                        attributeValueCache.add(new XMLString());
0456:                        stringBufferCache.add(new XMLStringBuffer());
0457:                    }
0458:                    fAttributeCacheInitDone = true;
0459:                }
0460:                fStringBufferIndex = 0;
0461:                fAttributeCacheUsedCount = 0;
0462:                init();
0463:            }
0464:
0465:            /**
0466:             * Returns a list of feature identifiers that are recognized by
0467:             * this component. This method may return null if no features
0468:             * are recognized by this component.
0469:             */
0470:            public String[] getRecognizedFeatures() {
0471:                return (String[]) (RECOGNIZED_FEATURES.clone());
0472:            } // getRecognizedFeatures():String[]
0473:
0474:            /**
0475:             * Returns a list of property identifiers that are recognized by
0476:             * this component. This method may return null if no properties
0477:             * are recognized by this component.
0478:             */
0479:            public String[] getRecognizedProperties() {
0480:                return (String[]) (RECOGNIZED_PROPERTIES.clone());
0481:            } // getRecognizedProperties():String[]
0482:
0483:            /**
0484:             * Returns the default state for a feature, or null if this
0485:             * component does not want to report a default value for this
0486:             * feature.
0487:             *
0488:             * @param featureId The feature identifier.
0489:             *
0490:             * @since Xerces 2.2.0
0491:             */
0492:            public Boolean getFeatureDefault(String featureId) {
0493:                for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
0494:                    if (RECOGNIZED_FEATURES[i].equals(featureId)) {
0495:                        return FEATURE_DEFAULTS[i];
0496:                    }
0497:                }
0498:                return null;
0499:            } // getFeatureDefault(String):Boolean
0500:
0501:            /**
0502:             * Returns the default state for a property, or null if this
0503:             * component does not want to report a default value for this
0504:             * property.
0505:             *
0506:             * @param propertyId The property identifier.
0507:             *
0508:             * @since Xerces 2.2.0
0509:             */
0510:            public Object getPropertyDefault(String propertyId) {
0511:                for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
0512:                    if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
0513:                        return PROPERTY_DEFAULTS[i];
0514:                    }
0515:                }
0516:                return null;
0517:            } // getPropertyDefault(String):Object
0518:
0519:            //
0520:            // XMLDTDSource methods
0521:            //
0522:
0523:            /**
0524:             * setDTDHandler
0525:             *
0526:             * @param dtdHandler
0527:             */
0528:            public void setDTDHandler(XMLDTDHandler dtdHandler) {
0529:                fDTDHandler = dtdHandler;
0530:            } // setDTDHandler(XMLDTDHandler)
0531:
0532:            /**
0533:             * getDTDHandler
0534:             *
0535:             * @return the XMLDTDHandler
0536:             */
0537:            public XMLDTDHandler getDTDHandler() {
0538:                return fDTDHandler;
0539:            } // getDTDHandler():  XMLDTDHandler
0540:
0541:            //
0542:            // XMLDTDContentModelSource methods
0543:            //
0544:
0545:            /**
0546:             * setDTDContentModelHandler
0547:             *
0548:             * @param dtdContentModelHandler
0549:             */
0550:            public void setDTDContentModelHandler(
0551:                    XMLDTDContentModelHandler dtdContentModelHandler) {
0552:                fDTDContentModelHandler = dtdContentModelHandler;
0553:            } // setDTDContentModelHandler
0554:
0555:            /**
0556:             * getDTDContentModelHandler
0557:             *
0558:             * @return XMLDTDContentModelHandler
0559:             */
0560:            public XMLDTDContentModelHandler getDTDContentModelHandler() {
0561:                return fDTDContentModelHandler;
0562:            } // setDTDContentModelHandler
0563:
0564:            //
0565:            // XMLEntityHandler methods
0566:            //
0567:
0568:            /**
0569:             * This method notifies of the start of an entity. The DTD has the
0570:             * pseudo-name of "[dtd]" parameter entity names start with '%'; and
0571:             * general entities are just specified by their name.
0572:             *
0573:             * @param name     The name of the entity.
0574:             * @param identifier The resource identifier.
0575:             * @param encoding The auto-detected IANA encoding name of the entity
0576:             *                 stream. This value will be null in those situations
0577:             *                 where the entity encoding is not auto-detected (e.g.
0578:             *                 internal entities or a document entity that is
0579:             *                 parsed from a java.io.Reader).
0580:             *
0581:             * @throws XNIException Thrown by handler to signal an error.
0582:             */
0583:            public void startEntity(String name,
0584:                    XMLResourceIdentifier identifier, String encoding)
0585:                    throws XNIException {
0586:
0587:                super .startEntity(name, identifier, encoding);
0588:
0589:                boolean dtdEntity = name.equals("[dtd]");
0590:                if (dtdEntity) {
0591:                    // call handler
0592:                    if (fDTDHandler != null && !fStartDTDCalled) {
0593:                        fDTDHandler.startDTD(fEntityScanner, null);
0594:                    }
0595:                    if (fDTDHandler != null) {
0596:                        fDTDHandler.startExternalSubset(identifier, null);
0597:                    }
0598:                    fEntityManager.startExternalSubset();
0599:                    fExtEntityDepth++;
0600:                } else if (name.charAt(0) == '%') {
0601:                    pushPEStack(fMarkUpDepth, fReportEntity);
0602:                    if (fEntityScanner.isExternal()) {
0603:                        fExtEntityDepth++;
0604:                    }
0605:                }
0606:
0607:                // call handler
0608:                if (fDTDHandler != null && !dtdEntity && fReportEntity) {
0609:                    fDTDHandler.startParameterEntity(name, identifier,
0610:                            encoding, null);
0611:                }
0612:
0613:            } // startEntity(String,XMLResourceIdentifier,String)
0614:
0615:            /**
0616:             * This method notifies the end of an entity. The DTD has the pseudo-name
0617:             * of "[dtd]" parameter entity names start with '%'; and general entities
0618:             * are just specified by their name.
0619:             *
0620:             * @param name The name of the entity.
0621:             *
0622:             * @throws XNIException Thrown by handler to signal an error.
0623:             */
0624:            public void endEntity(String name) throws XNIException, IOException {
0625:
0626:                super .endEntity(name);
0627:
0628:                // if there is no data after the doctype
0629:                //
0630:                if (fScannerState == SCANNER_STATE_END_OF_INPUT)
0631:                    return;
0632:
0633:                // Handle end of PE
0634:                boolean reportEntity = fReportEntity;
0635:                if (name.startsWith("%")) {
0636:                    reportEntity = peekReportEntity();
0637:                    // check well-formedness of the enity
0638:                    int startMarkUpDepth = popPEStack();
0639:                    // throw fatalError if this entity was incomplete and
0640:                    // was a freestanding decl
0641:                    if (startMarkUpDepth == 0
0642:                            && startMarkUpDepth < fMarkUpDepth) {
0643:                        fErrorReporter
0644:                                .reportError(
0645:                                        XMLMessageFormatter.XML_DOMAIN,
0646:                                        "ILL_FORMED_PARAMETER_ENTITY_WHEN_USED_IN_DECL",
0647:                                        new Object[] { fEntityManager.fCurrentEntity.name },
0648:                                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
0649:                    }
0650:                    if (startMarkUpDepth != fMarkUpDepth) {
0651:                        reportEntity = false;
0652:                        if (fValidation) {
0653:                            // Proper nesting of parameter entities is a Validity Constraint
0654:                            // and must not be enforced when validation is off
0655:                            fErrorReporter.reportError(
0656:                                    XMLMessageFormatter.XML_DOMAIN,
0657:                                    "ImproperDeclarationNesting",
0658:                                    new Object[] { name },
0659:                                    XMLErrorReporter.SEVERITY_ERROR);
0660:                        }
0661:                    }
0662:                    if (fEntityScanner.isExternal()) {
0663:                        fExtEntityDepth--;
0664:                    }
0665:                }
0666:
0667:                // call handler
0668:                boolean dtdEntity = name.equals("[dtd]");
0669:                if (fDTDHandler != null && !dtdEntity && reportEntity) {
0670:                    fDTDHandler.endParameterEntity(name, null);
0671:                }
0672:
0673:                // end DTD
0674:                if (dtdEntity) {
0675:                    if (fIncludeSectDepth != 0) {
0676:                        reportFatalError("IncludeSectUnterminated", null);
0677:                    }
0678:                    fScannerState = SCANNER_STATE_END_OF_INPUT;
0679:                    // call handler
0680:                    fEntityManager.endExternalSubset();
0681:                    if (fDTDHandler != null) {
0682:                        fDTDHandler.endExternalSubset(null);
0683:                        fDTDHandler.endDTD(null);
0684:                    }
0685:                    fExtEntityDepth--;
0686:                }
0687:
0688:            } // endEntity(String)
0689:
0690:            // helper methods
0691:
0692:            /**
0693:             * Sets the scanner state.
0694:             *
0695:             * @param state The new scanner state.
0696:             */
0697:            protected final void setScannerState(int state) {
0698:
0699:                fScannerState = state;
0700:                if (DEBUG_SCANNER_STATE) {
0701:                    System.out.print("### setScannerState: ");
0702:                    System.out.print(getScannerStateName(state));
0703:                    System.out.println();
0704:                }
0705:
0706:            } // setScannerState(int)
0707:
0708:            //
0709:            // Private methods
0710:            //
0711:
0712:            /** Returns the scanner state name. */
0713:            private static String getScannerStateName(int state) {
0714:
0715:                if (DEBUG_SCANNER_STATE) {
0716:                    switch (state) {
0717:                    case SCANNER_STATE_END_OF_INPUT:
0718:                        return "SCANNER_STATE_END_OF_INPUT";
0719:                    case SCANNER_STATE_TEXT_DECL:
0720:                        return "SCANNER_STATE_TEXT_DECL";
0721:                    case SCANNER_STATE_MARKUP_DECL:
0722:                        return "SCANNER_STATE_MARKUP_DECL";
0723:                    }
0724:                }
0725:
0726:                return "??? (" + state + ')';
0727:
0728:            } // getScannerStateName(int):String
0729:
0730:            protected final boolean scanningInternalSubset() {
0731:                return fExtEntityDepth == 0;
0732:            }
0733:
0734:            /**
0735:             * start a parameter entity dealing with the textdecl if there is any
0736:             *
0737:             * @param name The name of the parameter entity to start (without the '%')
0738:             * @param literal Whether this is happening within a literal
0739:             */
0740:            protected void startPE(String name, boolean literal)
0741:                    throws IOException, XNIException {
0742:                int depth = fPEDepth;
0743:                String pName = "%" + name;
0744:                if (fValidation && !fEntityStore.isDeclaredEntity(pName)) {
0745:                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
0746:                            "EntityNotDeclared", new Object[] { name },
0747:                            XMLErrorReporter.SEVERITY_ERROR);
0748:                }
0749:                fEntityManager.startEntity(fSymbolTable.addSymbol(pName),
0750:                        literal);
0751:                // if we actually got a new entity and it's external
0752:                // parse text decl if there is any
0753:                if (depth != fPEDepth && fEntityScanner.isExternal()) {
0754:                    scanTextDecl();
0755:                }
0756:            }
0757:
0758:            /**
0759:             * Dispatch an XML "event".
0760:             *
0761:             * @param complete True if this method is intended to scan
0762:             *                 and dispatch as much as possible.
0763:             *
0764:             * @return True if a TextDecl was scanned.
0765:             *
0766:             * @throws IOException  Thrown on i/o error.
0767:             * @throws XNIException Thrown on parse error.
0768:             *
0769:             */
0770:            protected final boolean scanTextDecl() throws IOException,
0771:                    XNIException {
0772:
0773:                // scan XMLDecl
0774:                boolean textDecl = false;
0775:                if (fEntityScanner.skipString("<?xml")) {
0776:                    fMarkUpDepth++;
0777:                    // NOTE: special case where document starts with a PI
0778:                    //       whose name starts with "xml" (e.g. "xmlfoo")
0779:                    if (isValidNameChar(fEntityScanner.peekChar())) {
0780:                        fStringBuffer.clear();
0781:                        fStringBuffer.append("xml");
0782:                        while (isValidNameChar(fEntityScanner.peekChar())) {
0783:                            fStringBuffer.append((char) fEntityScanner
0784:                                    .scanChar());
0785:                        }
0786:                        String target = fSymbolTable.addSymbol(
0787:                                fStringBuffer.ch, fStringBuffer.offset,
0788:                                fStringBuffer.length);
0789:                        scanPIData(target, fString);
0790:                    }
0791:
0792:                    // standard Text declaration
0793:                    else {
0794:                        // pseudo-attribute values
0795:                        String version = null;
0796:                        String encoding = null;
0797:
0798:                        scanXMLDeclOrTextDecl(true, fStrings);
0799:                        textDecl = true;
0800:                        fMarkUpDepth--;
0801:
0802:                        version = fStrings[0];
0803:                        encoding = fStrings[1];
0804:
0805:                        fEntityScanner.setEncoding(encoding);
0806:
0807:                        // call handler
0808:                        if (fDTDHandler != null) {
0809:                            fDTDHandler.textDecl(version, encoding, null);
0810:                        }
0811:                    }
0812:                }
0813:                fEntityManager.fCurrentEntity.mayReadChunks = true;
0814:
0815:                return textDecl;
0816:
0817:            } // scanTextDecl(boolean):boolean
0818:
0819:            /**
0820:             * Scans a processing data. This is needed to handle the situation
0821:             * where a document starts with a processing instruction whose
0822:             * target name <em>starts with</em> "xml". (e.g. xmlfoo)
0823:             *
0824:             * @param target The PI target
0825:             * @param data The string to fill in with the data
0826:             */
0827:            protected final void scanPIData(String target, XMLString data)
0828:                    throws IOException, XNIException {
0829:                //Venu REVISIT
0830:                //      super.scanPIData(target, data);
0831:                fMarkUpDepth--;
0832:
0833:                // call handler
0834:                if (fDTDHandler != null) {
0835:                    fDTDHandler.processingInstruction(target, data, null);
0836:                }
0837:
0838:            } // scanPIData(String)
0839:
0840:            /**
0841:             * Scans a comment.
0842:             * <p>
0843:             * <pre>
0844:             * [15] Comment ::= '&lt!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
0845:             * </pre>
0846:             * <p>
0847:             * <strong>Note:</strong> Called after scanning past '&lt;!--'
0848:             */
0849:            protected final void scanComment() throws IOException, XNIException {
0850:
0851:                fReportEntity = false;
0852:                scanComment(fStringBuffer);
0853:                fMarkUpDepth--;
0854:
0855:                // call handler
0856:                if (fDTDHandler != null) {
0857:                    fDTDHandler.comment(fStringBuffer, null);
0858:                }
0859:                fReportEntity = true;
0860:
0861:            } // scanComment()
0862:
0863:            /**
0864:             * Scans an element declaration
0865:             * <p>
0866:             * <pre>
0867:             * [45]    elementdecl    ::=    '&lt;!ELEMENT' S Name S contentspec S? '>'
0868:             * [46]    contentspec    ::=    'EMPTY' | 'ANY' | Mixed | children
0869:             * </pre>
0870:             * <p>
0871:             * <strong>Note:</strong> Called after scanning past '&lt;!ELEMENT'
0872:             */
0873:            protected final void scanElementDecl() throws IOException,
0874:                    XNIException {
0875:
0876:                // spaces
0877:                fReportEntity = false;
0878:                if (!skipSeparator(true, !scanningInternalSubset())) {
0879:                    reportFatalError(
0880:                            "MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ELEMENTDECL",
0881:                            null);
0882:                }
0883:
0884:                // element name
0885:                String name = fEntityScanner.scanName();
0886:                if (name == null) {
0887:                    reportFatalError(
0888:                            "MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL", null);
0889:                }
0890:
0891:                // spaces
0892:                if (!skipSeparator(true, !scanningInternalSubset())) {
0893:                    reportFatalError(
0894:                            "MSG_SPACE_REQUIRED_BEFORE_CONTENTSPEC_IN_ELEMENTDECL",
0895:                            new Object[] { name });
0896:                }
0897:
0898:                // content model
0899:                if (fDTDContentModelHandler != null) {
0900:                    fDTDContentModelHandler.startContentModel(name, null);
0901:                }
0902:                String contentModel = null;
0903:                fReportEntity = true;
0904:                if (fEntityScanner.skipString("EMPTY")) {
0905:                    contentModel = "EMPTY";
0906:                    // call handler
0907:                    if (fDTDContentModelHandler != null) {
0908:                        fDTDContentModelHandler.empty(null);
0909:                    }
0910:                } else if (fEntityScanner.skipString("ANY")) {
0911:                    contentModel = "ANY";
0912:                    // call handler
0913:                    if (fDTDContentModelHandler != null) {
0914:                        fDTDContentModelHandler.any(null);
0915:                    }
0916:                } else {
0917:                    if (!fEntityScanner.skipChar('(')) {
0918:                        reportFatalError(
0919:                                "MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN",
0920:                                new Object[] { name });
0921:                    }
0922:                    if (fDTDContentModelHandler != null) {
0923:                        fDTDContentModelHandler.startGroup(null);
0924:                    }
0925:                    fStringBuffer.clear();
0926:                    fStringBuffer.append('(');
0927:                    fMarkUpDepth++;
0928:                    skipSeparator(false, !scanningInternalSubset());
0929:
0930:                    // Mixed content model
0931:                    if (fEntityScanner.skipString("#PCDATA")) {
0932:                        scanMixed(name);
0933:                    } else { // children content
0934:                        scanChildren(name);
0935:                    }
0936:                    contentModel = fStringBuffer.toString();
0937:                }
0938:
0939:                // call handler
0940:                if (fDTDContentModelHandler != null) {
0941:                    fDTDContentModelHandler.endContentModel(null);
0942:                }
0943:
0944:                fReportEntity = false;
0945:                skipSeparator(false, !scanningInternalSubset());
0946:                // end
0947:                if (!fEntityScanner.skipChar('>')) {
0948:                    reportFatalError("ElementDeclUnterminated",
0949:                            new Object[] { name });
0950:                }
0951:                fReportEntity = true;
0952:                fMarkUpDepth--;
0953:
0954:                // call handler
0955:                if (fDTDHandler != null) {
0956:                    fDTDHandler.elementDecl(name, contentModel, null);
0957:                }
0958:                if (nonValidatingMode)
0959:                    nvGrammarInfo.elementDecl(name, contentModel, null);
0960:            } // scanElementDecl()
0961:
0962:            /**
0963:             * scan Mixed content model
0964:             * This assumes the content model has been parsed up to #PCDATA and
0965:             * can simply append to fStringBuffer.
0966:             * <pre>
0967:             * [51]    Mixed    ::=    '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
0968:             *                       | '(' S? '#PCDATA' S? ')'
0969:             * </pre>
0970:             *
0971:             * @param elName The element type name this declaration is about.
0972:             *
0973:             * <strong>Note:</strong> Called after scanning past '(#PCDATA'.
0974:             */
0975:            private final void scanMixed(String elName) throws IOException,
0976:                    XNIException {
0977:
0978:                String childName = null;
0979:
0980:                fStringBuffer.append("#PCDATA");
0981:                // call handler
0982:                if (fDTDContentModelHandler != null) {
0983:                    fDTDContentModelHandler.pcdata(null);
0984:                }
0985:                skipSeparator(false, !scanningInternalSubset());
0986:                while (fEntityScanner.skipChar('|')) {
0987:                    fStringBuffer.append('|');
0988:                    // call handler
0989:                    if (fDTDContentModelHandler != null) {
0990:                        fDTDContentModelHandler.separator(
0991:                                XMLDTDContentModelHandler.SEPARATOR_CHOICE,
0992:                                null);
0993:                    }
0994:                    skipSeparator(false, !scanningInternalSubset());
0995:
0996:                    childName = fEntityScanner.scanName();
0997:                    if (childName == null) {
0998:                        reportFatalError(
0999:                                "MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT",
1000:                                new Object[] { elName });
1001:                    }
1002:                    fStringBuffer.append(childName);
1003:                    // call handler
1004:                    if (fDTDContentModelHandler != null) {
1005:                        fDTDContentModelHandler.element(childName, null);
1006:                    }
1007:                    skipSeparator(false, !scanningInternalSubset());
1008:                }
1009:                // The following check must be done in a single call (as opposed to one
1010:                // for ')' and then one for '*') to guarantee that callbacks are
1011:                // properly nested. We do not want to trigger endEntity too early in
1012:                // case we cross the boundary of an entity between the two characters.
1013:                if (fEntityScanner.skipString(")*")) {
1014:                    fStringBuffer.append(")*");
1015:                    // call handler
1016:                    if (fDTDContentModelHandler != null) {
1017:                        fDTDContentModelHandler.endGroup(null);
1018:                        fDTDContentModelHandler.occurrence(
1019:                                XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE,
1020:                                null);
1021:                    }
1022:                } else if (childName != null) {
1023:                    reportFatalError("MixedContentUnterminated",
1024:                            new Object[] { elName });
1025:                } else if (fEntityScanner.skipChar(')')) {
1026:                    fStringBuffer.append(')');
1027:                    // call handler
1028:                    if (fDTDContentModelHandler != null) {
1029:                        fDTDContentModelHandler.endGroup(null);
1030:                    }
1031:                } else {
1032:                    reportFatalError("MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN",
1033:                            new Object[] { elName });
1034:                }
1035:                fMarkUpDepth--;
1036:                // we are done
1037:            }
1038:
1039:            /**
1040:             * scan children content model
1041:             * This assumes it can simply append to fStringBuffer.
1042:             * <pre>
1043:             * [47]    children  ::=    (choice | seq) ('?' | '*' | '+')?
1044:             * [48]    cp        ::=    (Name | choice | seq) ('?' | '*' | '+')?
1045:             * [49]    choice    ::=    '(' S? cp ( S? '|' S? cp )+ S? ')'
1046:             * [50]    seq       ::=    '(' S? cp ( S? ',' S? cp )* S? ')'
1047:             * </pre>
1048:             *
1049:             * @param elName The element type name this declaration is about.
1050:             *
1051:             * <strong>Note:</strong> Called after scanning past the first open
1052:             * paranthesis.
1053:             */
1054:            private final void scanChildren(String elName) throws IOException,
1055:                    XNIException {
1056:
1057:                fContentDepth = 0;
1058:                pushContentStack(0);
1059:                int currentOp = 0;
1060:                int c;
1061:                while (true) {
1062:                    if (fEntityScanner.skipChar('(')) {
1063:                        fMarkUpDepth++;
1064:                        fStringBuffer.append('(');
1065:                        // call handler
1066:                        if (fDTDContentModelHandler != null) {
1067:                            fDTDContentModelHandler.startGroup(null);
1068:                        }
1069:                        // push current op on stack and reset it
1070:                        pushContentStack(currentOp);
1071:                        currentOp = 0;
1072:                        skipSeparator(false, !scanningInternalSubset());
1073:                        continue;
1074:                    }
1075:                    skipSeparator(false, !scanningInternalSubset());
1076:                    String childName = fEntityScanner.scanName();
1077:                    if (childName == null) {
1078:                        reportFatalError(
1079:                                "MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN",
1080:                                new Object[] { elName });
1081:                        return;
1082:                    }
1083:                    // call handler
1084:                    if (fDTDContentModelHandler != null) {
1085:                        fDTDContentModelHandler.element(childName, null);
1086:                    }
1087:                    fStringBuffer.append(childName);
1088:                    c = fEntityScanner.peekChar();
1089:                    if (c == '?' || c == '*' || c == '+') {
1090:                        // call handler
1091:                        if (fDTDContentModelHandler != null) {
1092:                            short oc;
1093:                            if (c == '?') {
1094:                                oc = XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE;
1095:                            } else if (c == '*') {
1096:                                oc = XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE;
1097:                            } else {
1098:                                oc = XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE;
1099:                            }
1100:                            fDTDContentModelHandler.occurrence(oc, null);
1101:                        }
1102:                        fEntityScanner.scanChar();
1103:                        fStringBuffer.append((char) c);
1104:                    }
1105:                    while (true) {
1106:                        skipSeparator(false, !scanningInternalSubset());
1107:                        c = fEntityScanner.peekChar();
1108:                        if (c == ',' && currentOp != '|') {
1109:                            currentOp = c;
1110:                            // call handler
1111:                            if (fDTDContentModelHandler != null) {
1112:                                fDTDContentModelHandler
1113:                                        .separator(
1114:                                                XMLDTDContentModelHandler.SEPARATOR_SEQUENCE,
1115:                                                null);
1116:                            }
1117:                            fEntityScanner.scanChar();
1118:                            fStringBuffer.append(',');
1119:                            break;
1120:                        } else if (c == '|' && currentOp != ',') {
1121:                            currentOp = c;
1122:                            // call handler
1123:                            if (fDTDContentModelHandler != null) {
1124:                                fDTDContentModelHandler
1125:                                        .separator(
1126:                                                XMLDTDContentModelHandler.SEPARATOR_CHOICE,
1127:                                                null);
1128:                            }
1129:                            fEntityScanner.scanChar();
1130:                            fStringBuffer.append('|');
1131:                            break;
1132:                        } else if (c != ')') {
1133:                            reportFatalError(
1134:                                    "MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN",
1135:                                    new Object[] { elName });
1136:                        }
1137:                        // call handler
1138:                        if (fDTDContentModelHandler != null) {
1139:                            fDTDContentModelHandler.endGroup(null);
1140:                        }
1141:                        // restore previous op
1142:                        currentOp = popContentStack();
1143:                        short oc;
1144:                        // The following checks must be done in a single call (as
1145:                        // opposed to one for ')' and then one for '?', '*', and '+')
1146:                        // to guarantee that callbacks are properly nested. We do not
1147:                        // want to trigger endEntity too early in case we cross the
1148:                        // boundary of an entity between the two characters.
1149:                        if (fEntityScanner.skipString(")?")) {
1150:                            fStringBuffer.append(")?");
1151:                            // call handler
1152:                            if (fDTDContentModelHandler != null) {
1153:                                oc = XMLDTDContentModelHandler.OCCURS_ZERO_OR_ONE;
1154:                                fDTDContentModelHandler.occurrence(oc, null);
1155:                            }
1156:                        } else if (fEntityScanner.skipString(")+")) {
1157:                            fStringBuffer.append(")+");
1158:                            // call handler
1159:                            if (fDTDContentModelHandler != null) {
1160:                                oc = XMLDTDContentModelHandler.OCCURS_ONE_OR_MORE;
1161:                                fDTDContentModelHandler.occurrence(oc, null);
1162:                            }
1163:                        } else if (fEntityScanner.skipString(")*")) {
1164:                            fStringBuffer.append(")*");
1165:                            // call handler
1166:                            if (fDTDContentModelHandler != null) {
1167:                                oc = XMLDTDContentModelHandler.OCCURS_ZERO_OR_MORE;
1168:                                fDTDContentModelHandler.occurrence(oc, null);
1169:                            }
1170:                        } else {
1171:                            // no occurrence specified
1172:                            fEntityScanner.scanChar();
1173:                            fStringBuffer.append(')');
1174:                        }
1175:                        fMarkUpDepth--;
1176:                        if (fContentDepth == 0) {
1177:                            return;
1178:                        }
1179:                    }
1180:                    skipSeparator(false, !scanningInternalSubset());
1181:                }
1182:            }
1183:
1184:            /**
1185:             * Scans an attlist declaration
1186:             * <p>
1187:             * <pre>
1188:             * [52]  AttlistDecl    ::=   '&lt;!ATTLIST' S Name AttDef* S? '>'
1189:             * [53]  AttDef         ::=   S Name S AttType S DefaultDecl
1190:             * </pre>
1191:             * <p>
1192:             * <strong>Note:</strong> Called after scanning past '&lt;!ATTLIST'
1193:             */
1194:            protected final void scanAttlistDecl() throws IOException,
1195:                    XNIException {
1196:
1197:                // spaces
1198:                fReportEntity = false;
1199:                if (!skipSeparator(true, !scanningInternalSubset())) {
1200:                    reportFatalError(
1201:                            "MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ATTLISTDECL",
1202:                            null);
1203:                }
1204:
1205:                // element name
1206:                String elName = fEntityScanner.scanName();
1207:                if (elName == null) {
1208:                    reportFatalError(
1209:                            "MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL", null);
1210:                }
1211:
1212:                // call handler
1213:                if (fDTDHandler != null) {
1214:                    fDTDHandler.startAttlist(elName, null);
1215:                }
1216:
1217:                // spaces
1218:                if (!skipSeparator(true, !scanningInternalSubset())) {
1219:                    // no space, is it the end yet?
1220:                    if (fEntityScanner.skipChar('>')) {
1221:                        // yes, stop here
1222:                        // call handler
1223:                        if (fDTDHandler != null) {
1224:                            fDTDHandler.endAttlist(null);
1225:                        }
1226:                        fMarkUpDepth--;
1227:                        return;
1228:                    } else {
1229:                        reportFatalError(
1230:                                "MSG_SPACE_REQUIRED_BEFORE_ATTRIBUTE_NAME_IN_ATTDEF",
1231:                                new Object[] { elName });
1232:                    }
1233:                }
1234:
1235:                // definitions
1236:                while (!fEntityScanner.skipChar('>')) {
1237:                    String name = fEntityScanner.scanName();
1238:                    if (name == null) {
1239:                        reportFatalError("AttNameRequiredInAttDef",
1240:                                new Object[] { elName });
1241:                    }
1242:                    // spaces
1243:                    if (!skipSeparator(true, !scanningInternalSubset())) {
1244:                        reportFatalError(
1245:                                "MSG_SPACE_REQUIRED_BEFORE_ATTTYPE_IN_ATTDEF",
1246:                                new Object[] { elName, name });
1247:                    }
1248:                    // type
1249:                    String type = scanAttType(elName, name);
1250:
1251:                    // spaces
1252:                    if (!skipSeparator(true, !scanningInternalSubset())) {
1253:                        reportFatalError(
1254:                                "MSG_SPACE_REQUIRED_BEFORE_DEFAULTDECL_IN_ATTDEF",
1255:                                new Object[] { elName, name });
1256:                    }
1257:
1258:                    // default decl
1259:                    String defaultType = scanAttDefaultDecl(elName, name, type,
1260:                            fLiteral, fLiteral2);
1261:                    // REVISIT: Should we do anything with the non-normalized
1262:                    //          default attribute value? -Ac
1263:                    // yes--according to bug 5073.  - neilg
1264:                    String[] enumr = null;
1265:                    if (fDTDHandler != null || nonValidatingMode) {
1266:                        if (fEnumerationCount != 0) {
1267:                            enumr = new String[fEnumerationCount];
1268:                            System.arraycopy(fEnumeration, 0, enumr, 0,
1269:                                    fEnumerationCount);
1270:                        }
1271:                    }
1272:                    // call handler
1273:                    // Determine whether the default value to be passed should be null.
1274:                    // REVISIT: should probably check whether fLiteral.ch is null instead. LM.
1275:                    if (defaultType != null
1276:                            && (defaultType.equals("#REQUIRED") || defaultType
1277:                                    .equals("#IMPLIED"))) {
1278:                        if (fDTDHandler != null) {
1279:                            fDTDHandler.attributeDecl(elName, name, type,
1280:                                    enumr, defaultType, null, null, null);
1281:                        }
1282:                        if (nonValidatingMode) {
1283:                            nvGrammarInfo.attributeDecl(elName, name, type,
1284:                                    enumr, defaultType, null, null, null);
1285:
1286:                        }
1287:                    } else {
1288:                        if (fDTDHandler != null) {
1289:                            fDTDHandler.attributeDecl(elName, name, type,
1290:                                    enumr, defaultType, fLiteral, fLiteral2,
1291:                                    null);
1292:                        }
1293:                        if (nonValidatingMode) {
1294:                            nvGrammarInfo.attributeDecl(elName, name, type,
1295:                                    enumr, defaultType, fLiteral, fLiteral2,
1296:                                    null);
1297:                        }
1298:                    }
1299:                    skipSeparator(false, !scanningInternalSubset());
1300:                }
1301:
1302:                // call handler
1303:                if (fDTDHandler != null) {
1304:                    fDTDHandler.endAttlist(null);
1305:                }
1306:                fMarkUpDepth--;
1307:                fReportEntity = true;
1308:
1309:            } // scanAttlistDecl()
1310:
1311:            /**
1312:             * Scans an attribute type definition
1313:             * <p>
1314:             * <pre>
1315:             * [54]  AttType        ::=   StringType | TokenizedType | EnumeratedType
1316:             * [55]  StringType     ::=   'CDATA'
1317:             * [56]  TokenizedType  ::=   'ID'
1318:             *                          | 'IDREF'
1319:             *                          | 'IDREFS'
1320:             *                          | 'ENTITY'
1321:             *                          | 'ENTITIES'
1322:             *                          | 'NMTOKEN'
1323:             *                          | 'NMTOKENS'
1324:             * [57]  EnumeratedType ::=    NotationType | Enumeration
1325:             * [58]  NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
1326:             * [59]  Enumeration    ::=    '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
1327:             * </pre>
1328:             * <p>
1329:             * <strong>Note:</strong> Called after scanning past '&lt;!ATTLIST'
1330:             *
1331:             * @param elName The element type name this declaration is about.
1332:             * @param atName The attribute name this declaration is about.
1333:             */
1334:            private final String scanAttType(String elName, String atName)
1335:                    throws IOException, XNIException {
1336:
1337:                String type = null;
1338:                fEnumerationCount = 0;
1339:                /*
1340:                 * Watchout: the order here is important: when a string happens to
1341:                 * be a substring of another string, the longer one needs to be
1342:                 * looked for first!!
1343:                 */
1344:                if (fEntityScanner.skipString("CDATA")) {
1345:                    type = "CDATA";
1346:                } else if (fEntityScanner.skipString("IDREFS")) {
1347:                    type = "IDREFS";
1348:                } else if (fEntityScanner.skipString("IDREF")) {
1349:                    type = "IDREF";
1350:                } else if (fEntityScanner.skipString("ID")) {
1351:                    type = "ID";
1352:                } else if (fEntityScanner.skipString("ENTITY")) {
1353:                    type = "ENTITY";
1354:                } else if (fEntityScanner.skipString("ENTITIES")) {
1355:                    type = "ENTITIES";
1356:                } else if (fEntityScanner.skipString("NMTOKENS")) {
1357:                    type = "NMTOKENS";
1358:                } else if (fEntityScanner.skipString("NMTOKEN")) {
1359:                    type = "NMTOKEN";
1360:                } else if (fEntityScanner.skipString("NOTATION")) {
1361:                    type = "NOTATION";
1362:                    // spaces
1363:                    if (!skipSeparator(true, !scanningInternalSubset())) {
1364:                        reportFatalError(
1365:                                "MSG_SPACE_REQUIRED_AFTER_NOTATION_IN_NOTATIONTYPE",
1366:                                new Object[] { elName, atName });
1367:                    }
1368:                    // open paren
1369:                    int c = fEntityScanner.scanChar();
1370:                    if (c != '(') {
1371:                        reportFatalError(
1372:                                "MSG_OPEN_PAREN_REQUIRED_IN_NOTATIONTYPE",
1373:                                new Object[] { elName, atName });
1374:                    }
1375:                    fMarkUpDepth++;
1376:                    do {
1377:                        skipSeparator(false, !scanningInternalSubset());
1378:                        String aName = fEntityScanner.scanName();
1379:                        if (aName == null) {
1380:                            reportFatalError(
1381:                                    "MSG_NAME_REQUIRED_IN_NOTATIONTYPE",
1382:                                    new Object[] { elName, atName });
1383:                        }
1384:                        ensureEnumerationSize(fEnumerationCount + 1);
1385:                        fEnumeration[fEnumerationCount++] = aName;
1386:                        skipSeparator(false, !scanningInternalSubset());
1387:                        c = fEntityScanner.scanChar();
1388:                    } while (c == '|');
1389:                    if (c != ')') {
1390:                        reportFatalError("NotationTypeUnterminated",
1391:                                new Object[] { elName, atName });
1392:                    }
1393:                    fMarkUpDepth--;
1394:                } else { // Enumeration
1395:                    type = "ENUMERATION";
1396:                    // open paren
1397:                    int c = fEntityScanner.scanChar();
1398:                    if (c != '(') {
1399:                        //                       "OPEN_PAREN_REQUIRED_BEFORE_ENUMERATION_IN_ATTRDECL",
1400:                        reportFatalError("AttTypeRequiredInAttDef",
1401:                                new Object[] { elName, atName });
1402:                    }
1403:                    fMarkUpDepth++;
1404:                    do {
1405:                        skipSeparator(false, !scanningInternalSubset());
1406:                        String token = fEntityScanner.scanNmtoken();
1407:                        if (token == null) {
1408:                            reportFatalError(
1409:                                    "MSG_NMTOKEN_REQUIRED_IN_ENUMERATION",
1410:                                    new Object[] { elName, atName });
1411:                        }
1412:                        ensureEnumerationSize(fEnumerationCount + 1);
1413:                        fEnumeration[fEnumerationCount++] = token;
1414:                        skipSeparator(false, !scanningInternalSubset());
1415:                        c = fEntityScanner.scanChar();
1416:                    } while (c == '|');
1417:                    if (c != ')') {
1418:                        reportFatalError("EnumerationUnterminated",
1419:                                new Object[] { elName, atName });
1420:                    }
1421:                    fMarkUpDepth--;
1422:                }
1423:                return type;
1424:
1425:            } // scanAttType():String
1426:
1427:            /**
1428:             * Scans an attribute default declaration
1429:             * <p>
1430:             * <pre>
1431:             * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
1432:             * </pre>
1433:             *
1434:             * @param name The name of the attribute being scanned.
1435:             * @param defaultVal The string to fill in with the default value.
1436:             */
1437:            protected final String scanAttDefaultDecl(String elName,
1438:                    String atName, String type, XMLString defaultVal,
1439:                    XMLString nonNormalizedDefaultVal) throws IOException,
1440:                    XNIException {
1441:
1442:                String defaultType = null;
1443:                fString.clear();
1444:                defaultVal.clear();
1445:                if (fEntityScanner.skipString("#REQUIRED")) {
1446:                    defaultType = "#REQUIRED";
1447:                } else if (fEntityScanner.skipString("#IMPLIED")) {
1448:                    defaultType = "#IMPLIED";
1449:                } else {
1450:                    if (fEntityScanner.skipString("#FIXED")) {
1451:                        defaultType = "#FIXED";
1452:                        // spaces
1453:                        if (!skipSeparator(true, !scanningInternalSubset())) {
1454:                            reportFatalError(
1455:                                    "MSG_SPACE_REQUIRED_AFTER_FIXED_IN_DEFAULTDECL",
1456:                                    new Object[] { elName, atName });
1457:                        }
1458:                    }
1459:                    // AttValue
1460:                    boolean isVC = !fStandalone
1461:                            && (fSeenExternalDTD || fSeenExternalPE);
1462:                    scanAttributeValue(defaultVal, nonNormalizedDefaultVal,
1463:                            atName, fAttributes, 0, isVC);
1464:                }
1465:                return defaultType;
1466:
1467:            } // ScanAttDefaultDecl
1468:
1469:            /**
1470:             * Scans an entity declaration
1471:             * <p>
1472:             * <pre>
1473:             * [70]    EntityDecl  ::=    GEDecl | PEDecl
1474:             * [71]    GEDecl      ::=    '&lt;!ENTITY' S Name S EntityDef S? '>'
1475:             * [72]    PEDecl      ::=    '&lt;!ENTITY' S '%' S Name S PEDef S? '>'
1476:             * [73]    EntityDef   ::=    EntityValue | (ExternalID NDataDecl?)
1477:             * [74]    PEDef       ::=    EntityValue | ExternalID
1478:             * [75]    ExternalID  ::=    'SYSTEM' S SystemLiteral
1479:             *                          | 'PUBLIC' S PubidLiteral S SystemLiteral
1480:             * [76]    NDataDecl   ::=    S 'NDATA' S Name
1481:             * </pre>
1482:             * <p>
1483:             * <strong>Note:</strong> Called after scanning past '&lt;!ENTITY'
1484:             */
1485:            private final void scanEntityDecl() throws IOException,
1486:                    XNIException {
1487:
1488:                boolean isPEDecl = false;
1489:                boolean sawPERef = false;
1490:                fReportEntity = false;
1491:                if (fEntityScanner.skipSpaces()) {
1492:                    if (!fEntityScanner.skipChar('%')) {
1493:                        isPEDecl = false; // <!ENTITY x "x">
1494:                    } else if (skipSeparator(true, !scanningInternalSubset())) {
1495:                        // <!ENTITY % x "x">
1496:                        isPEDecl = true;
1497:                    } else if (scanningInternalSubset()) {
1498:                        reportFatalError(
1499:                                "MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL",
1500:                                null);
1501:                        isPEDecl = true;
1502:                    } else if (fEntityScanner.peekChar() == '%') {
1503:                        // <!ENTITY %%x; "x"> is legal
1504:                        skipSeparator(false, !scanningInternalSubset());
1505:                        isPEDecl = true;
1506:                    } else {
1507:                        sawPERef = true;
1508:                    }
1509:                } else if (scanningInternalSubset()
1510:                        || !fEntityScanner.skipChar('%')) {
1511:                    // <!ENTITY[^ ]...> or <!ENTITY[^ %]...>
1512:                    reportFatalError(
1513:                            "MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL",
1514:                            null);
1515:                    isPEDecl = false;
1516:                } else if (fEntityScanner.skipSpaces()) {
1517:                    // <!ENTITY% ...>
1518:                    reportFatalError(
1519:                            "MSG_SPACE_REQUIRED_BEFORE_PERCENT_IN_PEDECL", null);
1520:                    isPEDecl = false;
1521:                } else {
1522:                    sawPERef = true;
1523:                }
1524:                if (sawPERef) {
1525:                    while (true) {
1526:                        String peName = fEntityScanner.scanName();
1527:                        if (peName == null) {
1528:                            reportFatalError("NameRequiredInPEReference", null);
1529:                        } else if (!fEntityScanner.skipChar(';')) {
1530:                            reportFatalError("SemicolonRequiredInPEReference",
1531:                                    new Object[] { peName });
1532:                        } else {
1533:                            startPE(peName, false);
1534:                        }
1535:                        fEntityScanner.skipSpaces();
1536:                        if (!fEntityScanner.skipChar('%'))
1537:                            break;
1538:                        if (!isPEDecl) {
1539:                            if (skipSeparator(true, !scanningInternalSubset())) {
1540:                                isPEDecl = true;
1541:                                break;
1542:                            }
1543:                            isPEDecl = fEntityScanner.skipChar('%');
1544:                        }
1545:                    }
1546:                }
1547:
1548:                // name
1549:                String name = fEntityScanner.scanName();
1550:                if (name == null) {
1551:                    reportFatalError("MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL",
1552:                            null);
1553:                }
1554:
1555:                // spaces
1556:                if (!skipSeparator(true, !scanningInternalSubset())) {
1557:                    reportFatalError(
1558:                            "MSG_SPACE_REQUIRED_AFTER_ENTITY_NAME_IN_ENTITYDECL",
1559:                            new Object[] { name });
1560:                }
1561:
1562:                // external id
1563:                scanExternalID(fStrings, false);
1564:                String systemId = fStrings[0];
1565:                String publicId = fStrings[1];
1566:
1567:                if (isPEDecl && systemId != null) {
1568:                    fSeenExternalPE = true;
1569:                }
1570:
1571:                String notation = null;
1572:                // NDATA
1573:                boolean sawSpace = skipSeparator(true,
1574:                        !scanningInternalSubset());
1575:                if (!isPEDecl && fEntityScanner.skipString("NDATA")) {
1576:                    // check whether there was space before NDATA
1577:                    if (!sawSpace) {
1578:                        reportFatalError(
1579:                                "MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL",
1580:                                new Object[] { name });
1581:                    }
1582:
1583:                    // spaces
1584:                    if (!skipSeparator(true, !scanningInternalSubset())) {
1585:                        reportFatalError(
1586:                                "MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL",
1587:                                new Object[] { name });
1588:                    }
1589:                    notation = fEntityScanner.scanName();
1590:                    if (notation == null) {
1591:                        reportFatalError(
1592:                                "MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL",
1593:                                new Object[] { name });
1594:                    }
1595:                }
1596:
1597:                // internal entity
1598:                if (systemId == null) {
1599:                    scanEntityValue(fLiteral, fLiteral2);
1600:                    // since we need it's value anyway, let's snag it so it doesn't get corrupted
1601:                    // if a new load takes place before we store the entity values
1602:                    fStringBuffer.clear();
1603:                    fStringBuffer2.clear();
1604:                    fStringBuffer.append(fLiteral.ch, fLiteral.offset,
1605:                            fLiteral.length);
1606:                    fStringBuffer2.append(fLiteral2.ch, fLiteral2.offset,
1607:                            fLiteral2.length);
1608:                }
1609:
1610:                // skip possible trailing space
1611:                skipSeparator(false, !scanningInternalSubset());
1612:
1613:                // end
1614:                if (!fEntityScanner.skipChar('>')) {
1615:                    reportFatalError("EntityDeclUnterminated",
1616:                            new Object[] { name });
1617:                }
1618:                fMarkUpDepth--;
1619:
1620:                // register entity and make callback
1621:                if (isPEDecl) {
1622:                    name = "%" + name;
1623:                }
1624:                if (systemId != null) {
1625:                    String baseSystemId = fEntityScanner.getBaseSystemId();
1626:                    if (notation != null) {
1627:                        fEntityStore.addUnparsedEntity(name, publicId,
1628:                                systemId, baseSystemId, notation);
1629:                    } else {
1630:                        fEntityStore.addExternalEntity(name, publicId,
1631:                                systemId, baseSystemId);
1632:                    }
1633:                    if (fDTDHandler != null) {
1634:                        //Venu Revisit : why false has been removed in expandSYstem
1635:                        fResourceIdentifier.setValues(publicId, systemId,
1636:                                baseSystemId, XMLEntityManager.expandSystemId(
1637:                                        systemId, baseSystemId));
1638:
1639:                        if (notation != null) {
1640:                            fDTDHandler.unparsedEntityDecl(name,
1641:                                    fResourceIdentifier, notation, null);
1642:                        } else {
1643:                            fDTDHandler.externalEntityDecl(name,
1644:                                    fResourceIdentifier, null);
1645:                        }
1646:                    }
1647:                } else {
1648:                    fEntityStore.addInternalEntity(name, fStringBuffer
1649:                            .toString());
1650:                    if (fDTDHandler != null) {
1651:                        fDTDHandler.internalEntityDecl(name, fStringBuffer,
1652:                                fStringBuffer2, null);
1653:                    }
1654:                }
1655:                fReportEntity = true;
1656:
1657:            } // scanEntityDecl()
1658:
1659:            /**
1660:             * Scans an entity value.
1661:             *
1662:             * @param value The string to fill in with the value.
1663:             * @param nonNormalizedValue The string to fill in with the
1664:             *                           non-normalized value.
1665:             *
1666:             * <strong>Note:</strong> This method uses fString, fStringBuffer (through
1667:             * the use of scanCharReferenceValue), and fStringBuffer2, anything in them
1668:             * at the time of calling is lost.
1669:             */
1670:            protected final void scanEntityValue(XMLString value,
1671:                    XMLString nonNormalizedValue) throws IOException,
1672:                    XNIException {
1673:                int quote = fEntityScanner.scanChar();
1674:                if (quote != '\'' && quote != '"') {
1675:                    reportFatalError("OpenQuoteMissingInDecl", null);
1676:                }
1677:                // store at which depth of entities we start
1678:                int entityDepth = fEntityDepth;
1679:
1680:                XMLString literal = fString;
1681:                XMLString literal2 = fString;
1682:                if (fEntityScanner.scanLiteral(quote, fString) != quote) {
1683:                    fStringBuffer.clear();
1684:                    fStringBuffer2.clear();
1685:                    do {
1686:                        fStringBuffer.append(fString);
1687:                        fStringBuffer2.append(fString);
1688:                        if (fEntityScanner.skipChar('&')) {
1689:                            if (fEntityScanner.skipChar('#')) {
1690:                                fStringBuffer2.append("&#");
1691:                                scanCharReferenceValue(fStringBuffer,
1692:                                        fStringBuffer2);
1693:                            } else {
1694:                                fStringBuffer.append('&');
1695:                                fStringBuffer2.append('&');
1696:                                String eName = fEntityScanner.scanName();
1697:                                if (eName == null) {
1698:                                    reportFatalError("NameRequiredInReference",
1699:                                            null);
1700:                                } else {
1701:                                    fStringBuffer.append(eName);
1702:                                    fStringBuffer2.append(eName);
1703:                                }
1704:                                if (!fEntityScanner.skipChar(';')) {
1705:                                    reportFatalError(
1706:                                            "SemicolonRequiredInReference",
1707:                                            new Object[] { eName });
1708:                                } else {
1709:                                    fStringBuffer.append(';');
1710:                                    fStringBuffer2.append(';');
1711:                                }
1712:                            }
1713:                        } else if (fEntityScanner.skipChar('%')) {
1714:                            while (true) {
1715:                                fStringBuffer2.append('%');
1716:                                String peName = fEntityScanner.scanName();
1717:                                if (peName == null) {
1718:                                    reportFatalError(
1719:                                            "NameRequiredInPEReference", null);
1720:                                } else if (!fEntityScanner.skipChar(';')) {
1721:                                    reportFatalError(
1722:                                            "SemicolonRequiredInPEReference",
1723:                                            new Object[] { peName });
1724:                                } else {
1725:                                    if (scanningInternalSubset()) {
1726:                                        reportFatalError(
1727:                                                "PEReferenceWithinMarkup",
1728:                                                new Object[] { peName });
1729:                                    }
1730:                                    fStringBuffer2.append(peName);
1731:                                    fStringBuffer2.append(';');
1732:                                }
1733:                                startPE(peName, true);
1734:                                // REVISIT: [Q] Why do we skip spaces here? -Ac
1735:                                // REVISIT: This will make returning the non-
1736:                                //          normalized value harder. -Ac
1737:                                fEntityScanner.skipSpaces();
1738:                                if (!fEntityScanner.skipChar('%'))
1739:                                    break;
1740:                            }
1741:                        } else {
1742:                            int c = fEntityScanner.peekChar();
1743:                            if (XMLChar.isHighSurrogate(c)) {
1744:                                scanSurrogates(fStringBuffer2);
1745:                            } else if (isInvalidLiteral(c)) {
1746:                                reportFatalError("InvalidCharInLiteral",
1747:                                        new Object[] { Integer.toHexString(c) });
1748:                                fEntityScanner.scanChar();
1749:                            }
1750:                            // if it's not the delimiting quote or if it is but from a
1751:                            // different entity than the one this literal started from,
1752:                            // simply append the character to our buffer
1753:                            else if (c != quote || entityDepth != fEntityDepth) {
1754:                                fStringBuffer.append((char) c);
1755:                                fStringBuffer2.append((char) c);
1756:                                fEntityScanner.scanChar();
1757:                            }
1758:                        }
1759:                    } while (fEntityScanner.scanLiteral(quote, fString) != quote);
1760:                    fStringBuffer.append(fString);
1761:                    fStringBuffer2.append(fString);
1762:                    literal = fStringBuffer;
1763:                    literal2 = fStringBuffer2;
1764:                }
1765:                value.setValues(literal);
1766:                nonNormalizedValue.setValues(literal2);
1767:                if (!fEntityScanner.skipChar(quote)) {
1768:                    reportFatalError("CloseQuoteMissingInDecl", null);
1769:                }
1770:            } // scanEntityValue(XMLString,XMLString):void
1771:
1772:            /**
1773:             * Scans a notation declaration
1774:             * <p>
1775:             * <pre>
1776:             * [82] NotationDecl ::= '&lt;!NOTATION' S Name S (ExternalID|PublicID) S? '>'
1777:             * [83]  PublicID    ::= 'PUBLIC' S PubidLiteral
1778:             * </pre>
1779:             * <p>
1780:             * <strong>Note:</strong> Called after scanning past '&lt;!NOTATION'
1781:             */
1782:            private final void scanNotationDecl() throws IOException,
1783:                    XNIException {
1784:
1785:                // spaces
1786:                fReportEntity = false;
1787:                if (!skipSeparator(true, !scanningInternalSubset())) {
1788:                    reportFatalError(
1789:                            "MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_NOTATIONDECL",
1790:                            null);
1791:                }
1792:
1793:                // notation name
1794:                String name = fEntityScanner.scanName();
1795:                if (name == null) {
1796:                    reportFatalError(
1797:                            "MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL", null);
1798:                }
1799:
1800:                // spaces
1801:                if (!skipSeparator(true, !scanningInternalSubset())) {
1802:                    reportFatalError(
1803:                            "MSG_SPACE_REQUIRED_AFTER_NOTATION_NAME_IN_NOTATIONDECL",
1804:                            new Object[] { name });
1805:                }
1806:
1807:                // external id
1808:                scanExternalID(fStrings, true);
1809:                String systemId = fStrings[0];
1810:                String publicId = fStrings[1];
1811:                String baseSystemId = fEntityScanner.getBaseSystemId();
1812:
1813:                if (systemId == null && publicId == null) {
1814:                    reportFatalError("ExternalIDorPublicIDRequired",
1815:                            new Object[] { name });
1816:                }
1817:
1818:                // skip possible trailing space
1819:                skipSeparator(false, !scanningInternalSubset());
1820:
1821:                // end
1822:                if (!fEntityScanner.skipChar('>')) {
1823:                    reportFatalError("NotationDeclUnterminated",
1824:                            new Object[] { name });
1825:                }
1826:                fMarkUpDepth--;
1827:
1828:                fResourceIdentifier
1829:                        .setValues(publicId, systemId, baseSystemId,
1830:                                XMLEntityManager.expandSystemId(systemId,
1831:                                        baseSystemId));
1832:                if (nonValidatingMode)
1833:                    nvGrammarInfo.notationDecl(name, fResourceIdentifier, null);
1834:                // call handler
1835:                if (fDTDHandler != null) {
1836:                    //Venu Revisit wby false has been removed.
1837:                    //fResourceIdentifier.setValues(publicId, systemId, baseSystemId, XMLEntityManager.expandSystemId(systemId, baseSystemId, false));
1838:                    fDTDHandler.notationDecl(name, fResourceIdentifier, null);
1839:                }
1840:                fReportEntity = true;
1841:
1842:            } // scanNotationDecl()
1843:
1844:            /**
1845:             * Scans a conditional section. If it's a section to ignore the whole
1846:             * section gets scanned through and this method only returns after the
1847:             * closing bracket has been found. When it's an include section though, it
1848:             * returns to let the main loop take care of scanning it. In that case the
1849:             * end of the section if handled by the main loop (scanDecls).
1850:             * <p>
1851:             * <pre>
1852:             * [61] conditionalSect   ::= includeSect | ignoreSect
1853:             * [62] includeSect       ::= '&lt;![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
1854:             * [63] ignoreSect   ::= '&lt;![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
1855:             * [64] ignoreSectContents ::= Ignore ('&lt;![' ignoreSectContents ']]>' Ignore)*
1856:             * [65] Ignore            ::=    Char* - (Char* ('&lt;![' | ']]>') Char*)
1857:             * </pre>
1858:             * <p>
1859:             * <strong>Note:</strong> Called after scanning past '&lt;![' */
1860:            private final void scanConditionalSect(int currPEDepth)
1861:                    throws IOException, XNIException {
1862:
1863:                fReportEntity = false;
1864:                skipSeparator(false, !scanningInternalSubset());
1865:
1866:                if (fEntityScanner.skipString("INCLUDE")) {
1867:                    skipSeparator(false, !scanningInternalSubset());
1868:                    if (currPEDepth != fPEDepth && fValidation) {
1869:                        fErrorReporter
1870:                                .reportError(
1871:                                        XMLMessageFormatter.XML_DOMAIN,
1872:                                        "INVALID_PE_IN_CONDITIONAL",
1873:                                        new Object[] { fEntityManager.fCurrentEntity.name },
1874:                                        XMLErrorReporter.SEVERITY_ERROR);
1875:                    }
1876:                    // call handler
1877:                    if (!fEntityScanner.skipChar('[')) {
1878:                        reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD",
1879:                                null);
1880:                    }
1881:
1882:                    if (fDTDHandler != null) {
1883:                        fDTDHandler.startConditional(
1884:                                XMLDTDHandler.CONDITIONAL_INCLUDE, null);
1885:                    }
1886:                    fIncludeSectDepth++;
1887:                    // just stop there and go back to the main loop
1888:                    fReportEntity = true;
1889:                } else if (fEntityScanner.skipString("IGNORE")) {
1890:                    skipSeparator(false, !scanningInternalSubset());
1891:                    if (currPEDepth != fPEDepth && fValidation) {
1892:                        fErrorReporter
1893:                                .reportError(
1894:                                        XMLMessageFormatter.XML_DOMAIN,
1895:                                        "INVALID_PE_IN_CONDITIONAL",
1896:                                        new Object[] { fEntityManager.fCurrentEntity.name },
1897:                                        XMLErrorReporter.SEVERITY_ERROR);
1898:                    }
1899:                    // call handler
1900:                    if (fDTDHandler != null) {
1901:                        fDTDHandler.startConditional(
1902:                                XMLDTDHandler.CONDITIONAL_IGNORE, null);
1903:                    }
1904:                    if (!fEntityScanner.skipChar('[')) {
1905:                        reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD",
1906:                                null);
1907:                    }
1908:                    fReportEntity = true;
1909:                    int initialDepth = ++fIncludeSectDepth;
1910:                    if (fDTDHandler != null) {
1911:                        fIgnoreConditionalBuffer.clear();
1912:                    }
1913:                    while (true) {
1914:                        if (fEntityScanner.skipChar('<')) {
1915:                            if (fDTDHandler != null) {
1916:                                fIgnoreConditionalBuffer.append('<');
1917:                            }
1918:                            //
1919:                            // These tests are split so that we handle cases like
1920:                            // '<<![' and '<!<![' which we might otherwise miss.
1921:                            //
1922:                            if (fEntityScanner.skipChar('!')) {
1923:                                if (fEntityScanner.skipChar('[')) {
1924:                                    if (fDTDHandler != null) {
1925:                                        fIgnoreConditionalBuffer.append("![");
1926:                                    }
1927:                                    fIncludeSectDepth++;
1928:                                } else {
1929:                                    if (fDTDHandler != null) {
1930:                                        fIgnoreConditionalBuffer.append("!");
1931:                                    }
1932:                                }
1933:                            }
1934:                        } else if (fEntityScanner.skipChar(']')) {
1935:                            if (fDTDHandler != null) {
1936:                                fIgnoreConditionalBuffer.append(']');
1937:                            }
1938:                            //
1939:                            // The same thing goes for ']<![' and '<]]>', etc.
1940:                            //
1941:                            if (fEntityScanner.skipChar(']')) {
1942:                                if (fDTDHandler != null) {
1943:                                    fIgnoreConditionalBuffer.append(']');
1944:                                }
1945:                                while (fEntityScanner.skipChar(']')) {
1946:                                    /* empty loop body */
1947:                                    if (fDTDHandler != null) {
1948:                                        fIgnoreConditionalBuffer.append(']');
1949:                                    }
1950:                                }
1951:                                if (fEntityScanner.skipChar('>')) {
1952:                                    if (fIncludeSectDepth-- == initialDepth) {
1953:                                        fMarkUpDepth--;
1954:                                        // call handler
1955:                                        if (fDTDHandler != null) {
1956:                                            fLiteral
1957:                                                    .setValues(
1958:                                                            fIgnoreConditionalBuffer.ch,
1959:                                                            0,
1960:                                                            fIgnoreConditionalBuffer.length - 2);
1961:                                            fDTDHandler.ignoredCharacters(
1962:                                                    fLiteral, null);
1963:                                            fDTDHandler.endConditional(null);
1964:                                        }
1965:                                        return;
1966:                                    } else if (fDTDHandler != null) {
1967:                                        fIgnoreConditionalBuffer.append('>');
1968:                                    }
1969:                                }
1970:                            }
1971:                        } else {
1972:                            int c = fEntityScanner.scanChar();
1973:                            if (fScannerState == SCANNER_STATE_END_OF_INPUT) {
1974:                                reportFatalError("IgnoreSectUnterminated", null);
1975:                                return;
1976:                            }
1977:                            if (fDTDHandler != null) {
1978:                                fIgnoreConditionalBuffer.append((char) c);
1979:                            }
1980:                        }
1981:                    }
1982:                } else {
1983:                    reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
1984:                }
1985:
1986:            } // scanConditionalSect()
1987:
1988:            /**
1989:             * Dispatch an XML "event".
1990:             *
1991:             * @param complete True if this method is intended to scan
1992:             *                 and dispatch as much as possible.
1993:             *
1994:             * @return True if there is more to scan.
1995:             *
1996:             * @throws IOException  Thrown on i/o error.
1997:             * @throws XNIException Thrown on parse error.
1998:             *
1999:             */
2000:            protected final boolean scanDecls(boolean complete)
2001:                    throws IOException, XNIException {
2002:
2003:                skipSeparator(false, true);
2004:                boolean again = true;
2005:                //System.out.println("scanDecls"+fScannerState);
2006:                while (again && fScannerState == SCANNER_STATE_MARKUP_DECL) {
2007:                    again = complete;
2008:                    if (fEntityScanner.skipChar('<')) {
2009:                        fMarkUpDepth++;
2010:                        if (fEntityScanner.skipChar('?')) {
2011:                            fStringBuffer.clear();
2012:                            scanPI(fStringBuffer);
2013:                        } else if (fEntityScanner.skipChar('!')) {
2014:                            if (fEntityScanner.skipChar('-')) {
2015:                                if (!fEntityScanner.skipChar('-')) {
2016:                                    reportFatalError(
2017:                                            "MSG_MARKUP_NOT_RECOGNIZED_IN_DTD",
2018:                                            null);
2019:                                } else {
2020:                                    scanComment();
2021:                                }
2022:                            } else if (fEntityScanner.skipString("ELEMENT")) {
2023:                                scanElementDecl();
2024:                            } else if (fEntityScanner.skipString("ATTLIST")) {
2025:                                scanAttlistDecl();
2026:                            } else if (fEntityScanner.skipString("ENTITY")) {
2027:                                scanEntityDecl();
2028:                            } else if (fEntityScanner.skipString("NOTATION")) {
2029:                                scanNotationDecl();
2030:                            } else if (fEntityScanner.skipChar('[')
2031:                                    && !scanningInternalSubset()) {
2032:                                scanConditionalSect(fPEDepth);
2033:                            } else {
2034:                                fMarkUpDepth--;
2035:                                reportFatalError(
2036:                                        "MSG_MARKUP_NOT_RECOGNIZED_IN_DTD",
2037:                                        null);
2038:                            }
2039:                        } else {
2040:                            fMarkUpDepth--;
2041:                            reportFatalError(
2042:                                    "MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null);
2043:                        }
2044:                    } else if (fIncludeSectDepth > 0
2045:                            && fEntityScanner.skipChar(']')) {
2046:                        // end of conditional section?
2047:                        if (!fEntityScanner.skipChar(']')
2048:                                || !fEntityScanner.skipChar('>')) {
2049:                            reportFatalError("IncludeSectUnterminated", null);
2050:                        }
2051:                        // call handler
2052:                        if (fDTDHandler != null) {
2053:                            fDTDHandler.endConditional(null);
2054:                        }
2055:                        // decreaseMarkupDepth();
2056:                        fIncludeSectDepth--;
2057:                        fMarkUpDepth--;
2058:                    } else if (scanningInternalSubset()
2059:                            && fEntityScanner.peekChar() == ']') {
2060:                        // this is the end of the internal subset, let's stop here
2061:                        return false;
2062:                    } else if (fEntityScanner.skipSpaces()) {
2063:                        // simply skip
2064:                    } else {
2065:                        reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD",
2066:                                null);
2067:                    }
2068:                    skipSeparator(false, true);
2069:                }
2070:                return fScannerState != SCANNER_STATE_END_OF_INPUT;
2071:            }
2072:
2073:            /**
2074:             * Skip separator. This is typically just whitespace but it can also be one
2075:             * or more parameter entity references.
2076:             * <p>
2077:             * If there are some it "expands them" by calling the corresponding entity
2078:             * from the entity manager.
2079:             * <p>
2080:             * This is recursive and will process has many refs as possible.
2081:             *
2082:             * @param spaceRequired Specify whether some leading whitespace should be
2083:             *                      found
2084:             * @param lookForPERefs Specify whether parameter entity references should
2085:             *                      be looked for
2086:             * @return True if any leading whitespace was found or the end of a
2087:             *         parameter entity was crossed.
2088:             */
2089:            private boolean skipSeparator(boolean spaceRequired,
2090:                    boolean lookForPERefs) throws IOException, XNIException {
2091:                int depth = fPEDepth;
2092:                boolean sawSpace = fEntityScanner.skipSpaces();
2093:                if (!lookForPERefs || !fEntityScanner.skipChar('%')) {
2094:                    return !spaceRequired || sawSpace || (depth != fPEDepth);
2095:                }
2096:                while (true) {
2097:                    String name = fEntityScanner.scanName();
2098:                    if (name == null) {
2099:                        reportFatalError("NameRequiredInPEReference", null);
2100:                    } else if (!fEntityScanner.skipChar(';')) {
2101:                        reportFatalError("SemicolonRequiredInPEReference",
2102:                                new Object[] { name });
2103:                    }
2104:                    startPE(name, false);
2105:                    fEntityScanner.skipSpaces();
2106:                    if (!fEntityScanner.skipChar('%'))
2107:                        return true;
2108:                }
2109:            }
2110:
2111:            /*
2112:             * Element Children Content Stack
2113:             */
2114:            private final void pushContentStack(int c) {
2115:                if (fContentStack.length == fContentDepth) {
2116:                    int[] newStack = new int[fContentDepth * 2];
2117:                    System.arraycopy(fContentStack, 0, newStack, 0,
2118:                            fContentDepth);
2119:                    fContentStack = newStack;
2120:                }
2121:                fContentStack[fContentDepth++] = c;
2122:            }
2123:
2124:            private final int popContentStack() {
2125:                return fContentStack[--fContentDepth];
2126:            }
2127:
2128:            /*
2129:             * Parameter Entity Stack
2130:             */
2131:            private final void pushPEStack(int depth, boolean report) {
2132:                if (fPEStack.length == fPEDepth) {
2133:                    int[] newIntStack = new int[fPEDepth * 2];
2134:                    System.arraycopy(fPEStack, 0, newIntStack, 0, fPEDepth);
2135:                    fPEStack = newIntStack;
2136:                    // report end/start calls
2137:                    boolean[] newBooleanStack = new boolean[fPEDepth * 2];
2138:                    System
2139:                            .arraycopy(fPEReport, 0, newBooleanStack, 0,
2140:                                    fPEDepth);
2141:                    fPEReport = newBooleanStack;
2142:
2143:                }
2144:                fPEReport[fPEDepth] = report;
2145:                fPEStack[fPEDepth++] = depth;
2146:            }
2147:
2148:            /** pop the stack */
2149:            private final int popPEStack() {
2150:                return fPEStack[--fPEDepth];
2151:            }
2152:
2153:            /** look at the top of the stack */
2154:            private final boolean peekReportEntity() {
2155:                return fPEReport[fPEDepth - 1];
2156:            }
2157:
2158:            /*
2159:             * Utility method
2160:             */
2161:            private final void ensureEnumerationSize(int size) {
2162:                if (fEnumeration.length == size) {
2163:                    String[] newEnum = new String[size * 2];
2164:                    System.arraycopy(fEnumeration, 0, newEnum, 0, size);
2165:                    fEnumeration = newEnum;
2166:                }
2167:            }
2168:
2169:            // private methods
2170:            private void init() {
2171:                // reset state related data
2172:                fStartDTDCalled = false;
2173:                fExtEntityDepth = 0;
2174:                fIncludeSectDepth = 0;
2175:                fMarkUpDepth = 0;
2176:                fPEDepth = 0;
2177:
2178:                fStandalone = false;
2179:                fSeenExternalDTD = false;
2180:                fSeenExternalPE = false;
2181:
2182:                // set starting state
2183:                fSymbolTable = (SymbolTable) fPropertyManager
2184:                        .getProperty(Constants.XERCES_PROPERTY_PREFIX
2185:                                + Constants.SYMBOL_TABLE_PROPERTY);
2186:                setScannerState(SCANNER_STATE_TEXT_DECL);
2187:                //Revisit : Create new grammar until we implement GrammarPool.
2188:                nvGrammarInfo = new DTDGrammar(fSymbolTable);
2189:                //new SymbolTable());
2190:            }
2191:
2192:            public DTDGrammar getGrammar() {
2193:                return nvGrammarInfo;
2194:            }
2195:
2196:        } // class XMLDTDScannerImpl
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.