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