Created
October 6, 2012 12:54
-
-
Save TonyWhite/3844853 to your computer and use it in GitHub Desktop.
JDaemonFileSync
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * La classe è un demone che effettua la sincronizzazione dei file | |
| * | |
| * @author Antonio Bianco | |
| * creazione: 02/10/2012 | |
| * ultima modifica: 03/10/2012 | |
| */ | |
| import java.io.File; | |
| import java.nio.file.Files; | |
| import static java.nio.file.StandardCopyOption.*; | |
| import static java.lang.Thread.State.*; | |
| import javax.swing.JOptionPane; | |
| public class DaemonFileSync extends Thread | |
| { | |
| // Istanza di variabili | |
| private boolean vivo; | |
| private boolean loop; | |
| /** | |
| * Constructor for objects of class DaemonFileSync | |
| */ | |
| public DaemonFileSync() | |
| { | |
| super(); | |
| this.setDaemon(true); | |
| vivo = true; | |
| loop = true; | |
| } | |
| /** | |
| * Corpo del demone | |
| */ | |
| public void run() | |
| { | |
| while(vivo) | |
| { | |
| while(loop) | |
| { | |
| try | |
| { | |
| Thread.sleep(Opzioni.getAttesa()); | |
| } | |
| catch(Exception e){} | |
| sincronizza(); | |
| } | |
| } | |
| } | |
| /** | |
| * Sincronizza i file | |
| */ | |
| private void sincronizza() | |
| { | |
| // long lastModified() | |
| String descrizioneErrore = ""; | |
| for(int i=0; i<Opzioni.getFileSincronizzati(); i++) | |
| { | |
| //report+=i + " di " + Opzioni.getFileSincronizzati() + "\n"; | |
| descrizioneErrore = ""; | |
| File fileLocale = new File(Opzioni.getFileLocale(i)); | |
| File fileRemoto = new File(Opzioni.getFileRemoto(i)); | |
| boolean localePresente = fileLocale.exists(); | |
| boolean remotoPresente = fileRemoto.exists(); | |
| try | |
| { | |
| if ((localePresente)&&(remotoPresente)) // Esiste sia il file locale che remoto | |
| { | |
| /* | |
| * I file sono accessibili sia in locale che in remoto: | |
| * la sincronizzazione avviene in maniera normale | |
| */ | |
| // I file locali sono più aggiornati dei file remoti? | |
| boolean sincronizzato = false; | |
| if (fileLocale.lastModified()>(fileRemoto.lastModified()+Opzioni.getAttesa())) | |
| { | |
| descrizioneErrore = "Impossibile aggiornare i file remoti."; | |
| Files.copy(fileLocale.toPath(), fileRemoto.toPath(), REPLACE_EXISTING); | |
| sincronizzato = true; | |
| } | |
| else if (fileRemoto.lastModified()>(fileLocale.lastModified()+Opzioni.getAttesa())) | |
| { | |
| descrizioneErrore = "Impossibile aggiornare i file locali."; | |
| Files.copy(fileRemoto.toPath(), fileLocale.toPath(), REPLACE_EXISTING); | |
| sincronizzato = true; | |
| } | |
| if ((sincronizzato)&&(Opzioni.getNotifica(i))) | |
| { | |
| JOptionPane.showMessageDialog(null, "File sincronizzato correttamente:\n" + Opzioni.getFileLocale(i), Global.NOME_APPLICAZIONE, JOptionPane.INFORMATION_MESSAGE); | |
| } | |
| } | |
| else if (localePresente) // Esiste solo il file locale | |
| { | |
| /* | |
| * I file sono accessibili in locale, ma non in remoto: | |
| * prova ad aggiornare i file remoti. | |
| * Se non dovesse funzionare, significa che il percorso remoto è protetto oppure il dispositivo è disconnesso. | |
| */ | |
| descrizioneErrore = "Il percorso remoto è protetto oppure il dispositivo è disconnesso."; | |
| Files.copy(fileLocale.toPath(), fileRemoto.toPath(), REPLACE_EXISTING); | |
| } | |
| else if (remotoPresente) // Esiste solo il file remoto | |
| { | |
| /* | |
| * I file sono accessibili in remoto, ma non in locale: | |
| * prova ad aggiornare i file locali. | |
| * Se non dovesse funzionare, significa che non si hanno sufficienti permessi | |
| */ | |
| descrizioneErrore = "Non si hanno sufficienti permessi per scrivere i file in locale."; | |
| Files.copy(fileRemoto.toPath(), fileLocale.toPath(), REPLACE_EXISTING); | |
| } | |
| else // Non esiste il locale e nemmeno il remoto | |
| { | |
| // Non fare niente | |
| } | |
| } | |
| catch(Exception e) | |
| { | |
| System.out.println("WARNING! " + descrizioneErrore); | |
| } | |
| } | |
| } | |
| /** | |
| * Ferma definitivamente il thread. | |
| */ | |
| public void ferma() | |
| { | |
| loop = false; | |
| vivo = false; | |
| while(true) | |
| { | |
| if (getState().equals(Thread.State.valueOf("TERMINATED"))) | |
| { | |
| try | |
| { | |
| Thread.sleep(100); | |
| break; | |
| } | |
| catch(Exception e){} | |
| } | |
| } | |
| } | |
| /** | |
| * Mette in pausa il thread | |
| */ | |
| public void pausa() | |
| { | |
| loop = !loop; // Inverte il valore di una variabile booleana | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * La classe Global memorizza le variabili globali dell'applicazione. | |
| * | |
| * @author Antonio Bianco | |
| * @version 02/10/2012 | |
| */ | |
| import java.io.File; | |
| import java.net.URI; | |
| public class Global | |
| { | |
| // Istanzadi variabili | |
| private static String absolutePath = null; | |
| public static final String NOME_APPLICAZIONE = "JDaemonFileSync"; | |
| /** | |
| * Constructor for objects of class Global | |
| */ | |
| public Global() | |
| { | |
| // initialise instance variables | |
| } | |
| /** | |
| * Ritorna il percorso assoluto dell'applicazione. | |
| * Se il file jar si trova in ~/Documenti/Programma/Applicazione.jar | |
| * Il metodo restituisce ~/Documenti/Programma/ | |
| * Mantengo lo slash finale per favorire la concatenazione di altri nomi di file o cartelle. | |
| */ | |
| public static String getAbsolutePath() | |
| { | |
| if (absolutePath == null) | |
| { | |
| String path = Global.class.getProtectionDomain().getCodeSource().getLocation().getPath(); | |
| if (path != null) | |
| { | |
| File fileJar = new File(path); | |
| String nomeJar = fileJar.getName(); | |
| String percorsoAssoluto = fileJar.getAbsolutePath(); | |
| if (!fileJar.isDirectory()) | |
| { | |
| // Al percorso bisogna togliere il nome dell'eseguibile JAR | |
| percorsoAssoluto = percorsoAssoluto.substring(0, percorsoAssoluto.length()-nomeJar.length()); | |
| } | |
| if (!percorsoAssoluto.endsWith(System.getProperty("file.separator"))) // Finisce con un separatore di sistema? | |
| { | |
| // No: si aggiunge | |
| percorsoAssoluto+=System.getProperty("file.separator"); | |
| } | |
| //absolutePath = URI.create(percorsoAssoluto).getPath(); // Sostituisce i caratteri come %20 con i relativi ASCII, ma ho bug su Windows: mi riservo di correggerlo il prima possibile.. | |
| percorsoAssoluto = percorsoAssoluto.replace("%20", " "); // Nel frattempo uso questo. | |
| absolutePath = percorsoAssoluto; | |
| } | |
| } | |
| return absolutePath; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * La classe JDaemonFileSync avvia il demone | |
| * | |
| * @author Antonio Bianco | |
| * creazione: 02/10/2012 | |
| * ultima modifica: 03/10/2012 | |
| */ | |
| import java.io.File; | |
| import java.io.FileReader; | |
| import java.io.FileWriter; | |
| import java.io.BufferedReader; | |
| import java.io.PrintWriter; | |
| import java.lang.Process; | |
| import java.lang.Runtime; | |
| import java.net.URL; | |
| import javax.swing.JOptionPane; | |
| import javax.swing.UIManager; | |
| import javax.swing.UIManager.LookAndFeelInfo; | |
| public class JDaemonFileSync | |
| { | |
| private static ThreadProcessoChiuso threadProcesso = null; | |
| private static DaemonFileSync demone = null; | |
| private static File opzioni; | |
| private static final String nomeFileOpzioni = Global.getAbsolutePath()+"opzioni.txt"; | |
| /** | |
| * Metodo di avvio | |
| */ | |
| public static void main(String args[]) | |
| { | |
| setTema(); | |
| // Il file opzioni deve esistere | |
| boolean errore = false; | |
| String descrizioneErrore = ""; | |
| opzioni = new File(nomeFileOpzioni); | |
| if (opzioni.exists()) | |
| { | |
| //JOptionPane.showMessageDialog(null, "Il file " + nomeFileOpzioni + " esiste.", nomeApplicazione, JOptionPane.INFORMATION_MESSAGE); | |
| try | |
| { | |
| descrizioneErrore = "Impossibile creare lo stream di comunicazione"; | |
| FileReader streamOpzioni = new FileReader(opzioni); | |
| descrizioneErrore = "Impossibile accedere al buffer di lettura"; | |
| BufferedReader bufferOpzioni = new BufferedReader(streamOpzioni); | |
| try | |
| { | |
| descrizioneErrore = "Il file è vuoto"; | |
| String bufAttesa = bufferOpzioni.readLine(); | |
| if (bufAttesa==null) Integer.parseInt("Forza errore"); // Metodo casareccio ma funzionante | |
| descrizioneErrore = "Il file è corrotto: il primo campo non è un numero valido"; | |
| long attesa = Long.parseLong(bufAttesa); | |
| Opzioni.setAttesa(attesa); | |
| descrizioneErrore = "Il file è corrotto"; | |
| String bufComando = bufferOpzioni.readLine(); | |
| if (bufComando==null) Integer.parseInt("Forza errore"); // Metodo casareccio ma funzionante | |
| Opzioni.setComando(bufComando); | |
| descrizioneErrore = "Il file non contiene la lista di sincronizzazione"; | |
| String bufLocale = bufferOpzioni.readLine(); | |
| while(bufLocale!=null) // Esegue il ciclo solo se bufLocale non è null | |
| { | |
| // bufLocale contiene il nome del file locale | |
| // bufRemoto contiene il nome del file remoto | |
| // bufNotifica contiene il valore true o false per le notifica sui file | |
| String bufRemoto = bufferOpzioni.readLine(); | |
| descrizioneErrore = "La lista dei file da sincronizzare è corrotta"; | |
| if (bufRemoto==null) Integer.parseInt("Forza errore"); // Metodo casareccio ma funzionante | |
| String bufNotifica = bufferOpzioni.readLine(); | |
| descrizioneErrore = "La lista dei file da sincronizzare è corrotta"; | |
| boolean notifica = true; | |
| if (bufNotifica.equals("true")) | |
| { | |
| notifica = true; | |
| } | |
| else if (bufNotifica.equals("false")) | |
| { | |
| notifica = false; | |
| } | |
| else | |
| { | |
| Integer.parseInt("Forza errore"); // Metodo casareccio ma funzionante | |
| } | |
| Opzioni.addFile(bufLocale, bufRemoto, notifica); | |
| // Prova a leggere la riga seguente per ripetere il ciclo | |
| bufLocale = bufferOpzioni.readLine(); | |
| } | |
| // Genera un errore se la lista dei file da sincronizzare è vuota | |
| descrizioneErrore = "Non esistono file da sincronizzare"; | |
| if (Opzioni.getFileSincronizzati()==0) Integer.parseInt("Forza errore"); // Metodo casareccio ma funzionante | |
| } | |
| catch(Exception exc) | |
| { | |
| errore = true; | |
| JOptionPane.showMessageDialog(null, "ERRORE:\n" + descrizioneErrore, Global.NOME_APPLICAZIONE, JOptionPane.ERROR_MESSAGE); | |
| } | |
| descrizioneErrore = "Impossibile chiudere il buffer di lettura del file"; | |
| bufferOpzioni.close(); | |
| descrizioneErrore = "Impossibile chiudere lo stream di comunicazione del file"; | |
| streamOpzioni.close(); | |
| descrizioneErrore = ""; | |
| //DEBUG//JOptionPane.showMessageDialog(null, "File chiuso correttamente", nomeApplicazione, JOptionPane.INFORMATION_MESSAGE); | |
| } | |
| catch(Exception e) | |
| { | |
| errore = true; | |
| JOptionPane.showMessageDialog(null, "ERRORE:\n" + descrizioneErrore, Global.NOME_APPLICAZIONE, JOptionPane.ERROR_MESSAGE); | |
| } | |
| if (errore) | |
| { | |
| JOptionPane.showMessageDialog(null, "Il programma si chiuderà a causa di un errore", Global.NOME_APPLICAZIONE, JOptionPane.ERROR_MESSAGE); | |
| System.exit(1); | |
| } | |
| else | |
| { | |
| // Controlla se i file da sincronizzare sono accessibili | |
| if (!Opzioni.getAccessibilita()) | |
| { | |
| int scelta = JOptionPane.showConfirmDialog(null,"ERRORE:\nI file da sincronizzare non sono accessibili,\ni contatti non saranno sincronizzati.\n\nVuoi avviare comunque l'applicazione?", Global.NOME_APPLICAZIONE, JOptionPane.YES_NO_OPTION); | |
| if (scelta!=JOptionPane.YES_OPTION) | |
| { | |
| System.exit(1); | |
| } | |
| } | |
| // LIBERO!!!!!!!!!!!! | |
| } | |
| } | |
| else | |
| { | |
| // Avvia la finestra di configurazione | |
| JOptionPane.showMessageDialog(null, "Il file " + nomeFileOpzioni + " non esiste.\nCrea il file di configurazione.", Global.NOME_APPLICAZIONE, JOptionPane.WARNING_MESSAGE); | |
| System.exit(0); | |
| } | |
| // Avvia il comando | |
| try | |
| { | |
| descrizioneErrore = "Impossibile avviare il comando\n" + Opzioni.getComando(); | |
| Process processo = Runtime.getRuntime().exec(Opzioni.getComando()); | |
| descrizioneErrore = "Impossibile creare il monitor per il processo"; | |
| threadProcesso = new ThreadProcessoChiuso(processo); | |
| descrizioneErrore = "Impossibile monitorare il processo avviato"; | |
| threadProcesso.start(); | |
| } | |
| catch(Exception e) | |
| { | |
| JOptionPane.showMessageDialog(null, "ERRORE:\n" + descrizioneErrore, Global.NOME_APPLICAZIONE, JOptionPane.ERROR_MESSAGE); | |
| System.exit(1); | |
| } | |
| // Avvia il demone | |
| demone = new DaemonFileSync(); | |
| demone.start(); | |
| } | |
| /** | |
| * Esce dal programma fermando correttamente i thread | |
| */ | |
| public static void esci() | |
| { | |
| demone.ferma(); | |
| JOptionPane.showMessageDialog(null, "Sincronizzazione terminata.", Global.NOME_APPLICAZIONE, JOptionPane.INFORMATION_MESSAGE); | |
| System.exit(0); | |
| } | |
| /** | |
| * Carica il tema predefinito. | |
| */ | |
| private static void setTema() | |
| { | |
| try | |
| { | |
| String classeTemaPredefinito = UIManager.getSystemLookAndFeelClassName(); | |
| UIManager.setLookAndFeel(classeTemaPredefinito); | |
| // Correggi il FileChooser se il tema è GTK+ | |
| if ("GTK look and feel".equals(UIManager.getLookAndFeel().getName())) UIManager.put("FileChooserUI", "eu.kostia.gtkjfilechooser.ui.GtkFileChooserUI"); | |
| } | |
| catch(Exception e) | |
| { | |
| System.err.println(e.getMessage()); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * La classe Opzioni mantiene le informazioni sulle opzioni del programma. | |
| * | |
| * @author Antonio Bianco | |
| * creazione: 02/10/2012 | |
| * ultima modifica: 03/10/2012 | |
| */ | |
| import java.io.File; | |
| import java.util.Vector; | |
| public class Opzioni | |
| { | |
| // Istanza di variabili | |
| private static long attesa = 1000; | |
| private static String comando = ""; | |
| private static Vector<String> fileLocali = new Vector<String>(); // File locali | |
| private static Vector<String> fileRemoti = new Vector<String>(); // File remoti | |
| private static Vector<Boolean> notifiche = new Vector<Boolean>(); // Notifiche | |
| /** | |
| * Constructor for objects of class Opzioni | |
| */ | |
| public Opzioni() | |
| { | |
| // Inizializzazione delle variabili | |
| } | |
| /** | |
| * Aggiunge il file da sincronizzare | |
| */ | |
| public static void addFile(String fileLocale, String fileRemoto, boolean notifica) | |
| { | |
| fileLocali.add(fileLocale); | |
| fileRemoti.add(fileRemoto); | |
| notifiche.add(notifica); | |
| } | |
| /** | |
| * Ritorna il tempo di attesa | |
| */ | |
| public static long getAttesa() | |
| { | |
| return attesa; | |
| } | |
| /** | |
| * Ritorna il comando da avviare | |
| */ | |
| public static String getComando() | |
| { | |
| return comando; | |
| } | |
| /** | |
| * Ritorna il file locale all'indice i della lista | |
| */ | |
| public static String getFileLocale(int i) | |
| { | |
| return fileLocali.get(i); | |
| } | |
| /** | |
| * Ritorna il file remoto all'indice i della lista | |
| */ | |
| public static String getFileRemoto(int i) | |
| { | |
| return fileRemoti.get(i); | |
| } | |
| /** | |
| * Ritorna true se al file dell'indice i è associata una notifica | |
| */ | |
| public static boolean getNotifica(int i) | |
| { | |
| return notifiche.get(i); | |
| } | |
| /** | |
| * Ritorna il numero di file impegnati nella sincronizzazione | |
| */ | |
| public static int getFileSincronizzati() | |
| { | |
| return fileLocali.size(); | |
| } | |
| /** | |
| * Imposta il tempo di attesa in millisecondi tra una scansione e l'altra | |
| */ | |
| public static void setAttesa(long attesa) | |
| { | |
| Opzioni.attesa = attesa; | |
| } | |
| /** | |
| * Imposta il comando da avviare | |
| */ | |
| public static void setComando(String comando) | |
| { | |
| Opzioni.comando = comando; | |
| } | |
| /** | |
| * Ritorna true se tutti i file sono accessibili | |
| */ | |
| public static boolean getAccessibilita() | |
| { | |
| for(int i=0; i<fileLocali.size(); i++) | |
| { | |
| if ((!new File(fileLocali.get(i)).exists())||(!new File(fileRemoti.get(i)).exists())) | |
| { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * La classe chiude il programma quando il comando esterno viene terminato. | |
| * | |
| * @author Antonio Bianco | |
| * creazione: 03/10/2012 | |
| * ultima modifica: 03/10/2012 | |
| */ | |
| import java.lang.Process; | |
| public class ThreadProcessoChiuso extends Thread | |
| { | |
| // Istanza di variabili | |
| private Process processo; | |
| /** | |
| * Costruttore di oggetti della classe ThreadProcessoChiuso | |
| */ | |
| public ThreadProcessoChiuso(Process processo) | |
| { | |
| // Inizializza l'istanza di variabili | |
| this.processo = processo; | |
| } | |
| /** | |
| * Corpo del thread | |
| */ | |
| public void run() | |
| { | |
| try | |
| { | |
| processo.waitFor(); | |
| } | |
| catch(Exception e){} | |
| JDaemonFileSync.esci(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment