Java tutorial
/** * Copyright 2008 WebPhotos * * Licensed 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 net.sf.webphotos.gui.util; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; import net.sf.webphotos.BancoImagem; import net.sf.webphotos.sync.FTP.SyncAdapter; import net.sf.webphotos.sync.Sync; import net.sf.webphotos.sync.SyncEvent; import net.sf.webphotos.sync.SyncException; import net.sf.webphotos.util.ApplicationContextResource; import net.sf.webphotos.util.Util; import net.sf.webphotos.util.legacy.Arquivo; import net.sf.webphotos.util.legacy.Modal; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.io.CopyStreamAdapter; import org.apache.commons.net.io.CopyStreamException; import org.apache.log4j.Logger; /** * Cliente FTP. Cria uma interface para trabalhar com os comandos de FTP. * Implementa a classe Runnable, indica o uso de FtpClient por meio de thread. */ public class FtpClient extends JFrame implements Runnable { private static final int ONE_SECOND = 1000; private static final Logger log = Logger.getLogger(FtpClient.class); private String ftpRoot = Util.getProperty("FTPRoot"); private static final File albunsRoot = Util.getAlbunsRoot(); private Container cp; private final JScrollPane scrTabela; private final JTable tabela; private JTextArea txtLog = new JTextArea(); private JScrollPane scrLog = new JScrollPane(txtLog); private JProgressBar barra = new JProgressBar(0, 100); private JProgressBar barraArquivoAtual = new JProgressBar(0, 100); private JLabel lblServidor = new JLabel(); private JLabel lblArquivos = new JLabel("", JLabel.RIGHT); private JLabel lblKbytes = new JLabel("0 Kb"); private JLabel lblKbytesArquivoAtual = new JLabel("0 Kb"); private JButton btFechar = new JButton("fechar"); private final FTPTabelModel modeloTabela; private Modal modal; private Sync ftp; private int reply; private int retry; private String usuario; private String ftpHost; private int ftpPort; private char[] senha; private long totalBytes = 0; private long transmitido = 0; private FTPFile remoteFiles[] = null; private FTPFile remoteFile = null; // devemos enviar para internet os originais ? private boolean enviarAltaResolucao; /** * Construtor da classe. Prepara a interface de sincronizao. Configura o * sistema de sincronizao e confere o valor de enviarAltaResoluo para * enviar originais ou no. Seta os valores dos listeners de sincronizao * implementando os mtodos da interface Sync. */ public FtpClient() { cp = getContentPane(); /** * Preparando a interface de sincronizao */ retry = 3; try { //TODO: transformar este acesso em parmetro do sistema ftp = (Sync) ApplicationContextResource.getBean("syncObject"); /** * Configurao do sistema de sincronizao */ ftp.setSyncFolder(ftpRoot); enviarAltaResolucao = ftp.isEnviarAltaResolucao(); ftp.loadSyncCache(); } catch (Exception ex) { Util.log("[FtpClient.run]/ERRO: Inexperado."); log.error(ex); System.exit(1); } // ajusta o valor de enviarAltaResolucao if (enviarAltaResolucao == false) { this.setTitle("Transmisso FTP - Sem Enviar Originais"); } else { this.setTitle("Transmisso FTP - Enviando Originais"); } txtLog.setFont(new Font("courier", Font.PLAIN, 11)); Util.setLoggingTextArea(txtLog); cp.setLayout(null); cp.add(lblArquivos); lblArquivos.setBounds(348, 3, 60, 18); cp.add(lblServidor); lblServidor.setBounds(8, 3, 340, 18); txtLog.setWrapStyleWord(true); txtLog.setLineWrap(true); cp.add(scrLog); scrLog.setBounds(8, 127, 400, 70); modeloTabela = new FTPTabelModel(ftp.getListaArquivos()); tabela = new JTable(modeloTabela); cp.add(tabela); scrTabela = new JScrollPane(tabela); cp.add(scrTabela); scrTabela.setBounds(8, 20, 400, 100); cp.validate(); // barraArquivoAtual, kbytes, botao cp.add(barraArquivoAtual); barraArquivoAtual.setStringPainted(true); barraArquivoAtual.setBounds(8, 235, 234, 18); barraArquivoAtual.setToolTipText("Progresso do arquivo atual"); cp.add(lblKbytesArquivoAtual); lblKbytesArquivoAtual.setBounds(246, 235, 58, 18); // barra, kbytes, botao cp.add(barra); barra.setStringPainted(true); barra.setBounds(8, 205, 234, 18); barra.setToolTipText("Progresso total"); cp.add(lblKbytes); lblKbytes.setBounds(246, 205, 58, 18); cp.add(btFechar); btFechar.setBounds(308, 204, 100, 20); btFechar.setEnabled(false); this.setSize(420, 300); this.setResizable(false); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(FtpClient.DO_NOTHING_ON_CLOSE); this.getContentPane().repaint(); this.setVisible(true); modal = new Modal(this); this.addWindowFocusListener(modal); // ouvinte para o boto fechar btFechar.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { exit(); } }); // ouvinte para o fechamento convencional do JFrame // TODO: trocar o if para checagem de parmetro if (1 == 2) { addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent evt) { exit(); } }); } ftp.setSyncListener(new SyncAdapter() { @Override public void connected(SyncEvent e) { lblServidor.setText(ftpHost + ":" + ftpPort + " / usurio: " + usuario); } @Override public void logonStarted(SyncEvent event) { // Autenticacao if (!event.isRetrying()) { if (BancoImagem.getBancoImagem().getUserFTP() != null) { // Vamos tentar conectar com a senha prpria de FTP usuario = BancoImagem.getBancoImagem().getUserFTP(); senha = BancoImagem.getBancoImagem().getPasswordFTP(); } else if (BancoImagem.getBancoImagem().getUser() != null) { // Ou o mesmo usurio/senha do banco de dados usuario = BancoImagem.getBancoImagem().getUser(); senha = BancoImagem.getBancoImagem().getPassword(); } else { showLogonDialog(); } } else { showLogonDialog(); } ftp.setUsuario(usuario); ftp.setSenha(senha); } @Override public void disconnected(SyncEvent e) { //TODO: repensar esse comando //Util.setLoggingTextArea(PainelWebFotos.getTxtLog()); btFechar.setEnabled(true); } private void showLogonDialog() { // Ou requisitamos do usurio Login l = new Login("FTP " + ftpHost); removeWindowFocusListener(modal); l.show(); addWindowFocusListener(modal); usuario = l.getUser(); senha = l.getPassword(); } }); ftp.setCopyStreamListener(new CopyStreamAdapter() { @Override public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) { barraArquivoAtual.setValue((int) totalBytesTransferred); lblKbytesArquivoAtual.setText(Math.round((float) totalBytesTransferred / 1024) + " Kb"); } }); } private void exit() { //TODO: repensar esse comando //Util.setLoggingTextArea(PainelWebFotos.getTxtLog()); dispose(); } /** * Executa o comando FTP. Utiliza o mtodo * {@link net.sf.webphotos.sync.Sync#loadSyncCache() loadSyncCache}() para * fazer o load do arquivos com os comandos de FTP. Checa se existem * comandos a executar, caso positivo, tenta a conexo com FTP e executa os * comandos (UPLOAD, DELETE ou DOWNLOAD). */ @Override public void run() { String acao; String albumID; String arquivo; long tamanho; String arqOrigem; String arqDestino; Object streamOrigem = null; Object streamDestino = null; String ultimoID = ""; int i, j = 0; String diretorioDownload = null; // loadSyncCache arquivo ftp.loadSyncCache(); modeloTabela.refresh(ftp.getListaArquivos()); modeloTabela.fireTableDataChanged(); // tem algum comando executar ? if (tabela.getRowCount() == 0) { ftp.disconnect("No h comandos ftp"); return; } // tenta a conexao com FTP if (!ftp.connect()) { return; } preProcessBatch(); modeloTabela.refresh(ftp.getListaArquivos()); modeloTabela.fireTableDataChanged(); barra.setMaximum(Integer.parseInt(Long.toString(totalBytes))); // executa os comandos for (i = 0; i < tabela.getRowCount(); i++) { lblArquivos.setText(i + 1 + " / " + tabela.getRowCount()); tabela.setRowSelectionInterval(i, i); tabela.scrollRectToVisible(tabela.getCellRect(i + 1, 0, true)); tabela.repaint(); acao = tabela.getValueAt(i, 1).toString(); albumID = tabela.getValueAt(i, 2).toString(); arquivo = tabela.getValueAt(i, 4).toString(); // ajusta o diretrio para /ftpRoot/albumID // recebe a lista de arquivos if (!ultimoID.equals(albumID)) { Util.log("Mudando para o diretrio " + albumID); try { ftp.cd(albumID); remoteFiles = ftp.listFiles(); diretorioDownload = null; } catch (IOException ioE) { Util.log("[FtpClient.run]/ERRO: comando no foi aceito ao listar o diretrio " + albumID + " desconectando"); ftp.disconnect("no foi possivel entrar no diretorio"); } catch (SyncException se) { Util.log(se.getMessage()); ftp.disconnect("no foi possivel entrar no diretorio"); } } // UPLOAD switch (acao) { case "enviar": if (diretorioDownload == null) { diretorioDownload = albunsRoot.getAbsolutePath() + File.separator + albumID; } arqOrigem = diretorioDownload + File.separator + arquivo; Util.out.println(arqOrigem + " -> " + arquivo); try { streamOrigem = new FileInputStream(arqOrigem); streamDestino = new BufferedOutputStream(ftp.storeFileStream(arquivo), ftp.getBufferSize()); this.transfereArquivo((InputStream) streamOrigem, (OutputStream) streamDestino, Long.parseLong(tabela.getValueAt(i, 5).toString())); tabela.setValueAt("ok", i, 0); } catch (FileNotFoundException ioE) { Util.log("[FtpClient.run]/AVISO: " + arqOrigem + " no foi encontrado."); tabela.setValueAt("ok - ne", i, 0); } catch (IOException ioE) { Util.log("[FtpClient.run]/ERRO: erro na transmisso de " + arqOrigem); ioE.printStackTrace(Util.out); tabela.setValueAt("erro", i, 0); } catch (NumberFormatException e) { Util.err.println("Erro inexperado: " + e.getMessage()); e.printStackTrace(Util.out); tabela.setValueAt("erro", i, 0); } finally { try { ftp.printWorkingDirectory(); } catch (IOException e) { } try { ((OutputStream) streamDestino).close(); ((InputStream) streamOrigem).close(); } catch (Exception e) { } } posTransfer(i); // DELETE break; case "apagar": // apaga o diretorio inteiro if (arquivo.equals("* todos")) { try { for (FTPFile remote : remoteFiles) { ftp.deleteFile(remote.getName()); Util.log("Removendo arquivo remoto " + remote.getName()); transmitido += remote.getSize(); Util.out.println("Processado " + transmitido + " de " + totalBytes); barra.setValue((int) transmitido); lblKbytes.setText(Math.round((float) transmitido / 1024) + " Kb"); } // Volta para o diretrio principal ftp.changeWorkingDirectory(ftpRoot); // finalmente remove o diretorio ftp.removeDirectory(albumID); tabela.setValueAt("ok", i, 0); } catch (Exception e) { tabela.setValueAt("erro", i, 0); log.error(e); } // apaga somente uma foto } else { for (FTPFile remote : remoteFiles) { if (remote.getName().equals(arquivo)) { remoteFile = remote; break; } } //remoteFile=RemoteFile.findRemoteFile(remoteFiles,arquivo); if (remoteFile == null) { tabela.setValueAt("ok - ne", i, 0); } else { tabela.setValueAt(Long.toString(remoteFile.getSize()), i, 5); try { ftp.deleteFile(arquivo); tabela.setValueAt("ok", i, 0); posTransfer(i); } catch (IOException | NumberFormatException e) { tabela.setValueAt("erro", i, 0); } } } // DOWNLOAD - recebe os arquivos (pr listado e calculado) break; // fim if case "receber": try { // cada vez que muda o diretrio, a varivel diretrioDownload nula if (diretorioDownload == null) { diretorioDownload = albunsRoot.getAbsolutePath() + File.separator + albumID; File temp = new File(diretorioDownload); if (!temp.isDirectory()) { temp.mkdir(); Util.log("Criando diretrio " + diretorioDownload); } temp = null; } arqDestino = diretorioDownload + File.separator + arquivo; Util.out.println(arquivo + " -> " + arqDestino); streamOrigem = new BufferedInputStream(ftp.retrieveFileStream(arquivo), ftp.getBufferSize()); streamDestino = new FileOutputStream(arqDestino); this.transfereArquivo((InputStream) streamOrigem, (OutputStream) streamDestino, Long.parseLong(tabela.getValueAt(i, 5).toString())); tabela.setValueAt("ok", i, 0); // calcula porcentagem e atualiza barra posTransfer(i); } catch (IOException ioE) { Util.err.println("Erro de transmisso: " + ioE.getMessage() + " " + ((CopyStreamException) ioE).getIOException().getMessage()); tabela.setValueAt("erro", i, 0); log.error(ioE); } catch (NumberFormatException e) { Util.err.println("Erro: "); log.error(e); tabela.setValueAt("erro", i, 0); } finally { try { ftp.printWorkingDirectory(); } catch (IOException e) { } try { ((InputStream) streamOrigem).close(); ((OutputStream) streamDestino).close(); } catch (IOException e) { } } break; } ultimoID = albumID; } // fim for ftp.disconnect("transmisso terminada"); } private void preProcessBatch() { String acao; Arquivo tmpArq; int i, j = 0; // calcula quantidade de bytes a transmitir (upload e download somente) for (i = 0; i < tabela.getRowCount(); i++) { acao = tabela.getValueAt(i, 1).toString(); if (acao.equals("enviar")) { totalBytes += Long.parseLong(tabela.getValueAt(i, 5).toString()); } if (acao.equals("receber")) { Util.log("Calculando bytes a serem recebidos (lbum " + tabela.getValueAt(i, 2) + ")"); tmpArq = (Arquivo) ftp.getListaArquivos().get(i); if (tmpArq.getNomeArquivo().equals("* todos")) { // Baixando todo o lbum try { Util.out.println("Convertendo: " + tmpArq.getAlbumID()); // remove o tem atual e diminui // o marcador aps a remoo ftp.getListaArquivos().remove(i--); ftp.cd(Integer.toString(tmpArq.getAlbumID())); remoteFiles = ftp.listFiles(); for (FTPFile remote : remoteFiles) { ftp.getListaArquivos().add(new Arquivo(tmpArq.getLinhaComando(), 2, tmpArq.getAlbumID(), tmpArq.getFotoID(), remote.getName(), remote.getSize())); totalBytes += remote.getSize(); } // fim for } catch (SyncException se) { Util.log(se.getMessage()); ftp.disconnect("no foi possivel entrar no diretorio"); } catch (IOException e) { log.error(e); } } else { // Baixando um arquivo try { ftp.cd(Integer.toString(tmpArq.getAlbumID())); remoteFiles = this.ftp.listFiles(); for (FTPFile remote : remoteFiles) { if (tmpArq.getNomeArquivo().equals(remote.getName())) { totalBytes += remote.getSize(); tmpArq.setTamanho(remote.getSize()); break; } } // fim for } catch (SyncException se) { Util.log(se.getMessage()); ftp.disconnect("no foi possivel entrar no diretorio"); } catch (IOException e) { log.error(e); } } } if (acao.equals("apagar")) { Util.log("Calculando bytes a serem apagados (lbum " + tabela.getValueAt(i, 2) + ")"); tmpArq = (Arquivo) ftp.getListaArquivos().get(i); if (tmpArq.getNomeArquivo().equals("* todos")) { // Apagando todo o lbum try { Util.out.println("Convertendo: " + tmpArq.getAlbumID()); ftp.cd(Integer.toString(tmpArq.getAlbumID())); remoteFiles = this.ftp.listFiles(); for (FTPFile remote : remoteFiles) { totalBytes += remote.getSize(); } } catch (SyncException se) { Util.log(se.getMessage()); ftp.disconnect("no foi possivel entrar no diretorio"); } catch (IOException e) { log.error(e); } } else { // Apagando um arquivo try { ftp.cd(Integer.toString(tmpArq.getAlbumID())); remoteFiles = this.ftp.listFiles(); for (FTPFile remote : remoteFiles) { if (tmpArq.getNomeArquivo().equals(remote.getName())) { totalBytes += remote.getSize(); tmpArq.setTamanho(remote.getSize()); break; } } } catch (SyncException se) { Util.log(se.getMessage()); ftp.disconnect("no foi possivel entrar no diretorio"); } catch (IOException e) { log.error(e); } } } } } private void posTransfer(final int i) throws NumberFormatException { transmitido += Long.parseLong(tabela.getValueAt(i, 5).toString()); Util.out.println("Processado " + transmitido + " de " + totalBytes); barra.setValue((int) transmitido); lblKbytes.setText(Math.round((float) transmitido / 1024) + " Kb"); } private void transfereArquivo(InputStream streamOrigem, OutputStream streamDestino, long streamSize) throws CopyStreamException, IOException { barraArquivoAtual.setValue(0); barraArquivoAtual.setMaximum((int) streamSize); lblKbytesArquivoAtual.setText("0 Kb"); try { ftp.transferFile(streamOrigem, streamDestino, streamSize); } catch (IOException e) { try { streamOrigem.close(); streamDestino.close(); } catch (IOException f) { } throw e; } } }