blob: e20304c31dd0622291fa909be8f2d978639161a1 [file] [log] [blame]
/***
* ASM examples: examples showing how ASM can be used
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.objectweb.asm.depend;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.imageio.ImageIO;
import org.objectweb.asm.ClassReader;
/**
* DependencyTracker
*
* @author Eugene Kuleshov
*
* @see "http://www.onjava.com/pub/a/onjava/2005/08/17/asm3.html"
*/
public class DependencyTracker {
private static final int CELL_PAD = 1;
private static final int GRID_SIZE = 10;
private static final int CELLS_SIZE = 8;
private static final int LABEL_WIDTH = 200;
private static final String LABEL_FONT = "Tahoma-9";
public static void main(final String[] args) throws IOException {
DependencyVisitor v = new DependencyVisitor();
ZipFile f = new ZipFile(args[0]);
long l1 = System.currentTimeMillis();
Enumeration<? extends ZipEntry> en = f.entries();
while (en.hasMoreElements()) {
ZipEntry e = en.nextElement();
String name = e.getName();
if (name.endsWith(".class")) {
new ClassReader(f.getInputStream(e)).accept(v, 0);
}
}
long l2 = System.currentTimeMillis();
Map<String, Map<String, Integer>> globals = v.getGlobals();
Set<String> jarPackages = globals.keySet();
Set<String> classPackages = v.getPackages();
int size = classPackages.size();
System.err.println("time: " + (l2 - l1) / 1000f + " " + size);
String[] jarNames = jarPackages.toArray(new String[jarPackages.size()]);
String[] classNames = classPackages.toArray(new String[classPackages
.size()]);
Arrays.sort(jarNames);
Arrays.sort(classNames);
buildDiagram(jarNames, classNames, globals);
}
public static void buildDiagram(final String[] jarNames,
final String[] classNames,
final Map<String, Map<String, Integer>> globals) throws IOException {
// normalize
int max = 0;
for (int i = 0; i < classNames.length; i++) {
Map<String, Integer> map = globals.get(classNames[i]);
if (map == null) {
continue;
}
Integer maxCount = Collections.max(map.values());
if (maxCount > max) {
max = maxCount;
}
}
List<Color> colors = new ArrayList<Color>();
for (int i = LABEL_WIDTH; i >= 0; i--) {
colors.add(new Color(i, i, 255));
}
for (int i = 255; i >= 128; i--) {
colors.add(new Color(0, 0, i));
}
int maxcolor = colors.size() - 1;
int heigh = CELL_PAD + (CELLS_SIZE + CELL_PAD) * classNames.length;
int width = CELL_PAD + (CELLS_SIZE + CELL_PAD) * jarNames.length;
BufferedImage img = new BufferedImage(width + LABEL_WIDTH, heigh
+ LABEL_WIDTH, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.WHITE);
g.fillRect(0, 0, width + LABEL_WIDTH, heigh + LABEL_WIDTH);
// draw lines
g.setColor(Color.LIGHT_GRAY);
for (int y = GRID_SIZE; y < classNames.length; y += GRID_SIZE) {
g.drawLine(0, y * (CELLS_SIZE + CELL_PAD), width, y
* (CELLS_SIZE + CELL_PAD));
}
for (int x = GRID_SIZE; x < jarNames.length; x += GRID_SIZE) {
g.drawLine(x * (CELLS_SIZE + CELL_PAD), 0, x
* (CELLS_SIZE + CELL_PAD), heigh);
}
// draw diagram
for (int y = 0; y < classNames.length; y++) {
// System.err.println( y+" : "+classNames[ y]);
for (int x = 0; x < jarNames.length; x++) {
Map<String, Integer> map = globals.get(jarNames[x]);
Integer count = map == null ? null : map.get(classNames[y]);
if (count != null) {
int b = (int) ((float) count * maxcolor / max);
g.setColor(colors.get(b));
g.fillRect(CELL_PAD + x * (CELLS_SIZE + CELL_PAD), CELL_PAD
+ y * (CELLS_SIZE + CELL_PAD), CELLS_SIZE,
CELLS_SIZE);
}
}
}
// draw labels
Font f = Font.decode(LABEL_FONT);
g.setFont(f);
// g.setColor( new Color( 70, 70, 255));
g.setColor(Color.GRAY);
for (int y = 0; y < classNames.length; y++) {
AffineTransform trans = g.getTransform();
g.transform(AffineTransform.getTranslateInstance(CELL_PAD * 2
+ width, CELLS_SIZE + y * (CELLS_SIZE + CELL_PAD)));
g.transform(AffineTransform.getRotateInstance(Math.PI / 12));
g.drawString(classNames[y], 0, 0);
g.setTransform(trans);
}
for (int x = 0; x < jarNames.length; x++) {
AffineTransform trans = g.getTransform();
g.transform(AffineTransform.getTranslateInstance(CELL_PAD * 2 + x
* (CELLS_SIZE + CELL_PAD), heigh + CELL_PAD * 2));
g.transform(AffineTransform.getRotateInstance(Math.PI / 2.5));
g.drawString(jarNames[x], 0, 0);
g.setTransform(trans);
}
FileOutputStream fos = new FileOutputStream("test.png");
ImageIO.write(img, "png", fos);
fos.flush();
fos.close();
}
}