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 }