| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF 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.apache.aries.jndi; |
| |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.util.Hashtable; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import javax.naming.Context; |
| import javax.naming.NamingException; |
| import javax.naming.NoInitialContextException; |
| import javax.naming.spi.InitialContextFactory; |
| import javax.naming.spi.InitialContextFactoryBuilder; |
| import javax.naming.spi.ObjectFactory; |
| |
| import org.apache.aries.jndi.startup.Activator; |
| import org.apache.aries.jndi.tracker.ServiceTrackerCustomizers; |
| import org.apache.aries.jndi.urls.URLObjectFactoryFinder; |
| import org.apache.aries.util.service.registry.ServicePair; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.FrameworkUtil; |
| import org.osgi.framework.ServiceReference; |
| |
| /** |
| * Provides helper methods for the DelegateContext. This provides the methods so |
| * there can be many DelegateContexts, but few service trackers. |
| */ |
| public final class ContextHelper { |
| |
| /** Ensure no one constructs us */ |
| private ContextHelper() { |
| throw new RuntimeException(); |
| } |
| |
| /** |
| * This method is used to create a URL Context. It does this by looking for |
| * the URL context's ObjectFactory in the service registry. |
| * |
| * @param context |
| * @param urlScheme |
| * @param env |
| * @return a Context |
| * @throws NamingException |
| */ |
| public static ContextProvider createURLContext(final BundleContext context, |
| final String urlScheme, |
| final Hashtable<?, ?> env) |
| throws NamingException { |
| |
| ServicePair<ObjectFactory> urlObjectFactory = getURLObjectFactory(context, urlScheme, env); |
| |
| if (urlObjectFactory != null) { |
| ObjectFactory factory = urlObjectFactory.get(); |
| |
| if (factory != null) { |
| return new URLContextProvider(context, urlObjectFactory.getReference(), factory, env); |
| } |
| } |
| |
| // if we got here then we couldn't find a URL context factory so return null. |
| return null; |
| } |
| |
| public static final ServicePair<ObjectFactory> getURLObjectFactory(final BundleContext ctx, String urlScheme, Hashtable<?, ?> environment) |
| throws NamingException |
| { |
| ServicePair<ObjectFactory> result = null; |
| |
| ServiceReference ref = ServiceTrackerCustomizers.URL_FACTORY_CACHE.find(urlScheme); |
| |
| if (ref == null) { |
| ServiceReference[] refs = AccessController.doPrivileged(new PrivilegedAction<ServiceReference[]>() { |
| public ServiceReference[] run() { |
| return Activator.getURLObectFactoryFinderServices(); |
| } |
| }); |
| |
| if (refs != null) { |
| for (final ServiceReference finderRef : refs) { |
| URLObjectFactoryFinder finder = (URLObjectFactoryFinder) ServiceTrackerCustomizers.URLOBJFACTORYFINDER_CACHE.getServiceFromRef(ctx,finderRef); |
| |
| if (finder != null) { |
| ObjectFactory f = finder.findFactory(urlScheme, environment); |
| |
| if (f != null) { |
| result = new ServicePair<ObjectFactory>(ctx, finderRef, f); |
| break; |
| } |
| } |
| } |
| } |
| } else { |
| result = new ServicePair<ObjectFactory>(ctx, ref); |
| } |
| |
| return result; |
| } |
| |
| public static Context getInitialContext(BundleContext context, Hashtable<?, ?> environment) |
| throws NamingException { |
| |
| final Bundle jndiBundle = FrameworkUtil.getBundle(ContextHelper.class); |
| // if we are outside OSGi (like in our unittests) then we would get Null back here, so just make sure we don't. |
| if (jndiBundle != null) { |
| |
| BundleContext jndiBundleContext = AccessController.doPrivileged(new PrivilegedAction<BundleContext>() { |
| public BundleContext run() |
| { |
| return jndiBundle.getBundleContext(); |
| } |
| }); |
| |
| if (!!!jndiBundleContext.getClass().equals(context.getClass())){ |
| //the context passed in must have come from a child framework |
| //use the parent context instead |
| context = jndiBundleContext; |
| } |
| } |
| |
| ContextProvider provider = getContextProvider(context, environment); |
| |
| if (provider != null) { |
| return new DelegateContext(context, provider); |
| } else { |
| String contextFactoryClass = (String) environment.get(Context.INITIAL_CONTEXT_FACTORY); |
| if (contextFactoryClass == null) { |
| return new DelegateContext(context, environment); |
| } else { |
| throw new NoInitialContextException(Utils.MESSAGES.getMessage("no.initial.context.factory", contextFactoryClass)); |
| } |
| } |
| } |
| |
| public static ContextProvider getContextProvider(BundleContext context, |
| Hashtable<?, ?> environment) |
| throws NamingException { |
| |
| ContextProvider provider = null; |
| String contextFactoryClass = (String) environment.get(Context.INITIAL_CONTEXT_FACTORY); |
| if (contextFactoryClass == null) { |
| // 1. get ContextFactory using builder |
| provider = getInitialContextUsingBuilder(context, environment); |
| |
| // 2. lookup all ContextFactory services |
| if (provider == null) { |
| |
| ServiceReference[] references = AccessController.doPrivileged(new PrivilegedAction<ServiceReference[]>() { |
| public ServiceReference[] run() { |
| return Activator.getInitialContextFactoryServices(); |
| } |
| }); |
| |
| if (references != null) { |
| Context initialContext = null; |
| for (ServiceReference reference : references) { |
| InitialContextFactory factory = (InitialContextFactory) ServiceTrackerCustomizers.ICF_CACHE.getServiceFromRef(context, reference); |
| initialContext = factory.getInitialContext(environment); |
| if (initialContext != null) { |
| provider = new SingleContextProvider(context, reference, initialContext); |
| break; |
| } |
| } |
| } |
| } |
| } else { |
| ServiceReference ref = ServiceTrackerCustomizers.ICF_CACHE.find(contextFactoryClass); |
| |
| if (ref != null) { |
| Context initialContext = null; |
| InitialContextFactory factory = (InitialContextFactory) ServiceTrackerCustomizers.ICF_CACHE.getServiceFromRef(context, ref); |
| if (factory != null) { |
| initialContext = factory.getInitialContext(environment); |
| provider = new SingleContextProvider(context, ref, initialContext); |
| } |
| } |
| |
| // 2. get ContextFactory using builder |
| if (provider == null) { |
| provider = getInitialContextUsingBuilder(context, environment); |
| } |
| } |
| |
| return provider; |
| } |
| |
| private static final Logger logger = Logger.getLogger(ContextHelper.class.getName()); |
| |
| private static ContextProvider getInitialContextUsingBuilder(BundleContext context, |
| Hashtable<?, ?> environment) |
| throws NamingException { |
| |
| ContextProvider provider = null; |
| ServiceReference[] refs = AccessController.doPrivileged(new PrivilegedAction<ServiceReference[]>() { |
| public ServiceReference[] run() { |
| return Activator.getInitialContextFactoryBuilderServices(); |
| } |
| }); |
| |
| if (refs != null) { |
| InitialContextFactory factory = null; |
| for (ServiceReference ref : refs) { |
| InitialContextFactoryBuilder builder = (InitialContextFactoryBuilder) ServiceTrackerCustomizers.ICFB_CACHE.getServiceFromRef(context, ref); |
| try { |
| factory = builder.createInitialContextFactory(environment); |
| } catch (NamingException ne) { |
| // TODO: log |
| // ignore this, if the builder fails we want to move onto the next one |
| } catch (NullPointerException npe) { |
| logger.log(Level.SEVERE, "NPE caught in ContextHelper.getInitialContextUsingBuilder. context=" + context + " ref=" + ref); |
| throw npe; |
| } |
| |
| if (factory != null) { |
| provider = new SingleContextProvider(context, ref, factory.getInitialContext(environment)); |
| break; |
| } |
| } |
| } |
| return provider; |
| } |
| |
| } |