View Javadoc

1   /**
2    * Copyright 2008 WebPhotos
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.webphotos.gui.util;
17  
18  import java.awt.*;
19  import java.awt.event.*;
20  import java.io.*;
21  import javax.swing.*;
22  import net.sf.webphotos.BancoImagem;
23  import net.sf.webphotos.sync.FTP.SyncAdapter;
24  import net.sf.webphotos.sync.Sync;
25  import net.sf.webphotos.sync.SyncEvent;
26  import net.sf.webphotos.sync.SyncException;
27  import net.sf.webphotos.util.ApplicationContextResource;
28  import net.sf.webphotos.util.Util;
29  import net.sf.webphotos.util.legacy.Arquivo;
30  import net.sf.webphotos.util.legacy.Modal;
31  import org.apache.commons.net.ftp.FTPFile;
32  import org.apache.commons.net.io.CopyStreamAdapter;
33  import org.apache.commons.net.io.CopyStreamException;
34  import org.apache.log4j.Logger;
35  
36  /**
37   * Cliente FTP. Cria uma interface para trabalhar com os comandos de FTP.
38   * Implementa a classe Runnable, indica o uso de FtpClient por meio de thread.
39   */
40  public class FtpClient extends JFrame implements Runnable {
41  
42      private static final int ONE_SECOND = 1000;
43      private static final Logger log = Logger.getLogger(FtpClient.class);
44      private String ftpRoot = Util.getProperty("FTPRoot");
45      private static File albunsRoot = Util.getAlbunsRoot();
46      private Container cp;
47      private JScrollPane scrTabela;
48      private JTable tabela;
49      private JTextArea txtLog = new JTextArea();
50      private JScrollPane scrLog = new JScrollPane(txtLog);
51      private JProgressBar barra = new JProgressBar(0, 100);
52      private JProgressBar barraArquivoAtual = new JProgressBar(0, 100);
53      private JLabel lblServidor = new JLabel();
54      private JLabel lblArquivos = new JLabel("", JLabel.RIGHT);
55      private JLabel lblKbytes = new JLabel("0 Kb");
56      private JLabel lblKbytesArquivoAtual = new JLabel("0 Kb");
57      private JButton btFechar = new JButton("fechar");
58      private FTPTabelModel modeloTabela;
59      private Modal modal;
60      private Sync ftp;
61      private int reply;
62      private int retry;
63      private String usuario;
64      private String ftpHost;
65      private int ftpPort;
66      private char[] senha;
67      private long totalBytes = 0;
68      private long transmitido = 0;
69      private FTPFile remoteFiles[] = null;
70      private FTPFile remoteFile = null;
71      // devemos enviar para internet os originais ?
72      private boolean enviarAltaResolucao;
73  
74      /**
75       * Construtor da classe. Prepara a interface de sincronização. Configura o
76       * sistema de sincronização e confere o valor de enviarAltaResolução para
77       * enviar originais ou não. Seta os valores dos listeners de sincronização
78       * implementando os métodos da interface Sync.
79       */
80      public FtpClient() {
81          cp = getContentPane();
82          /**
83           * Preparando a interface de sincronização
84           */
85          retry = 3;
86          try {
87              //TODO: transformar este acesso em parâmetro do sistema
88              ftp = (Sync) ApplicationContextResource.getBean("syncObject");
89              /**
90               * Configuração do sistema de sincronização
91               */
92              ftp.setSyncFolder(ftpRoot);
93              enviarAltaResolucao = ftp.isEnviarAltaResolucao();
94              ftp.loadSyncCache();
95          } catch (Exception ex) {
96              Util.log("[FtpClient.run]/ERRO: Inexperado.");
97              log.error(ex);
98              System.exit(1);
99          }
100 
101         // ajusta o valor de enviarAltaResolucao
102         if (enviarAltaResolucao == false) {
103             this.setTitle("Transmissão FTP - Sem Enviar Originais");
104         } else {
105             this.setTitle("Transmissão FTP - Enviando Originais");
106         }
107         txtLog.setFont(new Font("courier", Font.PLAIN, 11));
108         Util.setLoggingTextArea(txtLog);
109         cp.setLayout(null);
110 
111         cp.add(lblArquivos);
112         lblArquivos.setBounds(348, 3, 60, 18);
113 
114         cp.add(lblServidor);
115         lblServidor.setBounds(8, 3, 340, 18);
116 
117         txtLog.setWrapStyleWord(true);
118         txtLog.setLineWrap(true);
119         cp.add(scrLog);
120         scrLog.setBounds(8, 127, 400, 70);
121 
122         modeloTabela = new FTPTabelModel(ftp.getListaArquivos());
123         tabela = new JTable(modeloTabela);
124 
125         cp.add(tabela);
126         scrTabela = new JScrollPane(tabela);
127         cp.add(scrTabela);
128         scrTabela.setBounds(8, 20, 400, 100);
129         cp.validate();
130 
131         // barraArquivoAtual, kbytes, botao
132         cp.add(barraArquivoAtual);
133         barraArquivoAtual.setStringPainted(true);
134         barraArquivoAtual.setBounds(8, 235, 234, 18);
135         barraArquivoAtual.setToolTipText("Progresso do arquivo atual");
136 
137         cp.add(lblKbytesArquivoAtual);
138         lblKbytesArquivoAtual.setBounds(246, 235, 58, 18);
139 
140         // barra, kbytes, botao
141         cp.add(barra);
142         barra.setStringPainted(true);
143         barra.setBounds(8, 205, 234, 18);
144         barra.setToolTipText("Progresso total");
145 
146         cp.add(lblKbytes);
147         lblKbytes.setBounds(246, 205, 58, 18);
148 
149         cp.add(btFechar);
150         btFechar.setBounds(308, 204, 100, 20);
151         btFechar.setEnabled(false);
152 
153         this.setSize(420, 300);
154         this.setResizable(false);
155         this.setLocationRelativeTo(null);
156         this.setDefaultCloseOperation(FtpClient.DO_NOTHING_ON_CLOSE);
157         this.getContentPane().repaint();
158         this.setVisible(true);
159 
160         modal = new Modal(this);
161         this.addWindowFocusListener(modal);
162 
163         // ouvinte para o botão fechar
164         btFechar.addMouseListener(new MouseAdapter() {
165             @Override
166             public void mouseClicked(MouseEvent e) {
167                 exit();
168             }
169         });
170 
171         // ouvinte para o fechamento convencional do JFrame
172         // TODO: trocar o if para checagem de parâmetro
173         if (1 == 2) {
174             addWindowListener(new java.awt.event.WindowAdapter() {
175                 @Override
176                 public void windowClosing(java.awt.event.WindowEvent evt) {
177                     exit();
178                 }
179             });
180         }
181 
182         ftp.setSyncListener(new SyncAdapter() {
183             @Override
184             public void connected(SyncEvent e) {
185                 lblServidor.setText(ftpHost + ":" + ftpPort + " / usuário: " + usuario);
186             }
187 
188             @Override
189             public void logonStarted(SyncEvent event) {
190                 // Autenticacao	
191                 if (!event.isRetrying()) {
192                     if (BancoImagem.getBancoImagem().getUserFTP() != null) {
193                         // Vamos tentar conectar com a senha própria de FTP
194                         usuario = BancoImagem.getBancoImagem().getUserFTP();
195                         senha = BancoImagem.getBancoImagem().getPasswordFTP();
196                     } else if (BancoImagem.getBancoImagem().getUser() != null) {
197                         // Ou o mesmo usuário/senha do banco de dados
198                         usuario = BancoImagem.getBancoImagem().getUser();
199                         senha = BancoImagem.getBancoImagem().getPassword();
200                     } else {
201                         showLogonDialog();
202                     }
203                 } else {
204                     showLogonDialog();
205                 }
206                 ftp.setUsuario(usuario);
207                 ftp.setSenha(senha);
208             }
209 
210             @Override
211             public void disconnected(SyncEvent e) {
212                 //TODO: repensar esse comando
213                 //Util.setLoggingTextArea(PainelWebFotos.getTxtLog());
214                 btFechar.setEnabled(true);
215             }
216 
217             private void showLogonDialog() {
218                 // Ou requisitamos do usuário
219                 Login l = new Login("FTP " + ftpHost);
220                 removeWindowFocusListener(modal);
221                 l.show();
222                 addWindowFocusListener(modal);
223                 usuario = l.getUser();
224                 senha = l.getPassword();
225             }
226         });
227 
228         ftp.setCopyStreamListener(new CopyStreamAdapter() {
229             @Override
230             public void bytesTransferred(long totalBytesTransferred,
231                     int bytesTransferred,
232                     long streamSize) {
233                 barraArquivoAtual.setValue((int) totalBytesTransferred);
234                 lblKbytesArquivoAtual.setText(Math.round((float) totalBytesTransferred / 1024) + " Kb");
235             }
236         });
237     }
238 
239     private void exit() {
240         //TODO: repensar esse comando
241         //Util.setLoggingTextArea(PainelWebFotos.getTxtLog());
242         dispose();
243     }
244 
245     /**
246      * Executa o comando FTP. Utiliza o método
247      * {@link net.sf.webphotos.sync.Sync#loadSyncCache() loadSyncCache}() para
248      * fazer o load do arquivos com os comandos de FTP. Checa se existem
249      * comandos a executar, caso positivo, tenta a conexão com FTP e executa os
250      * comandos (UPLOAD, DELETE ou DOWNLOAD).
251      */
252     @Override
253     public void run() {
254 
255         String acao;
256         String albumID;
257         String arquivo;
258         long tamanho;
259 
260         String arqOrigem;
261         String arqDestino;
262 
263         Object streamOrigem = null;
264         Object streamDestino = null;
265 
266         String ultimoID = "";
267         int i, j = 0;
268 
269         String diretorioDownload = null;
270         // loadSyncCache arquivo
271         ftp.loadSyncCache();
272         modeloTabela.refresh(ftp.getListaArquivos());
273         modeloTabela.fireTableDataChanged();
274 
275         // tem algum comando à executar ?
276         if (tabela.getRowCount() == 0) {
277             ftp.disconnect("Não há comandos ftp");
278             return;
279         }
280 
281         // tenta a conexao com FTP
282         if (!ftp.connect()) {
283             return;
284         }
285         preProcessBatch();
286         modeloTabela.refresh(ftp.getListaArquivos());
287         modeloTabela.fireTableDataChanged();
288         barra.setMaximum(Integer.parseInt(Long.toString(totalBytes)));
289 
290         // executa os comandos
291         for (i = 0; i < tabela.getRowCount(); i++) {
292 
293             lblArquivos.setText(i + 1 + " / " + tabela.getRowCount());
294             tabela.setRowSelectionInterval(i, i);
295             tabela.scrollRectToVisible(tabela.getCellRect(i + 1, 0, true));
296             tabela.repaint();
297             acao = tabela.getValueAt(i, 1).toString();
298             albumID = tabela.getValueAt(i, 2).toString();
299             arquivo = tabela.getValueAt(i, 4).toString();
300 
301             // ajusta o diretório para /ftpRoot/albumID
302             // recebe a lista de arquivos 
303             if (!ultimoID.equals(albumID)) {
304                 Util.log("Mudando para o diretório " + albumID);
305                 try {
306                     ftp.cd(albumID);
307                     remoteFiles = ftp.listFiles();
308                     diretorioDownload = null;
309                 } catch (IOException ioE) {
310                     Util.log("[FtpClient.run]/ERRO: comando não foi aceito ao listar o diretório " + albumID + " desconectando");
311                     ftp.disconnect("não foi possivel entrar no diretorio");
312                 } catch (SyncException se) {
313                     Util.log(se.getMessage());
314                     ftp.disconnect("não foi possivel entrar no diretorio");
315                 }
316             }
317 
318             // UPLOAD
319             if (acao.equals("enviar")) {
320                 if (diretorioDownload == null) {
321                     diretorioDownload = albunsRoot.getAbsolutePath() + File.separator + albumID;
322                 }
323                 arqOrigem = diretorioDownload + File.separator + arquivo;
324                 Util.out.println(arqOrigem + " -> " + arquivo);
325                 try {
326                     streamOrigem = new FileInputStream(arqOrigem);
327                     streamDestino = new BufferedOutputStream(ftp.storeFileStream(arquivo), ftp.getBufferSize());
328                     this.transfereArquivo((InputStream) streamOrigem, (OutputStream) streamDestino, Long.parseLong(tabela.getValueAt(i, 5).toString()));
329                     tabela.setValueAt("ok", i, 0);
330                 } catch (FileNotFoundException ioE) {
331                     Util.log("[FtpClient.run]/AVISO: " + arqOrigem + " não foi encontrado.");
332                     tabela.setValueAt("ok - ne", i, 0);
333                 } catch (IOException ioE) {
334                     Util.log("[FtpClient.run]/ERRO: erro na transmissão de " + arqOrigem);
335                     ioE.printStackTrace(Util.out);
336                     tabela.setValueAt("erro", i, 0);
337                 } catch (Exception e) {
338                     Util.err.println("Erro inexperado: " + e.getMessage());
339                     e.printStackTrace(Util.out);
340                     tabela.setValueAt("erro", i, 0);
341                 } finally {
342                     try {
343                         ftp.printWorkingDirectory();
344                     } catch (IOException e) {
345                     }
346                     try {
347                         ((OutputStream) streamDestino).close();
348                         ((InputStream) streamOrigem).close();
349                     } catch (Exception e) {
350                     }
351                 }
352                 posTransfer(i);
353 
354                 // DELETE
355             } else if (acao.equals("apagar")) {
356 
357                 // apaga o diretorio inteiro
358                 if (arquivo.equals("* todos")) {
359                     try {
360                         for (FTPFile remote : remoteFiles) {
361                             ftp.deleteFile(remote.getName());
362                             Util.log("Removendo arquivo remoto " + remote.getName());
363                             transmitido += remote.getSize();
364                             Util.out.println("Processado " + transmitido + " de " + totalBytes);
365                             barra.setValue((int) transmitido);
366                             lblKbytes.setText(Math.round((float) transmitido / 1024) + " Kb");
367                         }
368 
369                         // Volta para o diretório principal
370                         ftp.changeWorkingDirectory(ftpRoot);
371                         // finalmente remove o diretorio
372                         ftp.removeDirectory(albumID);
373                         tabela.setValueAt("ok", i, 0);
374 
375                     } catch (Exception e) {
376                         tabela.setValueAt("erro", i, 0);
377                         log.error(e);
378                     }
379                     // apaga somente uma foto
380                 } else {
381                     for (FTPFile remote : remoteFiles) {
382                         if (remote.getName().equals(arquivo)) {
383                             remoteFile = remote;
384                             break;
385                         }
386                     }
387                     //remoteFile=RemoteFile.findRemoteFile(remoteFiles,arquivo);
388                     if (remoteFile == null) {
389                         tabela.setValueAt("ok - ne", i, 0);
390                     } else {
391                         tabela.setValueAt(Long.toString(remoteFile.getSize()), i, 5);
392                         try {
393                             ftp.deleteFile(arquivo);
394                             tabela.setValueAt("ok", i, 0);
395 
396                             posTransfer(i);
397                         } catch (Exception e) {
398                             tabela.setValueAt("erro", i, 0);
399                         }
400                     }
401                 }
402 
403                 // DOWNLOAD - recebe os arquivos (pré listado e calculado)
404             } else if (acao.equals("receber")) {
405                 try {
406                     // cada vez que muda o diretório, a variável diretórioDownload é nula
407                     if (diretorioDownload == null) {
408                         diretorioDownload = albunsRoot.getAbsolutePath() + File.separator + albumID;
409                         File temp = new File(diretorioDownload);
410 
411                         if (!temp.isDirectory()) {
412                             temp.mkdir();
413                             Util.log("Criando diretório " + diretorioDownload);
414                         }
415                         temp = null;
416                     }
417                     arqDestino = diretorioDownload + File.separator + arquivo;
418                     Util.out.println(arquivo + " -> " + arqDestino);
419 
420                     streamOrigem =
421                             new BufferedInputStream(
422                             ftp.retrieveFileStream(arquivo),
423                             ftp.getBufferSize());
424 
425                     streamDestino =
426                             new FileOutputStream(arqDestino);
427 
428                     this.transfereArquivo((InputStream) streamOrigem, (OutputStream) streamDestino, Long.parseLong(tabela.getValueAt(i, 5).toString()));
429                     tabela.setValueAt("ok", i, 0);
430 
431                     // calcula porcentagem e atualiza barra
432                     posTransfer(i);
433 
434                 } catch (IOException ioE) {
435                     Util.err.println("Erro de transmissão: " + ioE.getMessage() + " "
436                             + ((CopyStreamException) ioE).getIOException().getMessage());
437                     tabela.setValueAt("erro", i, 0);
438                     log.error(ioE);
439                 } catch (Exception e) {
440                     Util.err.println("Erro: ");
441                     log.error(e);
442                     tabela.setValueAt("erro", i, 0);
443                 } finally {
444                     try {
445                         ftp.printWorkingDirectory();
446                     } catch (IOException e) {
447                     }
448                     try {
449                         ((InputStream) streamOrigem).close();
450                         ((OutputStream) streamDestino).close();
451                     } catch (IOException e) {
452                     }
453                 }
454             }// fim if
455 
456             ultimoID = albumID;
457         } // fim for
458         ftp.disconnect("transmissão terminada");
459     }
460 
461     private void preProcessBatch() {
462         String acao;
463         Arquivo tmpArq;
464         int i, j = 0;
465 
466         // calcula quantidade de bytes a transmitir (upload e download somente)
467         for (i = 0; i < tabela.getRowCount(); i++) {
468             acao = tabela.getValueAt(i, 1).toString();
469             if (acao.equals("enviar")) {
470                 totalBytes += Long.parseLong(tabela.getValueAt(i, 5).toString());
471             }
472             if (acao.equals("receber")) {
473                 Util.log("Calculando bytes a serem recebidos (álbum " + tabela.getValueAt(i, 2) + ")");
474                 tmpArq = (Arquivo) ftp.getListaArquivos().get(i);
475 
476                 if (tmpArq.getNomeArquivo().equals("* todos")) {
477                     // Baixando todo o Álbum
478                     try {
479                         Util.out.println("Convertendo: " + tmpArq.getAlbumID());
480                         // remove o ítem atual e diminui 
481                         // o marcador após a remoção
482                         ftp.getListaArquivos().remove(i--);
483                         ftp.cd(Integer.toString(tmpArq.getAlbumID()));
484                         remoteFiles = ftp.listFiles();
485                         for (FTPFile remote : remoteFiles) {
486                             ftp.getListaArquivos().add(
487                                     new Arquivo(tmpArq.getLinhaComando(), 2,
488                                     tmpArq.getAlbumID(), tmpArq.getFotoID(), remote.getName(),
489                                     remote.getSize()));
490                             totalBytes += remote.getSize();
491                         } // fim for
492                     } catch (SyncException se) {
493                         Util.log(se.getMessage());
494                         ftp.disconnect("não foi possivel entrar no diretorio");
495                     } catch (Exception e) {
496                         log.error(e);
497                     }
498                 } else {
499                     // Baixando um arquivo
500                     try {
501                         ftp.cd(Integer.toString(tmpArq.getAlbumID()));
502                         remoteFiles = this.ftp.listFiles();
503                         for (FTPFile remote : remoteFiles) {
504                             if (tmpArq.getNomeArquivo().equals(remote.getName())) {
505                                 totalBytes += remote.getSize();
506                                 tmpArq.setTamanho(remote.getSize());
507                                 break;
508                             }
509                         } // fim for
510                     } catch (SyncException se) {
511                         Util.log(se.getMessage());
512                         ftp.disconnect("não foi possivel entrar no diretorio");
513                     } catch (Exception e) {
514                         log.error(e);
515                     }
516                 }
517             }
518             if (acao.equals("apagar")) {
519                 Util.log("Calculando bytes a serem apagados (álbum " + tabela.getValueAt(i, 2) + ")");
520                 tmpArq = (Arquivo) ftp.getListaArquivos().get(i);
521                 if (tmpArq.getNomeArquivo().equals("* todos")) {
522                     // Apagando todo o Álbum
523                     try {
524                         Util.out.println("Convertendo: " + tmpArq.getAlbumID());
525                         ftp.cd(Integer.toString(tmpArq.getAlbumID()));
526                         remoteFiles = this.ftp.listFiles();
527                         for (FTPFile remote : remoteFiles) {
528                             totalBytes += remote.getSize();
529                         }
530                     } catch (SyncException se) {
531                         Util.log(se.getMessage());
532                         ftp.disconnect("não foi possivel entrar no diretorio");
533                     } catch (Exception e) {
534                         log.error(e);
535                     }
536                 } else {
537                     // Apagando um arquivo
538                     try {
539                         ftp.cd(Integer.toString(tmpArq.getAlbumID()));
540                         remoteFiles = this.ftp.listFiles();
541                         for (FTPFile remote : remoteFiles) {
542                             if (tmpArq.getNomeArquivo().equals(remote.getName())) {
543                                 totalBytes += remote.getSize();
544                                 tmpArq.setTamanho(remote.getSize());
545                                 break;
546                             }
547                         }
548                     } catch (SyncException se) {
549                         Util.log(se.getMessage());
550                         ftp.disconnect("não foi possivel entrar no diretorio");
551                     } catch (Exception e) {
552                         log.error(e);
553                     }
554                 }
555             }
556         }
557     }
558 
559     private void posTransfer(final int i) throws NumberFormatException {
560         transmitido += Long.parseLong(tabela.getValueAt(i, 5).toString());
561         Util.out.println("Processado " + transmitido + " de " + totalBytes);
562         barra.setValue((int) transmitido);
563         lblKbytes.setText(Math.round((float) transmitido / 1024) + " Kb");
564     }
565 
566     private void transfereArquivo(InputStream streamOrigem, OutputStream streamDestino, long streamSize)
567             throws CopyStreamException,
568             IOException {
569 
570         barraArquivoAtual.setValue(0);
571         barraArquivoAtual.setMaximum((int) streamSize);
572         lblKbytesArquivoAtual.setText("0 Kb");
573 
574         try {
575             ftp.transferFile(streamOrigem, streamDestino, streamSize);
576         } catch (IOException e) {
577             try {
578                 streamOrigem.close();
579                 streamDestino.close();
580             } catch (IOException f) {
581             }
582             throw e;
583         }
584 
585     }
586 }