001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.jcs.jcache.proxy; 020 021import org.apache.commons.jcs.jcache.JCSCache; 022 023import javax.cache.Cache; 024import javax.cache.CacheManager; 025import javax.cache.configuration.CacheEntryListenerConfiguration; 026import javax.cache.configuration.Configuration; 027import javax.cache.integration.CompletionListener; 028import javax.cache.processor.EntryProcessor; 029import javax.cache.processor.EntryProcessorException; 030import javax.cache.processor.EntryProcessorResult; 031import java.io.Serializable; 032import java.util.Iterator; 033import java.util.Map; 034import java.util.Set; 035 036// don't use a proxy, reflection is too slow here :( 037public class ClassLoaderAwareCache<K, V> implements Cache<K, V> 038{ 039 private final ClassLoader loader; 040 private final JCSCache<K, V> delegate; 041 042 public ClassLoaderAwareCache(final ClassLoader loader, final JCSCache<K, V> delegate) 043 { 044 this.loader = loader; 045 this.delegate = delegate; 046 } 047 048 private ClassLoader before(final Thread thread) 049 { 050 final ClassLoader tccl = thread.getContextClassLoader(); 051 thread.setContextClassLoader(loader); 052 return tccl; 053 } 054 055 public V get(final K key) 056 { 057 final Thread thread = Thread.currentThread(); 058 final ClassLoader loader = before(thread); 059 try 060 { 061 return delegate.get(key); 062 } 063 finally 064 { 065 thread.setContextClassLoader(loader); 066 } 067 } 068 069 public Map<K, V> getAll(final Set<? extends K> keys) 070 { 071 final Thread thread = Thread.currentThread(); 072 final ClassLoader loader = before(thread); 073 try 074 { 075 return delegate.getAll(keys); 076 } 077 finally 078 { 079 thread.setContextClassLoader(loader); 080 } 081 } 082 083 public boolean containsKey(final K key) 084 { 085 final Thread thread = Thread.currentThread(); 086 final ClassLoader loader = before(thread); 087 try 088 { 089 return delegate.containsKey(key); 090 } 091 finally 092 { 093 thread.setContextClassLoader(loader); 094 } 095 } 096 097 public void loadAll(final Set<? extends K> keys, boolean replaceExistingValues, final CompletionListener completionListener) 098 { 099 final Thread thread = Thread.currentThread(); 100 final ClassLoader loader = before(thread); 101 try 102 { 103 delegate.loadAll(keys, replaceExistingValues, completionListener); 104 } 105 finally 106 { 107 thread.setContextClassLoader(loader); 108 } 109 } 110 111 public void put(final K key, final V value) 112 { 113 final Thread thread = Thread.currentThread(); 114 final ClassLoader loader = before(thread); 115 try 116 { 117 delegate.put(key, value); 118 } 119 finally 120 { 121 thread.setContextClassLoader(loader); 122 } 123 } 124 125 public V getAndPut(final K key, final V value) 126 { 127 final Thread thread = Thread.currentThread(); 128 final ClassLoader loader = before(thread); 129 try 130 { 131 return delegate.getAndPut(key, value); 132 } 133 finally 134 { 135 thread.setContextClassLoader(loader); 136 } 137 } 138 139 public void putAll(final Map<? extends K, ? extends V> map) 140 { 141 final Thread thread = Thread.currentThread(); 142 final ClassLoader loader = before(thread); 143 try 144 { 145 delegate.putAll(map); 146 } 147 finally 148 { 149 thread.setContextClassLoader(loader); 150 } 151 } 152 153 public boolean putIfAbsent(final K key, final V value) 154 { 155 final Thread thread = Thread.currentThread(); 156 final ClassLoader loader = before(thread); 157 try 158 { 159 return delegate.putIfAbsent(key, value); 160 } 161 finally 162 { 163 thread.setContextClassLoader(loader); 164 } 165 } 166 167 public boolean remove(final K key) 168 { 169 final Thread thread = Thread.currentThread(); 170 final ClassLoader loader = before(thread); 171 try 172 { 173 return delegate.remove(key); 174 } 175 finally 176 { 177 thread.setContextClassLoader(loader); 178 } 179 } 180 181 public boolean remove(final K key, final V oldValue) 182 { 183 final Thread thread = Thread.currentThread(); 184 final ClassLoader loader = before(thread); 185 try 186 { 187 return delegate.remove(key, oldValue); 188 } 189 finally 190 { 191 thread.setContextClassLoader(loader); 192 } 193 } 194 195 public V getAndRemove(final K key) 196 { 197 final Thread thread = Thread.currentThread(); 198 final ClassLoader loader = before(thread); 199 try 200 { 201 return delegate.getAndRemove(key); 202 } 203 finally 204 { 205 thread.setContextClassLoader(loader); 206 } 207 } 208 209 public boolean replace(final K key, final V oldValue, final V newValue) 210 { 211 final Thread thread = Thread.currentThread(); 212 final ClassLoader loader = before(thread); 213 try 214 { 215 return delegate.replace(key, oldValue, newValue); 216 } 217 finally 218 { 219 thread.setContextClassLoader(loader); 220 } 221 } 222 223 public boolean replace(final K key, final V value) 224 { 225 final Thread thread = Thread.currentThread(); 226 final ClassLoader loader = before(thread); 227 try 228 { 229 return delegate.replace(key, value); 230 } 231 finally 232 { 233 thread.setContextClassLoader(loader); 234 } 235 } 236 237 public V getAndReplace(final K key, final V value) 238 { 239 final Thread thread = Thread.currentThread(); 240 final ClassLoader loader = before(thread); 241 try 242 { 243 return delegate.getAndReplace(key, value); 244 } 245 finally 246 { 247 thread.setContextClassLoader(loader); 248 } 249 } 250 251 public void removeAll(final Set<? extends K> keys) 252 { 253 final Thread thread = Thread.currentThread(); 254 final ClassLoader loader = before(thread); 255 try 256 { 257 delegate.removeAll(keys); 258 } 259 finally 260 { 261 thread.setContextClassLoader(loader); 262 } 263 } 264 265 @Override 266 public void removeAll() 267 { 268 final Thread thread = Thread.currentThread(); 269 final ClassLoader loader = before(thread); 270 try 271 { 272 delegate.removeAll(); 273 } 274 finally 275 { 276 thread.setContextClassLoader(loader); 277 } 278 } 279 280 @Override 281 public void clear() 282 { 283 final Thread thread = Thread.currentThread(); 284 final ClassLoader loader = before(thread); 285 try 286 { 287 delegate.clear(); 288 } 289 finally 290 { 291 thread.setContextClassLoader(loader); 292 } 293 } 294 295 public <C extends Configuration<K, V>> C getConfiguration(final Class<C> clazz) 296 { 297 final Thread thread = Thread.currentThread(); 298 final ClassLoader loader = before(thread); 299 try 300 { 301 return delegate.getConfiguration(clazz); 302 } 303 finally 304 { 305 thread.setContextClassLoader(loader); 306 } 307 } 308 309 public <T> T invoke(final K key, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments) throws EntryProcessorException 310 { 311 final Thread thread = Thread.currentThread(); 312 final ClassLoader loader = before(thread); 313 try 314 { 315 return delegate.invoke(key, entryProcessor, arguments); 316 } 317 finally 318 { 319 thread.setContextClassLoader(loader); 320 } 321 } 322 323 public <T> Map<K, EntryProcessorResult<T>> invokeAll(Set<? extends K> keys, EntryProcessor<K, V, T> entryProcessor, Object... arguments) 324 { 325 final Thread thread = Thread.currentThread(); 326 final ClassLoader loader = before(thread); 327 try 328 { 329 return delegate.invokeAll(keys, entryProcessor, arguments); 330 } 331 finally 332 { 333 thread.setContextClassLoader(loader); 334 } 335 } 336 337 @Override 338 public String getName() 339 { 340 final Thread thread = Thread.currentThread(); 341 final ClassLoader loader = before(thread); 342 try 343 { 344 return delegate.getName(); 345 } 346 finally 347 { 348 thread.setContextClassLoader(loader); 349 } 350 } 351 352 @Override 353 public CacheManager getCacheManager() 354 { 355 final Thread thread = Thread.currentThread(); 356 final ClassLoader loader = before(thread); 357 try 358 { 359 return delegate.getCacheManager(); 360 } 361 finally 362 { 363 thread.setContextClassLoader(loader); 364 } 365 } 366 367 @Override 368 public void close() 369 { 370 final Thread thread = Thread.currentThread(); 371 final ClassLoader loader = before(thread); 372 try 373 { 374 delegate.close(); 375 } 376 finally 377 { 378 thread.setContextClassLoader(loader); 379 } 380 } 381 382 @Override 383 public boolean isClosed() 384 { 385 final Thread thread = Thread.currentThread(); 386 final ClassLoader loader = before(thread); 387 try 388 { 389 return delegate.isClosed(); 390 } 391 finally 392 { 393 thread.setContextClassLoader(loader); 394 } 395 } 396 397 @Override 398 public <T> T unwrap(final Class<T> clazz) 399 { 400 final Thread thread = Thread.currentThread(); 401 final ClassLoader loader = before(thread); 402 try 403 { 404 return delegate.unwrap(clazz); 405 } 406 finally 407 { 408 thread.setContextClassLoader(loader); 409 } 410 } 411 412 public void registerCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration) 413 { 414 final Thread thread = Thread.currentThread(); 415 final ClassLoader loader = before(thread); 416 try 417 { 418 delegate.registerCacheEntryListener(cacheEntryListenerConfiguration); 419 } 420 finally 421 { 422 thread.setContextClassLoader(loader); 423 } 424 } 425 426 public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration) 427 { 428 final Thread thread = Thread.currentThread(); 429 final ClassLoader loader = before(thread); 430 try 431 { 432 delegate.deregisterCacheEntryListener(cacheEntryListenerConfiguration); 433 } 434 finally 435 { 436 thread.setContextClassLoader(loader); 437 } 438 } 439 440 @Override 441 public Iterator<Entry<K, V>> iterator() 442 { 443 final Thread thread = Thread.currentThread(); 444 final ClassLoader loader = before(thread); 445 try 446 { 447 return delegate.iterator(); 448 } 449 finally 450 { 451 thread.setContextClassLoader(loader); 452 } 453 } 454 455 @Override 456 public boolean equals(final Object obj) 457 { 458 if (ClassLoaderAwareCache.class.isInstance(obj)) 459 { 460 return delegate.equals(ClassLoaderAwareCache.class.cast(obj).delegate); 461 } 462 return super.equals(obj); 463 } 464 465 @Override 466 public int hashCode() 467 { 468 return delegate.hashCode(); 469 } 470 471 public static <K extends Serializable, V extends Serializable> Cache<K, V> wrap(final ClassLoader loader, final JCSCache<K, V> delegate) 472 { 473 ClassLoader dontWrapLoader = ClassLoaderAwareCache.class.getClassLoader(); 474 while (dontWrapLoader != null) 475 { 476 if (loader == dontWrapLoader) 477 { 478 return delegate; 479 } 480 dontWrapLoader = dontWrapLoader.getParent(); 481 } 482 return new ClassLoaderAwareCache<K, V>(loader, delegate); 483 } 484 485 public static <K extends Serializable, V extends Serializable> JCSCache<K, V> getDelegate(final Cache<?, ?> cache) 486 { 487 if (JCSCache.class.isInstance(cache)) 488 { 489 return (JCSCache<K, V>) cache; 490 } 491 return ((ClassLoaderAwareCache<K, V>) cache).delegate; 492 } 493}