FileDocCategorySizeDatePackage
SoftReferenceGrammarPool.javaAPI DocApache Xerces 3.0.116839Fri Sep 14 20:33:54 BST 2007org.apache.xerces.jaxp.validation

SoftReferenceGrammarPool

public final class SoftReferenceGrammarPool extends Object implements org.apache.xerces.xni.grammars.XMLGrammarPool

This grammar pool is a memory sensitive cache. The grammars stored in the pool are softly reachable and may be cleared by the garbage collector in response to memory demand. Equality of XMLSchemaDescriptions is determined using both the target namespace for the schema and schema location.

author
Michael Glavassevich, IBM
version
$Id: SoftReferenceGrammarPool.java 447235 2006-09-18 05:01:44Z mrglavas $

Fields Summary
protected static final int
TABLE_SIZE
Default size.
protected static final org.apache.xerces.xni.grammars.Grammar[]
ZERO_LENGTH_GRAMMAR_ARRAY
Zero length grammar array.
protected Entry[]
fGrammars
Grammars.
protected boolean
fPoolIsLocked
Flag indicating whether this pool is locked
protected int
fGrammarCount
The number of grammars in the pool
protected final ReferenceQueue
fReferenceQueue
Reference queue for cleared grammar references
Constructors Summary
public SoftReferenceGrammarPool()
Constructs a grammar pool with a default number of buckets.

    
    //
    // Constructors
    //
    
               
      
        fGrammars = new Entry[TABLE_SIZE];
        fPoolIsLocked = false;
    
public SoftReferenceGrammarPool(int initialCapacity)
Constructs a grammar pool with a specified number of buckets.

        fGrammars = new Entry[initialCapacity];
        fPoolIsLocked = false;
    
Methods Summary
public voidcacheGrammars(java.lang.String grammarType, org.apache.xerces.xni.grammars.Grammar[] grammars)

        if (!fPoolIsLocked) {
            for (int i = 0; i < grammars.length; ++i) {
                putGrammar(grammars[i]);
            }
        }
    
private voidclean()
Removes stale entries from the pool.

        Reference ref = fReferenceQueue.poll();
        while (ref != null) {
            Entry entry = ((SoftGrammarReference) ref).entry;
            if (entry != null) {
                removeEntry(entry);
            }
            ref = fReferenceQueue.poll();
        }
    
public voidclear()

        for (int i=0; i<fGrammars.length; i++) {
            if(fGrammars[i] != null) {
                fGrammars[i].clear();
                fGrammars[i] = null;
            }
        }
        fGrammarCount = 0;
    
public booleancontainsGrammar(org.apache.xerces.xni.grammars.XMLGrammarDescription desc)
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.

        synchronized (fGrammars) {
            clean();
            int hash = hashCode(desc);
            int index = (hash & 0x7FFFFFFF) % fGrammars.length;
            for (Entry entry = fGrammars[index]; entry != null ; entry = entry.next) {
                Grammar tempGrammar = (Grammar) entry.grammar.get();
                /** If the soft reference has been cleared, remove this entry from the pool. */
                if (tempGrammar == null) {
                    removeEntry(entry);
                }
                else if ((entry.hash == hash) && equals(entry.desc, desc)) {
                    return true;
                }
            }
            return false;
        }
    
public booleanequals(org.apache.xerces.xni.grammars.XMLGrammarDescription desc1, org.apache.xerces.xni.grammars.XMLGrammarDescription desc2)
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

        if (desc1 instanceof XMLSchemaDescription) {
            if (!(desc2 instanceof XMLSchemaDescription)) {
                return false;
            }
            final XMLSchemaDescription sd1 = (XMLSchemaDescription) desc1;
            final XMLSchemaDescription sd2 = (XMLSchemaDescription) desc2;
            final String targetNamespace = sd1.getTargetNamespace();
            if (targetNamespace != null) {
                if (!targetNamespace.equals(sd2.getTargetNamespace())) {
                    return false;
                }
            }
            else if (sd2.getTargetNamespace() != null) {
                return false;
            }
            // The JAXP 1.3 spec says that the implementation can assume that
            // if two schema location hints are the same they always resolve
            // to the same document. In the default grammar pool implementation
            // we only look at the target namespaces. Here we also compare
            // location hints.
            final String expandedSystemId = sd1.getExpandedSystemId();
            if (expandedSystemId != null) {
                if (!expandedSystemId.equals(sd2.getExpandedSystemId())) {
                    return false;
                }
            }
            else if (sd2.getExpandedSystemId() != null) {
                return false;
            }
            return true;
        }
        return desc1.equals(desc2);
    
public org.apache.xerces.xni.grammars.GrammargetGrammar(org.apache.xerces.xni.grammars.XMLGrammarDescription desc)
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.

        synchronized (fGrammars) {
            clean();
            int hash = hashCode(desc);
            int index = (hash & 0x7FFFFFFF) % fGrammars.length;
            for (Entry entry = fGrammars[index]; entry != null; entry = entry.next) {
                Grammar tempGrammar = (Grammar) entry.grammar.get();
                /** If the soft reference has been cleared, remove this entry from the pool. */
                if (tempGrammar == null) {
                    removeEntry(entry);
                }
                else if ((entry.hash == hash) && equals(entry.desc, desc)) {
                    return tempGrammar;
                }
            }
            return null;
        }
    
public inthashCode(org.apache.xerces.xni.grammars.XMLGrammarDescription desc)
Returns the hash code value for the given grammar description.

param
desc The grammar description
return
The hash code value

        if (desc instanceof XMLSchemaDescription) {
            final XMLSchemaDescription sd = (XMLSchemaDescription) desc;
            final String targetNamespace = sd.getTargetNamespace();
            final String expandedSystemId = sd.getExpandedSystemId();
            int hash = (targetNamespace != null) ? targetNamespace.hashCode() : 0;
            hash ^= (expandedSystemId != null) ? expandedSystemId.hashCode() : 0;
            return hash;     
        }
        return desc.hashCode();
    
public voidlockPool()

        fPoolIsLocked = true;
    
public voidputGrammar(org.apache.xerces.xni.grammars.Grammar grammar)
Puts the specified grammar into the grammar pool and associates it to its root element name or its target namespace.

param
grammar The Grammar.

        if (!fPoolIsLocked) {
            synchronized (fGrammars) {
                clean();
                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)) {
                        if (entry.grammar.get() != grammar) {
                            entry.grammar = new SoftGrammarReference(entry, grammar, fReferenceQueue);
                        }
                        return;
                    }
                }
                // create a new entry
                Entry entry = new Entry(hash, index, desc, grammar, fGrammars[index], fReferenceQueue);
                fGrammars[index] = entry;
                fGrammarCount++;
            }
        }
    
private org.apache.xerces.xni.grammars.GrammarremoveEntry(org.apache.xerces.jaxp.validation.SoftReferenceGrammarPool$Entry entry)
Removes the given entry from the pool

param
entry the entry to remove
return
The grammar attached to this entry

        if (entry.prev != null) {
            entry.prev.next = entry.next;
        }
        else {
            fGrammars[entry.bucket] = entry.next;
        }
        if (entry.next != null) {
            entry.next.prev = entry.prev;
        }
        --fGrammarCount;
        entry.grammar.entry = null;
        return (Grammar) entry.grammar.get();
    
public org.apache.xerces.xni.grammars.GrammarremoveGrammar(org.apache.xerces.xni.grammars.XMLGrammarDescription desc)
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.

        synchronized (fGrammars) {
            clean();
            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 removeEntry(entry);
                }
            }
            return null;
        }
    
public org.apache.xerces.xni.grammars.GrammarretrieveGrammar(org.apache.xerces.xni.grammars.XMLGrammarDescription desc)

        return getGrammar(desc);
    
public org.apache.xerces.xni.grammars.Grammar[]retrieveInitialGrammarSet(java.lang.String grammarType)

        synchronized (fGrammars) {
            clean();
            // Return no grammars. This allows the garbage collector to sift
            // out grammars which are not in use when memory demand is high.
            // It also allows the pool to return the "right" schema grammar
            // based on schema locations.
            return ZERO_LENGTH_GRAMMAR_ARRAY;
        }
    
public voidunlockPool()

        fPoolIsLocked = false;