View Javadoc

1   /*
2    * Copyright (c) 2007 Creative Sphere Limited.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
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   * Copy to other side action.
34   *
35   * @author Daniel Sendula
36   */
37  public class BinaryComparisonAction extends FileBaseAction {
38  
39      /** Default buffer size */
40      public static final int DEFAULT_BUFFER_SIZE = 10240;
41      // TODO move this to global context
42      
43      /**
44       * Constructor
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       * Returns if selection is valid
56       * @return <code>true</code> if selection is valid<
57       */
58      public boolean isEnabled() {
59          return isSelectionValid();
60      }
61      
62      /**
63       * Compares two sets of files
64       * @param e event
65       * @param monitor monitor
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]; // TODO 0 and 1? Should be all... or loop... or something
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                         // TODO is that ok?
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      * Checks if two files are the same
135      * @param f1 first file
136      * @param f2 second file
137      * @return <code>true</cod> if two files are the same
138      * @throws IOException
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      * Checks if two streams are the same. It doesn't close the streams
156      * @param f1 first file
157      * @param f2 second file
158      * @return <code>true</cod> if two files are the same
159      * @throws IOException
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      * Checks if two arrays of bytes are the same
180      * @param a1 first array
181      * @param a2 second array
182      * @param len number of bytes in the array
183      * @return <code>true</code> if they are the same
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 }