Skip to content

Commit

Permalink
Merge pull request #5946 from pkriens/issue/5918-include-directory-as…
Browse files Browse the repository at this point in the history
…-jar

Added an option to add a directory as a jar/zip file
  • Loading branch information
pkriens committed Dec 24, 2023
2 parents 5524a45 + 4a4d1f9 commit 7294a89
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 17 deletions.
6 changes: 6 additions & 0 deletions biz.aQute.bndlib.tests/test/test/IncludeResourceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ public void testIncludeResourceFromUrl() throws Exception {
Set<String> excludeOneFile = testResources("@" + uri + "!/!LICENSE", 528 - 1);
}

@Test
public void testIncludeResourceDirectoryToJar() throws Exception {
Set<String> jar = testResources("foo.jar=@jar", 1);
assertThat(jar).containsExactlyInAnyOrder("foo.jar");
}

@Test
public void testIncludeResourceFromClasspathJars() throws Exception {
Set<String> deflt = testResources("@osgi.jar", 528);
Expand Down
50 changes: 34 additions & 16 deletions biz.aQute.bndlib/src/aQute/bnd/osgi/Builder.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package aQute.bnd.osgi;

import static aQute.bnd.exceptions.FunctionWithException.asFunction;
import static aQute.libg.re.Catalog.caseInsenstive;
import static aQute.libg.re.Catalog.eof;
import static aQute.libg.re.Catalog.lit;
import static aQute.libg.re.Catalog.or;
import static aQute.libg.re.Catalog.setAll;
import static java.util.stream.Collectors.toList;

import java.io.File;
Expand Down Expand Up @@ -71,6 +76,7 @@
import aQute.lib.strings.Strings;
import aQute.lib.zip.ZipUtil;
import aQute.libg.generics.Create;
import aQute.libg.re.RE;

/**
* Include-Resource: ( [name '=' ] file )+ Private-Package: package-decl ( ','
Expand All @@ -80,7 +86,8 @@
public class Builder extends Analyzer {

@SuppressWarnings("deprecation")
private static final String INCLUDERESOURCE_HEADERS = Constants.INCLUDERESOURCE + "|" + Constants.INCLUDE_RESOURCE;
private static final String INCLUDERESOURCE_HEADERS = Constants.INCLUDERESOURCE + "|"
+ Constants.INCLUDE_RESOURCE;

private final static Logger logger = LoggerFactory.getLogger(Builder.class);
private final static Pattern IR_PATTERN = Pattern
Expand Down Expand Up @@ -376,14 +383,16 @@ private void doSaveManifest(Jar dot) throws Exception {
}
}

protected void changedFile(@SuppressWarnings("unused") File f) {}
protected void changedFile(@SuppressWarnings("unused")
File f) {}

/**
* Sign the jar file. -sign : <alias> [ ';' 'password:=' <password> ] [ ';'
* 'keystore:=' <keystore> ] [ ';' 'sign-password:=' <pw> ] ( ',' ... )*
*/

void sign(@SuppressWarnings("unused") Jar jar) throws Exception {
void sign(@SuppressWarnings("unused")
Jar jar) throws Exception {
String signing = getProperty(SIGN);
if (signing == null)
return;
Expand Down Expand Up @@ -608,7 +617,8 @@ public Collection<File> getSourcePath() {
return sourcePath;
}

private void doVerify(@SuppressWarnings("unused") Jar dot) throws Exception {
private void doVerify(@SuppressWarnings("unused")
Jar dot) throws Exception {

// Give the verifier the benefit of our analysis
// prevents parsing the files twice
Expand Down Expand Up @@ -666,11 +676,11 @@ else if (Logic.hasOverlap(testpackage.keySet(), unused))
else if (Logic.hasOverlap(includepackage.keySet(), unused))
header = Constants.INCLUDEPACKAGE;

warning(
"Unused %s instructions , no such package(s) on the class path: %s", header, unused).header(header)
.context(unused.iterator()
.next()
.getInput());
warning("Unused %s instructions , no such package(s) on the class path: %s", header, unused)
.header(header)
.context(unused.iterator()
.next()
.getInput());
}
}

Expand Down Expand Up @@ -1009,8 +1019,7 @@ private void doIncludeResource(Jar jar, String name, Map<String, String> extra)

private void doClassAttribute(Jar jar, String name, Map<String, String> extra, Instructions preprocess,
boolean absentIsOk) throws Exception {
FileLine header = getHeader(INCLUDERESOURCE_HEADERS,
Constants.CLASS_ATTRIBUTE);
FileLine header = getHeader(INCLUDERESOURCE_HEADERS, Constants.CLASS_ATTRIBUTE);
String fqn = extra.get(Constants.CLASS_ATTRIBUTE);
TypeRef typeRef = getTypeRefFromFQN(fqn);
if (typeRef == null) {
Expand Down Expand Up @@ -1292,14 +1301,15 @@ private void noSuchFile(Jar jar, String clause, Map<String, String> extra, Strin
}
}

final static RE ZIP_P = caseInsenstive(setAll, lit("."), or("jar", "zip"), eof);

/**
* Extra resources from a Jar and add them to the given jar.
*
* @param extra
*/
private void extractFromJar(Jar jar, String source, String destination, boolean absentIsOk,
Map<String, String> extra)
throws ZipException, IOException {
Map<String, String> extra) throws ZipException, IOException {
// Inline all resources and classes from another jar
// optionally appended with a modified regular expression
// like @zip.jar!/META-INF/MANIFEST.MF
Expand All @@ -1310,6 +1320,14 @@ private void extractFromJar(Jar jar, String source, String destination, boolean
source = source.substring(0, n);
}

File f = getFile(source);
if (f.isDirectory() && ZIP_P.matches(destination)
.isPresent()) {
DirectoryResource resource = new DirectoryResource(f);
jar.putResource(destination, resource);
return;
}

List<Jar> sub = getJarsFromName(source, "extract from jar");
if (sub.isEmpty()) {
if (absentIsOk)
Expand All @@ -1325,7 +1343,7 @@ private void extractFromJar(Jar jar, String source, String destination, boolean
Instruction in = instr;
String replacement = extra.get("rename:");
nameMapper = path -> in.getMatcher(path)
.replaceAll(replacement);
.replaceAll(replacement);
}
}

Expand All @@ -1334,7 +1352,6 @@ private void extractFromJar(Jar jar, String source, String destination, boolean
}
}


/**
* Add all the resources in the given jar that match the given filter.
*
Expand Down Expand Up @@ -1766,7 +1783,8 @@ protected void setTypeSpecificPlugins(PluginsContainer pluginsContainer) {
* @throws Exception
*/

public void doDiff(@SuppressWarnings("unused") Jar dot) throws Exception {
public void doDiff(@SuppressWarnings("unused")
Jar dot) throws Exception {
Parameters diffs = parseHeader(getProperty("-diff"));
if (diffs.isEmpty())
return;
Expand Down
40 changes: 40 additions & 0 deletions biz.aQute.bndlib/src/aQute/bnd/osgi/DirectoryResource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package aQute.bnd.osgi;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;

/**
* Resource for a directory. This class implementation assumes the file does not
* change underneath this object.
*/
public class DirectoryResource extends WriteResource {
private final File dir;

public DirectoryResource(File dir) throws IOException {
this.dir = dir;
assert dir.isDirectory();
}

public DirectoryResource(Path path) throws IOException {
this(path.toFile());
}

@Override
public String toString() {
return dir.toString();
}

@Override
public void write(OutputStream out) throws Exception {
try (Jar jar = new Jar(dir)) {
jar.write(out);
}
}

@Override
public long lastModified() {
return dir.lastModified();
}
}
8 changes: 7 additions & 1 deletion docs/_instructions/includeresource.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ A _source_ in the clause starting with a `-` sign will not generare an error whe

`-includeresource.all = {foo=-bar}`, -foo.txt

## Unrolling
## Rolling

There are two variants of the rolling _operator_ `@`. It can be used to _roll up_ a directory as a zip or jar file, or it can be used to unroll a jar file into its constituents.

If the destination is a path of a `jar` or `zip` file, like `foo/bar/icons.zip` and the source points to a directory in the file system, then the directory will be wrapped up in a Jar and stored as a single entry in the receiving jar file.

-includeresource foo/bar/icons.zip=@icons/

_Unrolling_ is getting the content from another JAR. It is activated by starting the source with an at sign (`@`). The at sign signals that it is not the actual file that should be copied, but the contents of that file should be placed in the destination.

Expand Down

0 comments on commit 7294a89

Please sign in to comment.