KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > versioning > system > cvss > ui > actions > diff > ExportDiffAction


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.versioning.system.cvss.ui.actions.diff;
21
22 import org.netbeans.modules.versioning.system.cvss.FileInformation;
23 import org.netbeans.modules.versioning.system.cvss.ExecutorGroup;
24 import org.netbeans.modules.versioning.system.cvss.CvsModuleConfig;
25 import org.netbeans.modules.versioning.system.cvss.util.Context;
26 import org.netbeans.modules.versioning.util.AccessibleJFileChooser;
27 import org.netbeans.modules.versioning.util.Utils;
28 import org.netbeans.modules.versioning.system.cvss.ui.actions.AbstractSystemAction;
29 import org.netbeans.modules.diff.builtin.visualizer.TextDiffVisualizer;
30 import org.netbeans.api.diff.Difference;
31 import org.netbeans.spi.diff.DiffProvider;
32 import org.openide.windows.TopComponent;
33 import org.openide.util.Lookup;
34 import org.openide.util.RequestProcessor;
35 import org.openide.util.NbBundle;
36 import org.openide.ErrorManager;
37 import org.openide.NotifyDescriptor;
38 import org.openide.DialogDisplayer;
39 import org.openide.DialogDescriptor;
40 import org.openide.nodes.Node;
41 import org.openide.awt.StatusDisplayer;
42
43 import javax.swing.*;
44 import java.io.*;
45 import java.util.*;
46 import java.util.List JavaDoc;
47 import java.awt.event.ActionListener JavaDoc;
48 import java.awt.event.ActionEvent JavaDoc;
49 import java.awt.*;
50
51 /**
52  * Exports diff to file:
53  *
54  * <ul>
55  * <li>for components that implements {@link DiffSetupSource} interface
56  * exports actually displayed diff.
57  *
58  * <li>for DataNodes <b>local</b> differencies between the current
59  * working copy and BASE repository version.
60  * </ul>
61  *
62  * @author Petr Kuzel
63  */

64 public class ExportDiffAction extends AbstractSystemAction {
65     
66     private static final int enabledForStatus =
67             FileInformation.STATUS_VERSIONED_MERGE |
68             FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY |
69             FileInformation.STATUS_VERSIONED_DELETEDLOCALLY |
70             FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY |
71             FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY |
72             FileInformation.STATUS_VERSIONED_ADDEDLOCALLY;
73
74     public ExportDiffAction() {
75         setIcon(null);
76         putValue("noIconInMenu", Boolean.TRUE); // NOI18N
77
}
78
79     protected String JavaDoc getBaseName(Node [] activatedNodes) {
80         return "CTL_MenuItem_ExportDiff"; // NOI18N
81
}
82
83     /**
84      * First look for DiffSetupSource name then for super (context name).
85      */

86     public String JavaDoc getName() {
87         TopComponent activated = TopComponent.getRegistry().getActivated();
88         if (activated instanceof DiffSetupSource) {
89             String JavaDoc setupName = ((DiffSetupSource)activated).getSetupDisplayName();
90             if (setupName != null) {
91                 return NbBundle.getMessage(this.getClass(), getBaseName(getActivatedNodes()) + "_Context", // NOI18N
92
setupName);
93             }
94         }
95         return super.getName();
96     }
97
98     protected int getFileEnabledStatus() {
99         return enabledForStatus;
100     }
101
102     public boolean enable(Node[] nodes) {
103         TopComponent activated = TopComponent.getRegistry().getActivated();
104         if (activated instanceof DiffSetupSource) {
105             return true;
106         }
107         return super.enable(nodes) &&
108                 Lookup.getDefault().lookup(DiffProvider.class) != null;
109     }
110
111     public void performCvsAction(final Node[] nodes) {
112
113         // reevaluate fast enablement logic guess
114

115         boolean noop;
116         TopComponent activated = TopComponent.getRegistry().getActivated();
117         if (activated instanceof DiffSetupSource) {
118             noop = ((DiffSetupSource) activated).getSetups().isEmpty();
119         } else {
120             Context context = getContext(nodes);
121             File [] files = DiffExecutor.getModifiedFiles(context, FileInformation.STATUS_LOCAL_CHANGE);
122             noop = files.length == 0;
123         }
124         if (noop) {
125             NotifyDescriptor msg = new NotifyDescriptor.Message(NbBundle.getMessage(ExportDiffAction.class, "BK3001"), NotifyDescriptor.INFORMATION_MESSAGE);
126             DialogDisplayer.getDefault().notify(msg);
127             return;
128         }
129
130         final JFileChooser chooser = new AccessibleJFileChooser(NbBundle.getMessage(ExportDiffAction.class, "ACSD_Export"));
131         chooser.setDialogTitle(NbBundle.getMessage(ExportDiffAction.class, "CTL_Export_Title"));
132         chooser.setMultiSelectionEnabled(false);
133         javax.swing.filechooser.FileFilter JavaDoc[] old = chooser.getChoosableFileFilters();
134         for (int i = 0; i < old.length; i++) {
135             javax.swing.filechooser.FileFilter JavaDoc fileFilter = old[i];
136             chooser.removeChoosableFileFilter(fileFilter);
137
138         }
139         chooser.setCurrentDirectory(new File(CvsModuleConfig.getDefault().getPreferences().get("ExportDiff.saveFolder", System.getProperty("user.home")))); // NOI18N
140
chooser.addChoosableFileFilter(new javax.swing.filechooser.FileFilter JavaDoc() {
141             public boolean accept(File f) {
142                 return f.getName().endsWith("diff") || f.getName().endsWith("patch") || f.isDirectory(); // NOI18N
143
}
144             public String JavaDoc getDescription() {
145                 return NbBundle.getMessage(ExportDiffAction.class, "BK3002");
146             }
147         });
148
149         chooser.setDialogType( JFileChooser.SAVE_DIALOG ); // #71861
150
chooser.setApproveButtonMnemonic(NbBundle.getMessage(ExportDiffAction.class, "MNE_Export_ExportAction").charAt(0));
151         chooser.setApproveButtonText(NbBundle.getMessage(ExportDiffAction.class, "CTL_Export_ExportAction"));
152         DialogDescriptor dd = new DialogDescriptor(chooser, NbBundle.getMessage(ExportDiffAction.class, "CTL_Export_Title"));
153         dd.setOptions(new Object JavaDoc[0]);
154         final Dialog dialog = DialogDisplayer.getDefault().createDialog(dd);
155
156         chooser.addActionListener(new ActionListener JavaDoc() {
157             public void actionPerformed(ActionEvent JavaDoc e) {
158                 String JavaDoc state = (String JavaDoc)e.getActionCommand();
159                 if (state.equals(JFileChooser.APPROVE_SELECTION)) {
160                     File destination = chooser.getSelectedFile();
161                     String JavaDoc name = destination.getName();
162                     boolean requiredExt = false;
163                     requiredExt |= name.endsWith(".diff"); // NOI18N
164
requiredExt |= name.endsWith(".dif"); // NOI18N
165
requiredExt |= name.endsWith(".patch"); // NOI18N
166
if (requiredExt == false) {
167                         File parent = destination.getParentFile();
168                         destination = new File(parent, name + ".patch"); // NOI18N
169
}
170
171                     if (destination.exists()) {
172                         NotifyDescriptor nd = new NotifyDescriptor.Confirmation(NbBundle.getMessage(ExportDiffAction.class, "BK3005", destination.getAbsolutePath()));
173                         nd.setOptionType(NotifyDescriptor.YES_NO_OPTION);
174                         DialogDisplayer.getDefault().notify(nd);
175                         if (nd.getValue().equals(NotifyDescriptor.OK_OPTION) == false) {
176                             return;
177                         }
178                     }
179
180                     CvsModuleConfig.getDefault().getPreferences().put("ExportDiff.saveFolder", destination.getParent());
181
182                     final File out = destination;
183                     RequestProcessor.getDefault().post(new Runnable JavaDoc() {
184                         public void run() {
185                             async(nodes, out);
186                         }
187                     });
188                 }
189                 dialog.dispose();
190             }
191         });
192         dialog.setVisible(true);
193
194     }
195
196     protected boolean asynchronous() {
197         return false;
198     }
199     
200     private void async(Node[] nodes, File destination) {
201         boolean success = false;
202         OutputStream out = null;
203         int exportedFiles = 0;
204         ExecutorGroup group = new ExecutorGroup(getRunningName(nodes));
205         try {
206
207             // prepare setups and common parent - root
208

209             File root;
210             Collection setups;
211
212             TopComponent activated = TopComponent.getRegistry().getActivated();
213             if (activated instanceof DiffSetupSource) {
214                 setups = ((DiffSetupSource) activated).getSetups();
215                 List JavaDoc setupFiles = new ArrayList(setups.size());
216                 for (Iterator i = setups.iterator(); i.hasNext();) {
217                     Setup setup = (Setup) i.next();
218                     setupFiles.add(setup.getBaseFile());
219                 }
220                 root = getCommonParent((File[]) setupFiles.toArray(new File[setupFiles.size()]));
221             } else {
222                 Context context = getContext(nodes);
223                 File [] files = DiffExecutor.getModifiedFiles(context, FileInformation.STATUS_LOCAL_CHANGE);
224                 root = getCommonParent(context.getRootFiles());
225                 setups = new ArrayList(files.length);
226                 for (int i = 0; i < files.length; i++) {
227                     File file = files[i];
228                     Setup setup = new Setup(file, Setup.DIFFTYPE_LOCAL);
229                     setups.add(setup);
230                 }
231             }
232             if (root == null) {
233                 NotifyDescriptor nd = new NotifyDescriptor(
234                         NbBundle.getMessage(ExportDiffAction.class, "MSG_BadSelection_Prompt"),
235                         NbBundle.getMessage(ExportDiffAction.class, "MSG_BadSelection_Title"),
236                         NotifyDescriptor.DEFAULT_OPTION, NotifyDescriptor.ERROR_MESSAGE, null, null);
237                 DialogDisplayer.getDefault().notify(nd);
238                 return;
239             }
240
241             String JavaDoc sep = System.getProperty("line.separator"); // NOI18N
242
out = new BufferedOutputStream(new FileOutputStream(destination));
243             // Used by PatchAction as MAGIC to detect right encoding
244
out.write(("# This patch file was generated by NetBeans IDE" + sep).getBytes("utf8")); // NOI18N
245
out.write(("# Following Index: paths are relative to: " + root.getAbsolutePath() + sep).getBytes("utf8")); // NOI18N
246
out.write(("# This patch can be applied using context Tools: Patch action on respective folder." + sep).getBytes("utf8")); // NOI18N
247
out.write(("# It uses platform neutral UTF-8 encoding and \\n newlines." + sep).getBytes("utf8")); // NOI18N
248
out.write(("# Above lines and this line are ignored by the patching process." + sep).getBytes("utf8")); // NOI18N
249

250
251             Iterator it = setups.iterator();
252             int i = 0;
253             while (it.hasNext()) {
254                 Setup setup = (Setup) it.next();
255                 File file = setup.getBaseFile();
256                 group.progress(file.getName());
257
258                 String JavaDoc index = "Index: "; // NOI18N
259
String JavaDoc rootPath = root.getAbsolutePath();
260                 String JavaDoc filePath = file.getAbsolutePath();
261                 if (filePath.startsWith(rootPath)) {
262                     index += filePath.substring(rootPath.length() + 1).replace(File.separatorChar, '/') + sep;
263                     out.write(index.getBytes("utf8")); // NOI18N
264
}
265                 exportDiff(group, setup, out);
266                 i++;
267             }
268
269             exportedFiles = i;
270             success = true;
271         } catch (IOException ex) {
272             ErrorManager.getDefault().annotate(ex, NbBundle.getMessage(ExportDiffAction.class, "BK3003"));
273             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); // stack trace to log
274
ErrorManager.getDefault().notify(ErrorManager.USER, ex); // message to user
275
} finally {
276             group.executed();
277             if (out != null) {
278                 try {
279                     out.flush();
280                     out.close();
281                 } catch (IOException alreadyClsoed) {
282                 }
283             }
284             if (success) {
285                 StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(ExportDiffAction.class, "BK3004", new Integer JavaDoc(exportedFiles)));
286                 if (exportedFiles == 0) {
287                     destination.delete();
288                 }
289             } else {
290                 destination.delete();
291             }
292
293         }
294     }
295
296     private static File getCommonParent(File [] files) {
297         File root = files[0];
298         if (root.isFile()) root = root.getParentFile();
299         for (int i = 1; i < files.length; i++) {
300             root = Utils.getCommonParent(root, files[i]);
301             if (root == null) return null;
302         }
303         return root;
304     }
305
306     /** Writes contextual diff into given stream.*/
307     private void exportDiff(ExecutorGroup group, Setup setup, OutputStream out) throws IOException {
308         setup.initSources(group);
309         DiffProvider diff = (DiffProvider) Lookup.getDefault().lookup(DiffProvider.class);
310         Reader r1 = setup.getFirstSource().createReader();
311         if (r1 == null) r1 = new StringReader(""); // NOI18N
312
Reader r2 = setup.getSecondSource().createReader();
313         if (r2 == null) r2 = new StringReader(""); // NOI18N
314
Difference[] differences = diff.computeDiff(r1, r2);
315
316         File file = setup.getBaseFile();
317         String JavaDoc name = file.getAbsolutePath();
318         r1 = setup.getFirstSource().createReader();
319         if (r1 == null) r1 = new StringReader(""); // NOI18N
320
r2 = setup.getSecondSource().createReader();
321         if (r2 == null) r2 = new StringReader(""); // NOI18N
322
TextDiffVisualizer.TextDiffInfo info = new TextDiffVisualizer.TextDiffInfo(
323             name + " " + setup.getFirstSource().getTitle(), // NOI18N
324
name + " " + setup.getSecondSource().getTitle(), // NOI18N
325
null,
326             null,
327             r1,
328             r2,
329             differences
330         );
331         info.setContextMode(true, 3);
332         InputStream is = TextDiffVisualizer.differenceToContextDiffText(info);
333         while(true) {
334             int i = is.read();
335             if (i == -1) break;
336             out.write(i);
337         }
338     }
339
340 }
341
Popular Tags