1 7 8 package org.gjt.jclasslib.browser; 9 10 import org.gjt.jclasslib.structures.*; 11 import org.gjt.jclasslib.structures.attributes.*; 12 import org.gjt.jclasslib.structures.constants.ConstantLargeNumeric; 13 import org.gjt.jclasslib.structures.elementvalues.*; 14 15 import javax.swing.*; 16 import javax.swing.tree.*; 17 import java.awt.*; 18 import java.util.HashMap ; 19 import java.util.Map ; 20 21 28 public class BrowserTreePane extends JPanel { 29 30 private static final Dimension treeMinimumSize = new Dimension(100, 150); 31 private static final Dimension treePreferredSize = new Dimension(250, 150); 32 33 private BrowserServices services; 34 private JTree tree; 35 private Map categoryToPath = new HashMap (); 36 37 42 public BrowserTreePane(BrowserServices services) { 43 this.services = services; 44 setLayout(new BorderLayout()); 45 setupComponent(); 46 } 47 48 53 public JTree getTree() { 54 return tree; 55 } 56 57 63 public TreePath getPathForCategory(String category) { 64 return (TreePath)categoryToPath.get(category); 65 } 66 67 73 public void showMethod(String methodName, String methodSignature) { 74 75 TreePath methodsPath = (TreePath)categoryToPath.get(BrowserTreeNode.NODE_METHOD); 76 if (methodsPath == null) { 77 return; 78 } 79 MethodInfo[] methods = services.getClassFile().getMethods(); 80 TreeNode methodsNode = (TreeNode)methodsPath.getLastPathComponent(); 81 for (int i = 0; i < methodsNode.getChildCount(); i++) { 82 BrowserTreeNode treeNode = (BrowserTreeNode)methodsNode.getChildAt(i); 83 MethodInfo testMethod = methods[treeNode.getIndex()]; 84 try { 85 if (testMethod.getName().equals(methodName) && testMethod.getDescriptor().equals(methodSignature)) { 86 TreePath path = methodsPath.pathByAddingChild(treeNode); 87 BrowserTreeNode codeNode = findCodeNode(treeNode, testMethod); 88 if (codeNode != null) { 89 path = path.pathByAddingChild(codeNode); 90 } 91 92 tree.makeVisible(path); 93 tree.scrollPathToVisible(path); 94 tree.setSelectionPath(path); 95 return; 96 } 97 } catch (InvalidByteCodeException ex) { 98 } 99 } 100 } 101 102 105 public void rebuild() { 106 categoryToPath.clear(); 107 tree.clearSelection(); 108 tree.setModel(buildTreeModel()); 109 } 110 111 private void setupComponent() { 112 113 JScrollPane treeScrollPane = new JScrollPane(buildTree()); 114 treeScrollPane.setMinimumSize(treeMinimumSize); 115 treeScrollPane.setPreferredSize(treePreferredSize); 116 117 add(treeScrollPane, BorderLayout.CENTER); 118 } 119 120 private JTree buildTree() { 121 122 tree = new JTree(buildTreeModel()); 123 124 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 125 tree.setRootVisible(false); 126 tree.setShowsRootHandles(true); 127 128 return tree; 129 } 130 131 private TreeModel buildTreeModel() { 132 BrowserTreeNode rootNode = buildRootNode(); 133 DefaultTreeModel treeModel = new DefaultTreeModel(rootNode); 134 135 return treeModel; 136 } 137 138 private BrowserTreeNode buildRootNode() { 139 140 BrowserTreeNode rootNode = new BrowserTreeNode("Class file"); 141 ClassFile classFile = services.getClassFile(); 142 if (classFile != null) { 143 144 BrowserTreeNode generalNode = new BrowserTreeNode("General Information", BrowserTreeNode.NODE_GENERAL); 145 BrowserTreeNode constantPoolNode = buildConstantPoolNode(); 146 BrowserTreeNode interfacesNode = buildInterfacesNode(); 147 BrowserTreeNode fieldsNode = buildFieldsNode(); 148 BrowserTreeNode methodsNode = buildMethodsNode(); 149 BrowserTreeNode attributesNode = buildAttributesNode(); 150 151 rootNode.add(generalNode); 152 rootNode.add(constantPoolNode); 153 rootNode.add(interfacesNode); 154 rootNode.add(fieldsNode); 155 rootNode.add(methodsNode); 156 rootNode.add(attributesNode); 157 158 categoryToPath.put(BrowserTreeNode.NODE_GENERAL, new TreePath(new Object []{rootNode, generalNode})); 159 categoryToPath.put(BrowserTreeNode.NODE_CONSTANT_POOL, new TreePath(new Object []{rootNode, constantPoolNode})); 160 categoryToPath.put(BrowserTreeNode.NODE_INTERFACE, new TreePath(new Object []{rootNode, interfacesNode})); 161 categoryToPath.put(BrowserTreeNode.NODE_FIELD, new TreePath(new Object []{rootNode, fieldsNode})); 162 categoryToPath.put(BrowserTreeNode.NODE_METHOD, new TreePath(new Object []{rootNode, methodsNode})); 163 categoryToPath.put(BrowserTreeNode.NODE_ATTRIBUTE, new TreePath(new Object []{rootNode, attributesNode})); 164 } 165 166 return rootNode; 167 } 168 169 private BrowserTreeNode buildConstantPoolNode() { 170 171 BrowserTreeNode constantPoolNode = new BrowserTreeNode("Constant Pool"); 172 173 CPInfo[] constantPool = services.getClassFile().getConstantPool(); 174 int constantPoolCount = constantPool.length; 175 176 for (int i = 1; i < constantPoolCount; i++) { 177 i += addConstantPoolEntry(constantPool[i], i, constantPoolCount, constantPoolNode); 178 } 179 180 return constantPoolNode; 181 } 182 183 private int addConstantPoolEntry(CPInfo constantPoolEntry, 184 int index, 185 int constantPoolCount, 186 BrowserTreeNode constantPoolNode) { 187 188 189 if (constantPoolEntry == null) { 190 constantPoolNode.add(buildNullNode()); 191 } else { 192 BrowserTreeNode entryNode = 193 new BrowserTreeNode(getFormattedIndex(index, constantPoolCount) + 194 constantPoolEntry.getTagVerbose(), 195 BrowserTreeNode.NODE_CONSTANT_POOL, 196 index); 197 198 constantPoolNode.add(entryNode); 199 if (constantPoolEntry instanceof ConstantLargeNumeric) { 200 addConstantPoolContinuedEntry(index + 1, 201 constantPoolCount, 202 constantPoolNode); 203 return 1; 204 } 205 } 206 return 0; 207 } 208 209 private void addConstantPoolContinuedEntry(int index, 210 int constantPoolCount, 211 BrowserTreeNode constantPoolNode) { 212 213 BrowserTreeNode entryNode = 214 new BrowserTreeNode(getFormattedIndex(index, constantPoolCount) + 215 "(large numeric continued)", 216 BrowserTreeNode.NODE_NO_CONTENT); 217 constantPoolNode.add(entryNode); 218 } 219 220 private BrowserTreeNode buildInterfacesNode() { 221 222 BrowserTreeNode interfacesNode = new BrowserTreeNode("Interfaces"); 223 int[] interfaces = services.getClassFile().getInterfaces(); 224 int interfacesCount = interfaces.length; 225 BrowserTreeNode entryNode; 226 for (int i = 0; i < interfacesCount; i++) { 227 entryNode = new BrowserTreeNode("Interface " + i, 228 BrowserTreeNode.NODE_INTERFACE, 229 i); 230 interfacesNode.add(entryNode); 231 } 232 233 return interfacesNode; 234 } 235 236 private BrowserTreeNode buildFieldsNode() { 237 238 return buildClassMembersNode("Fields", 239 BrowserTreeNode.NODE_FIELD, 240 services.getClassFile().getFields()); 241 } 242 243 private BrowserTreeNode buildMethodsNode() { 244 245 return buildClassMembersNode("Methods", 246 BrowserTreeNode.NODE_METHOD, 247 services.getClassFile().getMethods()); 248 } 249 250 private BrowserTreeNode buildClassMembersNode(String text, 251 String type, 252 ClassMember[] classMembers) { 253 254 BrowserTreeNode classMemberNode = new BrowserTreeNode(text); 255 int classMembersCount = classMembers.length; 256 257 for (int i = 0; i < classMembersCount; i++) { 258 addClassMembersNode(classMembers[i], 259 i, 260 classMembersCount, 261 type, 262 classMemberNode); 263 } 264 265 return classMemberNode; 266 } 267 268 private void addClassMembersNode(ClassMember classMember, 269 int index, 270 int classMembersCount, 271 String type, 272 BrowserTreeNode classMemberNode) { 273 274 if (classMember == null) { 275 classMemberNode.add(buildNullNode()); 276 } else { 277 try { 278 BrowserTreeNode entryNode = 279 new BrowserTreeNode(getFormattedIndex(index, classMembersCount) + 280 classMember.getName(), 281 type, 282 index); 283 284 classMemberNode.add(entryNode); 285 addAttributeNodes(entryNode, classMember); 286 287 } catch (InvalidByteCodeException ex) { 288 classMemberNode.add(buildNullNode()); 289 } 290 } 291 } 292 293 private BrowserTreeNode buildAttributesNode() { 294 BrowserTreeNode attributesNode = new BrowserTreeNode("Attributes"); 295 296 addAttributeNodes(attributesNode, services.getClassFile()); 297 298 return attributesNode; 299 } 300 301 private BrowserTreeNode buildNullNode() { 302 303 return new BrowserTreeNode("[error] null"); 304 } 305 306 private void addAttributeNodes(BrowserTreeNode parentNode, 307 AbstractStructureWithAttributes structure) { 308 309 AttributeInfo[] attributes = structure.getAttributes(); 310 if (attributes == null) { 311 return; 312 } 313 int attributesCount = attributes.length; 314 for (int i = 0; i < attributesCount; i++) { 315 addSingleAttributeNode(attributes[i], 316 i, 317 attributesCount, 318 parentNode); 319 } 320 } 321 322 private void addSingleAttributeNode(AttributeInfo attribute, 323 int index, 324 int attributesCount, 325 BrowserTreeNode parentNode) { 326 327 328 if (attribute == null) { 329 parentNode.add(buildNullNode()); 330 } else { 331 try { 332 BrowserTreeNode entryNode = 333 new BrowserTreeNode(getFormattedIndex(index, attributesCount) + 334 attribute.getName(), 335 BrowserTreeNode.NODE_ATTRIBUTE, 336 index); 337 338 parentNode.add(entryNode); 339 if (attribute instanceof RuntimeAnnotationsAttribute) { 340 addRuntimeAnnotation(entryNode, (RuntimeAnnotationsAttribute)attribute); 341 } else if (attribute instanceof AnnotationDefaultAttribute) { 342 addSingleElementValueEntryNode(((AnnotationDefaultAttribute)attribute).getDefaultValue(), 0, 1, entryNode); 343 } else { 344 addAttributeNodes(entryNode, attribute); 345 } 346 347 } catch (InvalidByteCodeException ex) { 348 parentNode.add(buildNullNode()); 349 } 350 } 351 } 352 353 354 private String getFormattedIndex(int index, int maxIndex) { 355 356 StringBuffer buffer = new StringBuffer ("["); 357 String indexString = String.valueOf(index); 358 String maxIndexString = String.valueOf(maxIndex - 1); 359 for (int i = 0; i < maxIndexString.length() - indexString.length(); i++) { 360 buffer.append("0"); 361 } 362 buffer.append(indexString); 363 buffer.append("]"); 364 buffer.append(" "); 365 366 return buffer.toString(); 367 } 368 369 private BrowserTreeNode findCodeNode(BrowserTreeNode treeNode, MethodInfo methodInfo) { 370 AttributeInfo[] attributes = methodInfo.getAttributes(); 371 for (int i = 0; i < attributes.length; i++) { 372 if (attributes[i] instanceof CodeAttribute) { 373 return (BrowserTreeNode)treeNode.getChildAt(i); 374 } 375 } 376 return null; 377 } 378 379 380 private void addRuntimeAnnotation(BrowserTreeNode parentNode, 381 RuntimeAnnotationsAttribute structure) { 382 383 AnnotationElementValue[] annotations = structure.getRuntimeAnnotations(); 384 if (annotations == null) { 385 return; 386 } 387 int annotationsCount = annotations.length; 388 for (int i = 0; i < annotationsCount; i++) { 389 addSingleAnnotationNode(annotations[i], 390 i, 391 annotationsCount, 392 parentNode); 393 } 394 } 395 396 private void addSingleAnnotationNode(AnnotationElementValue annotation, 397 int index, 398 int attributesCount, 399 BrowserTreeNode parentNode) { 400 401 402 if (annotation == null) { 403 parentNode.add(buildNullNode()); 404 } else { 405 BrowserTreeNode entryNode = 406 new BrowserTreeNode(getFormattedIndex(index, attributesCount) + 407 annotation.getEntryName(), 408 BrowserTreeNode.NODE_ANNOTATION, 409 index, 410 annotation); 411 parentNode.add(entryNode); 412 addElementValuePairEntry(entryNode, annotation); 413 } 414 } 415 416 private void addElementValuePairEntry(BrowserTreeNode parentNode, 417 AnnotationElementValue annotation) { 418 419 ElementValuePair[] entries = annotation.getElementValuePairEntries(); 420 if (entries == null) { 421 return; 422 } 423 int entriesCount = entries.length; 424 for (int i = 0; i < entriesCount; i++) { 425 addSingleElementValuePairEntryNode(entries[i], 426 i, 427 entriesCount, 428 parentNode); 429 } 430 } 431 432 private void addArrayElementValueEntry(BrowserTreeNode parentNode, 433 ArrayElementValue aeve) { 434 435 ElementValue[] entries = aeve.getElementValueEntries(); 436 if (entries == null) { 437 return; 438 } 439 int entriesCount = entries.length; 440 for (int i = 0; i < entriesCount; i++) { 441 addSingleElementValueEntryNode(entries[i], 442 i, 443 entriesCount, 444 parentNode); 445 } 446 } 447 448 449 private void addSingleElementValuePairEntryNode(ElementValuePair evep, 450 int index, 451 int attributesCount, 452 BrowserTreeNode parentNode) { 453 454 455 if (evep == null) { 456 parentNode.add(buildNullNode()); 457 } else { 458 BrowserTreeNode entryNode = 459 new BrowserTreeNode(getFormattedIndex(index, attributesCount) + 460 evep.getEntryName(), 461 BrowserTreeNode.NODE_ELEMENTVALUEPAIR, 462 index, 463 evep); 464 parentNode.add(entryNode); 465 addSingleElementValueEntryNode(evep.getElementValue(), 0, 1, entryNode); 466 } 467 } 468 469 private void addSingleElementValueEntryNode(ElementValue eve, 470 int index, 471 int attributesCount, 472 BrowserTreeNode parentNode) { 473 474 if (eve == null) { 475 parentNode.add(buildNullNode()); 476 } else { 477 String prefix = attributesCount > 1 ? 478 getFormattedIndex(index, attributesCount) : ""; 479 String nodeType = BrowserTreeNode.NODE_ELEMENTVALUE; 480 if (eve instanceof AnnotationElementValue) { 481 nodeType = BrowserTreeNode.NODE_ANNOTATION; 482 } else if (eve instanceof ArrayElementValue) { 483 nodeType = BrowserTreeNode.NODE_ARRAYELEMENTVALUE; 484 } 485 486 BrowserTreeNode entryNode = 487 new BrowserTreeNode(prefix + eve.getEntryName(), 488 nodeType, index, eve); 489 490 parentNode.add(entryNode); 491 if (nodeType == BrowserTreeNode.NODE_ANNOTATION) { 492 addElementValuePairEntry(entryNode, (AnnotationElementValue)eve); 493 } else if (nodeType == BrowserTreeNode.NODE_ARRAYELEMENTVALUE) { 494 addArrayElementValueEntry(entryNode, (ArrayElementValue)eve); 495 } 496 } 497 } 498 } 499 | Popular Tags |