blob: 921c0553028d9509350a1447127a772d0e839173 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.syncrepl;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.partition.Partition;
import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
import org.apache.directory.server.core.partition.ldif.LdifPartition;
import org.apache.directory.server.core.schema.SchemaPartition;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
import org.apache.directory.server.ldap.handlers.extended.StoredProcedureExtendedOperationHandler;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
import org.apache.directory.server.xdbm.Index;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.filter.SearchScope;
import org.apache.directory.shared.ldap.name.DN;
import org.apache.directory.shared.ldap.schema.SchemaManager;
import org.apache.directory.shared.ldap.schema.ldif.extractor.SchemaLdifExtractor;
import org.apache.directory.shared.ldap.schema.ldif.extractor.impl.DefaultSchemaLdifExtractor;
import org.apache.directory.shared.ldap.schema.loader.ldif.LdifSchemaLoader;
import org.apache.directory.shared.ldap.schema.manager.impl.DefaultSchemaManager;
import org.apache.directory.shared.ldap.schema.registries.SchemaLoader;
import org.apache.directory.shared.ldap.util.ExceptionUtils;
import org.apache.mina.util.AvailablePortFinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* A simple swing UI to start stop syncrepl consumer.
* This class avoids the costly operation of setting up config
* and directory service between start/stop of consumer.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class SyncreplRunnerUI implements ActionListener
{
private SyncreplConfiguration config;
private SyncReplConsumer agent = new SyncReplConsumer();
private File workDir;
private DirectoryService dirService;
private LdapServer ldapServer;
private static final Logger LOG = LoggerFactory.getLogger( SyncreplRunnerUI.class );
// UI components
private JButton btnStart;
private JButton btnStop;
private JButton btnCleanStart;
private EntryInjector entryInjector;
// private String provServerHost = "192.168.22.105";
// private int provServerPort = 389;
// private String provServerBindDn = "cn=Manager,dc=example,dc=com";
private String provServerHost = "localhost";
private int provServerPort = 10389;
private String provServerBindDn = "uid=admin,ou=system";
private String provServerPwd = "secret";
private boolean connected;
public SyncreplRunnerUI()
{
config = new SyncreplConfiguration();
config.setProviderHost( provServerHost );
config.setPort( provServerPort );
config.setReplUserDn( provServerBindDn );
config.setReplUserPassword( provServerPwd );
config.setBaseDn( "dc=example,dc=com" );
config.setFilter( "(objectclass=*)" );
config.setAttributes( new String[]{ "*", "ref", "entryUUID", "entryCSN" } );
config.setSearchScope( SearchScope.SUBTREE );
config.setReplicaId( 1 );
config.setRefreshPersist( true );
config.setRefreshInterval( 60 * 1000 );
agent.setConfig( config );
workDir = new File( "/Users/kayyagari/Desktop/syncrepl-work" );//new File( System.getProperty( "java.io.tmpdir" ) + "/syncrepl-work" );
}
public void start()
{
try
{
if ( !workDir.exists() )
{
workDir.mkdirs();
}
startEmbeddedServer( workDir );
agent.init( dirService );
agent.connect();
connected = true;
agent.prepareSyncSearchRequest();
agent.startSync();
}
catch ( Exception e )
{
LOG.error( "Failed to start the embedded server & syncrepl consumer", e );
throw new RuntimeException( e );
}
}
public void stop()
{
try
{
LOG.info( "stopping the embedded server" );
if ( connected )
{
agent.disconnet();
}
if ( ( dirService != null ) && dirService.isStarted() )
{
dirService.shutdown();
ldapServer.stop();
}
}
catch ( Exception e )
{
LOG.error( "Failed to stop", e );
}
connected = false;
}
public void cleanStart()
{
try
{
if ( workDir.exists() )
{
FileUtils.forceDelete( workDir );
}
}
catch ( Exception e )
{
LOG.error( "Failed to delete the work directory", e );
}
agent.deleteCookieFile();
start();
}
private void startEmbeddedServer( File workDir )
{
try
{
dirService = new DefaultDirectoryService();
dirService.setShutdownHookEnabled( false );
dirService.setWorkingDirectory( workDir );
int consumerPort = AvailablePortFinder.getNextAvailable( 1024 );
initSchema( dirService );
initSystemPartition( dirService );
ldapServer = new LdapServer();
ldapServer.setTransports( new TcpTransport( consumerPort ) );
ldapServer.setDirectoryService( dirService );
DN suffix = new DN( config.getBaseDn() );
JdbmPartition partition = new JdbmPartition();
partition.setSuffix( suffix.getName() );
partition.setId( "syncrepl" );
partition.setPartitionDir( new File( workDir, partition.getId() ) );
partition.setSyncOnWrite( true );
partition.setSchemaManager( dirService.getSchemaManager() );
// Add objectClass attribute for the system partition
Set<Index<?, Entry, Long>> indexedAttrs = new HashSet<Index<?, Entry, Long>>();
indexedAttrs.add( new JdbmIndex<Object, Entry>( SchemaConstants.ENTRY_UUID_AT ) );
( ( JdbmPartition ) partition ).setIndexedAttributes( indexedAttrs );
partition.initialize();
dirService.addPartition( partition );
dirService.startup();
ldapServer.addExtendedOperationHandler( new StartTlsHandler() );
ldapServer.addExtendedOperationHandler( new StoredProcedureExtendedOperationHandler() );
ldapServer.start();
}
catch ( Exception e )
{
e.printStackTrace();
}
}
public void show() throws Exception
{
btnStart = new JButton( "Start" );
btnStart.setMnemonic( 'S' );
btnStart.addActionListener( this );
btnCleanStart = new JButton( "Clean Start" );
btnCleanStart.setMnemonic( 'R' );
btnCleanStart.addActionListener( this );
btnStop = new JButton( "Stop" );
btnStop.setMnemonic( 'O' );
btnStop.setEnabled( false );
btnStop.addActionListener( this );
JPanel serverPanel = new JPanel();
serverPanel.add( btnStart );
serverPanel.add( btnStop );
serverPanel.add( btnCleanStart );
serverPanel.setBorder( new TitledBorder( "Server Controls" ) );
entryInjector = new EntryInjector( provServerHost, provServerPort, provServerBindDn, provServerPwd );
entryInjector.setBorder( new TitledBorder( "Entry Injector" ) );
entryInjector.setConfig( config );
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setTitle( "Syncrepl consumer UI" );
frame.getContentPane().add( serverPanel, BorderLayout.NORTH );
frame.getContentPane().add( entryInjector, BorderLayout.SOUTH );
frame.addWindowListener( new WindowAdapter()
{
@Override
public void windowClosed( WindowEvent e )
{
stop();
}
} );
frame.pack();
frame.setVisible( true );
}
public void actionPerformed( ActionEvent e )
{
Object src = e.getSource();
if ( src == btnStart )
{
btnStart.setEnabled( false );
btnCleanStart.setEnabled( false );
Runnable startTask = new Runnable()
{
public void run()
{
start();
}
};
new Thread( startTask ).start();
btnStop.setEnabled( true );
}
else if ( src == btnStop )
{
btnStop.setEnabled( false );
Runnable stopTask = new Runnable()
{
public void run()
{
stop();
}
};
new Thread( stopTask ).start();
btnStart.setEnabled( true );
btnCleanStart.setEnabled( true );
}
else if ( src == btnCleanStart )
{
btnCleanStart.setEnabled( false );
btnStart.setEnabled( false );
Runnable cleanStartTask = new Runnable()
{
public void run()
{
cleanStart();
}
};
new Thread( cleanStartTask ).start();
btnStop.setEnabled( true );
}
}
private void initSchema( DirectoryService service ) throws Exception
{
SchemaPartition schemaPartition = service.getSchemaService().getSchemaPartition();
// Init the LdifPartition
LdifPartition ldifPartition = new LdifPartition();
String workingDirectory = service.getWorkingDirectory().getPath();
ldifPartition.setWorkingDirectory( workingDirectory + "/schema" );
// Extract the schema on disk (a brand new one) and load the registries
File schemaRepository = new File( workingDirectory, "schema" );
SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
extractor.extractOrCopy( true );
schemaPartition.setWrappedPartition( ldifPartition );
SchemaLoader loader = new LdifSchemaLoader( schemaRepository );
SchemaManager schemaManager = new DefaultSchemaManager( loader );
service.setSchemaManager( schemaManager );
// We have to load the schema now, otherwise we won't be able
// to initialize the Partitions, as we won't be able to parse
// and normalize their suffix DN
schemaManager.loadAllEnabled();
schemaPartition.setSchemaManager( schemaManager );
List<Throwable> errors = schemaManager.getErrors();
if ( errors.size() != 0 )
{
throw new Exception( "Schema load failed : " + ExceptionUtils.printErrors( errors ) );
}
}
private void initSystemPartition( DirectoryService service ) throws Exception
{
// change the working directory to something that is unique
// on the system and somewhere either under target directory
// or somewhere in a temp area of the machine.
// Inject the System Partition
Partition systemPartition = new JdbmPartition();
systemPartition.setId( "system" );
( ( JdbmPartition ) systemPartition ).setCacheSize( 500 );
systemPartition.setSuffix( ServerDNConstants.SYSTEM_DN );
systemPartition.setSchemaManager( service.getSchemaManager() );
( ( JdbmPartition ) systemPartition ).setPartitionDir( new File( service.getWorkingDirectory(), "system" ) );
// Add objectClass attribute for the system partition
Set<Index<?, Entry, Long>> indexedAttrs = new HashSet<Index<?, Entry, Long>>();
indexedAttrs.add( new JdbmIndex<Object, Entry>( SchemaConstants.OBJECT_CLASS_AT ) );
( ( JdbmPartition ) systemPartition ).setIndexedAttributes( indexedAttrs );
service.setSystemPartition( systemPartition );
}
public static void main( String[] args )
{
final SyncreplRunnerUI runnerUi = new SyncreplRunnerUI();
try
{
runnerUi.show();
}
catch ( Exception e )
{
e.printStackTrace();
JOptionPane.showMessageDialog( null, e.getMessage(), "Failed to start Syncrepl test UI",
JOptionPane.ERROR_MESSAGE );
System.exit( 1 );
}
}
}