/*******************************************************************************
 * 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);
		}
	}

	
	
}
