KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > jclasslib > browser > detail > attributes > code > ByteCodeDisplay


1 /*
2     This library is free software; you can redistribute it and/or
3     modify it under the terms of the GNU General Public
4     License as published by the Free Software Foundation; either
5     version 2 of the license, or (at your option) any later version.
6 */

7
8 package org.gjt.jclasslib.browser.detail.attributes.code;
9
10 import org.gjt.jclasslib.browser.*;
11 import org.gjt.jclasslib.bytecode.*;
12 import org.gjt.jclasslib.io.ByteCodeReader;
13 import org.gjt.jclasslib.structures.ClassFile;
14 import org.gjt.jclasslib.structures.InvalidByteCodeException;
15 import org.gjt.jclasslib.structures.attributes.CodeAttribute;
16
17 import javax.swing.*;
18 import javax.swing.border.Border JavaDoc;
19 import javax.swing.border.EmptyBorder JavaDoc;
20 import javax.swing.tree.TreePath JavaDoc;
21 import java.awt.*;
22 import java.awt.datatransfer.StringSelection JavaDoc;
23 import java.awt.font.*;
24 import java.io.IOException JavaDoc;
25 import java.text.AttributedString JavaDoc;
26 import java.util.*;
27
28 /**
29     Bytecode renderer.
30
31     @author <a HREF="mailto:jclasslib@ej-technologies.com">Ingo Kegel</a>
32     @version $Revision: 1.3 $ $Date: 2004/11/02 09:38:13 $
33 */

34 public class ByteCodeDisplay extends JPanel implements Scrollable {
35
36     /** Horizontal margin. */
37     public static final int MARGIN_X = 3;
38     /** Vertical margin. */
39     public static final int MARGIN_Y = 3;
40
41     /** Border for the renderer. */
42     public static final Border JavaDoc BORDER = new EmptyBorder JavaDoc(MARGIN_Y, MARGIN_X, MARGIN_Y, MARGIN_X);
43
44     private static Map STYLE_BASE;
45     private static Map STYLE_NORMAL;
46     private static Map STYLE_SMALL;
47     private static Map STYLE_LINK;
48     private static Map STYLE_OFFSET;
49     private static Map STYLE_INSTRUCTION;
50     private static Map STYLE_IMMEDIATE_VALUE;
51
52     private static final String JavaDoc TAB_STRING = " ";
53
54     static {
55         initStyles(null);
56     }
57
58     public static void initStyles(Font baseFont) {
59
60         STYLE_BASE = new HashMap(2);
61         if (baseFont != null) {
62             STYLE_BASE.put(TextAttribute.FAMILY, baseFont.getFamily());
63         } else {
64             baseFont = UIManager.getFont("TextArea.font");
65             STYLE_BASE.put(TextAttribute.FAMILY, "MonoSpaced");
66         }
67
68         STYLE_BASE.put(TextAttribute.SIZE, new Float JavaDoc(baseFont.getSize()));
69
70         STYLE_NORMAL = new HashMap(0);
71
72         STYLE_SMALL = new HashMap(1);
73         STYLE_SMALL.put(TextAttribute.SIZE, new Float JavaDoc(baseFont.getSize() - 1));
74
75         STYLE_LINK = new HashMap(3);
76         STYLE_LINK.put(TextAttribute.FOREGROUND, new Color(0, 128, 0));
77         STYLE_LINK.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
78         STYLE_LINK.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
79
80         STYLE_OFFSET = new HashMap(1);
81         STYLE_OFFSET.put(TextAttribute.FOREGROUND, new Color(128, 0, 0));
82
83         STYLE_INSTRUCTION = new HashMap(1);
84         STYLE_INSTRUCTION.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
85
86         STYLE_IMMEDIATE_VALUE = new HashMap(2);
87         STYLE_IMMEDIATE_VALUE.put(TextAttribute.FOREGROUND, Color.magenta);
88         STYLE_IMMEDIATE_VALUE.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
89     }
90
91     private ByteCodeDetailPane detailPane;
92
93     private CodeAttribute codeAttribute;
94     private ClassFile classFile;
95
96     private int offsetWidth;
97     private String JavaDoc offsetBlank;
98     private HashMap offsetToLine = new HashMap();
99     private ArrayList lines = new ArrayList();
100     private ArrayList textLines = new ArrayList();
101     private TextLayout[] textLayouts;
102     private Map lineToLink = new HashMap();
103
104     private LinkedList currentLineCache = new LinkedList();
105     private FontRenderContext frc;
106     private float currentHeight;
107     private float currentWidth;
108     private int lineHeight;
109     private int ascent;
110     private int characterWidth;
111
112     /**
113      * Get the left-padded value for a number.
114      * @param number the number
115      * @param width the total width.
116      * @return the padded string.
117      */

118     public static String JavaDoc getPaddedValue(int number, int width) {
119
120         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
121         String JavaDoc value = String.valueOf(number);
122         int valueLength = value.length();
123         for (int i = valueLength; i < width; i++) {
124             buffer.append(' ');
125         }
126         buffer.append(value);
127         return buffer.toString();
128     }
129
130     /**
131      * Constructor.
132      * @param detailPane the parent detail pane.
133      */

134     public ByteCodeDisplay(ByteCodeDetailPane detailPane) {
135         this.detailPane = detailPane;
136
137         setupComponent();
138         setupEventHandlers();
139     }
140
141     // Scrollable
142

143     public Dimension getPreferredScrollableViewportSize() {
144         return null;
145     }
146
147     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
148
149         if (orientation == SwingConstants.HORIZONTAL) {
150             return 10;
151         } else {
152             if (lineHeight == 0) {
153                 return 1;
154             }
155             int currentY = ((JViewport)getParent()).getViewPosition().y;
156             float line = 1f * (currentY - MARGIN_Y) / lineHeight;
157             int targetLine = (int)(direction < 0 ? Math.floor(line) - 1: Math.ceil(line) + 1);
158             int targetY = MARGIN_Y + targetLine * lineHeight + 1;
159             return Math.abs(currentY - targetY);
160         }
161     }
162
163     public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
164
165         JViewport viewport = (JViewport)getParent();
166         if (orientation == SwingConstants.HORIZONTAL) {
167             return viewport.getWidth();
168         } else {
169             if (lineHeight == 0) {
170                 return 1;
171             }
172             int currentY = viewport.getViewPosition().y;
173             int rawTargetY = currentY + (direction < 0 ? -1 : 1) * viewport.getHeight();
174             float line = 1f * (rawTargetY - MARGIN_Y) / lineHeight;
175             int targetLine = (int)(direction < 0 ? Math.ceil(line): Math.floor(line));
176             int targetY = MARGIN_Y + targetLine * lineHeight + 1;
177
178             return Math.abs(currentY - targetY);
179         }
180     }
181
182     public boolean getScrollableTracksViewportWidth() {
183         return false;
184     }
185
186     public boolean getScrollableTracksViewportHeight() {
187         return false;
188     }
189
190     // end Scrollable
191

192
193     /**
194      * Get the currently displayed code attribute.
195      * @return the code attribute.
196      */

197     public CodeAttribute getCodeAttribute() {
198         return codeAttribute;
199     }
200
201     /**
202      * Get the current line count.
203      * @return the line count.
204      */

205     public int getLineCount() {
206         return lines.size();
207     }
208
209     /**
210      * Get the current line height.
211      * @return the line height.
212      */

213     public int getLineHeight() {
214         return lineHeight;
215     }
216
217     /**
218      * Get the curent line ascent.
219      * @return the line ascent.
220      */

221     public int getAscent() {
222         return ascent;
223     }
224
225     /**
226      * Set the code attribute that is to be displayed.
227      * @param codeAttribute the code attribute.
228      * @param classFile the class file of the code attribute.
229      */

230     public void setCodeAttribute(CodeAttribute codeAttribute, ClassFile classFile) {
231         this.codeAttribute = codeAttribute;
232         this.classFile = classFile;
233         frc = ((Graphics2D)getGraphics()).getFontRenderContext();
234         setupTextLayouts();
235         invalidate();
236     }
237
238     /**
239      * Perform a link operation at a given point. Does nothing if there is no
240      * link at this point.
241      * @param point the point.
242      */

243     public void link(Point point) {
244
245         BytecodeLink link = getLink(point);
246         if (link == null) {
247             return;
248         }
249         updateHistory(link.sourceOffset);
250
251         if (link instanceof ConstantPoolLink) {
252             ConstantPoolHyperlinkListener.link(detailPane.getBrowserServices(), ((ConstantPoolLink)link).cpIndex);
253         } else if (link instanceof OffsetLink) {
254             int targetOffset = ((OffsetLink)link).targetOffset;
255             scrollToOffset(targetOffset);
256             updateHistory(targetOffset);
257         }
258     }
259
260     /**
261      * Returns whether there is a link below the given point.
262      * @param point the point.
263      * @return the value.
264      */

265     public boolean isLink(Point point) {
266         return getLink(point) != null;
267     }
268
269     /**
270      * Scroll the view to a given bytecode offset.
271      * @param offset the bytecode offset.
272      */

273     public void scrollToOffset(int offset) {
274
275         Integer JavaDoc line = (Integer JavaDoc)offsetToLine.get(new Integer JavaDoc(offset));
276         if (line == null) {
277             return;
278         }
279         Rectangle target = new Rectangle(0, line.intValue() * lineHeight + MARGIN_Y + 1, 10, getParent().getHeight());
280         scrollRectToVisible(target);
281     }
282
283     /**
284      * Copy the view text to the clipboard.
285      */

286     public void copyToClipboard() {
287
288         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
289         Iterator it = textLines.iterator();
290         while (it.hasNext()) {
291             String JavaDoc line = (String JavaDoc)it.next();
292             buffer.append(line);
293             buffer.append('\n');
294         }
295         StringSelection JavaDoc stringSelection = new StringSelection JavaDoc(buffer.toString());
296         Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, stringSelection);
297     }
298
299     protected void paintComponent(Graphics graphics) {
300
301         if (lineHeight == 0) {
302             return;
303         }
304
305         Graphics2D g = (Graphics2D)graphics;
306         g.translate(MARGIN_X, MARGIN_Y);
307         Rectangle clipBounds = graphics.getClipBounds();
308         Paint oldPaint = g.getPaint();
309         g.setPaint(Color.WHITE);
310         g.fill(clipBounds);
311         g.setPaint(oldPaint);
312         int startLine = Math.max(0, clipBounds.y / lineHeight - 1);
313         int endLine = Math.min(lines.size(), (clipBounds.y + clipBounds.height) / lineHeight + 1);
314         for (int i = startLine; i < endLine; i++) {
315             TextLayout textLayout = getOrCreateTextLayout(i);
316             textLayout.draw(g, 0, i * lineHeight + textLayout.getAscent());
317         }
318
319         g.translate(-MARGIN_X, -MARGIN_Y);
320     }
321
322     private TextLayout getOrCreateTextLayout(int i) {
323
324         TextLayout textLayout = textLayouts[i];
325         if (textLayout == null) {
326             textLayout = textLayouts[i] = new TextLayout(((AttributedString JavaDoc)lines.get(i)).getIterator(), frc);
327         }
328         return textLayout;
329     }
330
331     private void setupComponent() {
332
333         setBorder(BORDER);
334         setDoubleBuffered(false);
335         setOpaque(false);
336     }
337
338     private void setupEventHandlers() {
339     }
340
341     private BytecodeLink getLink(Point point) {
342
343         if (lineHeight == 0) {
344             return null;
345         }
346         int x = point.x - MARGIN_X;
347         int y = point.y - MARGIN_Y;
348         int line = y / lineHeight;
349         BytecodeLink link = (BytecodeLink)lineToLink.get(new Integer JavaDoc(line));
350         if (link == null) {
351             return null;
352         }
353
354         TextLayout textLayout = getOrCreateTextLayout(line);
355         TextHitInfo textHitInfo = textLayout.hitTestChar(x, y - line * lineHeight);
356         int charIndex = textHitInfo.getCharIndex();
357         if (charIndex >= link.startCharIndex && charIndex < link.endCharIndex) {
358             return link;
359         } else {
360             return null;
361         }
362     }
363
364     private void updateHistory(int offset) {
365
366         BrowserServices services = detailPane.getBrowserServices();
367         TreePath JavaDoc treePath = services.getBrowserComponent().getTreePane().getTree().getSelectionPath();
368
369         BrowserHistory history = services.getBrowserComponent().getHistory();
370         history.updateHistory(treePath, new Integer JavaDoc(offset));
371     }
372
373     private void setupTextLayouts() {
374
375         lineHeight = 0;
376         currentHeight = 0f;
377         currentWidth = 0f;
378         textLines.clear();
379         lines.clear();
380         textLayouts = null;
381         offsetToLine.clear();
382         lineToLink.clear();
383
384
385         byte[] code = codeAttribute.getCode();
386
387         try {
388             java.util.List JavaDoc instructions = ByteCodeReader.readByteCode(code);
389
390             calculateOffsetWidth(instructions);
391
392             Iterator it = instructions.iterator();
393             AbstractInstruction currentInstruction;
394             while (it.hasNext()) {
395                 currentInstruction = (AbstractInstruction)it.next();
396                 addInstructionToDocument(currentInstruction);
397             }
398             textLayouts = new TextLayout[lines.size()];
399         } catch (IOException JavaDoc ex) {
400             ex.printStackTrace();
401         }
402         setPreferredSize(new Dimension((int)currentWidth + 2 * MARGIN_X, (int)currentHeight + 2 * MARGIN_Y));
403     }
404
405     private void calculateOffsetWidth(java.util.List JavaDoc instructions) {
406
407         int numberOfInstructions = instructions.size();
408
409         if (numberOfInstructions > 0) {
410             AbstractInstruction lastInstruction = (AbstractInstruction)instructions.get(numberOfInstructions - 1);
411             offsetWidth = String.valueOf(lastInstruction.getOffset()).length();
412         } else {
413             offsetWidth = 1;
414         }
415         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(offsetWidth);
416         for (int i = 0; i < offsetWidth; i++) {
417             buffer.append(' ');
418         }
419         offsetBlank = buffer.toString();
420     }
421
422
423     private void addInstructionToDocument(AbstractInstruction instruction) {
424
425         int offset = instruction.getOffset();
426
427         addOffsetReference(offset);
428
429         appendString(getPaddedValue(offset, offsetWidth),
430                 STYLE_OFFSET);
431
432         appendString(" " + instruction.getOpcodeVerbose(),
433                 STYLE_INSTRUCTION);
434
435         addOpcodeSpecificInfo(instruction);
436
437         newLine();
438
439     }
440
441     private void addOffsetReference(int offset) {
442
443         offsetToLine.put(new Integer JavaDoc(offset),
444                 new Integer JavaDoc(getCurrentLine()));
445     }
446
447     private void addOpcodeSpecificInfo(AbstractInstruction instruction) {
448
449         if (instruction instanceof ImmediateByteInstruction) {
450             addImmediateByteSpecificInfo((ImmediateByteInstruction)instruction);
451         } else if (instruction instanceof ImmediateShortInstruction) {
452             addImmediateShortSpecificInfo((ImmediateShortInstruction)instruction);
453         } else if (instruction instanceof ImmediateIntInstruction) {
454             addImmediateIntSpecificInfo((ImmediateIntInstruction)instruction);
455         } else if (instruction instanceof BranchInstruction) {
456             addBranchSpecificInfo((BranchInstruction)instruction);
457         } else if (instruction instanceof TableSwitchInstruction) {
458             addTableSwitchSpecificInfo((TableSwitchInstruction)instruction);
459         } else if (instruction instanceof LookupSwitchInstruction) {
460             addLookupSwitchSpecificInfo((LookupSwitchInstruction)instruction);
461         }
462     }
463
464     private void addImmediateByteSpecificInfo(ImmediateByteInstruction instruction) {
465
466         int opcode = instruction.getOpcode();
467         int sourceOffset = instruction.getOffset();
468         int immediateByte = instruction.getImmediateByte();
469
470         if (opcode == Opcodes.OPCODE_LDC) {
471             addConstantPoolLink(immediateByte, sourceOffset);
472         } else if (opcode == Opcodes.OPCODE_NEWARRAY) {
473             String JavaDoc verbose = OpcodesUtil.getArrayTypeVerbose(immediateByte);
474             appendString(" " + immediateByte + " (" + verbose + ")",
475                     STYLE_IMMEDIATE_VALUE);
476
477         } else {
478             appendString(" " + immediateByte,
479                     STYLE_IMMEDIATE_VALUE);
480
481             if (instruction instanceof IncrementInstruction) {
482                 appendString(" by", STYLE_NORMAL);
483                 appendString(" " + ((IncrementInstruction)instruction).getIncrementConst(),
484                         STYLE_IMMEDIATE_VALUE);
485             }
486         }
487     }
488
489     private void addImmediateShortSpecificInfo(ImmediateShortInstruction instruction) {
490
491         int opcode = instruction.getOpcode();
492         int sourceOffset = instruction.getOffset();
493         int immediateShort = instruction.getImmediateShort();
494
495         if (opcode == Opcodes.OPCODE_SIPUSH) {
496             appendString(" " + immediateShort,
497                     STYLE_IMMEDIATE_VALUE);
498         } else {
499             addConstantPoolLink(immediateShort, sourceOffset);
500
501             if (instruction instanceof InvokeInterfaceInstruction) {
502                 appendString(" count " + ((InvokeInterfaceInstruction)instruction).getCount(),
503                         STYLE_IMMEDIATE_VALUE);
504
505             } else if (instruction instanceof MultianewarrayInstruction) {
506                 appendString(" dim " + ((MultianewarrayInstruction)instruction).getDimensions(),
507                         STYLE_IMMEDIATE_VALUE);
508
509             }
510         }
511
512     }
513
514     private void addImmediateIntSpecificInfo(ImmediateIntInstruction instruction) {
515
516         int immediateInt = instruction.getImmediateInt();
517         int sourceOffset = instruction.getOffset();
518
519         addConstantPoolLink(immediateInt, sourceOffset);
520
521     }
522
523     private void addBranchSpecificInfo(BranchInstruction instruction) {
524
525         int branchOffset = instruction.getBranchOffset();
526         int instructionOffset = instruction.getOffset();
527
528         addOffsetLink(branchOffset, instructionOffset);
529
530     }
531
532     private void addTableSwitchSpecificInfo(TableSwitchInstruction instruction) {
533
534         int instructionOffset = instruction.getOffset();
535         int lowByte = instruction.getLowByte();
536         int highByte = instruction.getHighByte();
537         int[] jumpOffsets = instruction.getJumpOffsets();
538
539         appendString(" " + lowByte + " to " + highByte, STYLE_IMMEDIATE_VALUE);
540         newLine();
541
542         for (int i = 0; i <= highByte - lowByte; i++) {
543             appendString(offsetBlank + TAB_STRING + (i + lowByte) + ": ", STYLE_IMMEDIATE_VALUE);
544             addOffsetLink(jumpOffsets[i], instructionOffset);
545             newLine();
546
547         }
548         appendString(offsetBlank + TAB_STRING + "default: ", STYLE_IMMEDIATE_VALUE);
549         addOffsetLink(instruction.getDefaultOffset(), instructionOffset);
550
551     }
552
553     private void addLookupSwitchSpecificInfo(LookupSwitchInstruction instruction) {
554
555         int instructionOffset = instruction.getOffset();
556         java.util.List JavaDoc matchOffsetPairs = instruction.getMatchOffsetPairs();
557         int matchOffsetPairsCount = matchOffsetPairs.size();
558
559         appendString(" " + matchOffsetPairsCount, STYLE_IMMEDIATE_VALUE);
560         newLine();
561
562         MatchOffsetPair matchOffsetPairEntry;
563         for (int i = 0; i < matchOffsetPairsCount; i++) {
564             matchOffsetPairEntry = (MatchOffsetPair)matchOffsetPairs.get(i);
565             appendString(offsetBlank + TAB_STRING + matchOffsetPairEntry.getMatch() + ": ",
566                     STYLE_IMMEDIATE_VALUE);
567             addOffsetLink(matchOffsetPairEntry.getOffset(), instructionOffset);
568             newLine();
569
570         }
571         appendString(offsetBlank + TAB_STRING + "default: ", STYLE_IMMEDIATE_VALUE);
572         addOffsetLink(instruction.getDefaultOffset(), instructionOffset);
573
574     }
575
576     private void addConstantPoolLink(int constantPoolIndex, int sourceOffset) {
577
578         appendString(" ", STYLE_NORMAL);
579         int startCharIndex = getCurrentCharIndex();
580         appendString("#" + constantPoolIndex, STYLE_LINK);
581         int endCharIndex = getCurrentCharIndex();
582         lineToLink.put(new Integer JavaDoc(getCurrentLine()), new ConstantPoolLink(startCharIndex, endCharIndex, sourceOffset, constantPoolIndex));
583
584         try {
585             String JavaDoc name = classFile.getConstantPoolEntryName(constantPoolIndex);
586             if (name.length() > 0) {
587                 appendString(" <" + name + ">", STYLE_SMALL);
588             }
589         } catch (InvalidByteCodeException ex) {
590         }
591     }
592
593     private void addOffsetLink(int branchOffset, int sourceOffset) {
594
595         int targetOffset = branchOffset + sourceOffset;
596
597         appendString(" ", STYLE_NORMAL);
598         int startCharIndex = getCurrentCharIndex();
599         appendString(String.valueOf(targetOffset), STYLE_LINK);
600         int endCharIndex = getCurrentCharIndex();
601         lineToLink.put(new Integer JavaDoc(getCurrentLine()), new OffsetLink(startCharIndex, endCharIndex, sourceOffset, targetOffset));
602
603         appendString(" (" + (branchOffset > 0 ? "+" : "") + String.valueOf(branchOffset) + ")",
604                 STYLE_IMMEDIATE_VALUE);
605     }
606
607     private int getCurrentCharIndex() {
608
609         Iterator it = currentLineCache.iterator();
610         int offset = 0;
611         while (it.hasNext()) {
612             LineCacheEntry entry = (LineCacheEntry)it.next();
613             offset += entry.text.length();
614         }
615         return offset;
616     }
617
618     private int getCurrentLine() {
619         return lines.size();
620     }
621
622     private void appendString(String JavaDoc text, Map attributes) {
623         currentLineCache.add(new LineCacheEntry(text, attributes));
624     }
625
626     private void newLine() {
627
628         String JavaDoc text = getCurrentLineText();
629         AttributedString JavaDoc attrString = new AttributedString JavaDoc(text, STYLE_BASE);
630         Iterator it = currentLineCache.iterator();
631         int startCharIndex = 0;
632         while (it.hasNext()) {
633             LineCacheEntry entry = (LineCacheEntry)it.next();
634             int endCharIndex = startCharIndex + entry.text.length();
635             attrString.addAttributes(entry.attributes, startCharIndex, endCharIndex);
636             startCharIndex = endCharIndex;
637         }
638         lines.add(attrString);
639         textLines.add(text);
640
641         if (lineHeight == 0) {
642             TextLayout textLayout = new TextLayout(attrString.getIterator(), frc);
643             lineHeight = (int)(textLayout.getAscent() + textLayout.getDescent() + textLayout.getLeading());
644             ascent = (int)textLayout.getAscent();
645             textLayout = new TextLayout("0", STYLE_BASE, frc);
646             characterWidth = (int)textLayout.getAdvance();
647         }
648         currentHeight += lineHeight;
649         currentWidth = Math.max(currentWidth, characterWidth * text.length());
650
651         currentLineCache.clear();
652     }
653
654     private String JavaDoc getCurrentLineText() {
655
656         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(getCurrentLineLength());
657         Iterator it = currentLineCache.iterator();
658         while (it.hasNext()) {
659             LineCacheEntry entry = (LineCacheEntry)it.next();
660             buffer.append(entry.text);
661         }
662         return buffer.toString();
663     }
664
665     private int getCurrentLineLength() {
666
667         int length = 0;
668         Iterator it = currentLineCache.iterator();
669         while (it.hasNext()) {
670             LineCacheEntry entry = (LineCacheEntry)it.next();
671             length += entry.text.length();
672         }
673         return length;
674     }
675
676     private static class LineCacheEntry {
677
678         private String JavaDoc text;
679         private Map attributes;
680
681         private LineCacheEntry(String JavaDoc text, Map attributes) {
682             this.text = text;
683             this.attributes = attributes;
684         }
685     }
686
687     private static class BytecodeLink {
688
689         private int startCharIndex;
690         private int endCharIndex;
691         protected int sourceOffset;
692
693         private BytecodeLink(int startCharIndex, int endCharIndex, int sourceOffset) {
694             this.startCharIndex = startCharIndex;
695             this.endCharIndex = endCharIndex;
696             this.sourceOffset = sourceOffset;
697         }
698     }
699
700     private static class ConstantPoolLink extends BytecodeLink {
701
702         private int cpIndex;
703
704         private ConstantPoolLink(int startCharIndex, int endCharIndex, int sourceOffset, int cpIndex) {
705             super(startCharIndex, endCharIndex, sourceOffset);
706             this.cpIndex = cpIndex;
707         }
708
709     }
710
711     private static class OffsetLink extends BytecodeLink {
712
713         private int targetOffset;
714
715         private OffsetLink(int startCharIndex, int endCharIndex, int sourceOffset, int targetOffset) {
716             super(startCharIndex, endCharIndex, sourceOffset);
717             this.targetOffset = targetOffset;
718         }
719
720     }
721
722 }
723
Popular Tags