forked from SpongePowered/VanillaGradle
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ddcbe80
commit 2bb3fa9
Showing
5 changed files
with
242 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
...main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.spongepowered.gradle.vanilla.internal.task; | ||
|
||
import org.cadixdev.bombe.jar.JarEntryTransformer; | ||
|
||
import java.io.IOException; | ||
|
||
public interface JarEntryTransformerProvider { | ||
JarEntryTransformer getJarEntryTransformer() throws IOException; | ||
} |
69 changes: 69 additions & 0 deletions
69
...adle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package org.spongepowered.gradle.vanilla.internal.task; | ||
|
||
import org.apache.tools.ant.filters.BaseFilterReader; | ||
import org.apache.tools.ant.util.ReaderInputStream; | ||
import org.cadixdev.bombe.jar.JarClassEntry; | ||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; | ||
import org.gradle.api.Project; | ||
import org.gradle.api.file.CopySpec; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.io.Reader; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Collections; | ||
|
||
public class RemapFilter extends BaseFilterReader { | ||
private @MonotonicNonNull JarEntryTransformerProvider remapper; | ||
private @MonotonicNonNull Reader delegate; | ||
|
||
public RemapFilter(Reader in) { | ||
super(in); | ||
} | ||
|
||
public JarEntryTransformerProvider getRemapper() { | ||
return remapper; | ||
} | ||
|
||
public void setRemapper(JarEntryTransformerProvider remapper) { | ||
this.remapper = remapper; | ||
} | ||
|
||
public static CopySpec createCopySpec(Project project, JarEntryTransformerProvider remapper) { | ||
return project.copySpec(spec -> { | ||
spec.include("**/*.class"); | ||
spec.setFilteringCharset("ISO-8859-1"); | ||
spec.filter(Collections.singletonMap("remapper", remapper), RemapFilter.class); | ||
}); | ||
} | ||
|
||
private void initialize() throws IOException { | ||
InputStream in = new ReaderInputStream(this.in, StandardCharsets.ISO_8859_1); | ||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
byte[] buffer = new byte[8192]; | ||
int n; | ||
while ((n = in.read(buffer)) != -1) { | ||
baos.write(buffer, 0, n); | ||
} | ||
byte[] bytes = baos.toByteArray(); | ||
|
||
JarClassEntry transformed = remapper.getJarEntryTransformer().transform(new JarClassEntry("Foo.class", 0, bytes)); | ||
if (transformed == null) { | ||
delegate = this.in; | ||
} else { | ||
delegate = new InputStreamReader(new ByteArrayInputStream(transformed.getContents()), StandardCharsets.ISO_8859_1); | ||
} | ||
} | ||
|
||
@Override | ||
public int read() throws IOException { | ||
if (!getInitialized()) { | ||
initialize(); | ||
setInitialized(true); | ||
} | ||
return delegate.read(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
159 changes: 159 additions & 0 deletions
159
subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package org.spongepowered.gradle.vanilla.task; | ||
|
||
import org.cadixdev.atlas.jar.JarFile; | ||
import org.cadixdev.atlas.util.CascadingClassProvider; | ||
import org.cadixdev.bombe.asm.analysis.ClassProviderInheritanceProvider; | ||
import org.cadixdev.bombe.asm.jar.ClassProvider; | ||
import org.cadixdev.bombe.jar.JarEntryTransformer; | ||
import org.cadixdev.lorenz.MappingSet; | ||
import org.gradle.api.GradleException; | ||
import org.gradle.api.Project; | ||
import org.gradle.api.file.FileCollection; | ||
import org.gradle.api.file.FileTree; | ||
import org.gradle.api.model.ObjectFactory; | ||
import org.gradle.api.provider.Property; | ||
import org.gradle.api.tasks.Classpath; | ||
import org.gradle.api.tasks.Input; | ||
import org.gradle.api.tasks.Internal; | ||
import org.gradle.jvm.tasks.Jar; | ||
import org.spongepowered.gradle.vanilla.MinecraftExtension; | ||
import org.spongepowered.gradle.vanilla.internal.Constants; | ||
import org.spongepowered.gradle.vanilla.internal.MinecraftExtensionImpl; | ||
import org.spongepowered.gradle.vanilla.internal.repository.MinecraftProviderService; | ||
import org.spongepowered.gradle.vanilla.internal.task.JarEntryTransformerProvider; | ||
import org.spongepowered.gradle.vanilla.internal.task.RemapFilter; | ||
import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; | ||
import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; | ||
import org.spongepowered.gradle.vanilla.repository.MinecraftResolverImpl; | ||
import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; | ||
import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.nio.file.Files; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
public abstract class RemapJar extends Jar implements JarEntryTransformerProvider { | ||
private final Property<String> fromMappings; | ||
private final Property<String> toMappings; | ||
private FileCollection classpath; | ||
private JarEntryTransformer cachedTransformer; | ||
|
||
public RemapJar() { | ||
final Project project = getProject(); | ||
final ObjectFactory objects = project.getObjects(); | ||
|
||
fromMappings = objects.property(String.class).convention(project.provider(() -> { | ||
final MinecraftExtension extension = project.getExtensions().findByType(MinecraftExtension.class); | ||
Objects.requireNonNull(extension, "Could not find minecraft extension in project"); | ||
return extension.minecraftMappings().get(); | ||
})); | ||
toMappings = objects.property(String.class); | ||
|
||
with(RemapFilter.createCopySpec(project, this)); | ||
} | ||
|
||
@Input | ||
public Property<String> getFromMappings() { | ||
return fromMappings; | ||
} | ||
|
||
public void fromMappings(MappingsEntry mappings) { | ||
fromMappings(mappings.getName()); | ||
} | ||
|
||
public void fromMappings(String mappings) { | ||
fromMappings.set(mappings); | ||
} | ||
|
||
public void toMappings(MappingsEntry mappings) { | ||
toMappings(mappings.getName()); | ||
} | ||
|
||
public void toMappings(String mappings) { | ||
toMappings.set(mappings); | ||
} | ||
|
||
@Input | ||
public Property<String> getToMappings() { | ||
return toMappings; | ||
} | ||
|
||
@Classpath | ||
public FileCollection getClasspath() { | ||
return classpath; | ||
} | ||
|
||
public void setClasspath(FileCollection classpath) { | ||
this.classpath = classpath; | ||
} | ||
|
||
@Internal | ||
public abstract Property<MinecraftProviderService> getMinecraftProvider(); | ||
|
||
@Override | ||
public synchronized JarEntryTransformer getJarEntryTransformer() throws IOException { | ||
if (cachedTransformer != null) { | ||
return cachedTransformer; | ||
} | ||
Project project = getProject(); | ||
MinecraftExtensionImpl extension = (MinecraftExtensionImpl) project.getExtensions().findByType(MinecraftExtension.class); | ||
Objects.requireNonNull(extension, "Could not find minecraft extension in project"); | ||
MinecraftProviderService minecraftProvider = getMinecraftProvider().get(); | ||
minecraftProvider.primeResolver(project, extension.modifiers()); | ||
MinecraftResolverImpl resolver = (MinecraftResolverImpl) minecraftProvider.resolver(); | ||
String minecraftVersion = extension.version().get(); | ||
CompletableFuture<ResolutionResult<MinecraftResolver.MinecraftEnvironment>> envFuture = | ||
resolver.provide(extension.platform().get(), minecraftVersion, extension.modifiers()); | ||
try { | ||
resolver.processSyncTasksUntilComplete(envFuture); | ||
} catch (final ExecutionException ex) { | ||
throw new GradleException("Failed to remap", ex.getCause()); | ||
} catch (final InterruptedException ex) { | ||
Thread.currentThread().interrupt(); | ||
throw new GradleException("Interrupted"); | ||
} | ||
ResolutionResult<MinecraftResolver.MinecraftEnvironment> envResult = envFuture.join(); | ||
if (!envResult.isPresent()) { | ||
throw new IllegalStateException("Could not find Minecraft environment"); | ||
} | ||
|
||
List<FileTree> allFiles = new ArrayList<>(); | ||
getMainSpec().walk(res -> allFiles.add(res.getAllSource())); | ||
FileCollection actualClasspath = project.files(classpath, allFiles); | ||
MappingSet mappings = extension.getMappings().getByName(toMappings.get()).convertFrom( | ||
fromMappings.get(), | ||
resolver, | ||
envResult.get(), | ||
extension.platform().get(), | ||
resolver.sharedArtifactSupplier(minecraftVersion) | ||
); | ||
List<ClassProvider> classProviders = new ArrayList<>(); | ||
for (File file : actualClasspath) { | ||
if (file.getName().endsWith(".jar")) { | ||
classProviders.add(new JarFile(file.toPath())); | ||
} | ||
} | ||
classProviders.add(name -> { | ||
Set<File> files = actualClasspath.getAsFileTree().matching(tree -> tree.include(name + ".class")).getFiles(); | ||
if (files.size() != 1) { | ||
return null; | ||
} | ||
try { | ||
return Files.readAllBytes(files.iterator().next().toPath()); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
}); | ||
return cachedTransformer = AtlasTransformers.remap(mappings, new ClassProviderInheritanceProvider( | ||
Constants.ASM_VERSION, | ||
new CascadingClassProvider(classProviders)) | ||
); | ||
} | ||
} |