Programmatically accessing build.properties of a Java project through JDT API - java

Is there a way to access programmatically the build.properties of a Java project through the JDT API? Something like IJavaProject.getRawClasspath() just for the build.properties?
If I have an IProject/IJavaProject, can I add a line with the JDT API like this (through JDT API calls):
Before:
source.. = src/
output.. = bin/
After:
source.. = src/,\
xtend-gen/
output.. = bin/

This is a PDE object rather than JDT so you need to use the PDE APIs. There is very little documentation on the PDE APIs.
The build.properties is described by the org.eclipse.pde.core.build.IBuildModel interface. You get this using:
IProject project = ... project ...
IPluginModelBase base = PluginRegistry.findModel(project);
IBuildModel buildModel = PluginRegistry.createBuildModel(base);
You can get the entry for 'bin.includes' using
IBuildEntry entry = buildModel.getBuild().getEntry(IBuildEntry.BIN_INCLUDES);
The addToken method of IBuildEntry seems to be the way to add to the entry.
To save you need to check the model is an instance of IEditableModel and call the IEditableModel.save method.
if (buildModel instanceof IEditableModel) {
((IEditableModel)buildModel).save();
}

Related

Is there any way to automatically setting windows path in a string in groovy?

My project root directory is:
D:/Project/Node_Project
I am using a gradle plugin to install nodejs temporarily in my project root directory so that some nodejs command can run in the project while the thoject builds. The plugin is as below:
plugins {
id "com.github.node-gradle.node" version "2.2.4"
}
node {
download = true
version = "10.10.0"
distBaseUrl = 'https://nodejs.org/dist'
workDir = file("${project.buildDir}/nodejs")
}
So, nodejs is getting installed inside the project in the location:
D:/Project/Node_Project/build/nodejs/node-v10.10.0-win-x64
Now, I am using a .execute(String[] "path to set at environment variable", String path of file to be executed which is in the project root directory) method to run a windows command with node dependency. Code below:
cmd = "node connect.js"
def process = cmd.execute(["PATH=${project.projectDir}/build/nodejs/node-v10.10.0-win-x64"],null)
In the above .execute method, is there a way to auto-populate the "build/nodejs/node-v10.10.0-win-x64" part of the string instead of hardcoding it into the method?
Something like:
def process = cmd.execute(["PATH=${project.projectDir}/.*"],null)
Syntax of .execute method:
https://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/String.html#execute(java.lang.String[],%20java.io.File)
All the codes are inside "build.gradle" file. Please help!
I asked why you don't just write a task of type NodeTask, but I understand that you like to run a it in the background, which you can't do with that.
You could list the content of a directory and use that as part of the command. But you could also just grab it from the extension provided by the plugin.
This is not documented and it might break in future releases of the plugin, but you can do something like this (Groovy DSL):
task connectJS {
dependsOn nodeSetup
doFirst {
def connectProcess = "$node.variant.nodeExec $projectDir/src/js/connect.js".execute()
// Blocking readers (if async, pipe to a log file instead)
connectProcess.in.eachLine { logger.info(it) }
connectProcess.err.eachLine { logger.err(it) }
}
}

Include multiple source directories in Qt for Android

I want to include Java source code from multiple directories (which are shared between projects) in a Qt for Android project. On http://imaginativethinking.ca/what-the-heck-how-do-i-share-java-code-between-qt-android-projects/ an approach is described which copies the Java source files:
# This line makes sure my custom manifest file and project specific java code is copied to the android-build folder
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
# This is a custom variable which holds the path to my common Java code
# I use the $$system_path() qMake function to make sure that my directory separators are correct for the platform I'm compiling on as you need to use the correct separator in the Make file (i.e. \ for Windows and / for Linux)
commonAndroidFilesPath = $$system_path( $$PWD/../CommonLib/android-sources/src )
# This is a custom variable which holds the path to the src folder in the output directory. That is where they need to go for the ANT script to compile them.
androidBuildOutputDir = $$system_path( $$OUT_PWD/../android-build/src )
# Here is the magic, this is the actual copy command I want to run.
# Make has a platform agnostic copy command macro you can use which substitutes the correct copy command for the platform you are on: $(COPY_DIR)
copyCommonJavaFiles.commands = $(COPY_DIR) $${commonAndroidFilesPath} $${androidBuildOutputDir}
# I tack it on to the 'first' target which exists by default just because I know this will happen before the ANT script gets run.
first.depends = $(first) copyCommonJavaFiles
export(first.depends)
export(copyCommonJavaFiles.commands)
QMAKE_EXTRA_TARGETS += first copyCommonJavaFiles
With later Qt versions the code has to be changed to this:
commonAndroidFilesPath = $$system_path($$PWD/android/src)
androidBuildOutputDir = $$system_path($$OUT_PWD/../android-build)
createCommonJavaFilesDir.commands = $(MKDIR) $${androidBuildOutputDir}
copyCommonJavaFiles.commands = $(COPY_DIR) $${commonAndroidFilesPath} $${androidBuildOutputDir}
first.depends = $(first) createCommonJavaFilesDir copyCommonJavaFiles
export(first.depends)
export(createCommonJavaFilesDir.commands)
export(copyCommonJavaFiles.commands)
QMAKE_EXTRA_TARGETS += first createCommonJavaFilesDir copyCommonJavaFiles
Is this the standard way to go, or is there some built-in functionality for including multiple Java source directories in Qt for Android projects?
Regards,
A much cleaner solution is this one:
CONFIG += file_copies
COPIES += commonJavaFilesCopy
commonJavaFilesCopy.files = $$files($$system_path($$PWD/android/src))
commonJavaFilesCopy.path = $$OUT_PWD/android-build

How to allow my maven plugin to access resources of a project where it is used?

I have a maven project which contain sub module :
mainproject, subproject-a, subproject-b
I'm developping a maven plugin (test-toto-plugin ) and i'd like this module check for example if toto.txt is present in src/main/resources for the project and each subproject and if it contains the line "toto".
When i include my test-toto-plugin in mainproject, it's called at each clean phase, i put a log to be sure about that, so it's called when i want, but it doesn't seem to access to src/main/resources of mainproject and each subproject, it seem that it access its own src/main/resources.
I use :
Paths.get("src","main","resources", "toto.txt");
To access the file, i'm almost sure it access test-toto-plugin /src/main/resources.
But i want to access mainproject/src/main/resources when it's called in main project, subproject-a/src/main/resources when it's called in subproject-a, subproject-b/src/main/resources when it's called in subproject-b.
Is it possible ?, any suggestion ?
Finally found a solution to my problem reading code source of maven-resources-plugin : https://github.com/apache/maven-compiler-plugin/blob/master/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
In my maven plugin Mojo class, i declare :
#Parameter( defaultValue = "${project.resources}", required = true, readonly = true )
private List<Resource> resources;
It will provide me the absolute path of resource of project where my plugin is used.
In the function execute of my plugin i use FileInputStream to get file content from absolute path (i just put functionnal code but ofcourse there is exception handling).
FileInputStream fis = new FileInputStream(resources.get(0).getDirectory()+"\\toto.txt");
String body = IOUtils.toString(fis, StandardCharsets.UTF_8.name());
Executed in mainproject it will access mainproject\src\main\resources\toto.txt
Executed in subproject-a it will access subproject-a\src\main\resources\toto.txt
Executed in subproject-b it will access subproject-b\src\main\resources\toto.txt
And i just have to include my plugin to mainproject to make it work in each submodule.
You can also get the folder paths using the "project.basedir" or "project.build.directory" properties.
#Parameter(defaultValue = "${project.basedir}/src/main/resources", required = true, readonly = true)
private String sourceResourceDir;
#Parameter(defaultValue = "${project.build.directory}/classes", required = true, readonly = true)
private String buildResourceDir;
public void execute() throws MojoExecutionException {
getLog().info("sourceResourceDir=" + sourceResourceDir);
getLog().info("buildResourceDir=" + buildResourceDir);
}

Jxbtrowser retrieve platform specific artefact at runtime

I'm writing an intelij plugin and would like to download the platform specific artefact at runtime.
I've loaded the platform specific jar into a class loader but the ChromiumExtractor cannot access the nested resources when prefixed with "/". So I can access the resource as "chromium-mac.zip" but the library cannot.
I've tried to unzip the nested zipped chromium artefact into the correct directory but this does not leading to a working solution. So now I've been trying to piece together the way the library extracts the artefact but it's rather tedious as the code is obfuscated.
Does the jxbrowser plugin have some support for retrieving the artefact at runtime. Could such support be added (jxbtrowser devs use SO for support questions etc, this is a message to them :D ) ?
Approach taken :
// inside intelij plugin . The plugin has the jxbrowser-6.6.jar
// and license.jar loaded into the classloader. the platform specific
// artefact will be retrieved manual).
val cl = URLClassLoader(arrayOf(URL("file://.../jxbrowser-mac-6.6.jar")), Browser::class.java.classLoader)
val backup = Thread.currentThread().contextClassLoader
try {
Thread.currentThread().contextClassLoader = cl
// can access like this
Thread.currentThread().contextClassLoader.getResource("chromium-mac.zip")
val ce = ChromiumExtractor.create()
// cannot access as resource is retrieved "/chromium-mac.zip" ?
ce.extract(BrowserPreferences.getChromiumDir())
browser = Browser()
} finally {
Thread.currentThread().contextClassLoader = backup
}
The following does the trick, The resource jar had to be in the same class loader as the client jar (as well as the license). It would be nice if JxBrowser added a helper for this that is capable of performing the download and initialising chromium, perhaps taking just a path for a persistent storage directory.
private fun initializeJxBrowser(): Browser {
if(ChromiumExtractor.create().shouldExtract(BrowserPreferences.getChromiumDir())) {
val cl = URLClassLoader(arrayOf(
URL("file:.../license.jar"),
URL("file:.../jxbrowser-mac-6.6.jar"),
URL("file:../jxbrowser-6.6.jar")
))
cl.loadClass("com.teamdev.jxbrowser.chromium.BrowserContext")
.getMethod("defaultContext")
.invoke(null)
}
return Browser()
}

Creating a Eclipse Java Project from another project, programatically

I would like to create a Java project from another Java project, using some script or Java methods from an Eclipse library, whether it exists. An alternative to this can be duplicating a previously manually-created project. Is there any approach to this?
Thanks.
I believe you can make use of IProject#copy (inherited from IResource.copy)
Adding to Alexander Pavlov's answer, I found that a little extra work is required to copy the project properties (such as referenced projects) in addition to just copying the project files.
public static IProject copyProject(String projectName) throws CoreException {
IProgressMonitor m = new NullProgressMonitor();
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IProject project = workspaceRoot.getProject(projectName);
IProjectDescription projectDescription = project.getDescription();
String cloneName = projectName + "_copy";
// create clone project in workspace
IProjectDescription cloneDescription = workspaceRoot.getWorkspace().newProjectDescription(cloneName);
// copy project files
project.copy(cloneDescription, true, m);
IProject clone = workspaceRoot.getProject(cloneName);
// copy the project properties
cloneDescription.setNatureIds(projectDescription.getNatureIds());
cloneDescription.setReferencedProjects(projectDescription.getReferencedProjects());
cloneDescription.setDynamicReferences(projectDescription.getDynamicReferences());
cloneDescription.setBuildSpec(projectDescription.getBuildSpec());
cloneDescription.setReferencedProjects(projectDescription.getReferencedProjects());
clone.setDescription(cloneDescription, null);
return clone;
}

Categories