/* * Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you 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.wso2.micro.core.context; import java.lang.ref.WeakReference; import java.net.Authenticator; import java.net.PasswordAuthentication; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; import javax.naming.Binding; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameClassPair; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.NoInitialContextException; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.event.EventContext; import javax.naming.event.EventDirContext; import javax.naming.event.NamingListener; import javax.naming.ldap.Control; import javax.naming.ldap.ExtendedRequest; import javax.naming.ldap.ExtendedResponse; import javax.naming.ldap.LdapContext; import javax.naming.spi.InitialContextFactory; import javax.naming.spi.InitialContextFactoryBuilder; import javax.naming.spi.NamingManager; import javax.xml.namespace.QName; import org.apache.axiom.om.OMElement; import org.apache.axis2.util.XMLUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.micro.core.queueing.CarbonQueue; import org.wso2.micro.core.queueing.CarbonQueueManager; import org.wso2.micro.core.queueing.QueuingException; import org.wso2.micro.core.queueing.MultitenantCarbonQueueManager; import org.wso2.micro.core.Constants; import org.wso2.micro.integrator.core.util.MicroIntegratorBaseUtils; /** * This class will preserve an instance the current CarbonContext as a thread local variable. If a * CarbonContext is available on a global-scope (i.e. HTTP Session or AxisConfiguration) this class * will do the required lookup and obtain the corresponding instance. * <p/> * The CarbonContext provides the API for sub-tenant/super-tenant programming around <a * href="http://wso2.com/products/carbon">WSO2 Carbon</a> and <a href="http://wso2.com/cloud/stratos">WSO2 * Stratos</a>. */ @SuppressWarnings("unused") public final class CarbonContextDataHolder { private static final Log log = LogFactory.getLog(org.wso2.micro.core.context.CarbonContextDataHolder.class); private Map<String, Object> properties; private static List<UnloadTenantTask> unloadTenantTasks = null; static { try { log.debug("Started Setting up Authenticator Configuration"); CarbonAuthenticator authenticator = new CarbonAuthenticator(); try { setupAuthenticator(authenticator); } finally { String username = System.getProperty("http.proxyUser"); String password = System.getProperty("http.proxyPassword"); if (username != null && password != null) { authenticator.addAuthenticator("proxy", ".*", username, password); } Authenticator.setDefault(authenticator); } log.debug("Completed Setting up Authenticator Configuration"); } catch (NoClassDefFoundError ignore) { // There can be situations where the CarbonContext is accessed, when there is no Axis2 // library on the classpath. if (log.isDebugEnabled()) { log.debug("There can be situations where the CarbonContext is accessed, when there is no Axis2" + "library on the classpath.", ignore); } } catch (Exception e) { String msg = "Unable to read Server Configuration"; log.error(msg, e); } unloadTenantTasks = new LinkedList<UnloadTenantTask>(); registerUnloadTenantTask(new CarbonContextCleanupTask()); try { CarbonQueueManager.setInstance(new InternalCarbonQueueManager()); } catch (RuntimeException ignore) { // We don't mind an exception being thrown in here. Since there can be a possibility of // the same class loading twice and then trying to reset the queue manager. if (log.isDebugEnabled()) { log.debug("there can be a possibility of the same class loading twice and then trying " + "to reset the initial context factory builder", ignore); } } try { NamingManager. setInitialContextFactoryBuilder(new CarbonInitialJNDIContextFactoryBuilder()); } catch (NamingException ignore) { // We don't mind an exception being thrown in here. Since there can be a possibility of // the same class loading twice and then trying to reset the initial context factory // builder. if (log.isDebugEnabled()) { log.debug("there can be a possibility of the same class loading twice and then trying " + "to reset the initial context factory builder", ignore); } } catch (RuntimeException ignore) { // We don't mind an exception being thrown in here. Since there can be a possibility of // the same class loading twice and then trying to reset the initial context factory // builder. We are also catching Runtime exceptions here, since some JDKs do throw them // instead of the expected NamingException. if (log.isDebugEnabled()) { log.debug("there can be a possibility of the same class loading twice and then trying " + "to reset the initial context factory builder", ignore); } } } public void testCarbonStatic() { String name = "Sajinie"; } private static void setupAuthenticator(CarbonAuthenticator authenticator) throws Exception { OMElement documentElement = XMLUtils.toOM( MicroIntegratorBaseUtils.getServerConfiguration().getDocumentElement()); OMElement authenticators = documentElement.getFirstChildWithName( new QName(Constants.CARBON_SERVER_XML_NAMESPACE, "Security")). getFirstChildWithName( new QName(Constants.CARBON_SERVER_XML_NAMESPACE, "NetworkAuthenticatorConfig")); if (authenticators == null) { return; } for (Iterator iterator = authenticators.getChildElements(); iterator.hasNext(); ) { OMElement authenticatorElement = (OMElement) iterator.next(); if (!authenticatorElement.getLocalName().equalsIgnoreCase("Credential")) { continue; } String pattern = authenticatorElement.getFirstChildWithName( new QName(Constants.CARBON_SERVER_XML_NAMESPACE, "Pattern")).getText(); String type = authenticatorElement.getFirstChildWithName( new QName(Constants.CARBON_SERVER_XML_NAMESPACE, "Type")).getText(); String username = authenticatorElement.getFirstChildWithName( new QName(Constants.CARBON_SERVER_XML_NAMESPACE, "Username")).getText(); String password = authenticatorElement.getFirstChildWithName( new QName(Constants.CARBON_SERVER_XML_NAMESPACE, "Password")).getText(); authenticator.addAuthenticator(type, pattern, username, password); } } // Checks whether the given tenant is a sub-tenant or not. private static boolean isSubTenant(int tenantId) { return (tenantId != Constants.SUPER_TENANT_ID && tenantId != Constants.INVALID_TENANT_ID); } // A tenant-aware queue manager implementation. This will internally hold an instance of the // {@link MultitenantCarbonQueueManager}. private static class InternalCarbonQueueManager extends CarbonQueueManager { private AtomicReference<MultitenantCarbonQueueManager> queueManager = new AtomicReference<MultitenantCarbonQueueManager>(); public CarbonQueue<?> getQueue(String name) { int tenantId = Constants.SUPER_TENANT_ID; if (queueManager.get() != null) { if (log.isDebugEnabled()) { log.debug("Retrieving named queue: " + name); } return queueManager.get().getQueue(name, isSubTenant(tenantId) ? tenantId : Constants.SUPER_TENANT_ID); } return null; } public synchronized void setQueueManager(MultitenantCarbonQueueManager queueManager) throws QueuingException { MicroIntegratorBaseUtils.checkSecurity(); if (isSubTenant(Constants.SUPER_TENANT_ID)) { throw new QueuingException("Only the super-tenant can set the queue manager."); } InternalCarbonQueueManager carbonQueueManager = null; if (this.queueManager.get() != null) { throw new QueuingException("The queue manager has already been set."); } this.queueManager.set(queueManager); } public synchronized void removeQueueManager() throws QueuingException { MicroIntegratorBaseUtils.checkSecurity(); if (isSubTenant(Constants.SUPER_TENANT_ID)) { throw new QueuingException("Only the super-tenant can remove the queue manager."); } this.queueManager.set(null); } } // A tenant-aware JNDI Initial Context Factory Builder implementation. private static class CarbonInitialJNDIContextFactoryBuilder implements InitialContextFactoryBuilder { private static final String defaultInitialContextFactory = MicroIntegratorBaseUtils.getServerConfiguration().getFirstProperty( "JNDI.DefaultInitialContextFactory"); public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> h) throws NamingException { try { // get factory class name String factoryClassName = (String) h.get(Context.INITIAL_CONTEXT_FACTORY); // if the factory class has not been provided use the default initial context // factory defined in carbon.xml. if (factoryClassName == null) { factoryClassName = defaultInitialContextFactory; }else{ Class<?> factoryClass = classForName(factoryClassName); return (InitialContextFactory)factoryClass.newInstance(); } if (factoryClassName == null) { throw new NoInitialContextException("Failed to create " + "InitialContext. No factory specified in hash table."); } // new factory instance if (log.isDebugEnabled()) { log.debug("Loading JNDI Initial Context Factory: " + factoryClassName); } Class<?> factoryClass = classForName(factoryClassName); InitialContextFactory initialContextFactory = null; String defaultInitialContextFactoryClassName = MicroIntegratorBaseUtils.getServerConfiguration().getFirstProperty( "JNDI.CarbonInitialJNDIContextFactory"); if(defaultInitialContextFactoryClassName!=null){ Class<?> defaultInitialContextFactoryBuilderClass; try { defaultInitialContextFactoryBuilderClass=classForName (defaultInitialContextFactoryClassName); initialContextFactory=(InitialContextFactory) defaultInitialContextFactoryBuilderClass.getConstructor (InitialContextFactory.class).newInstance(factoryClass.newInstance()); } catch (ClassNotFoundException e) { log.warn("The specified InitialContextFactoryBuilder " +defaultInitialContextFactoryClassName+" is not there in the class " + "path.Using the default InitialContextFactoryBuilder ",e); } catch (InstantiationException e) { log.warn("The specified InitialContextFactoryBuilder " + ""+defaultInitialContextFactoryClassName+" could not be " + "instantiated.Using the default InitialContextFactoryBuilder ",e); } catch (IllegalAccessException e) { log.warn("The specified InitialContextFactoryBuilder " +defaultInitialContextFactoryClassName+" could not be " + "accessed.Using the default InitialContextFactoryBuilder ",e); } } if(initialContextFactory!=null){ return initialContextFactory; } //InitialContextFactory is not defined in carbon.xml, loading the default implementation. return new CarbonInitialJNDIContextFactory((InitialContextFactory) factoryClass.newInstance()); } catch (Exception e) { NamingException nex = new NoInitialContextException("Failed to create " + "InitialContext using factory specified in hash table."); nex.setRootCause(e); throw nex; } } } // A tenant-aware JNDI Initial Context Factory implementation. private static class CarbonInitialJNDIContextFactory implements InitialContextFactory { private InitialContextFactory factory; public CarbonInitialJNDIContextFactory(InitialContextFactory factory) { this.factory = factory; } public Context getInitialContext(Hashtable<?, ?> h) throws NamingException { return new CarbonInitialJNDIContext(factory.getInitialContext(h)); } } // A tenant-aware JNDI Initial Context implementation. private static class CarbonInitialJNDIContext implements EventDirContext, LdapContext { private Context initialContext; private Map<String, Context> contextCache = Collections.synchronizedMap(new HashMap<String, Context>()); private static ContextCleanupTask contextCleanupTask; private static List<String> superTenantOnlyUrlContextSchemes; private static List<String> allTenantUrlContextSchemes; static { contextCleanupTask = new ContextCleanupTask(); registerUnloadTenantTask(contextCleanupTask); superTenantOnlyUrlContextSchemes = Arrays.asList( MicroIntegratorBaseUtils.getServerConfiguration().getProperties( "JNDI.Restrictions.SuperTenantOnly.UrlContexts.UrlContext.Scheme")); allTenantUrlContextSchemes = Arrays.asList( MicroIntegratorBaseUtils.getServerConfiguration().getProperties( "JNDI.Restrictions.AllTenants.UrlContexts.UrlContext.Scheme")); } public CarbonInitialJNDIContext(Context initialContext) throws NamingException { this.initialContext = initialContext; } private static String getScheme(String url) { if (null == url) { return null; } int colPos = url.indexOf(':'); if (colPos < 0) { return null; } String scheme = url.substring(0, colPos); char c; boolean inCharSet; for (int i = 0; i < scheme.length(); i++) { c = scheme.charAt(i); inCharSet = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '.' || c == '-' || c == '_'; if (!inCharSet) { return null; } } return scheme; } private Context getInitialContext(Name name) { return getInitialContext(name.get(0)); } private Context getInitialContext() { return getInitialContext((String) null); } private boolean isBaseContextRequested() { try { String baseContextRequested = (String) this.initialContext.getEnvironment(). get(Constants.REQUEST_BASE_CONTEXT); if (baseContextRequested != null && baseContextRequested.equals("true")) { return true; } } catch (NamingException e) { log.warn( "An error occurred while retrieving environment properties from initial context.", e); } return false; } private Context getInitialContext(String name) { /** * If environment is requesting a base context return the * base context. */ if (isBaseContextRequested()) { return initialContext; } Context base = null; String scheme = null; if (name != null) { // If the name has components scheme = getScheme(name); if (scheme != null) { if (contextCache.containsKey(scheme)) { base = contextCache.get(scheme); } else { try { if (!initialContext.getEnvironment().containsKey(Context.URL_PKG_PREFIXES)) { String pkgValue = System.getProperty(Context.URL_PKG_PREFIXES); initialContext.addToEnvironment(Context.URL_PKG_PREFIXES, pkgValue); } Context urlContext = NamingManager.getURLContext(scheme, initialContext.getEnvironment()); if (urlContext != null) { contextCache.put(scheme, urlContext); base = urlContext; } } catch (NamingException ignored) { // If we are unable to find the context, we use the default context. if (log.isDebugEnabled()) { log.debug("If we are unable to find the context, we use the default context.", ignored); } } } } } if (base == null) { base = initialContext; scheme = null; } int tenantId = Constants.SUPER_TENANT_ID; if (!isSubTenant(tenantId)) { return base; } else if (scheme != null) { if (allTenantUrlContextSchemes.contains(scheme)) { return base; } else if (superTenantOnlyUrlContextSchemes.contains(scheme)) { throw new SecurityException("Tenants are not allowed to use JNDI contexts " + "with scheme: " + scheme); } } String tenantContextName = Constants.SUPER_TENANT_ID_STR; Context subContext; try { subContext = (Context) base.lookup(tenantContextName); if (subContext != null) { return subContext; } } catch (NamingException ignored) { // Depending on the JNDI Initial Context factory, the above operation may or may not // throw an exception. But, since we don't mind the exception, we can ignore it. if (log.isDebugEnabled()) { log.debug(ignored); } } try { log.debug("Creating Sub-Context: " + tenantContextName); subContext = base.createSubcontext(tenantContextName); contextCleanupTask.register(tenantId, subContext); if (subContext == null) { throw new RuntimeException("Initial context was not created for tenant: " + tenantId); } return subContext; } catch (NamingException e) { throw new RuntimeException("An error occurred while creating the initial context " + "for tenant: " + tenantId, e); } } private static class ContextCleanupTask implements UnloadTenantTask<Context> { private Map<Integer, ArrayList<Context>> contexts = new ConcurrentHashMap<Integer, ArrayList<Context>>(); public void register(int tenantId, Context context) { ArrayList<Context> list = contexts.get(tenantId); if (list == null) { list = new ArrayList<Context>(); list.add(context); contexts.put(tenantId, list); } else if (!list.contains(context)) { list.add(context); } } public void cleanup(int tenantId) { ArrayList<Context> list = contexts.remove(tenantId); // We need to close the context in a LIFO fashion. if (list != null) { Collections.reverse(list); for (Context context : list) { try { context.close(); } catch (NamingException ignore) { // We are not worried about the exception thrown here, as we are simply // doing a routine cleanup. if (log.isDebugEnabled()) { log.debug("Exception while outine cleanup", ignore); } } } list.clear(); } } } public Object lookup(String s) throws NamingException { return getInitialContext(s).lookup(s); } public Object lookup(Name name) throws NamingException { return getInitialContext(name).lookup(name); } public void bind(String s, Object o) throws NamingException { getInitialContext(s).bind(s, o); } public void bind(Name name, Object o) throws NamingException { getInitialContext(name).bind(name, o); } public void rebind(String s, Object o) throws NamingException { getInitialContext(s).rebind(s, o); } public void rebind(Name name, Object o) throws NamingException { getInitialContext(name).rebind(name, o); } public void unbind(String s) throws NamingException { getInitialContext(s).unbind(s); } public void unbind(Name name) throws NamingException { getInitialContext(name).unbind(name); } public void rename(String s, String s1) throws NamingException { getInitialContext(s).rename(s, s1); } public void rename(Name name, Name name1) throws NamingException { getInitialContext(name).rename(name, name1); } public NamingEnumeration<NameClassPair> list(String s) throws NamingException { return getInitialContext(s).list(s); } public NamingEnumeration<NameClassPair> list(Name name) throws NamingException { return getInitialContext(name).list(name); } public NamingEnumeration<Binding> listBindings(String s) throws NamingException { return getInitialContext(s).listBindings(s); } public NamingEnumeration<Binding> listBindings(Name name) throws NamingException { return getInitialContext(name).listBindings(name); } public void destroySubcontext(String s) throws NamingException { getInitialContext(s).destroySubcontext(s); } public void destroySubcontext(Name name) throws NamingException { getInitialContext(name).destroySubcontext(name); } public Context createSubcontext(String s) throws NamingException { return getInitialContext(s).createSubcontext(s); } public Context createSubcontext(Name name) throws NamingException { return getInitialContext(name).createSubcontext(name); } public Object lookupLink(String s) throws NamingException { return getInitialContext(s).lookupLink(s); } public Object lookupLink(Name name) throws NamingException { return getInitialContext(name).lookupLink(name); } public NameParser getNameParser(String s) throws NamingException { return getInitialContext(s).getNameParser(s); } public NameParser getNameParser(Name name) throws NamingException { return getInitialContext(name).getNameParser(name); } public String composeName(String s, String s1) throws NamingException { return getInitialContext(s).composeName(s, s1); } public Name composeName(Name name, Name name1) throws NamingException { return getInitialContext(name).composeName(name, name1); } public Object addToEnvironment(String s, Object o) throws NamingException { return getInitialContext().addToEnvironment(s, o); } public Object removeFromEnvironment(String s) throws NamingException { return getInitialContext().removeFromEnvironment(s); } public Hashtable<?, ?> getEnvironment() throws NamingException { if (isSubTenant(Constants.SUPER_TENANT_ID)) { throw new NamingException("Tenants cannot retrieve the environment."); } return getInitialContext().getEnvironment(); } public void close() throws NamingException { if (isSubTenant(Constants.SUPER_TENANT_ID) && !isBaseContextRequested()) { MicroIntegratorBaseUtils.checkSecurity(); } Context ctx = this.getInitialContext(); /* the below condition is there, because of a bug in Tomcat JNDI context close method, * see org.apache.naming.NamingContext#close() */ if (!ctx.getClass().getName().equals("org.apache.naming.SelectorContext")) { ctx.close(); } } public String getNameInNamespace() throws NamingException { return getInitialContext().getNameInNamespace(); } public int hashCode() { return initialContext.hashCode(); } public boolean equals(Object o) { return (o instanceof CarbonInitialJNDIContext) && initialContext.equals(o); } //////////////////////////////////////////////////////// // Methods Required by a DirContext //////////////////////////////////////////////////////// private DirContext getDirectoryContext(Name name) throws NamingException { return getDirectoryContext(name.get(0)); } private DirContext getDirectoryContext() throws NamingException { return getDirectoryContext((String) null); } private DirContext getDirectoryContext(String name) throws NamingException { Context initialContext = getInitialContext(name); if (initialContext instanceof DirContext) { return (DirContext) initialContext; } throw new NamingException("The given Context is not an instance of " + DirContext.class.getName()); } public Attributes getAttributes(Name name) throws NamingException { return getDirectoryContext(name).getAttributes(name); } public Attributes getAttributes(String s) throws NamingException { return getDirectoryContext(s).getAttributes(s); } public Attributes getAttributes(Name name, String[] strings) throws NamingException { return getDirectoryContext(name).getAttributes(name, strings); } public Attributes getAttributes(String s, String[] strings) throws NamingException { return getDirectoryContext(s).getAttributes(s, strings); } public void modifyAttributes(Name name, int i, Attributes attributes) throws NamingException { getDirectoryContext(name).modifyAttributes(name, i, attributes); } public void modifyAttributes(String s, int i, Attributes attributes) throws NamingException { getDirectoryContext(s).modifyAttributes(s, i, attributes); } public void modifyAttributes(Name name, ModificationItem[] modificationItems) throws NamingException { getDirectoryContext(name).modifyAttributes(name, modificationItems); } public void modifyAttributes(String s, ModificationItem[] modificationItems) throws NamingException { getDirectoryContext(s).modifyAttributes(s, modificationItems); } public void bind(Name name, Object o, Attributes attributes) throws NamingException { getDirectoryContext(name).bind(name, o, attributes); } public void bind(String s, Object o, Attributes attributes) throws NamingException { getDirectoryContext(s).bind(s, o, attributes); } public void rebind(Name name, Object o, Attributes attributes) throws NamingException { getDirectoryContext(name).rebind(name, o, attributes); } public void rebind(String s, Object o, Attributes attributes) throws NamingException { getDirectoryContext(s).rebind(s, o, attributes); } public DirContext createSubcontext(Name name, Attributes attributes) throws NamingException { return getDirectoryContext(name).createSubcontext(name, attributes); } public DirContext createSubcontext(String s, Attributes attributes) throws NamingException { return getDirectoryContext(s).createSubcontext(s, attributes); } public DirContext getSchema(Name name) throws NamingException { return getDirectoryContext(name).getSchema(name); } public DirContext getSchema(String s) throws NamingException { return getDirectoryContext(s).getSchema(s); } public DirContext getSchemaClassDefinition(Name name) throws NamingException { return getDirectoryContext(name).getSchemaClassDefinition(name); } public DirContext getSchemaClassDefinition(String s) throws NamingException { return getDirectoryContext(s).getSchemaClassDefinition(s); } public NamingEnumeration<SearchResult> search(Name name, Attributes attributes, String[] strings) throws NamingException { return getDirectoryContext(name).search(name, attributes, strings); } public NamingEnumeration<SearchResult> search(String s, Attributes attributes, String[] strings) throws NamingException { return getDirectoryContext(s).search(s, attributes, strings); } public NamingEnumeration<SearchResult> search(Name name, Attributes attributes) throws NamingException { return getDirectoryContext(name).search(name, attributes); } public NamingEnumeration<SearchResult> search(String s, Attributes attributes) throws NamingException { return getDirectoryContext(s).search(s, attributes); } public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls searchControls) throws NamingException { return getDirectoryContext(name).search(name, filter, searchControls); } public NamingEnumeration<SearchResult> search(String s, String filter, SearchControls searchControls) throws NamingException { return getDirectoryContext(s).search(s, filter, searchControls); } public NamingEnumeration<SearchResult> search(Name name, String filter, Object[] objects, SearchControls searchControls) throws NamingException { return getDirectoryContext(name).search(name, filter, objects, searchControls); } public NamingEnumeration<SearchResult> search(String s, String filter, Object[] objects, SearchControls searchControls) throws NamingException { return getDirectoryContext(s).search(s, filter, objects, searchControls); } //////////////////////////////////////////////////////// // Methods Required by a LdapContext //////////////////////////////////////////////////////// private LdapContext getLdapContext() throws NamingException { DirContext dirContext = getDirectoryContext(); if (dirContext instanceof EventContext) { return (LdapContext) dirContext; } throw new NamingException("The given Context is not an instance of " + LdapContext.class.getName()); } public ExtendedResponse extendedOperation(ExtendedRequest extendedRequest) throws NamingException { return getLdapContext().extendedOperation(extendedRequest); } public LdapContext newInstance(Control[] controls) throws NamingException { return getLdapContext().newInstance(controls); } public void reconnect(Control[] controls) throws NamingException { getLdapContext().reconnect(controls); } public Control[] getConnectControls() throws NamingException { return getLdapContext().getConnectControls(); } public void setRequestControls(Control[] controls) throws NamingException { getLdapContext().setRequestControls(controls); } public Control[] getRequestControls() throws NamingException { return getLdapContext().getRequestControls(); } public Control[] getResponseControls() throws NamingException { return getLdapContext().getResponseControls(); } //////////////////////////////////////////////////////// // Methods Required by a EventContext //////////////////////////////////////////////////////// private EventContext getEventContext(Name name) throws NamingException { return getEventContext(name.get(0)); } private EventContext getEventContext() throws NamingException { return getEventContext((String) null); } private EventContext getEventContext(String name) throws NamingException { Context initialContext = getInitialContext(name); if (initialContext instanceof EventContext) { return (EventContext) initialContext; } throw new NamingException("The given Context is not an instance of " + EventContext.class.getName()); } public void addNamingListener(Name name, int i, NamingListener namingListener) throws NamingException { MicroIntegratorBaseUtils.checkSecurity(); getEventContext(name).addNamingListener(name, i, namingListener); } public void addNamingListener(String s, int i, NamingListener namingListener) throws NamingException { MicroIntegratorBaseUtils.checkSecurity(); getEventContext(s).addNamingListener(s, i, namingListener); } public void removeNamingListener(NamingListener namingListener) throws NamingException { MicroIntegratorBaseUtils.checkSecurity(); getEventContext().removeNamingListener(namingListener); } public boolean targetMustExist() throws NamingException { return getEventContext().targetMustExist(); } //////////////////////////////////////////////////////// // Methods Required by a EventDirContext //////////////////////////////////////////////////////// private EventDirContext getEventDirContext(Name name) throws NamingException { return getEventDirContext(name.get(0)); } private EventDirContext getEventDirContext(String name) throws NamingException { EventContext eventContext = getEventContext(name); if (eventContext instanceof EventDirContext) { return (EventDirContext) eventContext; } throw new NamingException("The given Context is not an instance of " + EventDirContext.class.getName()); } public void addNamingListener(Name name, String filter, SearchControls searchControls, NamingListener namingListener) throws NamingException { MicroIntegratorBaseUtils.checkSecurity(); getEventDirContext(name) .addNamingListener(name, filter, searchControls, namingListener); } public void addNamingListener(String s, String filter, SearchControls searchControls, NamingListener namingListener) throws NamingException { MicroIntegratorBaseUtils.checkSecurity(); getEventDirContext(s).addNamingListener(s, filter, searchControls, namingListener); } public void addNamingListener(Name name, String filter, Object[] objects, SearchControls searchControls, NamingListener namingListener) throws NamingException { MicroIntegratorBaseUtils.checkSecurity(); getEventDirContext(name).addNamingListener(name, filter, objects, searchControls, namingListener); } public void addNamingListener(String s, String filter, Object[] objects, SearchControls searchControls, NamingListener namingListener) throws NamingException { MicroIntegratorBaseUtils.checkSecurity(); getEventDirContext(s).addNamingListener(s, filter, objects, searchControls, namingListener); } } private static class CarbonAuthenticator extends Authenticator { private static class AuthenticatorBean { private Pattern pattern; private PasswordAuthentication credential; public AuthenticatorBean(String regEx, String username, String password) { this.pattern = Pattern.compile(regEx); credential = new PasswordAuthentication(username, password.toCharArray()); } public PasswordAuthentication getPasswordAuthentication() { return credential; } public boolean matches(String protocol, String host, int port) { return pattern.matcher((protocol + "://" + host + ':' + port).toLowerCase()).matches(); } public boolean matches(URL url) { return pattern.matcher(url.toString()).matches(); } } private List<AuthenticatorBean> proxyAuthenticators = new LinkedList<AuthenticatorBean>(); private List<AuthenticatorBean> serverAuthenticators = new LinkedList<AuthenticatorBean>(); public void addAuthenticator(String type, String regEx, String username, String password) { if (type.equalsIgnoreCase("proxy")) { proxyAuthenticators.add(new AuthenticatorBean(regEx, username, password)); } else if (type.equalsIgnoreCase("server")) { serverAuthenticators.add(new AuthenticatorBean(regEx, username, password)); } } protected PasswordAuthentication getPasswordAuthentication() { if (RequestorType.PROXY.equals(getRequestorType())) { for (AuthenticatorBean authenticator : proxyAuthenticators) { if (authenticator.matches(getRequestingProtocol(), getRequestingHost(), getRequestingPort()) || authenticator.matches(getRequestingURL())) { return authenticator.getPasswordAuthentication(); } } } else if (RequestorType.SERVER.equals(getRequestorType())) { for (AuthenticatorBean authenticator : serverAuthenticators) { if (authenticator.matches(getRequestingScheme(), getRequestingHost(), getRequestingPort()) || authenticator.matches(getRequestingURL())) { return authenticator.getPasswordAuthentication(); } } } return super.getPasswordAuthentication(); } } // loads a class. private static Class<?> classForName(final String className) throws ClassNotFoundException { Class<?> cls = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() { public Class<?> run() { // try thread context class loader first try { return Class.forName(className, true, Thread .currentThread().getContextClassLoader()); } catch (ClassNotFoundException ignored) { if (log.isDebugEnabled()) { log.debug(ignored); } } // try system class loader second try { return Class.forName(className, true, ClassLoader .getSystemClassLoader()); } catch (ClassNotFoundException ignored) { if (log.isDebugEnabled()) { log.debug(ignored); } } // return null, if fail to load class return null; } }); if (cls == null) { throw new ClassNotFoundException("class " + className + " not found"); } return cls; } // // /** // * Method to obtain an instance to the Discovery Service. // * // * @return instance of the Discovery Service // */ // public static DiscoveryService getDiscoveryServiceProvider() { // return discoveryServiceProvider.get(); // } // // /** // * Method to define the instance of the Discovery Service. // * // * @param discoveryServiceProvider the Discovery Service instance. // */ // public static void setDiscoveryServiceProvider(DiscoveryService discoveryServiceProvider) { // org.wso2.carbon.context.internal.CarbonContextDataHolder.discoveryServiceProvider.set(discoveryServiceProvider); // } // // /** // * Method to obtain the current carbon context holder's base. // * // * @return the current carbon context holder's base. // */ // public static org.wso2.carbon.context.internal.CarbonContextDataHolder getCurrentCarbonContextHolderBase() { // return currentContextHolder.get(); // } // /** * Method to register a task that will be executed when a tenant is * unloaded. * * @param unloadTenantTask the task to run. * @see UnloadTenantTask */ public static synchronized void registerUnloadTenantTask( UnloadTenantTask unloadTenantTask) { if (log.isDebugEnabled()) { log.debug("Unload Tenant Task: " + unloadTenantTask.getClass().getName() + " was " + "registered."); } unloadTenantTasks.add(unloadTenantTask); } // // /** // * Method that will be called when a tenant is unloaded. This will run all // * the corresponding tasks that have been registered to be called when a // * tenant is unloaded. // * // * @param tenantId the tenant's identifier. // */ // public static void unloadTenant(int tenantId) { // log.debug("Started unloading tenant"); // for (UnloadTenantTask unloadTenantTask : unloadTenantTasks) { // unloadTenantTask.cleanup(tenantId); // } // log.info("Completed unloading tenant"); // } // // /** // * Starts a tenant flow. This will stack the current CarbonContext and begin // * a new nested flow which can have an entirely different context. This is // * ideal for scenarios where multiple super-tenant and sub-tenant phases are // * required within as a single block of execution. // */ // public void startTenantFlow() { // Stack<org.wso2.carbon.context.internal.CarbonContextDataHolder> carbonContextDataHolders = parentContextHolderStack.get(); // if(carbonContextDataHolders == null){ // carbonContextDataHolders = new Stack<org.wso2.carbon.context.internal.CarbonContextDataHolder>(); // parentContextHolderStack.set(carbonContextDataHolders); // } // carbonContextDataHolders.push(currentContextHolder.get()); // currentContextHolder.remove(); // } // // /** // * This will end the tenant flow and restore the previous CarbonContext. // */ // public void endTenantFlow() { // Stack<org.wso2.carbon.context.internal.CarbonContextDataHolder> carbonContextDataHolders = parentContextHolderStack.get(); // if (carbonContextDataHolders != null) { // currentContextHolder.set(carbonContextDataHolders.pop()); // } // } // // /** // * Default constructor to disallow creation of the CarbonContext. // */ // private CarbonContextDataHolder() { // this.tenantId = org.wso2.carbon.base.MultitenantConstants.INVALID_TENANT_ID; // this.username = null; // this.tenantDomain = null; // } // // /** // * Constructor that can be used to create clones. // * // * @param carbonContextHolder the CarbonContext holder instance of which the clone will be // * created from. // */ // public CarbonContextDataHolder(org.wso2.carbon.context.internal.CarbonContextDataHolder carbonContextHolder) { // this.tenantId = carbonContextHolder.tenantId; // this.username = carbonContextHolder.username; // this.tenantDomain = carbonContextHolder.tenantDomain; // if (carbonContextHolder.properties != null) { // this.properties = new HashMap<String, Object>(carbonContextHolder.properties); // } // } // // /** // * Method to obtain the tenant id on this CarbonContext instance. // * // * @return the tenant id. // */ // public int getTenantId() { // return tenantId; // } // // /** // * Method to set the tenant id on this CarbonContext instance. // * // * @param tenantId the tenant id. // */ // public void setTenantId(int tenantId) { // if (this.tenantId == org.wso2.carbon.base.MultitenantConstants.INVALID_TENANT_ID || // this.tenantId == org.wso2.carbon.base.MultitenantConstants.SUPER_TENANT_ID) { // this.tenantId = tenantId; // } else if (this.tenantId != tenantId) { // StackTraceElement[] traces = Thread.currentThread().getStackTrace(); // if (!isAllowedToChangeTenantDomain(traces)) { // throw new IllegalStateException("Trying to set the domain from " + this.tenantId + " to " + tenantId); // } // } // } // // /** // * Method to obtain the username on this CarbonContext instance. // * // * @return the username. // */ // public String getUsername() { // return username; // } // // /** // * Method to set the username on this CarbonContext instance. // * // * @param username the username. // */ // public void setUsername(String username) { // CarbonUtils.checkSecurity(); // this.username = username; // } // // /** // * Method to obtain the tenant domain on this CarbonContext instance. // * // * @return the tenant domain. // */ // public String getTenantDomain() { // return tenantDomain; // } // // /** // * Method to set the tenant domain on this CarbonContext instance. // * // * @param domain the tenant domain. // */ // public void setTenantDomain(String domain) { // try { // if (this.tenantDomain == null || // this.tenantDomain.equals(org.wso2.carbon.base.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { // this.tenantDomain = domain; // } else if (!tenantDomain.equals(domain)) { // StackTraceElement[] traces = Thread.currentThread().getStackTrace(); // if (!isAllowedToChangeTenantDomain(traces)) { // throw new IllegalStateException("Trying to set the domain from " + this.tenantDomain + " to " + domain); // } // } // } catch (IllegalStateException e) { // log.error(e.getMessage(), e); // } // } // // /** // * Method to obtain a property on this CarbonContext instance. // * // * @param name the property name. // * @return the value of the property by the given name. // */ // public Object getProperty(String name) { // if (properties == null) { // return null; // } // return properties.get(name); // } // // /** // * Method to set a property on this CarbonContext instance. // * // * @param name the property name. // * @param value the value to be set to the property by the given name. // */ // public void setProperty(String name, Object value) { // if (properties == null) { // properties = new HashMap<String, Object>(); // } // properties.put(name, value); // } // // Method to cleanup all properties. private void cleanupProperties() { // This method would be called to reclaim memory. Therefore, this might // be called on an // object which has been partially garbage collected. Even unlikely, it // might be possible // that the object exists without any field-references, until all // WeakReferences are // cleaned-up. if (properties != null) { properties.clear(); } } // // private boolean isAllowedToChangeTenantDomain(StackTraceElement[] traces) { // boolean allowChange = false; // if ((traces.length > CARBON_AUTHENTICATION_UTIL_INDEX) && // (traces[CARBON_AUTHENTICATION_UTIL_INDEX].getClassName().equals(CARBON_AUTHENTICATION_UTIL_CLASS))) { // allowChange = true; // } else if ((traces.length > CARBON_AUTHENTICATION_HANDLER_INDEX) && // traces[CARBON_AUTHENTICATION_HANDLER_INDEX].getClassName().equals(CARBON_AUTHENTICATION_HANDLER_CLASS)) { // allowChange = true; // } // return allowChange; // } // // /** // * This method will destroy the current CarbonContext holder. // */ // public static void destroyCurrentCarbonContextHolder() { // currentContextHolder.remove(); // parentContextHolderStack.remove(); // } // private static class CarbonContextCleanupTask implements UnloadTenantTask<org.wso2.micro.core.context.CarbonContextDataHolder> { private Map<Integer, ArrayList<WeakReference<org.wso2.micro.core.context.CarbonContextDataHolder>>> contextHolderList = new ConcurrentHashMap<Integer, ArrayList<WeakReference<org.wso2.micro.core.context.CarbonContextDataHolder>>>(); public void register(int tenantId, org.wso2.micro.core.context.CarbonContextDataHolder contextHolderBase) { ArrayList<WeakReference<org.wso2.micro.core.context.CarbonContextDataHolder>> list = contextHolderList .get(tenantId); if (list == null) { list = new ArrayList<WeakReference<org.wso2.micro.core.context.CarbonContextDataHolder>>(); list.add(new WeakReference<org.wso2.micro.core.context.CarbonContextDataHolder>( contextHolderBase)); contextHolderList.put(tenantId, list); } else { list.add(new WeakReference<org.wso2.micro.core.context.CarbonContextDataHolder>( contextHolderBase)); } } public void cleanup(int tenantId) { ArrayList<WeakReference<org.wso2.micro.core.context.CarbonContextDataHolder>> list = contextHolderList .remove(tenantId); if (list != null) { for (WeakReference<org.wso2.micro.core.context.CarbonContextDataHolder> carbonContextHolderBaseRef : list) { org.wso2.micro.core.context.CarbonContextDataHolder carbonContextHolderBase = carbonContextHolderBaseRef.get(); if (carbonContextHolderBase != null) { carbonContextHolderBase.cleanupProperties(); } } list.clear(); } } } }