One of the major reasons of why Eclipse was chosen as a foundation for the new ABAP development environment is its extensibility. Almost every introduction to ADT I’ve seen so far stresses the additional value that can be gained by combining plug-ins from multiple sources. I’ve used Eclipse for some time now (starting with 3.2 or 3.3, I don’t exactly remember when), developed my own Eclipse-based tools and while I’m certainly not an expert, I know about the basics of implementing and extending Eclipse plug-ins.
Until now, I have more or less ignored ADT – mostly because our ABAP environments were too outdated to use ADT. This is slowly changing, so I took the opportunity and visited the introductory DEV165 session at this year’s SAP TechEd && d-code in Berlin. Back at home, I wanted to put the claim of extensibility to the test. My aim was to create a plug-in that takes an existing interface and generates a pre-fabricated implementation class according to some rules. The details are not of importance here – I’ll probably write about it later when there is something to be seen.
My idea was to extend the Project Explorer view so that you could right-click the interface and start some kind of wizard that creates a class for the interface. Extending the Project Explorer is a frequent task in the Eclipse world, so there are a number of tutorials available. If you want to code along, I’d recommend using this tutorial to get a starting point.
The next step would be to place a restriction on the menu extension so that the context menu entry only appears for interfaces. This is fairly easy, you just need to add a condition to the extension. In this case, I figured that an instanceof condition should do the trick, so I used the Plug-in Spy provided by the PDE to find out more about the interface entries in the Project Explorer (select an interface in the project explorer, then press Alt+Shift+F1).
Among other information, you can see that the current selection (which is what matters most here) is a TreeSelection that contains an AbapRepositoryInterfaceNode. Using this information, it is possible to limit the popup menu entry to Interfaces:
In the command handler, you would usually use the central selection service to find out what objects the command should work on. There’s a basic example in the tutorial I mentioned above; it involves examining the selection and then casting the selected object to a suitable class or interface variable. This is where the trouble really starts…
If you try to look up the class AbapRepositoryInterfaceNode in the ADT SDK documentation, you’ll be out of luck – as the fully qualified class name com.sap.adt.oo.ui.internal.interfaces.projectexplorer.AbapRepositoryInterfaceNode suggests, this is an internal implementation class, and most of the object-specific classes aren’t documented anyway. This is not good – while it is still possible to plough on, it makes things a lot harder for wannabe contributors.
Using some dirty tricks, it is possible to put together an inheritance tree of AbapRepositoryInterfaceNode. However, it doesn’t look too promising:
Using the documented API, you can find out which project the interface belongs to, and that’s about it. Now for the average Eclipse plug-in that would be annoying, but not too uncommon – there are loads of plug-ins with a similar level of (un)documentation. At this point, you would start to dig into the source code to find out about the structure of AbapRepositoryInterfaceNode and its superclasses and interfaces, other classes that use it, perhaps some service implementations, and usually within a reasonable amount of time, you would have gained an understanding of the inner workings. That’s not possible in this case, simply because the source code is not available publicly. We’ll have to continue guessing, which in this case is easy: A TreeNode has a generic means to attach a value to the node. A quick look with the debugger reveals that this is indeed the way the node keeps track of the object it represents:
So, a RepositoryObjectListItem, let’s look that up in the SDK – whoops, internal stuff again. This class implements IRepositoryObject, which is undocumented as well, but at least gives you basic information about the selected interface:
Fine so far, but now you might want to be interested in the contents of the interface. At this point, you would probably use the References in Workspace (Ctrl+Shift+G) function to try and find out where the interface is used and what you might do with it – but again, this only applies to open source projects where you have the source code at your disposal.
At the moment, this looks like the end of the road – if you want to continue your journey, you have to put on a hard hat, break out the heavy machinery and probably violate a few terms of the licensing agreement in the process.
I would have liked to blog about something else today, something a bit closer to an implementation, but that wasn’t to be. A few key takeaways from my point of view:
- Extensibility doesn’t come automatically with the platform, it has to be considered in the architecture and implementation of each and every aspect of the product. An Eclipse plug-in can be as segregated and hard to extend as any other commercial application.
- Extensibility of other products largely comprises of the ability to examine the existing stuff. This applies not only to Eclipse, but likewise to the SAP NetWeaver platform and the applications built on top of it. Imagine having to implement a BAdI without access to the application around it…
- Documentation is no substitute for access to the source code unless it is really comprehensive and well-maintained.
- Likewise, access to the source code is no real substitute for documentation – it tells you how things are built, but not why.