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