1
2
3
4
5
6
7
8
9
10
11
12
13 package org.abstracthorizon.aequo.file.action;
14
15 import java.awt.event.ActionEvent;
16 import java.awt.event.KeyEvent;
17 import java.io.File;
18 import java.io.FileInputStream;
19 import java.io.IOException;
20 import java.io.StringWriter;
21
22 import javax.swing.Action;
23 import javax.swing.JOptionPane;
24 import javax.swing.KeyStroke;
25 import javax.swing.ListSelectionModel;
26 import javax.swing.ProgressMonitor;
27
28 import org.abstracthorizon.aequo.CompareEntry;
29 import org.abstracthorizon.aequo.file.FileCompareEntry;
30 import org.abstracthorizon.aequo.file.FilesModel;
31
32
33
34
35
36
37 public class BinaryComparisonAction extends FileBaseAction {
38
39
40 public static final int DEFAULT_BUFFER_SIZE = 10240;
41
42
43
44
45
46 public BinaryComparisonAction() {
47 setName("Compare Contents");
48 setMessage("Comparing contents");
49 setDescription("Comparing contents");
50 putValue(Action.MNEMONIC_KEY, KeyEvent.VK_C);
51 putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, ActionEvent.SHIFT_MASK));
52 }
53
54
55
56
57
58 public boolean isEnabled() {
59 return isSelectionValid();
60 }
61
62
63
64
65
66
67 public void perform(ActionEvent e, ProgressMonitor monitor) {
68 int failed = 0;
69 StringWriter failedDetails = new StringWriter();
70
71 FilesModel model = getFilesModel();
72
73 int first = 0;
74 int last = -1;
75 FileCompareEntry[] entries = getPreselectedEntries();
76 if (entries.length > 0) {
77 first = entries[0].getIndex();
78 int i = entries.length - 1;
79 while ((i >= 0) && (last < 0)) {
80 last = entries[i].getIndex();
81 i--;
82 }
83 }
84
85 monitor.setMaximum(entries.length);
86
87 ListSelectionModel selModel = model.getSelectionModel();
88
89 selModel.setValueIsAdjusting(true);
90 try {
91 int i = 0;
92 while (i < entries.length) {
93 FileCompareEntry entry = entries[i];
94 File[] data = entry.getData();
95 File fromFile = data[0];
96 File toFile = data[1];
97 monitor.setNote(fromFile.getAbsolutePath() + " to " + toFile.getAbsolutePath());
98 if (fromFile.exists() && toFile.exists() && fromFile.isFile() && toFile.isFile()) {
99 try {
100 if (same(fromFile, toFile)) {
101 if ((entry.getStatus(0) != CompareEntry.EQUAL)
102 || (entry.getStatus(1) != CompareEntry.EQUAL)) {
103 entry.setStatus(0, CompareEntry.EQUAL);
104 entry.setStatus(1, CompareEntry.EQUAL);
105 entry.updateEntryStatus(true);
106 }
107 } else {
108 if ((entry.getStatus(0) == CompareEntry.EQUAL)
109 || (entry.getStatus(1) == CompareEntry.EQUAL)) {
110 entry.setStatus(0, CompareEntry.DIFFERENT);
111 entry.setStatus(1, CompareEntry.DIFFERENT);
112 entry.updateEntryStatus(true);
113 }
114 }
115 } catch (IOException ignore) {
116
117 }
118 }
119 monitor.setProgress(i);
120 i++;
121 }
122 if (entries.length > 0) {
123 model.notifyOfChange(first, last);
124 }
125 } finally {
126 selModel.setValueIsAdjusting(false);
127 }
128 if (failed > 0) {
129 JOptionPane.showMessageDialog(null, failedDetails.toString(), "Problem deleting files", JOptionPane.WARNING_MESSAGE, null);
130 }
131 }
132
133
134
135
136
137
138
139
140 public static boolean same(File f1, File f2) throws IOException {
141 FileInputStream fis1 = new FileInputStream(f1);
142 try {
143 FileInputStream fis2 = new FileInputStream(f2);
144 try {
145 return same(fis1, fis2);
146 } finally {
147 fis2.close();
148 }
149 } finally {
150 fis1.close();
151 }
152 }
153
154
155
156
157
158
159
160
161 public static boolean same(FileInputStream fis1, FileInputStream fis2) throws IOException {
162 byte[] buf1 = new byte[DEFAULT_BUFFER_SIZE];
163 byte[] buf2 = new byte[DEFAULT_BUFFER_SIZE];
164
165 int r1 = fis1.read(buf1);
166 int r2 = fis2.read(buf2);
167 while ((r1 == r2) && (r1 >= 0) && equals(buf1, buf2, r1)) {
168 r1 = fis1.read(buf1);
169 r2 = fis2.read(buf2);
170 }
171 if ((r1 == r2) && (r1 < 0)) {
172 return true;
173 } else {
174 return false;
175 }
176 }
177
178
179
180
181
182
183
184
185 public static boolean equals(byte[] a1, byte[] a2, int len) {
186 for (int i = 0; i < len; i++) {
187 if (a1[i] != a2[i]) {
188 return false;
189 }
190 }
191 return true;
192 }
193
194
195 }