1 /* 2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.incubator.code.tools.dot; 27 28 import jdk.incubator.code.tools.renderer.ProcessRunner; 29 30 import java.io.File; 31 import java.io.FileWriter; 32 import java.io.IOException; 33 import java.io.StringWriter; 34 import java.util.ArrayList; 35 import java.util.List; 36 37 /** 38 * Created by gfrost 39 * http://graphviz.org/Documentation.php 40 * http://graphviz.org/content/arrow-shapes 41 * http://graphviz.org/content/rootNode-shapes 42 * http://graphviz.org/content/attrs 43 * http://www.graphviz.org/Documentation/dotguide.pdf 44 */ 45 public final class DotViewer { 46 private DotViewer() { 47 } 48 49 // Look at Path.of() ..... ;) I think I may have reimplemented it 50 static String[] svgViewers = new String[]{ 51 System.getenv("SVG_VIEWER_PATH"), 52 System.getProperty("SVG_VIEWER_PATH"), 53 "/usr/bin/google-chrome", 54 "/snap/chromium/1466/usr/lib/chromium-browser/chrome", 55 "/usr/bin/gpicview", 56 "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", 57 "/usr/bin/xdg-open" 58 }; 59 static String[] dotLocations = new String[]{ 60 System.getenv("DOT_PATH"), 61 System.getProperty("DOT_PATH"), 62 "/usr/bin/dot", 63 "/usr/local/bin/dot" // mac 64 }; 65 66 static String getLocation(String[] possibles) { 67 for (String s : possibles) { 68 if (s != null && !s.equals("")) { 69 File file = new File(s); 70 if (file.exists() && file.canExecute()) { 71 return s; 72 } 73 } 74 } 75 return null; 76 } 77 78 public static void view(String dotSource) { 79 80 String dot = getLocation(dotLocations); 81 System.out.println(dotSource); 82 String svgViewer = getLocation(svgViewers); 83 84 if (dot != null && svgViewer != null) { 85 try { 86 File tempFile = File.createTempFile("ast", ".svg"); 87 ProcessRunner.run(dot) 88 .opt("-Tsvg") 89 .opt("-o").file(tempFile) 90 .temp("ast", "dot", dotSource) 91 .go(false); 92 ProcessRunner.run(svgViewer) 93 .file(tempFile) 94 .go(false); 95 96 } catch (IOException ioe) { 97 ioe.printStackTrace(); 98 } 99 } 100 101 } 102 103 public static void viewNoWait(String dotSource) { 104 String dot = getLocation(dotLocations); 105 String svgViewer = getLocation(svgViewers); 106 107 if (dot != null && svgViewer != null) { 108 try { 109 File tempDotFile = File.createTempFile("ast", "dot"); 110 FileWriter tempDotFileWriter = new FileWriter(tempDotFile); 111 tempDotFileWriter.append(dotSource); 112 tempDotFileWriter.close(); 113 File tempPngFile = File.createTempFile("ast", "svg"); 114 List<String> dotCommand = new ArrayList<>(); 115 dotCommand.add(dot); 116 dotCommand.add("-Tsvg"); 117 dotCommand.add("-o"); 118 dotCommand.add(tempPngFile.getAbsolutePath()); 119 dotCommand.add(tempDotFile.getAbsolutePath()); 120 121 ProcessBuilder dotBuilder = new ProcessBuilder(dotCommand); 122 Process dotProcess = dotBuilder.start(); 123 dotProcess.waitFor(); 124 125 List<String> fehCommand = new ArrayList<>(); 126 fehCommand.add(svgViewer); 127 // fehCommand.add("-t"); 128 fehCommand.add(tempPngFile.getAbsolutePath()); 129 ProcessBuilder fehBuilder = new ProcessBuilder(fehCommand); 130 Process fehProcess = fehBuilder.start(); 131 132 } catch (IOException | InterruptedException ioe) { 133 ioe.printStackTrace(); 134 } 135 } else if (dot == null) { 136 System.out.println("Sorry can't find /usr/bin/dot (sudo apt-get install graphviz)"); 137 } else { 138 System.out.println("Sorry can't find a suitable SVG Viewer"); 139 } 140 141 } 142 143 public static void main(String[] args) throws IOException { 144 // https://renenyffenegger.ch/notes/tools/Graphviz/examples/index 145 146 StringWriter dotw = new StringWriter(); 147 // http://magjac.com/graphviz-visual-editor/ 148 new DotRenderer().writer(dotw).start("mine").graph( 149 (g) -> g 150 .box("A", 151 (box) -> box 152 .label("Snarlywang") 153 .color("lightyellow") 154 .style("filled") 155 ) 156 .record("B", 157 (record) -> record 158 .color("lightgreen") 159 .style("filled") 160 .label((label) -> label 161 .port("left", "left") 162 .box( 163 (vertical) -> vertical 164 .port("top", "top") 165 .label("center") 166 .port("bottom", "bottom") 167 ) 168 .port("right", "right") 169 ) 170 ) 171 .edge("A", "B:top:nw", (e) -> e.label("1")) 172 .edge("A", "B:bottom:se", (e) -> e.label("2")) 173 .edge("A", "B:left:w", (e) -> e.label("3")) 174 .edge("A", "B:right:e", (e) -> e.label("4")) 175 ).end(); 176 DotViewer.view(dotw.toString()); 177 } 178 }