package org.cache2k.jcache.provider;
/*
* #%L
* cache2k JCache provider
* %%
* Copyright (C) 2000 - 2017 headissue GmbH, Munich
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import org.junit.Test;
import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.spi.CachingProvider;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
/**
* Test cache manager with different class loader.
*
* @author Jens Wilke
*/
@SuppressWarnings("unchecked")
public class CacheManagerClassLoadingTest {
static final String CACHE_NAME = CacheManagerClassLoadingTest.class.getSimpleName();
/**
* Request cache manager with different class loader and put a key in the cache that
* was loaded by that class loader. equals() needs to work and class loaders needs to be
* identical
*/
@Test
public void testCorrectClassLoaderForKey() throws Exception {
SpecialClassLoader loader = new SpecialClassLoader();
CachingProvider provider = Caching.getCachingProvider();
CacheManager mgr = Caching.getCachingProvider().getCacheManager(provider.getDefaultURI(), loader);
Cache<Object, Object> cache = mgr.createCache(CACHE_NAME, new MutableConfiguration());
Class keyClass = loader.loadSpecial(DomainKey.class);
assertEquals(keyClass.getClassLoader(), loader);
Object key = keyClass.newInstance();
setValue(key, "someKey");
String someValue = "Value";
cache.put(key, someValue);
Cache.Entry e = cache.iterator().next();
assertSame("class loaders identical", key.getClass().getClassLoader(), e.getKey().getClass().getClassLoader());
assertEquals(key, e.getKey());
mgr.close();
}
/**
* Request cache manager with different class loader and put a value in the cache that
* was loaded by that class loader. equals() needs to work and class loaders needs to be
* identical
*/
@Test
public void testCorrectClassLoaderForValue() throws Exception {
SpecialClassLoader loader = new SpecialClassLoader();
CachingProvider provider = Caching.getCachingProvider();
CacheManager mgr = Caching.getCachingProvider().getCacheManager(provider.getDefaultURI(), loader);
Cache<Object, Object> cache = mgr.createCache(CACHE_NAME, new MutableConfiguration());
Class valueClass = loader.loadSpecial(DomainValue.class);
assertEquals(valueClass.getClassLoader(), loader);
Object value = valueClass.newInstance();
setValue(value, "someValue");
String someKey = "Key";
cache.put(someKey, value);
Cache.Entry e = cache.iterator().next();
assertSame("class loaders identical", value.getClass().getClassLoader(), e.getValue().getClass().getClassLoader());
assertEquals(value, e.getValue());
mgr.close();
}
private void setValue(Object o, String value) throws Exception {
Method m = o.getClass().getMethod("setValue", String.class);
m.invoke(o, value);
}
public static class DomainKey implements Serializable {
private String value;
public String getValue() {
return value;
}
public void setValue(final String v) {
value = v;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DomainKey _that = (DomainKey) o;
return value != null ? value.equals(_that.value) : _that.value == null;
}
@Override
public int hashCode() {
return value != null ? value.hashCode() : 0;
}
@Override
public String toString() {
return value;
}
}
public static class DomainValue extends DomainKey {
}
static class SpecialClassLoader extends ClassLoader {
Class<?> loadSpecial(Class<?> clazz) {
String fileName = clazz.getName().replace('.','/') + ".class";
try {
InputStream in = getClass().getClassLoader().getResourceAsStream(fileName);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int count;
byte[] data = new byte[4096];
while ((count = in.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, count);
}
buffer.flush();
byte[] bytes = buffer.toByteArray();
return defineClass(clazz.getName(), bytes, 0, bytes.length);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
}