KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > config > UserPreferences


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2004,2005 Dave Brosius <dbrosius@qis.net>
4  * Copyright (C) 2004,2005 University of Maryland
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */

20
21 /*
22  * UserPreferences.java
23  *
24  * Created on May 26, 2004, 11:55 PM
25  */

26
27 package edu.umd.cs.findbugs.config;
28
29 import java.io.BufferedInputStream JavaDoc;
30 import java.io.BufferedOutputStream JavaDoc;
31 import java.io.File JavaDoc;
32 import java.io.FileInputStream JavaDoc;
33 import java.io.FileOutputStream JavaDoc;
34 import java.io.IOException JavaDoc;
35 import java.io.InputStream JavaDoc;
36 import java.io.OutputStream JavaDoc;
37 import java.util.ArrayList JavaDoc;
38 import java.util.Collections JavaDoc;
39 import java.util.Comparator JavaDoc;
40 import java.util.Enumeration JavaDoc;
41 import java.util.HashMap JavaDoc;
42 import java.util.Iterator JavaDoc;
43 import java.util.LinkedList JavaDoc;
44 import java.util.List JavaDoc;
45 import java.util.Map JavaDoc;
46 import java.util.Properties JavaDoc;
47 import java.util.Set JavaDoc;
48 import java.util.Vector JavaDoc;
49 import java.util.Map.Entry;
50
51 import edu.umd.cs.findbugs.DetectorFactory;
52 import edu.umd.cs.findbugs.DetectorFactoryCollection;
53 import edu.umd.cs.findbugs.FindBugs;
54 import edu.umd.cs.findbugs.SystemProperties;
55
56 /**
57  * User Preferences outside of any one Project.
58  * This consists of a class to manage the findbugs.prop file found in the user.home.
59  *
60  * @author Dave Brosius
61  */

62 public class UserPreferences implements Cloneable JavaDoc {
63     private static final String JavaDoc PREF_FILE_NAME = ".Findbugs_prefs";
64     private static final int MAX_RECENT_FILES = 9;
65     private static final String JavaDoc DETECTOR_THRESHOLD_KEY = "detector_threshold";
66     private static final String JavaDoc FILTER_SETTINGS_KEY = "filter_settings";
67     private static final String JavaDoc FILTER_SETTINGS2_KEY = "filter_settings_neg";
68     private static final String JavaDoc DEFAULT_DIRECTORY = "default_directory";
69     private LinkedList JavaDoc<String JavaDoc> recentProjectsList = new LinkedList JavaDoc<String JavaDoc>();
70     private Map JavaDoc<String JavaDoc, Boolean JavaDoc> detectorEnablementMap = new HashMap JavaDoc<String JavaDoc, Boolean JavaDoc>();
71     private ProjectFilterSettings filterSettings;
72     private static UserPreferences preferencesSingleton = new UserPreferences();
73
74     private UserPreferences() {
75         this.filterSettings = ProjectFilterSettings.createDefault();
76     }
77     
78     /**
79      * Create default UserPreferences.
80      *
81      * @return default UserPreferences
82      */

83     public static UserPreferences createDefaultUserPreferences() {
84         return new UserPreferences();
85     }
86
87     /**
88      * Get UserPreferences singleton.
89      * This should only be used if there is a single set of user
90      * preferences to be used for all projects.
91      *
92      * @return the UserPreferences
93      */

94     public static UserPreferences getUserPreferences() {
95         return preferencesSingleton;
96     }
97
98     /**
99      * Read persistent global UserPreferences from file in
100      * the user's home directory.
101      */

102     public void read() {
103         File JavaDoc prefFile = new File JavaDoc(SystemProperties.getProperty("user.home"), PREF_FILE_NAME);
104         if (!prefFile.exists() || !prefFile.isFile())
105             return;
106         try {
107             read(new FileInputStream JavaDoc(prefFile));
108         } catch (IOException JavaDoc e) {
109             // Ignore - just use default preferences
110
}
111     }
112     
113     /**
114      * Read user preferences from given input stream.
115      * The InputStream is guaranteed to be closed by this method.
116      *
117      * @param in the InputStream
118      * @throws IOException
119      */

120     public void read(InputStream JavaDoc in) throws IOException JavaDoc {
121         BufferedInputStream JavaDoc prefStream = null;
122         Properties JavaDoc props = new Properties JavaDoc();
123         try {
124             prefStream = new BufferedInputStream JavaDoc(in);
125             props.load(prefStream);
126         } finally {
127             try {
128                 if (prefStream != null)
129                     prefStream.close();
130             } catch (IOException JavaDoc ioe) {
131                 // Ignore
132
}
133         }
134
135         if (props.size() == 0)
136             return;
137         for (int i = 0; i < MAX_RECENT_FILES; i++) {
138             String JavaDoc key = "recent" + i;
139             String JavaDoc projectName = (String JavaDoc) props.get(key);
140             if (projectName != null)
141                 recentProjectsList.add(projectName);
142         }
143
144         Iterator JavaDoc propKeysIter = props.keySet().iterator();
145         while(propKeysIter.hasNext()){
146             String JavaDoc key = (String JavaDoc) propKeysIter.next();
147             if(!key.startsWith("detector") || key.startsWith("detector_")){
148                 // it is not a detector enablement property
149
continue;
150             }
151             String JavaDoc detectorState = (String JavaDoc) props.get(key);
152             int pipePos = detectorState.indexOf("|");
153             if (pipePos >= 0) {
154                 String JavaDoc name = detectorState.substring(0, pipePos);
155                 String JavaDoc enabled = detectorState.substring(pipePos + 1);
156                 detectorEnablementMap.put(name, Boolean.valueOf(enabled));
157             }
158         }
159
160         if (props.get(FILTER_SETTINGS_KEY) != null) {
161             // Properties contain encoded project filter settings.
162
filterSettings = ProjectFilterSettings.fromEncodedString(props.getProperty(FILTER_SETTINGS_KEY));
163         } else {
164             // Properties contain only minimum warning priority threshold (probably).
165
// We will honor this threshold, and enable all bug categories.
166
String JavaDoc threshold = (String JavaDoc) props.get(DETECTOR_THRESHOLD_KEY);
167             if (threshold != null) {
168                 try {
169                     int detectorThreshold = Integer.parseInt(threshold);
170                     setUserDetectorThreshold(detectorThreshold);
171                 } catch (NumberFormatException JavaDoc nfe) {
172                     //Ok to ignore
173
}
174             }
175         }
176         if (props.get(FILTER_SETTINGS2_KEY) != null) {
177             // populate the hidden bug categories in the project filter settings
178
ProjectFilterSettings.hiddenFromEncodedString(filterSettings, props.getProperty(FILTER_SETTINGS2_KEY));
179         }
180         
181         String JavaDoc dd = (String JavaDoc)props.get(DEFAULT_DIRECTORY);
182         if (dd != null)
183             System.setProperty("user.dir", dd);
184
185     }
186
187     /**
188      * Write persistent global UserPreferences to file
189      * in user's home directory.
190      */

191     public void write() {
192         try {
193             File JavaDoc prefFile = new File JavaDoc(SystemProperties.getProperty("user.home"), PREF_FILE_NAME);
194             write(new FileOutputStream JavaDoc(prefFile));
195         } catch (IOException JavaDoc e) {
196             if (FindBugs.DEBUG) e.printStackTrace(); // Ignore
197
}
198     }
199
200     /**
201      * Write UserPreferences to given OutputStream.
202      * The OutputStream is guaranteed to be closed by this method.
203      *
204      * @param out the OutputStream
205      * @throws IOException
206      */

207     public void write(OutputStream JavaDoc out) throws IOException JavaDoc {
208         
209         Properties JavaDoc props = new Properties JavaDoc() {
210             /**
211              * Overriden to be able to write properties sorted by keys to the disk
212              * @see java.util.Hashtable#keys()
213              */

214             @SuppressWarnings JavaDoc("unchecked")
215             @Override JavaDoc
216             public synchronized Enumeration JavaDoc<Object JavaDoc> keys() {
217                 // sort elements based on detector (prop key) names
218
Set JavaDoc set = keySet();
219                 return sortKeys(set);
220             }
221         };
222         
223         for (int i = 0; i < recentProjectsList.size(); i++) {
224             String JavaDoc projectName = recentProjectsList.get(i);
225             String JavaDoc key = "recent" + i;
226             props.put(key, projectName);
227         }
228
229         Iterator JavaDoc<Entry<String JavaDoc, Boolean JavaDoc>> it = detectorEnablementMap.entrySet().iterator();
230         while (it.hasNext()) {
231             Entry<String JavaDoc, Boolean JavaDoc> entry = it.next();
232             props.put("detector" + entry.getKey(), entry.getKey() + "|" + String.valueOf(entry.getValue().booleanValue()));
233         }
234
235         // Save ProjectFilterSettings
236
props.put(FILTER_SETTINGS_KEY, filterSettings.toEncodedString());
237         props.put(FILTER_SETTINGS2_KEY, filterSettings.hiddenToEncodedString());
238         
239         // Backwards-compatibility: save minimum warning priority as integer.
240
// This will allow the properties file to work with older versions
241
// of FindBugs.
242
props.put(DETECTOR_THRESHOLD_KEY, String.valueOf(filterSettings.getMinPriorityAsInt()));
243         
244         props.put(DEFAULT_DIRECTORY, SystemProperties.getProperty("user.dir"));
245
246         OutputStream JavaDoc prefStream = null;
247         try {
248             prefStream = new BufferedOutputStream JavaDoc(out);
249             props.store(prefStream, "FindBugs User Preferences");
250             prefStream.flush();
251         } finally {
252             try {
253                 if (prefStream != null)
254                     prefStream.close();
255             } catch (IOException JavaDoc ioe) {
256             }
257         }
258     }
259     
260     /**
261      * To be compatible with version control systems, we need to sort properties before
262      * storing them to disk. Otherwise each change may lead to problems by diff against
263      * previous version - because Property entries are randomly distributed (it's a map).
264      *
265      * @param keySet non null set instance to sort
266      * @return non null list wich contains all given keys, sorted lexicographically.
267      * The list may be empty if given set was empty
268      */

269     private Enumeration JavaDoc sortKeys(Set JavaDoc<String JavaDoc> keySet) {
270         List JavaDoc<String JavaDoc> sortedList = new ArrayList JavaDoc<String JavaDoc>();
271         sortedList.addAll(keySet);
272         Collections.sort(sortedList);
273         return Collections.enumeration(sortedList);
274     }
275     
276     /**
277      * Get List of recent project filenames.
278      *
279      * @return List of recent project filenames
280      */

281     public List JavaDoc<String JavaDoc> getRecentProjects() {
282         return recentProjectsList;
283     }
284
285     /**
286      * Add given project filename to the front of the recently-used
287      * project list.
288      *
289      * @param projectName project filename
290      */

291     public void useProject(String JavaDoc projectName) {
292         removeProject(projectName);
293         recentProjectsList.addFirst(projectName);
294         while (recentProjectsList.size() > MAX_RECENT_FILES)
295             recentProjectsList.removeLast();
296     }
297
298     /**
299      * Remove project filename from the recently-used project list.
300      *
301      * @param projectName project filename
302      */

303     public void removeProject(String JavaDoc projectName) {
304         //It should only be in list once (usually in slot 0) but check entire list...
305
Iterator JavaDoc<String JavaDoc> it = recentProjectsList.iterator();
306         while (it.hasNext()) {
307             //LinkedList, so remove() via iterator is faster than remove(index).
308
if (projectName.equals(it.next())) it.remove();
309         }
310     }
311     
312     /**
313      * Set the enabled/disabled status of given Detector.
314      *
315      * @param factory the DetectorFactory for the Detector to be enabled/disabled
316      * @param enable true if the Detector should be enabled,
317      * false if it should be Disabled
318      */

319     public void enableDetector(DetectorFactory factory, boolean enable) {
320         detectorEnablementMap.put(factory.getShortName(), enable ? Boolean.TRUE : Boolean.FALSE);
321     }
322     
323     /**
324      * Get the enabled/disabled status of given Detector.
325      *
326      * @param factory the DetectorFactory of the Detector
327      * @return true if the Detector is enabled, false if not
328      */

329     public boolean isDetectorEnabled(DetectorFactory factory) {
330         String JavaDoc detectorName = factory.getShortName();
331         Boolean JavaDoc enabled = detectorEnablementMap.get(detectorName);
332         if (enabled == null) {
333             // No explicit preference has been specified for this detector,
334
// so use the default enablement specified by the
335
// DetectorFactory.
336
enabled = factory.isDefaultEnabled() ? Boolean.TRUE : Boolean.FALSE;
337             detectorEnablementMap.put(detectorName, enabled);
338         }
339         return enabled.booleanValue();
340     }
341
342     /**
343      * Enable or disable all known Detectors.
344      *
345      * @param enable true if all detectors should be enabled,
346      * false if they should all be disabled
347      */

348     public void enableAllDetectors(boolean enable) {
349         detectorEnablementMap.clear();
350         
351         DetectorFactoryCollection factoryCollection = DetectorFactoryCollection.instance();
352         for (Iterator JavaDoc<DetectorFactory> i = factoryCollection.factoryIterator(); i.hasNext();) {
353             DetectorFactory factory = i.next();
354             detectorEnablementMap.put(
355                     factory.getShortName(), enable ? Boolean.TRUE : Boolean.FALSE);
356         }
357     }
358     
359     /**
360      * Set the ProjectFilterSettings.
361      *
362      * @param filterSettings the ProjectFilterSettings
363      */

364     public void setProjectFilterSettings(ProjectFilterSettings filterSettings) {
365         this.filterSettings = filterSettings;
366     }
367     
368     /**
369      * Get ProjectFilterSettings.
370      *
371      * @return the ProjectFilterSettings
372      */

373     public ProjectFilterSettings getFilterSettings() {
374         return this.filterSettings;
375     }
376
377     /**
378      * Get the detector threshold (min severity to report a warning).
379      *
380      * @return the detector threshold
381      */

382     public int getUserDetectorThreshold() {
383         return filterSettings.getMinPriorityAsInt();
384     }
385
386     /**
387      * Set the detector threshold (min severity to report a warning).
388      *
389      * @param threshold the detector threshold
390      */

391     public void setUserDetectorThreshold(int threshold) {
392         String JavaDoc minPriority = ProjectFilterSettings.getIntPriorityAsString(threshold);
393         filterSettings.setMinPriority(minPriority);
394     }
395     
396     /**
397      * Set the detector threshold (min severity to report a warning).
398      *
399      * @param threshold the detector threshold
400      */

401     public void setUserDetectorThreshold(String JavaDoc threshold) {
402         filterSettings.setMinPriority(threshold);
403     }
404     //@Override
405
@Override JavaDoc
406          public boolean equals(Object JavaDoc obj) {
407         if (obj == null || obj.getClass() != this.getClass())
408             return false;
409         
410         UserPreferences other = (UserPreferences) obj;
411         
412         return recentProjectsList.equals(other.recentProjectsList)
413             && detectorEnablementMap.equals(other.detectorEnablementMap)
414             && filterSettings.equals(other.filterSettings);
415     }
416     
417     //@Override
418
@Override JavaDoc
419          public int hashCode() {
420         return recentProjectsList.hashCode()
421             + detectorEnablementMap.hashCode()
422             + filterSettings.hashCode();
423     }
424     
425     //@Override
426
@Override JavaDoc
427          public Object JavaDoc clone() {
428         try {
429             UserPreferences dup = (UserPreferences) super.clone();
430             
431             dup.recentProjectsList = new LinkedList JavaDoc<String JavaDoc>();
432             dup.recentProjectsList.addAll(this.recentProjectsList);
433             
434             dup.detectorEnablementMap = new HashMap JavaDoc<String JavaDoc, Boolean JavaDoc>();
435             dup.detectorEnablementMap.putAll(this.detectorEnablementMap);
436             
437             dup.filterSettings = (ProjectFilterSettings) this.filterSettings.clone();
438             
439             return dup;
440         } catch (CloneNotSupportedException JavaDoc e) {
441             throw new AssertionError JavaDoc(e);
442         }
443     }
444 }
445
446 // vim:ts=4
447
Popular Tags