/*
* Copyright 2015 Harald Wellmann.
*
* 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.
*
* Derived from org.apache.webbeans.corespi.DefaultSingletonService.
*/
package org.ops4j.pax.cdi.undertow.openwebbeans.impl;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.spi.SingletonService;
import org.apache.webbeans.util.Asserts;
import org.ops4j.pax.cdi.spi.util.Exceptions;
import org.ops4j.pax.swissbox.core.BundleClassLoader;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Singleton service which determines the current WebBeansContext based on the extended bundle
* class loader.
*
* @author Harald Wellmann
*/
public class BundleSingletonService implements SingletonService<WebBeansContext> {
private static Logger log = LoggerFactory.getLogger(BundleSingletonService.class);
/**
* Maps bundle IDs to contexts.
*/
private final Map<Long, WebBeansContext> singletonMap = new HashMap<Long, WebBeansContext>();
@Override
public WebBeansContext get(Object key) {
Bundle bundle = toBundle(key);
long bundleId = bundle.getBundleId();
synchronized (singletonMap) {
WebBeansContext webBeansContext = singletonMap.get(bundleId);
if (webBeansContext == null) {
Properties props = new Properties();
Map<Class<?>, Object> initialServices = new HashMap<Class<?>, Object>();
String resource = "/META-INF/openwebbeans/standalone.properties";
if (bundle.getHeaders().get("Web-ContextPath") != null) {
resource = "/META-INF/openwebbeans/wab.properties";
}
try {
props.load(getClass().getResourceAsStream(resource));
}
catch (IOException exc) {
throw Exceptions.unchecked(exc);
}
webBeansContext = new WebBeansContext(initialServices, props);
singletonMap.put(bundleId, webBeansContext);
}
return webBeansContext;
}
}
/**
* Clear all deployment instances when the application is undeployed.
*
* @param classLoader
* of the deployment
*/
public void clearInstances(ClassLoader classLoader) {
Asserts.assertNotNull(classLoader, "classloader is null");
Bundle bundle = toBundle(classLoader);
synchronized (singletonMap) {
singletonMap.remove(bundle.getBundleId());
}
}
@Override
public void clear(Object classLoader) {
clearInstances((ClassLoader) classLoader);
}
/**
* Assumes that the key is a bundle classloader and returns the corresponding bundle.
*
* @param key
* @return bundle
*/
private Bundle toBundle(Object key) {
// workaround for weird context class loader from Pax Web 3.1.1
if (key instanceof BundleClassLoader) {
BundleClassLoader bcl = (BundleClassLoader) key;
if (bcl.getParent() instanceof BundleReference) {
return BundleReference.class.cast(bcl.getParent()).getBundle();
}
}
if (key instanceof BundleReference) {
return BundleReference.class.cast(key).getBundle();
}
log.error("classloader {} does not implement BundleReference", key);
return null;
}
}