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;
18  
19  import javax.swing.*;
20  import java.awt.*;
21  import java.beans.PropertyChangeListener;
22  import java.beans.PropertyChangeSupport;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Vector;
26  
27  /**
28   * Encapsulates the Chainsaw Application wide properties
29   *
30   * @author Paul Smith <psmith@apache.org>
31   */
32  public class ApplicationPreferenceModel {
33  
34      private boolean showNoReceiverWarning = true;
35      private boolean statusBar = true;
36      private boolean toolbar = true;
37      private boolean receivers = false; //setting this to true will cause the receivers panel to be displayed by default
38      private boolean confirmExit = true;
39      private boolean showSplash = true;
40      private String lookAndFeelClassName = "";
41      private int toolTipDisplayMillis = 4000;
42      private int cyclicBufferSize = 50000;
43      private String lastUsedVersion = "";
44      private int responsiveness = 3;
45      private Color searchBackgroundColor = ChainsawConstants.FIND_LOGGER_BACKGROUND;
46      private Color searchForegroundColor = ChainsawConstants.FIND_LOGGER_FOREGROUND;
47      private Color alternatingColorForegroundColor = ChainsawConstants.COLOR_ODD_ROW_FOREGROUND;
48      private Color alternatingColorBackgroundColor = ChainsawConstants.COLOR_ODD_ROW_BACKGROUND;
49  
50      private String identifierExpression = "PROP.hostname - PROP.application";
51  
52      private transient final PropertyChangeSupport propertySupport =
53          new PropertyChangeSupport(this);
54  
55      private int tabPlacement = 3;
56  
57      /**
58       * If not 'empty', this property will be used as the URL to load log4j configuration at startup
59       */
60      private Vector<String> configurationURLs = new Vector<>();
61  
62      private String configurationURL = "";
63  
64      /**
65       * Remember current config if provided via means other than configurationURL (command line arg, etc)
66       */
67      private transient String bypassConfigurationURL = null;
68      /**
69       * this means for Receivers that require optional jars that can't be delivered
70       * by the Web start classloader, we need to be able to remove the SecurityManager in place
71       */
72      private boolean okToRemoveSecurityManager = false;
73      private static final int CONFIGURATION_URL_ENTRY_COUNT = 10;
74      private List defaultColumnNames = new ArrayList();
75      private boolean defaultColumnsSet;
76      private boolean bypassSearchColors = false;
77  
78      /**
79       * @param listener
80       */
81      public void addPropertyChangeListener(PropertyChangeListener listener) {
82          propertySupport.addPropertyChangeListener(listener);
83      }
84  
85      /**
86       * @param propertyName
87       * @param listener
88       */
89      public void addPropertyChangeListener(String propertyName,
90                                            PropertyChangeListener listener) {
91          propertySupport.addPropertyChangeListener(propertyName, listener);
92      }
93  
94      /**
95       * @param propertyName
96       * @param oldValue
97       * @param newValue
98       */
99      private void firePropertyChange(String propertyName, boolean oldValue,
100                                     boolean newValue) {
101         propertySupport.firePropertyChange(propertyName, oldValue, newValue);
102     }
103 
104     /**
105      * @param propertyName
106      * @param oldValue
107      * @param newValue
108      */
109     private void firePropertyChange(String propertyName, int oldValue,
110                                     int newValue) {
111         propertySupport.firePropertyChange(propertyName, oldValue, newValue);
112     }
113 
114     /**
115      * @param propertyName
116      * @param oldValue
117      * @param newValue
118      */
119     private void firePropertyChange(String propertyName, Object oldValue,
120                                     Object newValue) {
121         propertySupport.firePropertyChange(propertyName, oldValue, newValue);
122     }
123 
124     /**
125      * @param propertyName
126      * @return listeners flag
127      */
128     public boolean hasListeners(String propertyName) {
129         return propertySupport.hasListeners(propertyName);
130     }
131 
132     /**
133      * @param listener
134      */
135     public void removePropertyChangeListener(PropertyChangeListener listener) {
136         propertySupport.removePropertyChangeListener(listener);
137     }
138 
139     /**
140      * @return Returns the showNoReceiverWarning.
141      */
142     public final boolean isShowNoReceiverWarning() {
143 
144         return showNoReceiverWarning;
145     }
146 
147     public final String getIdentifierExpression() {
148         return identifierExpression;
149     }
150 
151     public final void setCyclicBufferSize(int newCyclicBufferSize) {
152         int oldCyclicBufferSize = cyclicBufferSize;
153         cyclicBufferSize = newCyclicBufferSize;
154         firePropertyChange("cyclicBufferSize", oldCyclicBufferSize, newCyclicBufferSize);
155     }
156 
157     public final int getCyclicBufferSize() {
158         return cyclicBufferSize;
159     }
160 
161     public final void setToolTipDisplayMillis(int newToolTipDisplayMillis) {
162         int oldToolTipDisplayMillis = toolTipDisplayMillis;
163         toolTipDisplayMillis = newToolTipDisplayMillis;
164         firePropertyChange("toolTipDisplayMillis", oldToolTipDisplayMillis, newToolTipDisplayMillis);
165     }
166 
167     public final int getToolTipDisplayMillis() {
168         return toolTipDisplayMillis;
169     }
170 
171     public final void setIdentifierExpression(String newIdentifierExpression) {
172         String oldIdentifierExpression = identifierExpression;
173         this.identifierExpression = newIdentifierExpression;
174         firePropertyChange("identifierExpression", oldIdentifierExpression, newIdentifierExpression);
175     }
176 
177     /**
178      * @param newShowNoReceiverWarning The showNoReceiverWarning to set.
179      */
180     public final void setShowNoReceiverWarning(boolean newShowNoReceiverWarning) {
181         boolean oldShowNoReceiverWarning = showNoReceiverWarning;
182         this.showNoReceiverWarning = newShowNoReceiverWarning;
183         firePropertyChange("showNoReceiverWarning", oldShowNoReceiverWarning, newShowNoReceiverWarning);
184     }
185 
186 
187     /**
188      * Takes another model and copies all the values into this model
189      *
190      * @param model
191      */
192     public void apply(ApplicationPreferenceModel model) {
193         setIdentifierExpression(model.getIdentifierExpression());
194         setShowNoReceiverWarning(model.isShowNoReceiverWarning() || (model.getConfigurationURL() == null || model.getConfigurationURL().trim().equals("")));
195         setResponsiveness(model.getResponsiveness());
196         setTabPlacement(model.getTabPlacement());
197         setStatusBar(model.isStatusBar());
198         setToolbar(model.isToolbar());
199         setReceivers(model.isReceivers());
200         if (model.getLookAndFeelClassName() != null && !model.getLookAndFeelClassName().trim().equals("")) {
201             setLookAndFeelClassName(model.getLookAndFeelClassName());
202         } else {
203             //ensure current look and feel is selected
204             setLookAndFeelClassName(UIManager.getLookAndFeel().getClass().getName());
205         }
206         setConfirmExit(model.isConfirmExit());
207         setShowSplash(model.isShowSplash());
208         setToolTipDisplayMillis(model.getToolTipDisplayMillis());
209         setCyclicBufferSize(model.getCyclicBufferSize());
210         Vector<String> configurationURLs = model.getConfigurationURLs();
211         if (configurationURLs != null) {
212             setConfigurationURLs(configurationURLs);
213         }
214         //only set current config URL if bypass is null
215         if (model.getBypassConfigurationURL() == null) {
216             setConfigurationURL(model.getConfigurationURL());
217         }
218         setLastUsedVersion(model.getLastUsedVersion());
219         setOkToRemoveSecurityManager(model.isOkToRemoveSecurityManager());
220         Color searchForeground = model.getSearchForegroundColor();
221         Color searchBackground = model.getSearchBackgroundColor();
222         if (searchForeground != null && searchBackground != null) {
223             setSearchBackgroundColor(searchBackground);
224             setSearchForegroundColor(searchForeground);
225         }
226 
227         Color alternatingForeground = model.getAlternatingColorForegroundColor();
228         Color alternatingBackground = model.getAlternatingColorBackgroundColor();
229         if (alternatingForeground != null && alternatingBackground != null) {
230             setAlternatingBackgroundColor(alternatingBackground);
231             setAlternatingForegroundColor(alternatingForeground);
232         }
233         if (model.isDefaultColumnsSet()) {
234             setDefaultColumnNames(model.getDefaultColumnNames());
235         }
236         setBypassSearchColors(model.isBypassSearchColors());
237     }
238 
239     //use a lighter version of search color as the delta color
240     public Color getDeltaColor() {
241         float factor = 1.3F;
242         Color search = getSearchBackgroundColor();
243 
244         return new Color(boundColorValue((int) (search.getRed() * factor)),
245             boundColorValue((int) (search.getGreen() * factor)),
246             boundColorValue((int) (search.getBlue() * factor)));
247     }
248 
249     private int boundColorValue(int colorValue) {
250         return Math.min(Math.max(0, colorValue), 255);
251     }
252 
253 
254     /**
255      * @return Returns the responsiveness.
256      */
257     public final int getResponsiveness() {
258         return responsiveness;
259     }
260 
261     /**
262      * @param newValue The responsiveness to set.
263      */
264     public final void setResponsiveness(int newValue) {
265         int oldvalue = responsiveness;
266 
267         if (newValue >= 1000) {
268             responsiveness = (newValue - 750) / 1000;
269         } else {
270             responsiveness = newValue;
271         }
272         firePropertyChange("responsiveness", oldvalue, responsiveness);
273     }
274 
275     /**
276      * @param i
277      */
278     public void setTabPlacement(int i) {
279         int oldValue = this.tabPlacement;
280         this.tabPlacement = i;
281         firePropertyChange("tabPlacement", oldValue, this.tabPlacement);
282     }
283 
284     /**
285      * @return Returns the tabPlacement.
286      */
287     public final int getTabPlacement() {
288         return tabPlacement;
289     }
290 
291     /**
292      * @return Returns the statusBar.
293      */
294     public final boolean isStatusBar() {
295         return statusBar;
296     }
297 
298     public Vector<String> getConfigurationURLs() {
299         return configurationURLs;
300     }
301 
302     public void setConfigurationURLs(Vector<String> urls) {
303         if (urls != null) {
304             configurationURLs = urls;
305         }
306     }
307 
308     /**
309      * @param statusBar The statusBar to set.
310      */
311     public final void setStatusBar(boolean statusBar) {
312         boolean oldValue = this.statusBar;
313         this.statusBar = statusBar;
314         firePropertyChange("statusBar", oldValue, this.statusBar);
315     }
316 
317     public void setAlternatingForegroundColor(Color alternatingColorForegroundColor) {
318         this.alternatingColorForegroundColor = alternatingColorForegroundColor;
319         firePropertyChange("alternatingColor", true, false);
320     }
321 
322     public void setAlternatingBackgroundColor(Color alternatingColorBackgroundColor) {
323         this.alternatingColorBackgroundColor = alternatingColorBackgroundColor;
324         firePropertyChange("alternatingColor", true, false);
325     }
326 
327     public void setSearchForegroundColor(Color searchForegroundColor) {
328         this.searchForegroundColor = searchForegroundColor;
329         firePropertyChange("searchColor", true, false);
330     }
331 
332     public void setSearchBackgroundColor(Color searchBackgroundColor) {
333         this.searchBackgroundColor = searchBackgroundColor;
334         firePropertyChange("searchColor", true, false);
335     }
336 
337     public Color getAlternatingColorBackgroundColor() {
338         return alternatingColorBackgroundColor;
339     }
340 
341     public Color getAlternatingColorForegroundColor() {
342         return alternatingColorForegroundColor;
343     }
344 
345     public Color getSearchBackgroundColor() {
346         return searchBackgroundColor;
347     }
348 
349     public Color getSearchForegroundColor() {
350         return searchForegroundColor;
351     }
352 
353     /**
354      * @return Returns the receivers.
355      */
356     public final boolean isReceivers() {
357         return receivers;
358     }
359 
360     /**
361      * @param receivers The receivers to set.
362      */
363     public final void setReceivers(boolean receivers) {
364         boolean oldValue = this.receivers;
365         this.receivers = receivers;
366         firePropertyChange("receivers", oldValue, this.receivers);
367     }
368 
369     /**
370      * @return Returns the toolbar.
371      */
372     public final boolean isToolbar() {
373         return toolbar;
374     }
375 
376     /**
377      * @param toolbar The toolbar to set.
378      */
379     public final void setToolbar(boolean toolbar) {
380         boolean oldValue = this.toolbar;
381         this.toolbar = toolbar;
382         firePropertyChange("toolbar", oldValue, this.toolbar);
383     }
384 
385     /**
386      * @return Returns the lookAndFeelClassName.
387      */
388     public final String getLookAndFeelClassName() {
389         return lookAndFeelClassName;
390     }
391 
392     /**
393      * @param lookAndFeelClassName The lookAndFeelClassName to set.
394      */
395     public final void setLookAndFeelClassName(String lookAndFeelClassName) {
396         String oldValue = this.lookAndFeelClassName;
397         this.lookAndFeelClassName = lookAndFeelClassName;
398         firePropertyChange("lookAndFeelClassName", oldValue, this.lookAndFeelClassName);
399     }
400 
401     /**
402      * @return Returns the confirmExit.
403      */
404     public final boolean isConfirmExit() {
405         return confirmExit;
406     }
407 
408     /**
409      * @param confirmExit The confirmExit to set.
410      */
411     public final void setConfirmExit(boolean confirmExit) {
412         boolean oldValue = this.confirmExit;
413         this.confirmExit = confirmExit;
414         firePropertyChange("confirmExit", oldValue, this.confirmExit);
415     }
416 
417     /**
418      * @return Returns the showSplash.
419      */
420     public final boolean isShowSplash() {
421         return showSplash;
422     }
423 
424     /**
425      * @param showSplash The showSplash to set.
426      */
427     public final void setShowSplash(boolean showSplash) {
428         boolean oldValue = this.showSplash;
429         this.showSplash = showSplash;
430         firePropertyChange("showSplash", oldValue, this.showSplash);
431     }
432 
433     /**
434      * @return Returns the configurationURL.
435      */
436     public final String getConfigurationURL() {
437         return this.configurationURL;
438     }
439 
440     public final String getBypassConfigurationURL() {
441         return bypassConfigurationURL;
442     }
443 
444     /*
445       Set to null to un-bypass
446      */
447     public void setBypassConfigurationURL(String bypassConfigurationURL) {
448         //don't change configuration URL..configurationURL is persisted on app exit
449         if (bypassConfigurationURL != null && bypassConfigurationURL.trim().equals("")) {
450             this.bypassConfigurationURL = null;
451         }
452         this.bypassConfigurationURL = bypassConfigurationURL;
453     }
454 
455     /**
456      * @param configurationURL The configurationURL to set.
457      */
458     public final void setConfigurationURL(String configurationURL) {
459         //don't add empty entries, but allow the current configuration URL to be set to an empty string
460         Object oldValue = this.bypassConfigurationURL != null ? this.bypassConfigurationURL : this.configurationURL;
461         bypassConfigurationURL = null;
462         if (configurationURL == null || configurationURL.trim().equals("")) {
463             this.configurationURL = "";
464             firePropertyChange("configurationURL", oldValue, this.configurationURL);
465             return;
466         }
467         //add entry to MRU list
468         if (!configurationURLs.contains(configurationURL)) {
469             if (configurationURLs.size() == CONFIGURATION_URL_ENTRY_COUNT) {
470                 configurationURLs.remove(CONFIGURATION_URL_ENTRY_COUNT - 1);
471             }
472             configurationURLs.add(0, configurationURL);
473         }
474         this.configurationURL = configurationURL;
475         firePropertyChange("configurationURL", oldValue, this.configurationURL);
476     }
477 
478     /**
479      * @return Returns the lastUsedVersion.
480      */
481     public final String getLastUsedVersion() {
482         return this.lastUsedVersion;
483     }
484 
485     /**
486      * @param lastUsedVersion The lastUsedVersion to set.
487      */
488     public final void setLastUsedVersion(String lastUsedVersion) {
489         String oldValue = this.lastUsedVersion;
490         this.lastUsedVersion = lastUsedVersion;
491         firePropertyChange("lastUsedVersion", oldValue, this.lastUsedVersion);
492     }
493 
494     /**
495      * @return ok to remove security manager flag
496      */
497     public final boolean isOkToRemoveSecurityManager() {
498         return this.okToRemoveSecurityManager;
499     }
500 
501     /**
502      * @param okToRemoveSecurityManager The okToRemoveSecurityManager to set.
503      */
504     public final void setOkToRemoveSecurityManager(boolean okToRemoveSecurityManager) {
505         boolean oldValue = this.okToRemoveSecurityManager;
506         this.okToRemoveSecurityManager = okToRemoveSecurityManager;
507         firePropertyChange("okToRemoveSecurityManager", oldValue, this.okToRemoveSecurityManager);
508     }
509 
510     public void setDefaultColumnNames(List defaultColumnNames) {
511         defaultColumnsSet = true;
512         this.defaultColumnNames.clear();
513         this.defaultColumnNames.addAll(defaultColumnNames);
514     }
515 
516     public boolean isDefaultColumnsSet() {
517         return defaultColumnsSet;
518     }
519 
520     public List getDefaultColumnNames() {
521         return defaultColumnNames;
522     }
523 
524     public void setBypassSearchColors(boolean bypassSearchColors) {
525         this.bypassSearchColors = bypassSearchColors;
526     }
527 
528     public boolean isBypassSearchColors() {
529         return bypassSearchColors;
530     }
531 }