/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * 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. */ package classloading; import com.hazelcast.util.FilteringClassLoader; import com.hazelcast.util.RootCauseMatcher; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import java.lang.reflect.Method; import java.util.List; import static classloading.ThreadLocalLeakTestUtils.checkThreadLocalsForLeaks; import static java.util.Collections.singletonList; /** * Creates a member or client {@link com.hazelcast.core.Hazelcast} instance with an explicit exclusion of {@code javax.cache}. * * If the method {@link #createHazelcastInstance()} or {@link #createHazelcastInstance_getCacheManager()} fails with a * {@link ClassNotFoundException} with the cause "javax.cache.* - Package excluded explicitly!" we accidentally introduced * a runtime dependency on {@link javax.cache} with a default configuration. * * The method {@link #createHazelcastInstance_getCache()} is expected to fail, since it actually tries to invoke * {@link com.hazelcast.core.ICacheManager#getCache(String)}. */ public abstract class AbstractJavaXCacheDependencyTest { private static final String EXPECTED_CAUSE = "javax.cache.Cache - Package excluded explicitly!"; private static final ClassLoader CLASS_LOADER; static { List<String> excludes = singletonList("javax.cache"); CLASS_LOADER = new FilteringClassLoader(excludes, "com.hazelcast"); } @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void createHazelcastInstance() throws Exception { createHazelcastInstance(false, false); checkThreadLocalsForLeaks(CLASS_LOADER); } @Test public void createHazelcastInstance_getCacheManager() throws Exception { createHazelcastInstance(true, false); checkThreadLocalsForLeaks(CLASS_LOADER); } @Test public void createHazelcastInstance_getCache() throws Exception { createHazelcastInstance(true, true); checkThreadLocalsForLeaks(CLASS_LOADER); } protected abstract String getConfigClass(); protected abstract String getHazelcastClass(); protected abstract String getNewInstanceMethod(); private void createHazelcastInstance(boolean testGetCacheManager, boolean testGetCache) throws Exception { Thread thread = Thread.currentThread(); ClassLoader tccl = thread.getContextClassLoader(); thread.setContextClassLoader(CLASS_LOADER); try { Class<?> configClazz = CLASS_LOADER.loadClass(getConfigClass()); Class<?> hazelcastClazz = CLASS_LOADER.loadClass(getHazelcastClass()); Class<?> hazelcastInstanceClazz = CLASS_LOADER.loadClass("com.hazelcast.core.HazelcastInstance"); Class<?> cacheManagerClazz = CLASS_LOADER.loadClass("com.hazelcast.core.ICacheManager"); try { Object config = configClazz.newInstance(); Method setClassLoader = configClazz.getDeclaredMethod("setClassLoader", ClassLoader.class); setClassLoader.invoke(config, CLASS_LOADER); Method newHazelcastInstance = hazelcastClazz.getDeclaredMethod(getNewInstanceMethod(), configClazz); Object hazelcastInstance = newHazelcastInstance.invoke(hazelcastClazz, config); if (testGetCacheManager) { Method getCacheManager = hazelcastInstanceClazz.getDeclaredMethod("getCacheManager"); getCacheManager.invoke(hazelcastInstance); } if (testGetCache) { expectedException.expect(new RootCauseMatcher(ClassNotFoundException.class, EXPECTED_CAUSE)); cacheManagerClazz.getDeclaredMethod("getCache", String.class); } } finally { Method shutdownAll = hazelcastClazz.getDeclaredMethod("shutdownAll"); shutdownAll.invoke(hazelcastClazz); } } finally { thread.setContextClassLoader(tccl); } } }