How to integrate Proguard obfuscation in my JavaFX's IntelliJ artifact? - intellij-idea

I'm developing a JavaFX application using IntelliJ IDEA as the IDE.
So far, everything runs smoothly, I have all my external libs configured and my JavaFX artifact being correctly created.
Now I would like to integrate obfuscation (using Proguard) when the artifact is created.
IntelliJ have a 'Pre-processing' and 'Post-processing' option in artifact's properties where I can define an Ant task to be runned.
But I have no idea how to create that task and tell the compiler my obfuscation options.
Thank you very much in advance for any clues,
Best regards

There are 3 basic ways you do it:
Create a normal proguard.cfg file, and reference it from ant
Put your proguard settings directly inside ant using XML notation
Put your proguard settings directly inside ant using the proguard.cfg format
Here's a basic example of using Proguard with Ant with the 3rd approach:
http://www.reviewmylife.co.uk/blog/2007/10/20/proguard-eclipse-ant-buildxml/
The important thing to remember about Proguard is that everything you want to obfuscate has to be inside a JAR file, and you'll need to explicitly tell it not to obfuscate certain things (like your program entry point, things you access via reflection, etc).
JavaFX creates a file used as an entry point you want to prevent obfuscating:
-keepclasseswithmembers public class com.javafx.main.Main {
public *; public static *;
}
Make sure to include Java/JavaFX libs
-libraryjars "${java.home}/lib/rt.jar"
-libraryjars "${java.home}/lib/ant-javafx.jar"
-libraryjars "${java.home}/lib/jfxrt.jar"
If you're using FXML files, you'll want to make sure your FXML files are renamed similarly to their respective controller file:
-adaptresourcefilecontents **.fxml
Anything annotated with #FXML is accessed through reflection, so don't obfuscate them:
-keepclassmembernames class * {
#javafx.fxml.FXML *;
}
The Proguard website has a lot of information, but it can be difficult to grok.
Honestly, there are plenty of examples on the web that show you how to do this. Just google javafx proguard, and you'll probably find some good complete examples.
Edit: as far as how IntelliJ passes information to Ant.. I don't know. There are probably some variables it passes in that you reference like a normal Ant propertly. I'm sure JetBrains website has info on that on their website if you can't find it on the net.
If it was me, I'd just create an ant script to compile my application without obfuscation, then add in proguard once you've got that squared away.

Just some complementing information, regarding running an Ant task in idea's 'post-processing'.
Make sure you have a 'default' target. Else the task wont execute. Example of build.xml:
<?xml version="1.0"?>
<project name="ant_task" default="obfuscate" basedir=".">
<target name="obfuscate">
<taskdef resource="proguard/ant/task.properties"
classpath="/opt/proguard5.2.1/lib/proguard.jar" />
<proguard configuration="proguard.cfg"/>
</target>
</project>

Related

How does kotlin-gradle-plugin use 'kotlin.code.style' property?

The official Kotlin documentation states:
Add kotlin.code.style=official property to the gradle.properties file at the project root.
I'm trying to understand how kotlin-gradle-plugin handles this property.
Which gradle task uses it?
When running gradle build, I don't see my code being reformatted, even if I format my code badly on purpose.
I went through the Github source code of the plugin but couldn't properly get to understand it.
Thanks for your help.
Kotlin Gradle plugin doesn't use this property, as it's not responsible for reformatting the code. Instead, this property is used by Gradle importer of Kotlin plugin for IntelliJ IDEA.
This facade provides access to Gradle properties defined for the project:
https://github.com/JetBrains/kotlin/blob/v1.4.10/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradlePropertiesFileFacade.kt
It checks local.properties first in case user wants to override this value in the local configuration (this file is usually added to .gitignore for VCS to skip it during it's operations), then in usual gradle.properties.
Then the property gets consumed to configure the project here:
https://github.com/JetBrains/kotlin/blob/v1.4.10/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSourceSetDataService.kt#L158-L159
Same thing goes for Maven-based projects. These are the only two places the property is used throughout Kotlin repository apart from tests right now.

Gradle project with no project classes but with some buildscript-accessible custom classes?

I am thinking to use Gradle to manipulate with mysql database. It will read some files from filesystem, analyse them and populate database accordingly.
Such project will not produce any project code, because all output will go to database tables. On the other hand, gradle script should access some custom java or groovy classes to facilitate working with source data.
Is this a possible Gradle usage? Where to put gradle-accessible classes then? I don't want to have separate project, producing JAR for this project. I wan't single project, so that Gradle first compiles classes and the utilizes them in the script.
Is this possible?
Gradle is extensible, so you can utilize buildSrc for such scenarios. It works in the following way:
along build.gradle in the project there is buildSrc dir with custom build.gradle
in buildSrc/build.gradle you can define the script dependencies itself, implement plugins and tasks
finally you can apply a plugin from buildSrc to build.gradle.
It's quite handy, since e.g. IntelliJ can import such project and provide code completion for instance.
Another way is to put all the necessary stuff in build.gradle itself.
Such buildSrc project can be compiled to a jar, published and provided as a plugin, or it can be a separate project on github to be downloaded and used to manipulate data. Also, there no need to implement Plugin, you can use static methods e.g. Have a look at the demo.

Cannot compile XTend classes in Intellij

I am trying to make a basic program using XTend for Intellij 15.0.5 (Ultimate) but for some reason I cannot run/compile any ".xtend" files.
Writing the following code is no problem and the ide checks for syntax errors as expected:
package presentation
class Greeter {
def static void main(String[] args){
println("Hello World!");
}
}
I downloaded and installed the custom language plugin and I can create a new Java project with XTend. However, I cannot run/compile any xtend files.
When performing a right click on the xtend file there is no "run". More interestingly, Intellij allows me to refactor normal java classes into xtend classes. Also, I cannot choose Greeter as Main class in the Run Configuration.
Of course, I also added the mandatory libraries (core, lib and macro). I really don't know what I am missing but I suppose it must be something very obvious. Apart from running/compiling everything seems to work like a charm.
I had a similar problem myself as I am just starting out with Xtend.
As far as I can tell you don't run Xtend files as much as you run/compile java files that get auto generated by Xtext (The parser system Xtend uses).
The problem I had (and the one you also most likely have) was caused by the module not having Xtend generation enabled.
After many frustration related headaches I fixed this problem by opening the Project Structure page, clicking on the Modules tab, selecting my desired module, clicking the green plus icon and then choosing Xtend from the resulting menu.
It should then show a panel with a bunch of options (you should leave these the way they are for now and then click OK).
IntelliJ will then auto generate a java file for each xtend file. To run the project you just configure your application launcher so that it points to the generated java file containing your main method and then you should be good to go.
Hope this helps.

Using Aspects in a java application - when javac/ajc?

I think about using AspectJ in an existing project.
I have several pure Java Eclipse projects and I like to create an AOP project.
I'm not quite sure about when ajc is needed and when optional. We use Ant (with javac) as our main build and I would like to avoid changing the build.
Is the following possible:
I have a AspectJ enabled Eclipse and create my aspect project. I create a jar from this and include this jar with the aspectj jar in the normal eclipse workspace with the other projects.
The build includes my aspect jar and the aspectj jar as dependency jars with javac.
Is this enough for working with the aspects ?
Or do every project of the application needs to be compiled with ajc ?
The main goal is to keep the current structure of Eclipse setup and build environment as as much as possible as it is now.
Or is this only possible with the annotation style ? (if so can someone link me some information about the weaver and how to do this at runtime ?)
Thank you
If you want to weave your aspect into your codebase, you must use AJC. If you only use javac, even with the annotation, your code won't be weaved by your aspects.
That being said, you don't have to add a lot to your ant build.
something like that should do the job:
<path id="ajclasspath">
<path refid="classpath"/>
<pathelement location="${scm.home}/ant_libs/aspectjrt.jar"/>
</path>
<iajc inpath="${classes.dir}" destDir="${classes.dir}" fork="true" maxmem="${aspectj.maxmem}">
<argfiles refid="aspectj.argfiles.path"/>
<classpath refid="ajclasspath"/>
</iajc>
In fact, you just build like normal and you add a step with the iajc taking your output dir of the javac compile as the inpath and you put the result in the same directory.
You can also take a jar as input to iajc and produce a jar with all your stuff weaved inside.
Edit: Or you can use runtime weaving, if your app is a web application, it is not too bad. If not, i do not recommand runtime weaving, since each time you will start your app, it might be a lot longer to start. I don't have a lot of experience with runtime weaving, but you can check it out. I know you need a aop.xml to define your aspects.
Regards

How do I add my fragment to the list of required-plugins on an existing plugin

I currently have an existing plugin, which references a class from a required plugin. I have replaced this code with a reference to a class which is part of my fragment.
I am facing two issues.
If I import my fragment as a jar file, I am not able to see the changes I have made as the plugin running as an eclipse application results in a ClassNotFoundException
To overcome this, I link an additional source (of fragment) to the existing plugin project. However, the link uses an absolute path, and makes it unfit for deployment.
I want to be able to package the plugin with the code modification and be able to "depend" on my fragment code. Is there a way I can add my fragment as a dependency?
For example:
Plugin Project I am changing : org.eclipse.*.editor
it depends on org.eclipse.*.edit
I have a fragment mydomain.*.edit which has org.eclipse.*.edit as host plugin
I want org.eclipse.*.editor to pick up mydomain.*.edit
instead of org.eclipse.*.edit
ps: I have also tried packaging the jar file for the mydomain.*.edit in the plugins directory and try and pick it up from there, it doesnt show up on the list when I click add required plugins on the dependency tab on the plugin.xml file of the org.eclipse.*.editor
Please let me know if I am not clear enough, I will try and rephrase it.
Thanks in advance!
If I understand correctly what you want to do, I don't think that it's possible. You will have to try some other way.
Plugins have dependencies on other plugins. Fragments don't exist as separate runtime entities, but only as extensions of a plugin. So your plugin can only refer to the 'editor' plugin.
Classes provided by a fragment can't (and shouldn't) be accessed directly. They can be returned by the original plugin (A) if they are implementing an executable extension provided by plugin A.
If you refer to the fragment's code from another plugin (B), the classes will be loaded by plugin B's classloader and be different from the ones that are loaded by plugin A.
What is the purpose of your fragment? Do you want to get access to internal code in plugin A? Do you want to extend an eclipse editor?
If you want to extend functionality that the original plugin is not exposing as extensible, I think the only way is to write a plugin, extend the editor class from the original plugin, register it alongside the original one and use it instead.
[Edit] Maybe this link will explain better: Eclipse FAQ
Hope this helps,
Vlad
Thanks Vlad,
Your explanation was very helpful. Unlike the extension based architecture that is truly intended for fragments, I had to modify a certain component in the editor that was not exposed as part of the extension. This modification referred to an external project I created as an fragment but could have been a normal java project packaged a jar file that I could place in the classpath of the editor.
I was able to resolve the dependency issues by placing the jar file in class path, however when I export the plugins and related plugins as jar files and place it in the dropin directory, it does not install correctly. (Nor does placing the jar files in the plugins directory)
The eclipse editor that I am trying to modify uses the EMF project. I have kept the EMF project in the workspace inorder to resolve dependencies of the editor. However when I replace the EMF jar files bundled with eclipse with the one in the workspace, the files that I want to edit are not correctly recognized.
Is there another way of doing this?