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