View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.log4j.chainsaw.prefs;
18  
19  import javax.swing.event.EventListenerList;
20  import java.io.*;
21  import java.net.URLEncoder;
22  import java.util.EventListener;
23  import java.util.Properties;
24  
25  
26  /**
27   * SettingManager allows components to register interest in Saving/Loading
28   * of general application preferences/settings.
29   *
30   * @author Paul Smith <psmith@apache.org>
31   * @author Scott Deboy <sdeboy@apache.org>
32   */
33  public final class SettingsManager {
34      private static final SettingsManager instance = new SettingsManager();
35      private static final String GLOBAL_SETTINGS_FILE_NAME = "chainsaw.settings.properties";
36      private static final String HEADER = "Chainsaws Settings Files";
37      private EventListenerList listenerList = new EventListenerList();
38      private Properties defaultProperties = new Properties();
39  
40      /**
41       * Initialises the SettingsManager by loading the default Properties from
42       * a resource
43       */
44      private SettingsManager() {
45          //	load the default properties as a Resource
46          InputStream is = null;
47  
48          try {
49              is = this.getClass().getClassLoader()
50                  .getResource("org/apache/log4j/chainsaw/prefs/default.properties")
51                  .openStream();
52              defaultProperties.load(is);
53  
54              //      defaultProperties.list(System.out);
55              is.close();
56          } catch (IOException e) {
57              e.printStackTrace();
58          } finally {
59              if (is != null) {
60                  try {
61                      is.close();
62                  } catch (Exception e) {
63                  }
64              }
65          }
66      }
67  
68      /**
69       * Returns the singleton instance of the SettingsManager
70       *
71       * @return settings manager
72       */
73      public static SettingsManager getInstance() {
74          return instance;
75      }
76  
77      /**
78       * Registers the listener with the manager
79       *
80       * @param listener
81       */
82      public void addSettingsListener(SettingsListener listener) {
83          listenerList.add(SettingsListener.class, listener);
84      }
85  
86      /**
87       * Requests that the settings be loaded, all listeners will be notified of
88       * this call, and configure themselves according to the values found in the
89       * loaded settings
90       */
91      public void loadSettings() {
92          /*
93           * Ok, note we ensure we have a .chainsaw directory in the users
94           * home folder, and create a chainsaw.settings.properties file..
95           */
96          File settingsDir = getSettingsDirectory();
97  
98          if (!settingsDir.exists()) {
99              settingsDir.mkdir();
100         }
101 
102         loadGlobalSettings();
103         loadProfileableSettings();
104     }
105 
106     /**
107      *
108      */
109     private void loadProfileableSettings() {
110         EventListener[] listeners = listenerList.getListeners(SettingsListener.class);
111 
112         for (EventListener listener : listeners) {
113             SettingsListener settingsListener = (SettingsListener) listener;
114 
115             if (settingsListener instanceof Profileable) {
116                 Profileable p = (Profileable) settingsListener;
117                 loadProfileble(p);
118             }
119         }
120     }
121 
122     private void loadProfileble(Profileable p) {
123         LoadSettingsEvent event = createProfilebleEvent(p);
124         p.loadSettings(event);
125     }
126 
127     private LoadSettingsEvent createProfilebleEvent(Profileable p) {
128         Properties loadedProperties = new Properties();
129         loadedProperties.putAll(getDefaultSettings());
130         loadedProperties.putAll(loadProperties(p));
131 
132 
133         LoadSettingsEvent event = new LoadSettingsEvent(this, loadedProperties);
134 
135         return event;
136     }
137 
138     /**
139      * @param p
140      * @return
141      */
142     private Properties loadProperties(Profileable p) {
143         Properties properties = new Properties(defaultProperties);
144         InputStream is = null;
145 
146         File f = new File(getSettingsDirectory(),
147             URLEncoder.encode(p.getNamespace() + ".properties"));
148 
149         if (!f.exists()) {
150             f = new File(getSettingsDirectory(),
151                 p.getNamespace() + ".properties");
152         }
153 
154         if (f.exists()) {
155             try {
156                 is = new BufferedInputStream(new FileInputStream(f));
157 
158                 Properties toLoad = new Properties();
159                 toLoad.load(is);
160                 properties.putAll(toLoad);
161             } catch (IOException ioe) {
162                 ioe.printStackTrace();
163             } finally {
164                 if (is != null) {
165                     try {
166                         is.close();
167                     } catch (IOException e1) {
168                         e1.printStackTrace();
169                     }
170                 }
171             }
172         }
173 
174         return properties;
175     }
176 
177     private void loadGlobalSettings() {
178         EventListener[] listeners = listenerList.getListeners(SettingsListener.class);
179         LoadSettingsEvent event = null;
180 
181         for (EventListener listener : listeners) {
182             SettingsListener settingsListener = (SettingsListener) listener;
183 
184             if (event == null) {
185                 Properties loadedProperties = loadGlobalProperties();
186 
187                 //        loadedProperties.list(System.out);
188                 event = new LoadSettingsEvent(this, loadedProperties);
189             }
190 
191             settingsListener.loadSettings(event);
192         }
193     }
194 
195     /**
196      * Creates a SaveSettingsEvent and calls all the SettingsListeners
197      * to populate the properties with configuration information
198      */
199     public void saveSettings() {
200         /*
201          * Ok, note we ensure we have a .chainsaw directory in the users
202          * home folder, and create a chainsaw.settings.properties file..
203          */
204         File settingsDir = getSettingsDirectory();
205 
206         if (!settingsDir.exists()) {
207             settingsDir.mkdir();
208         }
209 
210         saveGlobalSettings(settingsDir);
211         saveProfileableSetting(settingsDir);
212     }
213 
214     /**
215      * Looks up all the Profileable's that have been registered
216      * and creates a new event for each of them, and ensures that they
217      * are saved within a separate external store
218      *
219      * @param settingsDir
220      */
221     private void saveProfileableSetting(File settingsDir) {
222         EventListener[] listeners = listenerList.getListeners(SettingsListener.class);
223         SaveSettingsEvent event;
224 
225         for (EventListener listener : listeners) {
226             SettingsListener settingsListener = (SettingsListener) listener;
227 
228             if (settingsListener instanceof Profileable) {
229                 Profileable profileable = (Profileable) settingsListener;
230                 event = new SaveSettingsEvent(this, getSettingsDirectory());
231 
232                 profileable.saveSettings(event);
233 
234                 OutputStream os = null;
235 
236                 try {
237                     os = new BufferedOutputStream(new FileOutputStream(
238                         new File(settingsDir,
239                             URLEncoder.encode(profileable.getNamespace()) + ".properties")));
240                     event.getProperties().store(os, HEADER);
241                 } catch (Exception e) {
242                     e.printStackTrace();
243                 } finally {
244                     if (os != null) {
245                         try {
246                             os.close();
247                         } catch (IOException e1) {
248                             e1.printStackTrace();
249                         }
250                     }
251                 }
252             }
253         }
254     }
255 
256     private void saveGlobalSettings(File settingsDir) {
257         EventListener[] listeners = listenerList.getListeners(SettingsListener.class);
258         SaveSettingsEvent event = null;
259 
260         for (EventListener listener : listeners) {
261             SettingsListener settingsListener = (SettingsListener) listener;
262 
263             if (!(settingsListener instanceof Profileable)) {
264                 if (event == null) {
265                     event = new SaveSettingsEvent(this, getSettingsDirectory());
266                 }
267 
268                 settingsListener.saveSettings(event);
269             }
270         }
271 
272         OutputStream os = null;
273 
274         try {
275             os = new BufferedOutputStream(new FileOutputStream(
276                 new File(settingsDir, GLOBAL_SETTINGS_FILE_NAME)));
277             event.getProperties().store(os, HEADER);
278         } catch (Exception e) {
279             e.printStackTrace();
280         } finally {
281             if (os != null) {
282                 try {
283                     os.close();
284                 } catch (IOException e1) {
285                     e1.printStackTrace();
286                 }
287             }
288         }
289     }
290 
291     public File getSettingsDirectory() {
292         return new File(System.getProperty("user.home"), ".chainsaw");
293     }
294 
295     public void configure(SettingsListener listener) {
296         if (listener instanceof Profileable) {
297             loadProfileble((Profileable) listener);
298         } else {
299             Properties loadedProperties = loadGlobalProperties();
300             LoadSettingsEvent event = new LoadSettingsEvent(this,
301                 loadedProperties);
302             listener.loadSettings(event);
303         }
304     }
305 
306     /**
307      * Returns the current Properties settings for this user
308      * by merging the default Properties with the ones we find in their directory.
309      *
310      * @return
311      */
312     private Properties loadGlobalProperties() {
313         Properties properties = new Properties(defaultProperties);
314         InputStream is = null;
315 
316         File f = new File(getSettingsDirectory(), GLOBAL_SETTINGS_FILE_NAME);
317 
318         if (f.exists()) {
319             try {
320                 is = new BufferedInputStream(new FileInputStream(f));
321 
322                 Properties toLoad = new Properties();
323                 toLoad.load(is);
324                 properties.putAll(toLoad);
325             } catch (IOException ioe) {
326                 ioe.printStackTrace();
327             } finally {
328                 if (is != null) {
329                     try {
330                         is.close();
331                     } catch (IOException e1) {
332                         e1.printStackTrace();
333                     }
334                 }
335             }
336         }
337 
338         return properties;
339     }
340 
341     /**
342      * Returns the loaded default settings, which can be used by
343      * other classes within this package.
344      *
345      * @return Properties defaults
346      */
347     public Properties getDefaultSettings() {
348         return defaultProperties;
349     }
350 }