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