mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-19 23:48:50 +00:00
8324950: IGV: save the state to a file
Reviewed-by: rcastanedalo, chagedorn
This commit is contained in:
parent
571e6bc3f7
commit
ec180d4782
@ -88,6 +88,11 @@
|
||||
<artifactId>org-openide-util-lookup</artifactId>
|
||||
<version>${netbeans.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-openide-modules</artifactId>
|
||||
<version>${netbeans.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.api</groupId>
|
||||
<artifactId>org-openide-util-ui</artifactId>
|
||||
|
||||
@ -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.coordinator.actions.*;
|
||||
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.ExplorerUtils;
|
||||
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,97 +73,42 @@ import org.openide.windows.WindowManager;
|
||||
*/
|
||||
public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider, ChangedListener<InputGraphProvider> {
|
||||
|
||||
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<FolderNode> 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<FolderNode> 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();
|
||||
}
|
||||
|
||||
private void initListView() {
|
||||
manager = new ExplorerManager();
|
||||
root = new FolderNode(document);
|
||||
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
|
||||
|
||||
this.add(toolbar, BorderLayout.NORTH);
|
||||
|
||||
toolbar.add(ImportAction.get(ImportAction.class));
|
||||
toolbar.add(SaveAsAction.get(SaveAsAction.class).createContextAwareInstance(this.getLookup()));
|
||||
|
||||
saveAllAction = SaveAllAction.get(SaveAllAction.class);
|
||||
saveAllAction.setEnabled(false);
|
||||
toolbar.add(saveAllAction);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
document.getChangedEvent().addListener(g -> documentChanged());
|
||||
}
|
||||
|
||||
private void documentChanged() {
|
||||
boolean enableButton = !document.getElements().isEmpty();
|
||||
saveAllAction.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() {
|
||||
public static GraphDocument getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
@ -159,7 +117,7 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
|
||||
* 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() {
|
||||
private static synchronized OutlineTopComponent getDefault() {
|
||||
if (instance == null) {
|
||||
instance = new OutlineTopComponent();
|
||||
}
|
||||
@ -182,6 +140,97 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
|
||||
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<GraphContext> saveContexts = new ArrayList<>();
|
||||
WindowManager manager = WindowManager.getDefault();
|
||||
for (Mode mode : manager.getModes()) {
|
||||
List<TopComponent> 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<Integer> visibleNodes = new HashSet<>(etc.getModel().getVisibleNodes());
|
||||
return new GraphContext(openedGraph, new AtomicInteger(posDiff), visibleNodes, new AtomicBoolean(false));
|
||||
}
|
||||
}
|
||||
|
||||
private void initListView() {
|
||||
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
|
||||
|
||||
this.add(toolbar, BorderLayout.NORTH);
|
||||
|
||||
toolbar.add(OpenAction.get(OpenAction.class));
|
||||
toolbar.add(ImportAction.get(ImportAction.class));
|
||||
toolbar.addSeparator();
|
||||
|
||||
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);
|
||||
|
||||
for (Toolbar tb : ToolbarPool.getDefault().getToolbars()) {
|
||||
tb.setVisible(false);
|
||||
}
|
||||
|
||||
document.getChangedEvent().addListener(g -> documentChanged());
|
||||
}
|
||||
|
||||
private void documentChanged() {
|
||||
boolean enableButton = !document.getElements().isEmpty();
|
||||
saveAction.setEnabled(enableButton);
|
||||
saveAsAction.setEnabled(enableButton);
|
||||
removeAllAction.setEnabled(enableButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExplorerManager getExplorerManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPersistenceType() {
|
||||
return TopComponent.PERSISTENCE_ALWAYS;
|
||||
@ -236,15 +285,12 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
|
||||
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 final class OutlineTopComponent extends TopComponent implements ExplorerM
|
||||
}
|
||||
|
||||
@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("<html><b>" + documentPath.getFileName().toString() + "</b></html>");
|
||||
setToolTipText("File: " + path);
|
||||
} else {
|
||||
documentPath = null;
|
||||
setHtmlDisplayName("<html><i>untitled</i></html>");
|
||||
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<Integer> 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<GraphContext> 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
|
||||
|
||||
@ -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 @@ import org.openide.util.actions.CallableSystemAction;
|
||||
*/
|
||||
|
||||
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 final class ImportAction extends CallableSystemAction {
|
||||
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;
|
||||
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
@ -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 com.sun.hotspot.igv.coordinator.FolderNode;
|
||||
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 @@ import org.openide.util.actions.NodeAction;
|
||||
*/
|
||||
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 @@ public final class RemoveAction extends NodeAction {
|
||||
}
|
||||
}
|
||||
|
||||
public RemoveAction() {
|
||||
putValue(Action.SHORT_DESCRIPTION, getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NbBundle.getMessage(RemoveAction.class, "CTL_RemoveAction");
|
||||
|
||||
@ -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 @@ 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.actions.CallableSystemAction;
|
||||
|
||||
@ -42,7 +43,8 @@ public final class RemoveAllAction extends CallableSystemAction {
|
||||
}
|
||||
|
||||
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 @@ public final class RemoveAllAction extends CallableSystemAction {
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
OutlineTopComponent.findInstance().clear();
|
||||
OutlineTopComponent.findInstance().clearWorkspace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 @@ 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @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
|
||||
@ -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 final class SaveAsAction extends NodeAction {
|
||||
|
||||
@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 final class SaveAsAction extends NodeAction {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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...
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 634 B After Width: | Height: | Size: 634 B |
@ -26,8 +26,9 @@
|
||||
</folder>
|
||||
<folder name="Actions">
|
||||
<folder name="File">
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-OpenAction.instance"/>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-SaveAction.instance"/>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance"/>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-SaveAllAction.instance"/>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-ImportAction.instance"/>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-RemoveAction.instance"/>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-RemoveAllAction.instance"/>
|
||||
@ -55,6 +56,10 @@
|
||||
<file name="Separator2.instance_hidden"/>
|
||||
<file name="Separator3.instance_hidden"/>
|
||||
<file name="SeparatorOpen.instance_hidden"/>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-OpenAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-OpenAction.instance"/>
|
||||
<attr name="position" intvalue="50"/>
|
||||
</file>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-ImportAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-ImportAction.instance"/>
|
||||
<attr name="position" intvalue="100"/>
|
||||
@ -71,13 +76,13 @@
|
||||
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
|
||||
<attr name="position" intvalue="400"/>
|
||||
</file>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-SaveAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-SaveAction.instance"/>
|
||||
<attr name="position" intvalue="600"/>
|
||||
</file>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-SaveAsAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-SaveAsAction.instance"/>
|
||||
<attr name="position" intvalue="500"/>
|
||||
</file>
|
||||
<file name="com-sun-hotspot-igv-coordinator-actions-SaveAllAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/File/com-sun-hotspot-igv-coordinator-actions-SaveAllAction.instance"/>
|
||||
<attr name="position" intvalue="600"/>
|
||||
<attr name="position" intvalue="650"/>
|
||||
</file>
|
||||
<file name="SeparatorRemove.instance">
|
||||
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
|
||||
@ -105,8 +110,8 @@
|
||||
<file name="org-netbeans-modules-project-ui-RecentProjects.shadow_hidden"/>
|
||||
<file name="org-netbeans-modules-project-ui-groups-GroupsMenu.shadow_hidden"/>
|
||||
<file name="org-openide-actions-SaveAction.shadow_hidden"/>
|
||||
<file name="org-openide-actions-SaveAllAction.shadow_hidden"/>
|
||||
<file name="org-openide-actions-SaveAsAction.shadow_hidden"/>
|
||||
<file name="org-openide-actions-SaveAllAction.shadow_hidden"/>
|
||||
</folder>
|
||||
|
||||
<folder name="Edit">
|
||||
|
||||
@ -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 @@ package com.sun.hotspot.igv.data;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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 class GraphDocument extends Properties.Entity implements ChangedEventProv
|
||||
|
||||
public void addGraphDocument(GraphDocument document) {
|
||||
if (document != this) {
|
||||
for (FolderElement e : document.elements) {
|
||||
for (FolderElement e : document.getElements()) {
|
||||
e.setParent(this);
|
||||
this.addElement(e);
|
||||
}
|
||||
|
||||
@ -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 class Group extends Properties.Entity implements ChangedEventProvider<Gro
|
||||
|
||||
@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");
|
||||
}
|
||||
|
||||
@ -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 @@ import org.xml.sax.XMLReader;
|
||||
*/
|
||||
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,49 +89,242 @@ 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<GraphDocument> xmlDocument = new TopElementHandler<>();
|
||||
private final TopElementHandler<GraphDocument> xmlData = new TopElementHandler<>();
|
||||
private final Map<Group, Boolean> differenceEncoding = new HashMap<>();
|
||||
private final Map<Group, InputGraph> lastParsedGraph = new HashMap<>();
|
||||
private final GroupCallback groupCallback;
|
||||
private final GraphDocument callbackDocument;
|
||||
private final GraphContextAction contextAction;
|
||||
private final ArrayList<GraphContext> contexts = new ArrayList<>();
|
||||
private final HashMap<String, Integer> idCache = new HashMap<>();
|
||||
private final ArrayList<Pair<String, String>> 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;
|
||||
}
|
||||
|
||||
// <graphDocument>
|
||||
private ElementHandler<GraphDocument, Object> topHandler = new ElementHandler<GraphDocument, Object>(TOP_ELEMENT) {
|
||||
// <method>
|
||||
private final ElementHandler<InputMethod, Group> methodHandler = new XMLParser.ElementHandler<>(METHOD_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected GraphDocument start() throws SAXException {
|
||||
protected InputMethod start() throws SAXException {
|
||||
Group group = getParentObject();
|
||||
InputMethod method = parseMethod(this, group);
|
||||
group.setMethod(method);
|
||||
return method;
|
||||
}
|
||||
};
|
||||
// <bytecodes>
|
||||
private final HandoverElementHandler<InputMethod> bytecodesHandler = new XMLParser.HandoverElementHandler<>(BYTECODES_ELEMENT, true) {
|
||||
|
||||
@Override
|
||||
protected void end(String text) {
|
||||
getParentObject().setBytecodes(text);
|
||||
}
|
||||
};
|
||||
// <inlined>
|
||||
private final HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT);
|
||||
// <inlined><method>
|
||||
private final ElementHandler<InputMethod, InputMethod> inlinedMethodHandler = new XMLParser.ElementHandler<>(METHOD_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputMethod start() throws SAXException {
|
||||
InputMethod method = parseMethod(this, getParentObject().getGroup());
|
||||
getParentObject().addInlined(method);
|
||||
return method;
|
||||
}
|
||||
};
|
||||
// <nodes>
|
||||
private final HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
|
||||
// <controlFlow>
|
||||
private final HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT);
|
||||
private final HandoverElementHandler<InputGraph> graphStatesHandler = new HandoverElementHandler<>(GRAPH_STATES_ELEMENT);
|
||||
private final ElementHandler<GraphContext, InputGraph> stateHandler = new ElementHandler<>(STATE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
return graphContext;
|
||||
}
|
||||
};
|
||||
private final ElementHandler<GraphContext, GraphContext> visibleNodesHandler = new ElementHandler<>(VISIBLE_NODES_ELEMENT) {
|
||||
|
||||
@Override
|
||||
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<GraphContext, GraphContext> visibleNodeHandler = new ElementHandler<>(NODE_ELEMENT) {
|
||||
|
||||
@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);
|
||||
}
|
||||
getParentObject().visibleNodes().add(nodeID);
|
||||
return getParentObject();
|
||||
}
|
||||
};
|
||||
private final ElementHandler<GraphContext, GraphContext> differenceHandler = new ElementHandler<>(STATE_POSITION_DIFFERENCE) {
|
||||
|
||||
@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();
|
||||
}
|
||||
};
|
||||
// <block>
|
||||
private final ElementHandler<InputBlock, InputGraph> blockHandler = new ElementHandler<>(BLOCK_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputBlock start() throws SAXException {
|
||||
InputGraph graph = getParentObject();
|
||||
String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
|
||||
InputBlock b = graph.addBlock(name);
|
||||
for (InputNode n : b.getNodes()) {
|
||||
assert graph.getBlock(n).equals(b);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
};
|
||||
// <nodes>
|
||||
private final HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
|
||||
// <successors>
|
||||
private final HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT);
|
||||
// <successor>
|
||||
private final ElementHandler<InputBlock, InputBlock> 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();
|
||||
}
|
||||
};
|
||||
// <graph>
|
||||
private final HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT);
|
||||
// <edge>
|
||||
private final EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputEdge start(InputEdge conn) {
|
||||
InputGraph inputGraph = getParentObject();
|
||||
inputGraph.addEdge(conn);
|
||||
return conn;
|
||||
}
|
||||
};
|
||||
// <removeEdge>
|
||||
private final EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputEdge start(InputEdge conn) {
|
||||
getParentObject().removeEdge(conn);
|
||||
return conn;
|
||||
}
|
||||
};
|
||||
// <properties>
|
||||
private final HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT);
|
||||
// <property>
|
||||
private final ElementHandler<String, Properties.Provider> 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;
|
||||
// <node>
|
||||
private final ElementHandler<InputBlock, InputBlock> blockNodeHandler = new ElementHandler<>(NODE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputBlock start() throws SAXException {
|
||||
String s = readRequiredAttribute(NODE_ID_PROPERTY);
|
||||
|
||||
int id;
|
||||
try {
|
||||
id = lookupID(s);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
getParentObject().addNode(id);
|
||||
return getParentObject();
|
||||
}
|
||||
};
|
||||
// <node>
|
||||
private final ElementHandler<InputNode, InputGraph> nodeHandler = new ElementHandler<>(NODE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputNode start() throws SAXException {
|
||||
String s = readRequiredAttribute(NODE_ID_PROPERTY);
|
||||
int id;
|
||||
try {
|
||||
id = lookupID(s);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
InputNode node = new InputNode(id);
|
||||
getParentObject().addNode(node);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
// <removeNode>
|
||||
private final ElementHandler<InputNode, InputGraph> removeNodeHandler = new ElementHandler<>(REMOVE_NODE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputNode start() throws SAXException {
|
||||
String s = readRequiredAttribute(NODE_ID_PROPERTY);
|
||||
int id;
|
||||
try {
|
||||
id = lookupID(s);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
return getParentObject().removeNode(id);
|
||||
}
|
||||
};
|
||||
private GraphDocument graphDocument;
|
||||
// <graphDocument>
|
||||
private final ElementHandler<GraphDocument, Object> topHandler = new ElementHandler<>(TOP_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected GraphDocument start() {
|
||||
graphDocument = new GraphDocument();
|
||||
return graphDocument;
|
||||
}
|
||||
};
|
||||
// <group>
|
||||
private ElementHandler<Group, Folder> groupHandler = new XMLParser.ElementHandler<Group, Folder>(GROUP_ELEMENT) {
|
||||
private final ElementHandler<Group, Folder> groupHandler = new XMLParser.ElementHandler<>(GROUP_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected Group start() throws SAXException {
|
||||
final Group group = new Group(this.getParentObject());
|
||||
protected Group start() {
|
||||
final Folder folder = getParentObject();
|
||||
final Group group = new Group(folder);
|
||||
|
||||
String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
|
||||
Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))));
|
||||
@ -141,13 +334,11 @@ public class Parser implements GraphParser {
|
||||
monitor.setState(group.getName());
|
||||
}
|
||||
|
||||
final Folder parent = getParentObject();
|
||||
if (groupCallback == null || parent instanceof Group) {
|
||||
Runnable addToParent = () -> parent.addElement(group);
|
||||
if (callbackDocument == null || folder instanceof Group) {
|
||||
if (invokeLater) {
|
||||
SwingUtilities.invokeLater(addToParent);
|
||||
SwingUtilities.invokeLater(() -> folder.addElement(group));
|
||||
} else {
|
||||
addToParent.run();
|
||||
folder.addElement(group);
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,62 +346,20 @@ public class Parser implements GraphParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void end(String text) throws SAXException {
|
||||
}
|
||||
};
|
||||
// <method>
|
||||
private ElementHandler<InputMethod, Group> methodHandler = new XMLParser.ElementHandler<InputMethod, Group>(METHOD_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputMethod start() throws SAXException {
|
||||
|
||||
InputMethod method = parseMethod(this, getParentObject());
|
||||
getParentObject().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;
|
||||
}
|
||||
// <bytecodes>
|
||||
private HandoverElementHandler<InputMethod> bytecodesHandler = new XMLParser.HandoverElementHandler<InputMethod>(BYTECODES_ELEMENT, true) {
|
||||
|
||||
@Override
|
||||
protected void end(String text) throws SAXException {
|
||||
getParentObject().setBytecodes(text);
|
||||
}
|
||||
};
|
||||
// <inlined>
|
||||
private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT);
|
||||
// <inlined><method>
|
||||
private ElementHandler<InputMethod, InputMethod> inlinedMethodHandler = new XMLParser.ElementHandler<InputMethod, InputMethod>(METHOD_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputMethod start() throws SAXException {
|
||||
InputMethod method = parseMethod(this, getParentObject().getGroup());
|
||||
getParentObject().addInlined(method);
|
||||
return method;
|
||||
protected void end(String text) {
|
||||
}
|
||||
};
|
||||
// <graph>
|
||||
private ElementHandler<InputGraph, Group> graphHandler = new XMLParser.ElementHandler<InputGraph, Group>(GRAPH_ELEMENT) {
|
||||
private final ElementHandler<InputGraph, Group> graphHandler = new XMLParser.ElementHandler<>(GRAPH_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputGraph start() throws SAXException {
|
||||
protected InputGraph start() {
|
||||
Group group = getParentObject();
|
||||
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 (differenceEncoding.get(group)) {
|
||||
InputGraph previous = lastParsedGraph.get(group);
|
||||
lastParsedGraph.put(group, curGraph);
|
||||
if (previous != null) {
|
||||
for (InputNode n : previous.getNodes()) {
|
||||
curGraph.addNode(n);
|
||||
@ -228,8 +377,8 @@ public class Parser implements GraphParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void end(String text) throws SAXException {
|
||||
// NOTE: Some graphs intentionally don't provide blocks. Instead
|
||||
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
|
||||
@ -237,11 +386,12 @@ public class Parser implements GraphParser {
|
||||
// defined and nodes are assigned to them.
|
||||
|
||||
final InputGraph graph = getObject();
|
||||
|
||||
final Group parent = getParentObject();
|
||||
if (graph.getBlocks().size() > 0) {
|
||||
if (!graph.getBlocks().isEmpty()) {
|
||||
boolean blocksContainNodes = false;
|
||||
for (InputBlock b : graph.getBlocks()) {
|
||||
if (b.getNodes().size() > 0) {
|
||||
if (!b.getNodes().isEmpty()) {
|
||||
blocksContainNodes = true;
|
||||
break;
|
||||
}
|
||||
@ -252,7 +402,7 @@ public class Parser implements GraphParser {
|
||||
blockConnections.clear();
|
||||
} else {
|
||||
// Blocks and their nodes defined: add other nodes to an
|
||||
// artificial "no block" block
|
||||
// artificial "no block" block
|
||||
InputBlock noBlock = null;
|
||||
for (InputNode n : graph.getNodes()) {
|
||||
if (graph.getBlock(n) == null) {
|
||||
@ -278,97 +428,154 @@ public class Parser implements GraphParser {
|
||||
}
|
||||
blockConnections.clear();
|
||||
|
||||
Runnable addToParent = () -> parent.addElement(graph);
|
||||
if (invokeLater) {
|
||||
SwingUtilities.invokeLater(addToParent);
|
||||
SwingUtilities.invokeLater(() -> parent.addElement(graph));
|
||||
} else {
|
||||
addToParent.run();
|
||||
parent.addElement(graph);
|
||||
}
|
||||
if (contextAction != null) {
|
||||
for (GraphContext ctx : contexts) {
|
||||
contextAction.performAction(ctx);
|
||||
}
|
||||
}
|
||||
contexts.clear();
|
||||
}
|
||||
};
|
||||
// <properties>
|
||||
private final HandoverElementHandler<Group> groupPropertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT) {
|
||||
|
||||
@Override
|
||||
public void end(String text) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// <nodes>
|
||||
private HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
|
||||
// <controlFlow>
|
||||
private HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT);
|
||||
// <block>
|
||||
private ElementHandler<InputBlock, InputGraph> blockHandler = new ElementHandler<InputBlock, InputGraph>(BLOCK_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputBlock start() throws SAXException {
|
||||
InputGraph graph = getParentObject();
|
||||
String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
|
||||
InputBlock b = graph.addBlock(name);
|
||||
for (InputNode n : b.getNodes()) {
|
||||
assert graph.getBlock(n).equals(b);
|
||||
public Parser(ReadableByteChannel channel, ParseMonitor monitor, GraphDocument callbackDocument, GraphContextAction contextAction) {
|
||||
this.callbackDocument = callbackDocument;
|
||||
this.contextAction = contextAction;
|
||||
this.monitor = monitor;
|
||||
this.channel = channel;
|
||||
|
||||
// Initialize dependencies
|
||||
xmlData.addChild(topHandler);
|
||||
topHandler.addChild(groupHandler);
|
||||
|
||||
groupHandler.addChild(methodHandler);
|
||||
groupHandler.addChild(graphHandler);
|
||||
groupHandler.addChild(groupHandler);
|
||||
|
||||
methodHandler.addChild(inlinedHandler);
|
||||
methodHandler.addChild(bytecodesHandler);
|
||||
|
||||
inlinedHandler.addChild(inlinedMethodHandler);
|
||||
inlinedMethodHandler.addChild(bytecodesHandler);
|
||||
inlinedMethodHandler.addChild(inlinedHandler);
|
||||
|
||||
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);
|
||||
blockNodesHandler.addChild(blockNodeHandler);
|
||||
|
||||
nodesHandler.addChild(nodeHandler);
|
||||
nodesHandler.addChild(removeNodeHandler);
|
||||
edgesHandler.addChild(edgeHandler);
|
||||
edgesHandler.addChild(removeEdgeHandler);
|
||||
|
||||
methodHandler.addChild(propertiesHandler);
|
||||
inlinedMethodHandler.addChild(propertiesHandler);
|
||||
topHandler.addChild(propertiesHandler);
|
||||
groupHandler.addChild(groupPropertiesHandler);
|
||||
graphHandler.addChild(propertiesHandler);
|
||||
nodeHandler.addChild(propertiesHandler);
|
||||
propertiesHandler.addChild(propertyHandler);
|
||||
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 {
|
||||
if (monitor != null) {
|
||||
monitor.setState("Starting parsing");
|
||||
}
|
||||
try {
|
||||
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(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())) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
};
|
||||
// <nodes>
|
||||
private HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
|
||||
// <node>
|
||||
private ElementHandler<InputBlock, InputBlock> blockNodeHandler = new ElementHandler<InputBlock, InputBlock>(NODE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputBlock start() throws SAXException {
|
||||
String s = readRequiredAttribute(NODE_ID_PROPERTY);
|
||||
|
||||
int id = 0;
|
||||
try {
|
||||
id = lookupID(s);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
getParentObject().addNode(id);
|
||||
return getParentObject();
|
||||
if (monitor != null) {
|
||||
monitor.setState("Finished parsing");
|
||||
}
|
||||
};
|
||||
// <successors>
|
||||
private HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT);
|
||||
// <successor>
|
||||
private ElementHandler<InputBlock, InputBlock> successorHandler = new ElementHandler<InputBlock, InputBlock>(SUCCESSOR_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputBlock start() throws SAXException {
|
||||
String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
|
||||
blockConnections.add(new Pair<>(getParentObject().getName(), name));
|
||||
return getParentObject();
|
||||
}
|
||||
};
|
||||
// <node>
|
||||
private ElementHandler<InputNode, InputGraph> nodeHandler = new ElementHandler<InputNode, InputGraph>(NODE_ELEMENT) {
|
||||
return graphDocument;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputNode start() throws SAXException {
|
||||
String s = readRequiredAttribute(NODE_ID_PROPERTY);
|
||||
int id = 0;
|
||||
try {
|
||||
id = lookupID(s);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
InputNode node = new InputNode(id);
|
||||
getParentObject().addNode(node);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
// <removeNode>
|
||||
private ElementHandler<InputNode, InputGraph> removeNodeHandler = new ElementHandler<InputNode, InputGraph>(REMOVE_NODE_ELEMENT) {
|
||||
// Whether the parser is allowed to defer connecting the parsed elements.
|
||||
// Setting to false is useful for synchronization in unit tests.
|
||||
public void setInvokeLater(boolean invokeLater) {
|
||||
this.invokeLater = invokeLater;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputNode start() throws SAXException {
|
||||
String s = readRequiredAttribute(NODE_ID_PROPERTY);
|
||||
int id = 0;
|
||||
try {
|
||||
id = lookupID(s);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new SAXException(e);
|
||||
}
|
||||
return getParentObject().removeNode(id);
|
||||
private XMLReader createReader() throws SAXException {
|
||||
try {
|
||||
SAXParserFactory pFactory = SAXParserFactory.newInstance();
|
||||
pFactory.setValidating(false);
|
||||
pFactory.setNamespaceAware(true);
|
||||
return pFactory.newSAXParser().getXMLReader();
|
||||
} catch (ParserConfigurationException ex) {
|
||||
throw new SAXException(ex);
|
||||
}
|
||||
};
|
||||
// <graph>
|
||||
private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT);
|
||||
}
|
||||
|
||||
// Local class for edge elements
|
||||
private class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> {
|
||||
@ -381,10 +588,10 @@ public class Parser implements GraphParser {
|
||||
protected InputEdge start() throws SAXException {
|
||||
int fromIndex = 0;
|
||||
int toIndex = 0;
|
||||
int from = -1;
|
||||
int to = -1;
|
||||
String label = null;
|
||||
String type = null;
|
||||
int from;
|
||||
int to;
|
||||
String label;
|
||||
String type;
|
||||
|
||||
try {
|
||||
String fromIndexString = readAttribute(FROM_INDEX_PROPERTY);
|
||||
@ -413,148 +620,8 @@ public class Parser implements GraphParser {
|
||||
return start(conn);
|
||||
}
|
||||
|
||||
protected InputEdge start(InputEdge conn) throws SAXException {
|
||||
protected InputEdge start(InputEdge conn) {
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
// <edge>
|
||||
private EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputEdge start(InputEdge conn) throws SAXException {
|
||||
getParentObject().addEdge(conn);
|
||||
return conn;
|
||||
}
|
||||
};
|
||||
// <removeEdge>
|
||||
private EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) {
|
||||
|
||||
@Override
|
||||
protected InputEdge start(InputEdge conn) throws SAXException {
|
||||
getParentObject().removeEdge(conn);
|
||||
return conn;
|
||||
}
|
||||
};
|
||||
// <properties>
|
||||
private HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT);
|
||||
// <properties>
|
||||
private HandoverElementHandler<Group> groupPropertiesHandler = new HandoverElementHandler<Group>(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);
|
||||
} else {
|
||||
addStarted.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// <property>
|
||||
private ElementHandler<String, Properties.Provider> propertyHandler = new XMLParser.ElementHandler<String, Properties.Provider>(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());
|
||||
}
|
||||
};
|
||||
|
||||
public Parser(ReadableByteChannel channel) {
|
||||
this(channel, null, null);
|
||||
}
|
||||
|
||||
public Parser(ReadableByteChannel channel, ParseMonitor monitor, GroupCallback groupCallback) {
|
||||
|
||||
this.groupCallback = groupCallback;
|
||||
this.monitor = monitor;
|
||||
this.channel = channel;
|
||||
|
||||
// Initialize dependencies
|
||||
xmlDocument.addChild(topHandler);
|
||||
topHandler.addChild(groupHandler);
|
||||
|
||||
groupHandler.addChild(methodHandler);
|
||||
groupHandler.addChild(graphHandler);
|
||||
groupHandler.addChild(groupHandler);
|
||||
|
||||
methodHandler.addChild(inlinedHandler);
|
||||
methodHandler.addChild(bytecodesHandler);
|
||||
|
||||
inlinedHandler.addChild(inlinedMethodHandler);
|
||||
inlinedMethodHandler.addChild(bytecodesHandler);
|
||||
inlinedMethodHandler.addChild(inlinedHandler);
|
||||
|
||||
graphHandler.addChild(nodesHandler);
|
||||
graphHandler.addChild(edgesHandler);
|
||||
graphHandler.addChild(controlFlowHandler);
|
||||
|
||||
controlFlowHandler.addChild(blockHandler);
|
||||
|
||||
blockHandler.addChild(successorsHandler);
|
||||
successorsHandler.addChild(successorHandler);
|
||||
blockHandler.addChild(blockNodesHandler);
|
||||
blockNodesHandler.addChild(blockNodeHandler);
|
||||
|
||||
nodesHandler.addChild(nodeHandler);
|
||||
nodesHandler.addChild(removeNodeHandler);
|
||||
edgesHandler.addChild(edgeHandler);
|
||||
edgesHandler.addChild(removeEdgeHandler);
|
||||
|
||||
methodHandler.addChild(propertiesHandler);
|
||||
inlinedMethodHandler.addChild(propertiesHandler);
|
||||
topHandler.addChild(propertiesHandler);
|
||||
groupHandler.addChild(groupPropertiesHandler);
|
||||
graphHandler.addChild(propertiesHandler);
|
||||
nodeHandler.addChild(propertiesHandler);
|
||||
propertiesHandler.addChild(propertyHandler);
|
||||
groupPropertiesHandler.addChild(propertyHandler);
|
||||
}
|
||||
|
||||
// Returns a new GraphDocument object deserialized from an XML input source.
|
||||
@Override
|
||||
public GraphDocument parse() throws IOException {
|
||||
if (monitor != null) {
|
||||
monitor.setState("Starting parsing");
|
||||
}
|
||||
try {
|
||||
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.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())) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
if (monitor != null) {
|
||||
monitor.setState("Finished parsing");
|
||||
}
|
||||
return graphDocument;
|
||||
}
|
||||
|
||||
// Whether the parser is allowed to defer connecting the parsed elements.
|
||||
// Setting to false is useful for synchronization in unit tests.
|
||||
public void setInvokeLater(boolean invokeLater) {
|
||||
this.invokeLater = invokeLater;
|
||||
}
|
||||
|
||||
private XMLReader createReader() throws SAXException {
|
||||
try {
|
||||
SAXParserFactory pfactory = SAXParserFactory.newInstance();
|
||||
pfactory.setValidating(false);
|
||||
pfactory.setNamespaceAware(true);
|
||||
return pfactory.newSAXParser().getXMLReader();
|
||||
} catch (ParserConfigurationException ex) {
|
||||
throw new SAXException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 @@ package com.sun.hotspot.igv.data.serialization;
|
||||
|
||||
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 @@ import java.util.Set;
|
||||
*/
|
||||
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<GraphContext> contexts) {
|
||||
XMLWriter xmlWriter = new XMLWriter(writer);
|
||||
|
||||
try {
|
||||
export(xmlWriter, document);
|
||||
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();
|
||||
} 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.endTag();
|
||||
xmlWriter.flush();
|
||||
}
|
||||
|
||||
private void export(XMLWriter writer, Group g) throws IOException {
|
||||
private static void exportGroup(XMLWriter writer, Group g, List<GraphContext> 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<GraphContext> contexts) throws IOException {
|
||||
writer.startTag(Parser.GRAPH_ELEMENT);
|
||||
writer.writeProperties(graph.getProperties());
|
||||
writer.startTag(Parser.NODES_ELEMENT);
|
||||
@ -135,11 +109,11 @@ public class Printer {
|
||||
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<InputEdge> removedEdges = new HashSet<>();
|
||||
@ -169,45 +143,78 @@ public class Printer {
|
||||
}
|
||||
}
|
||||
|
||||
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<GraphContext> contexts) throws IOException {
|
||||
List<GraphContext> 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 @@ public class Printer {
|
||||
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 @@ public class Printer {
|
||||
p.setProperty(Parser.TYPE_PROPERTY, edge.getType());
|
||||
return p;
|
||||
}
|
||||
|
||||
public record GraphContext(InputGraph inputGraph, AtomicInteger posDiff, Set<Integer> visibleNodes, AtomicBoolean showAll) { }
|
||||
|
||||
public interface GraphContextAction {
|
||||
void performAction(GraphContext context);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 @@ import com.sun.hotspot.igv.data.InputGraph;
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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.IOException;
|
||||
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 class ParserTest {
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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.ServerSocketChannel;
|
||||
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 @@ import org.openide.util.RequestProcessor;
|
||||
*/
|
||||
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 class Server implements PreferenceChangeListener {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -652,7 +652,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
|
||||
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 class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
|
||||
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 class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
@ -332,6 +332,14 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
final HashSet<Integer> allNodes = new HashSet<>(getGroup().getAllNodes());
|
||||
allNodes.removeAll(nodes);
|
||||
setHiddenNodes(allNodes);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public Set<Integer> getVisibleNodes() {
|
||||
final Set<Integer> visibleNodes = new HashSet<>(getGraph().getNodesAsSet());
|
||||
visibleNodes.removeAll(hiddenNodes);
|
||||
return visibleNodes;
|
||||
}
|
||||
|
||||
public void setHiddenNodes(Set<Integer> nodes) {
|
||||
|
||||
@ -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 final class EditorTopComponent extends TopComponent implements TopCompone
|
||||
|
||||
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 final class EditorTopComponent extends TopComponent implements TopCompone
|
||||
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 final class EditorTopComponent extends TopComponent implements TopCompone
|
||||
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<InputNode> nodes, boolean showIfHidden) {
|
||||
@ -405,8 +417,7 @@ public final class EditorTopComponent extends TopComponent implements TopCompone
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 @@ package com.sun.hotspot.igv.view;
|
||||
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 @@ import org.openide.util.lookup.ServiceProvider;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user