1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * The contents of this file are subject to the terms of either the Universal Permissive License 7 * v 1.0 as shown at http://oss.oracle.com/licenses/upl 8 * 9 * or the following license: 10 * 11 * Redistribution and use in source and binary forms, with or without modification, are permitted 12 * provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 15 * and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 18 * conditions and the following disclaimer in the documentation and/or other materials provided with 19 * the distribution. 20 * 21 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to 22 * endorse or promote products derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 26 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 31 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 package org.openjdk.jmc.flightrecorder.ui.pages; 34 35 import java.util.Collections; 36 import java.util.HashSet; 37 import java.util.Set; 38 39 import org.eclipse.jface.resource.ImageDescriptor; 40 import org.eclipse.jface.viewers.ColumnViewer; 41 import org.eclipse.swt.SWT; 42 import org.eclipse.swt.custom.SashForm; 43 import org.eclipse.swt.layout.GridData; 44 import org.eclipse.swt.widgets.Composite; 45 import org.eclipse.ui.forms.widgets.Form; 46 import org.eclipse.ui.forms.widgets.FormToolkit; 47 import org.eclipse.ui.forms.widgets.Section; 48 49 import org.openjdk.jmc.common.IState; 50 import org.openjdk.jmc.common.IWritableState; 51 import org.openjdk.jmc.common.item.IAccessorFactory; 52 import org.openjdk.jmc.common.item.IItemFilter; 53 import org.openjdk.jmc.common.item.IMemberAccessor; 54 import org.openjdk.jmc.common.item.IType; 55 import org.openjdk.jmc.common.item.ItemFilters; 56 import org.openjdk.jmc.flightrecorder.jdk.JdkAggregators; 57 import org.openjdk.jmc.flightrecorder.jdk.JdkAttributes; 58 import org.openjdk.jmc.flightrecorder.jdk.JdkFilters; 59 import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs; 60 import org.openjdk.jmc.flightrecorder.rules.util.JfrRuleTopics; 61 import org.openjdk.jmc.flightrecorder.ui.FlightRecorderUI; 62 import org.openjdk.jmc.flightrecorder.ui.IDataPageFactory; 63 import org.openjdk.jmc.flightrecorder.ui.IDisplayablePage; 64 import org.openjdk.jmc.flightrecorder.ui.IPageContainer; 65 import org.openjdk.jmc.flightrecorder.ui.IPageDefinition; 66 import org.openjdk.jmc.flightrecorder.ui.IPageUI; 67 import org.openjdk.jmc.flightrecorder.ui.StreamModel; 68 import org.openjdk.jmc.flightrecorder.ui.common.AbstractDataPage; 69 import org.openjdk.jmc.flightrecorder.ui.common.DataPageToolkit; 70 import org.openjdk.jmc.flightrecorder.ui.common.FilterComponent; 71 import org.openjdk.jmc.flightrecorder.ui.common.ImageConstants; 72 import org.openjdk.jmc.flightrecorder.ui.common.ItemAggregateViewer; 73 import org.openjdk.jmc.flightrecorder.ui.common.ItemHistogram; 74 import org.openjdk.jmc.flightrecorder.ui.common.ItemHistogram.CompositeKeyHistogramBuilder; 75 import org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages; 76 import org.openjdk.jmc.ui.column.ColumnManager.SelectionState; 77 import org.openjdk.jmc.ui.column.ColumnMenusFactory; 78 import org.openjdk.jmc.ui.column.TableSettings; 79 import org.openjdk.jmc.ui.handlers.MCContextMenuManager; 80 import org.openjdk.jmc.ui.misc.CompositeToolkit; 81 import org.openjdk.jmc.ui.misc.PersistableSashForm; 82 83 public class JVMInformationPage extends AbstractDataPage { 84 public static class JVMInformationPageFactory implements IDataPageFactory { 85 86 @Override 87 public String getName(IState state) { 88 return Messages.JVMInformationPage_PAGE_NAME; 89 } 90 91 @Override 92 public ImageDescriptor getImageDescriptor(IState state) { 93 return FlightRecorderUI.getDefault().getMCImageDescriptor(ImageConstants.PAGE_JVM_INTERNALS); 94 } 95 96 @Override 97 public String[] getTopics(IState state) { 98 return new String[] {JfrRuleTopics.JVM_INFORMATION_TOPIC}; 99 } 100 101 @Override 102 public IDisplayablePage createPage(IPageDefinition dpd, StreamModel items, IPageContainer editor) { 103 return new JVMInformationPage(dpd, items, editor); 104 } 105 106 } 107 108 private static final Set<String> FLAGS; 109 110 static { 111 Set<String> types = new HashSet<>(); 112 types.add(JdkTypeIDs.LONG_FLAG); 113 types.add(JdkTypeIDs.ULONG_FLAG); 114 types.add(JdkTypeIDs.DOUBLE_FLAG); 115 types.add(JdkTypeIDs.BOOLEAN_FLAG); 116 types.add(JdkTypeIDs.STRING_FLAG); 117 types.add(JdkTypeIDs.INT_FLAG); 118 types.add(JdkTypeIDs.UINT_FLAG); 119 FLAGS = Collections.unmodifiableSet(types); 120 } 121 122 private static final IItemFilter FLAGS_FILTER = ItemFilters.type(FLAGS); 123 124 private static final IAccessorFactory<?> FLAG_VALUE_FIELD = new IAccessorFactory<Object>() { 125 126 @Override 127 public <T> IMemberAccessor<?, T> getAccessor(IType<T> type) { 128 switch (type.getIdentifier()) { 129 case JdkTypeIDs.LONG_FLAG: 130 case JdkTypeIDs.ULONG_FLAG: 131 case JdkTypeIDs.DOUBLE_FLAG: 132 case JdkTypeIDs.INT_FLAG: 133 case JdkTypeIDs.UINT_FLAG: 134 return JdkAttributes.FLAG_VALUE_NUMBER.getAccessor(type); 135 case JdkTypeIDs.BOOLEAN_FLAG: 136 return JdkAttributes.FLAG_VALUE_BOOLEAN.getAccessor(type); 137 case JdkTypeIDs.STRING_FLAG: 138 return JdkAttributes.FLAG_VALUE_TEXT.getAccessor(type); 139 default: 140 // FIXME: Return fallback function instead? 141 return null; 142 } 143 } 144 145 }; 146 147 private class JVMInformationUi implements IPageUI { 148 149 private final ItemAggregateViewer infoViewer; 150 private final ItemHistogram allFlagsTable; 151 private FilterComponent allFlagsFilter; 152 private final SashForm sash; 153 154 JVMInformationUi(Composite parent, FormToolkit toolkit, IPageContainer pageContainer, IState state) { 155 Form form = DataPageToolkit.createForm(parent, toolkit, getName(), getIcon()); 156 157 sash = new SashForm(form.getBody(), SWT.HORIZONTAL); 158 sash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 159 160 Section jvmInfSection = CompositeToolkit.createSection(sash, toolkit, 161 Messages.JVMInformationPage_SECTION_JVM_INFO); 162 infoViewer = new ItemAggregateViewer(jvmInfSection, toolkit); 163 infoViewer.addAggregate(JdkAggregators.JVM_START_TIME); 164 infoViewer.addAggregate(JdkAggregators.JVM_NAME); 165 infoViewer.addAggregate(JdkAggregators.JVM_VERSION); 166 infoViewer.addAggregate(JdkAggregators.JVM_ARGUMENTS); 167 infoViewer.addAggregate(JdkAggregators.JAVA_ARGUMENTS); 168 jvmInfSection.setClient(infoViewer.getControl()); 169 170 Section allFlagsSection = CompositeToolkit.createSection(sash, toolkit, 171 Messages.JVMInformationPage_SECTION_JVM_FLAGS); 172 allFlagsTable = FLAG_HISTOGRAM.buildWithoutBorder(allFlagsSection, 173 new TableSettings(state.getChild(JVM_FLAGS))); 174 allFlagsFilter = FilterComponent.createFilterComponent(allFlagsTable, flagsFilter, 175 getDataSource().getItems().apply(FLAGS_FILTER), pageContainer.getSelectionStore()::getSelections, 176 this::onFilterChange); 177 MCContextMenuManager mm = MCContextMenuManager.create(allFlagsTable.getManager().getViewer().getControl()); 178 ColumnMenusFactory.addDefaultMenus(allFlagsTable.getManager(), mm); 179 mm.add(allFlagsFilter.getShowFilterAction()); 180 mm.add(allFlagsFilter.getShowSearchAction()); 181 allFlagsSection.setClient(allFlagsFilter.getComponent()); 182 183 ColumnViewer viewer = allFlagsTable.getManager().getViewer(); 184 viewer.addSelectionChangedListener( 185 e -> pageContainer.showSelection(allFlagsTable.getSelection().getItems())); 186 187 PersistableSashForm.loadState(sash, state.getChild(SASH)); 188 allFlagsFilter.loadState(getState().getChild(JVM_FLAGS_FILTER)); 189 190 infoViewer.setValues(getDataSource().getItems()); 191 allFlagsTable.show(getDataSource().getItems().apply(FLAGS_FILTER)); 192 onFilterChange(flagsFilter); 193 addResultActions(form); 194 allFlagsTable.getManager().setSelectionState(flagsSelection); 195 } 196 197 private void onFilterChange(IItemFilter filter) { 198 allFlagsFilter.filterChangeHelper(filter, allFlagsTable, getDataSource().getItems().apply(FLAGS_FILTER)); 199 flagsFilter = filter; 200 } 201 202 @Override 203 public void saveTo(IWritableState memento) { 204 allFlagsTable.getManager().getSettings().saveState(memento.createChild(JVM_FLAGS)); 205 allFlagsFilter.saveState(memento.createChild(JVM_FLAGS_FILTER)); 206 PersistableSashForm.saveState(sash, memento.createChild(SASH)); 207 208 saveToLocal(); 209 } 210 211 private void saveToLocal() { 212 flagsSelection = allFlagsTable.getManager().getSelectionState(); 213 } 214 215 } 216 217 private static final String SASH = "sash"; //$NON-NLS-1$ 218 private static final String JVM_FLAGS = "jvmFlags"; //$NON-NLS-1$ 219 private static final String JVM_FLAGS_FILTER = "jvmFlagsFilter"; //$NON-NLS-1$ 220 221 private static final String FLAG_VALUE_COL_ID = "value"; //$NON-NLS-1$ 222 private static final CompositeKeyHistogramBuilder FLAG_HISTOGRAM = new CompositeKeyHistogramBuilder(); 223 static { 224 FLAG_HISTOGRAM.addKeyColumn(JdkAttributes.FLAG_NAME); 225 FLAG_HISTOGRAM.addKeyColumn(JdkAttributes.FLAG_ORIGIN); 226 FLAG_HISTOGRAM.addKeyColumn(FLAG_VALUE_COL_ID, Messages.JVMInformationPage_COLUMN_VALUE, FLAG_VALUE_FIELD); 227 } 228 229 private IItemFilter flagsFilter; 230 private SelectionState flagsSelection; 231 232 @Override 233 public IPageUI display(Composite parent, FormToolkit toolkit, IPageContainer pageContainer, IState state) { 234 return new JVMInformationUi(parent, toolkit, pageContainer, state); 235 } 236 237 public JVMInformationPage(IPageDefinition dpd, StreamModel items, IPageContainer editor) { 238 super(dpd, items, editor); 239 } 240 241 @Override 242 public IItemFilter getDefaultSelectionFilter() { 243 return ItemFilters.or(FLAGS_FILTER, JdkFilters.VM_INFO); 244 } 245 }