/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xerces" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.apache.org. For more * information on the Apache Software Foundation, please see * . */ 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 * * @version $Id: XMLGrammarPoolImpl.java,v 1.6 2003/07/30 21:30:04 elena Exp $ */ 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; } // () /** Constructs a grammar pool with a specified number of buckets. */ public XMLGrammarPoolImpl(int initialCapacity) { fGrammars = new Entry[initialCapacity]; fPoolIsLocked = false; } // // XMLGrammarPool methods // /*

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.

* * @param grammarType The type of the grammar, from the * com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription * 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[] /*

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.

*

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.

* * @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[]); /*

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.

* An application must not call its EntityResolver itself * from this method; this may result in infinite recursions. * * 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 /*

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() /*

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() /* *

This method clears the pool-i.e., removes references * to all the grammars in it.

*/ public void clear() { for (int i=0; i