1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.jndi;
18
19
20 import java.util.Hashtable;
21
22 import javax.naming.ConfigurationException;
23 import javax.naming.Context;
24 import javax.naming.InitialContext;
25 import javax.naming.NamingException;
26 import javax.naming.spi.InitialContextFactory;
27
28 import org.apache.ldap.server.configuration.AddContextPartitionConfiguration;
29 import org.apache.ldap.server.configuration.Configuration;
30 import org.apache.ldap.server.configuration.RemoveContextPartitionConfiguration;
31 import org.apache.ldap.server.configuration.ShutdownConfiguration;
32 import org.apache.ldap.server.configuration.StartupConfiguration;
33 import org.apache.ldap.server.configuration.SyncConfiguration;
34
35
36 /***
37 * A server-side JNDI provider implementation of {@link InitialContextFactory}.
38 * This class can be utilized via JNDI API in the standard fashion:
39 * <p>
40 * <code>
41 * Hashtable env = new Hashtable();
42 * env.put( Context.PROVIDER_URL, "ou=system" );
43 * env.put(
44 * Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.CoreContextFactory" );
45 * InitialContext initialContext = new InitialContext( env );
46 * </code>
47 * <p>
48 * Unfortunately, {@link InitialContext} creates a new instance of
49 * {@link InitialContextFactory} implementation everytime it is instantiated,
50 * so this factory maintains only a static, singleton instance of
51 * {@link ContextFactoryService}, which provides actual implementation.
52 * Please note that you'll also have to maintain any stateful information
53 * as using singleton pattern if you're going to extend this factory.
54 * <p>
55 * This class implements {@link ContextFactoryServiceListener}. This means that
56 * you can listen to the changes occurs to {@link ContextFactoryService}, and
57 * react to it (e.g. executing additional business logic).
58 *
59 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
60 * @version $Rev: 264732 $, $Date: 2005-08-30 04:04:51 -0400 (Tue, 30 Aug 2005) $
61 *
62 * @see javax.naming.spi.InitialContextFactory
63 */
64 public abstract class AbstractContextFactory implements InitialContextFactory, ContextFactoryServiceListener
65 {
66
67
68
69
70 /***
71 * Creates a new instance.
72 */
73 protected AbstractContextFactory()
74 {
75 }
76
77 public final synchronized Context getInitialContext( Hashtable env ) throws NamingException
78 {
79 Configuration cfg = Configuration.toConfiguration( env );
80 env = ( Hashtable ) env.clone();
81 String principal = getPrincipal( env );
82 byte[] credential = getCredential( env );
83 String authentication = getAuthentication( env );
84 String providerUrl = getProviderUrl( env );
85
86 ContextFactoryService service = ContextFactoryService.getInstance( cfg.getInstanceId() );
87
88
89 if( cfg instanceof ShutdownConfiguration )
90 {
91 service.shutdown();
92 }
93 else if( cfg instanceof SyncConfiguration )
94 {
95 service.sync();
96 }
97 else if( cfg instanceof StartupConfiguration )
98 {
99 service.startup( this, env );
100 }
101 else if( cfg instanceof AddContextPartitionConfiguration )
102 {
103 new ContextPartitionNexusProxy(
104 service.getJndiContext( principal, credential, authentication, providerUrl ),
105 service).addContextPartition( ( ( AddContextPartitionConfiguration ) cfg ).getContextPartitionConfiguration() );
106 }
107 else if( cfg instanceof RemoveContextPartitionConfiguration )
108 {
109 new ContextPartitionNexusProxy(
110 service.getJndiContext( principal, credential, authentication, providerUrl ),
111 service).removeContextPartition( ( ( RemoveContextPartitionConfiguration ) cfg ).getSuffix() );
112 }
113 else if( service == null )
114 {
115 throw new NamingException( "Unknown configuration: " + cfg );
116 }
117
118 return service.getJndiContext( principal, credential, authentication, providerUrl );
119 }
120
121 private String getProviderUrl( Hashtable env )
122 {
123 String providerUrl;
124 Object value;
125 value = env.get( Context.PROVIDER_URL );
126 if( value == null )
127 {
128 value = "";
129 }
130 providerUrl = value.toString();
131
132 env.put( Context.PROVIDER_URL, providerUrl );
133
134 return providerUrl;
135 }
136
137 private String getAuthentication( Hashtable env )
138 {
139 String authentication;
140 Object value = env.get( Context.SECURITY_AUTHENTICATION );
141 if( value == null )
142 {
143 authentication = "none";
144 }
145 else
146 {
147 authentication = value.toString();
148 }
149
150 env.put( Context.SECURITY_AUTHENTICATION, authentication );
151
152 return authentication;
153 }
154
155 private byte[] getCredential( Hashtable env ) throws ConfigurationException
156 {
157 byte[] credential;
158 Object value = env.get( Context.SECURITY_CREDENTIALS );
159 if( value == null )
160 {
161 credential = null;
162 }
163 else if( value instanceof String )
164 {
165 credential = ( ( String ) value ).getBytes();
166 }
167 else if( value instanceof byte[] )
168 {
169 credential = ( byte[] ) value;
170 }
171 else
172 {
173 throw new ConfigurationException( "Can't convert '" + Context.SECURITY_CREDENTIALS + "' to byte[]." );
174 }
175
176 if( credential != null )
177 {
178 env.put( Context.SECURITY_CREDENTIALS, credential );
179 }
180
181 return credential;
182 }
183
184 private String getPrincipal( Hashtable env )
185 {
186 String principal;
187 Object value = env.get( Context.SECURITY_PRINCIPAL );
188 if( value == null )
189 {
190 principal = null;
191 }
192 else
193 {
194 principal = value.toString();
195 env.put( Context.SECURITY_PRINCIPAL, principal );
196 }
197
198 return principal;
199 }
200 }