Source Code Cross Referenced for BytecodeClassFileEditor.java in  » Byte-Code » asm » de » loskutov » bco » editors » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Byte Code » asm » de.loskutov.bco.editors 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* $Id: BytecodeClassFileEditor.java,v 1.7 2007-10-05 22:05:41 andrei Exp $ */
002:
003:        package de.loskutov.bco.editors;
004:
005:        import java.lang.reflect.Constructor;
006:        import java.util.BitSet;
007:
008:        import org.eclipse.core.resources.IFile;
009:        import org.eclipse.core.runtime.CoreException;
010:        import org.eclipse.core.runtime.IStatus;
011:        import org.eclipse.debug.core.DebugException;
012:        import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget;
013:        import org.eclipse.jdt.core.IBuffer;
014:        import org.eclipse.jdt.core.IBufferChangedListener;
015:        import org.eclipse.jdt.core.IClassFile;
016:        import org.eclipse.jdt.core.IInitializer;
017:        import org.eclipse.jdt.core.IJavaElement;
018:        import org.eclipse.jdt.core.IJavaModelStatusConstants;
019:        import org.eclipse.jdt.core.IMember;
020:        import org.eclipse.jdt.core.IMethod;
021:        import org.eclipse.jdt.core.ISourceRange;
022:        import org.eclipse.jdt.core.ISourceReference;
023:        import org.eclipse.jdt.core.IType;
024:        import org.eclipse.jdt.core.JavaModelException;
025:        import org.eclipse.jdt.core.dom.CompilationUnit;
026:        import org.eclipse.jdt.debug.core.IJavaReferenceType;
027:        import org.eclipse.jdt.internal.ui.JavaPlugin;
028:        import org.eclipse.jdt.internal.ui.JavaUIStatus;
029:        import org.eclipse.jdt.internal.ui.javaeditor.ClassFileDocumentProvider;
030:        import org.eclipse.jdt.internal.ui.javaeditor.ExternalClassFileEditorInput;
031:        import org.eclipse.jdt.internal.ui.javaeditor.IClassFileEditorInput;
032:        import org.eclipse.jdt.internal.ui.javaeditor.InternalClassFileEditorInput;
033:        import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
034:        import org.eclipse.jface.text.BadLocationException;
035:        import org.eclipse.jface.text.IDocument;
036:        import org.eclipse.jface.text.IRegion;
037:        import org.eclipse.jface.text.ITextSelection;
038:        import org.eclipse.jface.text.ITextViewerExtension5;
039:        import org.eclipse.jface.text.Region;
040:        import org.eclipse.jface.text.TextSelection;
041:        import org.eclipse.jface.text.source.ISourceViewer;
042:        import org.eclipse.swt.SWT;
043:        import org.eclipse.swt.custom.StackLayout;
044:        import org.eclipse.swt.custom.StyledText;
045:        import org.eclipse.swt.layout.FillLayout;
046:        import org.eclipse.swt.widgets.Composite;
047:        import org.eclipse.ui.IEditorInput;
048:        import org.eclipse.ui.IEditorPart;
049:        import org.eclipse.ui.IEditorReference;
050:        import org.eclipse.ui.IEditorSite;
051:        import org.eclipse.ui.IFileEditorInput;
052:        import org.eclipse.ui.PartInitException;
053:        import org.eclipse.ui.PlatformUI;
054:        import org.eclipse.ui.part.FileEditorInput;
055:        import org.eclipse.ui.texteditor.IDocumentProvider;
056:
057:        import de.loskutov.bco.BytecodeOutlinePlugin;
058:        import de.loskutov.bco.asm.DecompiledClass;
059:        import de.loskutov.bco.preferences.BCOConstants;
060:        import de.loskutov.bco.ui.JdtUtils;
061:
062:        /**
063:         * A "better" way to hook into JDT...
064:         * @author Eugene Kuleshov, V. Grishchenko, Jochen Klein, Andrei Loskutov
065:         */
066:        public class BytecodeClassFileEditor extends JavaEditor implements 
067:                ClassFileDocumentProvider.InputChangeListener {
068:
069:            private StackLayout fStackLayout;
070:            private Composite fParent;
071:            private Composite fViewerComposite;
072:            private InputUpdater fInputUpdater;
073:            public static final String ID = "de.loskutov.bco.editors.BytecodeClassFileEditor";
074:            public static final String MARK = "// class version ";
075:            /** the modes (flags) for the decompiler */
076:            private BitSet decompilerFlags;
077:            /** is not null only on class files with decompiled source */
078:            private static BytecodeSourceMapper sourceMapper;
079:            private BytecodeDocumentProvider fClassFileDocumentProvider;
080:            private boolean hasMappedSource;
081:            private boolean decompiled;
082:            private boolean initDone;
083:
084:            /**
085:             * Constructor for JadclipseClassFileEditor.
086:             */
087:            public BytecodeClassFileEditor() {
088:                super ();
089:                if (sourceMapper == null) {
090:                    sourceMapper = new BytecodeSourceMapper();
091:                }
092:                fInputUpdater = new InputUpdater();
093:                setDocumentProvider(getClassFileDocumentProvider());
094:                setEditorContextMenuId("#ClassFileEditorContext"); //$NON-NLS-1$
095:                setRulerContextMenuId("#ClassFileRulerContext"); //$NON-NLS-1$
096:                setOutlinerContextMenuId("#ClassFileOutlinerContext"); //$NON-NLS-1$
097:                // don't set help contextId, we install our own help context
098:
099:                decompilerFlags = new BitSet();
100:                // TODO take from preferences and/or last editor memento
101:                decompilerFlags.set(BCOConstants.F_SHOW_LINE_INFO, true);
102:                decompilerFlags.set(BCOConstants.F_SHOW_VARIABLES, true);
103:                decompilerFlags.set(BCOConstants.F_SHOW_RAW_BYTECODE, false);
104:            }
105:
106:            /**
107:             * @return the hasMappedSource
108:             */
109:            protected boolean hasMappedSource() {
110:                return hasMappedSource;
111:            }
112:
113:            /**
114:             * @param hasMappedSource the hasMappedSource to set
115:             */
116:            protected void setHasMappedSource(boolean hasMappedSource) {
117:                this .hasMappedSource = hasMappedSource;
118:            }
119:
120:            private ClassFileDocumentProvider getClassFileDocumentProvider() {
121:                if (fClassFileDocumentProvider == null) {
122:                    fClassFileDocumentProvider = new BytecodeDocumentProvider(
123:                            this );
124:                }
125:                return fClassFileDocumentProvider;
126:            }
127:
128:            public void setDecompilerFlag(int flag, boolean value) {
129:                decompilerFlags.set(flag, value);
130:            }
131:
132:            public boolean getDecompilerFlag(int flag) {
133:                return decompilerFlags.get(flag);
134:            }
135:
136:            /*
137:             * @see IEditorPart#init(IEditorSite, IEditorInput)
138:             */
139:            public void init(IEditorSite site, IEditorInput input)
140:                    throws PartInitException {
141:                input = doOpenBuffer(input, false, true);
142:                super .init(site, input);
143:            }
144:
145:            /**
146:             * Sets editor input only if buffer was actually opened.
147:             * @param force if <code>true</code> initialize no matter what
148:             * @param reuseSource true to show source code if available
149:             */
150:            public void doSetInput(boolean force, boolean reuseSource) {
151:                IEditorInput input = getEditorInput();
152:                input = doOpenBuffer(input, force, reuseSource);
153:                if (input != null) {
154:                    try {
155:                        doSetInput(input);
156:                    } catch (Exception e) {
157:                        BytecodeOutlinePlugin.log(e, IStatus.ERROR);
158:                    }
159:                }
160:            }
161:
162:            /*
163:             * @see AbstractTextEditor#doSetInput(IEditorInput)
164:             * ClassFileDocumentProvider.setDocumentContent(IDocument, IEditorInput, String) line:
165:             * 202 ClassFileDocumentProvider(StorageDocumentProvider).createDocument(Object) line:
166:             * 228 ClassFileDocumentProvider.createDocument(Object) line: 247
167:             * ClassFileDocumentProvider.createElementInfo(Object) line: 275
168:             * ClassFileDocumentProvider(AbstractDocumentProvider).connect(Object) line: 398
169:             * BytecodeClassFileEditor(AbstractTextEditor).doSetInput(IEditorInput) line: 3063
170:             * BytecodeClassFileEditor(StatusTextEditor).doSetInput(IEditorInput) line: 173
171:             * BytecodeClassFileEditor(AbstractDecoratedTextEditor).doSetInput(IEditorInput) line:
172:             * 1511 BytecodeClassFileEditor(JavaEditor).internalDoSetInput(IEditorInput) line:
173:             * 2370 BytecodeClassFileEditor(JavaEditor).doSetInput(IEditorInput) line: 2343
174:             * BytecodeClassFileEditor.doSetInput(IEditorInput) line: 201
175:             * AbstractTextEditor$17.run(IProgressMonitor) line: 2396
176:             */
177:            protected void doSetInput(IEditorInput input) throws CoreException {
178:
179:                input = transformEditorInput(input);
180:                if (!(input instanceof  IClassFileEditorInput)) {
181:                    throw new CoreException(JavaUIStatus.createError(
182:                            IJavaModelStatusConstants.INVALID_RESOURCE_TYPE,
183:                            "invalid input", // JavaEditorMessages.ClassFileEditor_error_invalid_input_message,
184:                            null));
185:                }
186:
187:                IDocumentProvider documentProvider = getDocumentProvider();
188:                if (documentProvider instanceof  ClassFileDocumentProvider) {
189:                    ((ClassFileDocumentProvider) documentProvider)
190:                            .removeInputChangeListener(this );
191:                }
192:
193:                super .doSetInput(input);
194:
195:                documentProvider = getDocumentProvider();
196:                if (documentProvider instanceof  ClassFileDocumentProvider) {
197:                    ((ClassFileDocumentProvider) documentProvider)
198:                            .addInputChangeListener(this );
199:                }
200:            }
201:
202:            /**
203:             * @return <code>true</code> if this editor displays decompiled source,
204:             * <code>false</code> otherwise
205:             */
206:            public boolean isDecompiled() {
207:                return decompiled;
208:            }
209:
210:            private IEditorInput doOpenBuffer(IJavaReferenceType type,
211:                    IClassFile parent, boolean externalClass) {
212:                IClassFile classFile = null;
213:                try {
214:                    classFile = JdtUtils.getInnerType(parent, getSourceMapper()
215:                            .getDecompiledClass(parent), type.getSignature());
216:                } catch (DebugException e) {
217:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
218:                }
219:                return doOpenBuffer(classFile, externalClass);
220:            }
221:
222:            private IEditorInput doOpenBuffer(IClassFile classFile,
223:                    boolean externalClass) {
224:                IEditorInput input = null;
225:                if (classFile == null) {
226:                    return null;
227:                }
228:                if (externalClass) {
229:                    // TODO create external input, but we need a file object here...
230:                } else {
231:                    input = transformEditorInput(classFile);
232:                }
233:                return doOpenBuffer(input, false, true);
234:            }
235:
236:            private IEditorInput doOpenBuffer(IEditorInput input,
237:                    boolean force, boolean reuseSource) {
238:                if (input instanceof  IClassFileEditorInput) {
239:                    IClassFile cf = ((IClassFileEditorInput) input)
240:                            .getClassFile();
241:                    String origSrc = getAttachedJavaSource(cf, force);
242:                    if (origSrc != null && !hasMappedSource) {
243:                        // remember, that the JDT knows where the real source is and can show it
244:                        setHasMappedSource(true);
245:                    }
246:
247:                    if (origSrc == null || (force && !reuseSource)) {
248:                        setDecompiled(true);
249:                        char[] src;
250:                        if (input instanceof  ExternalClassFileEditorInput) {
251:                            ExternalClassFileEditorInput extInput = (ExternalClassFileEditorInput) input;
252:                            src = getSourceMapper().getSource(
253:                                    extInput.getFile(), cf, decompilerFlags);
254:                        } else {
255:                            src = getSourceMapper().getSource(cf,
256:                                    decompilerFlags);
257:                        }
258:                        changeBufferContent(cf, src);
259:                    } else {
260:                        setDecompiled(false);
261:                    }
262:                } else if (input instanceof  FileEditorInput) {
263:                    FileEditorInput fileEditorInput = (FileEditorInput) input;
264:                    // make class file from that
265:                    IClassFileEditorInput cfi = transformEditorInput(input);
266:                    // return changed reference
267:                    input = cfi;
268:                    setDecompiled(true);
269:                    IClassFile cf = cfi.getClassFile();
270:                    char[] src = getSourceMapper().getSource(
271:                            fileEditorInput.getFile(), cf, decompilerFlags);
272:                    changeBufferContent(cf, src);
273:                }
274:                return input;
275:            }
276:
277:            private void setDecompiled(boolean decompiled) {
278:                boolean oldDecompiled = this .decompiled;
279:                this .decompiled = decompiled;
280:                if (initDone && oldDecompiled != decompiled) {
281:                    if (decompiled) {
282:                        // prevent multiple errors in ASTProvider which fails to work without source
283:                        uninstallOccurrencesFinder();
284:                    } else {
285:                        // install again if source is available
286:                        installOccurrencesFinder(true);
287:                    }
288:                }
289:            }
290:
291:            private String getAttachedJavaSource(IClassFile cf, boolean force) {
292:                String origSrc = null;
293:                if (force) {
294:                    IBuffer buffer = BytecodeBufferManager.getBuffer(cf);
295:                    if (buffer != null) {
296:                        BytecodeBufferManager.removeBuffer(buffer);
297:                    }
298:                }
299:                try {
300:                    origSrc = cf.getSource();
301:                    if (origSrc != null && origSrc.startsWith(MARK)) {
302:                        // this is NOT orig. sourse, but cached content
303:                        origSrc = null;
304:                    }
305:                } catch (JavaModelException e) {
306:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
307:                }
308:                return origSrc;
309:            }
310:
311:            private void changeBufferContent(IClassFile cf, char[] src) {
312:                IBuffer buffer = BytecodeBufferManager.getBuffer(cf);
313:
314:                // i'm not sure if we need to create buffer each time -
315:                // couldn't we reuse existing one (if any)?
316:                // - seems that without "create" some listener didn't get notifications about
317:                // changed content
318:                boolean addBuffer = false;
319:
320:                // if(buffer == null) {
321:                buffer = BytecodeBufferManager.createBuffer(cf);
322:                addBuffer = true;
323:                // }
324:                if (src == null) {
325:                    src = new char[] { '\n', '/', '/', 'E', 'r', 'r', 'o', 'r' };
326:                }
327:                buffer.setContents(src);
328:                if (addBuffer) {
329:                    BytecodeBufferManager.addBuffer(buffer);
330:                    buffer
331:                            .addBufferChangedListener((IBufferChangedListener) cf);
332:                }
333:            }
334:
335:            /*
336:             * @see JavaEditor#getElementAt(int)
337:             */
338:            protected IJavaElement getElementAt(int offset) {
339:
340:                IClassFile classFile = getClassFile();
341:                if (classFile == null) {
342:                    return null;
343:                }
344:                IJavaElement result = null;
345:                if (isDecompiled()) {
346:                    IDocument document = getDocumentProvider().getDocument(
347:                            getEditorInput());
348:                    try {
349:                        int lineAtOffset = document.getLineOfOffset(offset);
350:                        // get DecompiledMethod from line, then get JavaElement with same
351:                        // signature, because we do not have offsets or lines in the class file,
352:                        // only java elements...
353:                        result = getSourceMapper().findElement(classFile,
354:                                lineAtOffset);
355:                    } catch (BadLocationException e) {
356:                        BytecodeOutlinePlugin.log(e, IStatus.ERROR);
357:                    }
358:                } else {
359:                    try {
360:                        result = classFile.getElementAt(offset);
361:                    } catch (JavaModelException e) {
362:                        BytecodeOutlinePlugin.log(e, IStatus.ERROR);
363:                    }
364:                }
365:
366:                return result;
367:            }
368:
369:            public IClassFile getClassFile() {
370:                IEditorInput editorInput = getEditorInput();
371:                if (!(editorInput instanceof  IClassFileEditorInput)) {
372:                    return null;
373:                }
374:                return ((IClassFileEditorInput) editorInput).getClassFile();
375:            }
376:
377:            protected void setSelection(ISourceReference reference,
378:                    boolean moveCursor) {
379:                if (reference == null) {
380:                    if (moveCursor) {
381:                        resetHighlightRange();
382:                    }
383:                    return;
384:                }
385:                try {
386:                    ISourceRange range = null;
387:                    int offset;
388:                    int length;
389:                    if (isDecompiled() && isSupportedMember(reference)) {
390:
391:                        // document lines count starts with 1 and not with 0
392:                        int decompLine = -1
393:                                + getSourceMapper().getDecompiledLine(
394:                                        (IMember) reference, getClassFile());
395:                        if (decompLine < 0) {
396:                            return;
397:                        }
398:                        IRegion region = ((BytecodeDocumentProvider) getDocumentProvider())
399:                                .getDecompiledLineInfo(getEditorInput(),
400:                                        decompLine);
401:                        if (region == null) {
402:                            return;
403:                        }
404:                        offset = region.getOffset();
405:                        length = region.getLength();
406:                    } else if (!isDecompiled()) {
407:                        range = reference.getSourceRange();
408:                        if (range == null) {
409:                            return;
410:                        }
411:                        offset = range.getOffset();
412:                        length = range.getLength();
413:                    } else {
414:                        return;
415:                    }
416:
417:                    if (offset > -1 && length > 0) {
418:                        setHighlightRange(offset, length, moveCursor);
419:                    }
420:
421:                    if ((reference instanceof  IMember) && !isDecompiled()) {
422:                        IMember member = (IMember) reference;
423:                        range = member.getNameRange();
424:                        if (range != null) {
425:                            offset = range.getOffset();
426:                            length = range.getLength();
427:                        }
428:                    }
429:                    if (moveCursor && offset > -1 && length > 0) {
430:                        ISourceViewer sourceViewer = getSourceViewer();
431:                        if (sourceViewer != null) {
432:                            sourceViewer.revealRange(offset, length);
433:                            sourceViewer.setSelectedRange(offset, length);
434:                        }
435:                    }
436:                    return;
437:                } catch (Exception e) {
438:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
439:                }
440:
441:                if (moveCursor) {
442:                    resetHighlightRange();
443:                }
444:            }
445:
446:            private boolean isSupportedMember(ISourceReference reference) {
447:                // TODO this condition is not enough. We could have inner/anon. classes
448:                // as selection source (they are displayed in the outline),
449:                // but they are not in the decompiled class,
450:                // so we need to filter "external" elements too, even if they are methods...
451:
452:                // we could also later point to the IField's, but currently it is not supported
453:                return reference instanceof  IMethod
454:                        || reference instanceof  IInitializer;
455:            }
456:
457:            public Object getAdapter(Class required) {
458:                if (IToggleBreakpointsTarget.class == required) {
459:
460:                    // TODO implement own adapter for toggle breakpoints, because the default one
461:                    // could not find java elements in our document and therefore could not
462:                    // create a Java breakpoint.
463:                    // see org.eclipse.jdt.internal.debug.ui.actions.ToggleBreakpointAdapter
464:                    // IMember member =
465:                    // ActionDelegateHelper.getDefault().getCurrentMember(selection);
466:                    // and the ActionDelegateHelper looks with the given offset at classfile or
467:                    // compilation unit, but our offset is completely different to Java source
468:                    // code
469:                    super .getAdapter(required);
470:                }
471:
472:                return super .getAdapter(required);
473:            }
474:
475:            /*
476:             * Overriden to prevent NPE on SourceReference objects without associated source
477:             * ranges, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=142936
478:             * @see JavaEditor#adjustHighlightRange(int, int)
479:             */
480:            protected void adjustHighlightRange(int offset, int length) {
481:                try {
482:
483:                    IJavaElement element = getElementAt(offset);
484:                    while (element instanceof  ISourceReference) {
485:                        ISourceRange range = ((ISourceReference) element)
486:                                .getSourceRange();
487:                        // range != null is the only one change we need here
488:                        if (range != null
489:                                && (offset < range.getOffset()
490:                                        + range.getLength() && range
491:                                        .getOffset() < offset + length)) {
492:
493:                            ISourceViewer viewer = getSourceViewer();
494:                            if (viewer instanceof  ITextViewerExtension5) {
495:                                ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
496:                                extension.exposeModelRange(new Region(range
497:                                        .getOffset(), range.getLength()));
498:                            }
499:
500:                            setHighlightRange(range.getOffset(), range
501:                                    .getLength(), true);
502:                            if (fOutlinePage != null) {
503:                                fOutlineSelectionChangedListener
504:                                        .uninstall(fOutlinePage);
505:                                fOutlinePage.select((ISourceReference) element);
506:                                fOutlineSelectionChangedListener
507:                                        .install(fOutlinePage);
508:                            }
509:
510:                            return;
511:                        }
512:                        element = element.getParent();
513:                    }
514:
515:                } catch (JavaModelException x) {
516:                    JavaPlugin.log(x.getStatus());
517:                }
518:
519:                ISourceViewer viewer = getSourceViewer();
520:                if (viewer instanceof  ITextViewerExtension5) {
521:                    ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
522:                    extension.exposeModelRange(new Region(offset, length));
523:                } else {
524:                    resetHighlightRange();
525:                }
526:
527:            }
528:
529:            /*
530:             * (non-Javadoc)
531:             * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#computeHighlightRangeSourceReference()
532:             */
533:            protected ISourceReference computeHighlightRangeSourceReference() {
534:                if (!isDecompiled()) {
535:                    return super .computeHighlightRangeSourceReference();
536:                }
537:
538:                ISourceViewer sourceViewer = getSourceViewer();
539:                if (sourceViewer == null) {
540:                    return null;
541:                }
542:                StyledText styledText = sourceViewer.getTextWidget();
543:                if (styledText == null) {
544:                    return null;
545:                }
546:
547:                int caret = 0;
548:                if (sourceViewer instanceof  ITextViewerExtension5) {
549:                    ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
550:                    caret = extension.widgetOffset2ModelOffset(styledText
551:                            .getCaretOffset());
552:                } else {
553:                    int offset = sourceViewer.getVisibleRegion().getOffset();
554:                    caret = offset + styledText.getCaretOffset();
555:                }
556:
557:                IJavaElement element = getElementAt(caret);
558:
559:                if (!(element instanceof  ISourceReference)) {
560:                    return null;
561:                }
562:                return (ISourceReference) element;
563:            }
564:
565:            public void showHighlightRangeOnly(boolean showHighlightRangeOnly) {
566:                // disabled as we currently do not support "partial" view on selected
567:                // elements
568:                // super.showHighlightRangeOnly(showHighlightRangeOnly);
569:            }
570:
571:            protected void updateOccurrenceAnnotations(
572:                    ITextSelection selection, CompilationUnit astRoot) {
573:                // disabled for bytecode as we currently do not support "occurencies" highlighting
574:                if (hasMappedSource()) {
575:                    super .updateOccurrenceAnnotations(selection, astRoot);
576:                }
577:            }
578:
579:            /**
580:             * Updater that takes care of minimizing changes of the editor input.
581:             */
582:            private class InputUpdater implements  Runnable {
583:
584:                /** Has the runnable already been posted? */
585:                private boolean fPosted = false;
586:                /** Editor input */
587:                private IClassFileEditorInput fClassFileEditorInput;
588:
589:                public InputUpdater() {
590:                    //
591:                }
592:
593:                /*
594:                 * @see Runnable#run()
595:                 */
596:                public void run() {
597:
598:                    IClassFileEditorInput input;
599:                    synchronized (this ) {
600:                        input = fClassFileEditorInput;
601:                    }
602:
603:                    try {
604:                        if (getSourceViewer() != null) {
605:                            setInput(input);
606:                        }
607:                    } finally {
608:                        synchronized (this ) {
609:                            fPosted = false;
610:                        }
611:                    }
612:                }
613:
614:                /**
615:                 * Posts this runnable into the event queue if not already there.
616:                 * @param input the input to be set when executed
617:                 */
618:                public void post(IClassFileEditorInput input) {
619:
620:                    synchronized (this ) {
621:                        if (fPosted) {
622:                            if (input != null
623:                                    && input.equals(fClassFileEditorInput)) {
624:                                fClassFileEditorInput = input;
625:                            }
626:                            return;
627:                        }
628:                    }
629:
630:                    if (input != null && input.equals(getEditorInput())) {
631:                        ISourceViewer viewer = getSourceViewer();
632:                        if (viewer != null) {
633:                            StyledText textWidget = viewer.getTextWidget();
634:                            if (textWidget != null && !textWidget.isDisposed()) {
635:                                synchronized (this ) {
636:                                    fPosted = true;
637:                                    fClassFileEditorInput = input;
638:                                }
639:                                textWidget.getDisplay().asyncExec(this );
640:                            }
641:                        }
642:                    }
643:                }
644:            }
645:
646:            /*
647:             * @see JavaEditor#getCorrespondingElement(IJavaElement)
648:             */
649:            protected IJavaElement getCorrespondingElement(IJavaElement element) {
650:                IClassFile classFile = getClassFile();
651:                if (classFile == null) {
652:                    return null;
653:                }
654:                if (classFile.equals(element
655:                        .getAncestor(IJavaElement.CLASS_FILE))) {
656:                    return element;
657:                }
658:                return null;
659:            }
660:
661:            /*
662:             * 1GEPKT5: ITPJUI:Linux - Source in editor for external classes is editable Removed
663:             * methods isSaveOnClosedNeeded and isDirty. Added method isEditable.
664:             */
665:            /*
666:             * @see org.eclipse.ui.texteditor.AbstractTextEditor#isEditable()
667:             */
668:            public boolean isEditable() {
669:                return isDecompiled();
670:            }
671:
672:            /*
673:             * @see org.eclipse.ui.texteditor.AbstractTextEditor#isEditorInputReadOnly()
674:             * @since 3.2
675:             */
676:            public boolean isEditorInputReadOnly() {
677:                return !isDecompiled();
678:            }
679:
680:            /*
681:             * @see ITextEditorExtension2#isEditorInputModifiable()
682:             * @since 2.1
683:             */
684:            public boolean isEditorInputModifiable() {
685:                return isDecompiled();
686:            }
687:
688:            public boolean isSaveAsAllowed() {
689:                return isDecompiled();
690:            }
691:
692:            /**
693:             * Translates the given object into an <code>IClassFileEditorInput</code>
694:             * @param input the object to be transformed if necessary
695:             * @return the transformed editor input
696:             */
697:            protected IClassFileEditorInput transformEditorInput(Object input) {
698:
699:                if (input instanceof  IFileEditorInput) {
700:                    IFile file = ((IFileEditorInput) input).getFile();
701:                    Constructor cons;
702:                    try {
703:                        cons = ExternalClassFileEditorInput.class
704:                                .getDeclaredConstructor(new Class[] { IFile.class });
705:                        cons.setAccessible(true);
706:                        IClassFileEditorInput classFileInput = (IClassFileEditorInput) cons
707:                                .newInstance(new Object[] { file });
708:                        return classFileInput;
709:                    } catch (Exception e) {
710:                        BytecodeOutlinePlugin.log(e, IStatus.ERROR);
711:                    }
712:                } else if (input instanceof  IClassFileEditorInput) {
713:                    return (IClassFileEditorInput) input;
714:                } else if (input instanceof  IClassFile) {
715:                    return new InternalClassFileEditorInput((IClassFile) input);
716:                }
717:
718:                return null;
719:            }
720:
721:            /*
722:             * @see IWorkbenchPart#createPartControl(Composite)
723:             */
724:            public void createPartControl(Composite parent) {
725:
726:                fParent = new Composite(parent, SWT.NONE);
727:                fStackLayout = new StackLayout();
728:                fParent.setLayout(fStackLayout);
729:
730:                fViewerComposite = new Composite(fParent, SWT.NONE);
731:                fViewerComposite.setLayout(new FillLayout());
732:
733:                super .createPartControl(fViewerComposite);
734:
735:                fStackLayout.topControl = fViewerComposite;
736:                fParent.layout();
737:                initDone = true;
738:            }
739:
740:            /*
741:             * @see ClassFileDocumentProvider.InputChangeListener#inputChanged(IClassFileEditorInput)
742:             */
743:            public void inputChanged(IClassFileEditorInput input) {
744:                fInputUpdater.post(input);
745:                IClassFile cf = input.getClassFile();
746:                String source;
747:                try {
748:                    source = cf.getSource();
749:                    setDecompiled(source != null && source.startsWith(MARK));
750:                } catch (JavaModelException e) {
751:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
752:                }
753:
754:            }
755:
756:            /*
757:             * @see org.eclipse.ui.IWorkbenchPart#dispose()
758:             */
759:            public void dispose() {
760:                // http://bugs.eclipse.org/bugs/show_bug.cgi?id=18510
761:                IDocumentProvider documentProvider = getDocumentProvider();
762:                if (documentProvider instanceof  ClassFileDocumentProvider) {
763:                    ((ClassFileDocumentProvider) documentProvider)
764:                            .removeInputChangeListener(this );
765:                }
766:
767:                IClassFile classFile = getClassFile();
768:                BytecodeBufferManager.removeBuffer(BytecodeBufferManager
769:                        .getBuffer(classFile));
770:                super .dispose();
771:            }
772:
773:            public static BytecodeSourceMapper getSourceMapper() {
774:                return sourceMapper;
775:            }
776:
777:            /**
778:             * Check if we can show an inner class, which was declared in the source code of the
779:             * given parent class and which could have the bytecode for the given source line.
780:             *
781:             * If both are true, then this method changes the input of the bytecode editor
782:             * with the given class file (if any) to the inner class, or opens a new editor with
783:             * the inner class.
784:             *
785:             * @param sourceLine requested source line (from debugger)
786:             * @param parent expected parent class file
787:             * @return The region in the inner class (if inner class could be found), or an empty
788:             * zero-based region.
789:             */
790:            public static IRegion checkForInnerClass(int sourceLine,
791:                    IClassFile parent) {
792:                IRegion region = new Region(0, 0);
793:
794:                // get the editor with given class file, if any
795:                BytecodeClassFileEditor editor = getBytecodeEditor(parent);
796:                if (editor == null) {
797:                    return region;
798:                }
799:
800:                // get the inner class type according to the debugger stack frame, if any
801:                IJavaReferenceType debugType = sourceMapper
802:                        .getLastTypeInDebugger();
803:                if (debugType == null) {
804:                    return region;
805:                }
806:
807:                boolean externalClass = editor.getEditorInput() instanceof  ExternalClassFileEditorInput;
808:                IEditorInput input = null;
809:                // check if it is a inner class from the class in editor
810:                if (!hasInnerClass(debugType, parent)) {
811:                    // not only inner classes could be defined in the same source file, but also
812:                    // local types (non public non inner classes in the same source file)
813:                    IClassFile classFile = getLocalTypeClass(debugType, parent);
814:                    if (classFile != null) {
815:                        input = editor.doOpenBuffer(classFile, externalClass);
816:                    }
817:                } else {
818:                    // if both exists, replace the input to the inner class
819:                    input = editor.doOpenBuffer(debugType, parent,
820:                            externalClass);
821:                }
822:
823:                if (input == null) {
824:                    return region;
825:                }
826:
827:                /*
828:                 * Now we change editor input from parent class to child class.
829:                 * It will change editor title too, so the user will see a new class.
830:                 * After this change, we could finally compute right source line for current stack
831:                 */
832:                try {
833:                    editor.doSetInput(input);
834:                } catch (CoreException e) {
835:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
836:                    return region;
837:                }
838:
839:                // and then map given source line to the decompiled code
840:                int decompiledLine = sourceMapper.mapToDecompiled(
841:                        sourceLine + 1, editor.getClassFile());
842:
843:                if (decompiledLine >= 0) {
844:                    // and get the requested line information
845:                    try {
846:                        region = editor.getDocumentProvider()
847:                                .getDocument(input).getLineInformation(
848:                                        decompiledLine);
849:                    } catch (BadLocationException e) {
850:                        BytecodeOutlinePlugin.log(e, IStatus.ERROR);
851:                    }
852:                }
853:                return region;
854:            }
855:
856:            /**
857:             * @param debugType
858:             * @param parent
859:             * @return non public class (local type class) with the name from "debugType" and
860:             * which source was in the "parent" class. Null if no class file could be found.
861:             */
862:            private static IClassFile getLocalTypeClass(
863:                    IJavaReferenceType debugType, IClassFile parent) {
864:                try {
865:                    IType type = parent.getType();
866:                    if ((type.isLocal()) || (type.isMember())) {
867:                        // local type could not be defined in local or inner classes
868:                        return null;
869:                    }
870:                    // debugType.getSignature() == Lpackage/name/with/slashes/className;
871:                    String binarySignature = debugType.getSignature();
872:                    // get only type name from binary signature
873:                    int idx = binarySignature.lastIndexOf('/');
874:                    if (idx > 0 && idx < binarySignature.length() - 1) {
875:                        String name = binarySignature.substring(idx + 1);
876:                        if (name.charAt(name.length() - 1) == ';') {
877:                            name = name.substring(0, name.length() - 1);
878:                        }
879:                        return type.getPackageFragment().getClassFile(
880:                                name + ".class");
881:                    }
882:                } catch (Exception e) {
883:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
884:                }
885:                return null;
886:            }
887:
888:            private static boolean hasInnerClass(IJavaReferenceType debugType,
889:                    IClassFile parent) {
890:                try {
891:                    String parentName = parent.getType()
892:                            .getFullyQualifiedName();
893:                    String childName = debugType.getName();
894:                    return childName != null
895:                            && childName.startsWith(parentName + "$");
896:                } catch (Exception e) {
897:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
898:                }
899:                return false;
900:            }
901:
902:            private static BytecodeClassFileEditor getBytecodeEditor(
903:                    IClassFile parent) {
904:                IEditorReference[] editorReferences = PlatformUI.getWorkbench()
905:                        .getActiveWorkbenchWindow().getActivePage()
906:                        .getEditorReferences();
907:                for (int i = 0; i < editorReferences.length; i++) {
908:                    IEditorPart editor = editorReferences[i].getEditor(false);
909:                    if (editor instanceof  BytecodeClassFileEditor) {
910:                        BytecodeClassFileEditor bytecodeEditor = (BytecodeClassFileEditor) editor;
911:                        if (parent.equals((bytecodeEditor).getClassFile())) {
912:                            return bytecodeEditor;
913:                        }
914:                    }
915:                }
916:                return null;
917:            }
918:
919:            public ITextSelection convertSelection(
920:                    ITextSelection textSelection, boolean toDecompiled) {
921:                int startLine = textSelection.getStartLine();
922:                int newLine;
923:                if (toDecompiled) {
924:                    newLine = sourceMapper.mapToDecompiled(startLine + 1,
925:                            getClassFile()) + 1;
926:                } else {
927:                    newLine = sourceMapper.mapToSource(startLine,
928:                            getClassFile()) - 1;
929:                }
930:                if (newLine < 0) {
931:                    return null;
932:                }
933:                IDocument document = getDocumentProvider().getDocument(
934:                        getEditorInput());
935:                try {
936:                    int lineOffset = document.getLineOffset(newLine);
937:                    return new TextSelection(lineOffset, 0);
938:                } catch (BadLocationException e) {
939:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
940:                }
941:                return null;
942:            }
943:
944:            public int getSourceLine(ITextSelection bytecodeSelection) {
945:                int startLine = bytecodeSelection.getStartLine();
946:                return sourceMapper.mapToSource(startLine, getClassFile()) - 1;
947:            }
948:
949:            public ITextSelection convertLine(int sourceLine) {
950:                int newLine = sourceMapper.mapToDecompiled(sourceLine + 1,
951:                        getClassFile()) + 1;
952:                IDocument document = getDocumentProvider().getDocument(
953:                        getEditorInput());
954:                try {
955:                    int lineOffset = document.getLineOffset(newLine);
956:                    return new TextSelection(lineOffset, 0);
957:                } catch (BadLocationException e) {
958:                    BytecodeOutlinePlugin.log(e, IStatus.ERROR);
959:                }
960:                return null;
961:            }
962:
963:            public int getBytecodeInstructionAtLine(int line) {
964:                if (isDecompiled()) {
965:                    DecompiledClass decompiledClass = sourceMapper
966:                            .getDecompiledClass(getClassFile());
967:                    if (line > 0 && decompiledClass != null) {
968:                        return decompiledClass.getBytecodeInsn(line);
969:                    }
970:                }
971:                return -1;
972:            }
973:
974:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.