All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scandroid.util.DexDotUtil Maven / Gradle / Ivy

There is a newer version: 1.6.8
Show newest version
/*
 * 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.util.viz.DotUtil;
import com.ibm.wala.util.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(
      @SuppressWarnings("unused") T n, @SuppressWarnings("unused") NodeDecorator d) {
    return " [ ]\n";
  }

  private static  String getLabel(T o, NodeDecorator d) throws WalaException {
    String result;
    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