/* * 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.profiling.presets; import com.sun.tools.visualvm.application.Application; import com.sun.tools.visualvm.application.jvm.Jvm; import com.sun.tools.visualvm.application.jvm.JvmFactory; import com.sun.tools.visualvm.application.type.ApplicationTypeFactory; import com.sun.tools.visualvm.core.datasource.descriptor.DataSourceDescriptorFactory; import java.io.File; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.prefs.Preferences; import javax.swing.DefaultListModel; import javax.swing.SwingUtilities; import org.netbeans.api.options.OptionsDisplayer; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; import org.openide.util.RequestProcessor; import org.openide.util.Utilities; /** * * @author Jiri Sedlacek */ public final class ProfilerPresets { private static final String JAR_SUFFIX = ".jar"; // NOI18N private static final String OPTIONS_HANDLE = "ProfilerOptions"; // NOI18N private static final String PROP_PRESET_HEADER = "prof_preset_header"; // NOI18N private static ProfilerPresets INSTANCE; private Preferences prefs; private List<ProfilerPreset> presets; private ProfilerPreset presetToSelect; private ProfilerPreset presetToCreate; private final Set<WeakReference<PresetSelector>> selectors; public static synchronized ProfilerPresets getInstance() { if (INSTANCE == null) INSTANCE = new ProfilerPresets(); return INSTANCE; } public void editPresets(ProfilerPreset preset) { presetToSelect = preset; OptionsDisplayer.getDefault().open(OPTIONS_HANDLE); } ProfilerPreset presetToSelect() { ProfilerPreset toSelect = presetToSelect; presetToSelect = null; return toSelect; } public void savePreset(ProfilerPreset preset) { presetToCreate = preset; OptionsDisplayer.getDefault().open(OPTIONS_HANDLE); } ProfilerPreset presetToCreate() { ProfilerPreset toCreate = presetToCreate; presetToCreate = null; return toCreate; } void optionsSubmitted(final ProfilerPreset selected) { SwingUtilities.invokeLater(new Runnable() { public void run() { Iterator<WeakReference<PresetSelector>> selectorsI = selectors.iterator(); while (selectorsI.hasNext()) { WeakReference<PresetSelector> selectorR = selectorsI.next(); PresetSelector selector = selectorR.get(); if (selector == null) selectorsI.remove(); else if (SwingUtilities.getRoot(selector) == null) selectorsI.remove(); else selector.presetsChanged(selected); } } }); } public PresetSelector createSelector(PresetSelector refSelector, Runnable presetSync) { return createSelector(null, refSelector, presetSync); } public PresetSelector createSelector(Application application, PresetSelector refSelector, Runnable presetSync) { String mainClass = null; if (application != null) { mainClass = getMainClass(application); if (mainClass == null || mainClass.isEmpty()) mainClass = ApplicationTypeFactory.getApplicationTypeFor(application).getName(); if (mainClass == null || mainClass.isEmpty()) mainClass = DataSourceDescriptorFactory.getDescriptor(application).getName(); } ProfilerPreset toSelect = null; if (mainClass != null && !mainClass.isEmpty()) { String mainClassL = mainClass.toLowerCase(); for (int i = 0; i < presets.size(); i++) { ProfilerPreset preset = presets.get(i); String selector = preset.getSelector(); if (selector != null && !selector.isEmpty()) { if (mainClass.equals(selector) || mainClassL.contains(selector.toLowerCase())) { toSelect = preset; break; } } } } ProfilerPreset defPreset = createDefaultPreset(application); ProfilerPreset custPreset = null; PresetSelector selector = new PresetSelector(refSelector, defPreset, custPreset, toSelect, presetSync, mainClass); selectors.add(new WeakReference(selector)); return selector; } public ProfilerPreset[] getPresets(Application application) { ProfilerPreset[] presetsArr = new ProfilerPreset[presets.size() + 1]; int index = 0; presetsArr[index++] = createDefaultPreset(application); for (ProfilerPreset preset : presets) presetsArr[index++] = preset; return presetsArr; } private void loadPresets() { RequestProcessor.getDefault().post(new Runnable() { public void run() { final List<ProfilerPreset> loadedPresets = doLoadPresets(); SwingUtilities.invokeLater(new Runnable() { public void run() { presets.clear(); presets.addAll(loadedPresets); } }); } }); } void savePresets(final PresetsModel toSave) { SwingUtilities.invokeLater(new Runnable() { public void run() { presets.clear(); Enumeration en = toSave.elements(); while (en.hasMoreElements()) presets.add((ProfilerPreset)en.nextElement()); RequestProcessor.getDefault().post(new Runnable() { public void run() { doSavePresets(toSave); } }); } }); } PresetsModel getPresets() { PresetsModel model = new PresetsModel(); for (ProfilerPreset preset : presets) model.addElement(preset); return model; } private static ProfilerPreset createDefaultPreset(Application application) { ProfilerPreset defaultPreset = new ProfilerPreset(NbBundle.getMessage( ProfilerPresets.class, "MSG_Default"), ""); // NOI18N defaultPreset.setFilterS(getDefaultFiltersS()); defaultPreset.setRootsP(getDefaultRootsP(application)); defaultPreset.setFilterP(getDefaultFiltersP(defaultPreset.getRootsP())); return defaultPreset; } private static String getMainClass(Application application) { Jvm jvm = JvmFactory.getJVMFor(application); String mainClass = jvm.getMainClass(); if (mainClass == null || mainClass.trim().length() == 0) { mainClass = ""; // NOI18N } else if (mainClass.endsWith(JAR_SUFFIX)) { // application is launched with -jar and uses relative path, try to find jar mainClass = ""; // NOI18N if (jvm.isGetSystemPropertiesSupported()) { Properties sysProp = jvm.getSystemProperties(); if (sysProp != null) { String userdir = sysProp.getProperty("user.dir"); // NOI18N if (userdir != null) { String args = jvm.getCommandLine(); int index = args.indexOf(JAR_SUFFIX); if (index != -1) { File jarFile = new File(userdir,args.substring(0,index+JAR_SUFFIX.length())); if (jarFile.exists()) { try { JarFile jf = new JarFile(jarFile); String mainClassName = jf.getManifest().getMainAttributes().getValue(Attributes.Name.MAIN_CLASS); assert mainClassName!=null; mainClass = mainClassName.replace('\\', '/').replace('/', '.'); // NOI18N } catch (IOException ex) { // LOGGER.log(Level.INFO, "getMainClass", ex); // NOI18N } } } } } } } return mainClass; } private static String getDefaultFiltersS() { return Utilities.isMac() ? "java.*, javax.*,\nsun.*, sunw.*, com.sun.*,\ncom.apple.*, apple.awt.*, apple.laf.*" : // NOI18N "java.*, javax.*,\nsun.*, sunw.*, com.sun.*"; // NOI18N } private static String getDefaultRootsP(Application application) { if (application == null) return NbBundle.getMessage( ProfilerPresets.class, "HINT_Define_roots"); // NOI18N String mainClass = getMainClass(application); if ("".equals(mainClass)) { // unknown main class return NbBundle.getMessage(ProfilerPresets.class, "HINT_Define_roots"); // NOI18N } int dotIndex = mainClass.lastIndexOf("."); // NOI18N if (dotIndex == -1) return mainClass; // default package else return mainClass.substring(0, dotIndex + 1) + "**"; // NOI18N } private static String getDefaultFiltersP(String defaultRoots) { if (defaultRoots.isEmpty()) return !Utilities.isMac() ? "sun.*, sunw.*, com.sun.*" : // NOI18N "sun.*, sunw.*, com.sun.*,\ncom.apple.*, apple.awt.*, apple.laf.*"; // NOI18N else return !Utilities.isMac() ? "java.*, javax.*,\nsun.*, sunw.*, com.sun.*" : // NOI18N "java.*, javax.*,\nsun.*, sunw.*, com.sun.*,\ncom.apple.*, apple.awt.*, apple.laf.*"; // NOI18N } private List<ProfilerPreset> doLoadPresets() { Preferences p = prefs(); List<ProfilerPreset> loadedPresets = new ArrayList(); int i = 0; String prefix = i + "_"; // NOI18N while (p.get(prefix + PROP_PRESET_HEADER, null) != null) { loadedPresets.add(new ProfilerPreset(p, prefix)); prefix = ++i + "_"; // NOI18N } return loadedPresets; } private void doSavePresets(PresetsModel toSave) { Preferences p = prefs(); try { p.clear(); } catch (Exception e) {} int count = toSave.size(); for (int i = 0; i < count; i++) { String prefix = i + "_"; // NOI18N p.put(prefix + PROP_PRESET_HEADER, ""); // NOI18N ProfilerPreset preset = (ProfilerPreset)toSave.get(i); preset.toPreferences(p, prefix); // NOI18N } } private synchronized Preferences prefs() { if (prefs == null) prefs = NbPreferences.forModule(ProfilerPresets.class); return prefs; } private ProfilerPresets() { presets = new ArrayList(); selectors = new HashSet(); loadPresets(); } static class PresetsModel extends DefaultListModel { void addPreset(ProfilerPreset preset) { addElement(preset); } void removePreset(int preset) { removeElementAt(preset); } void movePresetUp(int preset) { Object o = elementAt(preset); remove(preset); add(preset - 1, o); } void movePresetDown(int preset) { Object o = elementAt(preset); remove(preset); add(preset + 1, o); } public void fireItemChanged(int itemIndex) { fireContentsChanged(this, itemIndex, itemIndex); } } }