/** * Copyright 2011 meltmedia * * 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 org.xchain.framework.osgi; import org.xchain.framework.lifecycle.CCLPolicy; import org.xchain.framework.lifecycle.LifecycleClass; /** * A context class loader policy that will set the context class loader to be the class loader that loaded XChain. This * will have the effect that, when XChain is embedded in an application bundle, the application bundle's class loader * will always be the context class loader. * * @author John Trimble */ public class OSGiCCLPolicy implements CCLPolicy { /** The old context class loader for this thread. */ private ThreadLocal<CCLState> cclStateTl = new ThreadLocal<CCLState>(); public void bindCCL() { assertCCLNotBound(); CCLState cclState = new CCLState(Thread.currentThread().getContextClassLoader(), LifecycleClass.class.getClassLoader()); cclStateTl.set(cclState); Thread.currentThread().setContextClassLoader(cclState.boundCCL); } public void unbindCCL() { assertCCLBound(); CCLState cclState = cclStateTl.get(); Thread.currentThread().setContextClassLoader(cclState.previousCCL); cclStateTl.remove(); } private void assertCCLNotBound() { if( isCCLBound() ) throw new IllegalStateException("Context Class Loader is already bound."); } private void assertCCLBound() { if( !isCCLBound() ) throw new IllegalStateException("Context class loader is not bound."); } private class CCLState { ClassLoader previousCCL; ClassLoader boundCCL; CCLState(ClassLoader previousCCL, ClassLoader boundCCL) { this.previousCCL = previousCCL; this.boundCCL = boundCCL; } } public boolean isCCLBound() { return this.cclStateTl.get() != null; } }