Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 95dcb004f5c9b29437bfe878a544331862886e65 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*******************************************************************************
 * 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.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.NoInitialContextException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.ldap.LdapContext;
import javax.naming.spi.InitialContextFactory;
import javax.naming.spi.InitialContextFactoryBuilder;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.jndi.JNDIContextManager;

class TraditionalInitialContextFactoryBuilder implements InitialContextFactoryBuilder {

	private static final String JNDI_CONTEXT_MANAGER_CLASS = 
		JNDIContextManager.class.getName();
	
	private static final String INITIAL_CONTEXT_CLASSNAME = 
		InitialContext.class.getName();
	
	private static final String INITIAL_DIR_CONTEXT_CLASSNAME = 
		InitialDirContext.class.getName();
	
	public TraditionalInitialContextFactoryBuilder() {
	}
	
	@Override
	public InitialContextFactory createInitialContextFactory(Hashtable environment) throws NamingException {
		return new TraditionalInitialContextFactory();
	}
	
	
	
	/**
	 * An InitialContextFactory implementation that handles requests from 
	 * "traditional" clients (non-OSGi clients).  
	 * 
	 * This factory first attempts to obtain the client's BundleContext.  If this BundleContext
	 * cannot be located, a NoInitialContextException is thrown.  
	 *
	 * 
	 * @version $Revision$
	 */
	private static class TraditionalInitialContextFactory implements InitialContextFactory {

		@Override
		public Context getInitialContext(Hashtable environment) throws NamingException {
			// try to find BundleContext, assuming a call to the InitialContext constructor
			BundleContext clientBundleContext = 
				BuilderUtils.getBundleContext(environment, INITIAL_CONTEXT_CLASSNAME);

			if(clientBundleContext == null) {
				// try to find BundleContext, assuming a call to the InitialDirContext constructor
				clientBundleContext = 
					BuilderUtils.getBundleContext(environment, INITIAL_DIR_CONTEXT_CLASSNAME);
			}
			
			
			if(clientBundleContext == null) {
				throw new NoInitialContextException("Client's BundleContext could not be located");
			} else {
				ServiceReference serviceRef = 
					clientBundleContext.getServiceReference(JNDI_CONTEXT_MANAGER_CLASS);
				
				// if service not available, throw exception back to caller
				if(serviceRef == null) {
					throw new NamingException("JNDIContextManager service not available yet, cannot create a new context");
				} else {
					JNDIContextManager contextManager = 
						(JNDIContextManager)clientBundleContext.getService(serviceRef);
					if(contextManager == null) {
						throw new NamingException("JNDIContextManager service not available yet, cannot create a new context");
					} else {
						// install a dynamic proxy to trap calls to Context.close()
						try {
							final Context newInitialContext = contextManager.newInitialContext(environment);
							final TraditionalContextInvocationHandler handler = 
								new TraditionalContextInvocationHandler(serviceRef, newInitialContext, clientBundleContext);
							// create the correct proxy
							if (newInitialContext instanceof LdapContext) {
								return (LdapContext)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {LdapContext.class}, handler);
							} else if(newInitialContext instanceof DirContext) {
								return (DirContext)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {DirContext.class}, handler);
							} else {
								return (Context)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {Context.class}, handler);
							}
							
						}
						catch (NamingException namingException) {
							// clean up reference to JNDIContextManager service
							clientBundleContext.ungetService(serviceRef);
							// re-throw exception
							throw namingException;
						}
					}
				}
			}
		}
	}
	
	private static class TraditionalContextInvocationHandler implements InvocationHandler {

		private final ServiceReference m_referenceToContextManager;
		private final Context m_context;
		private final BundleContext m_bundleContext;
		
		TraditionalContextInvocationHandler(ServiceReference refToContextManager, Context context, BundleContext bundleContext) {
			m_referenceToContextManager = refToContextManager;
			m_context = context;
			m_bundleContext = bundleContext;
			
		}
		
		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			if(method.getName().equals("close")) {
				// clean up reference to JNDIContextManager
				m_bundleContext.ungetService(m_referenceToContextManager);
			}
			
			return ReflectionUtils.invokeMethodOnContext(method, m_context, args);
		}
	}

}

Back to the top