/*
* Copyright (C) 2003-2011 eXo Platform SAS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.etk.component.base.naming;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
import org.etk.kernel.container.KernelContainer;
import org.etk.kernel.container.KernelContainerContext;
/**
* This implementation of {@link InitialContextFactory} is used to be able to share
* all the objects that have been binded thanks to the {@link InitialContextInitializer}
* which is required for example to be able to create and bind data sources dynamically
* Created by The eXo Platform SAS
* Author : eXoPlatform
* thanhvucong.78@google.com
* Aug 11, 2011
*/
public class ExoContainerContextFactory implements InitialContextFactory
{
/**
* {@inheritDoc}
*/
public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException
{
return new ExoContainerCtx(environment);
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static class ExoContainerCtx extends SimpleContext
{
/**
* The map containing all the bindings for all the containers defined
*/
private static volatile Map<KernelContainer, AtomicReference<Map<String, Object>>> ALL_BINDINGS =
new HashMap<KernelContainer, AtomicReference<Map<String, Object>>>();
/**
* The environment to use in case we cannot find the object
*/
private final Hashtable env;
/**
* The current eXo container
*/
private final KernelContainer container;
/**
* The nested context
*/
private InitialContext ctx;
/**
* The reference to the bindings corresponding to this context;
*/
private AtomicReference<Map<String, Object>> bindingsRef;
public ExoContainerCtx(Hashtable<?, ?> env)
{
this.env = env == null ? null : (Hashtable)env.clone();
this.container = KernelContainerContext.getCurrentContainerIfPresent();
if (container != null)
{
AtomicReference<Map<String, Object>> ref = ALL_BINDINGS.get(container);
if (ref == null)
{
synchronized (ExoContainerCtx.class)
{
if (ref == null)
{
Map<KernelContainer, AtomicReference<Map<String, Object>>> tempAllBindings =
new HashMap<KernelContainer, AtomicReference<Map<String, Object>>>(ALL_BINDINGS);
tempAllBindings.put(container, ref =
new AtomicReference<Map<String, Object>>(new HashMap<String, Object>()));
ALL_BINDINGS = tempAllBindings;
}
}
}
this.bindingsRef = ref;
}
}
protected Map<String, Object> getBindings()
{
return bindingsRef.get();
}
protected void setBindings(Map<String, Object> bindings)
{
bindingsRef.set(bindings);
}
private InitialContext getContext() throws NamingException
{
if (ctx == null)
{
Hashtable env;
if (this.env == null)
{
env = new Hashtable();
}
else
{
env = new Hashtable(this.env);
}
env.put(Context.INITIAL_CONTEXT_FACTORY, InitialContextInitializer.DEFAULT_INITIAL_CONTEXT_FACTORY);
env.remove(InitialContextInitializer.class.getName());
ctx = new InitialContext(env);
}
return ctx;
}
private boolean isInitialContextInitializerCall()
{
return container != null && env != null && env.containsKey(InitialContextInitializer.class.getName());
}
/**
* {@inheritDoc}
*/
public Object lookup(String name) throws NamingException
{
if (getBindings().containsKey(name) || isInitialContextInitializerCall())
{
return super.lookup(name);
}
return getContext().lookup(name);
}
/**
* {@inheritDoc}
*/
public Object lookup(Name name) throws NamingException
{
if (getBindings().containsKey(name) || isInitialContextInitializerCall())
{
return super.lookup(nameToString(name));
}
return getContext().lookup(name);
}
/**
* {@inheritDoc}
*/
public void bind(String name, Object value) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.bind(name, value);
return;
}
getContext().bind(name, value);
}
/**
* {@inheritDoc}
*/
public void bind(Name name, Object value) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.bind(nameToString(name), value);
return;
}
getContext().bind(name, value);
}
/**
* {@inheritDoc}
*/
public void rebind(String name, Object value) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.rebind(name, value);
return;
}
getContext().rebind(name, value);
}
/**
* {@inheritDoc}
*/
public void rebind(Name name, Object value) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.rebind(nameToString(name), value);
return;
}
getContext().rebind(name, value);
}
/**
* {@inheritDoc}
*/
public void unbind(String name) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.unbind(name);
return;
}
getContext().unbind(name);
}
/**
* {@inheritDoc}
*/
public void unbind(Name name) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.unbind(nameToString(name));
return;
}
getContext().unbind(name);
}
/**
* {@inheritDoc}
*/
public void rename(String name1, String name2) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.rename(name1, name2);
return;
}
getContext().rename(name1, name2);
}
/**
* {@inheritDoc}
*/
public void rename(Name name1, Name name2) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.rename(nameToString(name1), nameToString(name2));
return;
}
getContext().rename(name1, name2);
}
/**
* {@inheritDoc}
*/
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.list(name);
}
return getContext().list(name);
}
/**
* {@inheritDoc}
*/
public NamingEnumeration<NameClassPair> list(String name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.list(name);
}
return getContext().list(name);
}
/**
* {@inheritDoc}
*/
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.listBindings(name);
}
return getContext().listBindings(name);
}
/**
* {@inheritDoc}
*/
public NamingEnumeration<Binding> listBindings(String name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.listBindings(name);
}
return getContext().listBindings(name);
}
/**
* {@inheritDoc}
*/
public void destroySubcontext(Name name) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.destroySubcontext(name);
return;
}
getContext().destroySubcontext(name);
}
/**
* {@inheritDoc}
*/
public void destroySubcontext(String name) throws NamingException
{
if (isInitialContextInitializerCall())
{
super.destroySubcontext(name);
return;
}
getContext().destroySubcontext(name);
}
/**
* {@inheritDoc}
*/
public Context createSubcontext(Name name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.createSubcontext(name);
}
return getContext().createSubcontext(name);
}
/**
* {@inheritDoc}
*/
public Context createSubcontext(String name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.createSubcontext(name);
}
return getContext().createSubcontext(name);
}
/**
* {@inheritDoc}
*/
public Object lookupLink(Name name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.lookupLink(name);
}
return getContext().lookupLink(name);
}
/**
* {@inheritDoc}
*/
public Object lookupLink(String name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.lookupLink(name);
}
return getContext().lookupLink(name);
}
/**
* {@inheritDoc}
*/
public NameParser getNameParser(Name name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.getNameParser(name);
}
return getContext().getNameParser(name);
}
/**
* {@inheritDoc}
*/
public NameParser getNameParser(String name) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.getNameParser(name);
}
return getContext().getNameParser(name);
}
/**
* {@inheritDoc}
*/
public Name composeName(Name name, Name prefix) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.composeName(name, prefix);
}
return getContext().composeName(name, prefix);
}
/**
* {@inheritDoc}
*/
public String composeName(String name, String prefix) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.composeName(name, prefix);
}
return getContext().composeName(name, prefix);
}
/**
* {@inheritDoc}
*/
public Object addToEnvironment(String propName, Object propVal) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.addToEnvironment(propName, propVal);
}
return getContext().addToEnvironment(propName, propVal);
}
/**
* {@inheritDoc}
*/
public Object removeFromEnvironment(String propName) throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.removeFromEnvironment(propName);
}
return getContext().removeFromEnvironment(propName);
}
/**
* {@inheritDoc}
*/
public Hashtable<?, ?> getEnvironment() throws NamingException
{
if (isInitialContextInitializerCall())
{
if (env == null)
{
// Must return non-null
return new Hashtable(3, 0.75f);
}
else
{
return (Hashtable)env.clone();
}
}
return getContext().getEnvironment();
}
protected Hashtable<?, ?> getInternalEnv()
{
return env;
}
protected Object getMutex()
{
return bindingsRef;
}
/**
* {@inheritDoc}
*/
public void close() throws NamingException
{
bindingsRef = null;
if (env != null)
{
env.clear();
}
if (ctx != null)
{
ctx.close();
}
}
/**
* {@inheritDoc}
*/
public String getNameInNamespace() throws NamingException
{
if (isInitialContextInitializerCall())
{
return super.getNameInNamespace();
}
return getContext().getNameInNamespace();
}
}
}