Java tutorial
/* * JSplitPaneClassFile.java 19:58, April 06, 2009 * * Copyright 2009, FreeInternals.org. All rights reserved. * Use is subject to license terms. */ package org.freeinternals.javaclassviewer.ui; import java.awt.Component; import java.io.File; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTextPane; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import org.freeinternals.commonlib.ui.HTMLKit; import org.freeinternals.commonlib.ui.JBinaryViewer; import org.freeinternals.commonlib.ui.JPanelForTree; import org.freeinternals.format.FileFormatException; import org.freeinternals.format.classfile.ClassFile; import org.freeinternals.format.classfile.FieldInfo; import org.freeinternals.format.classfile.MethodInfo; import org.freeinternals.format.classfile.Opcode; import org.freeinternals.format.classfile.Opcode.CodeResult; import org.freeinternals.format.classfile.constpool.AbstractCPInfo; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; /** * A split panel created from a class file byte array. * * @author Amos Shi * @since JDK 6.0 * @see ClassFile */ public class JSplitPaneClassFile extends JSplitPane { private static final long serialVersionUID = 4876543219876500000L; private ClassFile classFile; private JBinaryViewer binaryViewer = null; private JScrollPane binaryViewerView = null; private JTextPane opcode = null; private JTextPane report = null; /** * Creates a split panel from a Java class file byte array. * * @param byteArray * Java class file byte array */ public JSplitPaneClassFile(final byte[] byteArray, JFrame top) { try { this.classFile = new ClassFile(byteArray.clone()); } catch (IOException | FileFormatException ex) { Logger.getLogger(JSplitPaneClassFile.class.getName()).log(Level.SEVERE, null, ex); } ObjectMapper mapper = new ObjectMapper(); // or: // byte[] jsonBytes = mapper.writeValueAsBytes(classFile); String jsonString; try { mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.writeValue(new File("f:\\result.json"), classFile); //jsonString = mapper.writeValueAsString(classFile); //System.out.println(jsonString); } catch (JsonProcessingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.createAndShowGUI(top); this.generateClassReport(); } private void createAndShowGUI(JFrame top) { // Construct class file viewer final JTreeClassFile jTreeClassFile = new JTreeClassFile(this.classFile); jTreeClassFile.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(final javax.swing.event.TreeSelectionEvent evt) { jTreeClassFileSelectionChanged(evt); } }); final JPanelForTree panel = new JPanelForTree(jTreeClassFile, top); final JTabbedPane tabbedPane = new JTabbedPane(); // Construct binary viewer this.binaryViewer = new JBinaryViewer(); this.binaryViewer.setData(this.classFile.getClassByteArray()); this.binaryViewerView = new JScrollPane(this.binaryViewer); this.binaryViewerView.getVerticalScrollBar().setValue(0); tabbedPane.add("Class File", this.binaryViewerView); // Construct opcode viewer this.opcode = new JTextPane(); this.opcode.setAlignmentX(Component.LEFT_ALIGNMENT); // this.opcode.setFont(new Font(Font.DIALOG_INPUT, Font.PLAIN, 14)); this.opcode.setEditable(false); this.opcode.setBorder(null); this.opcode.setContentType("text/html"); tabbedPane.add("Opcode", new JScrollPane(this.opcode)); // Class report this.report = new JTextPane(); this.report.setAlignmentX(Component.LEFT_ALIGNMENT); this.report.setEditable(false); this.report.setBorder(null); this.report.setContentType("text/html"); tabbedPane.add("Report", new JScrollPane(this.report)); this.setOrientation(JSplitPane.HORIZONTAL_SPLIT); this.setDividerSize(5); this.setDividerLocation(280); this.setLeftComponent(panel); this.setRightComponent(tabbedPane); this.binaryViewerView.getVerticalScrollBar().setValue(0); } private void jTreeClassFileSelectionChanged(final TreeSelectionEvent evt) { Object obj = evt.getPath().getLastPathComponent(); if (obj instanceof DefaultMutableTreeNode) { final DefaultMutableTreeNode objDmtn = (DefaultMutableTreeNode) obj; obj = objDmtn.getUserObject(); if (obj instanceof JTreeNodeClassComponent) { final JTreeNodeClassComponent objTncc = (JTreeNodeClassComponent) obj; // Select the bytes of this data this.binaryViewer.setSelection(objTncc.getStartPos(), objTncc.getLength()); // clear opcode values; this.opcode.setText(null); // Get the code bytes if (objTncc.getText().equals("code")) { // System.out.println("code"); final byte[] data = this.classFile.getClassByteArray(objTncc.getStartPos(), objTncc.getLength()); this.generateOpcodeParseResult(data); } } } } private void generateOpcodeParseResult(byte[] opcodeData) { StringBuilder sb = new StringBuilder(1024); sb.append(HTMLKit.Start()); // The Extracted Code sb.append("<pre>"); sb.append(org.freeinternals.commonlib.util.Tool.getByteDataHexView(opcodeData, true)); sb.append("\n"); CodeResult codeResult = Opcode.parseCode(opcodeData, this.classFile); sb.append(codeResult.OpcodeTexts); sb.append("</pre>"); // The Reference Object if (!codeResult.CPIndexes.isEmpty()) { sb.append("<ol>"); for (Integer i : codeResult.CPIndexes) { sb.append(String.format("<li>%s</li>", HTMLKit.EscapeFilter(this.classFile.getCPDescription(i)))); } sb.append("</ol>"); } sb.append(HTMLKit.End()); this.opcode.setText(sb.toString()); } private void generateClassReport() { StringBuilder sb = new StringBuilder(1024); sb.append(HTMLKit.Start()); int count; // Constant Pool count = this.classFile.getCPCount().getValue(); sb.append(String.format("Constant Pool Count: %d", count)); sb.append(HTMLKit.NewLine()); if (count > 0) { AbstractCPInfo[] CPInfoList = this.classFile.getConstantPool(); // Constant Pool - by Type sb.append("Constant Pool - Class"); this.generateCPTypeReport(sb, CPInfoList, count, AbstractCPInfo.CONSTANT_Class); sb.append("Constant Pool - Field"); this.generateCPTypeReport(sb, CPInfoList, count, AbstractCPInfo.CONSTANT_Fieldref); sb.append("Constant Pool - Method"); this.generateCPTypeReport(sb, CPInfoList, count, AbstractCPInfo.CONSTANT_Methodref); // Constant Pool Object List sb.append("Constant Pool Object List"); sb.append(HTMLKit.NewLine()); sb.append("<ol>"); for (int i = 1; i < count; i++) { sb.append(String.format("<li>%s</li>", HTMLKit.EscapeFilter(this.classFile.getCPDescription(i)))); } sb.append("</ol>"); } // Fields count = this.classFile.getFieldCount().getValue(); sb.append(String.format("Field Count: %d", count)); sb.append(HTMLKit.NewLine()); if (count > 0) { FieldInfo[] fields = this.classFile.getFields(); sb.append("<ol>"); for (FieldInfo field : fields) { sb.append(String.format("<li>%s</li>", HTMLKit.EscapeFilter(field.getDeclaration()))); } sb.append("</ol>"); } sb.append(HTMLKit.NewLine()); // Methods count = this.classFile.getMethodCount().getValue(); sb.append(String.format("Method Count: %d", count)); sb.append(HTMLKit.NewLine()); if (count > 0) { MethodInfo[] methods = this.classFile.getMethods(); sb.append("<ol>"); for (MethodInfo method : methods) { sb.append(String.format("<li>%s</li>", HTMLKit.EscapeFilter(method.getDeclaration()))); } sb.append("</ol>"); } sb.append(HTMLKit.NewLine()); sb.append(HTMLKit.End()); this.report.setText(sb.toString()); } private void generateCPTypeReport(StringBuilder sb, AbstractCPInfo[] CPInfoList, int count, short tag) { sb.append(HTMLKit.NewLine()); sb.append("<ul>"); for (int i = 1; i < count; i++) { if (CPInfoList[i].getTag() == tag) { sb.append(String.format("<li>%d. %s</li>", i, HTMLKit.EscapeFilter(this.classFile.getCPDescription(i)))); } } sb.append("</ul>"); } }