I had a LocalIndexedRepo to resolve our platform dependencies.
The last weeks I wrote a Bulk Deploy tool to deploy all these bundles to our nexus, because they were structurally inconsistent.
Now I wanted to replace said LocalIndexedRepo with my MavenBndRepository.
I unfortunately deleted the folders containing the bundles before deleting the plugin from the build.bnd.
Now every project, for every external type throws an error that it can’t resolve the respective type to a variable.
While said types are in the buildpath and resolvable through the maven repo.
I’ve deleted the cache multiple times, so that didn’t help.
Any pointers?
OK, I just found out my precise question: Is it possible to replace one repository of type A with a Repository of type B, given that they contain the same depencies?
Precisely: Can I replace a LocalIndexedRepo with a MavenBndRepo containing the same artifacts?
The contract for repositories is exactly the same. So yes, you should be able to completely substitute one type for another assuming it provides the minimum set of capabilities needed.
In the end a repository is mostly the index file, which is standardized (which then points at artifact/resource URIs.)
From what you describe I would venture a guess:
Do you have -runrepos:
defined in your bndrun? This is a whitelist, that if set at any point in time, will not change automatically. I stumbled upon this from time to time.
Yes they are defined in the workspace projects’ .bnd files, but I had previously thought this only affects runtime-, not -buildpath
-resolution and the errors I got were at buildtime. Further suggesting -runrepos
don’t affect buildtime is that I had renamed multiple repositories, also the commented-out LocalIndexedRepo and the renaming is not reflected in the workspace projects’ .bnd files, yet the -buildpath
s still seem to get resolved correctly when the LocalIndexedRepo that originally supplied the dependencies is there.
Yesterday, after commenting out the LocalIndexedRepo plugin in build.bnd
, the errors in eclipse’s Problems view indicated, that the dependencies were still expected to be at the physical location of the LocalIndexedRepo.
I’ll quickly set the -runrepos
to the repos I’d like to resolve the -buildpath
from and report back if the -buildpath
gets resolved with the old LocalIndexedRepo commented out.
My understanding is, that runrepos only have an effect on runbundles and runrequires .
Have you tried hitting the various refresh buttons like this one:
I often need this button when I change something related to repos (e.g. adding / removing a repo plugin in build.bnd).
Frantically all the time.
Where in bnd’s sources do I need to step into in order to see if there is something wrong with the Maven repo?
It is a really weird overall situation.
My maven repo contains all the bundles that the LocalIndexedRepo previously contained.
The repositories view lists them all, doubleclicking each (at least the few I tried) correctly opens the jar editor and its output is good.
I get no further errors anywhere, the only thing that happens is that for every non-locally provided external type anywhere, I simply only get many errors like [ClassName] cannot be resolved to a type
or [ClassName] cannot be resolved to a variable
.
Each projects’ buildpath is set and correct.
When inspecting the build path (Right-click project → Properties → Java Build Path → Libraries → Classpath → Bnd Bundle Path → Edit), for every dependency I see $USER_HOME\.m2\repository\..\filename.jar (exists)
.
Still somehow they seem to not get resolved for the build.
MavenBndRepository.java
e.g. aQute.bnd.repository.maven.provider.MavenBndRepository.getArchive(Object...)
could be a starting point to set a breakpoint.
Could you maybe check how your .project
file in a bundle looks like? e.g. mine looks like this and have the javabuilder
and bndtoolsbuilder
Also what do you see when you right-click on a bundle and go to “Configure”? Do you see a “Add Bndtools nature” or a “Remove Bndtools nature”?
Can you maybe show a .bnd
file of a project where you see the errors?
e.g. do you have any exclamation marks shown in the -buildpath
section?
Which one?
I know of the following caches:
cnf
folder in your bnd workspace
Not sure if Eclipse Workspace .metadata
also caches some stuff.
This is all which comes to mind. Sorry for not being more helful. I’m just digging in the dark. But just remember I had some weird caching issues.
Aahh one more thing:
Which Eclipse do you use?
I had a issue with Eclipse 2024-03 and did not get it working.
Thus I am still one 2023-12 for that reason. A colleague had it too. Basically our bndtools workspace did not work anymore… Here is the github where I reported something:
Hi Chris, thanks so much for your reply! I really appreciate all you guys here very much taking so much time out your days to help me with my shenanigans all the time!
I have fixed my problem differently and maybe it helps if I sketch out how I did that so it could help others with similar problems later.
I had Errors in the Errors list in eclipses Problems view that indicated missing build time dependencies.
So the build didn’t work. Implying stepping through the builder first.
Now I closed all workspace projects but one, cause if I just put a breakpoint in org.bndtools.builder#build
, since it gets called asynchronously in many threads for all workspace projects, the actual debugging would have been annoying with all of them open.
So close all but one problematic project.
In there, the project under build gets initialized as ourModel
. Somewhere in its fields or a field of a field (can’t remember), was an errors
or exceptions
collection and that contained the actual exception for one bundle in my MavenBndRepository.
The problem was (and I should have totally realized earlier it must be something like this) that in my Bulk Deployer, I have to edit the poms of some bundles before uploading them, because they are versioned as SNAPSHOTs. Nearly all our platform dependencies are signed, though, and I am officially not exactly smart , so some Exception about violated referential integrity was thrown, but that never ended up in the UI.
My fix was to remove the signature related files from these bundles in my Bulk Deployer and with that, everything works.
I mean, in hindsight it is absolutely clear my BulkDeployer must have been the issue, because since starting my project to convert our PDE workspace to BndTools, I constantly messed around with supplying dependencies from changing repos and it always worked smoothly, but I was honestly way too stressed out with over 100k errors in my eclipse to realize my mistake earlier because everything looked so correct superficially, so without debugging my workspace out of bndtools’ sources I wouldn’t have found it. Still, next time I know to start single-stepping bndtools earlier.
Great to hear
Do you by any chance remember the place in bnd codebase where you have seen this exception? I ask because, maybe we can see we could do something so it really gets to the UI.
I’ll check that on monday, weekends are strictly non-coding for me
This is seemingly happening only for one of our dependencies. It is in org.bndtools.builder.BndtoolsBuilder#build:109
. After initializing ourModel
, the errors collection (inherited from aQute.bnd.osgi.Processor
) contains:
[0]:
Exception: java.lang.SecurityException: SHA-384 digest error for META-INF/maven/REDACTED/REDACTED/pom.xml
at java.base/sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:256)
at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:252)
at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:239)
at java.base/java.util.jar.JarInputStream.read(JarInputStream.java:199)
at java.base/java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:142)
at java.base/java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:120)
at java.base/java.util.jar.JarInputStream.getNextEntry(JarInputStream.java:129)
at java.base/java.util.jar.JarInputStream.getNextJarEntry(JarInputStream.java:166)
at org.bndtools.utils.jar.PseudoJar.nextEntry(PseudoJar.java:93)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.getJarInfo(BndContainerInitializer.java:514)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateContainerAccessRules(BndContainerInitializer.java:596)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateContainersClasspath(BndContainerInitializer.java:372)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateProjectClasspath(BndContainerInitializer.java:311)
at aQute.bnd.build.WorkspaceLock.locked(WorkspaceLock.java:168)
at aQute.bnd.build.Workspace.readLocked(Workspace.java:1500)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.updateClasspathContainer(BndContainerInitializer.java:248)
at org.bndtools.builder.classpath.BndContainerInitializer.requestClasspathContainerUpdate(BndContainerInitializer.java:120)
at org.bndtools.builder.classpath.BndContainerInitializer.lambda$1(BndContainerInitializer.java:103)
at org.osgi.util.promise.DeferredPromiseImpl$ThenAccept.accept(DeferredPromiseImpl.java:433)
at org.osgi.util.promise.DeferredPromiseImpl.result(DeferredPromiseImpl.java:151)
at org.osgi.util.promise.DeferredPromiseImpl$ThenAccept.run(DeferredPromiseImpl.java:426)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
[1]:
Unexpected error during classpath calculation: SHA-384 digest error for META-INF/maven/REDACTED/REDACTED/pom.xml
[2]:
Exception: java.lang.SecurityException: SHA-384 digest error for META-INF/maven/REDACTED/REDACTED/pom.xml
at java.base/sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:256)
at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:252)
at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:239)
at java.base/java.util.jar.JarInputStream.read(JarInputStream.java:199)
at java.base/java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:142)
at java.base/java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:120)
at java.base/java.util.jar.JarInputStream.getNextEntry(JarInputStream.java:129)
at java.base/java.util.jar.JarInputStream.getNextJarEntry(JarInputStream.java:166)
at org.bndtools.utils.jar.PseudoJar.nextEntry(PseudoJar.java:93)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.getJarInfo(BndContainerInitializer.java:514)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateContainerAccessRules(BndContainerInitializer.java:596)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateContainersClasspath(BndContainerInitializer.java:372)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateProjectClasspath(BndContainerInitializer.java:311)
at aQute.bnd.build.WorkspaceLock.locked(WorkspaceLock.java:168)
at aQute.bnd.build.Workspace.readLocked(Workspace.java:1500)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.updateClasspathContainer(BndContainerInitializer.java:248)
at org.bndtools.builder.classpath.BndContainerInitializer.requestClasspathContainerUpdate(BndContainerInitializer.java:120)
at org.bndtools.builder.classpath.BndContainerInitializer.requestClasspathContainerUpdate(BndContainerInitializer.java:168)
at org.bndtools.builder.classpath.BndContainerInitializer.modelChanged(BndContainerInitializer.java:137)
at bndtools.central.Central.refreshProjects(Central.java:608)
at bndtools.central.Central.refreshPlugins(Central.java:578)
at bndtools.views.repository.RepositoriesView$6.runInWorkspace(RepositoriesView.java:456)
at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:43)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
[3]:
Exception: java.lang.SecurityException: SHA-384 digest error for META-INF/maven/REDACTED/REDACTED/pom.xml
at java.base/sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:256)
at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:252)
at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:239)
at java.base/java.util.jar.JarInputStream.read(JarInputStream.java:199)
at java.base/java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:142)
at java.base/java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:120)
at java.base/java.util.jar.JarInputStream.getNextEntry(JarInputStream.java:129)
at java.base/java.util.jar.JarInputStream.getNextJarEntry(JarInputStream.java:166)
at org.bndtools.utils.jar.PseudoJar.nextEntry(PseudoJar.java:93)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.getJarInfo(BndContainerInitializer.java:514)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateContainerAccessRules(BndContainerInitializer.java:596)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateContainersClasspath(BndContainerInitializer.java:372)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateProjectClasspath(BndContainerInitializer.java:311)
at aQute.bnd.build.WorkspaceLock.locked(WorkspaceLock.java:168)
at aQute.bnd.build.Workspace.readLocked(Workspace.java:1500)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.updateClasspathContainer(BndContainerInitializer.java:248)
at org.bndtools.builder.classpath.BndContainerInitializer.requestClasspathContainerUpdate(BndContainerInitializer.java:120)
at org.bndtools.builder.classpath.BndContainerInitializer.requestClasspathContainerUpdate(BndContainerInitializer.java:168)
at org.bndtools.builder.classpath.BndContainerCompilationParticipant.aboutToBuild(BndContainerCompilationParticipant.java:19)
at org.eclipse.jdt.internal.core.builder.JavaBuilder.initializeBuilder(JavaBuilder.java:632)
at org.eclipse.jdt.internal.core.builder.JavaBuilder.clean(JavaBuilder.java:312)
at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:1029)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:254)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:311)
at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:400)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:403)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:362)
at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:624)
at org.eclipse.core.internal.resources.Project$1.run(Project.java:571)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2380)
at org.eclipse.core.internal.resources.Project.internalBuild(Project.java:609)
at org.eclipse.core.internal.resources.Project.build(Project.java:121)
at bndtools.editor.project.BuildOperationsPart$RebuildJob.runInWorkspace(BuildOperationsPart.java:106)
at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:43)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
[4]:
Exception: java.lang.SecurityException: SHA-384 digest error for META-INF/maven/REDACTED/REDACTED/pom.xml
at java.base/sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:256)
at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:252)
at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:239)
at java.base/java.util.jar.JarInputStream.read(JarInputStream.java:199)
at java.base/java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:142)
at java.base/java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:120)
at java.base/java.util.jar.JarInputStream.getNextEntry(JarInputStream.java:129)
at java.base/java.util.jar.JarInputStream.getNextJarEntry(JarInputStream.java:166)
at org.bndtools.utils.jar.PseudoJar.nextEntry(PseudoJar.java:93)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.getJarInfo(BndContainerInitializer.java:514)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateContainerAccessRules(BndContainerInitializer.java:596)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateContainersClasspath(BndContainerInitializer.java:372)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.calculateProjectClasspath(BndContainerInitializer.java:311)
at aQute.bnd.build.WorkspaceLock.locked(WorkspaceLock.java:168)
at aQute.bnd.build.Workspace.readLocked(Workspace.java:1500)
at org.bndtools.builder.classpath.BndContainerInitializer$Updater.updateClasspathContainer(BndContainerInitializer.java:248)
at org.bndtools.builder.classpath.BndContainerInitializer.requestClasspathContainerUpdate(BndContainerInitializer.java:120)
at org.bndtools.builder.classpath.BndContainerInitializer.requestClasspathContainerUpdate(BndContainerInitializer.java:168)
at org.bndtools.builder.classpath.BndContainerCompilationParticipant.aboutToBuild(BndContainerCompilationParticipant.java:19)
at org.eclipse.jdt.internal.core.builder.JavaBuilder.initializeBuilder(JavaBuilder.java:632)
at org.eclipse.jdt.internal.core.builder.JavaBuilder.build(JavaBuilder.java:182)
at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:1024)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:254)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:311)
at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:400)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:403)
at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:514)
at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:462)
at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:544)
at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:161)
at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:255)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
Thanks.
From looking at the source of org.bndtools.builder.BndtoolsBuilder#build:109
it looks like calls to
markers.setMarkers(processor, BndtoolsConstants.MARKER_BND_PROBLEM);
are responsible for bringing the errors in the UI (Eclipse Problems view). A few thoughts:
-
Do you see this specific error in the Eclipse Problems view somewhere? If yes, then the error is actually already in the UI but maybe you didn’t see it among the hundreds of other errors… is this possible?
-
if not: could you debug once more and see if any of the
markers.setMarkers(processor, BndtoolsConstants.MARKER_BND_PROBLEM);
are called? If not we should think about adding one a bit earlier, e.g. after line 109 where you discovered the error in the
… because setMarkers()
seems to do this:
the model.getErrors() should actually contain the
Another question is maybe also: How would you have expected to see the error?
Hello and sorry for the late reply, I had to do product dev work and couldn’t do any bndtools stuff in the last two weeks.
No. It is not in the Problems View. I’m not sure whether I might have gotten an Error Dialog weeks ago that I might have clicked away too fast. But I can’t remember if it was connected to this problem chain.
Yes, at #214. But for my project, it first goes into the next try block and in the callable
lambda of Central#bndCall
on #191 calls Processor#clear
with model.clear()
, which clears the errors list.
Adding following code starting from #162 adds the error description to the Problems view, but I think ideally it would need some decision making whether something is bad enough to throw an Exception in a dialog.
else if (ourModel != null && !ourModel.getErrors()
.isEmpty()) {
List<String> showableErrors = ourModel.getErrors()
.stream()
.filter(errorString -> !errorString.startsWith("Exception"))
.toList();
if (!showableErrors.isEmpty()) {
for (String showableError : showableErrors) {
markers.createMarker(null, IMarker.SEVERITY_ERROR, showableError,
BndtoolsConstants.MARKER_BND_PATH_PROBLEM);
}
}
}
No problem, much appreciated that you took the time
This is great. Do you mind creating a PR? I think this is useful.
Probably, but maybe this is even an improvement over the current situation where you don’t see this anywhere… and maybe not as “aggressive” as an Exception. at least I don’t feel in the position to decide that. But I think a problem view marker might be fine.
@pkriens What do you think?
We probably need a specific marker type for this, these markers should be applied at the Bnd Classpath container. The BndContainerInitializer
can then maintain it.
The life cycle of these errors are very different from normal build errors. bnd has a design flaw that it conflates the data and the run. Processor should have been separated in a static part and a part you can use for execution (errors/warnings/progress).
Hmm. org.eclipse.core.resources.IncrementalProjectBuilder#build
’s javadoc states
and the Exception causing the problem is unchecked (and at that, a SecurityException
), which I thought is unrecoverable, so I originally wanted to suggest throwing a CoreException
from BndContainerInitializer.Updater#calculateProjectClasspath
as is declared on the method signature, but never actually thrown, assuming it’s probably an oversight and might have thrown at some earlier point, I went ahead with
// BndContainerInitializer#Updater#calculateProjectClasspath@322
catch (SecurityException e) {
throw new CoreException(Status.error(e.getMessage(), e));
}
realizing that doesn’t surface the error either, it just logs to bndtools’ console and probably ends up in the eclipse error log for my workspace, but not in the UI.
So I guess I have to do something like
// BndContainerInitializer#Updater#calculateProjectClasspath@322
catch (SecurityException e) {
new MarkerSupport(project).createMarker(model, IMarker.SEVERITY_ERROR, e.getMessage(), BndtoolsConstants.NEW_FANCY_MARKER);
}
right?
I have an implementation without a new Marker type that doesn’t introduce a lot of change, just a new private method and two else if statements.
// BndtoolsBuilder.java
private void createMarkersForModelErrors(MarkerSupport markers, Project model) throws CoreException, Exception {
List<String> interestingErrors = model.getErrors()
.stream()
.filter(errorMessage -> errorMessage != null && !errorMessage.isBlank()
&& !errorMessage.startsWith("Exception"))
.toList();
if (!interestingErrors.isEmpty()) {
markers.deleteMarkers("*");
for (String errormessage : interestingErrors) {
markers.createMarker(model, IMarker.SEVERITY_ERROR, errormessage,
BndtoolsConstants.MARKER_BND_PATH_PROBLEM);
}
}
}
// build method
else if (ourModel != null && ourModel.getErrors() != null && !ourModel.getErrors()
.isEmpty()) {
createMarkersForModelErrors(markers, ourModel);
return null;
}
// clean method, but I'm not sure whether it's ok to do this, because clean
else if (model != null && model.getErrors() != null && !model.getErrors()
.isEmpty()) {
createMarkersForModelErrors(markers, model);
}
I think this is a good enough solution. Also with the marker creation in BndContainerInitializer
, I would have needed to refactor MarkerSupport to be public and have some public methods.
Luckily for me, the existing bndtools implementation already displays these markers in the heading of the Bnd Project Editor’s Build tab, which I think is ideal for visibility without displaying an error dialog.
My remaining problem now is testing this, as I’d need to programatically
- create a bundle (launchpad, maybe?)
- sign it (no idea)
- manipulate a contained file (easy)
- put it in a repository (no clue)
- create a project (launchpad again?)
- add first bundle to its buildpath (launchpad?)
- build it (launchpad?)
and then verify the marker exists and I’ll already struggle at creating the first bundle with launchpad if that’s even realistically working in bndtools.builder
… So any pointers are very welcome.
Thanks a lot.
Maybe if you somehow find the time, there is the call on friday where we could discuss those things in the group with screensharing and what not.
Regarding testing I could only do some wild guesses regarding pointers:
aQute.bnd.deployer.repository.TestLocalIndexGeneration
shows how to use dummy repos (e.g. see line #119Jar dummyJar = new Jar(IO.getFile("testdata/bundles/dummybundle.jar"));
Just an idea how you could maybe fake it and create exactly the “broken” bundles you need- then maybe
test.ProcessorTest
e.g.test.ProcessorTest.testBeginEndHandleErrors()
- and maybe
test.BuilderTest
- and
test.JarSignerTest
So maybe those testcases contain a bit of everything you need