blob: 3632bff851876497d14c234098685ca8bb38cf06 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2015 Oracle.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* Bob Nettleton (Oracle) - Initial Reference Implementation
******************************************************************************/
package org.eclipse.gemini.naming;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.NoInitialContextException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.naming.directory.Attributes;
import javax.naming.spi.DirObjectFactory;
import javax.naming.spi.InitialContextFactory;
import javax.naming.spi.InitialContextFactoryBuilder;
import javax.naming.spi.ObjectFactory;
import javax.naming.spi.ObjectFactoryBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.jndi.JNDIConstants;
import org.osgi.util.tracker.ServiceTracker;
/**
* This class represents the main integration point between the JNDI framework
* provided by the JDK and OSGi.
*
* This builder class is responsible for providing instances of
* InitialContextFactory and ObjectFactory to the JDK's NamingManager upon
* request. The builder uses the OSGi service registry to locate JNDI providers.
*
*/
class OSGiInitialContextFactoryBuilder implements ObjectFactoryBuilder, FactoryManager {
private static Logger logger =
Logger.getLogger(OSGiInitialContextFactoryBuilder.class.getName());
private static final String JNDI_PROPERTIES_FILE_NAME = "jndi.properties";
private final static String NO_CONTEXT_FACTORIES_MSG = "No JNDI implementations available";
/* calling JNDI Client's BundleContext */
private final BundleContext m_callerBundleContext;
/* JNDI implementation bundle's BundleContext */
private final BundleContext m_implBundleContext;
private ServiceTracker m_contextFactoryServiceTracker = null;
private ServiceTracker m_contextFactoryBuilderServiceTracker = null;
private ServiceTracker m_objectFactoryServiceTracker = null;
private ServiceTracker m_objectFactoryBuilderServiceTracker = null;
private ServiceTracker m_urlContextFactoryServiceTracker = null;
private ServiceTracker m_dirObjectFactoryServiceTracker = null;
/*
* Map of OSGi services to a List of Contexts created by that service.
* Each service services as a key to a list of Context implementations.
*/
private final Map<Object, WeakHashMap<Context, Object>> m_mapOfServicesToContexts =
Collections.synchronizedMap(new HashMap<Object, WeakHashMap<Context, Object>>());
public OSGiInitialContextFactoryBuilder(BundleContext callerBundleContext, BundleContext implBundleContext) {
m_callerBundleContext = callerBundleContext;
m_implBundleContext = implBundleContext;
try {
// create the service trackers inside a doPrivileged() block
// since this code is the only interaction with a BundleContext
// context not covered by the security-aware wrapper interfaces
SecurityUtils.invokePrivilegedActionNoReturn(new PrivilegedExceptionAction() {
@Override
public Object run() throws Exception {
createServiceTrackers(m_implBundleContext);
return null;
}
});
} catch (Exception e) {
logger.log(Level.FINE,
"Exception occurred while creating ServiceTracker implementations for JNDI Provider Services",
e);
}
}
/**
* This builder implementation uses the OSGi service registry to find
* matching JNDI service providers.
*/
@Override
public InitialContextFactory createInitialContextFactory(Hashtable environment) throws NamingException {
// check for valid tracker setup
if (m_contextFactoryServiceTracker == null) {
throw new NoInitialContextException(NO_CONTEXT_FACTORIES_MSG);
}
return getInitialContextFactoryInternal(getCombinedEnvironment(environment));
}
private InitialContextFactory getInitialContextFactoryInternal(Hashtable environment) throws NoInitialContextException {
if (environment.get(Context.INITIAL_CONTEXT_FACTORY) != null) {
final String initialContextFactoryName =
(String) environment.get(Context.INITIAL_CONTEXT_FACTORY);
Object factory =
obtainFactoryService(initialContextFactoryName, m_contextFactoryServiceTracker);
if (factory != null) {
return new InitialContextFactoryWrapper(
(InitialContextFactory) factory, this);
}
else {
// query known builders to see if any can support the
// given environment
InitialContextFactory contextFactory = getContextFactoryFromBuilder(environment);
if (contextFactory != null) {
return new InitialContextFactoryWrapper(contextFactory,
this);
}
}
throw new NoInitialContextException(NO_CONTEXT_FACTORIES_MSG);
}
else {
// query known builders to see if any can support
// the given environment
InitialContextFactory contextFactory = getContextFactoryFromBuilder(environment);
if (contextFactory != null) {
return new InitialContextFactoryWrapper(contextFactory, this);
}
// return the first valid context factory if one exists
try {
InitialContextFactory defaultContextFactory = getDefaultInitialContextFactory(environment);
if (defaultContextFactory == null) {
// return a wrapper to support URL-based lookups only
return new InitialContextFactoryWrapper(new DefaultInitialContextFactory(), this);
}
else {
return new InitialContextFactoryWrapper(defaultContextFactory, this);
}
}
catch (NamingException namingException) {
NoInitialContextException noInitialContextException =
new NoInitialContextException("Exception occured while iterating over the default InitialContextFactory services");
noInitialContextException.setRootCause(namingException);
throw noInitialContextException;
}
}
}
/**
* This Builder implementation uses the OSGi Service registry to find
* matching JNDI service providers for resolving references.
*
*/
@Override
public ObjectFactory createObjectFactory(Object obj, Hashtable environment) throws NamingException {
if (m_objectFactoryServiceTracker == null) {
throw new NoInitialContextException("No Object factories available");
}
return new ReturnReferenceInfoObjectFactory(createInnerObjectFactory(obj));
}
public DirObjectFactory getDirObjectFactory(Object obj, Hashtable environment) throws NamingException {
if (m_dirObjectFactoryServiceTracker == null) {
throw new NamingException("No DirObjectFactories available");
}
return new ReturnReferenceInfoDirObjectFactory(createInnerDirObjectFactory(obj)) ;
}
/**
* Returns a URL Context Factory implementation that is published to support
* the provided URL scheme.
*
* @param urlScheme the URL scheme that the URL context factory must support
* @return a javax.naming.spi.ObjectFactory instance that supports the
* requested URL scheme, or null if no matching factory was found
*/
@Override
public ObjectFactory getURLContextFactory(String urlScheme) {
if (m_urlContextFactoryServiceTracker.getServiceReferences() != null) {
ServiceReference[] serviceReferences = ServiceUtils.sortServiceReferences(m_urlContextFactoryServiceTracker);
for (int i = 0; i < serviceReferences.length; i++) {
ServiceReference serviceReference = serviceReferences[i];
if (serviceReference.getProperty(JNDIConstants.JNDI_URLSCHEME).equals(urlScheme)) {
return (ObjectFactory) m_callerBundleContext.getService(serviceReference);
}
}
}
return null;
}
@Override
public void associateFactoryService(Object factory, Context createdContext) {
if(m_mapOfServicesToContexts.containsKey(factory)) {
WeakHashMap<Context, Object> listOfContexts = m_mapOfServicesToContexts.get(factory);
listOfContexts.put(createdContext, null);
m_mapOfServicesToContexts.put(factory, listOfContexts);
} else {
WeakHashMap<Context, Object> listOfContexts = new WeakHashMap<Context, Object>();
listOfContexts.put(createdContext, null);
m_mapOfServicesToContexts.put(factory, listOfContexts);
}
}
@Override
public boolean isFactoryServiceActive(Object factory) {
return m_mapOfServicesToContexts.containsKey(factory);
}
/**
* Simple close method to close the ServiceTracker objects currently in use
* by the FactoryManager.
*/
protected void close() {
m_contextFactoryBuilderServiceTracker.close();
m_contextFactoryServiceTracker.close();
m_objectFactoryServiceTracker.close();
m_objectFactoryBuilderServiceTracker.close();
m_urlContextFactoryServiceTracker.close();
m_dirObjectFactoryServiceTracker.close();
}
private final void createServiceTrackers(BundleContext bundleContext) {
// create trackers
m_contextFactoryServiceTracker =
new ContextFactoryServiceTracker(bundleContext, InitialContextFactory.class.getName());
m_contextFactoryBuilderServiceTracker =
new ContextFactoryServiceTracker(bundleContext, InitialContextFactoryBuilder.class.getName());
m_objectFactoryServiceTracker =
new ObjectFactoryServiceTracker(bundleContext, ObjectFactory.class.getName());
m_dirObjectFactoryServiceTracker =
new ObjectFactoryServiceTracker(bundleContext, DirObjectFactory.class.getName());
m_objectFactoryBuilderServiceTracker =
createServiceTracker(bundleContext, ObjectFactoryBuilder.class.getName());
m_urlContextFactoryServiceTracker =
new URLContextFactoryServiceTracker(bundleContext, ObjectFactory.class.getName());
// open trackers
m_contextFactoryServiceTracker.open();
m_contextFactoryBuilderServiceTracker.open();
m_objectFactoryServiceTracker.open();
m_objectFactoryBuilderServiceTracker.open();
m_dirObjectFactoryServiceTracker.open();
m_urlContextFactoryServiceTracker.open();
}
private Object obtainFactoryService(String factoryServiceInterface,
ServiceTracker serviceTracker) {
ServiceReference[] serviceReferences = ServiceUtils.sortServiceReferences(serviceTracker);
for (int i = 0; i < serviceReferences.length; i++) {
ServiceReference serviceReference = serviceReferences[i];
String[] serviceInterfaces = (String[]) serviceReference
.getProperty(Constants.OBJECTCLASS);
List interfaceList = Arrays.asList(serviceInterfaces);
if (interfaceList.contains(factoryServiceInterface)) {
return m_callerBundleContext.getService(serviceReference);
}
}
return null;
}
/**
* Convenience method to query each known InitialContextFactoryBuilder, and to return
* the first non-null factory produced by a builder.
*
* The first builder to return a non-null result is
* given precedence as per Section 5.2.1.1 of RFC 142.
*
* @param environment the JNDI environment
* @return an InitialContextFactory instance that can support this request
* or null if no match can be found.
*/
private InitialContextFactory getContextFactoryFromBuilder(Hashtable environment) {
if (m_contextFactoryBuilderServiceTracker.getServiceReferences() != null) {
final ServiceReference[] serviceReferences = ServiceUtils.sortServiceReferences(m_contextFactoryBuilderServiceTracker);
for (int i = 0; i < serviceReferences.length; i++) {
ServiceReference serviceReference = serviceReferences[i];
InitialContextFactoryBuilder builder =
(InitialContextFactoryBuilder) m_callerBundleContext.getService(serviceReference);
try {
// if builder is null, then service is not available
if (builder != null) {
InitialContextFactory contextFactory = builder
.createInitialContextFactory(environment);
// the first builder to return a non-null result is
// given precedence as per Section 5.2.1.1 of RFC
// 142
if (contextFactory != null) {
return new DefaultBuilderSupportedInitialContextFactory(
contextFactory, builder);
}
}
}
catch (NamingException namingException) {
// catch exception, allow iteration to continue
logger.log(Level.FINE,
"NamingException occurred while invoking on an InitialContextFactoryBuilder",
namingException);
}
}
}
return null;
}
/**
* Convenience method for obtaining the "default" InitialContextFactory.
* This method takes the list of known InitialContextFactory implementations,
* in service ranking order, and attempts to use each to create a JNDI Context
* given the environment passed in. The first service to return a non-null
* result is returned.
*
* @param environment the JNDI environment to use when creating the Context
* @return the first InitialContextFactory service that can support this environment,
* or null if no matching service was found.
* @throws NamingException any NamingException thrown by an InitialContextFactory
* service is thrown back to the caller.
*/
private InitialContextFactory getDefaultInitialContextFactory(Hashtable environment) throws NamingException {
if (m_contextFactoryServiceTracker.getServiceReferences() != null) {
ServiceReference[] serviceReferences = ServiceUtils.sortServiceReferences(m_contextFactoryServiceTracker);
for (int i = 0; i < serviceReferences.length; i++) {
ServiceReference serviceReference = serviceReferences[i];
InitialContextFactory factoryService =
(InitialContextFactory) m_callerBundleContext.getService(serviceReference);
if(factoryService.getInitialContext(environment) != null) {
return factoryService;
} else {
m_callerBundleContext.ungetService(serviceReference);
}
}
}
return null;
}
/**
* Convenience method to query each known ObjectFactoryBuilder, and to return
* the first non-null factory produced by a builder.
*
* The first builder to return a non-null result is
* given precedence as per Section 5.2.2.1 of RFC 142.
*
* @param environment the JNDI environment
* @param refInfo the Object to resolve
* @return an ObjectFactory instance that matches this Reference,
* or null if no match can be found.
*/
private ObjectFactory getObjectFactoryFromBuilder(Hashtable environment, Object refInfo) {
if (m_objectFactoryBuilderServiceTracker.getServiceReferences() != null) {
final ServiceReference[] serviceReferences = ServiceUtils.sortServiceReferences(m_objectFactoryBuilderServiceTracker);
for (int i = 0; i < serviceReferences.length; i++) {
ServiceReference serviceReference = serviceReferences[i];
ObjectFactoryBuilder builder = (ObjectFactoryBuilder) m_callerBundleContext
.getService(serviceReference);
try {
ObjectFactory factory =
builder.createObjectFactory(refInfo, environment);
if (factory != null) {
return factory;
}
}
catch (NamingException namingException) {
// catch exception, allow iteration to continue
logger.log(Level.FINE,
"NamingException occurred while invoking on an ObjectFactoryBuilder",
namingException);
}
}
}
return null;
}
/**
* Examines a Reference to determine if a StringRefAddr of type
* 'URL' is associated with the Reference. If so, the Factory Manager
* will attempt to locate a URL context factory that can be used to
* resolve the reference.
*
* @param reference to be resolved
* @return an object resolved from a URL Context Factory, or null if no URL
* Context Factory could resolve the reference.
*/
private Object getObjectFromURLContextFactoryFromReference(final Reference reference, Hashtable environment) {
Enumeration refAddresses = reference.getAll();
while(refAddresses.hasMoreElements()) {
RefAddr address = (RefAddr)refAddresses.nextElement();
if((address instanceof StringRefAddr) && (address.getType().equals("URL"))) {
String urlContent = (String)address.getContent();
try {
URI uri = new URI(urlContent);
ObjectFactory objectFactory =
getURLContextFactory(uri.getScheme());
if(objectFactory != null) {
Object objToReturn = objectFactory.getObjectInstance(urlContent, null, null, environment);
if(objToReturn != null) {
// return the first object that is constructed from a URL string reference address
return objToReturn;
}
}
}
catch (URISyntaxException e) {
logger.log(Level.FINEST,
"Exception thrown while parsing URL. This URL reference address will be skipped.",
e);
}
catch (Exception e) {
logger.log(Level.FINEST,
"Exception thrown while parsing URL. This URL reference address will be skipped.",
e);
}
}
}
return null;
}
private Object getObjectToResolve(Object obj) throws NamingException {
Object objToResolve;
if(obj instanceof Referenceable) {
// obtain the Reference before proceeding
Referenceable referenceable = (Referenceable)obj;
objToResolve = referenceable.getReference();
} else {
// this object is either a Reference or another type
objToResolve = obj;
}
return objToResolve;
}
private ObjectFactory createInnerObjectFactory(Object obj) throws NamingException {
final Object objToResolve = getObjectToResolve(obj);
if (objToResolve instanceof Reference) {
final Reference reference = (Reference) objToResolve;
if (reference.getFactoryClassName() != null) {
return new FactoryNameSpecifiedObjectFactory();
}
else {
return new NoFactoryNameSpecifiedObjectFactory();
}
}
else {
return new NoReferenceObjectFactory();
}
}
private DirObjectFactory createInnerDirObjectFactory(Object obj) throws NamingException {
final Object objToResolve = getObjectToResolve(obj);
if (objToResolve instanceof Reference) {
final Reference reference = (Reference) objToResolve;
if (reference.getFactoryClassName() != null) {
return new FactoryNameSpecifiedDirObjectFactory();
}
else {
return new NoFactoryNameSpecifiedDirObjectFactory();
}
}
else {
return new NoReferenceDirObjectFactory();
}
}
/**
* Utility method for creating the set of environment properties from the
* following sources (in order of priority):
*
* 1. User-defined properties
* 2. Properties defined in a jndi.properties file in the caller's archive (if it exists)
*
*
* @param userEnvironment original environment passed in by the caller
* @return a Hashtable representing the combined JNDI environment for this context
*/
private Hashtable getCombinedEnvironment(Hashtable userEnvironment) {
// create a copy of the user-defined environment settings
Hashtable combinedEnvironment = new Hashtable();
combinedEnvironment.putAll(userEnvironment);
// obtain environment properties defined in the calling bundle's archive
Properties fileDefinedEnvironment =
getFileDefinedJndiProperties(m_callerBundleContext);
if(fileDefinedEnvironment != null) {
Enumeration keyEnum = fileDefinedEnvironment.keys();
while(keyEnum.hasMoreElements()) {
final String key = (String) keyEnum.nextElement();
if(!combinedEnvironment.containsKey(key)) {
// add the file-defined property to the combined environment
// only add keys that do not exist, since the user-defined
// environment takes precedence over the file-defined
combinedEnvironment.put(key, fileDefinedEnvironment.get(key));
}
}
}
return combinedEnvironment;
}
private Object resolveObjectUsingBuilders(Object objectToResolve, Name name, Context context,
Hashtable environment)
throws Exception {
ObjectFactory objectFactory =
getObjectFactoryFromBuilder(environment, objectToResolve);
if(objectFactory != null) {
Object resolvedObject = objectFactory.getObjectInstance(objectToResolve, name, context, environment);
if(resolvedObject != null) {
return resolvedObject;
}
}
return null;
}
private Object resolveObjectUsingObjectFactories(Object objectToResolve, Name name, Context context, Hashtable environment) throws NamingException {
if (m_objectFactoryServiceTracker.getServiceReferences() != null) {
final ServiceReference[] serviceReferences = ServiceUtils.sortServiceReferences(m_objectFactoryServiceTracker);
for (int i = 0; i < serviceReferences.length; i++) {
ServiceReference serviceReference = serviceReferences[i];
ObjectFactory factory =
(ObjectFactory) m_callerBundleContext.getService(serviceReference);
try {
Object result =
factory.getObjectInstance(objectToResolve, name, context, environment);
// release the service for this factory
m_callerBundleContext.ungetService(serviceReference);
if (result != null) {
// return resolved object
return result;
}
}
catch (Exception exception) {
NamingException namingException = new NamingException("Exception occurred while trying to resolve object using ObjectFactory search");
namingException.setRootCause(exception);
throw namingException;
}
}
}
return null;
}
private Object resolveObjectUsingDirObjectFactories(Object objectToResolve, Name name, Context context, Hashtable environment, Attributes attributes) throws NamingException {
if (m_dirObjectFactoryServiceTracker.getServiceReferences() != null) {
final ServiceReference[] serviceReferences = ServiceUtils.sortServiceReferences(m_dirObjectFactoryServiceTracker);
for (int i = 0; i < serviceReferences.length; i++) {
ServiceReference serviceReference = serviceReferences[i];
DirObjectFactory factory =
(DirObjectFactory) m_callerBundleContext.getService(serviceReference);
try {
Object result =
factory.getObjectInstance(objectToResolve, name, context, environment, attributes);
// release the service reference
m_callerBundleContext.ungetService(serviceReference);
if (result != null) {
// return the resolved object
return result;
}
}
catch (Exception exception) {
NamingException namingException = new NamingException("Exception occurred while trying to resolve object using ObjectFactory search");
namingException.setRootCause(exception);
throw namingException;
}
}
}
return null;
}
private Object resolveDirObjectUsingBuilders(Object objectToResolve, Name name, Context context, Hashtable environment, Attributes attributes)
throws Exception {
ObjectFactory objectFactory =
getObjectFactoryFromBuilder(environment, objectToResolve);
if((objectFactory != null) && (objectFactory instanceof DirObjectFactory)) {
DirObjectFactory dirObjectFactory = (DirObjectFactory)objectFactory;
Object resolvedObject = dirObjectFactory.getObjectInstance(objectToResolve, name, context, environment, attributes);
if(resolvedObject != null) {
return resolvedObject;
}
}
return null;
}
/**
* Checks the calling Bundle in order to search for a
* jndi.properties file.
*
* Check the client's bundle for a jndi.properties file in the archive
*
* @return a Properties instance that contains the properties defined in
* a jndi.properties file for the caller's archive, or null if none exists
*/
private static Properties getFileDefinedJndiProperties(BundleContext callerBundleContext) {
if (callerBundleContext.getBundle() != null) {
Bundle bundle = callerBundleContext.getBundle();
try {
URL propertiesURL = bundle.getResource(JNDI_PROPERTIES_FILE_NAME);
if (propertiesURL != null) {
InputStream userDefinedPropertiesStream = null;
try {
userDefinedPropertiesStream = propertiesURL.openStream();
Properties fileDefinedJndiProperties = new Properties();
fileDefinedJndiProperties.load(userDefinedPropertiesStream);
return fileDefinedJndiProperties;
}
catch (FileNotFoundException e) {
// this exception should never occur, since the File has
// already been tested to be available
logger.log(Level.FINEST, "Exception encountered while trying to locate a jndi.properties file.", e);
}
finally {
if (userDefinedPropertiesStream != null) {
try {
userDefinedPropertiesStream.close();
}
catch (IOException e) {
logger.log(Level.FINEST, "Exception encountered while trying to close a jndi.properties file.", e);
}
}
}
}
}
catch (IOException e) {
logger.log(Level.FINEST,
"Exception encounted while trying to load a jndi.properties file",
e);
}
}
return null;
}
/**
* Convenience method for creating ServiceTracker instances.
*
* This method only creates tracker instances for a single interface type,
* and does not support customizing the tracker.
*
* @param bundleContext the BundleContext to use to create the tracker
* @param serviceInterface the service interface name to use for this
* tracker
*
* @return a ServiceTracker instance for the given interface
*/
private static ServiceTracker createServiceTracker(BundleContext bundleContext, String serviceInterface) {
return new ServiceTracker(bundleContext, serviceInterface, null);
}
private static final class URLContextFactoryServiceTracker extends ServiceTracker {
private URLContextFactoryServiceTracker(BundleContext context, String clazz) {
super(context, clazz, null);
}
@Override
public Object addingService(ServiceReference serviceReference) {
if (serviceReference.getProperty(JNDIConstants.JNDI_URLSCHEME) != null) {
return super.addingService(serviceReference);
}
return null;
}
}
private static final class ObjectFactoryServiceTracker extends ServiceTracker {
private ObjectFactoryServiceTracker(BundleContext context, String clazz) {
super(context, clazz, null);
}
@Override
public Object addingService(ServiceReference serviceReference) {
if (serviceReference.getProperty(JNDIConstants.JNDI_URLSCHEME) == null) {
return super.addingService(serviceReference);
}
return null;
}
}
private final class ContextFactoryServiceTracker extends ServiceTracker {
private ContextFactoryServiceTracker(BundleContext context, String clazz) {
super(context, clazz, null);
}
@Override
public void removedService(ServiceReference reference, Object service) {
handleRemovedService(reference, service);
}
@Override
public Object addingService(ServiceReference reference) {
return handleAddingService(reference);
}
private void handleRemovedService(ServiceReference reference, Object service) {
super.removedService(reference, service);
m_mapOfServicesToContexts.remove(service);
}
private Object handleAddingService(ServiceReference reference) {
return super.addingService(reference);
}
}
/**
* Query the inner ObjectFactory instance to see if that factory
* can resolve the object.
*
* If no matching ObjectFactory services exist that can resolve the object,
* return a specialized ObjectFactory implementation that
* merely returns the reference passed in. This allows the Factory
* Manager to more closely comply with the behavior specified in the
* javadoc for NamingManger.getObjectInstance()
*
*
* @version $Revision: 9053 $
*/
private static class ReturnReferenceInfoObjectFactory implements ObjectFactory {
private final ObjectFactory m_objectFactory;
public ReturnReferenceInfoObjectFactory(ObjectFactory objectFactory) {
m_objectFactory = objectFactory;
}
@Override
public Object getObjectInstance(Object refInfo, Name name,
Context context, Hashtable environment) throws Exception {
if (m_objectFactory != null) {
Object resolvedObject =
m_objectFactory.getObjectInstance(refInfo, name,
context, environment);
if (resolvedObject != null) {
return resolvedObject;
}
}
// in all other cases return refInfo
return refInfo;
}
}
/**
* Query the inner DirObjectFactory instance to see if that factory
* can resolve the object.
*
* If no matching DirObjectFactory services exist that can resolve the object,
* return a specialized ObjectFactory implementation that
* merely returns the reference passed in. This allows the Factory
* Manager to more closely comply with the behavior specified in the
* javadoc for DirectoryManger.getObjectInstance()
*
*
* @version $Revision: 9053 $
*/
private static final class ReturnReferenceInfoDirObjectFactory extends ReturnReferenceInfoObjectFactory implements DirObjectFactory {
private final DirObjectFactory m_dirObjectFactory;
public ReturnReferenceInfoDirObjectFactory(DirObjectFactory dirObjectFactory) {
super(dirObjectFactory);
m_dirObjectFactory = dirObjectFactory;
}
@Override
public Object getObjectInstance(Object refInfo, Name name,
Context context, Hashtable environment, Attributes attributes) throws Exception {
if (m_dirObjectFactory != null) {
Object resolvedObject =
m_dirObjectFactory.getObjectInstance(refInfo, name,
context, environment, attributes);
if (resolvedObject != null) {
return resolvedObject;
}
}
// in all other cases return refInfo
return refInfo;
}
}
/**
* Inner ObjectFactory implementation used to handle cases where a Reference
* is specified, but the Reference does not indicate which ObjectFactory should be used
* to resolve the object.
*
* This factory will dynamically attempt to use a URL context factory to
* resolve the object (if a Reference Address of type "URL" is detected),
* and will also consult the known ObjectFactoryBuilder services if no other
* way to resolve the reference exists.
*
*
* @version $Revision: 9053 $
*/
private final class NoFactoryNameSpecifiedObjectFactory implements ObjectFactory {
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment) throws Exception {
if(refInfo == null) {
return null;
}
Object objectToResolve = getObjectToResolve(refInfo);
if(objectToResolve instanceof Reference) {
Reference reference = (Reference)objectToResolve;
Object resultFromURLContextFactories =
getObjectFromURLContextFactoryFromReference(reference, environment);
if (resultFromURLContextFactories != null) {
return resultFromURLContextFactories;
}
Object resultFromBuilders = resolveObjectUsingBuilders(objectToResolve, name, context, environment);
if(resultFromBuilders != null) {
return resultFromBuilders;
}
Object resultFromObjectFactories =
resolveObjectUsingObjectFactories(objectToResolve, name, context, environment);
if(resultFromObjectFactories != null) {
return resultFromObjectFactories;
}
}
return null;
}
}
private final class NoFactoryNameSpecifiedDirObjectFactory implements DirObjectFactory {
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment, Attributes attributes) throws Exception {
if(refInfo == null) {
return null;
}
Object objectToResolve = getObjectToResolve(refInfo);
if(objectToResolve instanceof Reference) {
Reference reference = (Reference)objectToResolve;
Object resultFromURLContextFactories =
getObjectFromURLContextFactoryFromReference(reference, environment);
if (resultFromURLContextFactories != null) {
return resultFromURLContextFactories;
}
Object resultFromBuilders = resolveDirObjectUsingBuilders(objectToResolve, name, context, environment, attributes);
if(resultFromBuilders != null) {
return resultFromBuilders;
}
Object resultFromDirObjectFactories =
resolveObjectUsingDirObjectFactories(objectToResolve, name, context, environment, attributes);
if(resultFromDirObjectFactories != null) {
return resultFromDirObjectFactories;
}
}
return null;
}
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment) throws Exception {
// no-op for this DirObjectFactory
return null;
}
}
/**
* Inner ObjectFactory implementation used to handle cases where a Reference
* is specified, and the Reference indicates which ObjectFactory should be used
* to resolve the object.
*
* This factory will dynamically attempt to use locate the specified
* factory in the OSGi service registry, and will also consult the known
* ObjectFactoryBuilder services if no other way to resolve the reference
* exists.
*
*
* @version $Revision: 9053 $
*/
private final class FactoryNameSpecifiedObjectFactory implements ObjectFactory {
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment) throws Exception {
Object objectToResolve = getObjectToResolve(refInfo);
if(objectToResolve instanceof Reference) {
// if a factory class name is specified, look through the list
// of known ObjectFactories, and try to find a service published
// that also supports the custom interface.
Reference reference = (Reference)objectToResolve;
Object factory =
obtainFactoryService(reference.getFactoryClassName(), m_objectFactoryServiceTracker);
if (factory != null) {
ObjectFactory objectFactory = (ObjectFactory)factory;
Object resolvedObject =
objectFactory.getObjectInstance(objectToResolve, name, context, environment);
if(resolvedObject != null) {
return resolvedObject;
}
} else {
return resolveObjectUsingBuilders(objectToResolve, name, context, environment);
}
}
return null;
}
}
private final class FactoryNameSpecifiedDirObjectFactory implements DirObjectFactory {
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment, Attributes attributes) throws Exception {
Object objectToResolve = getObjectToResolve(refInfo);
if(objectToResolve instanceof Reference) {
// if a factory class name is specified, look through the list
// of known ObjectFactories, and try to find a service published
// that also supports the custom interface.
Reference reference = (Reference)objectToResolve;
Object factory =
obtainFactoryService(reference.getFactoryClassName(), m_dirObjectFactoryServiceTracker);
if (factory != null) {
DirObjectFactory dirObjectFactory = (DirObjectFactory)factory;
Object resolvedObject =
dirObjectFactory.getObjectInstance(objectToResolve, name, context, environment, attributes);
if(resolvedObject != null) {
return resolvedObject;
}
} else {
return resolveDirObjectUsingBuilders(objectToResolve, name, context, environment, attributes);
}
}
return null;
}
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment) throws Exception {
// always return null, since this DirObjectFactory is a wrapper type
return null;
}
}
private class NoReferenceObjectFactory implements ObjectFactory {
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment) throws Exception {
// first query all known ObjectFactoryBuilder services to resolve this reference
Object resultFromBuilders =
resolveObjectUsingBuilders(refInfo, name, context, environment);
if(resultFromBuilders != null) {
return resultFromBuilders;
}
// as a last resort, query all known ObjectFactory services to attempt to resolve this reference
Object resultFromObjectFactories =
resolveObjectUsingObjectFactories(refInfo, name, context, environment);
if(resultFromObjectFactories != null) {
return resultFromObjectFactories;
}
return null;
}
}
private class NoReferenceDirObjectFactory implements DirObjectFactory {
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment, Attributes attributes) throws Exception {
final Object resultFromBuilders = resolveDirObjectUsingBuilders(refInfo, name, context, environment, attributes);
if(resultFromBuilders != null) {
return resultFromBuilders;
}
Object resultFromDirObjectFactories =
resolveObjectUsingDirObjectFactories(refInfo, name, context, environment, attributes);
if(resultFromDirObjectFactories != null) {
return resultFromDirObjectFactories;
}
return null;
}
@Override
public Object getObjectInstance(Object refInfo, Name name, Context context, Hashtable environment) throws Exception {
// no-op for this DirObjectFactory
return null;
}
}
private static class DefaultBuilderSupportedInitialContextFactory implements BuilderSupportedInitialContextFactory {
private final InitialContextFactory m_factory;
private final InitialContextFactoryBuilder m_builder;
DefaultBuilderSupportedInitialContextFactory(InitialContextFactory factory, InitialContextFactoryBuilder builder) {
m_factory = factory;
m_builder = builder;
}
@Override
public InitialContextFactoryBuilder getBuilder() {
return m_builder;
}
@Override
public Context getInitialContext(Hashtable environment) throws NamingException {
return m_factory.getInitialContext(environment);
}
}
}