OSGi: Recalculate the Import-Package of a JAR programmatically - osgi

I want to recalculate the "Import-Package" of an OSGi Jar programmatically. I try to use the bnd Analyser.
try(Analyzer analyzer = new Analyzer()) {
analyzer.setJar(new File(filename));
return analyzer.getImportPackage();
}
This returns the (wrong) existent imports of the MANIFEST.MF. How can I recalculate the "Import-Package" of an OSGi Jar programmatically?
Update
Adding as BJ Hargrave calMainfest() suggested does not work:
try(Analyzer analyzer = new Analyzer()) {
analyzer.setJar(new File(filename));
analyzer.calcManifest();
return analyzer.getImportPackage();
}
It seems to use the existing MANIFEST.MF contained in the Jar.
Best regards
Kisho

You need to call calcManifest() to compute a new manifest. Otherwise it just uses the existing manifest.

Related

Adding .so files by wildcard search to an android library project using gradle 7.4+

I am trying to add .so files by wildcard search to my android library project.
In my library structure I have 2 sub-projects with build.gradle files called primary and testapp. The project primary generates some libraries in the form testLib_*.so. In my testapp I am trying to grab all these libraries and include them. I currently got this working by utilizing sourceSets as follows;
sourceSets {
main {
jniLibs {
srcDirs += "../primary/build/intermediates/cmake/debug/obj/"
}
}
}
Such that this path contains target folders (i.e. arm64-v8a, etc.) which then holds the required test libs.
However my problem with this approach is that I prefer to have simply a wildcard search which can pickup the required files. I want to avoid having these long paths which may change with time and also want to avoid including all libraries and instead only the ones that match my search. For example I would like to have something like the following;
sourceSets {
main {
jniLibs {
srcDirs += "../primary/**/testLib_*.so"
}
}
}
However all my wildcard searches have come up empty handed and simply do not end up including any files.

Gradle distribution plugin: conditionally copy assets

I'm packaging my java application using Gradle's Distribution plugin. I wanted to make 2 distributions, one which doesn't include a JRE and another one that bundles a JRE with the app.
I've set up a copyJre task and wanted to only make Distributions plugin include a folder (jre-8 in the example below) only when copyJre task is in the tasks graph. Here's my attempt which doesn't work.
distributions {
main {
contents {
from('/') {
include 'tools/**'
}
// my attempt to conditionally copy
// jre-8 directory only when tasks graph contains
// a task named 'copyJre'
if (tasks.findByName('copyJre') != null) {
from('../../jre-dist/') {
include 'jre-8/**'
}
}
}
}
}
There probably should be a better approach in general. This looks like kludges.
From a Gradle perspective, you are better expressing what you need the other way around:
Create a different distribution that will include the JRE, possibly extracting the common part of the copy spec.
And if you really only want a single output, make it replace the default distribution after building it.

Gradle artifacts declaration

I need some guidance and clarification about how artifacts are declared in gradle tasks, I would like to upload files to maven/artifactory reading these files from any kind of output container instead of having to hardcode the path for each artifact generated.
This is simpler if you have a JAR, ZIP, File, and a few other types, because you can make use of project.artifacts.add(...), but this is not trivial when you have some random file types.
Im going to provide an example to specify and clarify what I need exactly:
if I have:
task generateMyFile {
doLast {
buildDir.mkdirs()
['touch', new File(buildDir, 'myfile.random').absolutePath].execute().waitFor()
}
}
What's the right way to declare myfile.random as the output for generateMyFile ?
How do I declare myfile.random to be a valid artifact that will be used by maven/artifactory later by the 'publish' task ? currently I assume the file was generated in build/myfile.random, but Im looking for a smarter solution, and gradle documentation (or any other source) is not clear about this.
Thanks in advance

How do I get Lazybones to create Multi Modular Java EE 7 Gradle Projects?

This is my repository in github: https://github.com/joedayz/lazybones-templates/
I used processTemplates according with the documentation
processTemplates 'build.gradle', props
processTemplates 'gradle.properties', props
processTemplates 'src/main/java/*.java', props
processTemplates 'settings.gradle', props
I request the user this information:
props.project_megaproceso = ask("Define value for 'megaproceso' [megaproceso]: ", "megaproceso", "megaproceso")
props.project_macroproceso = ask("Define value for 'macroproceso' [macroproceso]: ", "macroproceso", "macroproceso")
props.project_proceso = ask("Define value for 'proceso' [proceso]: ", "proceso", "proceso")
megaproceso2, macroproceso, proceso are directories or part of file names in my template.
How do I change the names of the unpacked directories and files? The code is in my github.
The post-install scripts for Lazybones currently have full access to both the standard JDK classes and the Apache Commons IO library, specifically to aid with file manipulation.
In this specific case, you can either use File.renameTo() or FileUtils.moveFile/Directory(). For example:
def prevPath = new File(projectDir, "megaproceso2-macroproceso-proceso.ear")
prevPath.renameTo(new File(
projectDir,
"${props.megaproceso}-${props.macroproceso}-${props.processo}.ear"))
The projectDir variable is one of several properties injected into the post-install script. You can find a list of them in the Template Developers Guide.
I think the main advantage of FileUtils.moveFile() is that it works even if you're moving files across devices, but that's not necessary here. Also note that you have to explicitly import the classes from Commons IO if you want to use them.

How do I apply a patch file in Gradle?

I have a Gradle build script that successfully builds my project and compiles all the artifacts I need.
However, in a couple of cases I'd like to give other developers the option to patch some of the files. For example, in one of the archives there's an xml file with information about database hooks - some of the devs use other versions (or even engines) and need to change these before they can use the build output.
Instead of having them make changes to a version-controlled file, which they might commit by mistake, I'd like to give them the option to have a local, individual patch file which the build script applies.
In an old ant script, we did something like this
<target name="appcontext-patch" if="applicationContext.patch.file">
<patch patchfile="${applicationContext.patch.file}" originalfile="${dist.dir}/applicationContext.xml"/>
</target>
but I can't figure out how to do the equivalent in Gradle. Is there a better (i.e. more idiomatic) way of doing this than trying to directly convert this into a call to ant.patch?
Some context
This is how the file ends up in the archive in the first place:
into('META-INF') {
from 'deployment', {
include 'applicationContext.xml'
rename { fn -> "jboss-spring.xml" }
}
}
It would be fantabulous if I could just do something like
into('META-INF') {
from 'deployment', {
include 'applicationContext.xml'
rename { fn -> "jboss-spring.xml' }
patch 'local/applicationContext.xml.patch'
}
}
and have the patch file applied before the file is put in the archive. I don't mind writing some code to make this possible, but I'm quite new to Gradle and I have no idea where to begin.
You should be able to translate your ant call into gradle pretty directly.
The gradle doc on how to do this generically. Basically attributes become named arguments and child tags become closures. The documentation has a bunch of good examples.
Once you have your translated ant task you can put in in a doFirst or doLast block on an appropriate task.
My first guess would be something like this:
apply plugin: 'java'
assemble.doFirst {
ant.patch(patchfile: applicationContext.patch.file,
originalFile: "${dist.dir}/applicationContext.xml")
}
That's untested, so but I'm pretty sure it will get you started on the right path. The intent is that just before the java plugin assembles your archive you want gradle to call a closure. In this case the closure will perform an ant action that patches your xml.
Alternately you could use the task you have above that performs a copy and tag onto that.
task myCopyTask(type: Copy) {
...
} << {
ant.patch(patchfile: applicationContext.patch.file,
originalFile: "${dist.dir}/applicationContext.xml")
}
In this case you are writing the task yourself and the left-shift operator (<<) is equivalent to .doLast but a whole lot cooler. I'm not sure which method you prefer, but if you already have a copy task that gets the file there in the first place, I think doLast keeps the relevant code blocks as close to each other as possible.
RFC 5621 defines an XML patching language that uses XPath to target the location in the document to patch. It's great for tweaking config files.
There is an open source implementation in Java (Disclaimer: I am the author). It includes a filter that can be used from Gradle to patch XML files during any task that implements CopySpec. For example:
buildscript {
repositories { jcenter() }
dependencies { classpath "com.github.dnault:xml-patch:0.3.0" }
}
import com.github.dnault.xmlpatch.filter.XmlPatch
task copyAndPatch(type: Copy) {
// Patch file in RFC 5621 format
def patchPath = 'local/applicationContext-patch.xml'
inputs.file patchPath
into('META-INF') {
from 'deployment', {
include 'applicationContext.xml'
rename { 'jboss-spring.xml' }
filter(XmlPatch, patch: patchPath)
}
}
}
If you'd like to do this more on the fly I can think of two main techniques. Both involve writing some code, but they may be more appealing to you and I'm pretty confident gradle doesn't have this behavior built-in anywhere.
Personally I think #1 is the better solution, since you don't need to muck around with the internals of the Copy task. A custom filter feels cleaner and more reusable.
1) Write a custom filter that you specify in your copy task. I can't help with the details of how to write a custom filter, but I'd start here. You should be able to put the custom filter in buildSrc (lots of info about that at gradle.org) and then you simply need to import it at the top of your gradle file. If you write it in groovy I think you can even just use ant.patch() again.
task copyAndPatch() {
into('META-INF') {
from 'deployment', {
include 'applicationContext.xml'
rename { fn -> "jboss-spring.xml' }
filter(MyCustomFilterThatDoesAPatch, patchFile: 'local/applicationContext.xml.patch')
}
}
2) Write a custom task. Again, I'll leave the details to the experts but you can probably get away with subclassing the Copy task, adding a 'patch' property, and then jumping in during execution to do the dirty work.

Resources