You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
13 KiB
367 lines
13 KiB
/*
|
|
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*/
|
|
/*
|
|
* Copyright 1999-2002,2004 The Apache Software Foundation.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.sun.org.apache.xerces.internal.util;
|
|
|
|
import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
|
|
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
|
|
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
|
|
|
|
/**
|
|
* Stores grammars in a pool associated to a specific key. This grammar pool
|
|
* implementation stores two types of grammars: those keyed by the root element
|
|
* name, and those keyed by the grammar's target namespace.
|
|
*
|
|
* This is the default implementation of the GrammarPool interface.
|
|
* As we move forward, this will become more function-rich and robust.
|
|
*
|
|
* @author Jeffrey Rodriguez, IBM
|
|
* @author Andy Clark, IBM
|
|
* @author Neil Graham, IBM
|
|
* @author Pavani Mukthipudi, Sun Microsystems
|
|
* @author Neeraj Bajaj, SUN Microsystems
|
|
*
|
|
*/
|
|
public class XMLGrammarPoolImpl implements XMLGrammarPool {
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
/** Default size. */
|
|
protected static final int TABLE_SIZE = 11;
|
|
|
|
//
|
|
// Data
|
|
//
|
|
|
|
/** Grammars. */
|
|
protected Entry[] fGrammars = null;
|
|
|
|
// whether this pool is locked
|
|
protected boolean fPoolIsLocked;
|
|
|
|
// the number of grammars in the pool
|
|
protected int fGrammarCount = 0;
|
|
|
|
private static final boolean DEBUG = false ;
|
|
|
|
//
|
|
// Constructors
|
|
//
|
|
|
|
/** Constructs a grammar pool with a default number of buckets. */
|
|
public XMLGrammarPoolImpl() {
|
|
fGrammars = new Entry[TABLE_SIZE];
|
|
fPoolIsLocked = false;
|
|
} // <init>()
|
|
|
|
/** Constructs a grammar pool with a specified number of buckets. */
|
|
public XMLGrammarPoolImpl(int initialCapacity) {
|
|
fGrammars = new Entry[initialCapacity];
|
|
fPoolIsLocked = false;
|
|
}
|
|
|
|
//
|
|
// XMLGrammarPool methods
|
|
//
|
|
|
|
/* <p> Retrieve the initial known set of grammars. This method is
|
|
* called by a validator before the validation starts. The application
|
|
* can provide an initial set of grammars available to the current
|
|
* validation attempt. </p>
|
|
*
|
|
* @param grammarType The type of the grammar, from the
|
|
* <code>com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription</code>
|
|
* interface.
|
|
* @return The set of grammars the validator may put in its "bucket"
|
|
*/
|
|
public Grammar [] retrieveInitialGrammarSet (String grammarType) {
|
|
synchronized (fGrammars) {
|
|
int grammarSize = fGrammars.length ;
|
|
Grammar [] tempGrammars = new Grammar[fGrammarCount];
|
|
int pos = 0;
|
|
for (int i = 0; i < grammarSize; i++) {
|
|
for (Entry e = fGrammars[i]; e != null; e = e.next) {
|
|
if (e.desc.getGrammarType().equals(grammarType)) {
|
|
tempGrammars[pos++] = e.grammar;
|
|
}
|
|
}
|
|
}
|
|
Grammar[] toReturn = new Grammar[pos];
|
|
System.arraycopy(tempGrammars, 0, toReturn, 0, pos);
|
|
return toReturn;
|
|
}
|
|
} // retrieveInitialGrammarSet (String): Grammar[]
|
|
|
|
/* <p> Return the final set of grammars that the validator ended up
|
|
* with. This method is called after the validation finishes. The
|
|
* application may then choose to cache some of the returned grammars.</p>
|
|
* <p>In this implementation, we make our choice based on whether this object
|
|
* is "locked"--that is, whether the application has instructed
|
|
* us not to accept any new grammars.</p>
|
|
*
|
|
* @param grammarType The type of the grammars being returned;
|
|
* @param grammars An array containing the set of grammars being
|
|
* returned; order is not significant.
|
|
*/
|
|
public void cacheGrammars(String grammarType, Grammar[] grammars) {
|
|
if(!fPoolIsLocked) {
|
|
for (int i = 0; i < grammars.length; i++) {
|
|
if(DEBUG) {
|
|
System.out.println("CACHED GRAMMAR " + (i+1) ) ;
|
|
Grammar temp = grammars[i] ;
|
|
//print(temp.getGrammarDescription());
|
|
}
|
|
putGrammar(grammars[i]);
|
|
}
|
|
}
|
|
} // cacheGrammars(String, Grammar[]);
|
|
|
|
/* <p> This method requests that the application retrieve a grammar
|
|
* corresponding to the given GrammarIdentifier from its cache.
|
|
* If it cannot do so it must return null; the parser will then
|
|
* call the EntityResolver. </p>
|
|
* <strong>An application must not call its EntityResolver itself
|
|
* from this method; this may result in infinite recursions.</strong>
|
|
*
|
|
* This implementation chooses to use the root element name to identify a DTD grammar
|
|
* and the target namespace to identify a Schema grammar.
|
|
*
|
|
* @param desc The description of the Grammar being requested.
|
|
* @return The Grammar corresponding to this description or null if
|
|
* no such Grammar is known.
|
|
*/
|
|
public Grammar retrieveGrammar(XMLGrammarDescription desc) {
|
|
if(DEBUG){
|
|
System.out.println("RETRIEVING GRAMMAR FROM THE APPLICATION WITH FOLLOWING DESCRIPTION :");
|
|
//print(desc);
|
|
}
|
|
return getGrammar(desc);
|
|
} // retrieveGrammar(XMLGrammarDescription): Grammar
|
|
|
|
//
|
|
// Public methods
|
|
//
|
|
|
|
/**
|
|
* Puts the specified grammar into the grammar pool and associates it to
|
|
* its root element name or its target namespace.
|
|
*
|
|
* @param grammar The Grammar.
|
|
*/
|
|
public void putGrammar(Grammar grammar) {
|
|
if(!fPoolIsLocked) {
|
|
synchronized (fGrammars) {
|
|
XMLGrammarDescription desc = grammar.getGrammarDescription();
|
|
int hash = hashCode(desc);
|
|
int index = (hash & 0x7FFFFFFF) % fGrammars.length;
|
|
for (Entry entry = fGrammars[index]; entry != null; entry = entry.next) {
|
|
if (entry.hash == hash && equals(entry.desc, desc)) {
|
|
entry.grammar = grammar;
|
|
return;
|
|
}
|
|
}
|
|
// create a new entry
|
|
Entry entry = new Entry(hash, desc, grammar, fGrammars[index]);
|
|
fGrammars[index] = entry;
|
|
fGrammarCount++;
|
|
}
|
|
}
|
|
} // putGrammar(Grammar)
|
|
|
|
/**
|
|
* Returns the grammar associated to the specified grammar description.
|
|
* Currently, the root element name is used as the key for DTD grammars
|
|
* and the target namespace is used as the key for Schema grammars.
|
|
*
|
|
* @param desc The Grammar Description.
|
|
*/
|
|
public Grammar getGrammar(XMLGrammarDescription desc) {
|
|
synchronized (fGrammars) {
|
|
int hash = hashCode(desc);
|
|
int index = (hash & 0x7FFFFFFF) % fGrammars.length;
|
|
for (Entry entry = fGrammars[index] ; entry != null ; entry = entry.next) {
|
|
if ((entry.hash == hash) && equals(entry.desc, desc)) {
|
|
return entry.grammar;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
} // getGrammar(XMLGrammarDescription):Grammar
|
|
|
|
/**
|
|
* Removes the grammar associated to the specified grammar description from the
|
|
* grammar pool and returns the removed grammar. Currently, the root element name
|
|
* is used as the key for DTD grammars and the target namespace is used
|
|
* as the key for Schema grammars.
|
|
*
|
|
* @param desc The Grammar Description.
|
|
* @return The removed grammar.
|
|
*/
|
|
public Grammar removeGrammar(XMLGrammarDescription desc) {
|
|
synchronized (fGrammars) {
|
|
int hash = hashCode(desc);
|
|
int index = (hash & 0x7FFFFFFF) % fGrammars.length;
|
|
for (Entry entry = fGrammars[index], prev = null ; entry != null ; prev = entry, entry = entry.next) {
|
|
if ((entry.hash == hash) && equals(entry.desc, desc)) {
|
|
if (prev != null) {
|
|
prev.next = entry.next;
|
|
}
|
|
else {
|
|
fGrammars[index] = entry.next;
|
|
}
|
|
Grammar tempGrammar = entry.grammar;
|
|
entry.grammar = null;
|
|
fGrammarCount--;
|
|
return tempGrammar;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
} // removeGrammar(XMLGrammarDescription):Grammar
|
|
|
|
/**
|
|
* Returns true if the grammar pool contains a grammar associated
|
|
* to the specified grammar description. Currently, the root element name
|
|
* is used as the key for DTD grammars and the target namespace is used
|
|
* as the key for Schema grammars.
|
|
*
|
|
* @param desc The Grammar Description.
|
|
*/
|
|
public boolean containsGrammar(XMLGrammarDescription desc) {
|
|
synchronized (fGrammars) {
|
|
int hash = hashCode(desc);
|
|
int index = (hash & 0x7FFFFFFF) % fGrammars.length;
|
|
for (Entry entry = fGrammars[index] ; entry != null ; entry = entry.next) {
|
|
if ((entry.hash == hash) && equals(entry.desc, desc)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
} // containsGrammar(XMLGrammarDescription):boolean
|
|
|
|
/* <p> Sets this grammar pool to a "locked" state--i.e.,
|
|
* no new grammars will be added until it is "unlocked".
|
|
*/
|
|
public void lockPool() {
|
|
fPoolIsLocked = true;
|
|
} // lockPool()
|
|
|
|
/* <p> Sets this grammar pool to an "unlocked" state--i.e.,
|
|
* new grammars will be added when putGrammar or cacheGrammars
|
|
* are called.
|
|
*/
|
|
public void unlockPool() {
|
|
fPoolIsLocked = false;
|
|
} // unlockPool()
|
|
|
|
/*
|
|
* <p>This method clears the pool-i.e., removes references
|
|
* to all the grammars in it.</p>
|
|
*/
|
|
public void clear() {
|
|
for (int i=0; i<fGrammars.length; i++) {
|
|
if(fGrammars[i] != null) {
|
|
fGrammars[i].clear();
|
|
fGrammars[i] = null;
|
|
}
|
|
}
|
|
fGrammarCount = 0;
|
|
} // clear()
|
|
|
|
/**
|
|
* This method checks whether two grammars are the same. Currently, we compare
|
|
* the root element names for DTD grammars and the target namespaces for Schema grammars.
|
|
* The application can override this behaviour and add its own logic.
|
|
*
|
|
* @param desc1 The grammar description
|
|
* @param desc2 The grammar description of the grammar to be compared to
|
|
* @return True if the grammars are equal, otherwise false
|
|
*/
|
|
public boolean equals(XMLGrammarDescription desc1, XMLGrammarDescription desc2) {
|
|
return desc1.equals(desc2);
|
|
}
|
|
|
|
/**
|
|
* Returns the hash code value for the given grammar description.
|
|
*
|
|
* @param desc The grammar description
|
|
* @return The hash code value
|
|
*/
|
|
public int hashCode(XMLGrammarDescription desc) {
|
|
return desc.hashCode();
|
|
}
|
|
|
|
/**
|
|
* This class is a grammar pool entry. Each entry acts as a node
|
|
* in a linked list.
|
|
*/
|
|
protected static final class Entry {
|
|
public int hash;
|
|
public XMLGrammarDescription desc;
|
|
public Grammar grammar;
|
|
public Entry next;
|
|
|
|
protected Entry(int hash, XMLGrammarDescription desc, Grammar grammar, Entry next) {
|
|
this.hash = hash;
|
|
this.desc = desc;
|
|
this.grammar = grammar;
|
|
this.next = next;
|
|
}
|
|
|
|
// clear this entry; useful to promote garbage collection
|
|
// since reduces reference count of objects to be destroyed
|
|
protected void clear () {
|
|
desc = null;
|
|
grammar = null;
|
|
if(next != null) {
|
|
next.clear();
|
|
next = null;
|
|
}
|
|
} // clear()
|
|
} // class Entry
|
|
|
|
/* For DTD build we can't import here XSDDescription. Thus, this method is commented out.. */
|
|
/* public void print(XMLGrammarDescription description){
|
|
if(description.getGrammarType().equals(XMLGrammarDescription.XML_DTD)){
|
|
|
|
}
|
|
else if(description.getGrammarType().equals(XMLGrammarDescription.XML_SCHEMA)){
|
|
XSDDescription schema = (XSDDescription)description ;
|
|
System.out.println("Context = " + schema.getContextType());
|
|
System.out.println("TargetNamespace = " + schema.getTargetNamespace());
|
|
String [] temp = schema.getLocationHints();
|
|
|
|
for (int i = 0 ; (temp != null && i < temp.length) ; i++){
|
|
System.out.println("LocationHint " + i + " = "+ temp[i]);
|
|
}
|
|
|
|
System.out.println("Triggering Component = " + schema.getTriggeringComponent());
|
|
System.out.println("EnclosingElementName =" + schema.getEnclosingElementName());
|
|
|
|
}
|
|
|
|
}//print
|
|
*/
|
|
|
|
} // class XMLGrammarPoolImpl
|