Path: blob/aarch64-shenandoah-jdk8u272-b10/jaxp/src/com/sun/xml/internal/stream/dtd/DTDGrammarUtil.java
48433 views
/*1* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.2*/34/*5* Copyright 2005 The Apache Software Foundation.6*7* Licensed under the Apache License, Version 2.0 (the "License");8* you may not use this file except in compliance with the License.9* You may obtain a copy of the License at10*11* http://www.apache.org/licenses/LICENSE-2.012*13* Unless required by applicable law or agreed to in writing, software14* distributed under the License is distributed on an "AS IS" BASIS,15* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.16* See the License for the specific language governing permissions and17* limitations under the License.18*/1920package com.sun.xml.internal.stream.dtd;21import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar;22import com.sun.xml.internal.stream.dtd.nonvalidating.XMLAttributeDecl;23import com.sun.xml.internal.stream.dtd.nonvalidating.XMLElementDecl;24import com.sun.xml.internal.stream.dtd.nonvalidating.XMLSimpleType;25import com.sun.org.apache.xerces.internal.impl.Constants;26import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;27import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;28import com.sun.org.apache.xerces.internal.util.SymbolTable;29import com.sun.org.apache.xerces.internal.util.XMLChar;30import com.sun.org.apache.xerces.internal.util.XMLSymbols;31import com.sun.org.apache.xerces.internal.xni.Augmentations;32import com.sun.org.apache.xerces.internal.xni.QName;33import com.sun.org.apache.xerces.internal.xni.NamespaceContext;34import com.sun.org.apache.xerces.internal.xni.XMLAttributes;35import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;36import com.sun.org.apache.xerces.internal.xni.XMLLocator;37import com.sun.org.apache.xerces.internal.xni.XMLString;38import com.sun.org.apache.xerces.internal.xni.XNIException;39import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;40import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;41import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;42import javax.xml.XMLConstants;4344/*45* @author Eric Ye, IBM46* @author Andy Clark, IBM47* @author Jeffrey Rodriguez IBM48* @author Neil Graham, IBM49* @author Sunitha Reddy, Sun Microsystems50*/5152public class DTDGrammarUtil {535455/** Property identifier: symbol table. */56protected static final String SYMBOL_TABLE =57Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;5859protected static final String NAMESPACES =60Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;616263/** Compile to true to debug attributes. */64private static final boolean DEBUG_ATTRIBUTES = false;6566/** Compile to true to debug element children. */67private static final boolean DEBUG_ELEMENT_CHILDREN = false;6869protected DTDGrammar fDTDGrammar = null;70/** Namespaces. */71protected boolean fNamespaces;7273/** Symbol table. */74protected SymbolTable fSymbolTable = null;7576/** Current element index. */77private int fCurrentElementIndex = -1;7879/** Current content spec type. */80private int fCurrentContentSpecType = -1;8182/** Content spec type stack. */83private boolean[] fElementContentState = new boolean[8];8485/** Element depth. */86private int fElementDepth = -1;8788/** True if inside of element content. */89private boolean fInElementContent = false;9091/** Temporary atribute declaration. */92private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();9394/** Temporary qualified name. */95private QName fTempQName = new QName();9697/** Temporary string buffers. */98private StringBuffer fBuffer = new StringBuffer();99100private NamespaceContext fNamespaceContext = null;101102/** Default constructor. */103public DTDGrammarUtil(SymbolTable symbolTable) {104fSymbolTable = symbolTable;105}106107public DTDGrammarUtil(DTDGrammar grammar, SymbolTable symbolTable) {108fDTDGrammar = grammar;109fSymbolTable = symbolTable;110}111112public DTDGrammarUtil(DTDGrammar grammar, SymbolTable symbolTable,113NamespaceContext namespaceContext) {114fDTDGrammar = grammar;115fSymbolTable = symbolTable;116fNamespaceContext = namespaceContext;117}118119/*120* Resets the component. The component can query the component manager121* about any features and properties that affect the operation of the122* component.123*124* @param componentManager The component manager.125*126* @throws SAXException Thrown by component on finitialization error.127* For example, if a feature or property is128* required for the operation of the component, the129* component manager may throw a130* SAXNotRecognizedException or a131* SAXNotSupportedException.132*/133public void reset(XMLComponentManager componentManager)134throws XMLConfigurationException {135136fDTDGrammar = null;137fInElementContent = false;138fCurrentElementIndex = -1;139fCurrentContentSpecType = -1;140fNamespaces = componentManager.getFeature(NAMESPACES, true);141fSymbolTable = (SymbolTable) componentManager.getProperty(142Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY);143fElementDepth = -1;144}145146147/**148* The start of an element.149*150* @param element The name of the element.151* @param attributes The element attributes.152* @param augs Additional information that may include infoset augmentations153*154* @throws XNIException Thrown by handler to signal an error.155*/156public void startElement(QName element, XMLAttributes attributes) throws XNIException {157handleStartElement(element, attributes);158}159160/**161* The end of an element.162*163* @param element The name of the element.164* @param augs Additional information that may include infoset augmentations165*166* @throws XNIException Thrown by handler to signal an error.167*/168public void endElement(QName element) throws XNIException {169handleEndElement(element);170}171172/**173* The start of a CDATA section.174* @param augs Additional information that may include infoset augmentations175*176* @throws XNIException Thrown by handler to signal an error.177*/178public void startCDATA(Augmentations augs) throws XNIException {179}180181/**182* The end of a CDATA section.183* @param augs Additional information that may include infoset augmentations184*185* @throws XNIException Thrown by handler to signal an error.186*/187public void endCDATA(Augmentations augs) throws XNIException {188}189190191192/** Add default attributes and validate. */193public void addDTDDefaultAttrs(QName elementName, XMLAttributes attributes)194throws XNIException {195196int elementIndex;197elementIndex = fDTDGrammar.getElementDeclIndex(elementName);198// is there anything to do?199if (elementIndex == -1 || fDTDGrammar == null) {200return;201}202203//204// Check after all specified attrs are scanned205// (1) report error for REQUIRED attrs that are missing (V_TAGc)206// (2) add default attrs (FIXED and NOT_FIXED)207//208int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);209210while (attlistIndex != -1) {211212fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);213214if (DEBUG_ATTRIBUTES) {215if (fTempAttDecl != null) {216XMLElementDecl elementDecl = new XMLElementDecl();217fDTDGrammar.getElementDecl(elementIndex, elementDecl);218System.out.println("element: " + (elementDecl.name.localpart));219System.out.println("attlistIndex " + attlistIndex + "\n" +220"attName : '" + (fTempAttDecl.name.localpart) + "'\n"221+ "attType : " + fTempAttDecl.simpleType.type + "\n"222+ "attDefaultType : " + fTempAttDecl.simpleType.defaultType + "\n"223+ "attDefaultValue : '" + fTempAttDecl.simpleType.defaultValue + "'\n"224+ attributes.getLength() + "\n"225);226}227}228String attPrefix = fTempAttDecl.name.prefix;229String attLocalpart = fTempAttDecl.name.localpart;230String attRawName = fTempAttDecl.name.rawname;231String attType = getAttributeTypeName(fTempAttDecl);232int attDefaultType = fTempAttDecl.simpleType.defaultType;233String attValue = null;234235if (fTempAttDecl.simpleType.defaultValue != null) {236attValue = fTempAttDecl.simpleType.defaultValue;237}238boolean specified = false;239boolean required = attDefaultType == XMLSimpleType.DEFAULT_TYPE_REQUIRED;240boolean cdata = attType == XMLSymbols.fCDATASymbol;241242if (!cdata || required || attValue != null) {243244//check whether attribute is a namespace declaration245if (fNamespaceContext != null && attRawName.startsWith(XMLConstants.XMLNS_ATTRIBUTE)) {246String prefix = "";247int pos = attRawName.indexOf(':');248if (pos != -1) {249prefix = attRawName.substring(0, pos);250} else {251prefix = attRawName;252}253prefix = fSymbolTable.addSymbol(prefix);254if (!((com.sun.org.apache.xerces.internal.util.255NamespaceSupport) fNamespaceContext).256containsPrefixInCurrentContext(prefix)) {257fNamespaceContext.declarePrefix(prefix, attValue);258}259specified = true;260} else {261262int attrCount = attributes.getLength();263for (int i = 0; i < attrCount; i++) {264if (attributes.getQName(i) == attRawName) {265specified = true;266break;267}268}269270}271272}273274if (!specified) {275if (attValue != null) {276if (fNamespaces) {277int index = attRawName.indexOf(':');278if (index != -1) {279attPrefix = attRawName.substring(0, index);280attPrefix = fSymbolTable.addSymbol(attPrefix);281attLocalpart = attRawName.substring(index + 1);282attLocalpart = fSymbolTable.addSymbol(attLocalpart);283}284}285fTempQName.setValues(attPrefix, attLocalpart, attRawName,286fTempAttDecl.name.uri);287int newAttr = attributes.addAttribute(fTempQName, attType,288attValue);289}290}291attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);292}293294// now iterate through the expanded attributes for295// 1. if every attribute seen is declared in the DTD296// 2. check if the VC: default_fixed holds297// 3. validate every attribute.298int attrCount = attributes.getLength();299for (int i = 0; i < attrCount; i++) {300String attrRawName = attributes.getQName(i);301boolean declared = false;302int position =303fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);304while (position != -1) {305fDTDGrammar.getAttributeDecl(position, fTempAttDecl);306if (fTempAttDecl.name.rawname == attrRawName) {307// found the match att decl,308declared = true;309break;310}311position = fDTDGrammar.getNextAttributeDeclIndex(position);312}313if (!declared) {314continue;315}316317String type = getAttributeTypeName(fTempAttDecl);318attributes.setType(i, type);319320boolean changedByNormalization = false;321if (attributes.isSpecified(i) && type != XMLSymbols.fCDATASymbol) {322changedByNormalization = normalizeAttrValue(attributes, i);323}324} // for all attributes325326} // addDTDDefaultAttrsAndValidate(int,XMLAttrList)327328329/**330* Normalize the attribute value of a non CDATA attributes collapsing331* sequences of space characters (x20)332*333* @param attributes The list of attributes334* @param index The index of the attribute to normalize335*/336private boolean normalizeAttrValue(XMLAttributes attributes, int index) {337// vars338boolean leadingSpace = true;339boolean spaceStart = false;340boolean readingNonSpace = false;341int count = 0;342int eaten = 0;343String attrValue = attributes.getValue(index);344char[] attValue = new char[attrValue.length()];345346fBuffer.setLength(0);347attrValue.getChars(0, attrValue.length(), attValue, 0);348for (int i = 0; i < attValue.length; i++) {349350if (attValue[i] == ' ') {351352// now the tricky part353if (readingNonSpace) {354spaceStart = true;355readingNonSpace = false;356}357358if (spaceStart && !leadingSpace) {359spaceStart = false;360fBuffer.append(attValue[i]);361count++;362} else {363if (leadingSpace || !spaceStart) {364eaten++;365}366}367368} else {369readingNonSpace = true;370spaceStart = false;371leadingSpace = false;372fBuffer.append(attValue[i]);373count++;374}375}376377// check if the last appended character is a space.378if (count > 0 && fBuffer.charAt(count - 1) == ' ') {379fBuffer.setLength(count - 1);380381}382String newValue = fBuffer.toString();383attributes.setValue(index, newValue);384return !attrValue.equals(newValue);385}386387388389/** convert attribute type from ints to strings */390private String getAttributeTypeName(XMLAttributeDecl attrDecl) {391392switch (attrDecl.simpleType.type) {393case XMLSimpleType.TYPE_ENTITY: {394return attrDecl.simpleType.list ? XMLSymbols.fENTITIESSymbol :395XMLSymbols.fENTITYSymbol;396}397case XMLSimpleType.TYPE_ENUMERATION: {398StringBuffer buffer = new StringBuffer();399buffer.append('(');400for (int i = 0; i < attrDecl.simpleType.enumeration.length; i++) {401if (i > 0) {402buffer.append("|");403}404buffer.append(attrDecl.simpleType.enumeration[i]);405}406buffer.append(')');407return fSymbolTable.addSymbol(buffer.toString());408}409case XMLSimpleType.TYPE_ID: {410return XMLSymbols.fIDSymbol;411}412case XMLSimpleType.TYPE_IDREF: {413return attrDecl.simpleType.list ? XMLSymbols.fIDREFSSymbol :414XMLSymbols.fIDREFSymbol;415}416case XMLSimpleType.TYPE_NMTOKEN: {417return attrDecl.simpleType.list ? XMLSymbols.fNMTOKENSSymbol :418XMLSymbols.fNMTOKENSymbol;419}420case XMLSimpleType.TYPE_NOTATION: {421return XMLSymbols.fNOTATIONSymbol;422}423}424return XMLSymbols.fCDATASymbol;425426}427428429/** ensure element stack capacity */430private void ensureStackCapacity(int newElementDepth) {431if (newElementDepth == fElementContentState.length) {432boolean[] newStack = new boolean[newElementDepth * 2];433System.arraycopy(this.fElementContentState, 0, newStack, 0,434newElementDepth);435fElementContentState = newStack;436}437}438439440441/** Handle element442* @return true if validator is removed from the pipeline443*/444protected void handleStartElement(QName element, XMLAttributes attributes) throws XNIException {445446if (fDTDGrammar == null) {447fCurrentElementIndex = -1;448fCurrentContentSpecType = -1;449fInElementContent = false;450return;451} else {452fCurrentElementIndex = fDTDGrammar.getElementDeclIndex(element);453fCurrentContentSpecType = fDTDGrammar.getContentSpecType(454fCurrentElementIndex);455//handleDTDDefaultAttrs(element,attributes);456addDTDDefaultAttrs(element, attributes);457}458459fInElementContent = fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN;460fElementDepth++;461ensureStackCapacity(fElementDepth);462fElementContentState[fElementDepth] = fInElementContent;463}464465466/** Handle end element. */467protected void handleEndElement(QName element) throws XNIException {468if (fDTDGrammar == null) return;469fElementDepth--;470if (fElementDepth < -1) {471throw new RuntimeException("FWK008 Element stack underflow");472}473if (fElementDepth < 0) {474fCurrentElementIndex = -1;475fCurrentContentSpecType = -1;476fInElementContent = false;477return;478}479fInElementContent = fElementContentState[fElementDepth];480}481482public boolean isInElementContent() {483return fInElementContent;484}485486public boolean isIgnorableWhiteSpace(XMLString text) {487if (isInElementContent()) {488for (int i = text.offset; i < text.offset + text.length; i++) {489if (!XMLChar.isSpace(text.ch[i])) {490return false;491}492}493return true;494}495return false;496}497}498499500