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;
18  
19  
20  import junit.framework.TestCase;
21  import org.apache.commons.io.FileUtils;
22  import org.apache.ldap.common.exception.LdapConfigurationException;
23  import org.apache.ldap.common.ldif.LdifIterator;
24  import org.apache.ldap.common.ldif.LdifParser;
25  import org.apache.ldap.common.ldif.LdifParserImpl;
26  import org.apache.ldap.common.message.LockableAttributesImpl;
27  import org.apache.ldap.common.name.LdapName;
28  import org.apache.ldap.server.jndi.EnvKeys;
29  import org.apache.mina.util.AvailablePortFinder;
30  
31  import javax.naming.Context;
32  import javax.naming.InitialContext;
33  import javax.naming.Name;
34  import javax.naming.NamingException;
35  import javax.naming.directory.Attributes;
36  import javax.naming.ldap.InitialLdapContext;
37  import javax.naming.ldap.LdapContext;
38  import java.io.File;
39  import java.io.IOException;
40  import java.io.InputStream;
41  import java.util.Hashtable;
42  
43  
44  /***
45   * A simple testcase for testing JNDI provider functionality.
46   *
47   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
48   * @version $Rev: 169088 $
49   */
50  public abstract class AbstractServerTest extends TestCase
51  {
52      /*** the context root for the system partition */
53      protected LdapContext sysRoot;
54  
55      /*** flag whether to delete database files for each test or not */
56      protected boolean doDelete = true;
57  
58      /*** extra environment parameters that can be added before setUp */
59      protected Hashtable extras = new Hashtable();
60  
61      /*** extra environment parameters that can be added before setUp to override values */
62      protected Hashtable overrides = new Hashtable();
63  
64      protected int port = -1;
65  
66      /***
67       * Get's the initial context factory for the provider's ou=system context
68       * root.
69       *
70       * @see junit.framework.TestCase#setUp()
71       */
72      protected void setUp() throws Exception
73      {
74          super.setUp();
75  
76          if ( overrides.containsKey( EnvKeys.WKDIR ) )
77          {
78              doDelete( new File( ( String ) overrides.get( EnvKeys.WKDIR ) ) );
79          }
80          else
81          {
82              doDelete( new File( "target" + File.separator + "apacheds" ) );
83          }
84  
85          port = AvailablePortFinder.getNextAvailable( 1024 );
86          
87          extras.put( EnvKeys.LDAP_PORT, String.valueOf( port ) );
88  
89          setSysRoot( "uid=admin,ou=system", "secret" );
90      }
91  
92  
93      /***
94       * Deletes the Eve working directory.
95       */
96      protected void doDelete( File wkdir ) throws IOException
97      {
98          if ( doDelete )
99          {
100             if ( wkdir.exists() )
101             {
102                 FileUtils.deleteDirectory( wkdir );
103             }
104             if ( wkdir.exists() )
105             {
106                 throw new IOException( "Failed to delete: " + wkdir );
107             }
108         }
109     }
110 
111 
112     /***
113      * Sets and returns the system root.  Values of user and password used to
114      * set the respective JNDI properties.  These values can be overriden by the
115      * overrides properties.
116      *
117      * @param user the username for authenticating as this user
118      * @param passwd the password of the user
119      * @return the sysRoot context which is also set
120      * @throws NamingException if there is a failure of any kind
121      */
122     protected LdapContext setSysRoot( String user, String passwd ) throws NamingException
123     {
124         Hashtable env = new Hashtable();
125 
126         env.put( Context.SECURITY_PRINCIPAL, user );
127 
128         env.put( Context.SECURITY_CREDENTIALS, passwd );
129 
130         return setSysRoot( env );
131     }
132 
133 
134     /***
135      * Sets the system root taking into account the extras and overrides
136      * properties.  In between these it sets the properties for the working
137      * directory, the provider URL and the JNDI InitialContexFactory to use.
138      *
139      * @param env an environment to use while setting up the system root.
140      * @return the sysRoot context which is also set
141      * @throws NamingException if there is a failure of any kind
142      */
143     protected LdapContext setSysRoot( Hashtable env ) throws NamingException
144     {
145         Hashtable envFinal = new Hashtable();
146 
147         envFinal.putAll( extras );
148 
149         envFinal.putAll( env );
150 
151         envFinal.put( Context.PROVIDER_URL, "ou=system" );
152 
153         envFinal.put( EnvKeys.WKDIR, "target" + File.separator + "apacheds" );
154 
155         envFinal.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.ServerContextFactory" );
156 
157         envFinal.putAll( overrides );
158 
159         return sysRoot = new InitialLdapContext( envFinal, null );
160     }
161 
162 
163 
164     /***
165      * Sets the system context root to null.
166      *
167      * @see junit.framework.TestCase#tearDown()
168      */
169     protected void tearDown() throws Exception
170     {
171         super.tearDown();
172 
173         Hashtable env = new Hashtable();
174 
175         env.put( Context.PROVIDER_URL, "ou=system" );
176 
177         env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.ServerContextFactory" );
178 
179         env.put( EnvKeys.SHUTDOWN, "" );
180 
181         env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
182 
183         env.put( Context.SECURITY_CREDENTIALS, "secret" );
184 
185         try { new InitialContext( env ); } catch( Exception e ) {}
186 
187         sysRoot = null;
188 
189         Runtime.getRuntime().gc();
190     }
191 
192 
193     /***
194      * Imports the LDIF entries packaged with the Eve JNDI provider jar into
195      * the newly created system partition to prime it up for operation.  Note
196      * that only ou=system entries will be added - entries for other partitions
197      * cannot be imported and will blow chunks.
198      *
199      * @throws NamingException if there are problems reading the ldif file and
200      * adding those entries to the system partition
201      */
202     protected void importLdif( InputStream in ) throws NamingException
203     {
204         Hashtable env = new Hashtable();
205 
206         env.putAll( sysRoot.getEnvironment() );
207 
208         LdapContext ctx = new InitialLdapContext( env, null );
209 
210         LdifParser parser = new LdifParserImpl();
211 
212         try
213         {
214             LdifIterator iterator = new LdifIterator( in );
215 
216             while ( iterator.hasNext() )
217             {
218                 Attributes attributes = new LockableAttributesImpl();
219 
220                 String ldif = ( String ) iterator.next();
221 
222                 parser.parse( attributes, ldif );
223 
224                 Name dn = new LdapName( ( String ) attributes.remove( "dn" ).get() );
225 
226                 dn.remove( 0 );
227 
228                 ctx.createSubcontext( dn, attributes );
229             }
230         }
231         catch ( Exception e )
232         {
233             String msg = "failed while trying to parse system ldif file";
234 
235             NamingException ne = new LdapConfigurationException( msg );
236 
237             ne.setRootCause( e );
238 
239             throw ne;
240         }
241     }
242 }