/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.visualvm.core.options; import com.sun.tools.visualvm.core.datasupport.ComparableWeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.BackingStoreException; import java.util.prefs.PreferenceChangeEvent; import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; import org.netbeans.modules.profiler.api.ProfilerIDESettings; import org.openide.util.NbPreferences; /** * General VisualVM settings defined in Options. * * @author Jaroslav Bachorik */ public final class GlobalPreferences implements PreferenceChangeListener { private final static Logger LOGGER = Logger.getLogger("com.sun.tools.visualvm.core.options"); // NOI18N private static final String INT_KEY_MONHOST_POLL = "MonitoredHostPoll"; // NOI18N private static final String INT_KEY_THREADS_POLL = "ThreadsPoll"; // NOI18N private static final String INT_KEY_MONDATA_POLL = "MonitoredDataPoll"; // NOI18N private static final String INT_KEY_MONHOST_CACHE = "MonitoredHostCache"; // NOI18N private static final String INT_KEY_MONDATA_CACHE = "MonitoredDataCache"; // NOI18N private final static int MONHOST_POLL_DEFAULT = 3; private final static int THREADS_POLL_DEFAULT = 1; private final static int MONDATA_POLL_DEFAULT = 1; private final static int MONHOST_CACHE_DEFAULT = 60; private final static int MONDATA_CACHE_DEFAULT = 60; private final static GlobalPreferences INSTANCE = new GlobalPreferences(); private final Preferences prefs; private final Map<String, Set<ComparableWeakReference<PreferenceChangeListener>>> listenerMap = new HashMap<String, Set<ComparableWeakReference<PreferenceChangeListener>>>(); private final ExecutorService dispatcher = Executors.newCachedThreadPool(); private GlobalPreferences() { prefs = NbPreferences.forModule(GlobalPreferences.class); prefs.addPreferenceChangeListener(this); } /** * Returns singleton instance of GlobalPreferences. * * @return singleton instance of GlobalPreferences. */ public static GlobalPreferences sharedInstance() { return INSTANCE; } public void preferenceChange(final PreferenceChangeEvent evt) { synchronized(listenerMap) { Set<ComparableWeakReference<PreferenceChangeListener>> set = listenerMap.get(evt.getKey()); if (set != null) { final Set<PreferenceChangeListener> tmpListeners = new HashSet<PreferenceChangeListener>(); Collection<ComparableWeakReference<PreferenceChangeListener>> deadRefs = new ArrayList<ComparableWeakReference<PreferenceChangeListener>>(); for(ComparableWeakReference<PreferenceChangeListener> pclRef : set) { if (pclRef.get() != null) { tmpListeners.add(pclRef.get()); } else { deadRefs.add(pclRef); } } set.removeAll(deadRefs); dispatcher.submit(new Runnable() { public void run() { for(PreferenceChangeListener pcl : tmpListeners) { pcl.preferenceChange(evt); } } }); } } } /** * Returns polling interval for monitored host. * * @return polling interval for monitored host. */ public int getMonitoredHostPoll() { return getPollingInterval(INT_KEY_MONHOST_POLL, MONHOST_POLL_DEFAULT); } /** * Sets polling interval for monitored host. * * @param value polling interval for monitored host. */ public void setMonitoredHostPoll(int value) { setPollingInterval(INT_KEY_MONHOST_POLL, value); } /** * Registers a listener for changes of polling interval for monitored host. * * @param pcl listener for changes of polling interval for monitored host. */ public void watchMonitoredHostPoll(PreferenceChangeListener pcl) { addListener(INT_KEY_MONHOST_POLL, pcl); } /** * Returns polling interval for threads. * * @return polling interval for threads. */ public int getThreadsPoll() { return getPollingInterval(INT_KEY_THREADS_POLL, THREADS_POLL_DEFAULT); } /** * Sets polling interval for threads. * * @param value polling interval for threads. */ public void setThreadsPoll(int value) { setPollingInterval(INT_KEY_THREADS_POLL, value); } /** * Registers a listener for changes of polling interval for threads. * * @param pcl listener for changes of polling interval for threads. */ public void watchThreadsPoll(PreferenceChangeListener pcl) { addListener(INT_KEY_THREADS_POLL, pcl); } /** * Returns polling interval for monitored data. * * @return polling interval for monitored data. */ public int getMonitoredDataPoll() { return getPollingInterval(INT_KEY_MONDATA_POLL, MONDATA_POLL_DEFAULT); } /** * Sets polling interval for monitored data. * * @param value polling interval for monitored data. */ public void setMonitoredDataPoll(int value) { setPollingInterval(INT_KEY_MONDATA_POLL, value); } /** * Registerz a listener for changes of polling interval for monitored data. * * @param pcl listener for changes of polling interval for monitored data. */ public void watchMonitoredDataPoll(PreferenceChangeListener pcl) { addListener(INT_KEY_MONDATA_POLL, pcl); } /** * Returns size of cache for monitored host data. * * @return size of cache for monitored host data. */ public int getMonitoredHostCache() { return getPollingInterval(INT_KEY_MONHOST_CACHE, MONHOST_CACHE_DEFAULT); } /** * Sets size of cache for monitored host data. * * @param value size of cache for monitored host data. */ public void setMonitoredHostCache(int value) { setPollingInterval(INT_KEY_MONHOST_CACHE, value); } /** * Registers a listener for changes of size of cache for monitored host data. * * @param pcl listener for changes of size of cache for monitored host data. */ public void watchMonitoredHostCache(PreferenceChangeListener pcl) { addListener(INT_KEY_MONHOST_CACHE, pcl); } /** * Returns size of cache for monitored data. * * @return size of cache for monitored data. */ public int getMonitoredDataCache() { return getPollingInterval(INT_KEY_MONDATA_CACHE, MONDATA_CACHE_DEFAULT); } /** * Sets size of cache for monitored data. * * @param value size of cache for monitored data. */ public void setMonitoredDataCache(int value) { setPollingInterval(INT_KEY_MONDATA_CACHE, value); } /** * Registers a listener for changes of size of cache for monitored data. * * @param pcl listener for changes of size of cache for monitored data. */ public void watchMonitoredDataCache(PreferenceChangeListener pcl) { addListener(INT_KEY_MONDATA_CACHE, pcl); } /** * Persistently stores preferences values. This method is called automatically, * typically you don't need to call it explicitely. * * @return true if the preferences have been stored successfuly, false otherwise. */ public boolean store() { try { prefs.sync(); return true; } catch (BackingStoreException ex) { LOGGER.log(Level.SEVERE, "Error saving preferences", ex); // NOI18N } return false; } private void addListener(String property, PreferenceChangeListener pcl) { synchronized(listenerMap) { if (listenerMap.containsKey(property)) { Set<ComparableWeakReference<PreferenceChangeListener>> set = listenerMap.get(property); set.add(new ComparableWeakReference<PreferenceChangeListener>(pcl)); } else { Set<ComparableWeakReference<PreferenceChangeListener>> set = new HashSet<ComparableWeakReference<PreferenceChangeListener>>(); set.add(new ComparableWeakReference<PreferenceChangeListener>(pcl)); listenerMap.put(property, set); } } } private int getPollingInterval(String property, int deflt) { int value = -1; synchronized (prefs) { value = prefs.getInt(property, -1); if (value == -1) { value = deflt; prefs.putInt(property, value); } } return value; } private void setPollingInterval(String property, int value) { synchronized(prefs) { prefs.putInt(property, value); } } /** * Allows to set or clear persistent do not show again value associated with given notification identified by the * provided key. * * @param key A key that uniquely identifies the notification * @param value The value that should be used without displaying the notification or null to clear the Do not show * again (i.e. start displaying the notifications again. * * @since VisualVM 1.3.9 */ public void setDoNotShowAgain(String key, String value) { ProfilerIDESettings.getInstance().setDoNotShowAgain(key, value); } /** * Allows to get persistent do not show again value associated with given notification identified by the provided key. * * @param key A key that uniquely identifies the notification * @return The value that should be used without displaying the notification or null if the notification should * be displayed * * @since VisualVM 1.3.9 */ public String getDoNotShowAgain(String key) { return ProfilerIDESettings.getInstance().getDoNotShowAgain(key); } }