1 package org.apache.commons.ognl.internal;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 /*
23 * $Id: ClassCacheImpl.java 1194946 2011-10-29 17:47:02Z mcucchiara $
24 */
25
26 import org.apache.commons.ognl.ClassCacheInspector;
27
28 import java.util.Arrays;
29
30 /**
31 * Implementation of {@link ClassCache}.
32 */
33 public class ClassCacheImpl<V>
34 implements ClassCache<V>
35 {
36
37 /* this MUST be a power of 2 */
38 private static final int TABLE_SIZE = 512;
39
40 /* ...and now you see why. The table size is used as a mask for generating hashes */
41 private static final int TABLE_SIZE_MASK = TABLE_SIZE - 1;
42
43 private Entry<Class<?>, V>[] table = new Entry[TABLE_SIZE];
44
45 private ClassCacheInspector classInspector;
46
47 private int size = 0;
48
49 /**
50 * {@inheritDoc}
51 */
52 public void setClassInspector( ClassCacheInspector inspector )
53 {
54 classInspector = inspector;
55 }
56
57 /**
58 * {@inheritDoc}
59 */
60 public void clear()
61 {
62 for ( int i = 0; i < table.length; i++ )
63 {
64 table[i] = null;
65 }
66
67 size = 0;
68 }
69
70 /**
71 * {@inheritDoc}
72 */
73 public int getSize()
74 {
75 return size;
76 }
77
78 /**
79 * {@inheritDoc}
80 */
81 public final V get( Class<?> key )
82 throws CacheException
83 {
84 int i = key.hashCode() & TABLE_SIZE_MASK;
85
86 Entry<Class<?>, V> entry = table[i];
87
88 while ( entry != null )
89 {
90 if ( key == entry.getKey() )
91 {
92 return entry.getValue();
93 }
94
95 entry = entry.getNext();
96 }
97 return null;
98 }
99
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 }