/* * Copyright (c) 2007, 2013, 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.profiler; import com.sun.tools.visualvm.profiling.presets.ProfilingOptionsSectionProvider; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.awt.Mnemonics; import org.openide.util.NbBundle; import org.openide.util.RequestProcessor; import org.openide.util.lookup.ServiceProvider; /** * * @author Jiri Sedlacek */ @ServiceProvider(service = ProfilingOptionsSectionProvider.class) @NbBundle.Messages({ "CAP_SectionName=Profiler Calibration", "HINT_RunCalibrationAction=Manage Calibration Data", "LBL_ManageCalibration=Manage calibration data:", "BTN_ManageCalibration=&Manage", "LBL_JavaPlatform=Java Platform", "LBL_LastCalibrated=Last Calibrated", "LBL_NotCalibrated=Not calibrated", "LBL_JavaPlatformsForProfiling=&Java platforms supported for profiling:", "LBL_Calibrate=&Calibrate", "LBL_JavaPlatforms=Java &Platforms...", "MSG_CalibrationOnProfile=Profiling session is currently in progress.\nDo you want to stop the current session and perform the calibration?", "MSG_CalibrationOnAttach=Profiling session is currently in progress\nDo you want to detach from the target application and perform the calibration?", "MSG_CalibrationFailed=Calibration failed.\nPlease check your setup and run the calibration again." }) public final class ManageCalibration extends ProfilingOptionsSectionProvider { public String getSectionName() { return Bundle.CAP_SectionName(); } public Component getSection() { JPanel container = new JPanel(new BorderLayout()); JLabel label = new JLabel(); Mnemonics.setLocalizedText(label, Bundle.LBL_ManageCalibration()); // NOI18N container.add(label, BorderLayout.CENTER); JButton button = new JButton() { protected void fireActionPerformed(ActionEvent e) { manageCalibration(); } }; Mnemonics.setLocalizedText(button, Bundle.BTN_ManageCalibration()); // NOI18N container.add(button, BorderLayout.EAST); return container; } private void manageCalibration() { String[] columnNames = new String[] { Bundle.LBL_JavaPlatform(), Bundle.LBL_LastCalibrated() }; final TableModel model = new DefaultTableModel(createData(), columnNames) { public boolean isCellEditable(int row, int column) { return false; } }; SwingUtilities.invokeLater(new Runnable() { public void run() { displayUI(model); } }); } private void displayUI(final TableModel model) { final JTable table = new JTable(model); table.setShowHorizontalLines(false); table.setShowVerticalLines(true); table.setGridColor(Color.LIGHT_GRAY); table.setFillsViewportHeight(true); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); TableColumnModel columns = table.getColumnModel(); final TableColumn status = columns.getColumn(1); status.setCellRenderer(new CalibrationDateCellRenderer()); table.setPreferredScrollableViewportSize(new Dimension(350, table.getRowHeight() * 4)); JPanel container = new JPanel(new BorderLayout()); container.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); container.add(new JScrollPane(table)); JLabel label = new JLabel(); Mnemonics.setLocalizedText(label, Bundle.LBL_JavaPlatformsForProfiling()); label.setLabelFor(table); label.setBorder(BorderFactory.createEmptyBorder(15, 10, 5, 10)); final JButton calibrate = new JButton() { protected void fireActionPerformed(ActionEvent e) { calibrate(table); } }; Mnemonics.setLocalizedText(calibrate, Bundle.LBL_Calibrate()); table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "DEFAULT_ACTION"); // NOI18N table.getActionMap().put("DEFAULT_ACTION", new AbstractAction() { // NOI18N public void actionPerformed(ActionEvent e) { calibrate(table); } }); table.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) calibrate(table); } }); table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { calibrate.setEnabled(table.getSelectedRow() != -1); } }); calibrate.setEnabled(false); table.clearSelection(); JPanel panel = new JPanel(new BorderLayout()); panel.add(label, BorderLayout.NORTH); panel.add(container, BorderLayout.CENTER); RequestProcessor.getDefault().post(new Runnable() { public void run() { refreshTimes(table); } }); DialogDescriptor dd = new DialogDescriptor(panel, Bundle.HINT_RunCalibrationAction(), true, new Object[] { DialogDescriptor.CLOSED_OPTION }, DialogDescriptor.CLOSED_OPTION, 0, null, null); dd.setAdditionalOptions(new Object[] { calibrate }); DialogDisplayer.getDefault().createDialog(dd).setVisible(true); } private void calibrate(final JTable table) { final int row = table.getSelectedRow(); if (row == -1) return; RequestProcessor.getDefault().post(new Runnable() { public void run() { Runnable refresher = new Runnable() { public void run() { refreshTimes(table); } }; CalibrationSupport.calibrate(javaPlatforms[row], -1, null, refresher); } }); } private void refreshTimes(JTable table) { final TableModel model = table.getModel(); for (int row = 0; row < model.getRowCount(); row++) { String javaPlatform = javaPlatforms[row]; Long modified = null; String s = CalibrationSupport.getCalibrationDataFileName(javaPlatform); if (s != null) { File f = new File(s); if (f.isFile()) modified = Long.valueOf(f.lastModified()); } final int index = row; final Long _modified = modified; SwingUtilities.invokeLater(new Runnable() { public void run() { model.setValueAt(_modified, index, 1); } }); } } private Object[][] createData() { String[][] platforms = ProfilerSupport.getInstance().getSupportedJavaPlatforms(); javaPlatforms = platforms[1]; String[] names = platforms[0]; Object[][] data = new String[names.length][2]; for (int i = 0; i < names.length; i++) data[i] = new String[] { names[i], null }; return data; } private String[] javaPlatforms; private static class CalibrationDateCellRenderer extends DefaultTableCellRenderer { private static Calendar CALENDAR; private static int REF_DAY_OF_YEAR = -1; private static int DAY_OF_YEAR = -1; private static int YEAR = -1; private static int ERA = -1; private static Date DATE; private static DateFormat FORMAT_TIME; private static DateFormat FORMAT_DATE; CalibrationDateCellRenderer() { setHorizontalAlignment(TRAILING); } protected void setValue(Object value) { if (value == null) { setText(Bundle.LBL_NotCalibrated()); } else { long time = ((Long)value).longValue(); setValue(time, isToday(time)); } } private void setValue(long time, boolean today) { DateFormat format; if (today) { if (FORMAT_TIME == null) FORMAT_TIME = DateFormat.getTimeInstance(); format = FORMAT_TIME; } else { if (FORMAT_DATE == null) FORMAT_DATE = DateFormat.getDateInstance(); format = FORMAT_DATE; } if (DATE == null) DATE = new Date(); DATE.setTime(time); setText(format.format(DATE)); } private static boolean isToday(long time) { if (REF_DAY_OF_YEAR != -1 && CALENDAR.get(Calendar.DAY_OF_YEAR) != REF_DAY_OF_YEAR) CALENDAR = null; if (CALENDAR == null) initializeCalendar(); CALENDAR.setTimeInMillis(time); return DAY_OF_YEAR == CALENDAR.get(Calendar.DAY_OF_YEAR) && YEAR == CALENDAR.get(Calendar.YEAR) && ERA == CALENDAR.get(Calendar.ERA); } private static void initializeCalendar() { CALENDAR = Calendar.getInstance(); DAY_OF_YEAR = CALENDAR.get(Calendar.DAY_OF_YEAR); YEAR = CALENDAR.get(Calendar.YEAR); ERA = CALENDAR.get(Calendar.ERA); if (REF_DAY_OF_YEAR == -1) REF_DAY_OF_YEAR = DAY_OF_YEAR; } } }