Checksums optional

This commit is contained in:
Denis Molony 2016-12-12 18:43:19 +11:00
parent cdb32786f4
commit af90a850a4
13 changed files with 140 additions and 64 deletions

View File

@ -89,7 +89,7 @@ public class DiskFactory
suffix = "dsk"; suffix = "dsk";
compressed = true; compressed = true;
} }
catch (IOException e) catch (IOException e) // can get EOFException: Unexpected end of ZLIB input stream
{ {
e.printStackTrace (); e.printStackTrace ();
return null; return null;

View File

@ -198,6 +198,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
if (ShapeTable.isShapeTable (exactBuffer)) if (ShapeTable.isShapeTable (exactBuffer))
appleFile = new ShapeTable (name, exactBuffer); appleFile = new ShapeTable (name, exactBuffer);
else if (name.endsWith (".S"))
appleFile = new MerlinSource (name, exactBuffer);
else if (HiResImage.isGif (exactBuffer)) else if (HiResImage.isGif (exactBuffer))
appleFile = new HiResImage (name, exactBuffer); appleFile = new HiResImage (name, exactBuffer);
else if (loadAddress == 0x2000 || loadAddress == 0x4000) else if (loadAddress == 0x2000 || loadAddress == 0x4000)
@ -210,16 +212,12 @@ abstract class AbstractCatalogEntry implements AppleFileSource
else else
appleFile = new AssemblerProgram (name, exactBuffer, loadAddress); appleFile = new AssemblerProgram (name, exactBuffer, loadAddress);
} }
else if (name.endsWith (".S"))
appleFile = new MerlinSource (name, exactBuffer);
else else
{ {
appleFile = new AssemblerProgram (name, exactBuffer, loadAddress); appleFile = new AssemblerProgram (name, exactBuffer, loadAddress);
// System.out.printf ("%d %d%n", exactBuffer.length, reportedLength);
if ((exactBuffer.length + 4) < buffer.length) if ((exactBuffer.length + 4) < buffer.length)
((AssemblerProgram) appleFile) ((AssemblerProgram) appleFile).setExtraBuffer (buffer,
.setExtraBuffer (buffer, exactBuffer.length + 4, exactBuffer.length + 4, buffer.length - (exactBuffer.length + 4));
buffer.length - (exactBuffer.length + 4));
} }
// } // }
break; break;

View File

@ -19,12 +19,16 @@ public class DiskDetails
private boolean isDuplicateName; private boolean isDuplicateName;
private boolean isDuplicateChecksum; private boolean isDuplicateChecksum;
public DiskDetails (File file, String rootName, String shortName) public DiskDetails (File file, String rootName, String shortName, boolean doChecksum)
{ {
this.file = file; this.file = file;
this.rootName = rootName; this.rootName = rootName;
this.shortName = shortName; this.shortName = shortName;
if (doChecksum)
checksum = ComputeCRC32.getChecksumValue (file); checksum = ComputeCRC32.getChecksumValue (file);
else
checksum = 0;
} }
public File getFile () public File getFile ()
@ -85,11 +89,11 @@ public class DiskDetails
return checksum; return checksum;
} }
public boolean delete () // public boolean delete ()
{ // {
// return file.delete (); // // return file.delete ();
return false; // return false;
} // }
@Override @Override
public String toString () public String toString ()

View File

@ -11,7 +11,7 @@ import com.bytezone.diskbrowser.utilities.Utility;
public class DiskTableModel extends AbstractTableModel public class DiskTableModel extends AbstractTableModel
{ {
static final String[] headers = static final String[] headers =
{ "Path", "Name", "Type", "Size (bytes)", "Dup name", "Dup data", "Checksum" }; { "Path", "Name", "Type", "Size", "Dup name", "Dup data", "Checksum" };
Map<String, DiskDetails> fileNameMap; Map<String, DiskDetails> fileNameMap;
Map<Long, DiskDetails> checkSumMap; Map<Long, DiskDetails> checkSumMap;

View File

@ -1,5 +1,6 @@
package com.bytezone.diskbrowser.duplicates; package com.bytezone.diskbrowser.duplicates;
import java.awt.Dimension;
import java.awt.Graphics; import java.awt.Graphics;
import java.io.File; import java.io.File;
import java.util.HashMap; import java.util.HashMap;
@ -21,6 +22,7 @@ public class DuplicateHandler extends SwingWorker<Void, ProgressState>
private final DuplicateWindow owner; private final DuplicateWindow owner;
private final JDialog dialog; private final JDialog dialog;
private final ProgressPanel progressPanel; private final ProgressPanel progressPanel;
private final boolean doChecksums;
// list of checksum -> DiskDetails // list of checksum -> DiskDetails
private final Map<Long, DiskDetails> checksumMap = new HashMap<Long, DiskDetails> (); private final Map<Long, DiskDetails> checksumMap = new HashMap<Long, DiskDetails> ();
@ -29,18 +31,20 @@ public class DuplicateHandler extends SwingWorker<Void, ProgressState>
private final Map<String, DiskDetails> fileNameMap = private final Map<String, DiskDetails> fileNameMap =
new TreeMap<String, DiskDetails> (); new TreeMap<String, DiskDetails> ();
public DuplicateHandler (File rootFolder, DuplicateWindow owner) public DuplicateHandler (File rootFolder, DuplicateWindow owner, boolean doChecksums)
{ {
this.rootFolder = rootFolder; this.rootFolder = rootFolder;
this.owner = owner; this.owner = owner;
this.doChecksums = doChecksums;
rootFolderNameLength = rootFolder.getAbsolutePath ().length (); rootFolderNameLength = rootFolder.getAbsolutePath ().length ();
dialog = new JDialog (owner); dialog = new JDialog (owner);
progressPanel = new ProgressPanel (); progressPanel = new ProgressPanel ();
progressPanel.setPreferredSize (new Dimension (485, 300));
dialog.add (progressPanel); dialog.add (progressPanel);
dialog.setSize (500, 400);
dialog.setLocationRelativeTo (null);
dialog.setTitle ("Reading disks"); dialog.setTitle ("Reading disks");
dialog.pack ();
dialog.setLocationRelativeTo (null);
dialog.setVisible (true); dialog.setVisible (true);
} }
@ -83,7 +87,7 @@ public class DuplicateHandler extends SwingWorker<Void, ProgressState>
progressState.incrementType (file, fileName); progressState.incrementType (file, fileName);
checkDuplicates (file, fileName); checkDuplicates (file, fileName);
if ((progressState.totalDisks % 1000) == 0) if ((progressState.totalDisks % 500) == 0)
publish (progressState); publish (progressState);
} }
} }
@ -92,19 +96,22 @@ public class DuplicateHandler extends SwingWorker<Void, ProgressState>
private void checkDuplicates (File file, String filename) private void checkDuplicates (File file, String filename)
{ {
String rootName = file.getAbsolutePath ().substring (rootFolderNameLength); String rootName = file.getAbsolutePath ().substring (rootFolderNameLength);
DiskDetails diskDetails = new DiskDetails (file, rootName, filename); DiskDetails diskDetails = new DiskDetails (file, rootName, filename, doChecksums);
if (fileNameMap.containsKey (filename)) if (fileNameMap.containsKey (filename))
fileNameMap.get (filename).addDuplicateName (diskDetails); fileNameMap.get (filename).addDuplicateName (diskDetails);
else else
fileNameMap.put (filename, diskDetails); fileNameMap.put (filename, diskDetails);
if (doChecksums)
{
long checksum = diskDetails.getChecksum (); long checksum = diskDetails.getChecksum ();
if (checksumMap.containsKey (checksum)) if (checksumMap.containsKey (checksum))
checksumMap.get (checksum).addDuplicateChecksum (diskDetails); checksumMap.get (checksum).addDuplicateChecksum (diskDetails);
else else
checksumMap.put (checksum, diskDetails); checksumMap.put (checksum, diskDetails);
} }
}
@Override @Override
protected void done () protected void done ()
@ -131,8 +138,6 @@ public class DuplicateHandler extends SwingWorker<Void, ProgressState>
@Override @Override
protected void process (List<ProgressState> chunks) protected void process (List<ProgressState> chunks)
{ {
// for (ProgressState progressState : chunks)
// progressState.print ();
progressPanel.repaint (); progressPanel.repaint ();
} }

View File

@ -12,10 +12,12 @@ import javax.swing.*;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import javax.swing.table.JTableHeader; import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableRowSorter; import javax.swing.table.TableRowSorter;
import com.bytezone.diskbrowser.gui.DuplicateAction; import com.bytezone.diskbrowser.gui.DuplicateAction;
import com.bytezone.diskbrowser.gui.DuplicateAction.DiskTableSelectionListener; import com.bytezone.diskbrowser.gui.DuplicateAction.DiskTableSelectionListener;
import com.bytezone.diskbrowser.utilities.NumberRenderer;
public class DuplicateWindow extends JFrame public class DuplicateWindow extends JFrame
{ {
@ -24,7 +26,6 @@ public class DuplicateWindow extends JFrame
private final JButton btnExport = new JButton ("Export"); private final JButton btnExport = new JButton ("Export");
private final JButton btnHide = new JButton ("Close"); private final JButton btnHide = new JButton ("Close");
// private DuplicateHandler duplicateHandler;
private final List<DiskTableSelectionListener> listeners; private final List<DiskTableSelectionListener> listeners;
public DuplicateWindow (File rootFolder, public DuplicateWindow (File rootFolder,
@ -71,13 +72,14 @@ public class DuplicateWindow extends JFrame
public void setDuplicateHandler (DuplicateHandler duplicateHandler) public void setDuplicateHandler (DuplicateHandler duplicateHandler)
{ {
// this.duplicateHandler = duplicateHandler;
table.setModel (new DiskTableModel (duplicateHandler)); table.setModel (new DiskTableModel (duplicateHandler));
int[] columnWidths = { 300, 300, 30, 40, 40, 40, 100 }; int[] columnWidths = { 300, 300, 30, 40, 40, 40, 100 };
TableColumnModel tcm = table.getColumnModel ();
for (int i = 0; i < columnWidths.length; i++) for (int i = 0; i < columnWidths.length; i++)
table.getColumnModel ().getColumn (i).setPreferredWidth (columnWidths[i]); tcm.getColumn (i).setPreferredWidth (columnWidths[i]);
tcm.getColumn (3).setCellRenderer (NumberRenderer.getIntegerRenderer ());
final TableRowSorter<DiskTableModel> sorter = final TableRowSorter<DiskTableModel> sorter =
new TableRowSorter<DiskTableModel> ((DiskTableModel) table.getModel ()); new TableRowSorter<DiskTableModel> ((DiskTableModel) table.getModel ());

View File

@ -14,7 +14,7 @@ public class ProgressState
private static final String header = " type uncmp .gz .zip"; private static final String header = " type uncmp .gz .zip";
private static final String line = "-------------- ------- ------- -------"; private static final String line = "-------------- ------- ------- -------";
private static final List<String> suffixes = Utility.suffixes; private static final List<String> suffixes = Utility.suffixes;
private static final Font font = new Font ("Monaco", Font.BOLD, 15); private static final Font font = new Font ("Monospaced", Font.BOLD, 15);
int totalDisks; int totalDisks;
int totalFolders; int totalFolders;
@ -52,7 +52,7 @@ public class ProgressState
g.setFont (font); g.setFont (font);
int x = 55; int x = 55;
int y = 55; int y = 25;
int lineHeight = 23; int lineHeight = 23;
String line; String line;

View File

@ -8,6 +8,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
import com.bytezone.common.DefaultAction; import com.bytezone.common.DefaultAction;
@ -25,13 +26,13 @@ public class DuplicateAction extends DefaultAction implements RootDirectoryChang
public DuplicateAction () public DuplicateAction ()
{ {
super ("Check for duplicates...", "Check for duplicate disks", super ("List disks...", "Display a sortable list of disks",
"/com/bytezone/diskbrowser/icons/"); "/com/bytezone/diskbrowser/icons/");
setIcon (Action.SMALL_ICON, "save_delete_16.png"); setIcon (Action.SMALL_ICON, "save_delete_16.png");
setIcon (Action.LARGE_ICON_KEY, "save_delete_32.png"); setIcon (Action.LARGE_ICON_KEY, "save_delete_32.png");
int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMask (); int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMask ();
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke (KeyEvent.VK_D, mask)); putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke (KeyEvent.VK_L, mask));
setEnabled (false); setEnabled (false);
} }
@ -47,9 +48,20 @@ public class DuplicateAction extends DefaultAction implements RootDirectoryChang
public void actionPerformed (ActionEvent arg0) public void actionPerformed (ActionEvent arg0)
{ {
if (window == null) if (window == null)
{
Object[] options = { "Generate checksums", "Disk names only", "Cancel" };
int n = JOptionPane.showOptionDialog (null,
"This command will list all of the disks in the root folder (including\n"
+ "nested folders). If you wish to generate a checksum for each disk, it\n"
+ "will slow the process down considerably.\n\n"
+ "Do you wish to generate checksums?",
"Generate Disk Listing", JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options, options[2]);
if (n < 2)
{ {
window = new DuplicateWindow (rootFolder, listeners); window = new DuplicateWindow (rootFolder, listeners);
new DuplicateHandler (rootFolder, window).execute (); new DuplicateHandler (rootFolder, window, n == 0).execute ();
}
} }
else else
window.setVisible (true); window.setVisible (true);

View File

@ -22,9 +22,6 @@ import com.bytezone.diskbrowser.utilities.Utility;
public class TreeBuilder public class TreeBuilder
{ {
private static SimpleDateFormat sdf = new SimpleDateFormat ("dd MMM yyyy"); private static SimpleDateFormat sdf = new SimpleDateFormat ("dd MMM yyyy");
// private static final int DISK_13_SIZE = 116480;
// private static final int DISK_16_SIZE = 143360;
// private static final int DISK_800K_SIZE = 819264;
private final FileComparator fileComparator = new FileComparator (); private final FileComparator fileComparator = new FileComparator ();
private final JTree tree; private final JTree tree;
@ -71,19 +68,8 @@ public class TreeBuilder
fileNode.setTreeNode (newNode); fileNode.setTreeNode (newNode);
newNode.setAllowsChildren (true); newNode.setAllowsChildren (true);
node.add (newNode); node.add (newNode);
continue;
} }
else if (Utility.validFileType (file.getName ()) && file.length () > 0)
// if (file.length () != DISK_16_SIZE && file.length () != DISK_13_SIZE
// && file.length () != DISK_800K_SIZE && file.length () < 200000)
// {
// String name = file.getName ().toLowerCase ();
// if (!name.endsWith (".sdk") && !name.endsWith (".dsk.gz"))
// continue;
// }
if (Utility.validFileType (file.getName ()) && file.length () > 0)
{ {
FileNode fileNode = new FileNode (file); FileNode fileNode = new FileNode (file);
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode (fileNode); DefaultMutableTreeNode newNode = new DefaultMutableTreeNode (fileNode);

View File

@ -259,6 +259,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
case FILE_TYPE_BINARY: case FILE_TYPE_BINARY:
case FILE_TYPE_RELOCATABLE: case FILE_TYPE_RELOCATABLE:
case FILE_TYPE_SYS: case FILE_TYPE_SYS:
// if (name.endsWith (".S"))
// file = new MerlinSource (name, exactBuffer, auxType, endOfFile);
if (ShapeTable.isShapeTable (exactBuffer)) if (ShapeTable.isShapeTable (exactBuffer))
file = new ShapeTable (name, exactBuffer); file = new ShapeTable (name, exactBuffer);
else if (SimpleText.isHTML (exactBuffer)) else if (SimpleText.isHTML (exactBuffer))
@ -275,8 +277,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
{ {
file = new AssemblerProgram (name, exactBuffer, auxType); file = new AssemblerProgram (name, exactBuffer, auxType);
if (exactBuffer.length < buffer.length) if (exactBuffer.length < buffer.length)
((AssemblerProgram) file) ((AssemblerProgram) file).setExtraBuffer (buffer, exactBuffer.length,
.setExtraBuffer (buffer, exactBuffer.length,
buffer.length - exactBuffer.length); buffer.length - exactBuffer.length);
} }
break; break;
@ -384,8 +385,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
if (addresses.size () > 0) if (addresses.size () > 0)
{ {
byte[] tempBuffer = disk.readSectors (addresses); byte[] tempBuffer = disk.readSectors (addresses);
buffers.add (new TextBuffer (tempBuffer, auxType, buffers.add (
logicalBlock - addresses.size ())); new TextBuffer (tempBuffer, auxType, logicalBlock - addresses.size ()));
addresses.clear (); addresses.clear ();
} }
logicalBlock += 256; logicalBlock += 256;
@ -559,13 +560,11 @@ class FileEntry extends CatalogEntry implements ProdosConstants
String locked = (access == 0x00) ? "*" : " "; String locked = (access == 0x00) ? "*" : " ";
if (true) if (true)
return String.format ("%s %03d %s", ProdosConstants.fileTypes[fileType], return String.format ("%s %03d %s", ProdosConstants.fileTypes[fileType],
blocksUsed, locked) blocksUsed, locked) + name;
+ name;
String timeC = created == null ? "" : parentDisk.df.format (created.getTime ()); String timeC = created == null ? "" : parentDisk.df.format (created.getTime ());
String timeF = modified == null ? "" : parentDisk.df.format (modified.getTime ()); String timeF = modified == null ? "" : parentDisk.df.format (modified.getTime ());
return String.format ("%s %s%-30s %3d %,10d %15s %15s", return String.format ("%s %s%-30s %3d %,10d %15s %15s",
ProdosConstants.fileTypes[fileType], locked, ProdosConstants.fileTypes[fileType], locked, parentDirectory.name + "/" + name,
parentDirectory.name + "/" + name, blocksUsed, endOfFile, timeC, blocksUsed, endOfFile, timeC, timeF);
timeF);
} }
} }

View File

@ -0,0 +1,41 @@
package com.bytezone.diskbrowser.utilities;
import java.text.DateFormat;
import java.text.Format;
import javax.swing.table.DefaultTableCellRenderer;
public class FormatRenderer extends DefaultTableCellRenderer
{
private final Format formatter;
public FormatRenderer (Format formatter)
{
this.formatter = formatter;
}
@Override
public void setValue (Object value)
{
try
{
if (value != null)
value = formatter.format (value);
}
catch (IllegalArgumentException e)
{
}
super.setValue (value);
}
public static FormatRenderer getDateTimeRenderer ()
{
return new FormatRenderer (DateFormat.getDateTimeInstance ());
}
public static FormatRenderer getTimeRenderer ()
{
return new FormatRenderer (DateFormat.getTimeInstance ());
}
}

View File

@ -0,0 +1,29 @@
package com.bytezone.diskbrowser.utilities;
import java.text.NumberFormat;
import javax.swing.SwingConstants;
public class NumberRenderer extends FormatRenderer
{
public NumberRenderer (NumberFormat formatter)
{
super (formatter);
setHorizontalAlignment (SwingConstants.RIGHT);
}
public static NumberRenderer getCurrencyRenderer ()
{
return new NumberRenderer (NumberFormat.getCurrencyInstance ());
}
public static NumberRenderer getIntegerRenderer ()
{
return new NumberRenderer (NumberFormat.getIntegerInstance ());
}
public static NumberRenderer getPercentRenderer ()
{
return new NumberRenderer (NumberFormat.getPercentInstance ());
}
}