Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You 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 org.apache.tomcat.util.buf;
 
 
This class implements a String cache for ByteChunk and CharChunk.

Author(s):
Remy Maucherat
 
 public class StringCache {
 
 
     // ------------------------------------------------------- Static Variables
 
    
    
Enabled ?
 
     protected static boolean byteEnabled = 
         ("true".equals(System.getProperty("org.apache.tomcat.util.buf.StringCache.byte.enabled"
                 ..... ? "false" : "true")));
 
     
     protected static boolean charEnabled = 
         ("true".equals(System.getProperty("org.apache.tomcat.util.buf.StringCache.char.enabled""false")));
 
     
     protected static int trainThreshold = 
         Integer.parseInt(System.getProperty("org.apache.tomcat.util.buf.StringCache.trainThreshold""100000"));
     
 
     protected static int cacheSize = 
         Integer.parseInt(System.getProperty("org.apache.tomcat.util.buf.StringCache.cacheSize""5000"));
     
 
     protected static int maxStringSize = 
         Integer.parseInt(System.getProperty("org.apache.tomcat.util.buf.StringCache.maxStringSize""128"));
    

   
Statistics hash map for byte chunk.
 
     protected static HashMap bcStats = new HashMap();

    
    
toString count for byte chunk.
 
     protected static int bcCount = 0;
    
    
    
Cache for byte chunk.
 
     protected static ByteEntry[] bcCache = null;
    

    
Statistics hash map for char chunk.
 
     protected static HashMap ccStats = new HashMap();


    
toString count for char chunk.
 
     protected static int ccCount = 0; 
    

    
Cache for char chunk.
 
     protected static CharEntry[] ccCache = null;

    
    
Access count.
    protected static int accessCount = 0;
    

    
Hit count.
    protected static int hitCount = 0;
    
    // ------------------------------------------------------------ Properties

    
    

Returns:
Returns the cacheSize.
    public int getCacheSize() {
        return ;
    }
    
    
    

Parameters:
cacheSize The cacheSize to set.
    public void setCacheSize(int cacheSize) {
        . = cacheSize;
    }

    
    

Returns:
Returns the enabled.
    public boolean getByteEnabled() {
        return ;
    }
    
    
    

Parameters:
byteEnabled The enabled to set.
    public void setByteEnabled(boolean byteEnabled) {
        . = byteEnabled;
    }
    
    
    

Returns:
Returns the enabled.
    public boolean getCharEnabled() {
        return ;
    }
    
    
    

Parameters:
charEnabled The enabled to set.
    public void setCharEnabled(boolean charEnabled) {
        . = charEnabled;
    }
    
    
    

Returns:
Returns the trainThreshold.
    public int getTrainThreshold() {
        return ;
    }
    
    
    

Parameters:
trainThreshold The trainThreshold to set.
    public void setTrainThreshold(int trainThreshold) {
        . = trainThreshold;
    }

    
    

Returns:
Returns the accessCount.
    public int getAccessCount() {
        return ;
    }
    
    
    

Returns:
Returns the hitCount.
    public int getHitCount() {
        return ;
    }
    
    // -------------------------------------------------- Public Static Methods
    
    public void reset() {
         = 0;
         = 0;
        synchronized () {
             = null;
             = 0;
        }
        synchronized () {
             = null;
             = 0;
        }
    }
    
    
    public static String toString(ByteChunk bc) {
        // If the cache is null, then either caching is disabled, or we're
        // still training
        if ( == null) {
            String value = bc.toStringInternal();
            if ( && (value.length() < )) {
                // If training, everything is synced
                synchronized () {
                    // If the cache has been generated on a previous invocation
                    // while waiting fot the lock, just return the toString value
                    // we just calculated
                    if ( != null) {
                        return value;
                    }
                    // Two cases: either we just exceeded the train count, in which
                    // case the cache must be created, or we just update the count for
                    // the string
                    if ( > ) {
                        long t1 = System.currentTimeMillis();
                        // Sort the entries according to occurrence
                        TreeMap tempMap = new TreeMap();
                        Iterator entries = .keySet().iterator();
                        while (entries.hasNext()) {
                            ByteEntry entry = (ByteEntryentries.next();
                            int[] countA = (int[]) .get(entry);
                            Integer count = new Integer(countA[0]);
                            // Add to the list for that count
                            ArrayList list = (ArrayListtempMap.get(count);
                            if (list == null) {
                                // Create list
                                list = new ArrayList();
                                tempMap.put(countlist);
                            }
                            list.add(entry);
                        }
                        // Allocate array of the right size
                        int size = .size();
                        if (size > ) {
                            size = ;
                        }
                        ByteEntry[] tempbcCache = new ByteEntry[size];
                        // Fill it up using an alphabetical order
                        // and a dumb insert sort
                        ByteChunk tempChunk = new ByteChunk();
                        int n = 0;
                        while (n < size) {
                            Object key = tempMap.lastKey();
                            ArrayList list = (ArrayListtempMap.get(key);
                            ByteEntry[] list2 = 
                                (ByteEntry[]) list.toArray(new ByteEntry[list.size()]);
                            for (int i = 0; i < list.size() && n < sizei++) {
                                ByteEntry entry = (ByteEntrylist.get(i);
                                tempChunk.setBytes(entry.name, 0, entry.name.length);
                                int insertPos = findClosest(tempChunktempbcCachen);
                                if (insertPos == n) {
                                    tempbcCache[n + 1] = entry;
                                } else {
                                    System.arraycopy(tempbcCacheinsertPos + 1, tempbcCache
                                            insertPos + 2, n - insertPos - 1);
                                    tempbcCache[insertPos + 1] = entry;
                                }
                                n++;
                            }
                            tempMap.remove(key);
                        }
                         = 0;
                        .clear();
                         = tempbcCache;
                        if (..isDebugEnabled()) {
                            long t2 = System.currentTimeMillis();
                            ..debug("ByteCache generation time: " + (t2 - t1) + "ms");
                        }
                    } else {
                        ++;
                        // Allocate new ByteEntry for the lookup
                        ByteEntry entry = new ByteEntry();
                        entry.value = value;
                        int[] count = (int[]) .get(entry);
                        if (count == null) {
                            int end = bc.getEnd();
                            int start = bc.getStart();
                            // Create byte array and copy bytes
                            entry.name = new byte[bc.getLength()];
                            System.arraycopy(bc.getBuffer(), startentry.name, 0, end - start);
                            // Set encoding
                            entry.enc = bc.getEncoding();
                            // Initialize occurrence count to one 
                            count = new int[1];
                            count[0] = 1;
                            // Set in the stats hash map
                            .put(entrycount);
                        } else {
                            count[0] = count[0] + 1;
                        }
                    }
                }
            }
            return value;
        } else {
            ++;
            // Find the corresponding String
            String result = find(bc);
            if (result == null) {
                return bc.toStringInternal();
            }
            // Note: We don't care about safety for the stats
            ++;
            return result;
        }
        
    }
    public static String toString(CharChunk cc) {
        
        // If the cache is null, then either caching is disabled, or we're
        // still training
        if ( == null) {
            String value = cc.toStringInternal();
            if ( && (value.length() < )) {
                // If training, everything is synced
                synchronized () {
                    // If the cache has been generated on a previous invocation
                    // while waiting fot the lock, just return the toString value
                    // we just calculated
                    if ( != null) {
                        return value;
                    }
                    // Two cases: either we just exceeded the train count, in which
                    // case the cache must be created, or we just update the count for
                    // the string
                    if ( > ) {
                        long t1 = System.currentTimeMillis();
                        // Sort the entries according to occurrence
                        TreeMap tempMap = new TreeMap();
                        Iterator entries = .keySet().iterator();
                        while (entries.hasNext()) {
                            CharEntry entry = (CharEntryentries.next();
                            int[] countA = (int[]) .get(entry);
                            Integer count = new Integer(countA[0]);
                            // Add to the list for that count
                            ArrayList list = (ArrayListtempMap.get(count);
                            if (list == null) {
                                // Create list
                                list = new ArrayList();
                                tempMap.put(countlist);
                            }
                            list.add(entry);
                        }
                        // Allocate array of the right size
                        int size = .size();
                        if (size > ) {
                            size = ;
                        }
                        CharEntry[] tempccCache = new CharEntry[size];
                        // Fill it up using an alphabetical order
                        // and a dumb insert sort
                        CharChunk tempChunk = new CharChunk();
                        int n = 0;
                        while (n < size) {
                            Object key = tempMap.lastKey();
                            ArrayList list = (ArrayListtempMap.get(key);
                            CharEntry[] list2 = 
                                (CharEntry[]) list.toArray(new CharEntry[list.size()]);
                            for (int i = 0; i < list.size() && n < sizei++) {
                                CharEntry entry = (CharEntrylist.get(i);
                                tempChunk.setChars(entry.name, 0, entry.name.length);
                                int insertPos = findClosest(tempChunktempccCachen);
                                if (insertPos == n) {
                                    tempccCache[n + 1] = entry;
                                } else {
                                    System.arraycopy(tempccCacheinsertPos + 1, tempccCache
                                            insertPos + 2, n - insertPos - 1);
                                    tempccCache[insertPos + 1] = entry;
                                }
                                n++;
                            }
                            tempMap.remove(key);
                        }
                         = 0;
                        .clear();
                         = tempccCache;
                        if (..isDebugEnabled()) {
                            long t2 = System.currentTimeMillis();
                            ..debug("CharCache generation time: " + (t2 - t1) + "ms");
                        }
                    } else {
                        ++;
                        // Allocate new CharEntry for the lookup
                        CharEntry entry = new CharEntry();
                        entry.value = value;
                        int[] count = (int[]) .get(entry);
                        if (count == null) {
                            int end = cc.getEnd();
                            int start = cc.getStart();
                            // Create char array and copy chars
                            entry.name = new char[cc.getLength()];
                            System.arraycopy(cc.getBuffer(), startentry.name, 0, end - start);
                            // Initialize occurrence count to one 
                            count = new int[1];
                            count[0] = 1;
                            // Set in the stats hash map
                            .put(entrycount);
                        } else {
                            count[0] = count[0] + 1;
                        }
                    }
                }
            }
            return value;
        } else {
            ++;
            // Find the corresponding String
            String result = find(cc);
            if (result == null) {
                return cc.toStringInternal();
            }
            // Note: We don't care about safety for the stats
            ++;
            return result;
        }
        
    }
    
    
    // ----------------------------------------------------- Protected Methods


    
Compare given byte chunk with byte array. Return -1, 0 or +1 if inferior, equal, or superior to the String.
    protected static final int compare(ByteChunk namebyte[] compareTo) {
        int result = 0;
        byte[] b = name.getBuffer();
        int start = name.getStart();
        int end = name.getEnd();
        int len = compareTo.length;
        if ((end - start) < len) {
            len = end - start;
        }
        for (int i = 0; (i < len) && (result == 0); i++) {
            if (b[i + start] > compareTo[i]) {
                result = 1;
            } else if (b[i + start] < compareTo[i]) {
                result = -1;
            }
        }
        if (result == 0) {
            if (compareTo.length > (end - start)) {
                result = -1;
            } else if (compareTo.length < (end - start)) {
                result = 1;
            }
        }
        return result;
    }

    
    
Find an entry given its name in the cache and return the associated String.
    protected static final String find(ByteChunk name) {
        int pos = findClosest(name.);
        if ((pos < 0) || (compare(name[pos].) != 0)
                || !(name.getEncoding().equals([pos].))) {
            return null;
        } else {
            return [pos].;
        }
    }

    
    
Find an entry given its name in a sorted array of map elements. This will return the index for the closest inferior or equal item in the given array.
    protected static final int findClosest(ByteChunk nameByteEntry[] arrayint len) {
        int a = 0;
        int b = len - 1;
        // Special cases: -1 and 0
        if (b == -1) {
            return -1;
        }
        
        if (compare(namearray[0].) < 0) {
            return -1;
        }         
        if (b == 0) {
            return 0;
        }
        int i = 0;
        while (true) {
            i = (b + a) / 2;
            int result = compare(namearray[i].);
            if (result == 1) {
                a = i;
            } else if (result == 0) {
                return i;
            } else {
                b = i;
            }
            if ((b - a) == 1) {
                int result2 = compare(namearray[b].);
                if (result2 < 0) {
                    return a;
                } else {
                    return b;
                }
            }
        }
    }


    
Compare given char chunk with char array. Return -1, 0 or +1 if inferior, equal, or superior to the String.
    protected static final int compare(CharChunk namechar[] compareTo) {
        int result = 0;
        char[] c = name.getBuffer();
        int start = name.getStart();
        int end = name.getEnd();
        int len = compareTo.length;
        if ((end - start) < len) {
            len = end - start;
        }
        for (int i = 0; (i < len) && (result == 0); i++) {
            if (c[i + start] > compareTo[i]) {
                result = 1;
            } else if (c[i + start] < compareTo[i]) {
                result = -1;
            }
        }
        if (result == 0) {
            if (compareTo.length > (end - start)) {
                result = -1;
            } else if (compareTo.length < (end - start)) {
                result = 1;
            }
        }
        return result;
    }

    
    
Find an entry given its name in the cache and return the associated String.
    protected static final String find(CharChunk name) {
        int pos = findClosest(name.);
        if ((pos < 0) || (compare(name[pos].) != 0)) {
            return null;
        } else {
            return [pos].;
        }
    }

    
    
Find an entry given its name in a sorted array of map elements. This will return the index for the closest inferior or equal item in the given array.
    protected static final int findClosest(CharChunk nameCharEntry[] arrayint len) {
        int a = 0;
        int b = len - 1;
        // Special cases: -1 and 0
        if (b == -1) {
            return -1;
        }
        
        if (compare(namearray[0].) < 0 ) {
            return -1;
        }         
        if (b == 0) {
            return 0;
        }
        int i = 0;
        while (true) {
            i = (b + a) / 2;
            int result = compare(namearray[i].);
            if (result == 1) {
                a = i;
            } else if (result == 0) {
                return i;
            } else {
                b = i;
            }
            if ((b - a) == 1) {
                int result2 = compare(namearray[b].);
                if (result2 < 0) {
                    return a;
                } else {
                    return b;
                }
            }
        }
    }
    // -------------------------------------------------- ByteEntry Inner Class
    public static class ByteEntry {
        public byte[] name = null;
        public String enc = null;
        public String value = null;
        public String toString() {
            return ;
        }
        public int hashCode() {
            return .hashCode();
        }
        public boolean equals(Object obj) {
            if (obj instanceof ByteEntry) {
                return .equals(((ByteEntryobj).);
            }
            return false;
        }
        
    }
    // -------------------------------------------------- CharEntry Inner Class
    public static class CharEntry {
        public char[] name = null;
        public String value = null;
        public String toString() {
            return ;
        }
        public int hashCode() {
            return .hashCode();
        }
        public boolean equals(Object obj) {
            if (obj instanceof CharEntry) {
                return .equals(((CharEntryobj).);
            }
            return false;
        }
        
    }
New to GrepCode? Check out our FAQ X