o added a new UI component to inject entries into the provider 
o modified syncrepl test ui to include entry injector
o formatted the syncrepl test ui code
o updated the syncrepl test ui main method to handle errors while connecting to provider


git-svn-id: https://svn.apache.org/repos/asf/directory/apacheds/branches/apacheds-replication@773251 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/syncrepl/src/main/java/org/apache/directory/server/syncrepl/EntryInjector.java b/syncrepl/src/main/java/org/apache/directory/server/syncrepl/EntryInjector.java
new file mode 100644
index 0000000..08b6022
--- /dev/null
+++ b/syncrepl/src/main/java/org/apache/directory/server/syncrepl/EntryInjector.java
@@ -0,0 +1,223 @@
+/*
+ *  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.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.swing.JButton;
+import javax.swing.JPanel;
+
+import org.apache.directory.shared.ldap.client.api.LdapConnection;
+import org.apache.directory.shared.ldap.entry.client.DefaultClientEntry;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 
+ * A utitlity class to inject entries into the syncrepl provider server.
+ *
+ * TODO add a feature to purge entries
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class EntryInjector extends JPanel implements ActionListener
+{
+    private JButton btnAdd;
+    private JButton btnPause;
+    private JButton btnKeepAdding;
+
+    private RunnerThread runner = new RunnerThread();
+
+    private LdapConnection connection;
+
+    private static final Logger LOG = LoggerFactory.getLogger( EntryInjector.class );
+
+
+    public EntryInjector( String host, int port, String bindDn, String pwd ) throws Exception
+    {
+        connection = new LdapConnection( host, port );
+        connection.bind( bindDn, pwd );
+
+        addcomponents();
+    }
+
+
+    public void addEntry()
+    {
+
+        try
+        {
+            String cn = "entry-" + System.currentTimeMillis();
+            LdapDN dn = new LdapDN( "cn=" + cn + ",dc=test,dc=nodomain" );
+            DefaultClientEntry entry = new DefaultClientEntry();
+            entry.add( "objectclass", "inetOrgPerson", "organizationalPerson", "person" );
+            entry.add( "cn", cn );
+            entry.add( "sn", cn );
+            entry.setDn( dn );
+
+            LOG.debug( "adding entry with dn: {}" + dn );
+            connection.add( entry );
+        }
+        catch ( Exception e )
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+    public void close()
+    {
+        try
+        {
+            runner.stopThread();
+            connection.unBind();
+        }
+        catch ( Exception e )
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+    private void addcomponents()
+    {
+        btnAdd = new JButton( "Add" );
+        btnAdd.addActionListener( this );
+        add( btnAdd );
+
+        btnPause = new JButton( "Pause" );
+        btnPause.addActionListener( this );
+        btnPause.setEnabled( false );
+        add( btnPause );
+
+        btnKeepAdding = new JButton( "Keep Adding" );
+        btnKeepAdding.addActionListener( this );
+        add( btnKeepAdding );
+    }
+
+
+    public void actionPerformed( ActionEvent e )
+    {
+        Object src = e.getSource();
+
+        if ( src == btnAdd )
+        {
+            addEntry();
+        }
+        else if ( src == btnPause )
+        {
+            runner.pause( true );
+            btnPause.setEnabled( false );
+            btnKeepAdding.setEnabled( true );
+        }
+        else if ( src == btnKeepAdding )
+        {
+            if ( !runner.isRunning() )
+            {
+                runner.start();
+            }
+            else
+            {
+                runner.pause( false );
+            }
+            btnPause.setEnabled( true );
+            btnKeepAdding.setEnabled( false );
+        }
+    }
+
+    class RunnerThread extends Thread
+    {
+        private boolean stop = false;
+        private boolean running;
+
+        private Semaphore mutex = new Semaphore( 1 );
+
+
+        @Override
+        public void run()
+        {
+            running = true;
+
+            while ( !stop )
+            {
+                try
+                {
+                    mutex.acquire();
+                    addEntry();
+                    mutex.release();
+
+                    Thread.sleep( 10000 );
+                }
+                catch ( Exception e )
+                {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+
+        public boolean isRunning()
+        {
+            return running;
+        }
+
+
+        public void pause( boolean pause )
+        {
+            try
+            {
+                if ( pause )
+                {
+                    mutex.acquire();
+                }
+                else
+                {
+                    mutex.release();
+                }
+            }
+            catch ( Exception e )
+            {
+                e.printStackTrace();
+            }
+        }
+
+
+        public void stopThread()
+        {
+            stop = true;
+        }
+
+    }
+
+
+    public void enable( boolean enable )
+    {
+        btnAdd.setEnabled( enable );
+        btnKeepAdding.setEnabled( enable );
+    }
+
+}
diff --git a/syncrepl/src/main/java/org/apache/directory/server/syncrepl/SyncreplRunnerUI.java b/syncrepl/src/main/java/org/apache/directory/server/syncrepl/SyncreplRunnerUI.java
index 72433f6..9cee826 100644
--- a/syncrepl/src/main/java/org/apache/directory/server/syncrepl/SyncreplRunnerUI.java
+++ b/syncrepl/src/main/java/org/apache/directory/server/syncrepl/SyncreplRunnerUI.java
@@ -19,6 +19,8 @@
  */
 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;
@@ -27,8 +29,10 @@
 
 import javax.swing.JButton;
 import javax.swing.JFrame;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.SwingUtilities;
+import javax.swing.border.TitledBorder;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.directory.server.core.DefaultDirectoryService;
@@ -44,6 +48,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  * 
  *  A simple swing UI to start stop syncrepl consumer.
@@ -56,24 +61,34 @@
 public class SyncreplRunnerUI implements ActionListener
 {
     private SyncreplConfiguration config;
-    
+
     private SyncReplConsumer agent = new SyncReplConsumer();
-    
+
     private File workDir;
-    
+
     private DirectoryService dirService;
-    
+
     private LdapService ldapService;
-    
+
     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 = "localhost";
+    private int provServerPort = 389;
+    private String provServerBindDn = "cn=admin,dc=nodomain";
+    private String provServerPwd = "secret";
+
+    private boolean connected;
+
+
     public SyncreplRunnerUI()
     {
         config = new SyncreplConfiguration();
@@ -86,58 +101,74 @@
         config.setSearchScope( SearchScope.SUBTREE.getJndiScope() );
         config.setReplicaId( 1 );
         agent.setConfig( config );
-        
+
         workDir = new File( System.getProperty( "java.io.tmpdir" ) + "/work" );
     }
 
-    
+
     public void start()
     {
         try
         {
-            if ( ! workDir.exists() )
+            if ( !workDir.exists() )
             {
                 workDir.mkdirs();
             }
-            
+
             dirService = startEmbeddedServer( workDir );
-            
             agent.init( dirService );
             agent.bind();
+
+            entryInjector.enable( true );
+
+            connected = true;
             agent.prepareSyncSearchRequest();
             agent.startSync();
         }
-        catch( Exception e )
+        catch ( Exception e )
         {
             LOG.error( "Failed to start the embedded server & syncrepl consumer", e );
             throw new RuntimeException( e );
         }
     }
 
+
     public void stop()
     {
         try
         {
-            agent.disconnet();
-            dirService.shutdown();
-            ldapService.stop();
+            LOG.info( "stopping the embedded server" );
+
+            if ( connected )
+            {
+                entryInjector.enable( false );
+                agent.disconnet();
+            }
+
+            if ( ( dirService != null ) && dirService.isStarted() )
+            {
+                dirService.shutdown();
+                ldapService.stop();
+            }
+
         }
-        catch( Exception e )
+        catch ( Exception e )
         {
             LOG.error( "Failed to stop", e );
         }
     }
-    
+
+
     public void cleanStart()
     {
         try
         {
-            if( workDir.exists() )
+            if ( workDir.exists() )
             {
                 FileUtils.forceDelete( workDir );
             }
         }
-        catch( Exception e )
+        catch ( Exception e )
         {
             LOG.error( "Failed to delete the work directory", e );
         }
@@ -145,8 +176,8 @@
         agent.deleteCookieFile();
         start();
     }
-    
-    
+
+
     private DirectoryService startEmbeddedServer( File workDir )
     {
         try
@@ -180,36 +211,43 @@
         {
             e.printStackTrace();
         }
-        
+
         return null;
     }
 
-    public void show()
+
+    public void show() throws Exception
     {
-        JFrame frame = new JFrame();
-        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
-        frame.setTitle( "Syncrepl consumer UI" );
-        
+
         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 panel = new JPanel();
-        panel.add( btnStart );
-        panel.add( btnStop );
-        panel.add( btnCleanStart );
-        
-        frame.getContentPane().add( panel );
+
+        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.enable( false );
+        entryInjector.setBorder( new TitledBorder( "Entry Injector" ) );
+
+        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
@@ -217,7 +255,7 @@
             {
                 stop();
             }
-        });
+        } );
 
         frame.pack();
         frame.setVisible( true );
@@ -227,8 +265,8 @@
     public void actionPerformed( ActionEvent e )
     {
         Object src = e.getSource();
-        
-        if( src == btnStart )
+
+        if ( src == btnStart )
         {
             btnStart.setEnabled( false );
             btnCleanStart.setEnabled( false );
@@ -241,7 +279,7 @@
             } );
             btnStop.setEnabled( true );
         }
-        else if( src == btnStop )
+        else if ( src == btnStop )
         {
             btnStop.setEnabled( false );
             SwingUtilities.invokeLater( new Runnable()
@@ -255,7 +293,7 @@
             btnStart.setEnabled( true );
             btnCleanStart.setEnabled( true );
         }
-        else if( src == btnCleanStart )
+        else if ( src == btnCleanStart )
         {
             btnCleanStart.setEnabled( false );
             btnStart.setEnabled( false );
@@ -275,6 +313,17 @@
     public static void main( String[] args )
     {
         SyncreplRunnerUI runnerUi = new SyncreplRunnerUI();
-        runnerUi.show();
+        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 );
+        }
     }
 }