Java tutorial
/* Copyright (C) 2013 Tobias Baum <tbaum at tntinteractive.de> This file is a part of Portalsammler. Portalsammler is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Portalsammler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Portalsammler. If not, see <http://www.gnu.org/licenses/>. */ package de.tntinteractive.portalsammler.gui; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.SecureRandom; import java.util.Arrays; import java.util.List; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JTextField; import javax.swing.ProgressMonitor; import javax.swing.SwingWorker; import org.apache.commons.lang3.tuple.Pair; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.factories.CC; import com.jgoodies.forms.layout.FormLayout; import de.tntinteractive.portalsammler.engine.CryptoHelper; import de.tntinteractive.portalsammler.engine.DocumentFilterParser; import de.tntinteractive.portalsammler.engine.SecureStore; import de.tntinteractive.portalsammler.engine.Settings; import de.tntinteractive.portalsammler.engine.SourceSettings; import de.tntinteractive.portalsammler.sources.DocumentSourceFactory; public final class MainDialog extends JFrame { private static final long serialVersionUID = -2309663260423505246L; private final Gui gui; private final JTextField filterField; private final JButton pollButton; private final DocumentTable table; public MainDialog(final Gui gui, final SecureStore store) { this.setTitle("Portalsammler"); this.setSize(800, 600); this.gui = gui; this.table = new DocumentTable(gui, store); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.filterField = new JTextField(); this.filterField.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { MainDialog.this.filter(); } }); final PanelBuilder fpb = new PanelBuilder(new FormLayout("right:pref, 4dlu, fill:pref:grow", "p")); fpb.addLabel("&Filter", CC.xy(1, 1)); fpb.add(this.filterField, CC.xy(3, 1)); final ButtonBarBuilder bbb = new ButtonBarBuilder(); this.pollButton = this.createPollButton(); bbb.addButton(this.pollButton, this.createConfigButton()); final PanelBuilder builder = new PanelBuilder( new FormLayout("4dlu, fill:pref:grow, 4dlu", "4dlu, p, 4dlu, fill:50dlu:grow, 4dlu, p, 4dlu")); builder.add(fpb.getPanel(), CC.xy(2, 2)); builder.add(this.table.createWrappedPanel(), CC.xy(2, 4)); builder.add(bbb.getPanel(), CC.xy(2, 6)); this.setContentPane(builder.getPanel()); this.setLocationRelativeTo(this.getOwner()); } private void filter() { this.table.changeFilter(DocumentFilterParser.parse(this.filterField.getText())); } private JButton createConfigButton() { final JButton button = new JButton("Konfiguration..."); button.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { final JPopupMenu menu = MainDialog.this.createConfigMenu(); final JButton source = (JButton) e.getSource(); menu.show(source, 0, source.getHeight()); } }); return button; } private JPopupMenu createConfigMenu() { final JPopupMenu menu = new JPopupMenu(); final JMenuItem sourceConfig = new JMenuItem("Quellen verwalten..."); sourceConfig.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { MainDialog.this.gui.showConfigGui(MainDialog.this.getStore()); } }); menu.add(sourceConfig); final JMenuItem changePassword = new JMenuItem("Neues Passwort..."); changePassword.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { try { MainDialog.this.changePassword(); } catch (final GeneralSecurityException ex) { MainDialog.this.gui.showError(ex); } catch (final IOException ex) { MainDialog.this.gui.showError(ex); } } }); menu.add(changePassword); return menu; } private JButton createPollButton() { final JButton button = new JButton("Dokumente abrufen"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { MainDialog.this.poll(MainDialog.this.gui); } }); return button; } private void poll(final Gui gui) { this.pollButton.setEnabled(false); final Settings settings = this.getStore().getSettings().deepClone(); final ProgressMonitor progress = new ProgressMonitor(this, "Sammle Daten aus den Quell-Portalen...", "...", 0, settings.getSize()); progress.setMillisToDecideToPopup(0); progress.setMillisToPopup(0); progress.setProgress(0); final SwingWorker<String, String> task = new SwingWorker<String, String>() { @Override protected String doInBackground() throws Exception { final StringBuilder summary = new StringBuilder(); int cnt = 0; for (final String id : settings.getAllSettingIds()) { if (this.isCancelled()) { break; } cnt++; this.publish(cnt + ": " + id); final Pair<Integer, Integer> counts = MainDialog.this.pollSingleSource(settings, id); summary.append(id).append(": "); if (counts != null) { summary.append(counts.getLeft()).append(" neu, ").append(counts.getRight()) .append(" schon bekannt\n"); } else { summary.append("Fehler!\n"); } this.setProgress(cnt); } MainDialog.this.getStore().writeMetadata(); return summary.toString(); } @Override protected void process(final List<String> ids) { progress.setNote(ids.get(ids.size() - 1)); } @Override public void done() { MainDialog.this.pollButton.setEnabled(true); MainDialog.this.table.refreshContents(); try { final String summary = this.get(); JOptionPane.showMessageDialog(MainDialog.this, summary, "Abruf-Zusammenfassung", JOptionPane.INFORMATION_MESSAGE); } catch (final Exception e) { gui.showError(e); } } }; task.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(final PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progress.setProgress((Integer) evt.getNewValue()); } if (progress.isCanceled()) { task.cancel(true); } } }); task.execute(); } private Pair<Integer, Integer> pollSingleSource(final Settings settings, final String id) { final SourceSettings s = settings.getSettings(id); final DocumentSourceFactory factory = SourceFactories.getByName(s.get(SourceFactories.TYPE, this.gui)); try { return factory.create(id).poll(s, this.gui, this.getStore()); } catch (final Exception e) { this.gui.showError(e); return null; } } private void changePassword() throws GeneralSecurityException, IOException { final SecureRandom srand = new SecureRandom(); final byte[] key = CryptoHelper.generateKey(srand); this.gui.showGeneratedPassword(CryptoHelper.keyToString(key)); while (true) { final String enteredPw = this.gui.askForPassword(this.getStore().getDirectory()); if (enteredPw == null) { //Abbruch durch den Benutzer return; } if (Arrays.equals(key, CryptoHelper.keyFromString(enteredPw))) { //alles OK => ndern kann abgeschlossen werden break; } JOptionPane.showMessageDialog(this, "Das neue Passwort wurde nicht korrekt eingegeben.", "Falsches Passwort", JOptionPane.ERROR_MESSAGE, null); } this.table.setStore(this.getStore().recrypt(key)); } private SecureStore getStore() { return this.table.getStore(); } }