KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > versioning > util > Utils


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.versioning.util;
20
21 import org.openide.util.RequestProcessor;
22 import org.openide.util.NbBundle;
23 import org.openide.util.actions.Presenter;
24 import org.openide.loaders.DataObject;
25 import org.openide.loaders.DataObjectNotFoundException;
26 import org.openide.loaders.DataShadow;
27 import org.openide.filesystems.FileObject;
28 import org.openide.filesystems.FileUtil;
29 import org.openide.awt.Actions;
30 import org.openide.nodes.Node;
31 import org.openide.text.CloneableEditorSupport;
32 import org.openide.windows.CloneableOpenSupport;
33 import org.netbeans.modules.versioning.spi.VCSContext;
34 import org.netbeans.api.project.Project;
35 import org.netbeans.api.project.ProjectUtils;
36
37 import javax.swing.text.Document JavaDoc;
38 import javax.swing.*;
39 import java.io.*;
40 import java.util.prefs.Preferences JavaDoc;
41 import java.util.prefs.BackingStoreException JavaDoc;
42 import java.util.*;
43 import java.util.logging.Logger JavaDoc;
44 import java.util.logging.Level JavaDoc;
45 import java.awt.Rectangle JavaDoc;
46 import java.awt.Point JavaDoc;
47 import java.text.MessageFormat JavaDoc;
48 import java.beans.PropertyChangeListener JavaDoc;
49 import java.beans.VetoableChangeListener JavaDoc;
50
51 /**
52  * Utilities class.
53  *
54  * @author Maros Sandor
55  */

56 public final class Utils {
57     
58     /**
59      * Request processor for quick tasks.
60      */

61     private static final RequestProcessor vcsRequestProcessor = new RequestProcessor("Versioning", 1);
62
63     /**
64      * Request processor for long running tasks.
65      */

66     private static final RequestProcessor vcsBlockingRequestProcessor = new RequestProcessor("Versioning long tasks", 1);
67
68     private Utils() {
69     }
70
71     /**
72      * Creates a task that will run in the Versioning RequestProcessor (with has throughput of 1). The runnable may take long
73      * to execute (connet through network, etc).
74      *
75      * @param runnable Runnable to run
76      * @return RequestProcessor.Task created task
77      */

78     public static RequestProcessor.Task createTask(Runnable JavaDoc runnable) {
79         return vcsBlockingRequestProcessor.create(runnable);
80     }
81
82     /**
83      * Runs the runnable in the Versioning RequestProcessor (with has throughput of 1). The runnable must not take long
84      * to execute (connet through network, etc).
85      *
86      * @param runnable Runnable to run
87      */

88     public static void post(Runnable JavaDoc runnable) {
89         vcsRequestProcessor.post(runnable);
90     }
91     
92     /**
93      * Tests for parent/child file relationsip.
94      *
95      * @param parent supposed parent of the file
96      * @param file a file
97      * @return true if parent is a parent folder of file OR both parameters are equal, false otherwise
98      */

99     public static boolean isParentOrEqual(File parent, File file) {
100         if (parent instanceof FlatFolder) {
101             return parent.equals(file) || parent.equals(file.getParentFile()) && !file.isDirectory();
102         }
103         for (; file != null; file = file.getParentFile()) {
104             if (file.equals(parent)) return true;
105         }
106         return false;
107     }
108
109     /**
110      * Tests whether all files belong to the same data object.
111      *
112      * @param files array of Files
113      * @return true if all files share common DataObject (even null), false otherwise
114      */

115     public static boolean shareCommonDataObject(File[] files) {
116         if (files == null || files.length < 2) return true;
117         DataObject common = findDataObject(files[0]);
118         for (int i = 1; i < files.length; i++) {
119             DataObject dao = findDataObject(files[i]);
120             if (dao != common && (dao == null || !dao.equals(common))) return false;
121         }
122         return true;
123     }
124
125     /**
126      * @param file
127      * @return Set<File> all files that belong to the same DataObject as the argument
128      */

129     public static Set<File> getAllDataObjectFiles(File file) {
130         Set<File> filesToCheckout = new HashSet<File>(2);
131         filesToCheckout.add(file);
132         FileObject fo = FileUtil.toFileObject(file);
133         if (fo != null) {
134             try {
135                 DataObject dao = DataObject.find(fo);
136                 Set<FileObject> fileObjects = dao.files();
137                 for (FileObject fileObject : fileObjects) {
138                     filesToCheckout.add(FileUtil.toFile(fileObject));
139                 }
140             } catch (DataObjectNotFoundException e) {
141                 // no dataobject, never mind
142
}
143         }
144         return filesToCheckout;
145     }
146     
147     private static DataObject findDataObject(File file) {
148         FileObject fo = FileUtil.toFileObject(file);
149         if (fo != null) {
150             try {
151                 return DataObject.find(fo);
152             } catch (DataObjectNotFoundException e) {
153                 // ignore
154
}
155         }
156         return null;
157     }
158     
159     /**
160      * Copies all content from the supplied reader to the supplies writer and closes both streams when finished.
161      *
162      * @param writer where to write
163      * @param reader what to read
164      * @throws IOException if any I/O operation fails
165      */

166     public static void copyStreamsCloseAll(OutputStream writer, InputStream reader) throws IOException {
167         byte [] buffer = new byte[4096];
168         int n;
169         while ((n = reader.read(buffer)) != -1) {
170             writer.write(buffer, 0, n);
171         }
172         writer.close();
173         reader.close();
174     }
175
176     /**
177      * Copies all content from the supplied reader to the supplies writer and closes both streams when finished.
178      *
179      * @param writer where to write
180      * @param reader what to read
181      * @throws IOException if any I/O operation fails
182      */

183     public static void copyStreamsCloseAll(Writer writer, Reader reader) throws IOException {
184         char [] buffer = new char[4096];
185         int n;
186         while ((n = reader.read(buffer)) != -1) {
187             writer.write(buffer, 0, n);
188         }
189         writer.close();
190         reader.close();
191     }
192     
193     /**
194      * Helper method to get an array of Strings from preferences.
195      *
196      * @param prefs storage
197      * @param key key of the String array
198      * @return List<String> stored List of String or an empty List if the key was not found (order is preserved)
199      */

200     public static List<String JavaDoc> getStringList(Preferences JavaDoc prefs, String JavaDoc key) {
201         List<String JavaDoc> retval = new ArrayList<String JavaDoc>();
202         try {
203             String JavaDoc[] keys = prefs.keys();
204             for (int i = 0; i < keys.length; i++) {
205                 String JavaDoc k = keys[i];
206                 if (k != null && k.startsWith(key)) {
207                     int idx = Integer.parseInt(k.substring(k.lastIndexOf('.') + 1));
208                     retval.add(idx + "." + prefs.get(k, null));
209                 }
210             }
211             List<String JavaDoc> rv = new ArrayList<String JavaDoc>(retval.size());
212             rv.addAll(retval);
213             for (String JavaDoc s : retval) {
214                 int pos = s.indexOf('.');
215                 int index = Integer.parseInt(s.substring(0, pos));
216                 rv.set(index, s.substring(pos + 1));
217             }
218             return rv;
219         } catch (Exception JavaDoc ex) {
220             Logger.getLogger(Utils.class.getName()).log(Level.INFO, null, ex);
221             return new ArrayList<String JavaDoc>(0);
222         }
223     }
224
225     /**
226      * Stores a List of Strings into Preferences node under the given key.
227      *
228      * @param prefs storage
229      * @param key key of the String array
230      * @param value List of Strings to write (order will be preserved)
231      */

232     public static void put(Preferences JavaDoc prefs, String JavaDoc key, List<String JavaDoc> value) {
233         try {
234             String JavaDoc[] keys = prefs.keys();
235             for (int i = 0; i < keys.length; i++) {
236                 String JavaDoc k = keys[i];
237                 if (k != null && k.startsWith(key + ".")) {
238                     prefs.remove(k);
239                 }
240             }
241             int idx = 0;
242             for (String JavaDoc s : value) {
243                 prefs.put(key + "." + idx++, s);
244             }
245         } catch (BackingStoreException JavaDoc ex) {
246             Logger.getLogger(Utils.class.getName()).log(Level.INFO, null, ex);
247         }
248     }
249
250     /**
251      * Convenience method for storing array of Strings with a maximum length with LRU policy. Supplied value is
252      * stored at index 0 and all items beyond (maxLength - 1) index are discarded. <br>
253      * If the value is already stored then it will be first removed from its old position.
254      *
255      * @param prefs storage
256      * @param key key for the array
257      * @param value String to store
258      * @param maxLength maximum length of the stored array. won't be considered if &lt; 0
259      */

260     public static void insert(Preferences JavaDoc prefs, String JavaDoc key, String JavaDoc value, int maxLength) {
261         List<String JavaDoc> newValues = getStringList(prefs, key);
262         if(newValues.contains(value)) {
263             newValues.remove(value);
264         }
265         newValues.add(0, value);
266         if (maxLength > -1 && newValues.size() > maxLength) {
267             newValues.subList(maxLength, newValues.size()).clear();
268         }
269         put(prefs, key, newValues);
270     }
271     
272     /**
273      * Convenience method to remove a array of values from a in preferences stored array of Strings
274      *
275      * @param prefs storage
276      * @param key key for the array
277      * @param values Strings to remove
278      */

279     public static void removeFromArray(Preferences JavaDoc prefs, String JavaDoc key, List<String JavaDoc> values) {
280         List<String JavaDoc> newValues = getStringList(prefs, key);
281         newValues.removeAll(values);
282         put(prefs, key, newValues);
283     }
284
285     /**
286      * Convenience method to remove a value from a in preferences stored array of Strings
287      *
288      * @param prefs storage
289      * @param key key for the array
290      * @param value String to remove
291      */

292     public static void removeFromArray(Preferences JavaDoc prefs, String JavaDoc key, String JavaDoc value) {
293         List<String JavaDoc> newValues = getStringList(prefs, key);
294         newValues.remove(value);
295         put(prefs, key, newValues);
296     }
297     
298     /**
299      * Splits files/folders into 2 groups: flat folders and other files
300      *
301      * @param files array of files to split
302      * @return File[][] the first array File[0] contains flat folders (@see #flatten for their direct descendants),
303      * File[1] contains all other files
304      */

305     public static File[][] splitFlatOthers(File [] files) {
306         Set<File> flat = new HashSet<File>(1);
307         for (int i = 0; i < files.length; i++) {
308             if (files[i] instanceof FlatFolder) {
309                 flat.add(files[i]);
310             }
311         }
312         if (flat.size() == 0) {
313             return new File[][] { new File[0], files };
314         } else {
315             Set<File> allFiles = new HashSet<File>(Arrays.asList(files));
316             allFiles.removeAll(flat);
317             return new File[][] {
318                 flat.toArray(new File[flat.size()]),
319                 allFiles.toArray(new File[allFiles.size()])
320             };
321         }
322     }
323
324     /**
325      * Recursively deletes the file or directory.
326      *
327      * @param file file/directory to delete
328      */

329     public static void deleteRecursively(File file) {
330         if (file.isDirectory()) {
331             File [] files = file.listFiles();
332             for (int i = 0; i < files.length; i++) {
333                 deleteRecursively(files[i]);
334             }
335         }
336         file.delete();
337     }
338
339     /**
340      * Searches for common filesystem parent folder for given files.
341      *
342      * @param a first file
343      * @param b second file
344      * @return File common parent for both input files with the longest filesystem path or null of these files
345      * have not a common parent
346      */

347     public static File getCommonParent(File a, File b) {
348         for (;;) {
349             if (a.equals(b)) {
350                 return a;
351             } else if (a.getAbsolutePath().length() > b.getAbsolutePath().length()) {
352                 a = a.getParentFile();
353                 if (a == null) return null;
354             } else {
355                 b = b.getParentFile();
356                 if (b == null) return null;
357             }
358         }
359     }
360
361     public static String JavaDoc getStackTrace() {
362         Exception JavaDoc e = new Exception JavaDoc();
363         e.fillInStackTrace();
364         StringWriter sw = new StringWriter();
365         e.printStackTrace(new PrintWriter(sw));
366         return sw.toString();
367     }
368
369     /**
370      * Copied from org.netbeans.api.xml.parsers.DocumentInputSource to save whole module dependency.
371      *
372      * @param doc a Document to read
373      * @return Reader a reader that reads document's text
374      */

375     public static Reader getDocumentReader(final Document JavaDoc doc) {
376         final String JavaDoc[] str = new String JavaDoc[1];
377         Runnable JavaDoc run = new Runnable JavaDoc() {
378             public void run () {
379                 try {
380                     str[0] = doc.getText(0, doc.getLength());
381                 } catch (javax.swing.text.BadLocationException JavaDoc e) {
382                     // impossible
383
e.printStackTrace();
384                 }
385             }
386         };
387         doc.render(run);
388         return new StringReader(str[0]);
389     }
390
391     /**
392      * For popups invoked by keyboard determines best location for it.
393      *
394      * @param table source of popup event
395      * @return Point best location for menu popup
396      */

397     public static Point JavaDoc getPositionForPopup(JTable table) {
398         int idx = table.getSelectedRow();
399         if (idx == -1) idx = 0;
400         Rectangle JavaDoc rect = table.getCellRect(idx, 1, true);
401         return rect.getLocation();
402     }
403
404     /**
405      * Creates a menu item from an action.
406      *
407      * @param action an action
408      * @return JMenuItem
409      */

410     public static JMenuItem toMenuItem(Action action) {
411         JMenuItem item;
412         if (action instanceof Presenter.Menu) {
413             item = ((Presenter.Menu) action).getMenuPresenter();
414         } else {
415             item = new JMenuItem();
416             Actions.connect(item, action, false);
417         }
418         return item;
419     }
420
421     public static File getTempFolder() {
422         File tmpDir = new File(System.getProperty("java.io.tmpdir")); // NOI18N
423
for (;;) {
424             File dir = new File(tmpDir, "vcs-" + Long.toString(System.currentTimeMillis())); // NOI18N
425
if (!dir.exists() && dir.mkdirs()) {
426                 dir.deleteOnExit();
427                 return FileUtil.normalizeFile(dir);
428             }
429         }
430     }
431
432     /**
433      * Utility method to word-wrap a String.
434      *
435      * @param s String to wrap
436      * @param maxLineLength maximum length of one line. If less than 1 no wrapping will occurr
437      * @return String wrapped string
438      */

439     public static String JavaDoc wordWrap(String JavaDoc s, int maxLineLength) {
440         int n = s.length() - 1;
441         if (maxLineLength < 1 || n < maxLineLength) return s;
442         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
443
444         int currentWrap = 0;
445         for (;;) {
446             int nextWrap = currentWrap + maxLineLength - 1;
447             if (nextWrap >= n) {
448                 sb.append(s.substring(currentWrap));
449                 break;
450             }
451             int idx = s.lastIndexOf(' ', nextWrap + 1);
452             if (idx > currentWrap) {
453                 sb.append(s.substring(currentWrap, idx).trim());
454                 currentWrap = idx + 1;
455             } else {
456                 sb.append(s.substring(currentWrap, nextWrap + 1));
457                 currentWrap = nextWrap + 1;
458             }
459             sb.append('\n');
460         }
461         return sb.toString();
462     }
463
464     /**
465      * Computes display name of an action based on its context.
466      *
467      * @param clazz caller class for bundle location
468      * @param baseName base bundle name
469      * @param ctx action's context
470      * @return String full name of the action, eg. Show "File.java" Annotations
471      */

472     public static String JavaDoc getActionName(Class JavaDoc clazz, String JavaDoc baseName, VCSContext ctx) {
473         Set<File> nodes = ctx.getRootFiles();
474         int objectCount = nodes.size();
475         // if all nodes represent project node the use plain name
476
// It avoids "Show changes 2 files" on project node
477
// caused by fact that project contains two source groups.
478

479         Node[] activatedNodes = ctx.getNodes();
480         boolean projectsOnly = true;
481         for (int i = 0; i < activatedNodes.length; i++) {
482             Node activatedNode = activatedNodes[i];
483             Project project = (Project) activatedNode.getLookup().lookup(Project.class);
484             if (project == null) {
485                 projectsOnly = false;
486                 break;
487             }
488         }
489         if (projectsOnly) objectCount = activatedNodes.length;
490
491         if (objectCount == 0) {
492             return NbBundle.getBundle(clazz).getString(baseName);
493         } else if (objectCount == 1) {
494             if (projectsOnly) {
495                 String JavaDoc dispName = ProjectUtils.getInformation((Project) activatedNodes[0].getLookup().lookup(Project.class)).getDisplayName();
496                 return NbBundle.getMessage(clazz, baseName + "_Context", // NOI18N
497
dispName);
498             }
499             String JavaDoc name;
500             FileObject fo = (FileObject) activatedNodes[0].getLookup().lookup(FileObject.class);
501             if (fo != null) {
502                 name = fo.getNameExt();
503             } else {
504                 DataObject dao = (DataObject) activatedNodes[0].getLookup().lookup(DataObject.class);
505                 if (dao instanceof DataShadow) {
506                     dao = ((DataShadow) dao).getOriginal();
507                 }
508                 if (dao != null) {
509                     name = dao.getPrimaryFile().getNameExt();
510                 } else {
511                     name = activatedNodes[0].getDisplayName();
512                 }
513             }
514             return MessageFormat.format(NbBundle.getBundle(clazz).getString(baseName + "_Context"), name); // NOI18N
515
} else {
516             if (projectsOnly) {
517                 try {
518                     return MessageFormat.format(NbBundle.getBundle(clazz).getString(baseName + "_Projects"), objectCount); // NOI18N
519
} catch (MissingResourceException ex) {
520                     // ignore use files alternative bellow
521
}
522             }
523             return MessageFormat.format(NbBundle.getBundle(clazz).getString(baseName + "_Context_Multiple"), objectCount); // NOI18N
524
}
525     }
526
527     /**
528      * Computes display name of a context.
529      *
530      * @param ctx a context
531      * @return String short display name of the context, eg. File.java, 3 Files, 2 Projects, etc.
532      */

533     public static String JavaDoc getContextDisplayName(VCSContext ctx) {
534         // TODO: reuse this code in getActionName()
535
Set<File> nodes = ctx.getRootFiles();
536         int objectCount = nodes.size();
537         // if all nodes represent project node the use plain name
538
// It avoids "Show changes 2 files" on project node
539
// caused by fact that project contains two source groups.
540

541         Node[] activatedNodes = ctx.getNodes();
542         boolean projectsOnly = true;
543         for (int i = 0; i < activatedNodes.length; i++) {
544             Node activatedNode = activatedNodes[i];
545             Project project = (Project) activatedNode.getLookup().lookup(Project.class);
546             if (project == null) {
547                 projectsOnly = false;
548                 break;
549             }
550         }
551         if (projectsOnly) objectCount = activatedNodes.length;
552
553         if (objectCount == 0) {
554             return null;
555         } else if (objectCount == 1) {
556             if (projectsOnly) {
557                 return ProjectUtils.getInformation((Project) activatedNodes[0].getLookup().lookup(Project.class)).getDisplayName();
558             }
559             FileObject fo = (FileObject) activatedNodes[0].getLookup().lookup(FileObject.class);
560             if (fo != null) {
561                 return fo.getNameExt();
562             } else {
563                 DataObject dao = (DataObject) activatedNodes[0].getLookup().lookup(DataObject.class);
564                 if (dao instanceof DataShadow) {
565                     dao = ((DataShadow) dao).getOriginal();
566                 }
567                 if (dao != null) {
568                     return dao.getPrimaryFile().getNameExt();
569                 } else {
570                     return activatedNodes[0].getDisplayName();
571                 }
572             }
573         } else {
574             if (projectsOnly) {
575                 try {
576                     return MessageFormat.format(NbBundle.getBundle(Utils.class).getString("MSG_ActionContext_MultipleProjects"), objectCount); // NOI18N
577
} catch (MissingResourceException ex) {
578                     // ignore use files alternative bellow
579
}
580             }
581             return MessageFormat.format(NbBundle.getBundle(Utils.class).getString("MSG_ActionContext_MultipleFiles"), objectCount); // NOI18N
582
}
583     }
584
585     /**
586      * Open a read-only view of the file in editor area.
587      *
588      * @param fo a file to open
589      * @param revision revision of the file
590      */

591     public static void openFile(FileObject fo, String JavaDoc revision) {
592         ViewEnv env = new ViewEnv(fo);
593         CloneableEditorSupport ces = new ViewCES(env, fo.getNameExt() + " @ " + revision); // NOI18N
594
ces.view();
595     }
596
597     private static class ViewEnv implements CloneableEditorSupport.Env {
598         
599         private final FileObject file;
600
601         public ViewEnv(FileObject file) {
602             this.file = file;
603         }
604
605         public InputStream inputStream() throws IOException {
606             return file.getInputStream();
607         }
608
609         public OutputStream outputStream() throws IOException {
610             throw new IOException();
611         }
612
613         public Date getTime() {
614             return file.lastModified();
615         }
616
617         public String JavaDoc getMimeType() {
618             return file.getMIMEType();
619         }
620
621         public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
622         }
623
624         public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
625         }
626
627         public void addVetoableChangeListener(VetoableChangeListener JavaDoc l) {
628         }
629
630         public void removeVetoableChangeListener(VetoableChangeListener JavaDoc l) {
631         }
632
633         public boolean isValid() {
634             return file.isValid();
635         }
636
637         public boolean isModified() {
638             return false;
639         }
640
641         public void markModified() throws IOException {
642             throw new IOException();
643         }
644
645         public void unmarkModified() {
646         }
647
648         public CloneableOpenSupport findCloneableOpenSupport() {
649             return null;
650         }
651     }
652     
653     private static class ViewCES extends CloneableEditorSupport {
654         
655         private final String JavaDoc name;
656
657         public ViewCES(Env env, String JavaDoc name) {
658             super(env);
659             this.name = name;
660         }
661
662         protected String JavaDoc messageSave() {
663             return name;
664         }
665
666         protected String JavaDoc messageName() {
667             return name;
668         }
669
670         protected String JavaDoc messageToolTip() {
671             return name;
672         }
673
674         protected String JavaDoc messageOpening() {
675             return name;
676         }
677
678         protected String JavaDoc messageOpened() {
679             return name;
680         }
681     }
682 }
683
Popular Tags