001 package org.apache.commons.ognl.internal;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 /*
023 * $Id: ClassCacheImpl.java 1194946 2011-10-29 17:47:02Z mcucchiara $
024 */
025
026 import org.apache.commons.ognl.ClassCacheInspector;
027
028 import java.util.Arrays;
029
030 /**
031 * Implementation of {@link ClassCache}.
032 */
033 public class ClassCacheImpl<V>
034 implements ClassCache<V>
035 {
036
037 /* this MUST be a power of 2 */
038 private static final int TABLE_SIZE = 512;
039
040 /* ...and now you see why. The table size is used as a mask for generating hashes */
041 private static final int TABLE_SIZE_MASK = TABLE_SIZE - 1;
042
043 private Entry<Class<?>, V>[] table = new Entry[TABLE_SIZE];
044
045 private ClassCacheInspector classInspector;
046
047 private int size = 0;
048
049 /**
050 * {@inheritDoc}
051 */
052 public void setClassInspector( ClassCacheInspector inspector )
053 {
054 classInspector = inspector;
055 }
056
057 /**
058 * {@inheritDoc}
059 */
060 public void clear()
061 {
062 for ( int i = 0; i < table.length; i++ )
063 {
064 table[i] = null;
065 }
066
067 size = 0;
068 }
069
070 /**
071 * {@inheritDoc}
072 */
073 public int getSize()
074 {
075 return size;
076 }
077
078 /**
079 * {@inheritDoc}
080 */
081 public final V get( Class<?> key )
082 throws CacheException
083 {
084 int i = key.hashCode() & TABLE_SIZE_MASK;
085
086 Entry<Class<?>, V> entry = table[i];
087
088 while ( entry != null )
089 {
090 if ( key == entry.getKey() )
091 {
092 return entry.getValue();
093 }
094
095 entry = entry.getNext();
096 }
097 return null;
098 }
099
100 /**
101 * {@inheritDoc}
102 */
103 public final V put( Class<?> key, V value )
104 {
105 if ( classInspector != null && !classInspector.shouldCache( key ) )
106 {
107 return value;
108 }
109
110 V result = null;
111 int i = key.hashCode() & TABLE_SIZE_MASK;
112
113 Entry<Class<?>, V> entry = table[i];
114
115 if ( entry == null )
116 {
117 table[i] = new Entry<Class<?>, V>( key, value );
118 size++;
119 }
120 else
121 {
122 if ( key == entry.getKey() )
123 {
124 result = entry.getValue();
125 entry.setValue( value );
126 }
127 else
128 {
129 while ( true )
130 {
131 if ( key == entry.getKey() )
132 {
133 /* replace value */
134 result = entry.getValue();
135 entry.setValue( value );
136 break;
137 }
138
139 if ( entry.getNext() == null )
140 {
141 /* add value */
142 entry.setNext( new Entry<Class<?>, V>( key, value ) );
143 break;
144 }
145
146 entry = entry.getNext();
147 }
148 }
149 }
150
151 return result;
152 }
153
154 /**
155 * {@inheritDoc}
156 */
157 @Override
158 public String toString()
159 {
160 return "ClassCacheImpl[" + "_table=" + ( table == null ? null : Arrays.asList( table ) ) + '\n'
161 + ", _classInspector=" + classInspector + '\n' + ", _size=" + size + '\n' + ']';
162 }
163
164 }