diff --git a/src/utils/IdealGraphVisualizer/Coordinator/pom.xml b/src/utils/IdealGraphVisualizer/Coordinator/pom.xml
index 4d773f0d8b344..fcfad0ba23369 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/pom.xml
+++ b/src/utils/IdealGraphVisualizer/Coordinator/pom.xml
@@ -88,6 +88,11 @@
org-openide-util-lookup
${netbeans.version}
+
+ org.netbeans.api
+ org-openide-modules
+ ${netbeans.version}
+
org.netbeans.api
org-openide-util-ui
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java
index d4764648adf9e..c66c40810c086 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -28,21 +28,32 @@
import com.sun.hotspot.igv.data.ChangedListener;
import com.sun.hotspot.igv.data.GraphDocument;
import com.sun.hotspot.igv.data.InputGraph;
-import com.sun.hotspot.igv.data.services.GroupCallback;
+import com.sun.hotspot.igv.data.serialization.ParseMonitor;
+import com.sun.hotspot.igv.data.serialization.Parser;
+import com.sun.hotspot.igv.data.serialization.Printer;
+import com.sun.hotspot.igv.data.serialization.Printer.GraphContext;
+import com.sun.hotspot.igv.data.services.GraphViewer;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
+import com.sun.hotspot.igv.settings.Settings;
import com.sun.hotspot.igv.util.LookupHistory;
import com.sun.hotspot.igv.view.EditorTopComponent;
import java.awt.BorderLayout;
import java.awt.Dimension;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.HashSet;
-import java.util.Set;
-import javax.swing.UIManager;
+import java.io.*;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.swing.*;
import javax.swing.border.Border;
+import javax.swing.filechooser.FileFilter;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.ErrorManager;
-import org.openide.actions.GarbageCollectAction;
import org.openide.awt.Toolbar;
import org.openide.awt.ToolbarPool;
import org.openide.explorer.ExplorerManager;
@@ -50,7 +61,9 @@
import org.openide.explorer.view.BeanTreeView;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
import org.openide.util.NbBundle;
+import org.openide.windows.Mode;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
@@ -60,59 +73,145 @@
*/
public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider, ChangedListener {
- public static OutlineTopComponent instance;
public static final String PREFERRED_ID = "OutlineTopComponent";
+ private static final GraphDocument document = new GraphDocument();
+ private static final int WORK_UNITS = 10000;
+ private static final FileFilter xmlFileFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory();
+ }
+
+ @Override
+ public String getDescription() {
+ return "Graph files (*.xml)";
+ }
+ };
+ private static final Server server = new Server(document, OutlineTopComponent::loadContext);
+ public static OutlineTopComponent instance;
+ private final Set selectedFolders = new HashSet<>();
private ExplorerManager manager;
- private final GraphDocument document;
private FolderNode root;
- private SaveAllAction saveAllAction;
+ private SaveAction saveAction;
+ private SaveAsAction saveAsAction;
private RemoveAllAction removeAllAction;
private GraphNode[] selectedGraphs = new GraphNode[0];
- private final Set selectedFolders = new HashSet<>();
+ private Path documentPath = null;
private OutlineTopComponent() {
initComponents();
setName(NbBundle.getMessage(OutlineTopComponent.class, "CTL_OutlineTopComponent"));
setToolTipText(NbBundle.getMessage(OutlineTopComponent.class, "HINT_OutlineTopComponent"));
-
- document = new GraphDocument();
initListView();
initToolbar();
- initReceivers();
+ server.startServer();
+ }
+
+ public static GraphDocument getDocument() {
+ return document;
+ }
+
+ /**
+ * Gets default instance. Do not use directly: reserved for *.settings files only,
+ * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
+ * To obtain the singleton instance, use {@link #findInstance()}.
+ */
+ private static synchronized OutlineTopComponent getDefault() {
+ if (instance == null) {
+ instance = new OutlineTopComponent();
+ }
+ return instance;
+ }
+
+ /**
+ * Obtain the OutlineTopComponent instance. Never call {@link #getDefault} directly!
+ */
+ public static synchronized OutlineTopComponent findInstance() {
+ TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
+ if (win == null) {
+ ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find Outline component. It will not be located properly in the window system.");
+ return getDefault();
+ }
+ if (win instanceof OutlineTopComponent) {
+ return (OutlineTopComponent) win;
+ }
+ ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior.");
+ return getDefault();
+ }
+
+ /**
+ * Stores the provided graph document to the designated file path with associated contexts.
+ */
+ private static void saveGraphDocument(GraphDocument doc, String path) throws IOException {
+ List saveContexts = new ArrayList<>();
+ WindowManager manager = WindowManager.getDefault();
+ for (Mode mode : manager.getModes()) {
+ List compList = new ArrayList<>(Arrays.asList(manager.getOpenedTopComponents(mode)));
+ for (TopComponent comp : compList) {
+ if (comp instanceof EditorTopComponent etc) {
+ InputGraph graph = etc.getModel().getGraph();
+ if (graph.isDiffGraph() && graph.getFirstGraph().getGroup() != graph.getSecondGraph().getGroup()) {
+ // don't save diff graphs comparing graphs from different groups
+ continue;
+ }
+ GraphContext graphContext = getGraphContext(etc);
+ saveContexts.add(graphContext);
+ }
+ }
+ }
+
+ try (Writer writer = new OutputStreamWriter(new FileOutputStream(path))) {
+ Printer.exportGraphDocument(writer, doc, saveContexts);
+ }
+ }
+
+ private static GraphContext getGraphContext(EditorTopComponent etc) {
+ InputGraph openedGraph = etc.getModel().getFirstGraph();
+ int posDiff = etc.getModel().getSecondPosition() - etc.getModel().getFirstPosition();
+ if (etc.getModel().getHiddenNodes().isEmpty()) {
+ return new GraphContext(openedGraph, new AtomicInteger(posDiff), new HashSet<>(), new AtomicBoolean(true));
+ } else {
+ Set visibleNodes = new HashSet<>(etc.getModel().getVisibleNodes());
+ return new GraphContext(openedGraph, new AtomicInteger(posDiff), visibleNodes, new AtomicBoolean(false));
+ }
}
private void initListView() {
- manager = new ExplorerManager();
+ setDocumentPath(null);
+ FolderNode.clearGraphNodeMap();
+ document.clear();
root = new FolderNode(document);
+ manager = new ExplorerManager();
manager.setRootContext(root);
((BeanTreeView) this.treeView).setRootVisible(false);
-
associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
}
private void initToolbar() {
Toolbar toolbar = new Toolbar();
toolbar.setBorder((Border) UIManager.get("Nb.Editor.Toolbar.border")); //NOI18N
- toolbar.setMinimumSize(new Dimension(0,0)); // MacOS BUG with ToolbarWithOverflow
+ toolbar.setMinimumSize(new Dimension(0, 0)); // MacOS BUG with ToolbarWithOverflow
this.add(toolbar, BorderLayout.NORTH);
+ toolbar.add(OpenAction.get(OpenAction.class));
toolbar.add(ImportAction.get(ImportAction.class));
- toolbar.add(SaveAsAction.get(SaveAsAction.class).createContextAwareInstance(this.getLookup()));
+ toolbar.addSeparator();
- saveAllAction = SaveAllAction.get(SaveAllAction.class);
- saveAllAction.setEnabled(false);
- toolbar.add(saveAllAction);
+ saveAction = SaveAction.get(SaveAction.class);
+ saveAction.setEnabled(false);
+ toolbar.add(saveAction);
+ saveAsAction = SaveAsAction.get(SaveAsAction.class);
+ saveAsAction.setEnabled(false);
+ toolbar.add(saveAsAction);
+ toolbar.addSeparator();
toolbar.add(RemoveAction.get(RemoveAction.class).createContextAwareInstance(this.getLookup()));
-
removeAllAction = RemoveAllAction.get(RemoveAllAction.class);
removeAllAction.setEnabled(false);
toolbar.add(removeAllAction);
- toolbar.add(GarbageCollectAction.get(GarbageCollectAction.class).getToolbarPresenter());
-
for (Toolbar tb : ToolbarPool.getDefault().getToolbars()) {
tb.setVisible(false);
}
@@ -122,66 +221,16 @@ private void initToolbar() {
private void documentChanged() {
boolean enableButton = !document.getElements().isEmpty();
- saveAllAction.setEnabled(enableButton);
+ saveAction.setEnabled(enableButton);
+ saveAsAction.setEnabled(enableButton);
removeAllAction.setEnabled(enableButton);
}
- private void initReceivers() {
-
- final GroupCallback callback = g -> {
- synchronized(OutlineTopComponent.this) {
- g.setParent(getDocument());
- getDocument().addElement(g);
- }
- };
-
- new Server(callback);
- }
-
- public void clear() {
- document.clear();
- FolderNode.clearGraphNodeMap();
- root = new FolderNode(document);
- manager.setRootContext(root);
- }
-
@Override
public ExplorerManager getExplorerManager() {
return manager;
}
- public GraphDocument getDocument() {
- return document;
- }
-
- /**
- * Gets default instance. Do not use directly: reserved for *.settings files only,
- * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
- * To obtain the singleton instance, use {@link #findInstance()}.
- */
- public static synchronized OutlineTopComponent getDefault() {
- if (instance == null) {
- instance = new OutlineTopComponent();
- }
- return instance;
- }
-
- /**
- * Obtain the OutlineTopComponent instance. Never call {@link #getDefault} directly!
- */
- public static synchronized OutlineTopComponent findInstance() {
- TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
- if (win == null) {
- ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find Outline component. It will not be located properly in the window system.");
- return getDefault();
- }
- if (win instanceof OutlineTopComponent) {
- return (OutlineTopComponent) win;
- }
- ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior.");
- return getDefault();
- }
-
@Override
public int getPersistenceType() {
return TopComponent.PERSISTENCE_ALWAYS;
@@ -236,15 +285,12 @@ public void changed(InputGraphProvider lastProvider) {
InputGraph graph = lastProvider.getGraph();
if (graph != null) {
if (graph.isDiffGraph()) {
- EditorTopComponent editor = EditorTopComponent.getActive();
- if (editor != null) {
- InputGraph firstGraph = editor.getModel().getFirstGraph();
- GraphNode firstNode = FolderNode.getGraphNode(firstGraph);
- InputGraph secondGraph = editor.getModel().getSecondGraph();
- GraphNode secondNode = FolderNode.getGraphNode(secondGraph);
- if (firstNode != null && secondNode != null) {
- selectedGraphs = new GraphNode[]{firstNode, secondNode};
- }
+ InputGraph firstGraph = graph.getFirstGraph();
+ GraphNode firstNode = FolderNode.getGraphNode(firstGraph);
+ InputGraph secondGraph = graph.getSecondGraph();
+ GraphNode secondNode = FolderNode.getGraphNode(secondGraph);
+ if (firstNode != null && secondNode != null) {
+ selectedGraphs = new GraphNode[]{firstNode, secondNode};
}
} else {
GraphNode graphNode = FolderNode.getGraphNode(graph);
@@ -271,15 +317,229 @@ public void changed(InputGraphProvider lastProvider) {
}
@Override
- public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
- // Not called when user starts application for the first time
- super.readExternal(objectInput);
- ((BeanTreeView) this.treeView).setRootVisible(false);
+ public boolean canClose() {
+ SwingUtilities.invokeLater(() -> {
+ clearWorkspace();
+ open(); // Reopen the OutlineTopComponent
+ requestActive();
+ });
+ return true;
}
- @Override
- public void writeExternal(ObjectOutput objectOutput) throws IOException {
- super.writeExternal(objectOutput);
+ private void setDocumentPath(String path) {
+ if (path != null) {
+ documentPath = Paths.get(path);
+ setHtmlDisplayName("" + documentPath.getFileName().toString() + "");
+ setToolTipText("File: " + path);
+ } else {
+ documentPath = null;
+ setHtmlDisplayName("untitled");
+ setToolTipText("No file");
+ }
+
+ }
+
+ /**
+ * Clears the workspace by resetting the document path, clearing the document, and resetting the folder structure.
+ * After clearing the workspace, it will be ready for new documents.
+ */
+ public void clearWorkspace() {
+ setDocumentPath(null);
+ document.clear();
+ FolderNode.clearGraphNodeMap();
+ root = new FolderNode(document);
+ manager.setRootContext(root);
+ EditorTopComponent.closeAllInstances();
+ }
+
+ /**
+ * Opens a file dialog to select and load a graph document.
+ * Clears the workspace and adds the loaded document to the workspace.
+ **/
+ public void openFile() {
+ JFileChooser fc = new JFileChooser(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT));
+ fc.setFileFilter(xmlFileFilter);
+ if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
+ clearWorkspace();
+ String path = fc.getSelectedFile().getAbsolutePath();
+ Settings.get().put(Settings.DIRECTORY, path);
+ setDocumentPath(path);
+ try {
+ loadGraphDocument(path, true);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private boolean overwriteDialog(String filename) {
+ JFrame frame = new JFrame();
+ String message = "Do you want to overwrite " + filename + "?";
+ int result = JOptionPane.showConfirmDialog(frame, message, "Confirm Overwrite", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
+ frame.dispose();
+ return result == JOptionPane.YES_OPTION;
+ }
+
+ /**
+ * Saves the current graph document.
+ * If the document has no location, let the user specify the file location.
+ */
+ public void save() {
+ if (documentPath == null) {
+ saveAs();
+ return;
+ }
+
+ String filePath = documentPath.toAbsolutePath().toString();
+ if (Files.exists(Paths.get(filePath)) && overwriteDialog(documentPath.getFileName().toString())) {
+ try {
+ saveGraphDocument(getDocument(), filePath);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ saveAs();
+ }
+ }
+
+ public void saveAs() {
+ JFileChooser fc = new JFileChooser();
+ fc.setDialogTitle("Save As...");
+ fc.setFileFilter(xmlFileFilter);
+ fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT)));
+ if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
+ String path = fc.getSelectedFile().getAbsolutePath();
+
+ // Ask if the user wants to overwrite the file if it already exists
+ if (Files.exists(Paths.get(path)) && !overwriteDialog(fc.getSelectedFile().getName())) {
+ return; // user does not want to overwrite
+ }
+
+ Settings.get().put(Settings.DIRECTORY, path);
+ setDocumentPath(path);
+ try {
+ saveGraphDocument(getDocument(), path);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Imports graph documents from one or more XML files.
+ * Displays a file chooser dialog to select one or multiple XML files for import.
+ * Each selected file is added to the workspace.
+ **/
+ public void importFromXML() {
+ JFileChooser fc = new JFileChooser();
+ fc.setFileFilter(xmlFileFilter);
+ fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT)));
+ fc.setMultiSelectionEnabled(true);
+ if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
+ for (final File file : fc.getSelectedFiles()) {
+ String path = file.getAbsolutePath();
+ Settings.get().put(Settings.DIRECTORY, path);
+ try {
+ loadGraphDocument(path, false);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Loads and opens the given graph context (opened graphs and visible nodes).
+ */
+ private static void loadContext(GraphContext context) {
+ final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class);
+ if (viewer != null) {
+ final int difference = context.posDiff().get();
+ final InputGraph firstGraph = context.inputGraph();
+ final Set visibleNodes = context.visibleNodes();
+ final boolean showAll = context.showAll().get();
+
+ SwingUtilities.invokeLater(() -> {
+ InputGraph openedGraph = viewer.view(firstGraph, true);
+ if (openedGraph != null) {
+ EditorTopComponent etc = EditorTopComponent.findEditorForGraph(firstGraph);
+ if (etc != null) {
+ if (showAll) {
+ etc.getModel().setHiddenNodes(new HashSet<>());
+ } else {
+ etc.getModel().showOnly(visibleNodes);
+ }
+ int firstGraphIdx = firstGraph.getIndex();
+ if (difference > 0) {
+ etc.getModel().setPositions(firstGraphIdx, firstGraphIdx + difference);
+ } else if (difference < 0) {
+ etc.getModel().setPositions(firstGraphIdx + difference, firstGraphIdx);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Loads a graph document from the given file path, updating progress via a ProgressHandle.
+ * Parse the XML file, add the parsed document to the workspace, and load associated contexts if specified.
+ */
+ private void loadGraphDocument(String path, boolean loadContext) throws IOException {
+ if (Files.notExists(Path.of(path))) {
+ return;
+ }
+ File file = new File(path);
+ final FileChannel channel;
+ final long start;
+ try {
+ channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
+ start = channel.size();
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ return;
+ }
+
+ final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName());
+ handle.start(WORK_UNITS);
+
+ ParseMonitor monitor = new ParseMonitor() {
+ @Override
+ public void updateProgress() {
+ try {
+ int prog = (int) (WORK_UNITS * (double) channel.position() / (double) start);
+ handle.progress(prog);
+ } catch (IOException ignored) {
+ }
+ }
+
+ @Override
+ public void setState(String state) {
+ updateProgress();
+ handle.progress(state);
+ }
+ };
+ try {
+ if (file.getName().endsWith(".xml")) {
+ ArrayList contexts = new ArrayList<>();
+ final Parser parser = new Parser(channel, monitor, document, loadContext ? contexts::add : null);
+ parser.parse();
+ SwingUtilities.invokeLater(() -> {
+ for (Node child : manager.getRootContext().getChildren().getNodes(true)) {
+ // Nodes are lazily created. By expanding and collapsing they are all initialized
+ ((BeanTreeView) this.treeView).expandNode(child);
+ ((BeanTreeView) this.treeView).collapseNode(child);
+ }
+ requestActive();
+ });
+ for (GraphContext ctx : contexts) {
+ loadContext(ctx);
+ }
+ }
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ handle.finish();
}
/** This method is called from within the constructor to
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/ImportAction.java b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/ImportAction.java
index 03d062d804104..f503e6c2eb748 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/ImportAction.java
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/ImportAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -25,24 +25,10 @@
package com.sun.hotspot.igv.coordinator.actions;
import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
-import com.sun.hotspot.igv.data.GraphDocument;
-import com.sun.hotspot.igv.data.serialization.GraphParser;
-import com.sun.hotspot.igv.data.serialization.ParseMonitor;
-import com.sun.hotspot.igv.data.serialization.Parser;
-import com.sun.hotspot.igv.settings.Settings;
-import java.io.File;
-import java.io.IOException;
-import java.nio.channels.FileChannel;
-import java.nio.file.StandardOpenOption;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import javax.swing.Action;
-import javax.swing.JFileChooser;
-import javax.swing.SwingUtilities;
-import javax.swing.filechooser.FileFilter;
-import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
-import org.openide.util.*;
+import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
/**
@@ -51,89 +37,15 @@
*/
public final class ImportAction extends CallableSystemAction {
- private static final int WORKUNITS = 10000;
- public static FileFilter getFileFilter() {
- return new FileFilter() {
-
- @Override
- public boolean accept(File f) {
- return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory();
- }
-
- @Override
- public String getDescription() {
- return "Graph files (*.xml)";
- }
- };
+ public ImportAction() {
+ putValue(Action.SHORT_DESCRIPTION, "Import from XML...");
+ putValue(Action.SMALL_ICON, ImageUtilities.loadImageIcon(iconResource(), true));
}
@Override
public void performAction() {
- JFileChooser fc = new JFileChooser();
- fc.setFileFilter(ImportAction.getFileFilter());
- fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT)));
- fc.setMultiSelectionEnabled(true);
-
- if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
- for (final File file : fc.getSelectedFiles()) {
- File dir = file;
- if (!dir.isDirectory()) {
- dir = dir.getParentFile();
- }
-
- Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
- try {
- final FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
- final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName());
- handle.start(WORKUNITS);
- final long startTime = System.currentTimeMillis();
- final long start = channel.size();
- ParseMonitor monitor = new ParseMonitor() {
- @Override
- public void updateProgress() {
- try {
- int prog = (int) (WORKUNITS * (double) channel.position() / (double) start);
- handle.progress(prog);
- } catch (IOException ignored) {}
- }
- @Override
- public void setState(String state) {
- updateProgress();
- handle.progress(state);
- }
- };
- final GraphParser parser;
- final OutlineTopComponent component = OutlineTopComponent.findInstance();
- if (file.getName().endsWith(".xml")) {
- parser = new Parser(channel, monitor, null);
- } else {
- parser = null;
- }
- RequestProcessor.getDefault().post(new Runnable() {
- @Override
- public void run() {
- try {
- final GraphDocument document = parser.parse();
- if (document != null) {
- SwingUtilities.invokeLater(() -> {
- component.requestActive();
- component.getDocument().addGraphDocument(document);
- });
- }
- } catch (IOException ex) {
- Exceptions.printStackTrace(ex);
- }
- handle.finish();
- long stop = System.currentTimeMillis();
- Logger.getLogger(getClass().getName()).log(Level.INFO, "Loaded in " + file + " in " + ((stop - startTime) / 1000.0) + " seconds");
- }
- });
- } catch (IOException ex) {
- Exceptions.printStackTrace(ex);
- }
- }
- }
+ OutlineTopComponent.findInstance().importFromXML();
}
@Override
@@ -141,12 +53,6 @@ public String getName() {
return NbBundle.getMessage(ImportAction.class, "CTL_ImportAction");
}
- public ImportAction() {
- putValue(Action.SHORT_DESCRIPTION, "Open");
- // D is the Control key on most platforms, the Command (meta) key on Macintosh
- putValue(Action.ACCELERATOR_KEY, Utilities.stringToKey("D-O"));
- }
-
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/OpenAction.java b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/OpenAction.java
new file mode 100644
index 0000000000000..cd322efe61989
--- /dev/null
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/OpenAction.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024, 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.
+ *
+ * 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.hotspot.igv.coordinator.actions;
+
+import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
+import javax.swing.Action;
+import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+import org.openide.util.actions.CallableSystemAction;
+
+public final class OpenAction extends CallableSystemAction {
+
+ public OpenAction() {
+ putValue(Action.SHORT_DESCRIPTION, "Open...");
+ // D is the Control key on most platforms, the Command (meta) key on Macintosh
+ putValue(Action.ACCELERATOR_KEY, Utilities.stringToKey("D-O"));
+ putValue(Action.SMALL_ICON, ImageUtilities.loadImageIcon(iconResource(), true));
+ }
+
+ @Override
+ public void performAction() {
+ OutlineTopComponent.findInstance().openFile();
+ }
+
+ @Override
+ public String getName() {
+ return NbBundle.getMessage(OpenAction.class, "CTL_OpenAction");
+ }
+
+ @Override
+ public HelpCtx getHelpCtx() {
+ return HelpCtx.DEFAULT_HELP;
+ }
+
+ @Override
+ protected boolean asynchronous() {
+ return false;
+ }
+
+ @Override
+ protected String iconResource() {
+ return "com/sun/hotspot/igv/coordinator/images/open.png";
+ }
+}
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java
index e1b3a62f0eb86..9f2ac69aa641b 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/RemoveAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -28,6 +28,7 @@
import javax.swing.Action;
import org.openide.nodes.Node;
import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.actions.NodeAction;
@@ -37,6 +38,11 @@
*/
public final class RemoveAction extends NodeAction {
+ public RemoveAction() {
+ putValue(Action.SHORT_DESCRIPTION, getName());
+ putValue(Action.SMALL_ICON, ImageUtilities.loadImageIcon(iconResource(), true));
+ }
+
@Override
protected void performAction(Node[] activatedNodes) {
for (Node n : activatedNodes) {
@@ -47,10 +53,6 @@ protected void performAction(Node[] activatedNodes) {
}
}
- public RemoveAction() {
- putValue(Action.SHORT_DESCRIPTION, getName());
- }
-
@Override
public String getName() {
return NbBundle.getMessage(RemoveAction.class, "CTL_RemoveAction");
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java
index e95099d0f97fb..04158b23b5260 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/RemoveAllAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2024, 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
@@ -27,6 +27,7 @@
import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
import javax.swing.Action;
import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
@@ -42,7 +43,8 @@ public String getName() {
}
public RemoveAllAction() {
- putValue(Action.SHORT_DESCRIPTION, "Remove all graphs and groups");
+ putValue(Action.SHORT_DESCRIPTION, "Clear workspace");
+ putValue(Action.SMALL_ICON, ImageUtilities.loadImageIcon(iconResource(), true));
}
@Override
@@ -62,6 +64,6 @@ protected boolean asynchronous() {
@Override
public void performAction() {
- OutlineTopComponent.findInstance().clear();
+ OutlineTopComponent.findInstance().clearWorkspace();
}
}
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAction.java
similarity index 77%
rename from src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java
rename to src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAction.java
index dde018f60e937..77ec88d0659b1 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAllAction.java
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -27,37 +27,34 @@
import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
import javax.swing.Action;
import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.util.actions.CallableSystemAction;
-/**
- *
- * @author Thomas Wuerthinger
- */
-public final class SaveAllAction extends CallableSystemAction {
+public final class SaveAction extends CallableSystemAction {
+
+ public SaveAction() {
+ putValue(Action.SHORT_DESCRIPTION, "Save");
+ // D is the Control key on most platforms, the Command (meta) key on Macintosh
+ putValue(Action.ACCELERATOR_KEY, Utilities.stringToKey("D-S"));
+ putValue(Action.SMALL_ICON, ImageUtilities.loadImageIcon(iconResource(), true));
+ }
@Override
public void performAction() {
- final OutlineTopComponent component = OutlineTopComponent.findInstance();
- SaveAsAction.save(component.getDocument());
+ OutlineTopComponent.findInstance().save();
}
@Override
public String getName() {
- return NbBundle.getMessage(SaveAllAction.class, "CTL_SaveAllAction");
- }
-
- public SaveAllAction() {
- putValue(Action.SHORT_DESCRIPTION, "Save all groups to XML file...");
- // D is the Control key on most platforms, the Command (meta) key on Macintosh
- putValue(Action.ACCELERATOR_KEY, Utilities.stringToKey("D-S"));
+ return NbBundle.getMessage(SaveAction.class, "CTL_SaveAction");
}
@Override
protected String iconResource() {
- return "com/sun/hotspot/igv/coordinator/images/saveall.gif";
+ return "com/sun/hotspot/igv/coordinator/images/save.png";
}
@Override
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java
index 4be57a51dba44..65b13dfbf0689 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/actions/SaveAsAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -24,75 +24,27 @@
package com.sun.hotspot.igv.coordinator.actions;
-import com.sun.hotspot.igv.coordinator.FolderNode;
-import com.sun.hotspot.igv.data.Folder;
-import com.sun.hotspot.igv.data.GraphDocument;
-import com.sun.hotspot.igv.data.Group;
-import com.sun.hotspot.igv.data.serialization.Printer;
-import com.sun.hotspot.igv.settings.Settings;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.file.Files;
+import com.sun.hotspot.igv.coordinator.OutlineTopComponent;
import javax.swing.Action;
-import javax.swing.JFileChooser;
-import org.openide.nodes.Node;
import org.openide.util.HelpCtx;
+import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
-import org.openide.util.actions.NodeAction;
+import org.openide.util.actions.CallableSystemAction;
/**
*
* @author Thomas Wuerthinger
*/
-public final class SaveAsAction extends NodeAction {
+public final class SaveAsAction extends CallableSystemAction {
public SaveAsAction() {
- putValue(Action.SHORT_DESCRIPTION, "Save selected groups to XML file...");
+ putValue(Action.SHORT_DESCRIPTION, "Save as...");
+ putValue(Action.SMALL_ICON, ImageUtilities.loadImageIcon(iconResource(), true));
}
@Override
- protected void performAction(Node[] activatedNodes) {
- GraphDocument doc = new GraphDocument();
- for (Node node : activatedNodes) {
- if (node instanceof FolderNode) {
- FolderNode folderNode = (FolderNode) node;
- Folder folder = folderNode.getFolder();
- if (folder instanceof Group) {
- Group group = (Group) folder;
- doc.addElement(group);
- }
- }
- }
- save(doc);
- }
-
- public static void save(GraphDocument doc) {
- JFileChooser fc = new JFileChooser();
- fc.setFileFilter(ImportAction.getFileFilter());
- fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT)));
-
- if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
- File file = fc.getSelectedFile();
- if (!file.getName().contains(".")) {
- file = new File(file.getAbsolutePath() + ".xml");
- }
-
- File dir = file;
- if (!dir.isDirectory()) {
- dir = dir.getParentFile();
- }
- Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath());
- try {
- try (Writer writer = new OutputStreamWriter(Files.newOutputStream(file.toPath()))) {
- Printer p = new Printer();
- p.export(writer, doc);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ public void performAction() {
+ OutlineTopComponent.findInstance().saveAs();
}
@Override
@@ -102,7 +54,7 @@ public String getName() {
@Override
protected String iconResource() {
- return "com/sun/hotspot/igv/coordinator/images/save.png";
+ return "com/sun/hotspot/igv/coordinator/images/save_as.gif";
}
@Override
@@ -114,17 +66,4 @@ public HelpCtx getHelpCtx() {
protected boolean asynchronous() {
return false;
}
-
- @Override
- protected boolean enable(Node[] nodes) {
- if (nodes.length > 0) {
- for (Node n : nodes) {
- if (!(n instanceof FolderNode) || ((FolderNode) n).isRootNode()) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
}
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/Bundle.properties b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/Bundle.properties
index 1b17042508e6e..2bebc0e279781 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/Bundle.properties
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/Bundle.properties
@@ -1,6 +1,3 @@
-AdvancedOption_DisplayName_Coordinator=Settings
-AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
-CTL_OutlineTopComponent=Outline
-CTL_SomeAction=test
-HINT_OutlineTopComponent=Displays loaded groups of graphs.
+CTL_OutlineTopComponent=Workspace
+HINT_OutlineTopComponent=Opened groups of graphs.
OpenIDE-Module-Name=Coordinator
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/actions/Bundle.properties b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/actions/Bundle.properties
index de3aa509a3111..f192e91fceb11 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/actions/Bundle.properties
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/actions/Bundle.properties
@@ -1,8 +1,9 @@
-CTL_ImportAction=Open...
+CTL_ImportAction=Import...
+CTL_OpenAction=Open...
CTL_DiffGraphAction=Difference to current graph
CTL_RemoveAction=Remove selected graphs and groups
-CTL_RemoveAllAction=Remove all graphs and groups
-CTL_OutlineAction=Outline
-CTL_SaveAsAction=Save selected groups...
-CTL_SaveAllAction=Save all groups...
+CTL_RemoveAllAction=Clear workspace
+CTL_OutlineAction=Workspace
+CTL_SaveAction=Save
+CTL_SaveAsAction=Save as...
CTL_NewFilterAction=New filter...
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/import.png b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/import.png
index 7e4a6badcb151..d8c8c766b88fd 100644
Binary files a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/import.png and b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/import.png differ
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/open.png b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/open.png
new file mode 100644
index 0000000000000..212763d1263e3
Binary files /dev/null and b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/open.png differ
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/saveall.gif b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/save_as.gif
similarity index 100%
rename from src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/saveall.gif
rename to src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/images/save_as.gif
diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/layer.xml b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/layer.xml
index 60e73788c952a..dd1a2c0d2abc3 100644
--- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/layer.xml
+++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/layer.xml
@@ -26,8 +26,9 @@
+
+
-
@@ -55,6 +56,10 @@
+
+
+
+
@@ -71,13 +76,13 @@
+
+
+
+
-
-
-
-
-
+
@@ -105,8 +110,8 @@
-
+
diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/Folder.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/Folder.java
index 9ff7c32bd1f1d..3bd92a49cbfb3 100644
--- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/Folder.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/Folder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024, 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
@@ -25,7 +25,7 @@
import java.util.List;
-public interface Folder {
+public interface Folder extends Properties.Provider {
void setName(String name);
String getName();
String getDisplayName();
@@ -33,4 +33,5 @@ public interface Folder {
void removeElement(FolderElement element);
void addElement(FolderElement group);
ChangedEvent extends Folder> getChangedEvent();
+ Properties getProperties();
}
diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/FolderElement.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/FolderElement.java
index eb0a874278fab..2bf153674c739 100644
--- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/FolderElement.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/FolderElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024, 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
@@ -23,11 +23,12 @@
*/
package com.sun.hotspot.igv.data;
-public interface FolderElement {
+public interface FolderElement extends Properties.Provider {
ChangedEvent extends FolderElement> getDisplayNameChangedEvent();
void setName(String name);
String getName();
String getDisplayName();
void setParent(Folder parent);
Folder getParent();
+ Properties getProperties();
}
diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/GraphDocument.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/GraphDocument.java
index 1f13cb3b43374..4bf933d43c223 100644
--- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/GraphDocument.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/GraphDocument.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -54,7 +54,7 @@ public ChangedEvent getChangedEvent() {
public void addGraphDocument(GraphDocument document) {
if (document != this) {
- for (FolderElement e : document.elements) {
+ for (FolderElement e : document.getElements()) {
e.setParent(this);
this.addElement(e);
}
diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/Group.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/Group.java
index 01af950a0936d..e98164409b690 100644
--- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/Group.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/Group.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -126,13 +126,22 @@ public String getName() {
@Override
public String getDisplayName() {
- String displayName = (getParent() == null ? "" : getParent().getElements().indexOf(this) + 1 + " - ") + getName();
+ String displayName = (getParent() == null ? "" : getIndex() + 1 + " - ") + getName();
if (getProperties().get("osr") != null) {
displayName += " [OSR]";
}
return displayName;
}
+ public int getIndex() {
+ Folder parent = getParent();
+ if (parent != null) {
+ return parent.getElements().indexOf(this);
+ } else {
+ return -1;
+ }
+ }
+
public String getType() {
return getProperties().get("type");
}
diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java
index 26dc2c6cfb2da..9db0d83e0ebf7 100644
--- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -23,18 +23,19 @@
*/
package com.sun.hotspot.igv.data.serialization;
+import com.sun.hotspot.igv.data.Properties;
import com.sun.hotspot.igv.data.*;
+import com.sun.hotspot.igv.data.serialization.Printer.GraphContext;
+import com.sun.hotspot.igv.data.serialization.Printer.GraphContextAction;
import com.sun.hotspot.igv.data.serialization.XMLParser.ElementHandler;
import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler;
import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler;
-import com.sun.hotspot.igv.data.services.GroupCallback;
import java.io.IOException;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.SwingUtilities;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
@@ -49,10 +50,13 @@
*/
public class Parser implements GraphParser {
- public static final String INDENT = " ";
public static final String TOP_ELEMENT = "graphDocument";
public static final String GROUP_ELEMENT = "group";
public static final String GRAPH_ELEMENT = "graph";
+ public static final String GRAPH_STATES_ELEMENT = "graphStates";
+ public static final String STATE_ELEMENT = "state";
+ public static final String STATE_POSITION_DIFFERENCE = "difference";
+ public static final String POSITION_DIFFERENCE_PROPERTY = "value";
public static final String ROOT_ELEMENT = "graphDocument";
public static final String PROPERTIES_ELEMENT = "properties";
public static final String EDGES_ELEMENT = "edges";
@@ -60,15 +64,11 @@ public class Parser implements GraphParser {
public static final String EDGE_ELEMENT = "edge";
public static final String NODE_ELEMENT = "node";
public static final String NODES_ELEMENT = "nodes";
+ public static final String VISIBLE_NODES_ELEMENT = "visibleNodes";
+ public static final String ALL_PROPERTY = "all";
public static final String REMOVE_EDGE_ELEMENT = "removeEdge";
public static final String REMOVE_NODE_ELEMENT = "removeNode";
public static final String METHOD_NAME_PROPERTY = "name";
- public static final String GROUP_NAME_PROPERTY = "name";
- public static final String METHOD_IS_PUBLIC_PROPERTY = "public";
- public static final String METHOD_IS_STATIC_PROPERTY = "static";
- public static final String TRUE_VALUE = "true";
- public static final String NODE_NAME_PROPERTY = "name";
- public static final String EDGE_NAME_PROPERTY = "name";
public static final String NODE_ID_PROPERTY = "id";
public static final String FROM_PROPERTY = "from";
public static final String TO_PROPERTY = "to";
@@ -89,110 +89,42 @@ public class Parser implements GraphParser {
public static final String BLOCK_ELEMENT = "block";
public static final String SUCCESSORS_ELEMENT = "successors";
public static final String SUCCESSOR_ELEMENT = "successor";
- public static final String ASSEMBLY_ELEMENT = "assembly";
public static final String DIFFERENCE_PROPERTY = "difference";
- private final TopElementHandler xmlDocument = new TopElementHandler<>();
+ private final TopElementHandler xmlData = new TopElementHandler<>();
private final Map differenceEncoding = new HashMap<>();
private final Map lastParsedGraph = new HashMap<>();
- private final GroupCallback groupCallback;
+ private final GraphDocument callbackDocument;
+ private final GraphContextAction contextAction;
+ private final ArrayList contexts = new ArrayList<>();
private final HashMap idCache = new HashMap<>();
private final ArrayList> blockConnections = new ArrayList<>();
- private int maxId = 0;
- private GraphDocument graphDocument;
private final ParseMonitor monitor;
private final ReadableByteChannel channel;
private boolean invokeLater = true;
- private int lookupID(String i) {
- try {
- return Integer.parseInt(i);
- } catch (NumberFormatException nfe) {
- // ignore
- }
- Integer id = idCache.get(i);
- if (id == null) {
- id = maxId++;
- idCache.put(i, id);
- }
- return id;
- }
-
- //
- private ElementHandler topHandler = new ElementHandler(TOP_ELEMENT) {
-
- @Override
- protected GraphDocument start() throws SAXException {
- graphDocument = new GraphDocument();
- return graphDocument;
- }
- };
- //
- private ElementHandler groupHandler = new XMLParser.ElementHandler(GROUP_ELEMENT) {
-
- @Override
- protected Group start() throws SAXException {
- final Group group = new Group(this.getParentObject());
-
- String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
- Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))));
-
- ParseMonitor monitor = getMonitor();
- if (monitor != null) {
- monitor.setState(group.getName());
- }
-
- final Folder parent = getParentObject();
- if (groupCallback == null || parent instanceof Group) {
- Runnable addToParent = () -> parent.addElement(group);
- if (invokeLater) {
- SwingUtilities.invokeLater(addToParent);
- } else {
- addToParent.run();
- }
- }
-
- return group;
- }
-
- @Override
- protected void end(String text) throws SAXException {
- }
- };
//
- private ElementHandler methodHandler = new XMLParser.ElementHandler(METHOD_ELEMENT) {
+ private final ElementHandler methodHandler = new XMLParser.ElementHandler<>(METHOD_ELEMENT) {
@Override
protected InputMethod start() throws SAXException {
-
- InputMethod method = parseMethod(this, getParentObject());
- getParentObject().setMethod(method);
+ Group group = getParentObject();
+ InputMethod method = parseMethod(this, group);
+ group.setMethod(method);
return method;
}
};
-
- private InputMethod parseMethod(XMLParser.ElementHandler,?> handler, Group group) throws SAXException {
- String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY);
- int bci = 0;
- try {
- bci = Integer.parseInt(s);
- } catch (NumberFormatException e) {
- throw new SAXException(e);
- }
- InputMethod method = new InputMethod(group, handler.readRequiredAttribute(METHOD_NAME_PROPERTY), handler.readRequiredAttribute(METHOD_SHORT_NAME_PROPERTY), bci);
- return method;
- }
//
- private HandoverElementHandler bytecodesHandler = new XMLParser.HandoverElementHandler(BYTECODES_ELEMENT, true) {
+ private final HandoverElementHandler bytecodesHandler = new XMLParser.HandoverElementHandler<>(BYTECODES_ELEMENT, true) {
@Override
- protected void end(String text) throws SAXException {
+ protected void end(String text) {
getParentObject().setBytecodes(text);
}
};
//
- private HandoverElementHandler inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT);
+ private final HandoverElementHandler inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT);
//
- private ElementHandler inlinedMethodHandler = new XMLParser.ElementHandler(METHOD_ELEMENT) {
+ private final ElementHandler inlinedMethodHandler = new XMLParser.ElementHandler<>(METHOD_ELEMENT) {
@Override
protected InputMethod start() throws SAXException {
@@ -201,97 +133,69 @@ protected InputMethod start() throws SAXException {
return method;
}
};
- //
- private ElementHandler graphHandler = new XMLParser.ElementHandler(GRAPH_ELEMENT) {
+ //
+ private final HandoverElementHandler nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
+ //
+ private final HandoverElementHandler controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT);
+ private final HandoverElementHandler graphStatesHandler = new HandoverElementHandler<>(GRAPH_STATES_ELEMENT);
+ private final ElementHandler stateHandler = new ElementHandler<>(STATE_ELEMENT) {
@Override
- protected InputGraph start() throws SAXException {
- String name = readAttribute(GRAPH_NAME_PROPERTY);
- InputGraph curGraph = new InputGraph(name);
- if (differenceEncoding.get(getParentObject())) {
- InputGraph previous = lastParsedGraph.get(getParentObject());
- lastParsedGraph.put(getParentObject(), curGraph);
- if (previous != null) {
- for (InputNode n : previous.getNodes()) {
- curGraph.addNode(n);
- }
- for (InputEdge e : previous.getEdges()) {
- curGraph.addEdge(e);
- }
- }
+ protected GraphContext start() {
+ InputGraph inputGraph = getParentObject();
+ GraphContext graphContext = new GraphContext(inputGraph, new AtomicInteger(0), new HashSet<>(), new AtomicBoolean(false));
+ if (contextAction != null) {
+ contexts.add(graphContext);
}
- ParseMonitor monitor = getMonitor();
- if (monitor != null) {
- monitor.updateProgress();
- }
- return curGraph;
+ return graphContext;
}
+ };
+ private final ElementHandler visibleNodesHandler = new ElementHandler<>(VISIBLE_NODES_ELEMENT) {
@Override
- protected void end(String text) throws SAXException {
- // NOTE: Some graphs intentionally don't provide blocks. Instead
- // they later generate the blocks from other information such
- // as node properties (example: ServerCompilerScheduler).
- // Thus, we shouldn't assign nodes that don't belong to any
- // block to some artificial block below unless blocks are
- // defined and nodes are assigned to them.
-
- final InputGraph graph = getObject();
- final Group parent = getParentObject();
- if (graph.getBlocks().size() > 0) {
- boolean blocksContainNodes = false;
- for (InputBlock b : graph.getBlocks()) {
- if (b.getNodes().size() > 0) {
- blocksContainNodes = true;
- break;
- }
- }
-
- if (!blocksContainNodes) {
- graph.clearBlocks();
- blockConnections.clear();
- } else {
- // Blocks and their nodes defined: add other nodes to an
- // artificial "no block" block
- InputBlock noBlock = null;
- for (InputNode n : graph.getNodes()) {
- if (graph.getBlock(n) == null) {
- if (noBlock == null) {
- noBlock = graph.addArtificialBlock();
- }
-
- noBlock.addNode(n.getId());
- }
-
- assert graph.getBlock(n) != null;
- }
- }
+ protected GraphContext start() throws SAXException {
+ String s = readRequiredAttribute(ALL_PROPERTY);
+ try {
+ boolean all = Boolean.parseBoolean(s);
+ getParentObject().showAll().set(all);
+ } catch (NumberFormatException e) {
+ throw new SAXException(e);
}
+ return getParentObject();
+ }
+ };
+ private final ElementHandler visibleNodeHandler = new ElementHandler<>(NODE_ELEMENT) {
- // Resolve block successors
- for (Pair p : blockConnections) {
- final InputBlock left = graph.getBlock(p.getLeft());
- assert left != null;
- final InputBlock right = graph.getBlock(p.getRight());
- assert right != null;
- graph.addBlockEdge(left, right);
+ @Override
+ protected GraphContext start() throws SAXException {
+ String s = readRequiredAttribute(NODE_ID_PROPERTY);
+ int nodeID;
+ try {
+ nodeID = Integer.parseInt(s);
+ } catch (NumberFormatException e) {
+ throw new SAXException(e);
}
- blockConnections.clear();
+ getParentObject().visibleNodes().add(nodeID);
+ return getParentObject();
+ }
+ };
+ private final ElementHandler differenceHandler = new ElementHandler<>(STATE_POSITION_DIFFERENCE) {
- Runnable addToParent = () -> parent.addElement(graph);
- if (invokeLater) {
- SwingUtilities.invokeLater(addToParent);
- } else {
- addToParent.run();
+ @Override
+ protected GraphContext start() throws SAXException {
+ String s = readRequiredAttribute(POSITION_DIFFERENCE_PROPERTY);
+ int posDiff;
+ try {
+ posDiff = Integer.parseInt(s);
+ } catch (NumberFormatException e) {
+ throw new SAXException(e);
}
+ getParentObject().posDiff().set(posDiff);
+ return getParentObject();
}
};
- //
- private HandoverElementHandler nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
- //
- private HandoverElementHandler controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT);
//
- private ElementHandler blockHandler = new ElementHandler(BLOCK_ELEMENT) {
+ private final ElementHandler blockHandler = new ElementHandler<>(BLOCK_ELEMENT) {
@Override
protected InputBlock start() throws SAXException {
@@ -305,15 +209,64 @@ protected InputBlock start() throws SAXException {
}
};
//
- private HandoverElementHandler blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
+ private final HandoverElementHandler blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
+ //
+ private final HandoverElementHandler successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT);
+ //
+ private final ElementHandler successorHandler = new ElementHandler<>(SUCCESSOR_ELEMENT) {
+
+ @Override
+ protected InputBlock start() throws SAXException {
+ String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
+ blockConnections.add(new Pair<>(getParentObject().getName(), name));
+ return getParentObject();
+ }
+ };
+ //
+ private final HandoverElementHandler edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT);
+ //
+ private final EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) {
+
+ @Override
+ protected InputEdge start(InputEdge conn) {
+ InputGraph inputGraph = getParentObject();
+ inputGraph.addEdge(conn);
+ return conn;
+ }
+ };
+ //
+ private final EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) {
+
+ @Override
+ protected InputEdge start(InputEdge conn) {
+ getParentObject().removeEdge(conn);
+ return conn;
+ }
+ };
+ //
+ private final HandoverElementHandler propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT);
+ //
+ private final ElementHandler propertyHandler = new XMLParser.ElementHandler<>(PROPERTY_ELEMENT, true) {
+
+ @Override
+ public String start() throws SAXException {
+ return readRequiredAttribute(PROPERTY_NAME_PROPERTY);
+ }
+
+ @Override
+ public void end(String text) {
+ getParentObject().getProperties().setProperty(getObject(), text.trim());
+ }
+ };
+ private int maxId = 0;
//
- private ElementHandler blockNodeHandler = new ElementHandler(NODE_ELEMENT) {
+ private final ElementHandler blockNodeHandler = new ElementHandler<>(NODE_ELEMENT) {
@Override
protected InputBlock start() throws SAXException {
String s = readRequiredAttribute(NODE_ID_PROPERTY);
- int id = 0;
+ int id;
try {
id = lookupID(s);
} catch (NumberFormatException e) {
@@ -323,25 +276,13 @@ protected InputBlock start() throws SAXException {
return getParentObject();
}
};
- //
- private HandoverElementHandler successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT);
- //
- private ElementHandler successorHandler = new ElementHandler(SUCCESSOR_ELEMENT) {
-
- @Override
- protected InputBlock start() throws SAXException {
- String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
- blockConnections.add(new Pair<>(getParentObject().getName(), name));
- return getParentObject();
- }
- };
//
- private ElementHandler nodeHandler = new ElementHandler(NODE_ELEMENT) {
+ private final ElementHandler nodeHandler = new ElementHandler<>(NODE_ELEMENT) {
@Override
protected InputNode start() throws SAXException {
String s = readRequiredAttribute(NODE_ID_PROPERTY);
- int id = 0;
+ int id;
try {
id = lookupID(s);
} catch (NumberFormatException e) {
@@ -353,12 +294,12 @@ protected InputNode start() throws SAXException {
}
};
//
- private ElementHandler removeNodeHandler = new ElementHandler(REMOVE_NODE_ELEMENT) {
+ private final ElementHandler removeNodeHandler = new ElementHandler<>(REMOVE_NODE_ELEMENT) {
@Override
protected InputNode start() throws SAXException {
String s = readRequiredAttribute(NODE_ID_PROPERTY);
- int id = 0;
+ int id;
try {
id = lookupID(s);
} catch (NumberFormatException e) {
@@ -367,118 +308,164 @@ protected InputNode start() throws SAXException {
return getParentObject().removeNode(id);
}
};
- //
- private HandoverElementHandler edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT);
-
- // Local class for edge elements
- private class EdgeElementHandler extends ElementHandler {
+ private GraphDocument graphDocument;
+ //
+ private final ElementHandler topHandler = new ElementHandler<>(TOP_ELEMENT) {
- public EdgeElementHandler(String name) {
- super(name);
+ @Override
+ protected GraphDocument start() {
+ graphDocument = new GraphDocument();
+ return graphDocument;
}
+ };
+ //
+ private final ElementHandler groupHandler = new XMLParser.ElementHandler<>(GROUP_ELEMENT) {
@Override
- protected InputEdge start() throws SAXException {
- int fromIndex = 0;
- int toIndex = 0;
- int from = -1;
- int to = -1;
- String label = null;
- String type = null;
+ protected Group start() {
+ final Folder folder = getParentObject();
+ final Group group = new Group(folder);
- try {
- String fromIndexString = readAttribute(FROM_INDEX_PROPERTY);
- if (fromIndexString != null) {
- fromIndex = Integer.parseInt(fromIndexString);
- }
-
- String toIndexString = readAttribute(TO_INDEX_PROPERTY);
- if (toIndexString == null) {
- toIndexString = readAttribute(TO_INDEX_ALT_PROPERTY);
- }
- if (toIndexString != null) {
- toIndex = Integer.parseInt(toIndexString);
- }
-
- label = readAttribute(LABEL_PROPERTY);
- type = readAttribute(TYPE_PROPERTY);
+ String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
+ Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))));
- from = lookupID(readRequiredAttribute(FROM_PROPERTY));
- to = lookupID(readRequiredAttribute(TO_PROPERTY));
- } catch (NumberFormatException e) {
- throw new SAXException(e);
+ ParseMonitor monitor = getMonitor();
+ if (monitor != null) {
+ monitor.setState(group.getName());
}
- InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label, type == null ? "" : type);
- return start(conn);
- }
+ if (callbackDocument == null || folder instanceof Group) {
+ if (invokeLater) {
+ SwingUtilities.invokeLater(() -> folder.addElement(group));
+ } else {
+ folder.addElement(group);
+ }
+ }
- protected InputEdge start(InputEdge conn) throws SAXException {
- return conn;
+ return group;
}
- }
- //
- private EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) {
@Override
- protected InputEdge start(InputEdge conn) throws SAXException {
- getParentObject().addEdge(conn);
- return conn;
+ protected void end(String text) {
}
};
- //
- private EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) {
+ //
+ private final ElementHandler graphHandler = new XMLParser.ElementHandler<>(GRAPH_ELEMENT) {
@Override
- protected InputEdge start(InputEdge conn) throws SAXException {
- getParentObject().removeEdge(conn);
- return conn;
+ protected InputGraph start() {
+ Group group = getParentObject();
+ String name = readAttribute(GRAPH_NAME_PROPERTY);
+ InputGraph curGraph = new InputGraph(name);
+ if (differenceEncoding.get(group)) {
+ InputGraph previous = lastParsedGraph.get(group);
+ lastParsedGraph.put(group, curGraph);
+ if (previous != null) {
+ for (InputNode n : previous.getNodes()) {
+ curGraph.addNode(n);
+ }
+ for (InputEdge e : previous.getEdges()) {
+ curGraph.addEdge(e);
+ }
+ }
+ }
+ ParseMonitor monitor = getMonitor();
+ if (monitor != null) {
+ monitor.updateProgress();
+ }
+ return curGraph;
}
- };
- //
- private HandoverElementHandler propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT);
- //
- private HandoverElementHandler groupPropertiesHandler = new HandoverElementHandler(PROPERTIES_ELEMENT) {
@Override
- public void end(String text) throws SAXException {
- if (groupCallback != null && getParentObject().getParent() instanceof GraphDocument) {
- final Group group = getParentObject();
- Runnable addStarted = () -> groupCallback.started(group);
- if (invokeLater) {
- SwingUtilities.invokeLater(addStarted);
+ protected void end(String text) {
+ // NOTE: Some graphs intentionally don't provide blocks. Instead,
+ // they later generate the blocks from other information such
+ // as node properties (example: ServerCompilerScheduler).
+ // Thus, we shouldn't assign nodes that don't belong to any
+ // block to some artificial block below unless blocks are
+ // defined and nodes are assigned to them.
+
+ final InputGraph graph = getObject();
+
+ final Group parent = getParentObject();
+ if (!graph.getBlocks().isEmpty()) {
+ boolean blocksContainNodes = false;
+ for (InputBlock b : graph.getBlocks()) {
+ if (!b.getNodes().isEmpty()) {
+ blocksContainNodes = true;
+ break;
+ }
+ }
+
+ if (!blocksContainNodes) {
+ graph.clearBlocks();
+ blockConnections.clear();
} else {
- addStarted.run();
+ // Blocks and their nodes defined: add other nodes to an
+ // artificial "no block" block
+ InputBlock noBlock = null;
+ for (InputNode n : graph.getNodes()) {
+ if (graph.getBlock(n) == null) {
+ if (noBlock == null) {
+ noBlock = graph.addArtificialBlock();
+ }
+
+ noBlock.addNode(n.getId());
+ }
+
+ assert graph.getBlock(n) != null;
+ }
}
}
+
+ // Resolve block successors
+ for (Pair p : blockConnections) {
+ final InputBlock left = graph.getBlock(p.getLeft());
+ assert left != null;
+ final InputBlock right = graph.getBlock(p.getRight());
+ assert right != null;
+ graph.addBlockEdge(left, right);
+ }
+ blockConnections.clear();
+
+ if (invokeLater) {
+ SwingUtilities.invokeLater(() -> parent.addElement(graph));
+ } else {
+ parent.addElement(graph);
+ }
+ if (contextAction != null) {
+ for (GraphContext ctx : contexts) {
+ contextAction.performAction(ctx);
+ }
+ }
+ contexts.clear();
}
};
- //
- private ElementHandler propertyHandler = new XMLParser.ElementHandler(PROPERTY_ELEMENT, true) {
-
- @Override
- public String start() throws SAXException {
- return readRequiredAttribute(PROPERTY_NAME_PROPERTY);
- }
+ //
+ private final HandoverElementHandler groupPropertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT) {
@Override
public void end(String text) {
- getParentObject().getProperties().setProperty(getObject(), text.trim());
+ final Group group = getParentObject();
+ if (callbackDocument != null && group.getParent() instanceof GraphDocument) {
+ group.setParent(callbackDocument);
+ if (invokeLater) {
+ SwingUtilities.invokeLater(() -> callbackDocument.addElement(group));
+ } else {
+ callbackDocument.addElement(group);
+ }
+ }
}
};
- public Parser(ReadableByteChannel channel) {
- this(channel, null, null);
- }
-
- public Parser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback groupCallback) {
-
- this.groupCallback = groupCallback;
+ public Parser(ReadableByteChannel channel, ParseMonitor monitor, GraphDocument callbackDocument, GraphContextAction contextAction) {
+ this.callbackDocument = callbackDocument;
+ this.contextAction = contextAction;
this.monitor = monitor;
this.channel = channel;
// Initialize dependencies
- xmlDocument.addChild(topHandler);
+ xmlData.addChild(topHandler);
topHandler.addChild(groupHandler);
groupHandler.addChild(methodHandler);
@@ -495,9 +482,15 @@ public Parser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback g
graphHandler.addChild(nodesHandler);
graphHandler.addChild(edgesHandler);
graphHandler.addChild(controlFlowHandler);
+ graphHandler.addChild(graphStatesHandler);
controlFlowHandler.addChild(blockHandler);
+ graphStatesHandler.addChild(stateHandler);
+ stateHandler.addChild(differenceHandler);
+ stateHandler.addChild(visibleNodesHandler);
+ visibleNodesHandler.addChild(visibleNodeHandler);
+
blockHandler.addChild(successorsHandler);
successorsHandler.addChild(successorHandler);
blockHandler.addChild(blockNodesHandler);
@@ -518,6 +511,31 @@ public Parser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback g
groupPropertiesHandler.addChild(propertyHandler);
}
+ private int lookupID(String i) {
+ try {
+ return Integer.parseInt(i);
+ } catch (NumberFormatException nfe) {
+ // ignore
+ }
+ Integer id = idCache.get(i);
+ if (id == null) {
+ id = maxId++;
+ idCache.put(i, id);
+ }
+ return id;
+ }
+
+ private InputMethod parseMethod(XMLParser.ElementHandler, ?> handler, Group group) throws SAXException {
+ String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY);
+ int bci;
+ try {
+ bci = Integer.parseInt(s);
+ } catch (NumberFormatException e) {
+ throw new SAXException(e);
+ }
+ return new InputMethod(group, handler.readRequiredAttribute(METHOD_NAME_PROPERTY), handler.readRequiredAttribute(METHOD_SHORT_NAME_PROPERTY), bci);
+ }
+
// Returns a new GraphDocument object deserialized from an XML input source.
@Override
public GraphDocument parse() throws IOException {
@@ -528,7 +546,7 @@ public GraphDocument parse() throws IOException {
XMLReader reader = createReader();
// To enforce using English for non-English users, we must use Locale.ROOT rather than Locale.ENGLISH
reader.setProperty("http://apache.org/xml/properties/locale", Locale.ROOT);
- reader.setContentHandler(new XMLParser(xmlDocument, monitor));
+ reader.setContentHandler(new XMLParser(xmlData, monitor));
reader.parse(new InputSource(Channels.newInputStream(channel)));
} catch (SAXException ex) {
if (!(ex instanceof SAXParseException) || !"XML document structures must start and end within the same entity.".equals(ex.getMessage())) {
@@ -538,6 +556,7 @@ public GraphDocument parse() throws IOException {
if (monitor != null) {
monitor.setState("Finished parsing");
}
+
return graphDocument;
}
@@ -549,12 +568,60 @@ public void setInvokeLater(boolean invokeLater) {
private XMLReader createReader() throws SAXException {
try {
- SAXParserFactory pfactory = SAXParserFactory.newInstance();
- pfactory.setValidating(false);
- pfactory.setNamespaceAware(true);
- return pfactory.newSAXParser().getXMLReader();
+ SAXParserFactory pFactory = SAXParserFactory.newInstance();
+ pFactory.setValidating(false);
+ pFactory.setNamespaceAware(true);
+ return pFactory.newSAXParser().getXMLReader();
} catch (ParserConfigurationException ex) {
throw new SAXException(ex);
}
}
+
+ // Local class for edge elements
+ private class EdgeElementHandler extends ElementHandler {
+
+ public EdgeElementHandler(String name) {
+ super(name);
+ }
+
+ @Override
+ protected InputEdge start() throws SAXException {
+ int fromIndex = 0;
+ int toIndex = 0;
+ int from;
+ int to;
+ String label;
+ String type;
+
+ try {
+ String fromIndexString = readAttribute(FROM_INDEX_PROPERTY);
+ if (fromIndexString != null) {
+ fromIndex = Integer.parseInt(fromIndexString);
+ }
+
+ String toIndexString = readAttribute(TO_INDEX_PROPERTY);
+ if (toIndexString == null) {
+ toIndexString = readAttribute(TO_INDEX_ALT_PROPERTY);
+ }
+ if (toIndexString != null) {
+ toIndex = Integer.parseInt(toIndexString);
+ }
+
+ label = readAttribute(LABEL_PROPERTY);
+ type = readAttribute(TYPE_PROPERTY);
+
+ from = lookupID(readRequiredAttribute(FROM_PROPERTY));
+ to = lookupID(readRequiredAttribute(TO_PROPERTY));
+ } catch (NumberFormatException e) {
+ throw new SAXException(e);
+ }
+
+ InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label, type == null ? "" : type);
+ return start(conn);
+ }
+
+ protected InputEdge start(InputEdge conn) {
+ return conn;
+ }
+ }
}
diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Printer.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Printer.java
index eb3f145170324..f930e47877635 100644
--- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Printer.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Printer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -25,10 +25,13 @@
import com.sun.hotspot.igv.data.*;
import java.io.IOException;
-import java.io.InputStream;
import java.io.Writer;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
/**
*
@@ -36,76 +39,47 @@
*/
public class Printer {
- private final InputStream in;
-
- public Printer() {
- this(null);
- }
-
- public Printer(InputStream inputStream) {
- this.in = inputStream;
- }
-
- public void export(Writer writer, GraphDocument document) {
-
+ public static void exportGraphDocument(Writer writer, Folder folder, List contexts) {
XMLWriter xmlWriter = new XMLWriter(writer);
-
try {
- export(xmlWriter, document);
- } catch (IOException ignored) {}
- }
-
- private void export(XMLWriter xmlWriter, GraphDocument document) throws IOException {
- xmlWriter.startTag(Parser.ROOT_ELEMENT);
- xmlWriter.writeProperties(document.getProperties());
- for (FolderElement e : document.getElements()) {
- if (e instanceof Group) {
- export(xmlWriter, (Group) e);
- } else if (e instanceof InputGraph) {
- export(xmlWriter, (InputGraph)e, null, false);
+ xmlWriter.startTag(Parser.ROOT_ELEMENT);
+ xmlWriter.writeProperties(folder.getProperties());
+ for (FolderElement e : folder.getElements()) {
+ if (e instanceof Group group) {
+ exportGroup(xmlWriter, group, contexts);
+ } else if (e instanceof InputGraph graph) {
+ exportInputGraph(xmlWriter, graph, null, false, contexts);
+ }
}
- }
-
- xmlWriter.endTag();
- xmlWriter.flush();
+ xmlWriter.endTag();
+ xmlWriter.flush();
+ } catch (IOException ignored) {}
}
- private void export(XMLWriter writer, Group g) throws IOException {
+ private static void exportGroup(XMLWriter writer, Group g, List contexts) throws IOException {
Properties attributes = new Properties();
attributes.setProperty("difference", Boolean.toString(true));
writer.startTag(Parser.GROUP_ELEMENT, attributes);
writer.writeProperties(g.getProperties());
- boolean shouldExport = true;
- if (in != null) {
- char c = (char) in.read();
- if (c != 'y') {
- shouldExport = false;
- }
+ if (g.getMethod() != null) {
+ exportInputMethod(writer, g.getMethod());
}
- if (shouldExport) {
- if (g.getMethod() != null) {
- export(writer, g.getMethod());
- }
-
- InputGraph previous = null;
- for (FolderElement e : g.getElements()) {
- if (e instanceof InputGraph) {
- InputGraph graph = (InputGraph) e;
- export(writer, graph, previous, true);
- previous = graph;
- } else if (e instanceof Group) {
- export(writer, (Group) e);
- }
+ InputGraph previous = null;
+ for (FolderElement e : g.getElements()) {
+ if (e instanceof InputGraph graph) {
+ exportInputGraph(writer, graph, previous, true, contexts);
+ previous = graph;
+ } else if (e instanceof Group group) {
+ exportGroup(writer, group, contexts);
}
}
writer.endTag();
}
- public void export(XMLWriter writer, InputGraph graph, InputGraph previous, boolean difference) throws IOException {
-
+ private static void exportInputGraph(XMLWriter writer, InputGraph graph, InputGraph previous, boolean difference, List contexts) throws IOException {
writer.startTag(Parser.GRAPH_ELEMENT);
writer.writeProperties(graph.getProperties());
writer.startTag(Parser.NODES_ELEMENT);
@@ -135,11 +109,11 @@ public void export(XMLWriter writer, InputGraph graph, InputGraph previous, bool
if (!difference || !equal.contains(n)) {
writer.startTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId())));
writer.writeProperties(n.getProperties());
- writer.endTag();
+ writer.endTag(); // Parser.NODE_ELEMENT
}
}
- writer.endTag();
+ writer.endTag(); // Parser.NODES_ELEMENT
writer.startTag(Parser.EDGES_ELEMENT);
Set removedEdges = new HashSet<>();
@@ -169,45 +143,78 @@ public void export(XMLWriter writer, InputGraph graph, InputGraph previous, bool
}
}
- writer.endTag();
+ writer.endTag(); // Parser.EDGES_ELEMENT
writer.startTag(Parser.CONTROL_FLOW_ELEMENT);
for (InputBlock b : graph.getBlocks()) {
writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.getName()));
- if (b.getSuccessors().size() > 0) {
+ if (!b.getSuccessors().isEmpty()) {
writer.startTag(Parser.SUCCESSORS_ELEMENT);
for (InputBlock s : b.getSuccessors()) {
writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName()));
}
- writer.endTag();
+ writer.endTag(); // Parser.SUCCESSORS_ELEMENT
}
- if (b.getNodes().size() > 0) {
- writer.startTag(Parser.NODES_ELEMENT);
+ if (!b.getNodes().isEmpty()) {
+ writer.startTag(Parser.NODES_ELEMENT);
for (InputNode n : b.getNodes()) {
writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + ""));
}
- writer.endTag();
+ writer.endTag(); // Parser.NODES_ELEMENT
}
- writer.endTag();
+ writer.endTag(); // Parser.BLOCK_ELEMENT
}
- writer.endTag();
- writer.endTag();
+ writer.endTag(); // Parser.CONTROL_FLOW_ELEMENT
+
+ exportStates(writer, graph, contexts);
+
+ writer.endTag(); // Parser.GRAPH_ELEMENT
}
- private void export(XMLWriter w, InputMethod method) throws IOException {
+ private static void exportStates(XMLWriter writer, InputGraph exportingGraph, List contexts) throws IOException {
+ List contextsContainingGraph = contexts.stream()
+ .filter(context -> context.inputGraph().equals(exportingGraph))
+ .toList();
+
+ if (contextsContainingGraph.isEmpty()) {
+ return;
+ }
+
+ writer.startTag(Parser.GRAPH_STATES_ELEMENT);
+
+ for (GraphContext context : contextsContainingGraph) {
+ assert exportingGraph == context.inputGraph();
+
+ writer.startTag(Parser.STATE_ELEMENT);
+ writer.simpleTag(Parser.STATE_POSITION_DIFFERENCE,
+ new Properties(Parser.POSITION_DIFFERENCE_PROPERTY, Integer.toString(context.posDiff().get())));
+
+ writer.startTag(Parser.VISIBLE_NODES_ELEMENT, new Properties(Parser.ALL_PROPERTY, Boolean.toString(context.showAll().get())));
+ for (Integer hiddenNodeID : context.visibleNodes()) {
+ writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, hiddenNodeID.toString()));
+ }
+ writer.endTag(); // Parser.VISIBLE_NODES_ELEMENT
+
+ writer.endTag(); // Parser.STATES_ELEMENT
+ }
+
+ writer.endTag(); // Parser.GRAPH_STATE_ELEMENT
+ }
+
+ private static void exportInputMethod(XMLWriter w, InputMethod method) throws IOException {
w.startTag(Parser.METHOD_ELEMENT, new Properties(Parser.METHOD_BCI_PROPERTY, method.getBci() + "", Parser.METHOD_NAME_PROPERTY, method.getName(), Parser.METHOD_SHORT_NAME_PROPERTY, method.getShortName()));
w.writeProperties(method.getProperties());
- if (method.getInlined().size() > 0) {
+ if (!method.getInlined().isEmpty()) {
w.startTag(Parser.INLINE_ELEMENT);
for (InputMethod m : method.getInlined()) {
- export(w, m);
+ exportInputMethod(w, m);
}
w.endTag();
}
@@ -229,7 +236,7 @@ private void export(XMLWriter w, InputMethod method) throws IOException {
w.endTag();
}
- private Properties createProperties(InputEdge edge) {
+ private static Properties createProperties(InputEdge edge) {
Properties p = new Properties();
if (edge.getToIndex() != 0) {
p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex()));
@@ -242,4 +249,10 @@ private Properties createProperties(InputEdge edge) {
p.setProperty(Parser.TYPE_PROPERTY, edge.getType());
return p;
}
+
+ public record GraphContext(InputGraph inputGraph, AtomicInteger posDiff, Set visibleNodes, AtomicBoolean showAll) { }
+
+ public interface GraphContextAction {
+ void performAction(GraphContext context);
+ }
}
diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/GraphViewer.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/GraphViewer.java
index ebaa03df282ae..3cef9c4fc95a5 100644
--- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/GraphViewer.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/GraphViewer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -31,7 +31,7 @@
*/
public interface GraphViewer {
- void view(InputGraph graph, boolean newTab);
+ InputGraph view(InputGraph graph, boolean newTab);
- void viewDifference(InputGraph firstGraph, InputGraph secondGraph);
+ InputGraph viewDifference(InputGraph firstGraph, InputGraph secondGraph);
}
diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/GroupCallback.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/GroupCallback.java
deleted file mode 100644
index b35f3eabf89dd..0000000000000
--- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/GroupCallback.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 1998, 2015, 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.hotspot.igv.data.services;
-
-import com.sun.hotspot.igv.data.Group;
-
-/**
- *
- * @author Thomas Wuerthinger
- */
-public interface GroupCallback {
-
- public void started(Group g);
-}
diff --git a/src/utils/IdealGraphVisualizer/Data/src/test/java/com/sun/hotspot/igv/data/serialization/ParserTest.java b/src/utils/IdealGraphVisualizer/Data/src/test/java/com/sun/hotspot/igv/data/serialization/ParserTest.java
index 4342604644805..9788ee4443c61 100644
--- a/src/utils/IdealGraphVisualizer/Data/src/test/java/com/sun/hotspot/igv/data/serialization/ParserTest.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/test/java/com/sun/hotspot/igv/data/serialization/ParserTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2024, 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
@@ -32,6 +32,8 @@
import java.io.InputStream;
import java.nio.channels.Channels;
import static java.nio.charset.StandardCharsets.UTF_8;
+import java.util.ArrayList;
+import java.util.HashSet;
import org.junit.*;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -62,19 +64,18 @@ public void tearDown() {
}
private void test(GraphDocument document) {
- final Printer printer = new Printer();
final CharArrayWriter writer = new CharArrayWriter();
- printer.export(writer, document);
+ Printer.exportGraphDocument(writer, document, new ArrayList<>());
test(document, writer.toString());
}
private void test(GraphDocument document, String xmlString) {
InputStream in = new ByteArrayInputStream(xmlString.getBytes(UTF_8));
try {
- Parser parser = new Parser(Channels.newChannel(in));
+ Parser parser = new Parser(Channels.newChannel(in), null, null, null);
parser.setInvokeLater(false);
- final GraphDocument parsedDocument = parser.parse();
- Util.assertGraphDocumentEquals(document, parsedDocument);
+ final GraphDocument exportData = parser.parse();
+ Util.assertGraphDocumentEquals(document, exportData);
} catch (IOException ex) {
fail(ex.toString());
}
diff --git a/src/utils/IdealGraphVisualizer/NetworkConnection/src/main/java/com/sun/hotspot/igv/connection/Client.java b/src/utils/IdealGraphVisualizer/NetworkConnection/src/main/java/com/sun/hotspot/igv/connection/Client.java
deleted file mode 100644
index 2f4b6cff0dbac..0000000000000
--- a/src/utils/IdealGraphVisualizer/NetworkConnection/src/main/java/com/sun/hotspot/igv/connection/Client.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2012, 2022, 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.hotspot.igv.connection;
-
-import com.sun.hotspot.igv.data.serialization.Parser;
-import com.sun.hotspot.igv.data.services.GroupCallback;
-import java.io.IOException;
-import java.nio.channels.SocketChannel;
-import org.openide.util.Exceptions;
-
-public class Client implements Runnable {
- private final SocketChannel socket;
- private final GroupCallback callback;
-
- public Client(SocketChannel socket, GroupCallback callback) {
- this.callback = callback;
- this.socket = socket;
- }
-
- @Override
- public void run() {
-
- try {
- final SocketChannel channel = socket;
- channel.configureBlocking(true);
- channel.socket().getOutputStream().write('y');
- new Parser(channel, null, callback).parse();
- } catch (IOException ex) {
- Exceptions.printStackTrace(ex);
- } finally {
- try {
- socket.close();
- } catch (IOException ex) {
- Exceptions.printStackTrace(ex);
- }
- }
- }
-}
diff --git a/src/utils/IdealGraphVisualizer/NetworkConnection/src/main/java/com/sun/hotspot/igv/connection/Server.java b/src/utils/IdealGraphVisualizer/NetworkConnection/src/main/java/com/sun/hotspot/igv/connection/Server.java
index 523f4d2017d10..a507c568be25f 100644
--- a/src/utils/IdealGraphVisualizer/NetworkConnection/src/main/java/com/sun/hotspot/igv/connection/Server.java
+++ b/src/utils/IdealGraphVisualizer/NetworkConnection/src/main/java/com/sun/hotspot/igv/connection/Server.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024, 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
@@ -24,7 +24,9 @@
*/
package com.sun.hotspot.igv.connection;
-import com.sun.hotspot.igv.data.services.GroupCallback;
+import com.sun.hotspot.igv.data.GraphDocument;
+import com.sun.hotspot.igv.data.serialization.Parser;
+import com.sun.hotspot.igv.data.serialization.Printer.GraphContextAction;
import com.sun.hotspot.igv.settings.Settings;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -32,9 +34,6 @@
import java.nio.channels.SocketChannel;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
-import org.openide.util.RequestProcessor;
/**
*
@@ -42,13 +41,16 @@
*/
public class Server implements PreferenceChangeListener {
private ServerSocketChannel serverSocket;
- private final GroupCallback callback;
+ private final GraphDocument graphDocument;
+ private final GraphContextAction contextAction;
private int port;
- private Runnable serverRunnable;
- public Server(GroupCallback callback) {
- this.callback = callback;
- initializeNetwork();
+ private volatile boolean isServerRunning;
+
+ public Server(GraphDocument graphDocument, GraphContextAction contextAction) {
+ this.graphDocument = graphDocument;
+ this.contextAction = contextAction;
+ port = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
Settings.get().addPreferenceChangeListener(this);
}
@@ -56,46 +58,65 @@ public Server(GroupCallback callback) {
public void preferenceChange(PreferenceChangeEvent e) {
int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
if (curPort != port) {
- initializeNetwork();
+ port = curPort;
+ shutdownServer();
+ startServer();
}
}
- private void initializeNetwork() {
- int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT));
- this.port = curPort;
+ public void startServer() {
+ isServerRunning = true;
+
try {
serverSocket = ServerSocketChannel.open();
- serverSocket.bind(new InetSocketAddress(curPort));
- } catch (Throwable ex) {
- NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
- DialogDisplayer.getDefault().notifyLater(message);
+ serverSocket.bind(new InetSocketAddress(port));
+ } catch (IOException ex) {
+ ex.printStackTrace();
return;
}
- Runnable runnable = new Runnable() {
-
- @Override
- public void run() {
- while (true) {
- try {
- SocketChannel clientSocket = serverSocket.accept();
- if (serverRunnable != this) {
- clientSocket.close();
- return;
- }
- RequestProcessor.getDefault().post(new Client(clientSocket, callback), 0, Thread.MAX_PRIORITY);
- } catch (IOException ex) {
- serverSocket = null;
- NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE);
- DialogDisplayer.getDefault().notifyLater(message);
+ Runnable client = () -> {
+ while (isServerRunning) {
+ try {
+ SocketChannel clientSocket = serverSocket.accept();
+ if (!isServerRunning) {
+ clientSocket.close();
return;
}
+ new Thread(() -> {
+ try (clientSocket) {
+ clientSocket.configureBlocking(true);
+ clientSocket.socket().getOutputStream().write('y');
+ new Parser(clientSocket, null, graphDocument, contextAction).parse();
+ } catch (IOException ignored) {}
+ }).start();
+ } catch (IOException ex) {
+ if (isServerRunning) {
+ ex.printStackTrace();
+ }
+ return;
}
}
+ try {
+ if (serverSocket != null) {
+ serverSocket.close();
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
};
- serverRunnable = runnable;
+ new Thread(client).start();
+ }
- RequestProcessor.getDefault().post(runnable, 0, Thread.MAX_PRIORITY);
+ public void shutdownServer() {
+ isServerRunning = false;
+ try {
+ if (serverSocket != null) {
+ serverSocket.close();
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
}
}
diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java
index 23cd4a4360fd5..e47518de4a722 100644
--- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java
+++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java
@@ -652,7 +652,7 @@ private void centerRootNode() {
Rectangle bounds = rootWidget.getBounds();
if (bounds != null) {
Point location = rootWidget.getLocation();
- centerRectangle(new Rectangle(location.x, location.y, bounds.width, bounds.height));
+ centerRectangle(new Rectangle(location.x, location.y, bounds.width, bounds.height), false);
}
}
}
@@ -872,7 +872,7 @@ public Lookup getLookup() {
private void gotoBlock(final Block block) {
BlockWidget bw = getWidget(block.getInputBlock());
if (bw != null) {
- centerRectangle(bw.getBounds());
+ centerRectangle(bw.getBounds(), true);
}
}
@@ -919,26 +919,28 @@ public void centerSelectedFigures() {
}
}
if (overallRect != null) {
- centerRectangle(overallRect);
+ centerRectangle(overallRect, true);
}
}
- private void centerRectangle(Rectangle r) {
+ private void centerRectangle(Rectangle r, boolean zoomToFit) {
Rectangle rect = convertSceneToView(r);
Rectangle viewRect = scrollPane.getViewport().getViewRect();
-
- double factor = Math.min(viewRect.getWidth() / rect.getWidth(), viewRect.getHeight() / rect.getHeight());
- double zoomFactor = getZoomFactor();
- double newZoomFactor = zoomFactor * factor;
- if (factor < 1.0 || zoomFactor < 1.0) {
- newZoomFactor = Math.min(1.0, newZoomFactor);
- centredZoom(newZoomFactor, null);
- factor = newZoomFactor / zoomFactor;
- rect.x *= factor;
- rect.y *= factor;
- rect.width *= factor;
- rect.height *= factor;
+ if (zoomToFit) {
+ double factor = Math.min(viewRect.getWidth() / rect.getWidth(), viewRect.getHeight() / rect.getHeight());
+ double zoomFactor = getZoomFactor();
+ double newZoomFactor = zoomFactor * factor;
+ if (factor < 1.0 || zoomFactor < 1.0) {
+ newZoomFactor = Math.min(1.0, newZoomFactor);
+ centredZoom(newZoomFactor, null);
+ factor = newZoomFactor / zoomFactor;
+ rect.x *= factor;
+ rect.y *= factor;
+ rect.width *= factor;
+ rect.height *= factor;
+ }
}
+
viewRect.x = rect.x + rect.width / 2 - viewRect.width / 2;
viewRect.y = rect.y + rect.height / 2 - viewRect.height / 2;
// Ensure to be within area
diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java
index f48e05ec6b9f3..6d7599e6d3458 100644
--- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java
+++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewModel.java
@@ -332,6 +332,14 @@ public void showOnly(final Set nodes) {
final HashSet allNodes = new HashSet<>(getGroup().getAllNodes());
allNodes.removeAll(nodes);
setHiddenNodes(allNodes);
+
+
+ }
+
+ public Set getVisibleNodes() {
+ final Set visibleNodes = new HashSet<>(getGraph().getNodesAsSet());
+ visibleNodes.removeAll(hiddenNodes);
+ return visibleNodes;
}
public void setHiddenNodes(Set nodes) {
diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java
index 57d2b006ac0e9..617f59a591d4d 100644
--- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java
+++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -125,8 +125,7 @@ public EditorTopComponent(DiagramViewModel diagramViewModel) {
Group group = diagramViewModel.getGroup();
group.getChangedEvent().addListener(g -> closeOnRemovedOrEmptyGroup());
- if (group.getParent() instanceof GraphDocument) {
- final GraphDocument doc = (GraphDocument) group.getParent();
+ if (group.getParent() instanceof GraphDocument doc) {
doc.getChangedEvent().addListener(d -> closeOnRemovedOrEmptyGroup());
}
@@ -309,8 +308,7 @@ public static EditorTopComponent findEditorForGraph(InputGraph graph) {
l.add(m.getSelectedTopComponent());
l.addAll(Arrays.asList(manager.getOpenedTopComponents(m)));
for (TopComponent t : l) {
- if (t instanceof EditorTopComponent) {
- EditorTopComponent etc = (EditorTopComponent) t;
+ if (t instanceof EditorTopComponent etc) {
if (etc.getModel().getGroup().getGraphs().contains(graph)) {
return etc;
}
@@ -320,17 +318,31 @@ public static EditorTopComponent findEditorForGraph(InputGraph graph) {
return null;
}
+ public static void closeAllInstances() {
+ WindowManager manager = WindowManager.getDefault();
+ for (Mode mode : manager.getModes()) {
+ TopComponent[] openedTopComponents = manager.getOpenedTopComponents(mode);
+ for (TopComponent tc : openedTopComponents) {
+ if (tc instanceof EditorTopComponent etc) {
+ etc.close();
+ }
+ }
+ }
+ }
+
@Override
public int getPersistenceType() {
return TopComponent.PERSISTENCE_NEVER;
}
private void closeOnRemovedOrEmptyGroup() {
- Group group = getModel().getGroup();
- if (!group.getParent().getElements().contains(group) ||
- group.getGraphs().isEmpty()) {
- close();
- }
+ SwingUtilities.invokeLater(() -> {
+ Group group = getModel().getGroup();
+ if (!group.getParent().getElements().contains(group) ||
+ group.getGraphs().isEmpty()) {
+ close();
+ }
+ });
}
public void addSelectedNodes(Collection nodes, boolean showIfHidden) {
@@ -405,8 +417,7 @@ protected void componentActivated() {
WindowManager manager = WindowManager.getDefault();
for (Mode m : manager.getModes()) {
for (TopComponent topComponent : manager.getOpenedTopComponents(m)) {
- if (topComponent instanceof EditorTopComponent) {
- EditorTopComponent editor = (EditorTopComponent) topComponent;
+ if (topComponent instanceof EditorTopComponent editor) {
editor.setBoldDisplayName(false);
}
}
diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/GraphViewerImplementation.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/GraphViewerImplementation.java
index d4b88135408c9..04e63ebbc5f60 100644
--- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/GraphViewerImplementation.java
+++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/GraphViewerImplementation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2024, 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
@@ -26,8 +26,6 @@
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.GraphViewer;
import com.sun.hotspot.igv.difference.Difference;
-import com.sun.hotspot.igv.graph.Diagram;
-import com.sun.hotspot.igv.settings.Settings;
import org.openide.util.lookup.ServiceProvider;
/**
@@ -38,33 +36,37 @@
public class GraphViewerImplementation implements GraphViewer {
@Override
- public void viewDifference(InputGraph firstGraph, InputGraph secondGraph) {
+ public InputGraph viewDifference(InputGraph firstGraph, InputGraph secondGraph) {
if (firstGraph.getGroup() != secondGraph.getGroup()) {
InputGraph diffGraph = Difference.createDiffGraph(firstGraph, secondGraph);
- view(diffGraph, true);
+ return view(diffGraph, true);
} else {
- view(firstGraph, true);
- EditorTopComponent etc = EditorTopComponent.findEditorForGraph(firstGraph);
- if (etc != null) {
- etc.getModel().selectDiffGraph(secondGraph);
- etc.requestActive();
+ if (view(firstGraph, true) != null) {
+ EditorTopComponent etc = EditorTopComponent.findEditorForGraph(firstGraph);
+ if (etc != null) {
+ etc.getModel().selectDiffGraph(secondGraph);
+ etc.requestActive();
+ return etc.getModel().getGraph();
+ }
}
+ return null;
}
}
@Override
- public void view(InputGraph graph, boolean newTab) {
+ public InputGraph view(InputGraph graph, boolean newTab) {
if (!newTab) {
EditorTopComponent etc = EditorTopComponent.findEditorForGraph(graph);
if (etc != null) {
etc.getModel().selectGraph(graph);
etc.requestActive();
- return;
+ return etc.getModel().getGraph();
}
}
DiagramViewModel model = new DiagramViewModel(graph);
EditorTopComponent etc = new EditorTopComponent(model);
etc.open();
etc.requestActive();
+ return etc.getModel().getGraph();
}
}