Skip to content

Commit

Permalink
Fixes #6, enable to use path relocation
Browse files Browse the repository at this point in the history
  • Loading branch information
rmannibucau committed Mar 15, 2022
1 parent f876fd2 commit 3782f9b
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 87 deletions.
1 change: 1 addition & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ It supports a list of delegate transformers if needed.
This provides two transformer implementations which use slightly different replacement algorithms.
* `io.yupiik.maven.shade.transformer.RelocationTransformer`: relocates class names
* `io.yupiik.maven.shade.transformer.SourceRelocationTransformer`: relocates class names in source-like files
* `io.yupiik.maven.shade.transformer.PathRelocationTransformer`: relocates paths (enabling to use `rawString` relocation configuration and use a plain `replaceAll`)

[source,xml]
----
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@
*/
package io.yupiik.maven.shade.transformer;

import java.util.List;
import org.apache.maven.plugins.shade.relocation.Relocator;

public class SourceRelocationHandler implements RelocationHandler{
import java.util.List;

/**
* Trivial transformer applying relocators using relocate path.
*/
public class PathRelocationTransformer extends RelocationTransformer {
@Override
public String relocate(String originalValue, List<Relocator> relocators) {
String newValue = originalValue;
protected String relocate(final String string, final List<Relocator> relocators) {
String newValue = string;
for (Relocator relocator : relocators) {
newValue = relocator.applyToSourceContent(newValue);
newValue = relocator.relocatePath(newValue);
}
return newValue;
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.yupiik.maven.shade.transformer;

import org.apache.maven.plugins.shade.relocation.Relocator;
import org.apache.maven.plugins.shade.resource.ReproducibleResourceTransformer;
import org.apache.maven.plugins.shade.resource.ResourceTransformer;
import org.codehaus.plexus.util.IOUtil;

Expand All @@ -30,19 +31,10 @@
/**
* Trivial transformer applying relocators on resources content.
*/
public class RelocationTransformer implements ResourceTransformer {
private RelocationHandler handler;
public class RelocationTransformer implements ReproducibleResourceTransformer {
private Collection<ResourceTransformer> delegates;
private boolean transformed;

public RelocationTransformer() {
this(new ClassRelocationHandler());
}

protected RelocationTransformer(RelocationHandler handler) {
this.handler = handler;
}

@Override
public boolean canTransformResource(String resource) {
if (delegates == null) {
Expand All @@ -58,20 +50,46 @@ public boolean canTransformResource(String resource) {

@Override
public void processResource(final String resource, final InputStream is, final List<Relocator> relocators) throws IOException {
processResource(resource, is, relocators, 0);
}

@Override
public void processResource(final String resource, final InputStream is,
final List<Relocator> relocators, final long time) throws IOException {
byte[] relocated = null;
for (final ResourceTransformer transformer : delegates) {
if (transformer.canTransformResource(resource)) {
transformed = true;
if (relocated == null) {
relocated = handler.relocate(IOUtil.toString(is), relocators)
relocated = relocate(IOUtil.toString(is), relocators)
.getBytes(StandardCharsets.UTF_8);
}
transformer.processResource(
resource,
new ByteArrayInputStream(relocated),
relocators);
if (ReproducibleResourceTransformer.class.isInstance(transformer)) {
ReproducibleResourceTransformer.class.cast(transformer).processResource(
resource,
new ByteArrayInputStream(relocated),
relocators, time);
} else {
transformer.processResource(
resource,
new ByteArrayInputStream(relocated),
relocators);
}
}
}
}

protected String relocate(final String string, final List<Relocator> relocators) {
String newValue = string;
for (Relocator relocator : relocators) {
String value;
do {
value = newValue;
newValue = relocator.relocateClass(value);
}
while (!value.equals(newValue));
}
return newValue;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,20 @@
*/
package io.yupiik.maven.shade.transformer;

import org.apache.maven.plugins.shade.relocation.Relocator;

import java.util.List;

/**
* Trivial transformer applying relocators on sources-like content.
*/
public class SourceRelocationTransformer extends RelocationTransformer {
public SourceRelocationTransformer() {
super(new SourceRelocationHandler());
@Override
public String relocate(final String originalValue, final List<Relocator> relocators) {
String newValue = originalValue;
for (Relocator relocator : relocators) {
newValue = relocator.applyToSourceContent(newValue);
}
return newValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@

import org.apache.maven.plugins.shade.relocation.SimpleRelocator;
import org.apache.maven.plugins.shade.resource.AppendingTransformer;
import org.apache.maven.plugins.shade.resource.ResourceTransformer;
import org.apache.maven.plugins.shade.resource.XmlAppendingTransformer;
import org.codehaus.plexus.util.IOUtil;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.jar.JarEntry;
Expand All @@ -35,31 +38,87 @@
import static org.junit.jupiter.api.Assertions.assertTrue;

class RelocationTransformerTest {
@Test
void relocateUri() throws Exception {
final XmlAppendingTransformer delegate = new XmlAppendingTransformer();
final Field resource = XmlAppendingTransformer.class.getDeclaredField("resource");
resource.setAccessible(true);
resource.set(delegate, "META-INF/faces-config.xml");

final RelocationTransformer resourceTransformer = createTransformer(delegate, true);
resourceTransformer.processResource(
"META-INF/faces-config.xml",
new ByteArrayInputStream(("" +
"<faces-config" +
" xmlns=\"http://java.sun.com/xml/ns/javaee\"" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"2.0\"" +
" xsi:schemaLocation=\"" +
"http://java.sun.com/xml/ns/javaee " +
"http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd\" />")
.getBytes(StandardCharsets.UTF_8)),
singletonList(new SimpleRelocator(
"http://java.sun.com/xml/ns/javaee",
"https://jakarta.ee/xml/ns/jakartaee",
null, null, true)));
assertOutput(resourceTransformer, jarInputStream -> {
final JarEntry entry = jarInputStream.getNextJarEntry();
assertNotNull(entry);
assertEquals("META-INF/faces-config.xml", entry.getName());
assertEquals("" +
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<faces-config" +
" xmlns=\"https://jakarta.ee/xml/ns/jakartaee\"" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
" version=\"2.0\"" +
" xsi:schemaLocation=\"" +
"https://jakarta.ee/xml/ns/jakartaee " +
"https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_2_0.xsd\" />",
IOUtil.toString(jarInputStream).replace("\r\n", "\n").trim());
assertNull(jarInputStream.getNextJarEntry());
});
}

@Test
void relocate() throws Exception {
final AppendingTransformer delegate = new AppendingTransformer();
final Field resource = AppendingTransformer.class.getDeclaredField("resource");
resource.setAccessible(true);
resource.set(delegate, "foo/bar.txt");

final RelocationTransformer resourceTransformer = new RelocationTransformer();
resourceTransformer.setDelegates(singletonList(delegate));
final RelocationTransformer resourceTransformer = createTransformer(delegate, false);

assertTrue(resourceTransformer.canTransformResource("foo/bar.txt"));
resourceTransformer.processResource(
"foo/bar.txt",
new ByteArrayInputStream("a=javax.foo.bar".getBytes(StandardCharsets.UTF_8)),
singletonList(new SimpleRelocator("javax", "jakarta", null, null)));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
try (final JarOutputStream jarOutputStream = new JarOutputStream(out)) {
resourceTransformer.modifyOutputStream(jarOutputStream);
}
try (final JarInputStream jarInputStream = new JarInputStream(new ByteArrayInputStream(out.toByteArray()))) {
assertOutput(resourceTransformer, jarInputStream -> {
final JarEntry entry = jarInputStream.getNextJarEntry();
assertNotNull(entry);
assertEquals("foo/bar.txt", entry.getName());
assertEquals("a=jakarta.foo.bar", IOUtil.toString(jarInputStream).trim());
assertNull(jarInputStream.getNextJarEntry());
});
}

private void assertOutput(final ResourceTransformer resourceTransformer, final IOConsumer<JarInputStream> onJar) throws IOException {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
try (final JarOutputStream jarOutputStream = new JarOutputStream(out)) {
resourceTransformer.modifyOutputStream(jarOutputStream);
}
try (final JarInputStream jarInputStream = new JarInputStream(new ByteArrayInputStream(out.toByteArray()))) {
onJar.accept(jarInputStream);
}
}

private RelocationTransformer createTransformer(final ResourceTransformer delegate, final boolean path) {
final RelocationTransformer resourceTransformer = path ?
new PathRelocationTransformer() : new RelocationTransformer();
resourceTransformer.setDelegates(singletonList(delegate));
return resourceTransformer;
}

private interface IOConsumer<A> {
void accept(A a) throws IOException;
}
}

0 comments on commit 3782f9b

Please sign in to comment.