org.scandroid.util.DexDotUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.ibm.wala.scandroid Show documentation
Show all versions of com.ibm.wala.scandroid Show documentation
T. J. Watson Libraries for Analysis
/*
* Copyright (c) 2002 - 2006, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Steve Suh - added cleanUpString
*/
package org.scandroid.util;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.collections.Iterator2Collection;
import com.ibm.wala.util.collections.Iterator2Iterable;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.viz.DotUtil;
import com.ibm.wala.viz.NodeDecorator;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
public class DexDotUtil extends DotUtil {
/** possible output formats for dot */
// public static enum DotOutputType {
// PS, SVG, PDF, EPS
// }
private static final DotOutputType outputType = DotOutputType.PDF;
private static int fontSize = 6;
private static final String fontColor = "black";
private static final String fontName = "Arial";
// public static void setOutputType(DotOutputType outType) {
// outputType = outType;
// }
// public static DotOutputType getOutputType() {
// return outputType;
// }
private static String outputTypeCmdLineParam() {
switch (outputType) {
case PS:
return "-Tps";
case EPS:
return "-Teps";
case SVG:
return "-Tsvg";
case PDF:
return "-Tpdf";
default:
Assertions.UNREACHABLE();
return null;
}
}
/** Some versions of dot appear to croak on long labels. Reduce this if so. */
private static final int MAX_LABEL_LENGTH = Integer.MAX_VALUE;
/** */
public static void dotify(
Graph g, NodeDecorator labels, String dotFile, String outputFile, String dotExe)
throws WalaException {
dotify(g, labels, null, dotFile, outputFile, dotExe);
}
public static void dotify(
Graph g,
NodeDecorator labels,
String title,
String dotFile,
String outputFile,
String dotExe)
throws WalaException {
if (g == null) {
throw new IllegalArgumentException("g is null");
}
File f = DexDotUtil.writeDotFile(g, labels, title, dotFile);
spawnDot(dotExe, outputFile, f);
}
public static void spawnDot(String dotExe, String outputFile, File dotFile) throws WalaException {
if (dotFile == null) {
throw new IllegalArgumentException("dotFile is null");
}
String[] cmdarray = {
dotExe, outputTypeCmdLineParam(), "-o", outputFile, "-v", dotFile.getAbsolutePath()
};
BufferedInputStream output = null;
BufferedInputStream error = null;
try {
Process p = Runtime.getRuntime().exec(cmdarray);
output = new BufferedInputStream(p.getInputStream());
error = new BufferedInputStream(p.getErrorStream());
boolean repeat = true;
while (repeat) {
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
e1.printStackTrace();
// just ignore and continue
}
if (output.available() > 0) {
byte[] data = new byte[output.available()];
output.read(data);
}
if (error.available() > 0) {
byte[] data = new byte[error.available()];
error.read(data);
}
try {
p.exitValue();
// if we get here, the process has terminated
repeat = false;
} catch (IllegalThreadStateException e) {
// this means the process has not yet terminated.
repeat = true;
}
}
} catch (IOException e) {
e.printStackTrace();
throw new WalaException("IOException in " + DotUtil.class);
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (error != null) {
try {
error.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static File writeDotFile(
Graph g, NodeDecorator labels, String title, String dotfile) throws WalaException {
if (g == null) {
throw new IllegalArgumentException("g is null");
}
StringBuilder dotStringBuffer = dotOutput(g, labels, title);
// retrieve the filename parameter to this component, a String
if (dotfile == null) {
throw new WalaException("internal error: null filename parameter");
}
try {
File f = new File(dotfile);
try (final FileWriter fw = new FileWriter(f)) {
fw.write(dotStringBuffer.toString());
}
return f;
} catch (Exception e) {
throw new WalaException("Error writing dot file " + dotfile, e);
}
}
/** @return StringBuffer holding dot output representing G */
public static StringBuilder dotOutput(Graph g, NodeDecorator labels, String title)
throws WalaException {
StringBuilder result = new StringBuilder("digraph \"DirectedGraph\" {\n");
if (title != null) {
result
.append("graph [label = \"")
.append(title)
.append("\", labelloc=t, concentrate = true];");
} else {
result.append("graph [concentrate = true];");
}
String rankdir = getRankDir();
if (rankdir != null) {
result.append("rankdir=").append(rankdir).append(';');
}
String fontsizeStr = "fontsize=" + fontSize;
String fontcolorStr = ",fontcolor=" + fontColor;
String fontnameStr = ",fontname=" + fontName;
result.append("center=true;");
result.append(fontsizeStr);
result.append(";node [ color=blue,shape=\"box\"");
result.append(fontsizeStr);
result.append(fontcolorStr);
result.append(fontnameStr);
result.append("];edge [ color=black,");
result.append(fontsizeStr);
result.append(fontcolorStr);
result.append(fontnameStr);
result.append("]; \n");
Collection dotNodes = computeDotNodes(g);
outputNodes(labels, result, dotNodes);
for (T n : g) {
for (T s : Iterator2Iterable.make(g.getSuccNodes(n))) {
result.append(' ');
result.append(getPort(n, labels));
result.append(" -> ");
result.append(getPort(s, labels));
result.append(" \n");
}
}
result.append("\n}");
return result;
}
private static void outputNodes(
NodeDecorator labels, StringBuilder result, Collection dotNodes) throws WalaException {
for (T t : dotNodes) {
outputNode(labels, result, t);
}
}
private static void outputNode(NodeDecorator labels, StringBuilder result, T n)
throws WalaException {
result.append(" ");
result.append('\"');
result.append(getLabel(n, labels));
result.append('\"');
result.append(decorateNode(n, labels));
}
/** Compute the nodes to visualize */
private static Collection computeDotNodes(Graph g) {
return Iterator2Collection.toSet(g.iterator());
}
private static String getRankDir() {
return null;
}
/**
* @param n node to decorate
* @param d decorating master
*/
private static String decorateNode(T n, NodeDecorator d) {
return " [ ]\n";
}
private static String getLabel(T o, NodeDecorator d) throws WalaException {
String result = null;
if (d == null) {
// result = o.toString();
result = cleanUpString(o.toString());
} else {
result = d.getLabel(o);
result = result == null ? cleanUpString(o.toString()) : cleanUpString(result);
}
if (result.length() >= MAX_LABEL_LENGTH) {
result = result.substring(0, MAX_LABEL_LENGTH - 3) + "...";
}
return result;
}
private static String getPort(T o, NodeDecorator d) throws WalaException {
return '"' + getLabel(o, d) + '"';
}
public static int getFontSize() {
return fontSize;
}
public static void setFontSize(int fontSize) {
DexDotUtil.fontSize = fontSize;
}
private static String cleanUpString(String s) {
if (!s.isEmpty() && s.startsWith("Node: ")) {
String[] nodeString = s.split(",");
if (nodeString.length >= 3) {
String className = nodeString[1];
String methodName = nodeString[2];
return className.trim() + "\\n" + methodName.substring(0, methodName.indexOf(" > ")).trim();
}
}
return s;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy