/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.weld.services;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.jboss.as.weld.logging.WeldLogger;
import org.jboss.modules.ModuleClassLoader;
import org.jboss.weld.bootstrap.api.Singleton;
import org.jboss.weld.bootstrap.api.SingletonProvider;
import org.wildfly.security.manager.WildFlySecurityManager;
/**
* Singleton Provider that uses the TCCL to figure out the current application.
*
* @author Stuart Douglas
*/
public class ModuleGroupSingletonProvider extends SingletonProvider {
/**
* Map of the top level class loader to all class loaders in a deployment
*/
public static final Map<ClassLoader, Set<ClassLoader>> deploymentClassLoaders = new ConcurrentHashMap<ClassLoader, Set<ClassLoader>>();
/**
* Maps a top level class loader to all CL's in the deployment
*/
public static void addClassLoaders(ClassLoader topLevel, Set<ClassLoader> allClassLoaders) {
deploymentClassLoaders.put(topLevel, allClassLoaders);
}
/**
* Removes the class loader mapping
*/
public static void removeClassLoader(ClassLoader topLevel) {
deploymentClassLoaders.remove(topLevel);
}
@Override
public <T> Singleton<T> create(Class<? extends T> type) {
return new TCCLSingleton<T>();
}
@SuppressWarnings("unused")
private static class TCCLSingleton<T> implements Singleton<T> {
private volatile Map<ClassLoader, T> store = Collections.emptyMap();
private volatile Map<String, T> contextIdStore = Collections.emptyMap();
public T get() {
T instance = store.get(findParentModuleCl(WildFlySecurityManager.getCurrentContextClassLoaderPrivileged()));
if (instance == null) {
throw WeldLogger.ROOT_LOGGER.singletonNotSet(WildFlySecurityManager.getCurrentContextClassLoaderPrivileged());
}
return instance;
}
public synchronized void set(T object) {
final Map<ClassLoader, T> store = new IdentityHashMap<ClassLoader, T>(this.store);
ClassLoader classLoader = WildFlySecurityManager.getCurrentContextClassLoaderPrivileged();
store.put(classLoader, object);
if (deploymentClassLoaders.containsKey(classLoader)) {
for (ClassLoader cl : deploymentClassLoaders.get(classLoader)) {
store.put(cl, object);
}
}
this.store = store;
}
public synchronized void clear() {
ClassLoader classLoader = WildFlySecurityManager.getCurrentContextClassLoaderPrivileged();
final Map<ClassLoader, T> store = new IdentityHashMap<ClassLoader, T>(this.store);
store.remove(classLoader);
if (deploymentClassLoaders.containsKey(classLoader)) {
for (ClassLoader cl : deploymentClassLoaders.get(classLoader)) {
store.remove(cl);
}
}
this.store = store;
}
public boolean isSet() {
return store.containsKey(findParentModuleCl(WildFlySecurityManager.getCurrentContextClassLoaderPrivileged()));
}
/**
* If a custom CL is in use we want to get the module CL it delegates to
* @param classLoader The current CL
* @returnThe corresponding module CL
*/
private ClassLoader findParentModuleCl(ClassLoader classLoader) {
ClassLoader c = classLoader;
while (c != null && !(c instanceof ModuleClassLoader)) {
c = c.getParent();
}
return c;
}
/*
* Default implementation of the Weld 1.2 API
*
* This provides forward binary compatibility with Weld 1.2 (OSGi integration).
* It is OK to ignore the id parameter as TCCL is still used to identify the singleton in Java EE.
*/
public T get(String id) {
T val = contextIdStore.get(id);
if(val != null) {
return val;
}
return get();
}
public boolean isSet(String id) {
T val = contextIdStore.get(id);
if(val != null) {
return true;
}
return isSet();
}
public synchronized void set(String id, T object) {
set(object);
final HashMap<String, T> store = new HashMap<String, T>(this.contextIdStore);
store.put(id, object);
this.contextIdStore = store;
}
public synchronized void clear(String id) {
clear();
final HashMap<String, T> store = new HashMap<String, T>(this.contextIdStore);
store.remove(id);
this.contextIdStore = store;
}
}
}