/** * EasyBeans * Copyright (C) 2006 Bull S.A.S. * Contact: easybeans@ow2.org * * This library 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 any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * -------------------------------------------------------------------------- * $Id: SmartContext.java 5369 2010-02-24 14:58:19Z benoitf $ * -------------------------------------------------------------------------- */ package org.ow2.easybeans.component.smartclient.spi; import java.util.Hashtable; import javax.naming.Binding; import javax.naming.Context; import javax.naming.LinkRef; import javax.naming.Name; import javax.naming.NameClassPair; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; /** * Context that use a given classloader before calling every methods. * @author Florent Benoit */ public class SmartContext implements Context { /** * java:global/ context. */ private static final String JAVA_GLOBAL_PREFIX = "java:global/"; /** * java:global/ length. */ private static final int JAVA_GLOBAL_PREFIX_LENGTH = JAVA_GLOBAL_PREFIX.length(); /** * Context that is wrapped. */ private Context wrapped; /** * Classloader to use for all methods. */ private ClassLoader classLoader; /** * Creates a context with the given wrapped context and the given * classloader. * @param wrapped the context to wrap * @param classLoader the classloader to use. */ public SmartContext(final Context wrapped, final ClassLoader classLoader) { this.wrapped = wrapped; this.classLoader = classLoader; } /** * Adds a new environment property to the environment of this context. If * the property already exists, its value is overwritten. * @param propName the name of the environment property to add; may not be * null * @param propVal the value of the property to add; may not be null * @return the previous value of the property, or null if the property was * not in the environment before * @throws NamingException if a naming exception is encountered */ public Object addToEnvironment(final String propName, final Object propVal) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.addToEnvironment(propName, propVal); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Binds a name to an object. Delegate to the String version. * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @throws NamingException if a naming exception is encountered * @see javax.naming.NameAlreadyBoundException */ public void bind(final Name name, final Object obj) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.bind(name, obj); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Binds a name to an object. * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @throws NamingException if a naming exception is encountered * @see javax.naming.NameAlreadyBoundException */ public void bind(final String name, final Object obj) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.bind(name, obj); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Closes this context. * @throws NamingException if a naming exception is encountered */ public void close() throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.close(); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Composes the name of this context with a name relative to this context. * @param name a name relative to this context * @param prefix the name of this context relative to one of its ancestors * @return the composition of prefix and name * @throws NamingException if a naming exception is encountered */ public Name composeName(final Name name, final Name prefix) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.composeName(name, prefix); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Composes the name of this context with a name relative to this context: * Not supported. * @param name a name relative to this context * @param prefix the name of this context relative to one of its ancestors * @return the composition of prefix and name * @throws NamingException if a naming exception is encountered */ public String composeName(final String name, final String prefix) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.composeName(name, prefix); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Creates and binds a new context. Creates a new context with the given * name and binds it in the target context. * @param name the name of the context to create; may not be empty * @return the newly created context * @throws NamingException if a naming exception is encountered * @see javax.naming.NameAlreadyBoundException */ public Context createSubcontext(final Name name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.createSubcontext(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Creates and binds a new context. * @param name the name of the context to create; may not be empty * @return the newly created context * @throws NamingException if a naming exception is encountered * @see javax.naming.NameAlreadyBoundException */ public Context createSubcontext(final String name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.createSubcontext(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Destroys the named context and removes it from the namespace. Not * supported yet. * @param name the name of the context to be destroyed; may not be empty * @throws NamingException if a naming exception is encountered */ public void destroySubcontext(final Name name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.destroySubcontext(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Destroys the named context and removes it from the namespace. Not * supported yet. * @param name the name of the context to be destroyed; may not be empty * @throws NamingException if a naming exception is encountered */ public void destroySubcontext(final String name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.destroySubcontext(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Retrieves the environment in effect for this context. * @return the environment of this context; never null * @throws NamingException if a naming exception is encountered */ public Hashtable<?, ?> getEnvironment() throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.getEnvironment(); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Retrieves the full name of this context within its own namespace. * @return this context's name in its own namespace; never null * @throws NamingException if it fails. */ public String getNameInNamespace() throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.getNameInNamespace(); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Retrieves the parser associated with the named context. * @param name the name of the context from which to get the parser * @return a name parser that can parse compound names into their atomic * components * @throws NamingException if a naming exception is encountered */ public NameParser getNameParser(final Name name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.getNameParser(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Retrieves the parser associated with the named context. * @param name the name of the context from which to get the parser * @return a name parser that can parse compound names into their atomic * components * @throws NamingException if a naming exception is encountered */ public NameParser getNameParser(final String name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.getNameParser(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Enumerates the names bound in the named context, along with the class * names of objects bound to them. The contents of any subcontexts are not * included. * @param name the name of the context to list * @return an enumeration of the names and class names of the bindings in * this context. Each element of the enumeration is of type * NameClassPair. * @throws NamingException if a naming exception is encountered */ public NamingEnumeration<NameClassPair> list(final Name name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.list(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Enumerates the names bound in the named context, along with the class * names of objects bound to them. * @param name the name of the context to list * @return an enumeration of the names and class names of the bindings in * this context. Each element of the enumeration is of type * NameClassPair. * @throws NamingException if a naming exception is encountered */ public NamingEnumeration<NameClassPair> list(final String name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.list(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Enumerates the names bound in the named context, along with the objects * bound to them. The contents of any subcontexts are not included. If a * binding is added to or removed from this context, its effect on an * enumeration previously returned is undefined. * @param name the name of the context to list * @return an enumeration of the bindings in this context. Each element of * the enumeration is of type Binding. * @throws NamingException if a naming exception is encountered */ public NamingEnumeration<Binding> listBindings(final Name name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.listBindings(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Enumerates the names bound in the named context, along with the objects * bound to them. * @param name the name of the context to list * @return an enumeration of the bindings in this context. Each element of * the enumeration is of type Binding. * @throws NamingException if a naming exception is encountered */ public NamingEnumeration<Binding> listBindings(final String name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.listBindings(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Retrieves the named object. * @param name the name of the object to look up * @return the object bound to <tt>name</tt> * @throws NamingException if a naming exception is encountered */ public Object lookup(final Name name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.lookup(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Retrieves the named object. * @param name the name of the object to look up * @return the object bound to name * @throws NamingException if a naming exception is encountered */ public Object lookup(final String name) throws NamingException { // Handle redirect to global JNDI if (name.startsWith(JAVA_GLOBAL_PREFIX)) { return lookup(name.substring(JAVA_GLOBAL_PREFIX_LENGTH)); } ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { Object o = this.wrapped.lookup(name); if (o instanceof LinkRef) { LinkRef linkRef = (LinkRef) o; return lookup(linkRef.getLinkName()); } return o; } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Retrieves the named object, following links except for the terminal * atomic component of the name. If the object bound to name is not a link, * returns the object itself. * @param name the name of the object to look up * @return the object bound to name, not following the terminal link (if * any). * @throws NamingException if a naming exception is encountered */ public Object lookupLink(final Name name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.lookupLink(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Retrieves the named object, following links except for the terminal * atomic component of the name. If the object bound to name is not a link, * returns the object itself. * @param name the name of the object to look up * @return the object bound to name, not following the terminal link (if * any) * @throws NamingException if a naming exception is encountered */ public Object lookupLink(final String name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.lookupLink(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Binds a name to an object, overwriting any existing binding. * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @throws NamingException if a naming exception is encountered */ public void rebind(final Name name, final Object obj) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.rebind(name, obj); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Binds a name to an object, overwriting any existing binding. * @param name the name to bind; may not be empty * @param obj the object to bind; possibly null * @throws NamingException if a naming exception is encountered * @see javax.naming.InvalidNameException */ public void rebind(final String name, final Object obj) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.rebind(name, obj); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Removes an environment property from the environment of this context. * @param propName the name of the environment property to remove; may not * be null * @return the previous value of the property, or null if the property was * not in the environment * @throws NamingException if a naming exception is encountered */ public Object removeFromEnvironment(final String propName) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { return this.wrapped.removeFromEnvironment(propName); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Binds a new name to the object bound to an old name, and unbinds the old * name. * @param oldName the name of the existing binding; may not be empty * @param newName the name of the new binding; may not be empty * @throws NamingException if a naming exception is encountered */ public void rename(final Name oldName, final Name newName) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.rename(oldName, newName); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Binds a new name to the object bound to an old name, and unbinds the old * name. * @param oldName the name of the existing binding; may not be empty * @param newName the name of the new binding; may not be empty * @throws NamingException if a naming exception is encountered */ public void rename(final String oldName, final String newName) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.rename(oldName, newName); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Unbinds the named object. * @param name the name to unbind; may not be empty * @throws NamingException if a naming exception is encountered * @see javax.naming.NameNotFoundException */ public void unbind(final Name name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.unbind(name); } finally { Thread.currentThread().setContextClassLoader(old); } } /** * Unbinds the named object. * @param name the name to unbind; may not be empty * @throws NamingException if a naming exception is encountered * @see javax.naming.NameNotFoundException * @see javax.naming.InvalidNameException */ public void unbind(final String name) throws NamingException { ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(this.classLoader); try { this.wrapped.unbind(name); } finally { Thread.currentThread().setContextClassLoader(old); } } }