Override existing Eclipse plugin extension - java

I have an existing Eclipse plugin that provides an extension point. The plugin uses standard Eclipse mechanism to find the extensions. In this plugin's code, following code is used to get the extension.
IConfigurationElement[] config = Platform.getExtensionRegistry()
.getConfigurationElementsFor(extensionPoint);
if (config.length > 0) {
return config[0];
}
As you can see in the code, only the first found extension is used. This plugin already provides an extension and this extension is used in the default case.
Now I need to override the behavior of the default extension, so I created a new plugin and extends the same extension point. But it turns out that the default extension is always the first one in the IConfigurationElement array, so it's always picked up.
How can I make my own plugin appear first in the found IConfigurationElement array, then my own plugin is used instead of the default one?
The existing plugin is written by others and I don't want to make changes to it until it's absolutely necessary.

I'd say this is a bad way to get extensions from an extension point, either way. If they just want the use the pluginsystem to load a specific extension they have created, they could use the getConfigurationElementsFor(String namespace, String extensionPointName, String extensionId) method instead and close off the possibility for others to use the extension point. As of now there is no sure way of knowing which extension they will get. Chances are, there are instances in the code later on that assumes they will get their extension and when they don't get the extension they expect, Mr ClassCastException comes knocking on the door. (Had a bug like this in a system once)
Of course the best way is to change the code to handle many extensions!
But to your question; I dont know how the ExtensionRegistry fills the array, the API doesnt say. Perhaps there is a way to perhaps set a specific version of your extension that will allow it to be placed first in the array. You would have to look in the code of the ExtensionRegistry to know exactly how the extensions are found. I think it may be in alphabetical order, but im not sure.
Another way is to overload the existing plugin with your plugin and replace functionality. A very dirty approach, but in some cases it is doable. See one of my questions regarding this

Related

Eclipse Plugin for custom Strg+Click hook

Eclipse for Java has the convenient feature of jumping to the definition of a class or method by clicking on a usage while holding the Ctrl-key.
I want to implement a similar functionality for the following usecase:
We have an annotation taking the path of a yaml-file as a parameter like this:
#MyAnnotation("myYamlFile.yaml")
Clicking on the filename while holding Ctrl (or some other key or combination) should open the file in an editor (the path is relative to a specified root path, which is on the classpath). Obviously selecting the filename and performing Ctrl+Shift+R (for "Open Resource") would work too, but since it'll be a very common usecase to jump between the Java and the yaml file, I want to look into making it even simpler.
My plan is to write a plugin for this. Before I start, I wanted to ask, if there's a simpler or better solution, maybe an existing plugin, which can be configured to be used for my purpose. Does anyone have experience with something similar, who can point me in the right direction?
It turned out quite easy to write an Eclipse plugin for it.
All I needed to do was implementing org.eclipse.jface.text.hyperlink.IHyperlink and org.eclipse.jface.text.hyperlink.IHyperlinkDetector.
http://codeandme.blogspot.co.at/2014/06/adding-hyperlink-detectors-to-editors.html

ASM4/5: How can I embedded source code in ASM4/5

I am about to transform(manipulate) a lot of classes and to allow easy debugging and transparent communication of the changes applied to the code, I want to add java source code equivalent of the manipulated class.
In order to add java code I would be able to use existing source code and manipulate it in parallel. Then I need to store it along with the class.
Visiting the class file format for JDK 8, I noticed that no attribute exists to directly embed source code. Remembering the old times it was possible to include the source code within a class file. What do I miss? (I only found the attribute for specifying a source file). Also the option in the compiler tab of Eclipse does only show options to embed file names... .
Beside seaming to store source files separately, I wonder if it is feasible to reverse engineer (decompile) the class file. If one provide information about local names and parameter names, this might even be a better option.
The ASM documentation stated out that a tool is available to even decompile byte code.
Does anyone has some insights or experiences to share on this matter?

Realize modular architecture / simple plugin system

I wrote a simple program taking some commands from a XML file, executing it, checkings for errors of the commands, reporting back by mail etc. An entry for a command looks e.g. like this:
<command>C:\Program Files\Test\test.exe /xyz</command>
Now I want to introduce some kind of plugins:
<command myPlugin1="abc,1" myPlugin2="def">C:\Program Files\Test\test.exe /xyz</command>
I thought about writing the plugins as a Java class implementing some interface or subclassing some Plugin class, then having a method like
pluginExec(List<String> parameters, String command)
that gets passed the parameters (e.g. abc,1) and the command (C:\Program Files\Test\test.exe /xyz).
Then maybe take all attribute names of the command tag, therefore myPlugin1 and myPlugin2, then search for a class with the same name as the attribute on myapp.plugins namespace and call pluginExec(...).
Any better ideas on this? I guess with my idea I need some kind of reflection, is there a way without it? The application is a private tool, no need to be able to add plugins without recompiling the software. I just don't want to change the code everytime, I just want to plug in my new plugin class.
If your plugin based program you develop will not grow a lot in the next future then your design is fine.
However, if you expect it to grow and you expect to add multiple features to it than I suggest you try Java standards like OSGi.

How to modify the class file?

I was working on the project in eclipse in which I have added this maven dependency for PDFBOX
Maven dependency
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>1.6.0</version>
</dependency>
And I was getting the error on some pdf file as:
Parsing Error, Skipping Object
java.io.IOException: expected='endstream' actual='' org.apache.pdfbox.io.PushBackInputStream#1b8d77fe
at org.apache.pdfbox.pdfparser.BaseParser.parseCOSStream(BaseParser.java:439)
at org.apache.pdfbox.pdfparser.PDFParser.parseObject(PDFParser.java:552)
at org.apache.pdfbox.pdfparser.PDFParser.parse(PDFParser.java:184)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1088)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1053)
at org.apache.tika.parser.pdf.PDFParser.parse(PDFParser.java:74)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:197)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:197)
at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:135)
at org.apache.tika.Tika.parseToString(Tika.java:357)
at edu.uci.ics.crawler4j.crawler.BinaryParser.parse(BinaryParser.java:37)
at edu.uci.ics.crawler4j.crawler.WebCrawler.handleBinary(WebCrawler.java:223)
at edu.uci.ics.crawler4j.crawler.WebCrawler.processPage(WebCrawler.java:460)
at edu.uci.ics.crawler4j.crawler.WebCrawler.run(WebCrawler.java:129)
at java.lang.Thread.run(Thread.java:662)
So when I google it, I found there was some bug in BaseParser.java file, So they have given the patch(https://issues.apache.org/jira/browse/PDFBOX-195) for this java file only.. So my question is how can I modify this java file only.. I can see the BaseParser.class file in eclipse as I have attached the source doc for that PDFBOX-Issue. Any suggestions will be appreciated.
Given that BaseParser.java is an Apache file, there is absolutely no reason why you cannot download the source, make your changes and re-compile it. I have done this with Apache code in the past. It was pretty straight forward and took me only a few minutes. Remember to submit your fix back to Apache so that way it will be included in the release.
You can:
create subclass manual (and use it if it possible)
download source, fix it, recompile, and finally, overwrite it in jar
create subclass programmaticly (using cglib or asm)
download only BasicParser, mock all depends (just create empty class files with needs methods), recompile it and put in jar (or ./ext ./endorsed dir in jvm, if you want)
Generally, one doesn't modify a class file directly, they download the source code and then rebuild the class file with javac. Yes, it is possible to modify class files without doing such a thing; but, patch files are not generally binary patch files, they are generally source code patch files.
Stefanglase has mentioned that the release you are working with should have the patch applied, but there is a small chance that a recent change reintroduced the issue. You might want to verify that you're not solving the wrong problem before you get too deep into it.
On the rare odds that you really want to modify a binary, you open it with a hexadecimal editor, or a hexeditor for short. Basically this allows you to set any byte in the file to any value, which means you must have a strong knowledge of the file's internal format, what is allowed / disallowed, and how to make allowable changes that actually implement your expected behavior. In short, you'll be doing a compiler's work manually, by hand.
It can be done, but it is the sort of task that generally requires a lot of knowledge, and few people have that knowledge already, so the costs of learning that knowledge and successfully implementing the change is likely much higher than rebuilding from available patched source. Even the costs of successfully implementing the change with the knowledge of the general principals and techniques already present isn't something that one can say with certainty is less than the costs of rebuilding the entire library with patched source.
Good Luck.

Patching Java software

I'm trying to create a process to patch our current java application so users only need to download the diffs rather than the entire application. I don't think I need to go as low level as a binary diff since most of the jar files are small, so replacing an entire jar file wouldn't be that big of a deal (maybe 5MB at most).
Are there standard tools for determining which files changed and generating a patch for them? I've seen tools like xdelta and vpatch, but I think they work at a binary level.
I basically want to figure out - which files need to be added, replaced or removed. When I run the patch, it will check the current version of the software (from a registry setting) and ensure the patch is for the correct version. If it is, it will then make the necessary changes. It doesn't sound like this would be too difficult to implement on my own, but I was wondering if other people had already done this. I'm using NSIS as my installer if that makes any difference.
Thanks,
Jeff
Be careful when doing this--I recommend not doing it at all.
The biggest problem is public static variables. They are actually compiled into the target, not referenced. This means that even if a java file doesn't change, the class must be recompiled or you will still refer to the old value.
You also want to be very careful of changing method signatures--you will get some very subtle bugs if you change a method signature and do not recompile all files that call that method--even if the calling java files don't actually need to change (for instance, change a parameter from an int to a long).
If you decide to go down this path, be ready for some really hard to debug errors (generally no traces or significant indications, just strange behavior like the number received not matching the one sent) on customer site that you cannot duplicate and a lot of pissed off customers.
Edit (too long for comment):
A binary diff of the class files might work but I'd assume that some kind of version number or date gets compiled in and that they'd change a little every compile for no reason but that could be easily tested.
You could take on some strict development practices of not using public final statics (make them private) and not every changing method signatures (deprecate instead) but I'm not convinced that I know all the possible problems, I just know the ones we encountered.
Also binary diffs of the Jar files would be useless, you'd have to diff the classes and re-integrate them into the jars (doesn't sound easy to track)
Can you package your resources separately then minimize your code a bit? Pull out strings (Good for i18n)--I guess I'm just wondering if you could trim the class files enough to always do a full build/ship.
On the other hand, Sun seems to do an okay job of making class files that are completely compatible with the previous JRE release, so they must have guidelines somewhere.
You may want to see if Java WebStart can help you as it is designed to do exactly those things you want to do.
I know that the documentation describes how to create and do incremental updates, but we deploy the whole application as it changes very rarely. It is then an issue of updating the JNLP when ready.
How is it deployed?
On a local network I just leave everything as .class files in a folder. The startup script uses robocopy or rsync to copy from network share to local. If any .class file is different it is synced down. If not, it doesn't sync.
For non-local network I created my own updater. It downloads a text file of md5sums and compares to local files. If different it pulls file down from http.
A long time ago the way we solved this was to used Classpath and jar files. Our application was built in a Jar file, and it had a launcher Jar file. The launcher classpath had a patch.jar that was read into the classpath before the main application.jar. This meant that we could update the patch.jar to supersede any classes in the main application.
However, this was a long time ago. You may be better using something like the Java Web Start type of approach, which offers more seamless application updating.

Categories