1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  
21  package org.apache.directory.mitosis.service;
22  
23  import org.apache.commons.io.FileUtils;
24  import org.apache.directory.mitosis.common.Replica;
25  import org.apache.directory.mitosis.configuration.ReplicationConfiguration;
26  import org.apache.directory.server.constants.ServerDNConstants;
27  import org.apache.directory.server.core.DefaultDirectoryService;
28  import org.apache.directory.server.core.DirectoryService;
29  import org.apache.directory.server.core.interceptor.Interceptor;
30  import org.apache.directory.server.core.jndi.CoreContextFactory;
31  import org.apache.directory.server.core.jndi.ServerLdapContext;
32  import org.apache.directory.shared.ldap.name.LdapDN;
33  import org.apache.mina.util.AvailablePortFinder;
34  import org.junit.After;
35  import org.junit.Before;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  import javax.naming.Context;
40  import javax.naming.ldap.LdapContext;
41  import java.io.File;
42  import java.net.InetSocketAddress;
43  import java.util.HashMap;
44  import java.util.Hashtable;
45  import java.util.Iterator;
46  import java.util.List;
47  import java.util.Map;
48  import java.util.Random;
49  
50  
51  /**
52   * An abstract base class for replication tests.
53   *
54   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
55   * @version $Rev$, $Date$
56   */
57  public abstract class AbstractReplicationServiceTestCase
58  {
59      private static final Logger LOG = LoggerFactory.getLogger( AbstractReplicationServiceTestCase.class );
60      protected Map<String, LdapContext> contexts = new HashMap<String, LdapContext>();
61      protected Map<String, DirectoryService> services = new HashMap<String, DirectoryService>();
62      protected Map<String, ReplicationInterceptor> replicationServices = new HashMap<String, ReplicationInterceptor>();
63  
64  
65      @Before public void setUp() throws Exception
66      {
67          createReplicas( new String[] { "A", "B", "C" } );
68      }
69  
70  
71      @After public void tearDown() throws Exception
72      {
73          destroyAllReplicas();
74      }
75  
76  
77      protected void createReplicas( String[] names ) throws Exception
78      {
79          int lastAvailablePort = 1024;
80  
81          Replica[] replicas = new Replica[ names.length ];
82          
83          for( int i = 0; i < names.length; i++ )
84          {
85              int replicationPort = AvailablePortFinder.getNextAvailable( lastAvailablePort );
86              lastAvailablePort = replicationPort + 1;
87  
88              replicas[ i ] = new Replica( names[ i ],
89                      new InetSocketAddress( "127.0.0.1", replicationPort ) );
90          }
91  
92          Random random = new Random();
93          String homeDirectory = System.getProperty( "java.io.tmpdir" )
94                  + File.separator + "mitosis-"
95                  + Long.toHexString( random.nextLong() );
96  
97          for ( Replica replica : replicas )
98          {
99              String replicaId = replica.getId();
100             DirectoryService service = new DefaultDirectoryService();
101             service.setInstanceId( replicaId );
102             File workDir = new File( homeDirectory + File.separator + service.getInstanceId() );
103             service.setShutdownHookEnabled( false );
104             service.setWorkingDirectory( workDir );
105 
106             List<Interceptor> interceptors = service.getInterceptors();
107 
108             ReplicationConfiguration replicationCfg = new ReplicationConfiguration();
109             replicationCfg.setReplicaId( replica.getId() );
110             // Disable automatic replication to prevent unexpected behavior
111             replicationCfg.setReplicationInterval( 0 );
112             replicationCfg.setServerPort( replica.getAddress().getPort() );
113 
114             for ( Replica replica1 : replicas )
115             {
116                 if ( replica1 != replica )
117                 {
118                     replicationCfg.addPeerReplica( replica1 );
119                 }
120             }
121 
122             ReplicationInterceptor replicationInterceptor = new ReplicationInterceptor();
123             replicationInterceptor.setConfiguration( replicationCfg );
124             interceptors.add( replicationInterceptor );
125 
126             service.setInterceptors( interceptors );
127 
128             if ( workDir.exists() )
129             {
130                 FileUtils.deleteDirectory( workDir );
131             }
132 
133             service.startup();
134             
135 //            LdapDN dn = new LdapDN()
136 //            ServerEntry entry = service.newEntry( dn )
137 //            service.getPartitionNexus().add( new AddOperationContext( service.getAdminSession(), entry ) );
138 //            
139             
140             Hashtable<String,Object> env = new Hashtable<String,Object>();
141             env.put( DirectoryService.JNDI_KEY, service );
142             env.put( Context.SECURITY_PRINCIPAL, ServerDNConstants.ADMIN_SYSTEM_DN );
143             env.put( Context.SECURITY_CREDENTIALS, "secret" );
144             env.put( Context.SECURITY_AUTHENTICATION, "simple" );
145             env.put( Context.PROVIDER_URL, "" );
146             env.put( Context.INITIAL_CONTEXT_FACTORY, CoreContextFactory.class.getName() );
147 
148             // Initialize the server instance.
149             LdapContext context = new ServerLdapContext( service, service.getAdminSession(), new LdapDN() );
150             contexts.put( replicaId, context );
151             services.put( replicaId, service );
152             replicationServices.put( replicaId, replicationInterceptor );
153         }
154 
155         // Ensure all replicas have had a chance to connect to each other since the last one started.
156         for ( ReplicationInterceptor replicationInterceptor : replicationServices.values() )
157         {
158             replicationInterceptor.interruptConnectors();
159         }
160         Thread.sleep( 5000 );
161     }
162 
163 
164     protected LdapContext getReplicaContext( String name ) throws Exception
165     {
166         LdapContext context = contexts.get( name );
167         if( context == null )
168         {
169             throw new IllegalArgumentException( "No such replica: " + name );
170         }
171 
172         return ( LdapContext ) context.lookup( "" );
173     }
174 
175 
176     @SuppressWarnings("unchecked")
177     protected void destroyAllReplicas() throws Exception
178     {
179         for( Iterator<DirectoryService> i = services.values().iterator(); i.hasNext(); )
180         {
181             DirectoryService replica = i.next();
182             File workDir = replica.getWorkingDirectory();
183 
184             try
185             {
186                 replica.shutdown();
187             }
188             catch( Exception e )
189             {
190                 LOG.error( "Encountered error while shutting down replica {}", replica.getInstanceId(), e );
191                 throw e;
192             }
193 
194             try
195             {
196                 FileUtils.deleteDirectory( workDir );
197             }
198             catch( Exception e )
199             {
200                 e.printStackTrace();
201             }
202 
203             workDir.getParentFile().delete();
204 
205             i.remove();
206         }
207     }
208 }