import java.io.*;

import java.net.*;

 

class serverRegistrazioniFTP extends Thread

{

  private static String LogFile="Registrazioni.log";

  private Socket connessione;

  ListaFile serverReg=new ListaFile();

  int PORTA_DATI=1189;

 

  public serverRegistrazioniFTP(Socket in,ListaFile ll)

  {

     connessione=in;

     serverReg=ll;

  }

 

  public void run()

  {

     String lista_temp[]=new String[60];

     InetAddress server_remoto;

     BufferedReader comandiIn;

    PrintWriter comandiOut;

    String messaggio=new String();

    FileWriter scrittoreLog;

    

     try

     {

       scrittoreLog=new FileWriter(LogFile,true);

       server_remoto=connessione.getInetAddress();

       System.out.println("Connessione stabilita con "+server_remoto);

       scrittoreLog.write("Connessione stabilita con "+server_remoto+"\r\n");

       scrittoreLog.flush();

       ObjectOutputStream oos=new ObjectOutputStream(connessione.getOutputStream());

       ObjectInputStream ois=new ObjectInputStream(connessione.getInputStream());

       messaggio=(String) ois.readObject();  

       if(messaggio.equals("registrazione"))

       {

          synchronized(connessione)

          {

          synchronized(serverReg)

       {

          try

          {

            //leggo la lista dal server che si vuole registrare

            lista_temp=(String[]) ois.readObject();

            //preparo la struttura dati (lista file + lista server attivi)

            int num_server;

           

            for(num_server=0;num_server<serverReg.lista_server.length;num_server++)

            {

              if(serverReg.lista_server[num_server]==null)

              {

                 serverReg.lista_server[num_server]=new String(server_remoto.getHostName());

                 serverReg.lista_file_server[num_server]=lista_temp;

                 oos.writeObject("registrazione OK");

                 oos.flush();

                 System.out.println("Registrazione");

                 System.out.println("server numero: "+(num_server+1));

                 System.out.println("nome del server: "+serverReg.lista_server[num_server]);

                 scrittoreLog.write("Registrazione del server numero: "+(num_server+1)+"\r\n");

                 scrittoreLog.write("Nome del server: "+serverReg.lista_server[num_server]+"\r\n");

                 scrittoreLog.flush();

                 break;

              }

              if(serverReg.lista_server[num_server].equals(server_remoto.getHostName()))

              {

                 System.out.println("il server e\' gia registrato");

                 break;

              }

            }//for

            //invio al server che si registra la sua struttura dati

            oos.writeObject(serverReg);

          oos.flush();

            oos.close();

            //inviare le strutture agli altri server: "ListaFile"

            for(int i=0;i<serverReg.lista_server.length;i++)

            {

              if(serverReg.lista_server[i]==null)

              {

                 break;

              }

              if(!serverReg.lista_server[i].equals(server_remoto.getHostName()))

              {

                 new Thread(new aggiornaFTP(serverReg.lista_server[i],serverReg)).start();

              }

            }

         

            System.out.println("Fine aggiornamento dei server registrati");

            scrittoreLog.write("Fine aggiornamento dei server registrati\r\n");

            scrittoreLog.flush();

          }

          catch(Exception e)

          {

            System.out.println("ERRORE durante l\' aggiornamento dei server dopo una registrazione");

            System.out.println(e);

          }

          }//synchro

          }//synchro

       }

       else if(messaggio.startsWith("aggiornamento"))

       {

          synchronized(connessione)

          {

          synchronized(serverReg)

          {

          try

          {

            boolean registrato=false;

            //legge la struttura dei file

            lista_temp=(String[]) ois.readObject();

            //aggiorna la lista del server in comunicazione

            for(int i=0;i<serverReg.lista_server.length;i++)

            {

              if(serverReg.lista_server[i]==null)break;

              if(serverReg.lista_server[i].equals(server_remoto.getHostName()))

            {

                 serverReg.lista_file_server[i]=lista_temp;

                 serverReg.lista_file_server[i][lista_temp.length-1]=null;

                 System.out.println("Aggiornamento");

                 System.out.println("Server: "+server_remoto);

                 oos.writeObject("aggiornamento OK");

                 oos.flush();

                 //il server si registra da solo la sua struttura dati

                 oos.close();

                 scrittoreLog.write("Aggiornamento effettuato dal server: "+server_remoto+"\r\n");

                 registrato=true;

                 break;

              }

            }//for

          

            //caso server non registrato

            if(!registrato)

            {

              oos.writeObject("server non registrato ancora");

              oos.flush();

              //richiesta registrazione

              try

              {

                Socket sock_dati=new Socket(server_remoto.getHostName(),PORTA_DATI);

                 ObjectOutputStream oos2=new ObjectOutputStream(sock_dati.getOutputStream());

                 ObjectInputStream ois2=new ObjectInputStream(sock_dati.getInputStream());  

                 oos2.writeObject("richiesta registrazione");

                 oos2.flush();

                 messaggio=(String)ois2.readObject();

                 if(messaggio.equals("effetuo la registrazione"))

                 {

                   lista_temp=(String[])ois2.readObject();

                   int num_server;

                   for(num_server=0;num_server<serverReg.lista_server.length;num_server++)

                  {

                   if(serverReg.lista_server[num_server]==null)

                   {

                     serverReg.lista_server[num_server]=new String(server_remoto.getHostName());

                     serverReg.lista_file_server[num_server]=lista_temp;

                     oos.writeObject("registrazione OK");

                     oos.flush();

                     System.out.println("Registrazione");

                     System.out.println("server numero: "+(num_server+1));

                     System.out.println("nome del server: "+serverReg.lista_server[num_server]);

                     scrittoreLog.write("Registrazione del server numero: "+(num_server+1)+"\r\n");

                     scrittoreLog.write("Nome del server: "+serverReg.lista_server[num_server]+"\r\n");

                     scrittoreLog.flush();

                     break;

                    }

                    if(serverReg.lista_server[num_server].equals(server_remoto.getHostName()))

                    {

                      System.out.println("il server e\' gia registrato");

                      break;

                    }

                   }//for

               //invio la struttura dati al server che si registra

                   oos2.writeObject(serverReg);

                   oos2.flush();

                 }

                 ois2.close();

                 oos2.close();

              }

              catch(Exception ex)

              {

                 System.out.println("registrazione di "+server_remoto.getHostName()+" non effettuata");

              }

            }

           

            //inviare le strutture agli altri server: "ListaFile"

           for(int i=0;i<serverReg.lista_server.length;i++)

            {

              if(serverReg.lista_server[i]==null)

                 {

                   break;

                 }

              if(!serverReg.lista_server[i].equals(server_remoto.getHostName()))

              {

                 new Thread(new aggiornaFTP(serverReg.lista_server[i],serverReg)).start();

              }

            }//for

         

            System.out.println("Fine aggiornamento dei server registrati");

            scrittoreLog.write("Fine aggiornamneto dei server registrati\r\n");

            scrittoreLog.flush();

    }

   

       catch(Exception e)

       {

          System.out.println("ERRORE durante l\' aggiornamento dei server dopo una modifica ad una lista");

          System.out.println(e);

       }

       }//synchro

       }//synchro

     }

     else if(messaggio.startsWith("informazione"))

     {

       //gestisce il caso di un server che si accorge che un altro server non è più disponibile

       synchronized(connessione)

       {

       synchronized(serverReg)

       {

       try

       {

          String server_caduto=new String();

          ListaFile temp=new ListaFile();

          temp.cancella();

          boolean aggiornamento_necessario=false;

          boolean trovato=false;

          server_caduto=(String) ois.readObject();

          oos.writeObject("ricevuta informazione");

          oos.flush();

          oos.close();

          //verifico se il server è ancora nella lista

          for(int ii=0;ii<serverReg.lista_server.length;ii++)

          {

            if(serverReg.lista_server[ii]==null)break;

            if(serverReg.lista_server[ii].equals(server_caduto))

            {

              trovato=true;

              break;

            }

          }

          if(trovato)

          {

          System.out.println("il server "+server_caduto+" non e\' piu\' disponibile");                               

          System.out.println("cancello il server "+server_caduto+" dalla lista");      

          scrittoreLog.write("il server "+server_caduto+" non e\' piu\' disponibile\r\n");         

          scrittoreLog.write("cancello il server "+server_caduto+" dalla lista\r\n");

         

          for(int h=0,k=0;h<serverReg.lista_server.length;h++)

          {

             if(serverReg.lista_server[h]==null)

              {

                 if(h>0)aggiornamento_necessario=true;

                 break;

              }

            if(!(serverReg.lista_server[h].equals(server_caduto)))

               {

                temp.lista_server[k]=new String(serverReg.lista_server[h]);

                for(int g=0;g<serverReg.lista_file_server[h].length;g++)

                {

                   if(serverReg.lista_file_server[h][g]==null)break;

                   temp.lista_file_server[k][g]=new String(serverReg.lista_file_server[h][g]);

                }

                k++;

               }

            }                      

        //aggiorno la struttura serverReg

        serverReg.cancella();

        serverReg.copia(temp);

       

                

          for(int cont=0;((cont<serverReg.lista_server.length)&&(aggiornamento_necessario));cont++)

          {

           if(serverReg.lista_server[cont]==null)

           {

             if(cont!=0)

             {

              System.out.println("Fine aggiornamento dei server registrati");

              scrittoreLog.write("Fine aggiornamento dei server registrati\r\n");

              scrittoreLog.flush();

             }

            aggiornamento_necessario=false;

             break;

           }

           else

           {

            try

            {

              new Thread(new aggiornaFTP(serverReg.lista_server[cont],serverReg)).start();

            }

            catch(Exception ex)

            {

               System.out.println("Errore durante l\' aggiornamento dei server");

               System.out.println(ex);

            }

           }//else

          }

          }//if(trovato)

       }

       catch(Exception e)

       {

          System.out.println("ERRORE durante la cancellazione di un server per una informazione");

          System.out.println(e);

       }

       }//synchro

       }//synchro

     }

     }

     catch(Exception e)

     {

       System.out.println("Errore duarnte l\' avvio del server per la registrazioni");

       System.out.println(e);

       System.exit(1);

     }

  }

 

 

}