aboutsummaryrefslogtreecommitdiff
path: root/sandbox/src/main/java/org/robolectric/internal/bytecode/NativeCallHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/src/main/java/org/robolectric/internal/bytecode/NativeCallHandler.java')
-rw-r--r--sandbox/src/main/java/org/robolectric/internal/bytecode/NativeCallHandler.java137
1 files changed, 0 insertions, 137 deletions
diff --git a/sandbox/src/main/java/org/robolectric/internal/bytecode/NativeCallHandler.java b/sandbox/src/main/java/org/robolectric/internal/bytecode/NativeCallHandler.java
deleted file mode 100644
index 89034d63f..000000000
--- a/sandbox/src/main/java/org/robolectric/internal/bytecode/NativeCallHandler.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package org.robolectric.internal.bytecode;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Set;
-import java.util.TreeSet;
-import javax.annotation.Nonnull;
-
-/**
- * Handler for native calls instrumented by ClassInstrumentor.
- *
- * <p>Native Calls can either be instrumented as no-op calls (returning a default value or 0 or
- * null) or throw an exception. This helper class helps maintain a list of exemptions to indicates
- * which native calls should be no-op and never throw.
- */
-public class NativeCallHandler {
-
- private final File exemptionsFile;
- private final boolean writeExemptions;
- private final boolean throwOnNatives;
- private final Set<String> descriptors = new TreeSet<>();
-
- /**
- * Initializes the native calls handler.
- *
- * @param exemptionsFile The exemptions file to read from and/or to generate.
- * @param writeExemptions When true, native calls are added to the exemption list.
- * @param throwOnNatives Whether native calls should throw by default unless their signature is
- * listed in the exemption list. When false, all native calls become no-op.
- * @throws IOException if there's an issue reading an existing exemption list.
- */
- public NativeCallHandler(
- @Nonnull File exemptionsFile, boolean writeExemptions, boolean throwOnNatives)
- throws IOException {
- this.exemptionsFile = exemptionsFile;
- this.writeExemptions = writeExemptions;
- this.throwOnNatives = throwOnNatives;
-
- if (exemptionsFile.exists()) {
- readExemptionsList(exemptionsFile);
- }
- }
-
- private String getExemptionFileName() {
- return exemptionsFile.getName();
- }
-
- private void readExemptionsList(File exemptionsFile) throws IOException {
- try (BufferedReader reader =
- new BufferedReader(new FileReader(exemptionsFile.getPath(), UTF_8))) {
- String line;
- while ((line = reader.readLine()) != null) {
- // Sanitize input. Ignore empty lines and commented lines starting with #.
- line = sanitize(line.trim());
- if (line.isEmpty() || line.charAt(0) == '#') {
- continue;
- }
- descriptors.add(line);
- }
- }
- System.out.println(
- "Loaded " + descriptors.size() + " exemptions from " + exemptionsFile.getPath());
- }
-
- public void writeExemptionsList() throws IOException {
- try (BufferedWriter writer =
- new BufferedWriter(new FileWriter(exemptionsFile.getPath(), UTF_8))) {
- for (String descriptor : descriptors) {
- writer.write(descriptor);
- writer.write('\n');
- }
- }
- System.out.println(
- "Wrote " + descriptors.size() + " exemptions to " + exemptionsFile.getPath());
- }
-
- /**
- * Adds the method description to the native call exemption list if {@link #writeExemptions} is
- * set.
- */
- public void logNativeCall(@Nonnull String descriptor) {
- if (!writeExemptions) {
- return;
- }
- descriptors.add(sanitize(descriptor));
- }
-
- /** Returns whether the ClassInstrumentor should generate an exception or a no-op bytecode. */
- public boolean shouldThrow(@Nonnull String descriptor) {
- return throwOnNatives && !descriptors.contains(sanitize(descriptor));
- }
-
- private String sanitize(String descriptor) {
- // Post-processing of the exemptions files is made complicated by the presence of $ signs
- // in the FQCN. Instead of escaping them, just replace them by another unused character
- // that is not so sensitive to shell or make mangling.
- return descriptor.replace('$', '^');
- }
-
- /**
- * Returns the detailed message to be used by the ClassInstrumentor in the generated bytecode.
- *
- * @param descriptor The ASM descriptor as it should be written in the exemption file.
- * @param className The fully qualified class name, used for the user description.
- * @param methodName The method name, used for the user description.
- */
- public String getExceptionMessage(
- @Nonnull String descriptor, @Nonnull String className, @Nonnull String methodName) {
- // The shadow message is merely a hint based on the last component of the FQCN, which is
- // typically the pattern used for shadow classes.
- String shadowHint =
- "Shadow" + className.replaceAll("[^.]+\\.", "").replaceAll("\\$.*", "") + ".java";
- // The message below tries to educate the user that shadow overrides are not necessarily
- // needed nor desired for trivial cases that are better covered by a no-op return operation.
- return "Unexpected Robolectric native method call to '"
- + className
- + "#"
- + methodName
- + "()'.\n"
- + "Option 1: If customizing this method is useful, add an implementation in "
- + shadowHint
- + ".\n"
- + "Option 2: If this method just needs to trivially return 0 or null, please add an"
- + " exemption entry for\n"
- + " "
- + sanitize(descriptor)
- + "\n"
- + "to exemption file "
- + getExemptionFileName();
- }
-}