blob: 22dbfcf2a56dc1bfb18b669c613f5025b01c4873 [file] [log] [blame]
/*
* 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;
}
}