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.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      // Members
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          // Execute configuration
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 }