From jflesch at freenetproject.org Wed Aug 1 03:20:43 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Wed, 1 Aug 2007 03:20:43 +0000 (UTC) Subject: [Thaw-dev] r14453 - trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK Message-ID: <20070801032043.4C5D647993F@freenetproject.org> Author: jflesch Date: 2007-08-01 03:20:42 +0000 (Wed, 01 Aug 2007) New Revision: 14453 Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java Log: Fix a mistake in the message date checks Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java 2007-07-31 17:33:16 UTC (rev 14452) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java 2007-08-01 03:20:42 UTC (rev 14453) @@ -162,11 +162,30 @@ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.M.d HH:mm:ss"); + date = date.trim(); time = time.trim(); - java.sql.Timestamp dateSql = new java.sql.Timestamp(boardDate.getTime()); + date += " "+time; + java.util.Date dateUtil = dateFormat.parse(date, new java.text.ParsePosition(0)); + if (dateUtil != null) { + long dateDiff = KSKBoard.getMidnight(dateUtil).getTime() - KSKBoard.getMidnight(boardDate).getTime(); + /* we accept between -24h before and +24h after */ + + if (dateDiff < 24*60*60*1000 || dateDiff > 24*60*60*1000) + dateUtil = null; + } + + + java.sql.Timestamp dateSql; + + if (dateUtil != null) + dateSql = new java.sql.Timestamp(dateUtil.getTime()); + else + dateSql = new java.sql.Timestamp(boardDate.getTime()); + + int replyToId = -1; try { From jflesch at freenetproject.org Wed Aug 1 14:40:22 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Wed, 1 Aug 2007 14:40:22 +0000 (UTC) Subject: [Thaw-dev] r14455 - trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK Message-ID: <20070801144022.6FC63478171@freenetproject.org> Author: jflesch Date: 2007-08-01 14:40:22 +0000 (Wed, 01 Aug 2007) New Revision: 14455 Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java Log: Fix a mistake in the message date checks Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java 2007-08-01 10:32:12 UTC (rev 14454) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java 2007-08-01 14:40:22 UTC (rev 14455) @@ -173,7 +173,7 @@ long dateDiff = KSKBoard.getMidnight(dateUtil).getTime() - KSKBoard.getMidnight(boardDate).getTime(); /* we accept between -24h before and +24h after */ - if (dateDiff < 24*60*60*1000 || dateDiff > 24*60*60*1000) + if (dateDiff < (-1)*48*60*60*1000 || dateDiff > 48*60*60*1000) dateUtil = null; } From jflesch at freenetproject.org Wed Aug 1 17:49:01 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Wed, 1 Aug 2007 17:49:01 +0000 (UTC) Subject: [Thaw-dev] r14456 - in trunk/apps/Thaw/src/thaw: core fcp plugins/signatures Message-ID: <20070801174901.A93DA3886E5@freenetproject.org> Author: jflesch Date: 2007-08-01 17:49:01 +0000 (Wed, 01 Aug 2007) New Revision: 14456 Modified: trunk/apps/Thaw/src/thaw/core/Core.java trunk/apps/Thaw/src/thaw/core/I18n.java trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java trunk/apps/Thaw/src/thaw/plugins/signatures/Identity.java trunk/apps/Thaw/src/thaw/plugins/signatures/SigConfigTab.java Log: Fix the signature management (remove an error + fix the way the signature are ordered) Modified: trunk/apps/Thaw/src/thaw/core/Core.java =================================================================== --- trunk/apps/Thaw/src/thaw/core/Core.java 2007-08-01 14:40:22 UTC (rev 14455) +++ trunk/apps/Thaw/src/thaw/core/Core.java 2007-08-01 17:49:01 UTC (rev 14456) @@ -394,12 +394,10 @@ try { javax.swing.SwingUtilities.invokeAndWait(s); } catch(InterruptedException e) { - Logger.error(s, "Interrupted while setting theme '"+theme+"' !"); - Logger.error(s, "Interrupted because: "+e.toString()); + Logger.error(s, "Interrupted while setting theme '"+theme+"' because: "+e.toString()); } catch(java.lang.reflect.InvocationTargetException e) { Logger.error(s, "Error while setting theme : "+e.toString()); - e.printStackTrace(); - Logger.error(s, "Original exception: "+e.getTargetException().toString()); + Logger.notice(s, "Original exception: "+e.getTargetException().toString()); e.getTargetException().printStackTrace(); } } Modified: trunk/apps/Thaw/src/thaw/core/I18n.java =================================================================== --- trunk/apps/Thaw/src/thaw/core/I18n.java 2007-08-01 14:40:22 UTC (rev 14455) +++ trunk/apps/Thaw/src/thaw/core/I18n.java 2007-08-01 17:49:01 UTC (rev 14456) @@ -68,7 +68,7 @@ try { return I18n.getResourceBundle().getString(key); } catch(final Exception e) { - Logger.warning(new I18n(),/* we need a ref -> random ref -> this is *bad* */ + Logger.warning(new I18n(), "Unable to find translation for '"+key+"'"); e.printStackTrace(); return key; Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java =================================================================== --- trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java 2007-08-01 14:40:22 UTC (rev 14455) +++ trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java 2007-08-01 17:49:01 UTC (rev 14456) @@ -475,8 +475,7 @@ schedule(); } catch(final Exception e) { - Logger.error(this, "EXCEPTION FROM ORDONNANCOR : "+e.toString()); - Logger.error(this, "ERROR : "+e.getMessage()); + Logger.error(this, "EXCEPTION FROM ORDONNANCOR : "+e.toString()+ " ; "+e.getMessage()); e.printStackTrace(); } } Modified: trunk/apps/Thaw/src/thaw/plugins/signatures/Identity.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/signatures/Identity.java 2007-08-01 14:40:22 UTC (rev 14455) +++ trunk/apps/Thaw/src/thaw/plugins/signatures/Identity.java 2007-08-01 17:49:01 UTC (rev 14456) @@ -540,11 +540,11 @@ "privateKey, isDup, trustLevel "+ "FROM signatures "+ "WHERE "+cond + " "+ - "ORDER BY nickName"); + "ORDER BY LOWER(nickName)"); else st = db.getConnection().prepareStatement("SELECT id, nickName, publicKey, "+ "privateKey, isDup, trustLevel "+ - "FROM signatures ORDER BY nickName"); + "FROM signatures ORDER BY LOWER(nickName)"); ResultSet set = st.executeQuery(); Modified: trunk/apps/Thaw/src/thaw/plugins/signatures/SigConfigTab.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/signatures/SigConfigTab.java 2007-08-01 14:40:22 UTC (rev 14455) +++ trunk/apps/Thaw/src/thaw/plugins/signatures/SigConfigTab.java 2007-08-01 17:49:01 UTC (rev 14456) @@ -480,6 +480,7 @@ if (e.getSource() == close) { dialog.setVisible(false); + return; } int row = table.getSelectedRow(); From jflesch at freenetproject.org Wed Aug 1 21:20:07 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Wed, 1 Aug 2007 21:20:07 +0000 (UTC) Subject: [Thaw-dev] r14457 - in trunk/apps/Thaw/src/thaw: gui plugins/miniFrost plugins/transferLogs Message-ID: <20070801212007.A886947A221@freenetproject.org> Author: jflesch Date: 2007-08-01 21:20:07 +0000 (Wed, 01 Aug 2007) New Revision: 14457 Modified: trunk/apps/Thaw/src/thaw/gui/Table.java trunk/apps/Thaw/src/thaw/gui/TransferProgressBar.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java trunk/apps/Thaw/src/thaw/plugins/transferLogs/TransferTable.java Log: Optimize the table renderers Modified: trunk/apps/Thaw/src/thaw/gui/Table.java =================================================================== --- trunk/apps/Thaw/src/thaw/gui/Table.java 2007-08-01 17:49:01 UTC (rev 14456) +++ trunk/apps/Thaw/src/thaw/gui/Table.java 2007-08-01 21:20:07 UTC (rev 14457) @@ -161,13 +161,23 @@ private Color softGray; + private JLabel labelRenderer; + private TransferProgressBar transferProgressBarRenderer; + private JTextArea textAreaRenderer; public DefaultRenderer() { softGray = new Color(240,240,240); + labelRenderer = new JLabel(); + transferProgressBarRenderer = new TransferProgressBar(null, statusInProgressBars); + textAreaRenderer = new JTextArea(); + textAreaRenderer.setEditable(false); + textAreaRenderer.setLineWrap(true); + textAreaRenderer.setWrapStyleWord(true); } public void showStatusInProgressBars(boolean v) { statusInProgressBars = v; + transferProgressBarRenderer.showStatusInProgressBar(v); } public void specifyColumnWithKeys(int c) { @@ -183,15 +193,20 @@ if (value instanceof FCPTransferQuery) { final FCPTransferQuery query = (FCPTransferQuery)value; - final JProgressBar bar = new TransferProgressBar(query, statusInProgressBars); - return bar; + //final JProgressBar bar = new TransferProgressBar(query, statusInProgressBars); + + transferProgressBarRenderer.setQuery(query); + transferProgressBarRenderer.refresh(); + + return transferProgressBarRenderer; } Component cell; if (value instanceof ImageIcon) { - return new JLabel(((ImageIcon)value)); + labelRenderer.setIcon((ImageIcon)value); + return labelRenderer; } if (value instanceof JPanel) { cell = (Component)value; } else if(value instanceof Long) { @@ -201,15 +216,12 @@ isSelected, hasFocus, row, column); } else if (value instanceof String && ((String)value).indexOf("\n") >= 0) { - JTextArea area = new JTextArea((String)value); - area.setEditable(false); - area.setLineWrap(true); - area.setWrapStyleWord(true); + textAreaRenderer.setText((String)value); - if (table.getRowHeight(row) < area.getPreferredSize().getHeight()) - table.setRowHeight((int)area.getPreferredSize().getHeight()); + if (table.getRowHeight(row) < textAreaRenderer.getPreferredSize().getHeight()) + table.setRowHeight((int)textAreaRenderer.getPreferredSize().getHeight()); - cell = area; + cell = textAreaRenderer; } else { cell = super.getTableCellRendererComponent(table, value, Modified: trunk/apps/Thaw/src/thaw/gui/TransferProgressBar.java =================================================================== --- trunk/apps/Thaw/src/thaw/gui/TransferProgressBar.java 2007-08-01 17:49:01 UTC (rev 14456) +++ trunk/apps/Thaw/src/thaw/gui/TransferProgressBar.java 2007-08-01 21:20:07 UTC (rev 14457) @@ -23,14 +23,21 @@ this.query = query; this.statusInProgressBar = statusInProgressBar; this.withBorder = withBorder; - - refresh(); } public TransferProgressBar(FCPTransferQuery query, boolean statusInProgressBar) { this(query, statusInProgressBar, false); } + public void setQuery(FCPTransferQuery query) { + this.query = query; + } + + public void showStatusInProgressBar(boolean v) { + this.statusInProgressBar = v; + } + + public void refresh() { int progress; Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-01 17:49:01 UTC (rev 14456) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-01 21:20:07 UTC (rev 14457) @@ -261,8 +261,11 @@ } protected class MessageTableRenderer extends Table.DefaultRenderer { + private JCheckBox checkBoxRenderer; + public MessageTableRenderer() { super(); + this.checkBoxRenderer = new JCheckBox(); } public Component getTableCellRendererComponent(final JTable table, Object value, @@ -273,11 +276,9 @@ Author author = model.getMsg(row).getSender(); if (value instanceof Boolean) { - JCheckBox box = new JCheckBox(); + checkBoxRenderer.setSelected(((Boolean)value).booleanValue()); - box.setSelected(((Boolean)value).booleanValue()); - - return box; + return checkBoxRenderer; } Color color = Color.BLACK; Modified: trunk/apps/Thaw/src/thaw/plugins/transferLogs/TransferTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/transferLogs/TransferTable.java 2007-08-01 17:49:01 UTC (rev 14456) +++ trunk/apps/Thaw/src/thaw/plugins/transferLogs/TransferTable.java 2007-08-01 21:20:07 UTC (rev 14457) @@ -132,9 +132,18 @@ private Color softGray; private Color lightBlue; + private JTextArea textAreaRenderer; + private JLabel labelRenderer; + public TransferTableRenderer() { softGray = new Color(240,240,240); lightBlue = new Color(220, 220, 255); + + labelRenderer = new JLabel("", JLabel.CENTER); + + textAreaRenderer = new JTextArea(); + textAreaRenderer.setEditable(false); + textAreaRenderer.setLineWrap(false); } public Component getTableCellRendererComponent(final JTable table, Object value, @@ -143,14 +152,12 @@ Component cell; if (value instanceof String && ((String)value).indexOf("\n") >= 0) { - JTextArea area = new JTextArea((String)value); - area.setEditable(false); - area.setLineWrap(false); + textAreaRenderer.setText((String)value); + cell = textAreaRenderer; - cell = area; - } else if ((value instanceof String) && "X".equals((String)value) ) { - return new JLabel(IconBox.minClose); + labelRenderer.setIcon(IconBox.minClose); + return labelRenderer; } else if (value instanceof Integer) { int val = ((Integer)value).intValue(); @@ -168,7 +175,9 @@ icon = (val == TransferLogs.TRANSFER_TYPE_DOWNLOAD) ? IconBox.minDownloads : IconBox.minInsertions; - return new JLabel(icon); + labelRenderer.setIcon(icon); + + return labelRenderer; } } else { From jflesch at freenetproject.org Thu Aug 2 00:41:03 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 00:41:03 +0000 (UTC) Subject: [Thaw-dev] r14458 - in trunk/apps/Thaw/src/thaw: gui i18n plugins plugins/miniFrost plugins/miniFrost/frostKSK plugins/miniFrost/interfaces Message-ID: <20070802004103.1DA9A479F2B@freenetproject.org> Author: jflesch Date: 2007-08-02 00:41:02 +0000 (Thu, 02 Aug 2007) New Revision: 14458 Modified: trunk/apps/Thaw/src/thaw/gui/Table.java trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties trunk/apps/Thaw/src/thaw/i18n/thaw.properties trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties trunk/apps/Thaw/src/thaw/plugins/TrayIcon.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessage.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/interfaces/Message.java Log: Allow to display a tree with all the messages Modified: trunk/apps/Thaw/src/thaw/gui/Table.java =================================================================== --- trunk/apps/Thaw/src/thaw/gui/Table.java 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/gui/Table.java 2007-08-02 00:41:02 UTC (rev 14458) @@ -39,6 +39,9 @@ */ public class Table extends JTable implements TableColumnModelListener, Runnable { + public final static Color COLOR_ONE = Color.WHITE; + public final static Color COLOR_TWO = new Color(240, 240, 240); + private Config config; private String configPrefix; @@ -159,14 +162,11 @@ private boolean statusInProgressBars = true; private int columnWithKeys = -1; - private Color softGray; - private JLabel labelRenderer; private TransferProgressBar transferProgressBarRenderer; private JTextArea textAreaRenderer; public DefaultRenderer() { - softGray = new Color(240,240,240); labelRenderer = new JLabel(); transferProgressBarRenderer = new TransferProgressBar(null, statusInProgressBars); textAreaRenderer = new JTextArea(); @@ -184,6 +184,16 @@ columnWithKeys = c; } + + public void setBackground(Component c, int row, boolean isSelected) { + if (!isSelected) { + if (row % 2 == 0) + c.setBackground(COLOR_ONE); + else + c.setBackground(COLOR_TWO); + } + } + public Component getTableCellRendererComponent(final JTable table, Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) { @@ -230,12 +240,7 @@ } - if (!isSelected) { - if (row % 2 == 0) - cell.setBackground(Color.WHITE); - else - cell.setBackground(softGray); - } + setBackground(cell, row, isSelected); cell.setForeground(Color.BLACK); Modified: trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties =================================================================== --- trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties 2007-08-02 00:41:02 UTC (rev 14458) @@ -599,3 +599,5 @@ thaw.plugin.miniFrost.invalidRegexp=Une de vos regexp est invalide : X thaw.plugin.miniFrost.modifyRegexp=Modifier les r?gles de filtrage + +thaw.plugin.miniFrost.seeTree=Voir les messages sous forme d'arbre Modified: trunk/apps/Thaw/src/thaw/i18n/thaw.properties =================================================================== --- trunk/apps/Thaw/src/thaw/i18n/thaw.properties 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/i18n/thaw.properties 2007-08-02 00:41:02 UTC (rev 14458) @@ -618,3 +618,4 @@ thaw.plugin.miniFrost.invalidRegexp=One of your regexp is invalid : X thaw.plugin.miniFrost.modifyRegexp=Modify the filtering rules +thaw.plugin.miniFrost.seeTree=See message tree Modified: trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties =================================================================== --- trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties 2007-08-02 00:41:02 UTC (rev 14458) @@ -593,9 +593,11 @@ thaw.plugin.miniFrost.encrypted=Crypt\u00e9 thaw.plugin.miniFrost.encryptedBody=Crypt\u00e9 pour 'X' -thaw.plugin.miniFrost.regexpBlacklist=Archiver imm\u00e9diatement les messages correspondant aux expressions suivantes (une par line): +thaw.plugin.miniFrost.regexpBlacklistLongDesc=Archiver imm\u00e9diatement les messages correspondant aux expressions suivantes (une par line): thaw.plugin.miniFrost.seeSunManual=(Voir X) thaw.plugin.miniFrost.regexpBlacklist=Filtrage thaw.plugin.miniFrost.invalidRegexp=Une de vos regexp est invalide : X thaw.plugin.miniFrost.modifyRegexp=Modifier les r\u00e8gles de filtrage + +thaw.plugin.miniFrost.seeTree=Voir les messages sous forme d'arbre Modified: trunk/apps/Thaw/src/thaw/plugins/TrayIcon.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/TrayIcon.java 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/plugins/TrayIcon.java 2007-08-02 00:41:02 UTC (rev 14458) @@ -236,6 +236,7 @@ p.add(l); TransferProgressBar bar = new TransferProgressBar(q, true, true); + bar.refresh(); progressBars.add(bar); p.add(bar); Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 00:41:02 UTC (rev 14458) @@ -18,10 +18,15 @@ import java.awt.Color; import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; import javax.swing.DefaultCellEditor; import javax.swing.event.TableModelEvent; + import java.util.Vector; +import java.util.Iterator; +import java.util.Enumeration; + import java.awt.Component; import java.awt.event.ActionListener; @@ -30,6 +35,7 @@ import javax.swing.table.TableCellEditor; import javax.swing.event.CellEditorListener; + import javax.swing.JComboBox; import javax.swing.JTextField; @@ -44,8 +50,14 @@ import java.awt.Font; import java.awt.event.KeyEvent; +import javax.swing.JTree; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeNode; +import java.util.HashMap; + import thaw.gui.Table; import thaw.gui.IconBox; import thaw.core.I18n; @@ -113,10 +125,18 @@ private int orderBy; private boolean desc; + private JCheckBox seeTree; private JCheckBox seeUnsigned; private JComboBox minTrustLevel; private int minTrustLevelInt; + + + /** for the thread tree **/ + private MessageNodeTree messageNodeTree; + private HashMap messageNodeHashMap; + + public MessageTreeTable(MiniFrostPanel mainPanel) { this.mainPanel = mainPanel; @@ -182,9 +202,7 @@ table.addMouseListener(this); setBoard(null); - refresh(); - panel.add(northPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); @@ -216,8 +234,15 @@ seeUnsigned = new JCheckBox(I18n.getMessage("thaw.plugin.miniFrost.seeUnsigned"), true); seeUnsigned.addActionListener(this); + seeTree = new JCheckBox(I18n.getMessage("thaw.plugin.miniFrost.seeTree")); + seeTree.setSelected(true); + seeTree.addActionListener(this); + JPanel southWestPanel = new JPanel(new GridLayout(2, 1)); + southWestPanel.add(new JLabel("")); + southWestPanel.add(seeTree); + JPanel southEastPanel = new JPanel(new GridLayout(2, 1)); JPanel southEastPanelTop = new JPanel(new GridLayout(1, 2, 10, 10)); @@ -229,12 +254,15 @@ JPanel southPanel = new JPanel(new BorderLayout(5, 5)); + southPanel.add(southWestPanel, BorderLayout.WEST); southPanel.add(new JLabel(""), BorderLayout.CENTER); southPanel.add(southEastPanel, BorderLayout.EAST); panel.add(southPanel, BorderLayout.SOUTH); mainPanel.getBoardTree().addObserver(this); + + refresh(); } @@ -260,6 +288,196 @@ return panel; } + + + + protected class MessageNodeTree extends JTree { + + public MessageNodeTree(TreeNode root) { + super(root); + + DefaultTreeCellRenderer cellRenderer = (DefaultTreeCellRenderer)getCellRenderer(); + cellRenderer.setOpenIcon(cellRenderer.getDefaultLeafIcon()); + cellRenderer.setClosedIcon(cellRenderer.getDefaultLeafIcon()); + } + + protected int visibleRow; + protected int rowHeight; + + public void setBounds(int x, int y, int w, int h) { + super.setBounds(x, 0, w, table.getHeight()); + } + + public void paint(java.awt.Graphics g) { + g.translate(0, (-(visibleRow+1) * rowHeight)); + super.paint(g); + } + + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, int column) { + if (isSelected) + setSelectionRow(row+1); /* don't forget the root :) */ + + setRowHeight(table.getRowHeight()); + rowHeight = table.getRowHeight(); + + Message msg = ((MessageNode)value).getMessage(); + + int mod = Font.PLAIN; + + if (msg != null) { + + if (!msg.isRead()) { + mod = Font.BOLD; + } + + if (msg.isArchived()) { + if (mod == Font.BOLD) + mod = Font.ITALIC | Font.BOLD; + else + mod = Font.ITALIC; + } + + } else + mod = Font.ITALIC; + + setFont(getFont().deriveFont(mod)); + + if (msg != null && msg.getSender().getIdentity() != null) + setForeground(msg.getSender().getIdentity().getTrustLevelColor()); + + visibleRow = row; + return this; + } + } + + + protected static class RootMessageNode implements TreeNode { + private Vector children; + + public RootMessageNode(Vector nodes) { + this.children = nodes; + } + + public Enumeration children() { + return children.elements(); + } + + public boolean getAllowsChildren() { + return true; + } + + public TreeNode getChildAt(int childIndex) { + return (MessageNode)children.get(childIndex); + } + + public int getChildCount() { + return children.size(); + } + + public int getIndex(TreeNode node) { + return children.indexOf(node); + } + + public TreeNode getParent() { + return null; + } + + public boolean isLeaf() { + return (children.size() == 0); + } + } + + + protected static class MessageNode implements TreeNode { + private Vector children; + + private boolean hasParent; + private TreeNode parent; + + private Message msg; + + public MessageNode(Message msg) { + this.parent = null; + this.msg = msg; + children = new Vector(0); + } + + public Message getMessage() { + return msg; + } + + public void setParent(TreeNode node) { + parent = node; + } + + /** + * will register + */ + public void setParent(HashMap messageNodes) { + String inReplyTo; + + if (msg != null && (inReplyTo = msg.getInReplyToId()) != null) { + hasParent = true; + + MessageNode node = (MessageNode)messageNodes.get(inReplyTo); + + if (node != null) { + setParent(node); + node.registerChild(this); + } + } + } + + public boolean hasParent() { + return hasParent; + } + + public void registerChild(MessageNode node) { + children.add(node); + } + + public java.util.Enumeration children() { + return children.elements(); + } + + public boolean getAllowsChildren() { + return true; + } + + public TreeNode getChildAt(int childIndex) { + return (MessageNode)children.get(childIndex); + } + + public int getChildCount() { + return children.size(); + } + + public int getIndex(TreeNode node) { + return children.indexOf(node); + } + + public TreeNode getParent() { + return parent; + } + + public boolean isLeaf() { + return (children.size() == 0); + } + + public String toString() { + if (msg != null) + return msg.getSubject(); + else + return "(?)"; + } + } + + + protected class MessageTableRenderer extends Table.DefaultRenderer { private JCheckBox checkBoxRenderer; @@ -273,27 +491,43 @@ final int row, final int column) { Component c; - Author author = model.getMsg(row).getSender(); + Message msg = model.getMsg(row); + Author author = (msg != null ? msg.getSender() : null); if (value instanceof Boolean) { - checkBoxRenderer.setSelected(((Boolean)value).booleanValue()); + checkBoxRenderer.setEnabled(msg != null); + + if (msg != null) + checkBoxRenderer.setSelected(((Boolean)value).booleanValue()); + else + checkBoxRenderer.setSelected(false); + return checkBoxRenderer; } + if (value instanceof MessageNode) { + return messageNodeTree.getTableCellRendererComponent(table, + value, + isSelected, + hasFocus, + row, + column); + } + Color color = Color.BLACK; - if (column == 2) - value = author.toString(); - else if (column == 3) { - if (author.getIdentity() != null) + if (column == 2) { + value = ((author != null) ? author.toString() : "(?)"); + } else if (column == 3) { + if (author != null && author.getIdentity() != null) value = author.getIdentity().getTrustLevelStr(); else value = I18n.getMessage("thaw.plugin.signature.trustLevel.none"); } - if (author.getIdentity() != null) + if (author != null && author.getIdentity() != null) color = author.getIdentity().getTrustLevelColor(); c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, @@ -301,20 +535,22 @@ c.setForeground(color); - Message msg = model.getMsg(row); - int mod = Font.PLAIN; - if (!msg.isRead()) { - mod = Font.BOLD; - } + if (msg != null) { + if (!msg.isRead()) { + mod = Font.BOLD; + } - if (msg.isArchived()) { - if (mod == Font.BOLD) - mod = Font.ITALIC | Font.BOLD; - else - mod = Font.ITALIC; + if (msg.isArchived()) { + if (mod == Font.BOLD) + mod = Font.ITALIC | Font.BOLD; + else + mod = Font.ITALIC; + } } + else + mod = Font.ITALIC; c.setFont(c.getFont().deriveFont(mod)); @@ -349,7 +585,7 @@ } public Message getMsg(int row) { - return (Message)msgs.get(row); + return ((MessageNode)msgs.get(row)).getMessage(); } public Object getValueAt(int row, int column) { @@ -358,25 +594,28 @@ } if (column == 1) { - Message msg = (Message)msgs.get(row); - return "("+Integer.toString(msg.getRev()) + ") "+ - msg.getSubject(); + return (MessageNode)msgs.get(row); } + Message msg = ((MessageNode)msgs.get(row)).getMessage(); + + if (msg == null) + return "(?)"; + if (column == 2) { - return ((Message)msgs.get(row)).getSender(); + return msg.getSender(); } if (column == 3) { - return ((Message)msgs.get(row)).getSender(); + return msg.getSender(); } if (column == 4) { - return ((Message)msgs.get(row)).getDate(); + return msg.getDate(); } if (column == 5) { - return ((Message)msgs.get(row)); + return msg; //.getMessage(); } return null; @@ -395,8 +634,12 @@ public void setSelectedAll(boolean s) { - for (int i = 0 ; i < selection.length ; i++) - selection[i] = s; + for (int i = 0 ; i < selection.length ; i++) { + Message msg = ((MessageNode)msgs.get(i)).getMessage(); + + if (msg != null) + selection[i] = s; + } } @@ -406,7 +649,12 @@ public void switchSelection(int row) { - selection[row] = !selection[row]; + Message msg = ((MessageNode)msgs.get(row)).getMessage(); + + if (msg != null) + selection[row] = !selection[row]; + else + selection[row] = false; } public Vector getMessages(Vector msgs) { @@ -414,9 +662,14 @@ } public void refresh(Message msg) { - refresh(msgs.indexOf(msg)); + /* quick and dirty */ + refresh(); } + public void refresh(MessageNode msgNode) { + refresh(msgs.indexOf(msgNode)); + } + public void refresh(int row) { if (row == -1) { Logger.error(this, "Message not found in the list ?!"); @@ -447,14 +700,43 @@ refresh(keywords, orderBy, desc, everywhereBox.isSelected()); } + + private boolean rebuildMsgList(Vector msgs, TreeNode node, int proof) { + if (node instanceof MessageNode) + msgs.add(node); + + if (proof >= 20) { + Logger.notice(this, "Too proof, sorry"); + return false; + } + + for(Enumeration e = node.children(); + e.hasMoreElements();) { + TreeNode sub = (TreeNode)e.nextElement(); + if (!rebuildMsgList(msgs, sub, proof+1)) + return false; + } + + return true; + } + + + public void refresh(String[] keywords, int orderBy, boolean desc, boolean allBoards) { Vector msgs = null; if ((!allBoards) && targetBoard != null) { - msgs = targetBoard.getMessages(keywords, orderBy, - desc, seeArchived.isSelected(), - seeUnsigned.isSelected(), - minTrustLevelInt); + Vector rawMsgs = targetBoard.getMessages(keywords, orderBy, + desc, seeArchived.isSelected(), + seeUnsigned.isSelected(), + minTrustLevelInt); + + msgs = new Vector(rawMsgs.size()); + + for(Iterator it = rawMsgs.iterator(); + it.hasNext();) { + msgs.add(new MessageNode((Message)it.next())); + } } if (allBoards) { @@ -467,13 +749,97 @@ seeArchived.isSelected(), seeUnsigned.isSelected(), minTrustLevelInt); - msgs.addAll(boardMsgs); + for (Iterator it = boardMsgs.iterator(); + it.hasNext();) { + msgs.add(new MessageNode((Message)it.next())); + } } } - if (msgs != null) - model.setMessages(msgs); + if (msgs == null) { + msgs = new Vector(); + } + Logger.info(this, "Nmb msgs in the tree : "+Integer.toString(msgs.size())); + + Vector rootNodes; + + if (seeTree.isSelected()) { + + /** Filling in messageNodeHashMap **/ + messageNodeHashMap = new HashMap(msgs.size()); + + for (Iterator it = msgs.iterator(); + it.hasNext();) { + MessageNode node = (MessageNode)it.next(); + messageNodeHashMap.put(node.getMessage().getMsgId(), node); + } + + + /** Building the tree **/ + for (Iterator it = msgs.iterator(); + it.hasNext();) { + ((MessageNode)it.next()).setParent(messageNodeHashMap); + } + + /** we search the nodes who should have a parent but haven't **/ + /* we don't use an iterator to avoid the collisions */ + for (int i = 0 ; i < msgs.size(); i++) { + MessageNode node = (MessageNode)msgs.get(i); + + if (node.getParent() == null && node.hasParent()) { + MessageNode newEmptyNode = new MessageNode(null); + node.setParent(newEmptyNode); + newEmptyNode.registerChild(node); + + /* we replace */ + msgs.set(i, newEmptyNode); + /* and readd the other node at the end of the vector */ + msgs.add(node); + } + } + + rootNodes = new Vector(); + + /* Building the root tree */ + + for (Iterator it = msgs.iterator(); + it.hasNext();) { + MessageNode node = (MessageNode)it.next(); + + if (node.getParent() == null) + rootNodes.add(node); + } + } else + rootNodes = msgs; + + + /* we add all the message without any parent to the root */ + RootMessageNode rootNode = new RootMessageNode(rootNodes); + + for (Iterator it = rootNodes.iterator(); + it.hasNext();) { + ((MessageNode)it.next()).setParent(rootNode); + } + + + /** and to finish, the tree itself **/ + messageNodeTree = new MessageNodeTree(rootNode); + + for (int i = 0 ; i < messageNodeTree.getRowCount() ; i++) { + messageNodeTree.expandRow(i); + } + + /** next we check we have the same order in the tree and in the table **/ + + msgs = new Vector(); + + rebuildMsgList(msgs, rootNode, 0); + + Logger.info(this, "Nmb msgs in the tree : "+Integer.toString(msgs.size())); + + model.setMessages(msgs); + model.refresh(); } @@ -520,7 +886,8 @@ public void actionPerformed(ActionEvent e) { if (e.getSource() == seeUnsigned || e.getSource() == minTrustLevel - || e.getSource() == seeArchived) { + || e.getSource() == seeArchived + || e.getSource() == seeTree) { minTrustLevelInt = Identity.getTrustLevel((String)(minTrustLevel.getSelectedItem())); refresh(); @@ -588,12 +955,17 @@ int row = table.rowAtPoint(e.getPoint()); int column = table.columnAtPoint(e.getPoint()); + Logger.info(this, "Mouse clicked"); + if (column == 0) { model.switchSelection(row); refresh(row); } else { - mainPanel.getMessagePanel().setMessage(model.getMsg(row)); - mainPanel.displayMessage(); + Message msg = model.getMsg(row); + if (msg != null) { + mainPanel.getMessagePanel().setMessage(msg); + mainPanel.displayMessage(); + } } } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java 2007-08-02 00:41:02 UTC (rev 14458) @@ -148,6 +148,8 @@ PreparedStatement st; String query = "SELECT frostKSKMessages.id, "+ + " frostKSKMessages.msgId, "+ + " frostKSKMessages.inReplyToId, "+ " frostKSKMessages.subject, "+ " frostKSKMessages.nick, "+ " frostKSKMessages.sigId, "+ @@ -205,6 +207,8 @@ String nick = set.getString("nickname"); v.add(new KSKMessage(set.getInt("id"), + set.getString("msgId"), + set.getString("inReplyToId"), set.getString("subject"), set.getString("nick"), sigId, @@ -252,6 +256,8 @@ PreparedStatement st; String query = "SELECT frostKSKMessages.id AS id, "+ + " frostKSKMessages.msgId AS msgId, "+ + " frostKSKMessages.inReplyToId AS inReplyToId, "+ " frostKSKMessages.subject AS subject, "+ " frostKSKMessages.nick AS nick, "+ " frostKSKMessages.sigId AS sigId, "+ @@ -286,6 +292,8 @@ int sigId = set.getInt("sigId"); return new KSKMessage(set.getInt("id"), + set.getString("msgId"), + set.getString("inReplyToId"), set.getString("subject"), set.getString("nick"), sigId, Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessage.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessage.java 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessage.java 2007-08-02 00:41:02 UTC (rev 14458) @@ -38,6 +38,8 @@ /* content is not kept in memory (at least not here) */ private int id; + private String idStr; + private String inReplyToStr; private String subject; private KSKAuthor author; private int sigId; @@ -165,24 +167,36 @@ } - public KSKMessage(int id, + public String getMsgId() { + return idStr; + } + + public String getInReplyToId() { + return inReplyToStr; + } + + + public KSKMessage(int id, String idStr, + String inReplyToStr, String subject, String nick, int sigId, Identity identity, java.util.Date date, int rev, boolean read, boolean archived, Identity encryptedFor, KSKBoard board) { - this.id = id; - this.subject = subject; + this.id = id; + this.idStr = idStr; + this.inReplyToStr = inReplyToStr; + this.subject = subject; - this.author = new KSKAuthor(nick, identity); + this.author = new KSKAuthor(nick, identity); - this.sigId = sigId; - this.date = date; - this.rev = rev; - this.read = read; - this.archived = archived; - this.board = board; + this.sigId = sigId; + this.date = date; + this.rev = rev; + this.read = read; + this.archived = archived; + this.board = board; this.encryptedFor = encryptedFor; } @@ -335,34 +349,7 @@ } - protected String getMsgId() { - try { - Hsqldb db = board.getFactory().getDb(); - synchronized(db.dbLock) { - - PreparedStatement st; - - st = db.getConnection().prepareStatement("SELECT msgId "+ - "FROM frostKSKMessages "+ - "WHERE id = ? "+ - "LIMIT 1"); - st.setInt(1, id); - - ResultSet set = st.executeQuery(); - - if (!set.next()) - return null; - - return set.getString("msgId"); - } - } catch(SQLException e) { - Logger.error(this, "Error while getting the messages : "+e.toString()); - return null; - } - } - - public String getRawMessage() { try { Hsqldb db = board.getFactory().getDb(); Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/interfaces/Message.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/interfaces/Message.java 2007-08-01 21:20:07 UTC (rev 14457) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/interfaces/Message.java 2007-08-02 00:41:02 UTC (rev 14458) @@ -8,6 +8,9 @@ public interface Message /* extends TreeNode */ { + public String getMsgId(); + public String getInReplyToId(); + //public int getParentId(); public String getSubject(); From jflesch at freenetproject.org Thu Aug 2 01:05:07 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 01:05:07 +0000 (UTC) Subject: [Thaw-dev] r14459 - in trunk/apps/Thaw/src/thaw: gui plugins/miniFrost Message-ID: <20070802010507.DE5B23886E9@freenetproject.org> Author: jflesch Date: 2007-08-02 01:05:07 +0000 (Thu, 02 Aug 2007) New Revision: 14459 Modified: trunk/apps/Thaw/src/thaw/gui/Table.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessagePanel.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java Log: Fix message tree colourisation Modified: trunk/apps/Thaw/src/thaw/gui/Table.java =================================================================== --- trunk/apps/Thaw/src/thaw/gui/Table.java 2007-08-02 00:41:02 UTC (rev 14458) +++ trunk/apps/Thaw/src/thaw/gui/Table.java 2007-08-02 01:05:07 UTC (rev 14459) @@ -185,13 +185,23 @@ } - public void setBackground(Component c, int row, boolean isSelected) { + /** + * @return null if default color + */ + public static Color setBackground(Component c, int row, boolean isSelected) { if (!isSelected) { - if (row % 2 == 0) - c.setBackground(COLOR_ONE); - else - c.setBackground(COLOR_TWO); + if (row % 2 == 0) { + if (c != null) + c.setBackground(COLOR_ONE); + return COLOR_ONE; + } else { + if (c != null) + c.setBackground(COLOR_TWO); + return COLOR_TWO; + } } + + return null; } public Component getTableCellRendererComponent(final JTable table, Object value, Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessagePanel.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessagePanel.java 2007-08-02 00:41:02 UTC (rev 14458) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessagePanel.java 2007-08-02 01:05:07 UTC (rev 14459) @@ -371,7 +371,8 @@ JPanel iPanel = null; - subject.setText(I18n.getMessage("thaw.plugin.miniFrost.subject")+": "+msg.getSubject()); + subject.setText(I18n.getMessage("thaw.plugin.miniFrost.subject")+": "+msg.getSubject()+ + " [r"+Integer.toString(msg.getRev())+"]"); Logger.info(this, "Displaying "+Integer.toString(subMsgs.size())+" sub-msgs"); Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 00:41:02 UTC (rev 14458) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 01:05:07 UTC (rev 14459) @@ -292,11 +292,12 @@ protected class MessageNodeTree extends JTree { + DefaultTreeCellRenderer cellRenderer; public MessageNodeTree(TreeNode root) { super(root); - DefaultTreeCellRenderer cellRenderer = (DefaultTreeCellRenderer)getCellRenderer(); + cellRenderer = (DefaultTreeCellRenderer)getCellRenderer(); cellRenderer.setOpenIcon(cellRenderer.getDefaultLeafIcon()); cellRenderer.setClosedIcon(cellRenderer.getDefaultLeafIcon()); } @@ -321,6 +322,8 @@ if (isSelected) setSelectionRow(row+1); /* don't forget the root :) */ + Color background = thaw.gui.Table.DefaultRenderer.setBackground(this, row, isSelected); + setRowHeight(table.getRowHeight()); rowHeight = table.getRowHeight(); @@ -346,9 +349,20 @@ setFont(getFont().deriveFont(mod)); - if (msg != null && msg.getSender().getIdentity() != null) - setForeground(msg.getSender().getIdentity().getTrustLevelColor()); + if (msg != null && msg.getSender().getIdentity() != null) { + Color foreground = msg.getSender().getIdentity().getTrustLevelColor(); + cellRenderer.setTextNonSelectionColor(foreground); + cellRenderer.setTextSelectionColor(foreground); + } else { + cellRenderer.setTextNonSelectionColor(Color.BLACK); + cellRenderer.setTextSelectionColor(Color.BLACK); + } + if (background != null) { + cellRenderer.setBackground(background); + cellRenderer.setBackgroundNonSelectionColor(background); + } + visibleRow = row; return this; } From jflesch at freenetproject.org Thu Aug 2 01:14:24 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 01:14:24 +0000 (UTC) Subject: [Thaw-dev] r14460 - trunk/apps/Thaw/src/thaw/plugins/miniFrost Message-ID: <20070802011424.BFE6D47A015@freenetproject.org> Author: jflesch Date: 2007-08-02 01:14:24 +0000 (Thu, 02 Aug 2007) New Revision: 14460 Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java Log: Fix the message ordering Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 01:05:07 UTC (rev 14459) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 01:14:24 UTC (rev 14460) @@ -451,7 +451,7 @@ } public void registerChild(MessageNode node) { - children.add(node); + children.insertElementAt(node, 0); } public java.util.Enumeration children() { From jflesch at freenetproject.org Thu Aug 2 03:46:47 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 03:46:47 +0000 (UTC) Subject: [Thaw-dev] r14461 - in trunk/apps/Thaw/src/thaw: core plugins/miniFrost/frostKSK Message-ID: <20070802034647.B8F7947A216@freenetproject.org> Author: jflesch Date: 2007-08-02 03:46:47 +0000 (Thu, 02 Aug 2007) New Revision: 14461 Modified: trunk/apps/Thaw/src/thaw/core/Core.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java Log: Implement a workaround to avoid a possible crash due to the tray icon when used under Linux without the GTK look'n'feel. (Bug reported to Sun ; ID: 1025293) Modified: trunk/apps/Thaw/src/thaw/core/Core.java =================================================================== --- trunk/apps/Thaw/src/thaw/core/Core.java 2007-08-02 01:14:24 UTC (rev 14460) +++ trunk/apps/Thaw/src/thaw/core/Core.java 2007-08-02 03:46:47 UTC (rev 14461) @@ -146,7 +146,7 @@ mainWindow.setVisible(true); - reallySetTheme(lookAndFeel); + setTheme(lookAndFeel); return true; } @@ -413,6 +413,7 @@ lookAndFeel = theme; + if (mainWindow.getMainFrame().isVisible()) reallySetTheme(lookAndFeel); } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java 2007-08-02 01:14:24 UTC (rev 14460) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java 2007-08-02 03:46:47 UTC (rev 14461) @@ -288,6 +288,12 @@ if (name == null) return; + try { + Thread.sleep(1500); + } catch(InterruptedException e) { + /* \_o< */ + } + createBoard(name); } From jflesch at freenetproject.org Thu Aug 2 04:25:16 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 04:25:16 +0000 (UTC) Subject: [Thaw-dev] r14462 - in trunk/apps/Thaw/src/thaw: core plugins/miniFrost plugins/miniFrost/frostKSK Message-ID: <20070802042516.0D9A247A148@freenetproject.org> Author: jflesch Date: 2007-08-02 04:25:15 +0000 (Thu, 02 Aug 2007) New Revision: 14462 Modified: trunk/apps/Thaw/src/thaw/core/Logger.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java Log: Synchronize the log listener list to avoid collisions Modified: trunk/apps/Thaw/src/thaw/core/Logger.java =================================================================== --- trunk/apps/Thaw/src/thaw/core/Logger.java 2007-08-02 03:46:47 UTC (rev 14461) +++ trunk/apps/Thaw/src/thaw/core/Logger.java 2007-08-02 04:25:15 UTC (rev 14462) @@ -133,17 +133,21 @@ if(Logger.logListeners == null) Logger.logListeners = new Vector(); - Logger.logListeners.add(logListener); + synchronized(logListeners) { + Logger.logListeners.add(logListener); + } } public static void removeLogListener(final LogListener logListener) { if(Logger.logListeners == null) return; - Logger.logListeners.remove(logListener); + synchronized(logListener) { + Logger.logListeners.remove(logListener); - if (logListeners.size() == 0) - logListeners = null; + if (logListeners.size() == 0) + logListeners = null; + } } @@ -154,11 +158,13 @@ if(Logger.logListeners == null) return; - for(final Iterator it = Logger.logListeners.iterator(); - it.hasNext(); ) { - final LogListener logListener = (LogListener)it.next(); + synchronized(logListeners) { + for(final Iterator it = Logger.logListeners.iterator(); + it.hasNext(); ) { + final LogListener logListener = (LogListener)it.next(); - logListener.newLogLine(level, src, line); + logListener.newLogLine(level, src, line); + } } } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 03:46:47 UTC (rev 14461) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 04:25:15 UTC (rev 14462) @@ -715,19 +715,19 @@ } - private boolean rebuildMsgList(Vector msgs, TreeNode node, int proof) { + private boolean rebuildMsgList(Vector msgs, TreeNode node, int depth) { if (node instanceof MessageNode) msgs.add(node); - if (proof >= 20) { - Logger.notice(this, "Too proof, sorry"); + if (depth >= 15) { + Logger.notice(this, "Too much depths, sorry"); return false; } for(Enumeration e = node.children(); e.hasMoreElements();) { TreeNode sub = (TreeNode)e.nextElement(); - if (!rebuildMsgList(msgs, sub, proof+1)) + if (!rebuildMsgList(msgs, sub, depth+1)) return false; } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java 2007-08-02 03:46:47 UTC (rev 14461) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java 2007-08-02 04:25:15 UTC (rev 14462) @@ -289,6 +289,11 @@ return; try { + /* ugly workaround to avoid a crash due to a Sun bug: + * If you call JOptionPanel.showInputDialog() and just after + * TrayIcon.displayMessage(), Swing will crash. + * (Note: remember, TrayIcon.displayMessage() is called by Logger.warning()) + */ Thread.sleep(1500); } catch(InterruptedException e) { /* \_o< */ From jflesch at freenetproject.org Thu Aug 2 13:07:28 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 13:07:28 +0000 (UTC) Subject: [Thaw-dev] r14463 - trunk/apps/Thaw/src/thaw/plugins/miniFrost Message-ID: <20070802130728.5381F47AAB0@freenetproject.org> Author: jflesch Date: 2007-08-02 13:07:27 +0000 (Thu, 02 Aug 2007) New Revision: 14463 Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java Log: In the messagre tree panel, try to prevent freezes by synchronizing the access to the hashtable (shouldn't be needed ?!) Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 04:25:15 UTC (rev 14462) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 13:07:27 UTC (rev 14463) @@ -55,7 +55,7 @@ import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeNode; -import java.util.HashMap; +import java.util.Hashtable; import thaw.gui.Table; @@ -134,7 +134,7 @@ /** for the thread tree **/ private MessageNodeTree messageNodeTree; - private HashMap messageNodeHashMap; + private Hashtable messageNodeHashtable; public MessageTreeTable(MiniFrostPanel mainPanel) { @@ -431,7 +431,7 @@ /** * will register */ - public void setParent(HashMap messageNodes) { + public void setParent(Hashtable messageNodes) { String inReplyTo; if (msg != null && (inReplyTo = msg.getInReplyToId()) != null) { @@ -780,20 +780,22 @@ if (seeTree.isSelected()) { - /** Filling in messageNodeHashMap **/ - messageNodeHashMap = new HashMap(msgs.size()); + /** Filling in messageNodeHashtable **/ + messageNodeHashtable = new Hashtable(msgs.size()); - for (Iterator it = msgs.iterator(); - it.hasNext();) { - MessageNode node = (MessageNode)it.next(); - messageNodeHashMap.put(node.getMessage().getMsgId(), node); - } + synchronized(messageNodeHashtable) { + for (Iterator it = msgs.iterator(); + it.hasNext();) { + MessageNode node = (MessageNode)it.next(); + messageNodeHashtable.put(node.getMessage().getMsgId(), node); + } - /** Building the tree **/ - for (Iterator it = msgs.iterator(); - it.hasNext();) { - ((MessageNode)it.next()).setParent(messageNodeHashMap); + /** Building the tree **/ + for (Iterator it = msgs.iterator(); + it.hasNext();) { + ((MessageNode)it.next()).setParent(messageNodeHashtable); + } } /** we search the nodes who should have a parent but haven't **/ From jflesch at freenetproject.org Thu Aug 2 13:15:56 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 13:15:56 +0000 (UTC) Subject: [Thaw-dev] r14464 - trunk/apps/Thaw/src/thaw/plugins/miniFrost Message-ID: <20070802131556.4135F4798D4@freenetproject.org> Author: jflesch Date: 2007-08-02 13:15:55 +0000 (Thu, 02 Aug 2007) New Revision: 14464 Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java Log: Synchronize the whole MessageTreePanel.refresh() "just to be sure" Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 13:07:27 UTC (rev 14463) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 13:15:55 UTC (rev 14464) @@ -134,7 +134,6 @@ /** for the thread tree **/ private MessageNodeTree messageNodeTree; - private Hashtable messageNodeHashtable; public MessageTreeTable(MiniFrostPanel mainPanel) { @@ -736,7 +735,7 @@ - public void refresh(String[] keywords, int orderBy, boolean desc, boolean allBoards) { + public synchronized void refresh(String[] keywords, int orderBy, boolean desc, boolean allBoards) { Vector msgs = null; if ((!allBoards) && targetBoard != null) { @@ -781,7 +780,7 @@ if (seeTree.isSelected()) { /** Filling in messageNodeHashtable **/ - messageNodeHashtable = new Hashtable(msgs.size()); + Hashtable messageNodeHashtable = new Hashtable(msgs.size()); synchronized(messageNodeHashtable) { for (Iterator it = msgs.iterator(); From jflesch at freenetproject.org Thu Aug 2 14:37:49 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 14:37:49 +0000 (UTC) Subject: [Thaw-dev] r14465 - in trunk/apps/Thaw/src/thaw: fcp plugins/miniFrost Message-ID: <20070802143749.49D1547AACA@freenetproject.org> Author: jflesch Date: 2007-08-02 14:37:49 +0000 (Thu, 02 Aug 2007) New Revision: 14465 Modified: trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java Log: Multithread the FCP message processings seems to solve the freeze problem (don't ask me why) Modified: trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java =================================================================== --- trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2007-08-02 13:15:55 UTC (rev 14464) +++ trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2007-08-02 14:37:49 UTC (rev 14465) @@ -211,7 +211,7 @@ /** * Doesn't check the lock state ! You have to manage it yourself. */ - public boolean rawWrite(final byte[] data) { + public synchronized boolean rawWrite(final byte[] data) { if(bufferedOut != null) return bufferedOut.write(data); else { @@ -224,7 +224,7 @@ /** * Should be call by FCPBufferedStream. Not you. */ - public boolean realRawWrite(final byte[] data) { + public synchronized boolean realRawWrite(final byte[] data) { if((out != null) && (socket != null) && socket.isConnected()) { try { lastWrite = System.currentTimeMillis(); Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java =================================================================== --- trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2007-08-02 13:15:55 UTC (rev 14464) +++ trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2007-08-02 14:37:49 UTC (rev 14465) @@ -13,12 +13,10 @@ private Thread me; private FCPConnection connection; - private FCPMessage latestMessage; public FCPQueryManager(final FCPConnection connection) { me = null; - latestMessage = null; setConnection(connection); } @@ -94,25 +92,93 @@ } + public class Notifier implements Runnable { + FCPMessage msg; + + public Notifier(FCPMessage msg) { + this.msg = msg; + } + + public void run() { + try { + setChanged(); + notifyObservers(msg); + } catch(final Exception e) { + /* it's really bad ... because if data are waiting on the socket ... */ + Logger.error(this, "EXCEPTION FROM ONE OF LISTENER : "+e.toString()); + Logger.error(this, "ERROR : "+e.getMessage()); + e.printStackTrace(); + } + } + } + + + + public class WatchDog implements Runnable { + public final static int TIMEOUT = 5000; + + Runnable runnable; + + public WatchDog(Runnable runnable) { + this.runnable = runnable; + } + + private boolean isRunning(Thread th) { + return (th.getState() != Thread.State.TERMINATED); + } + + public void run() { + Thread th = new Thread(runnable); + th.start(); + + for (int i = 0 ; i < TIMEOUT && isRunning(th) ; i += 300) { + try { + Thread.sleep(100); + } catch(InterruptedException e) { + /* \_o< */ + } + } + + if (isRunning(th)) { + Logger.warning(this, "Notifier thread seems to be blocked !!"); + th.dumpStack(); + } + } + + } + /** + * Multithreading allow the use of a watchdog + */ + public final static boolean MULTITHREADED = true; + + /** * Will listen in loop for new incoming messages. */ public void run() { - while(true) { - latestMessage = readMessage(); + FCPMessage latestMessage = readMessage(); Logger.verbose(this, "Message received. Notifying observers"); if(latestMessage != null) { - try { - setChanged(); - this.notifyObservers(latestMessage); - } catch(final Exception e) { - /* it's really bad ... because if data are waiting on the socket ... */ - Logger.error(this, "EXCEPTION FROM ONE OF LISTENER : "+e.toString()); - Logger.error(this, "ERROR : "+e.getMessage()); - e.printStackTrace(); + /* + * can't multithread if data are waiting + */ + if (MULTITHREADED && latestMessage.getAmountOfDataWaiting() == 0) { + Thread notifierTh = new Thread(new WatchDog(new Notifier(latestMessage))); + notifierTh.start(); + } else { + try { + setChanged(); + notifyObservers(latestMessage); + } catch(final Exception e) { + /* it's really bad ... because if data are waiting on the socket ... */ + Logger.error(this, "EXCEPTION FROM ONE OF LISTENER : "+e.toString()); + Logger.error(this, "ERROR : "+e.getMessage()); + e.printStackTrace(); + } + } } else { Logger.info(this, "Stopping listening"); Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 13:15:55 UTC (rev 14464) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 14:37:49 UTC (rev 14465) @@ -76,7 +76,12 @@ MouseListener, ActionListener { + /** + * Just here to avoid an infinite recursion + */ + public final static int MAX_DEPTH = 30; + public final static String[] COLUMNS = { "", /* checkboxes */ I18n.getMessage("thaw.plugin.miniFrost.subject"), @@ -718,7 +723,7 @@ if (node instanceof MessageNode) msgs.add(node); - if (depth >= 15) { + if (depth >= MAX_DEPTH) { Logger.notice(this, "Too much depths, sorry"); return false; } @@ -773,7 +778,7 @@ msgs = new Vector(); } - Logger.info(this, "Nmb msgs in the tree : "+Integer.toString(msgs.size())); + Logger.info(this, "Nmb msgs in the tree (before) : "+Integer.toString(msgs.size())); Vector rootNodes; @@ -851,7 +856,7 @@ rebuildMsgList(msgs, rootNode, 0); - Logger.info(this, "Nmb msgs in the tree : "+Integer.toString(msgs.size())); + Logger.info(this, "Nmb msgs in the tree (after) : "+Integer.toString(msgs.size())); model.setMessages(msgs); From jflesch at freenetproject.org Thu Aug 2 14:41:13 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 14:41:13 +0000 (UTC) Subject: [Thaw-dev] r14466 - trunk/apps/Thaw/src/thaw/fcp Message-ID: <20070802144114.011634797E1@freenetproject.org> Author: jflesch Date: 2007-08-02 14:41:13 +0000 (Thu, 02 Aug 2007) New Revision: 14466 Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java Log: Fix the build Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java =================================================================== --- trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2007-08-02 14:37:49 UTC (rev 14465) +++ trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2007-08-02 14:41:13 UTC (rev 14466) @@ -124,7 +124,7 @@ } private boolean isRunning(Thread th) { - return (th.getState() != Thread.State.TERMINATED); + return (th.isAlive()); } public void run() { From jflesch at freenetproject.org Thu Aug 2 16:32:18 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 16:32:18 +0000 (UTC) Subject: [Thaw-dev] r14467 - in trunk/apps/Thaw/src/thaw: fcp plugins/miniFrost Message-ID: <20070802163218.2D58B47AAD7@freenetproject.org> Author: jflesch Date: 2007-08-02 16:32:17 +0000 (Thu, 02 Aug 2007) New Revision: 14467 Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java Log: Still trying to fix the deadlock bug Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java =================================================================== --- trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2007-08-02 14:41:13 UTC (rev 14466) +++ trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2007-08-02 16:32:17 UTC (rev 14467) @@ -139,9 +139,9 @@ } } - if (isRunning(th)) { - Logger.warning(this, "Notifier thread seems to be blocked !!"); - th.dumpStack(); + while (isRunning(th)) { + Logger.warning(this, "Notifier thread ('"+th.toString()+"') seems to be blocked !!"); + try { Thread.sleep(1000); } catch(InterruptedException e) { /* \_o< */ } } } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 14:41:13 UTC (rev 14466) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 16:32:17 UTC (rev 14467) @@ -685,7 +685,8 @@ } public void refresh(MessageNode msgNode) { - refresh(msgs.indexOf(msgNode)); + //refresh(msgs.indexOf(msgNode)); + refresh(); } public void refresh(int row) { @@ -740,7 +741,7 @@ - public synchronized void refresh(String[] keywords, int orderBy, boolean desc, boolean allBoards) { + public void refresh(String[] keywords, int orderBy, boolean desc, boolean allBoards) { Vector msgs = null; if ((!allBoards) && targetBoard != null) { From jflesch at freenetproject.org Thu Aug 2 18:57:48 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 18:57:48 +0000 (UTC) Subject: [Thaw-dev] r14468 - in trunk/apps/Thaw/src/thaw: i18n plugins plugins/miniFrost plugins/miniFrost/frostKSK plugins/miniFrost/interfaces Message-ID: <20070802185748.655E347AB1F@freenetproject.org> Author: jflesch Date: 2007-08-02 18:57:47 +0000 (Thu, 02 Aug 2007) New Revision: 14468 Modified: trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties trunk/apps/Thaw/src/thaw/i18n/thaw.properties trunk/apps/Thaw/src/thaw/plugins/MiniFrost.java trunk/apps/Thaw/src/thaw/plugins/ToolbarModifier.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MiniFrostConfigTab.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/interfaces/BoardFactory.java Log: Add an automatic cleaning of the database at each startup of Thaw Modified: trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties =================================================================== --- trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties 2007-08-02 16:32:17 UTC (rev 14467) +++ trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties 2007-08-02 18:57:47 UTC (rev 14468) @@ -601,3 +601,8 @@ thaw.plugin.miniFrost.modifyRegexp=Modifier les r?gles de filtrage thaw.plugin.miniFrost.seeTree=Voir les messages sous forme d'arbre +thaw.plugin.miniFrost.archiveAfter=Archiver automatiquement les messages apr?s: +thaw.plugin.miniFrost.deleteAfter=Effacer automatiquement les messages apr?s: + +thaw.plugin.miniFrost.days=jours + Modified: trunk/apps/Thaw/src/thaw/i18n/thaw.properties =================================================================== --- trunk/apps/Thaw/src/thaw/i18n/thaw.properties 2007-08-02 16:32:17 UTC (rev 14467) +++ trunk/apps/Thaw/src/thaw/i18n/thaw.properties 2007-08-02 18:57:47 UTC (rev 14468) @@ -619,3 +619,7 @@ thaw.plugin.miniFrost.modifyRegexp=Modify the filtering rules thaw.plugin.miniFrost.seeTree=See message tree + +thaw.plugin.miniFrost.archiveAfter=Automatically archive the messages after: +thaw.plugin.miniFrost.deleteAfter=Automatically delete the messages after: +thaw.plugin.miniFrost.days=days Modified: trunk/apps/Thaw/src/thaw/plugins/MiniFrost.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/MiniFrost.java 2007-08-02 16:32:17 UTC (rev 14467) +++ trunk/apps/Thaw/src/thaw/plugins/MiniFrost.java 2007-08-02 18:57:47 UTC (rev 14468) @@ -3,6 +3,7 @@ import thaw.core.I18n; import thaw.core.Core; import thaw.core.Logger; +import thaw.core.Config; import thaw.plugins.miniFrost.MiniFrostPanel; import thaw.plugins.miniFrost.interfaces.BoardFactory; @@ -13,6 +14,9 @@ public class MiniFrost implements thaw.core.Plugin { + public final static int DEFAULT_ARCHIVE_AFTER = 7; /* days */ + public final static int DEFAULT_DELETE_AFTER = 60; /* days */ + private Core core; private Hsqldb hsqldb; @@ -37,6 +41,7 @@ if (!loadDeps() || !initFactories() + || !cleanUp(core.getConfig()) || !loadGUI() || !loadAutoRefresh()) return false; @@ -90,6 +95,27 @@ } + protected boolean cleanUp(Config config) { + int archiveAfter = DEFAULT_ARCHIVE_AFTER; + int deleteAfter = DEFAULT_DELETE_AFTER; + + if (config.getValue("miniFrostArchiveAfter") != null) + archiveAfter = Integer.parseInt(config.getValue("miniFrostArchiveAfter")); + + if (config.getValue("miniFrostDeleteAfter") != null) + deleteAfter = Integer.parseInt(config.getValue("miniFrostDeleteAfter")); + + boolean b = true; + + for (int i = 0 ; i < factories.length ; i++) { + if (!factories[i].cleanUp(archiveAfter, deleteAfter)) + b = false; + } + + return b; + } + + protected boolean loadGUI() { miniFrostPanel = new MiniFrostPanel(core.getConfig(), hsqldb, this); Modified: trunk/apps/Thaw/src/thaw/plugins/ToolbarModifier.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/ToolbarModifier.java 2007-08-02 16:32:17 UTC (rev 14467) +++ trunk/apps/Thaw/src/thaw/plugins/ToolbarModifier.java 2007-08-02 18:57:47 UTC (rev 14468) @@ -40,6 +40,9 @@ * @param position if == -1, then the button is put at the end */ public void addButtonToTheToolbar(final JButton button, int position) { + if (button != null) + button.setBorderPainted(false); + if (position < 0) buttons.add(button); else { Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MiniFrostConfigTab.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MiniFrostConfigTab.java 2007-08-02 16:32:17 UTC (rev 14467) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MiniFrostConfigTab.java 2007-08-02 18:57:47 UTC (rev 14468) @@ -20,7 +20,9 @@ import thaw.core.Logger; import thaw.gui.IconBox; +import thaw.plugins.MiniFrost; + public class MiniFrostConfigTab implements Observer, ActionListener { private Config config; @@ -33,6 +35,14 @@ public final static int MAX_BOARDS = 30; private JComboBox maxBoards; + + public final static int MIN_DAYS = 0; + public final static int MAX_DAYS = 365; + + private JComboBox archiveAfter; + private JComboBox deleteAfter; + + private JButton regexpButton; @@ -50,11 +60,25 @@ for (int i = MIN_BOARDS ; i <= MAX_BOARDS ; i++) maxBoards.addItem(Integer.toString(i)); + archiveAfter = new JComboBox(); + deleteAfter = new JComboBox(); + + for (int i = MIN_DAYS ; i <= MAX_DAYS ; i++) { + archiveAfter.addItem(Integer.toString(i)+ " "+I18n.getMessage("thaw.plugin.miniFrost.days")); + deleteAfter.addItem( Integer.toString(i)+ " "+I18n.getMessage("thaw.plugin.miniFrost.days")); + } + selectValue(); panel.add(new JLabel(I18n.getMessage("thaw.plugin.miniFrost.maxBoardsRefreshed"))); panel.add(maxBoards); + panel.add(new JLabel(I18n.getMessage("thaw.plugin.miniFrost.archiveAfter"))); + panel.add(archiveAfter); + + panel.add(new JLabel(I18n.getMessage("thaw.plugin.miniFrost.deleteAfter"))); + panel.add(deleteAfter); + JPanel regexpPanel = new JPanel(new BorderLayout()); regexpPanel.add(new JLabel(""), BorderLayout.CENTER); regexpButton = new JButton(I18n.getMessage("thaw.plugin.miniFrost.modifyRegexp")); @@ -85,21 +109,53 @@ if (config.getValue("miniFrostAutoRefreshMaxBoards") != null) { max = Integer.parseInt(config.getValue("miniFrostAutoRefreshMaxBoards")); - Logger.info(this, "Max: "+Integer.toString(max)); + Logger.info(this, "Max boards: "+Integer.toString(max)); } else { max = AutoRefresh.DEFAULT_MAX_BOARDS_REFRESHING; } maxBoards.setSelectedIndex(max-MIN_BOARDS); + + + if (config.getValue("miniFrostArchiveAfter") != null) { + max = Integer.parseInt(config.getValue("miniFrostArchiveAfter")); + Logger.info(this, "Archive after: "+Integer.toString(max)); + } else { + max = MiniFrost.DEFAULT_ARCHIVE_AFTER; + } + + archiveAfter.setSelectedIndex(max-MIN_DAYS); + + + if (config.getValue("miniFrostDeleteAfter") != null) { + max = Integer.parseInt(config.getValue("miniFrostDeleteAfter")); + Logger.info(this, "Delete after: "+Integer.toString(max)); + } else { + max = MiniFrost.DEFAULT_DELETE_AFTER; + } + + deleteAfter.setSelectedIndex(max-MIN_DAYS); } + private String extractNumber(JComboBox box) { + String[] split = ((String)box.getSelectedItem()).split(" "); + return split[0]; + } + + public void update(Observable o, Object param) { if (param == configWindow.getOkButton()) { config.setValue("miniFrostAutoRefreshMaxBoards", (String)maxBoards.getSelectedItem()); + config.setValue("miniFrostArchiveAfter", + extractNumber(archiveAfter)); + + config.setValue("miniFrostDeleteAfter", + extractNumber(deleteAfter)); + } else if (param == configWindow.getCancelButton()) { selectValue(); Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java 2007-08-02 16:32:17 UTC (rev 14467) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java 2007-08-02 18:57:47 UTC (rev 14468) @@ -74,6 +74,33 @@ return true; } + + public boolean cleanUp(int archiveAfter, int deleteAfter) { + try { + synchronized(db.dbLock) { + PreparedStatement st; + + java.sql.Timestamp timestamp = new java.sql.Timestamp(new Date().getTime() - (deleteAfter * 24 * 60*60*1000)); + + st = db.getConnection().prepareStatement("DELETE from frostKSKMessages WHERE date < ?"); + st.setTimestamp(1, timestamp); + st.execute(); + + + timestamp = new java.sql.Timestamp(new Date().getTime() - (archiveAfter * 24 * 60*60*1000)); + + st = db.getConnection().prepareStatement("UPDATE frostKSKMessages SET archived = TRUE WHERE date < ?"); + st.setTimestamp(1, timestamp); + st.execute(); + } + } catch(SQLException e) { + Logger.error(this, "Can't cleanup the db because : "+e.toString()); + } + + return true; + } + + public MiniFrost getPlugin() { return plugin; } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/interfaces/BoardFactory.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/interfaces/BoardFactory.java 2007-08-02 16:32:17 UTC (rev 14467) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/interfaces/BoardFactory.java 2007-08-02 18:57:47 UTC (rev 14468) @@ -17,6 +17,8 @@ MiniFrost miniFrost); + public boolean cleanUp(int archiveAfter, int deleteAfter); + /** * @return all the boards managed by this factory */ From jflesch at freenetproject.org Thu Aug 2 19:31:57 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Thu, 2 Aug 2007 19:31:57 +0000 (UTC) Subject: [Thaw-dev] r14469 - in trunk/apps/Thaw/src/thaw: fcp plugins/miniFrost/frostKSK Message-ID: <20070802193157.8F45047AAF6@freenetproject.org> Author: jflesch Date: 2007-08-02 19:31:57 +0000 (Thu, 02 Aug 2007) New Revision: 14469 Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java Log: Make the distinction between the date in the messages and in the message keys Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java =================================================================== --- trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2007-08-02 18:57:47 UTC (rev 14468) +++ trunk/apps/Thaw/src/thaw/fcp/FCPQueryManager.java 2007-08-02 19:31:57 UTC (rev 14469) @@ -141,7 +141,7 @@ while (isRunning(th)) { Logger.warning(this, "Notifier thread ('"+th.toString()+"') seems to be blocked !!"); - try { Thread.sleep(1000); } catch(InterruptedException e) { /* \_o< */ } + try { Thread.sleep(TIMEOUT); } catch(InterruptedException e) { /* \_o< */ } } } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java 2007-08-02 18:57:47 UTC (rev 14468) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java 2007-08-02 19:31:57 UTC (rev 14469) @@ -403,7 +403,7 @@ protected int getNextNonDownloadedRev(Date daDate, int rev) { daDate = getMidnight(daDate); - java.sql.Timestamp date = new java.sql.Timestamp(daDate.getTime()); + java.sql.Date date = new java.sql.Date(daDate.getTime()); try { @@ -413,12 +413,11 @@ PreparedStatement st; st = db.getConnection().prepareStatement("SELECT rev FROM frostKSKMessages "+ - "WHERE date >= ? AND date < ? "+ + "WHERE keyDate = ? "+ "AND rev > ? AND boardId = ? ORDER by rev"); - st.setTimestamp(1, date); - st.setTimestamp(2, new java.sql.Timestamp(date.getTime() + 24*60*60*1000)); - st.setInt( 3, rev); - st.setInt(4, id); + st.setDate(1, date); + st.setInt( 2, rev); + st.setInt(3, id); ResultSet set = st.executeQuery(); @@ -447,7 +446,7 @@ protected int getLastDownloadedRev(Date daDate) { daDate = getMidnight(daDate); - java.sql.Timestamp date = new java.sql.Timestamp(daDate.getTime()); + java.sql.Date date = new java.sql.Date(daDate.getTime()); try { @@ -457,13 +456,12 @@ PreparedStatement st; st = db.getConnection().prepareStatement("SELECT rev FROM frostKSKMessages "+ - "WHERE date >= ? AND date < ? "+ + "WHERE keyDate = ? "+ "AND boardId = ? "+ "ORDER by rev DESC "+ "LIMIT 1"); - st.setTimestamp(1, date); - st.setTimestamp(2, new java.sql.Timestamp(date.getTime() + 24*60*60*1000)); - st.setInt(3, id); + st.setDate(1, date); + st.setInt(2, id); ResultSet set = st.executeQuery(); @@ -538,7 +536,7 @@ st = db.getConnection().prepareStatement("UPDATE frostKSKBoards "+ "SET lastUpdate = ? "+ "WHERE id = ?"); - st.setTimestamp(1, new java.sql.Timestamp(new java.util.Date().getTime())); + st.setDate(1, new java.sql.Date(new java.util.Date().getTime())); st.setInt(2, id); st.execute(); } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java 2007-08-02 18:57:47 UTC (rev 14468) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoardFactory.java 2007-08-02 19:31:57 UTC (rev 14469) @@ -137,6 +137,14 @@ if (convertDatabase_0_to_1()) core.getConfig().setValue("frostKSKDatabaseVersion", "2"); } + + /* due to a stupid mistake, the rev 1 will never really exist */ + + if ("1".equals(core.getConfig().getValue("frostKSKDatabaseVersion")) + || "2".equals(core.getConfig().getValue("frostKSKDatabaseVersion"))) { + if (convertDatabase_2_to_3()) + core.getConfig().setValue("frostKSKDatabaseVersion", "3"); + } } protected boolean convertDatabase_0_to_1() { @@ -155,10 +163,43 @@ return true; } + protected boolean convertDatabase_2_to_3() { + if (!sendQuery("ALTER TABLE frostKSKMessages ADD COLUMN keyDate DATE DEFAULT NULL NULL")) { + Logger.error(this, "Error while converting the board database from version 2 to 3"); + return false; + } + try { + synchronized(db.dbLock) { + PreparedStatement st; + + st = db.getConnection().prepareStatement("SELECT id, date FROM frostKSKMessages"); + + ResultSet set = st.executeQuery(); + + st = db.getConnection().prepareStatement("UPDATE frostKSKMessages SET keyDate = ? WHERE id = ?"); + + while (set.next()) { + int id = set.getInt("id"); + java.sql.Timestamp timestamp = set.getTimestamp("date"); + java.sql.Date date = new java.sql.Date(timestamp.getTime()); + + st.setDate(1, date); + st.setInt(2, id); + st.execute(); + } + } + } catch(SQLException e) { + Logger.error(this, "Error while converting the board database from version 2 to 3: "+e.toString()); + } + + return true; + } + + protected void createTables() { - if (core.getConfig().getValue("frostKSKDatabaseVersion") != null) - core.getConfig().setValue("frostKSKDatabaseVersion", "1"); + if (core.getConfig().getValue("frostKSKDatabaseVersion") == null) + core.getConfig().setValue("frostKSKDatabaseVersion", "3"); sendQuery("CREATE CACHED TABLE frostKSKBoards (" + "id INTEGER IDENTITY NOT NULL, " @@ -178,6 +219,7 @@ + "nick VARCHAR(128) NOT NULL, " + "sigId INTEGER NULL, " + "content VARCHAR(32768) NOT NULL, " + + "keyDate DATE NOT NULL, " + "date TIMESTAMP NOT NULL, " + "msgId VARCHAR(128) NOT NULL, " + "inReplyToId VARCHAR(128) NULL, " Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java 2007-08-02 18:57:47 UTC (rev 14468) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKMessageParser.java 2007-08-02 19:31:57 UTC (rev 14469) @@ -178,14 +178,16 @@ } - java.sql.Timestamp dateSql; + java.sql.Timestamp timestampSql; if (dateUtil != null) - dateSql = new java.sql.Timestamp(dateUtil.getTime()); + timestampSql = new java.sql.Timestamp(dateUtil.getTime()); else - dateSql = new java.sql.Timestamp(boardDate.getTime()); + timestampSql = new java.sql.Timestamp(boardDate.getTime()); + java.sql.Date dateSql = new java.sql.Date(boardDate.getTime()); + int replyToId = -1; try { @@ -213,10 +215,12 @@ st = db.getConnection().prepareStatement("INSERT INTO frostKSKMessages ("+ "subject, nick, sigId, content, "+ "date, msgId, inReplyTo, inReplyToId, "+ - "rev, read, archived, encryptedFor, boardId) VALUES ("+ + "rev, keyDate, read, archived, "+ + "encryptedFor, boardId) VALUES ("+ "?, ?, ?, ?, "+ "?, ?, ?, ?, "+ - "?, ?, ?, ?, ?)"); + "?, ?, ?, ?, "+ + "?, ?)"); st.setString(1, subject); st.setString(2, from); /* nick */ if (identity != null) @@ -224,7 +228,7 @@ else st.setNull(3, Types.INTEGER); st.setString(4, body); /* content */ - st.setTimestamp(5, dateSql); + st.setTimestamp(5, timestampSql); st.setString(6, messageId); if (replyToId >= 0) @@ -239,15 +243,17 @@ st.setInt(9, rev); - st.setBoolean(10, read); - st.setBoolean(11, archived); + st.setDate(10, dateSql); + st.setBoolean(11, read); + st.setBoolean(12, archived); + if (encryptedFor == null) - st.setNull(12, Types.INTEGER); + st.setNull(13, Types.INTEGER); else - st.setInt(12, encryptedFor.getId()); + st.setInt(13, encryptedFor.getId()); - st.setInt(13, boardId); + st.setInt(14, boardId); st.execute(); From jflesch at freenetproject.org Fri Aug 3 01:17:30 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Fri, 3 Aug 2007 01:17:30 +0000 (UTC) Subject: [Thaw-dev] r14472 - trunk/apps/Thaw/src/thaw/plugins/miniFrost Message-ID: <20070803011730.4F220479845@freenetproject.org> Author: jflesch Date: 2007-08-03 01:17:29 +0000 (Fri, 03 Aug 2007) New Revision: 14472 Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/BoardTree.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java Log: Synchronize the access to the board list and to the message list (once again to try to prevent a possible freeze) Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/BoardTree.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/BoardTree.java 2007-08-02 22:07:29 UTC (rev 14471) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/BoardTree.java 2007-08-03 01:17:29 UTC (rev 14472) @@ -204,7 +204,9 @@ } public Vector getBoardList() { - return boardList; + synchronized(boardList) { + return boardList; + } } public void setBoardList(Vector l) { @@ -216,17 +218,21 @@ boardList = l; - if (boardList.size() < oldSize) - fireIntervalRemoved(this, boardList.size(), oldSize); + synchronized(boardList) { + if (boardList.size() < oldSize) + fireIntervalRemoved(this, boardList.size(), oldSize); - if (boardList.size() > oldSize) - fireIntervalAdded(this, oldSize, boardList.size()); + if (boardList.size() > oldSize) + fireIntervalAdded(this, oldSize, boardList.size()); - fireContentsChanged(this, 0, boardList.size()); + fireContentsChanged(this, 0, boardList.size()); + } } public void refresh(Board board) { - refresh(boardList.indexOf(board)); + synchronized(boardList) { + refresh(boardList.indexOf(board)); + } } public void refresh(int row) { @@ -237,14 +243,18 @@ if (boardList == null) return null; - return boardList.get(index); + synchronized(boardList) { + return boardList.get(index); + } } public int getSize() { if (boardList == null) return 0; - return boardList.size(); + synchronized(boardList) { + return boardList.size(); + } } } Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-02 22:07:29 UTC (rev 14471) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/MessageTreeTable.java 2007-08-03 01:17:29 UTC (rev 14472) @@ -381,7 +381,9 @@ } public Enumeration children() { - return children.elements(); + synchronized(children) { /* yep, quite useless */ + return children.elements(); + } } public boolean getAllowsChildren() { @@ -389,15 +391,21 @@ } public TreeNode getChildAt(int childIndex) { - return (MessageNode)children.get(childIndex); + synchronized(children) { + return (MessageNode)children.get(childIndex); + } } public int getChildCount() { - return children.size(); + synchronized(children) { + return children.size(); + } } public int getIndex(TreeNode node) { - return children.indexOf(node); + synchronized(children) { + return children.indexOf(node); + } } public TreeNode getParent() { @@ -405,7 +413,9 @@ } public boolean isLeaf() { - return (children.size() == 0); + synchronized(children) { + return (children.size() == 0); + } } } @@ -455,11 +465,15 @@ } public void registerChild(MessageNode node) { - children.insertElementAt(node, 0); + synchronized(children) { + children.insertElementAt(node, 0); + } } public java.util.Enumeration children() { - return children.elements(); + synchronized(children) { + return children.elements(); + } } public boolean getAllowsChildren() { @@ -467,15 +481,21 @@ } public TreeNode getChildAt(int childIndex) { - return (MessageNode)children.get(childIndex); + synchronized(children) { + return (MessageNode)children.get(childIndex); + } } public int getChildCount() { - return children.size(); + synchronized(children) { + return children.size(); + } } public int getIndex(TreeNode node) { - return children.indexOf(node); + synchronized(children) { + return children.indexOf(node); + } } public TreeNode getParent() { @@ -483,7 +503,9 @@ } public boolean isLeaf() { - return (children.size() == 0); + synchronized(children) { + return (children.size() == 0); + } } public String toString() { @@ -591,7 +613,9 @@ public int getRowCount() { if (msgs == null) return 0; - return msgs.size(); + synchronized(msgs) { + return msgs.size(); + } } public int getColumnCount() { @@ -603,7 +627,9 @@ } public Message getMsg(int row) { - return ((MessageNode)msgs.get(row)).getMessage(); + synchronized(msgs) { + return ((MessageNode)msgs.get(row)).getMessage(); + } } public Object getValueAt(int row, int column) { @@ -612,11 +638,17 @@ } if (column == 1) { - return (MessageNode)msgs.get(row); + synchronized(msgs) { + return (MessageNode)msgs.get(row); + } } - Message msg = ((MessageNode)msgs.get(row)).getMessage(); + Message msg; + synchronized(msgs) { + msg = ((MessageNode)msgs.get(row)).getMessage(); + } + if (msg == null) return "(?)"; @@ -642,8 +674,12 @@ public void setMessages(Vector msgs) { this.msgs = msgs; - int lng = msgs.size(); + int lng = 0; + synchronized(msgs) { + lng = msgs.size(); + } + selection = new boolean[lng]; for (int i = 0 ; i < lng ; i++) @@ -652,11 +688,13 @@ public void setSelectedAll(boolean s) { - for (int i = 0 ; i < selection.length ; i++) { - Message msg = ((MessageNode)msgs.get(i)).getMessage(); + synchronized(msgs) { + for (int i = 0 ; i < selection.length ; i++) { + Message msg = ((MessageNode)msgs.get(i)).getMessage(); - if (msg != null) - selection[i] = s; + if (msg != null) + selection[i] = s; + } } } @@ -667,8 +705,12 @@ public void switchSelection(int row) { - Message msg = ((MessageNode)msgs.get(row)).getMessage(); + Message msg = null; + synchronized(msgs) { + msg = ((MessageNode)msgs.get(row)).getMessage(); + } + if (msg != null) selection[row] = !selection[row]; else From jflesch at freenetproject.org Fri Aug 3 03:30:22 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Fri, 3 Aug 2007 03:30:22 +0000 (UTC) Subject: [Thaw-dev] r14473 - in trunk/apps/Thaw/src/thaw/plugins: . miniFrost Message-ID: <20070803033022.7EA9747A033@freenetproject.org> Author: jflesch Date: 2007-08-03 03:30:21 +0000 (Fri, 03 Aug 2007) New Revision: 14473 Modified: trunk/apps/Thaw/src/thaw/plugins/MiniFrost.java trunk/apps/Thaw/src/thaw/plugins/miniFrost/AutoRefresh.java Log: Fix this deadlock once for all Modified: trunk/apps/Thaw/src/thaw/plugins/MiniFrost.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/MiniFrost.java 2007-08-03 01:17:29 UTC (rev 14472) +++ trunk/apps/Thaw/src/thaw/plugins/MiniFrost.java 2007-08-03 03:30:21 UTC (rev 14473) @@ -14,7 +14,7 @@ public class MiniFrost implements thaw.core.Plugin { - public final static int DEFAULT_ARCHIVE_AFTER = 7; /* days */ + public final static int DEFAULT_ARCHIVE_AFTER = 15; /* days */ public final static int DEFAULT_DELETE_AFTER = 60; /* days */ private Core core; Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/AutoRefresh.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/miniFrost/AutoRefresh.java 2007-08-03 01:17:29 UTC (rev 14472) +++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/AutoRefresh.java 2007-08-03 03:30:21 UTC (rev 14473) @@ -115,9 +115,11 @@ if (!run) return; - synchronized(boardTree.getBoards()) { + try { if (canRefreshAnotherOne()) refreshAnotherOne(); + } catch(Exception e) { + Logger.error(this, "Error while autorefreshing : "+e.toString()); } } } From jflesch at freenetproject.org Fri Aug 3 03:39:37 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Fri, 3 Aug 2007 03:39:37 +0000 (UTC) Subject: [Thaw-dev] r14474 - trunk/apps/Thaw/src/thaw/fcp Message-ID: <20070803033937.642C84796C1@freenetproject.org> Author: jflesch Date: 2007-08-03 03:39:36 +0000 (Fri, 03 Aug 2007) New Revision: 14474 Modified: trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java Log: Reduce the log verbosity when disconnected from the node Modified: trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java =================================================================== --- trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2007-08-03 03:30:21 UTC (rev 14473) +++ trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2007-08-03 03:39:36 UTC (rev 14474) @@ -238,7 +238,7 @@ return false; } } else { - Logger.warning(this, "Cannot write if disconnected !"); + Logger.notice(this, "Cannot write if disconnected !"); return false; } @@ -303,7 +303,7 @@ bufferedOut.write(toWrite.getBytes()); } } else { - Logger.warning(this, "Cannot write if disconnected !"); + Logger.notice(this, "Cannot write if disconnected !"); if (checkLock) removeFromWriterQueue(); return false; @@ -451,7 +451,7 @@ return null; } } else { - Logger.warning(this, "Cannot read if disconnected => null"); + Logger.notice(this, "Cannot read if disconnected => null"); } return null; From jflesch at freenetproject.org Fri Aug 3 17:40:47 2007 From: jflesch at freenetproject.org (jflesch at freenetproject.org) Date: Fri, 3 Aug 2007 17:40:47 +0000 (UTC) Subject: [Thaw-dev] r14475 - in trunk/apps/Thaw/src/thaw: fcp plugins plugins/index Message-ID: <20070803174047.030CF4797E1@freenetproject.org> Author: jflesch Date: 2007-08-03 17:40:46 +0000 (Fri, 03 Aug 2007) New Revision: 14475 Added: trunk/apps/Thaw/src/thaw/plugins/index/FileContainer.java trunk/apps/Thaw/src/thaw/plugins/index/IndexContainer.java trunk/apps/Thaw/src/thaw/plugins/index/IndexParser.java trunk/apps/Thaw/src/thaw/plugins/index/LinkContainer.java Modified: trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java trunk/apps/Thaw/src/thaw/plugins/TrayIcon.java trunk/apps/Thaw/src/thaw/plugins/index/DatabaseManager.java trunk/apps/Thaw/src/thaw/plugins/index/File.java trunk/apps/Thaw/src/thaw/plugins/index/Index.java trunk/apps/Thaw/src/thaw/plugins/index/IndexManagementHelper.java trunk/apps/Thaw/src/thaw/plugins/index/Link.java Log: Separate the index parsing from the index storage Modified: trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java =================================================================== --- trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2007-08-03 03:39:36 UTC (rev 14474) +++ trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -372,8 +372,7 @@ /* SECURITY */ if(rawBytesWaiting > 0) { - Logger.error(this, "RAW BYTES STILL WAITING ON SOCKET. THIS IS ABNORMAL."); - Logger.error(this, "Will drop them."); + Logger.warning(this, "RAW BYTES STILL WAITING ON SOCKET. THIS IS ABNORMAL. : Will drop them."); while(rawBytesWaiting > 0) { int to_read = 1024; Modified: trunk/apps/Thaw/src/thaw/plugins/TrayIcon.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/TrayIcon.java 2007-08-03 03:39:36 UTC (rev 14474) +++ trunk/apps/Thaw/src/thaw/plugins/TrayIcon.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -149,8 +149,7 @@ public String getNameForUser() { - return I18n.getMessage("thaw.plugin.trayIcon.pluginName") - + " "+I18n.getMessage("thaw.common.unstable.linux"); + return I18n.getMessage("thaw.plugin.trayIcon.pluginName"); } public javax.swing.ImageIcon getIcon() { Modified: trunk/apps/Thaw/src/thaw/plugins/index/DatabaseManager.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/index/DatabaseManager.java 2007-08-03 03:39:36 UTC (rev 14474) +++ trunk/apps/Thaw/src/thaw/plugins/index/DatabaseManager.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -527,7 +527,7 @@ * if null, then not in an index * else all the tag found will be sent to this handler */ - private Index.IndexHandler indexHandler = null; + private IndexParser.IndexHandler indexHandler = null; /** @@ -575,7 +575,7 @@ if (index != null) { index.rename(attrs.getValue("displayName")); - indexHandler = index.getIndexHandler(); + indexHandler = new IndexParser(index).getIndexHandler(); indexHandler.startDocument(); } Modified: trunk/apps/Thaw/src/thaw/plugins/index/File.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/index/File.java 2007-08-03 03:39:36 UTC (rev 14474) +++ trunk/apps/Thaw/src/thaw/plugins/index/File.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -26,7 +26,7 @@ import thaw.plugins.Hsqldb; -public class File implements Observer { +public class File implements Observer, FileContainer { private Hsqldb db = null; private int id = -1; /* -1 = undefined */ @@ -175,6 +175,11 @@ return res; } + + public String getMime() { + return mime; + } + public long getSize() { return size; } Added: trunk/apps/Thaw/src/thaw/plugins/index/FileContainer.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/index/FileContainer.java (rev 0) +++ trunk/apps/Thaw/src/thaw/plugins/index/FileContainer.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -0,0 +1,19 @@ +package thaw.plugins.index; + +public interface FileContainer { + + public String getFilename(); + + /** + * @return if the result is not a valid key, it won't be added to the index + */ + public String getPublicKey(); + + public long getSize(); + + /** + * @return null if null, the mime type will be guessed from the filename + */ + public String getMime(); + +} Modified: trunk/apps/Thaw/src/thaw/plugins/index/Index.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/index/Index.java 2007-08-03 03:39:36 UTC (rev 14474) +++ trunk/apps/Thaw/src/thaw/plugins/index/Index.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -22,40 +22,11 @@ import javax.swing.tree.TreePath; - -/* DOM */ - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; -/* SAX */ - -import org.xml.sax.*; -import org.xml.sax.helpers.LocatorImpl; - -import java.io.IOException; - -import org.xml.sax.helpers.XMLReaderFactory; -import org.xml.sax.helpers.DefaultHandler; - -import javax.xml.parsers.SAXParserFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; - import thaw.core.Main; import thaw.core.I18n; @@ -76,7 +47,11 @@ -public class Index extends Observable implements MutableTreeNode, FileAndLinkList, IndexTreeNode, Observer { +public class Index extends Observable implements MutableTreeNode, + IndexTreeNode, + Observer, + IndexContainer { + private final static long MAX_SIZE = 5242880; /* 5MB */ @@ -105,8 +80,6 @@ private Config config; - public final static String DATE_FORMAT = "yyyyMMdd"; - /** * @deprecated Just don't use it ! */ @@ -439,7 +412,7 @@ } - public boolean getPublishPrivateKey() { + public boolean publishPrivateKey() { try { PreparedStatement st @@ -669,7 +642,7 @@ /* Let's hope that users are not stupid - * and won't insert 5 revisions at once. */ + * and won't insert too much revisions at once. */ /* if (indexBrowser != null && indexBrowser.getIndexTree() != null && indexBrowser.getIndexTree().isIndexUpdating(this)) { @@ -696,7 +669,9 @@ Logger.info(this, "Generating index ..."); - if (!generateXML(targetFile.getAbsolutePath())) + IndexParser parser = new IndexParser(this); + + if (!parser.generateXML(targetFile.getAbsolutePath())) return 0; FCPClientPut put; @@ -894,8 +869,10 @@ String path = get.getPath(); if (path != null) { - loadXML(path); + IndexParser parser = new IndexParser(this); + parser.loadXML(path); + boolean loadComm = true; if (config != null && config.getValue("indexFetchComments") != null) @@ -993,8 +970,88 @@ } + public void purgeIndex() { + purgeFileList(); + purgeLinkList(); + purgeCommentKeys(); + } + + + + public void setInsertionDate(java.util.Date date) { + try { + synchronized(db.dbLock) { + java.sql.Date dateSql = null; + dateSql = new java.sql.Date(date.getTime()); + + PreparedStatement st = + db.getConnection().prepareStatement("UPDATE indexes "+ + "SET insertionDate = ? "+ + "WHERE id = ?"); + st.setDate(1, dateSql); + st.setInt(2, id); + + st.execute(); + } + } catch(SQLException e) { + Logger.error(this, "Error while updating index insertion date: "+e.toString()); + } + } + + + + ////// Comments black list ////// + public Vector getCommentBlacklistedRev() { + Vector v = new Vector(); + + try { + synchronized(db.dbLock) { + PreparedStatement st; + + st = db.getConnection().prepareStatement("SELECT rev "+ + "FROM indexCommentBlackList "+ + "WHERE indexId = ?"); + st.setInt(1, id); + + ResultSet set = st.executeQuery(); + + while (set.next()) { + v.add(new Integer(set.getInt("rev"))); + } + } + } catch(SQLException e) { + Logger.error(this, "Unable to get comment black list because: "+e.toString()); + } + + return v; + } + + + public void addBlackListedRev(int rev) { + try { + synchronized(db.dbLock) { + PreparedStatement st; + + st = db.getConnection().prepareStatement("INSERT into indexCommentBlackList (rev, indexId) VALUES (?, ?)"); + st.setInt(1, rev); + st.setInt(2, id); + + st.execute(); + + } + } catch(SQLException e) { + Logger.error(this, "Error while adding element to the blackList: "+e.toString()); + } + + } + + ////// FILE LIST //////// + public Vector getFileList() { + return getFileList(null, false); + } + public Vector getFileList(String columnToSort, boolean asc) { synchronized(db.dbLock) { @@ -1041,8 +1098,41 @@ } + public void addFile(String key, long size, String mime) { + try { + synchronized(db.dbLock) { + PreparedStatement st; + + st = db.getConnection().prepareStatement("INSERT INTO files " + + "(filename, publicKey, localPath, mime, size, category, indexParent) " + + "VALUES (?, ?, NULL, ?, ?, NULL, ?)"); + + + String filename = FreenetURIHelper.getFilenameFromKey(key); + if (filename == null) + filename = key; + + st.setString(1, filename); + st.setString(2, key); + st.setString(3, mime); + st.setLong(4, size); + st.setInt(5, id); + + st.execute(); + } + } catch(SQLException e) { + Logger.error(this, "Error while adding file to index '"+toString()+"' : "+e.toString()); + } + } + + + //// LINKS //// + public Vector getLinkList() { + return getLinkList(null, false); + } + public Vector getLinkList(String columnToSort, boolean asc) { synchronized(db.dbLock) { @@ -1051,7 +1141,8 @@ PreparedStatement st; - st = db.getConnection().prepareStatement("SELECT id, publicKey, blackListed FROM links WHERE indexParent = ?"); + st = db.getConnection().prepareStatement("SELECT id, publicKey, blackListed "+ + "FROM links WHERE indexParent = ?"); st.setInt(1, id); @@ -1074,704 +1165,89 @@ return null; } - //// XML //// - public boolean generateXML(String path) { - try { - generateXML(new FileOutputStream(new File(path))); - return true; - } catch(java.io.FileNotFoundException e) { - Logger.error(this, "File not found exception ?!"); - } - return false; - } - public void generateXML(final OutputStream out) { - StreamResult streamResult; + public static String getNameFromKey(final String key) { + String name = null; - streamResult = new StreamResult(out); + name = FreenetURIHelper.getFilenameFromKey(key); - Document xmlDoc; + if (name == null) + return null; - final DocumentBuilderFactory xmlFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder xmlBuilder; + /* quick and dirty */ + name = name.replaceAll(".xml", ""); + name = name.replaceAll(".frdx", ""); - try { - xmlBuilder = xmlFactory.newDocumentBuilder(); - } catch(final javax.xml.parsers.ParserConfigurationException e) { - Logger.error(this, "Unable to generate the index because : "+e.toString()); - return; - } + return name; + } - final DOMImplementation impl = xmlBuilder.getDOMImplementation(); - xmlDoc = impl.createDocument(null, "index", null); - - final Element rootEl = xmlDoc.getDocumentElement(); - - fillInRootElement(rootEl, xmlDoc); - - /* Serialization */ - final DOMSource domSource = new DOMSource(xmlDoc); - final TransformerFactory transformFactory = TransformerFactory.newInstance(); - - Transformer serializer; - + public void addLink(String key) { try { - serializer = transformFactory.newTransformer(); - } catch(final javax.xml.transform.TransformerConfigurationException e) { - Logger.error(this, "Unable to save index because: "+e.toString()); - return; - } + if (key == null) /* it was the beginning of the index */ + return; - serializer.setOutputProperty(OutputKeys.ENCODING,"UTF-8"); - serializer.setOutputProperty(OutputKeys.INDENT,"yes"); + key = key.trim(); - /* final step */ - try { - serializer.transform(domSource, streamResult); - } catch(final javax.xml.transform.TransformerException e) { - Logger.error(this, "Unable to save index because: "+e.toString()); - return; - } - } - public boolean fillInRootElement(Element rootEl, Document xmlDoc) { - rootEl.appendChild(getXMLHeader(xmlDoc)); - rootEl.appendChild(getXMLLinks(xmlDoc)); - rootEl.appendChild(getXMLFileList(xmlDoc)); + boolean blackListed = (BlackList.isBlackListed(db, key) >= 0); - if (canHaveComments()) - rootEl.appendChild(getXMLCommentInfos(xmlDoc)); - - return true; - } - - public Element getXMLHeader(final Document xmlDoc) { - final Element header = xmlDoc.createElement("header"); - - final Element title = xmlDoc.createElement("title"); - final Text titleText = xmlDoc.createTextNode(toString(false)); - title.appendChild(titleText); - - header.appendChild(title); - - - final Element thawVersion = xmlDoc.createElement("client"); - final Text versionText = xmlDoc.createTextNode("Thaw "+Main.VERSION); - thawVersion.appendChild(versionText); - - header.appendChild(thawVersion); - - if (getPublishPrivateKey() && getPrivateKey() != null) { - final Element privateKeyEl = xmlDoc.createElement("privateKey"); - final Text privateKeyText = xmlDoc.createTextNode(getPrivateKey()); - privateKeyEl.appendChild(privateKeyText); - - header.appendChild(privateKeyEl); - } - - /* insertion date */ - String dateStr; - - java.text.SimpleDateFormat sdf = - new java.text.SimpleDateFormat(DATE_FORMAT); - Calendar c1 = Calendar.getInstance(); // today - dateStr = sdf.format(c1.getTime()); - - final Element date = xmlDoc.createElement("date"); - final Text dateText = xmlDoc.createTextNode(dateStr); - date.appendChild(dateText); - - header.appendChild(date); - - /* TODO : Author */ - - return header; - } - - - /** - * must be in a synchronized(db.dbLock) - */ - private String findTheLatestKey(String linkKey) throws SQLException { - PreparedStatement st = db.getConnection().prepareStatement("SELECT publicKey FROM indexes "+ - "WHERE publicKey LIKE ?"); - st.setString(1, FreenetURIHelper.getComparablePart(linkKey)); - - ResultSet set = st.executeQuery(); - - while (set.next()) { - /* we will assume that we have *always* the latest version of the index */ - - String oKey = set.getString("publicKey"); - if (FreenetURIHelper.compareKeys(oKey, linkKey)) - return oKey; - } - - return linkKey; - } - - - public Element getXMLLinks(final Document xmlDoc) { - final Element links = xmlDoc.createElement("indexes"); - synchronized(db.dbLock) { - try { + synchronized(db.dbLock) { PreparedStatement st; - st = db.getConnection().prepareStatement("SELECT publicKey FROM links WHERE indexParent = ?"); - st.setInt(1, id); + st = db.getConnection().prepareStatement("INSERT INTO links "+ + "(publicKey, mark, comment, "+ + "indexParent, indexTarget, blackListed) "+ + "VALUES (?, 0, ?, ?, NULL, ?)"); + st.setString(1, key); + st.setString(2, "No comment"); /* comment not used at the moment */ + st.setInt(3, id); + st.setBoolean(4, blackListed); - ResultSet set = st.executeQuery(); - - while (set.next()) { - String key = findTheLatestKey(set.getString("publicKey")); - - final Element xmlLink = xmlDoc.createElement("index"); - - xmlLink.setAttribute("key", key); - - if (xmlLink != null) - links.appendChild(xmlLink); - else - Logger.warning(this, "Unable to get XML for a link => Gruick da link"); - - } - } catch(SQLException e) { - Logger.error(this, "Error while getting link list for XML : "+e.toString()); + st.execute(); } + } catch(SQLException e) { + Logger.error(this, "Error while adding link to index '"+toString()+"' : "+e.toString()); } - - return links; } - public Element getXMLFileList(final Document xmlDoc) { - final Element files = xmlDoc.createElement("files"); + + public String findTheLatestKey(String linkKey) { synchronized(db.dbLock) { try { PreparedStatement st; - st = db.getConnection().prepareStatement("SELECT id, filename, publicKey, size, mime "+ - "FROM files "+ - "WHERE indexParent = ?"); + st = db.getConnection().prepareStatement("SELECT publicKey, revision "+ + "FROM indexes "+ + "WHERE publicKey LIKE ?"); - st.setInt(1, id); + st.setString(1, FreenetURIHelper.getComparablePart(linkKey)); ResultSet set = st.executeQuery(); - while(set.next()) { - String pubKey = set.getString("publicKey"); + while (set.next()) { + /* we will assume that we have *always* the latest version of the index */ - if (pubKey == null) - continue; - - pubKey = pubKey.trim(); - - if (!FreenetURIHelper.isAKey(pubKey)) { - Logger.notice(this, "One of the file key wasn't generated => not added"); - continue; + String oKey = set.getString("publicKey"); + if (FreenetURIHelper.compareKeys(oKey, linkKey)) { + String key = FreenetURIHelper.changeUSKRevision(oKey, + set.getInt("revision"), + 0); + return key; } - - final Element xmlFile = xmlDoc.createElement("file"); - - //xmlFile.setAttribute("id", set.getString("id")); - xmlFile.setAttribute("key", pubKey); - xmlFile.setAttribute("size", set.getString("size")); - if (set.getString("mime") == null) - xmlFile.setAttribute("mime", DefaultMIMETypes.guessMIMEType(set.getString("filename"))); - else - xmlFile.setAttribute("mime", set.getString("mime")); - - if(xmlFile != null) - files.appendChild(xmlFile); - else - Logger.warning(this, "Public key wasn't generated ! Not added to the index !"); } - } catch(SQLException e) { - Logger.error(this, "Error while getting file list for XML : "+e.toString()); + Logger.error(this, "Can't find the latest key of a link because : "+e.toString()); } } - return files; + return linkKey; } - public Element getXMLCommentInfos(final Document xmlDoc) { - final Element infos = xmlDoc.createElement("comments"); - infos.setAttribute("publicKey", getCommentPublicKey()); - infos.setAttribute("privateKey", getCommentPrivateKey()); - - try { - synchronized(db.dbLock) { - PreparedStatement st; - - st = db.getConnection().prepareStatement("SELECT rev FROM indexCommentBlackList WHERE indexId = ?"); - st.setInt(1, id); - - ResultSet set = st.executeQuery(); - - while (set.next()) { - Element bl = xmlDoc.createElement("blackListed"); - bl.setAttribute("rev", set.getString("rev")); - - infos.appendChild(bl); - } - } - } catch(SQLException e) { - Logger.error(this, "Unable to get comment black list because: "+e.toString()); - } - - return infos; - } - - - - - /*********** INDEX LOADING **************/ - - - public void loadXML(final String filePath) { - loadXML(filePath, true); - } - - - /** - * @param clean if set to false, will do a merge - */ - public void loadXML(final String filePath, boolean clean) { - try { - loadXML(new FileInputStream(filePath), clean); - } catch(final java.io.FileNotFoundException e) { - Logger.error(this, "Unable to load XML: FileNotFoundException ('"+filePath+"') ! : "+e.toString()); - } - } - - - public class IndexHandler extends DefaultHandler { - private Locator locator = null; - - public IndexHandler() { - - } - - /** - * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) - */ - public void setDocumentLocator(Locator value) { - locator = value; - } - - /** - * Called when parsing is started - * @see org.xml.sax.ContentHandler#startDocument() - */ - public void startDocument() throws SAXException { - try { - PreparedStatement st; - - st = db.getConnection().prepareStatement("DELETE FROM files WHERE indexParent = ? AND dontDelete = FALSE"); - st.setInt(1, id); - st.execute(); - - st = db.getConnection().prepareStatement("DELETE FROM links WHERE indexParent = ? AND dontDelete = FALSE"); - st.setInt(1, id); - st.execute(); - - st = db.getConnection().prepareStatement("DELETE FROM indexCommentBlackList WHERE indexId = ?"); - st.setInt(1, id); - st.execute(); - - } catch(SQLException e) { - Logger.error(this, "Hm, failure while starting to parse the index: "+e.toString()); - throw new SAXException("SQLException ; have a nice day."); - } - } - - /** - * Called when starting to parse in a specific name space - * @param prefix name space prefix - * @param URI name space URI - * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) - */ - public void startPrefixMapping(String prefix, String URI) throws SAXException { - /* \_o< */ - } - - /** - * @param prefix name space prefix - * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) - */ - public void endPrefixMapping(String prefix) throws SAXException { - /* \_o< */ - } - - - - private boolean ownerTag = false; - private boolean privateKeyTag = false; - private boolean dateTag = false; - private boolean commentsTag = false; - - private boolean hasCommentTag = false; - - private String dateStr = null; - - private PreparedStatement insertFileSt = null; - private PreparedStatement insertLinkSt = null; - - /** - * Called when the parsed find an opening tag - * @param localName local tag name - * @param rawName rawName (the one used here) - * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) - */ - public void startElement(String nameSpaceURI, String localName, - String rawName, Attributes attrs) throws SAXException { - if (rawName == null) { - rawName = localName; - } - - if (rawName == null) - return; - - ownerTag = false; - privateKeyTag = false; - - /* TODO : */ - - if ("owner".equals(rawName)) { - ownerTag = true; - return; - } - - if ("privateKey".equals(rawName)) { - privateKeyTag = true; - return; - } - - if ("date".equals(rawName)) { - dateTag = true; - return; - } - - if ("index".equals(rawName)) { /* links */ - - int nextId; - - try { - String key = attrs.getValue("key"); - - if (key == null) /* it was the beginning of the index */ - return; - - key = key.trim(); - - - boolean blackListed = (BlackList.isBlackListed(db, key) >= 0); - - - if (insertLinkSt == null) - insertLinkSt = db.getConnection().prepareStatement("INSERT INTO links " - + "(publicKey, mark, comment, indexParent, indexTarget, blackListed) " - + "VALUES (?, 0, ?, ?, NULL, ?)"); - - insertLinkSt.setString(1, key); - insertLinkSt.setString(2, "No comment"); /* comment not used at the moment */ - insertLinkSt.setInt(3, id); - insertLinkSt.setBoolean(4, blackListed); - - insertLinkSt.execute(); - } catch(SQLException e) { - Logger.error(this, "Error while adding link to index '"+toString()+"' : "+e.toString()); - } - - return; - } - - if ("file".equals(rawName)) { - int nextId; - - try { - if (insertFileSt == null) - insertFileSt = - db.getConnection().prepareStatement("INSERT INTO files " - + "(filename, publicKey, localPath, mime, size, category, indexParent) " - + "VALUES (?, ?, NULL, ?, ?, NULL, ?)"); - - String key = attrs.getValue("key"); - String filename = FreenetURIHelper.getFilenameFromKey(key); - if (filename == null) - filename = key; - String mime = attrs.getValue("mime"); - long size = Long.parseLong(attrs.getValue("size")); - - insertFileSt.setString(1, filename); - insertFileSt.setString(2, key); - insertFileSt.setString(3, mime); - insertFileSt.setLong(4, size); - insertFileSt.setInt(5, id); - - synchronized(db.dbLock) { - insertFileSt.execute(); - } - } catch(SQLException e) { - Logger.error(this, "Error while adding file to index '"+toString()+"' : "+e.toString()); - } - - return; - - } - - - if ("comments".equals(rawName)) { - String pub = attrs.getValue("publicKey"); - String priv = attrs.getValue("privateKey"); - - if (pub != null && priv != null) { - hasCommentTag = true; - commentsTag = true; - Logger.debug(this, "Comment allowed in this index"); - setCommentKeys(pub, priv); - } - } - - - if ("blackListed".equals(rawName)) { - int blRev; - - try { - blRev = Integer.parseInt(attrs.getValue("rev")); - } catch(Exception e) { - /* quick and dirty */ - return; - } - - Logger.notice(this, "BlackListing rev '"+Integer.toString(rev)+"'"); - - try { - synchronized(db.dbLock) { - PreparedStatement st; - - st = db.getConnection().prepareStatement("INSERT into indexCommentBlackList (rev, indexId) VALUES (?, ?)"); - st.setInt(1, blRev); - st.setInt(2, id); - - st.execute(); - - } - } catch(SQLException e) { - Logger.error(this, "Error while adding element to the blackList: "+e.toString()); - } - } - - - - /* ignore unknown tags */ - - /* et paf ! Ca fait des Chocapics(tm)(r)(c)(m)(dtc) ! */ - } - - /** - * Called when a closing tag is met - * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String) - */ - public void endElement(String nameSpaceURI, String localName, - String rawName) throws SAXException { - if (rawName == null) { - rawName = localName; - } - - if (rawName == null) - return; - - if ("owner".equals(rawName)) { - ownerTag = false; - return; - } - - if ("privateKey".equals(rawName)) { - privateKeyTag = false; - return; - } - - if ("date".equals(rawName)) { - dateTag = false; - return; - } - - if ("header".equals(rawName)) { - try { - synchronized(db.dbLock) { - java.sql.Date dateSql = null; - - if (dateStr != null) { - java.text.SimpleDateFormat sdf = - new java.text.SimpleDateFormat(DATE_FORMAT); - java.util.Date dateUtil = sdf.parse(dateStr, new java.text.ParsePosition(0)); - dateSql = new java.sql.Date(dateUtil.getTime()); - } - - PreparedStatement st = - db.getConnection().prepareStatement("UPDATE indexes "+ - "SET insertionDate = ? "+ - "WHERE id = ?"); - st.setDate(1, dateSql); - st.setInt(2, id); - - st.execute(); - } - } catch(SQLException e) { - Logger.error(this, "Error while updating index insertion date: "+e.toString()); - } - } - - if ("comments".equals(rawName)) { - commentsTag = false; - return; - } - } - - - /** - * Called when a text between two tag is met - * @param ch text - * @param start position - * @param end position - * @see org.xml.sax.ContentHandler#characters(char[], int, int) - */ - public void characters(char[] ch, int start, int end) throws SAXException { - String txt = new String(ch, start, end); - - if (ownerTag) { - /* \_o< ==> TODO */ - - return; - } - - if (dateTag) { - dateStr = txt; - } - - if (privateKeyTag) { - if (privateKey == null || privateKey.trim().equals(txt.trim())) { - /** - * the private key was published, we will have to do the same later - */ - setPublishPrivateKey(true); - } else { - /** - * the provided key doesn't match with the one we have, - * we won't publish it anymore - */ - Logger.warning(this, "A private key was provided, but didn't match with the one we have ; ignored."); - - } - - if (privateKey == null) { - String newPrivate = txt.trim(); - - /* check that nobody is trying to inject some FCP commands - * through the private key - */ - if (!newPrivate.startsWith("SSK@") - || newPrivate.indexOf('\n') >= 0) { - Logger.warning(this, "Invalid private key"); - return; - } - - setPrivateKey(newPrivate); - } - return; - } - - - - - /* ignore unkwown stuffs */ - - } - - public void ignorableWhitespace(char[] ch, int start, int end) throws SAXException { - - } - - public void processingInstruction(String target, String data) throws SAXException { - - } - - /** - * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) - */ - public void skippedEntity(String arg0) throws SAXException { - - } - - - /** - * Called when parsing is finished - * @see org.xml.sax.ContentHandler#endDocument() - */ - public void endDocument() throws SAXException { - if (!hasCommentTag) { - Logger.debug(this, "No comment allowed in this index"); - purgeCommentKeys(); - } - } - } - - - /** - * see import functionnality - */ - public IndexHandler getIndexHandler() { - return new IndexHandler(); - } - - - public synchronized void loadXML(final java.io.InputStream input, boolean clean) { - IndexHandler handler = new IndexHandler(); - - synchronized(db.dbLock) { - try { - // Use the default (non-validating) parser - SAXParserFactory factory = SAXParserFactory.newInstance(); - - // Parse the input - SAXParser saxParser = factory.newSAXParser(); - Logger.info(this, "Parsing index ..."); - saxParser.parse(input, handler ); - Logger.info(this, "Parsing done"); - } catch(javax.xml.parsers.ParserConfigurationException e) { - Logger.error(this, "Error (1) while parsing index: "+e.toString()); - } catch(org.xml.sax.SAXException e) { - Logger.error(this, "Error (2) while parsing index: "+e.toString()); - } catch(java.io.IOException e) { - Logger.error(this, "Error (3) while parsing index: "+e.toString()); - } - } - } - - - - public static String getNameFromKey(final String key) { - String name = null; - - name = FreenetURIHelper.getFilenameFromKey(key); - - if (name == null) - return null; - - /* quick and dirty */ - name = name.replaceAll(".xml", ""); - name = name.replaceAll(".frdx", ""); - - return name; - } - - public boolean isModifiable() { if (getPrivateKey() != null) return true; @@ -1931,7 +1407,7 @@ e.setAttribute("privateKey", getPrivateKey()); if (withContent) { - fillInRootElement(e, xmlDoc); + new IndexParser(this).fillInRootElement(e, xmlDoc); } return e; @@ -2302,4 +1778,9 @@ return null; } + + + public String getClientVersion() { + return ("Thaw "+Main.VERSION); + } } Added: trunk/apps/Thaw/src/thaw/plugins/index/IndexContainer.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/index/IndexContainer.java (rev 0) +++ trunk/apps/Thaw/src/thaw/plugins/index/IndexContainer.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -0,0 +1,73 @@ +package thaw.plugins.index; + +import java.util.Vector; + + +/** + * This is what you need to implements to use IndexParser. + */ +public interface IndexContainer extends FileAndLinkList { + + /** + * @return a vector of FileContainer + */ + public Vector getFileList(); + + /** + * @return a vector of LinkContainer + */ + public Vector getLinkList(); + + + /** + * @return true if the private key must be published + */ + public boolean publishPrivateKey(); + + /** + * @return the private key of the index (Expected: "SSK@[...]/") + */ + public String getPrivateKey(); + + + /** + * Used to update the links. The simplest way to find the correct + * is to look at your index list. + */ + public String findTheLatestKey(String originalKey); + + + /** + * @param toGUI if set to false, must *just* return the index name + */ + public String toString(boolean toGUI); + + /** + * @return for example "Thaw 0.8 r4242" + */ + public String getClientVersion(); + + public boolean canHaveComments(); + public String getCommentPublicKey(); + public String getCommentPrivateKey(); + + /** + * @return Vector of Integer + */ + public Vector getCommentBlacklistedRev(); + + /** + * delete all the files / links / comment blacklisted revs / comments keys + */ + public void purgeIndex(); + + public void setInsertionDate(java.util.Date date); + + public void addFile(String publicKey, long size, String mime); + public void addLink(String publicKey); + public void setCommentKeys(String publicKey, String privateKey); + public void addBlackListedRev(int rev); + + public void setPublishPrivateKey(boolean publish); + public void setPrivateKey(String key); +} Modified: trunk/apps/Thaw/src/thaw/plugins/index/IndexManagementHelper.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/index/IndexManagementHelper.java 2007-08-03 03:39:36 UTC (rev 14474) +++ trunk/apps/Thaw/src/thaw/plugins/index/IndexManagementHelper.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -536,7 +536,7 @@ final KeyAsker asker = KeyAsker.askKeys(index, getQueueManager(), true, index.getPublicKey(), - index.getPrivateKey(), index.getPublishPrivateKey(), + index.getPrivateKey(), index.publishPrivateKey(), index.canHaveComments(), true, getIndexBrowserPanel()); if (asker == null) { @@ -1020,7 +1020,7 @@ return; } - ((Index)getTarget()).generateXML(out); + new IndexParser(((Index)getTarget())).generateXML(out); } } @@ -1049,7 +1049,7 @@ if (newFile == null) return; - ((Index)getTarget()).loadXML(newFile.getPath()); + new IndexParser(((Index)getTarget())).loadXML(newFile.getPath()); } } Added: trunk/apps/Thaw/src/thaw/plugins/index/IndexParser.java =================================================================== --- trunk/apps/Thaw/src/thaw/plugins/index/IndexParser.java (rev 0) +++ trunk/apps/Thaw/src/thaw/plugins/index/IndexParser.java 2007-08-03 17:40:46 UTC (rev 14475) @@ -0,0 +1,579 @@ +package thaw.plugins.index; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.Vector; +import java.util.Iterator; + +/* DOM */ + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + + +/* SAX */ + +import org.xml.sax.*; +import org.xml.sax.helpers.LocatorImpl; + +import java.io.IOException; + +import org.xml.sax.helpers.XMLReaderFactory; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; + + + +import thaw.core.Main; +import thaw.core.Logger; +import thaw.plugins.Hsqldb; +import thaw.fcp.FreenetURIHelper; +import thaw.plugins.insertPlugin.DefaultMIMETypes; + + + +public class IndexParser { + public final static String DATE_FORMAT = "yyyyMMdd"; + + private IndexContainer index; + + public IndexParser(IndexContainer index) { + this.index = index; + } + + public boolean generateXML(String path) { + try { + generateXML(new FileOutputStream(new File(path))); + return true; + } catch(java.io.FileNotFoundException e) { + Logger.error(this, "File not found exception ?!"); + } + return false; + } + + public void generateXML(final OutputStream out) { + StreamResult streamResult; + + streamResult = new StreamResult(out); + + Document xmlDoc; + + final DocumentBuilderFactory xmlFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder xmlBuilder; + + try { + xmlBuilder = xmlFactory.newDocumentBuilder(); + } catch(final javax.xml.parsers.ParserConfigurationException e) { + Logger.error(this, "Unable to generate the index because : "+e.toString()); + return; + } + + final DOMImplementation impl = xmlBuilder.getDOMImplementation(); + + xmlDoc = impl.createDocument(null, "index", null); + + final Element rootEl = xmlDoc.getDocumentElement(); + + /**** DOM Tree generation ****/ + fillInRootElement(rootEl, xmlDoc); + + + /* Serialization */ + final DOMSource domSource = new DOMSource(xmlDoc); + final TransformerFactory transformFactory = TransformerFactory.newInstance(); + + Transformer serializer; + + try { + serializer = transformFactory.newTransformer(); + } catch(final javax.xml.transform.TransformerConfigurationException e) { + Logger.error(this, "Unable to save index because: "+e.toString()); + return; + } + + serializer.setOutputProperty(OutputKeys.ENCODING,"UTF-8"); + serializer.setOutputProperty(OutputKeys.INDENT,"yes"); + + /* final step */ + try { + serializer.transform(domSource, streamResult); + } catch(final javax.xml.transform.TransformerException e) { + Logger.error(this, "Unable to save index because: "+e.toString()); + return; + } + } + + + + public boolean fillInRootElement(Element rootEl, Document xmlDoc) { + rootEl.appendChild(getXMLHeader(xmlDoc)); + rootEl.appendChild(getXMLLinks(xmlDoc)); + rootEl.appendChild(getXMLFileList(xmlDoc)); + + if (index.canHaveComments()) + rootEl.appendChild(getXMLCommentInfos(xmlDoc)); + + return true; + } + + + public Element getXMLHeader(final Document xmlDoc) { + final Element header = xmlDoc.createElement("header"); + + final Element title = xmlDoc.createElement("title"); + final Text titleText = xmlDoc.createTextNode(index.toString(false)); + title.appendChild(titleText); + + header.appendChild(title); + + + final Element clientVersion = xmlDoc.createElement("client"); + final Text versionText = xmlDoc.createTextNode(index.getClientVersion()); + clientVersion.appendChild(versionText); + + header.appendChild(clientVersion); + + if (index.publishPri