View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
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      // Members
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          // Execute configuration
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 }