Skip to content

Commit 508a8d4

Browse files
author
shehabic
committed
WIP: Adding plugin to proxy all okhttp requests without interceptors
1 parent 06cb859 commit 508a8d4

File tree

13 files changed

+108
-220
lines changed

13 files changed

+108
-220
lines changed

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
22
apply plugin: 'kotlin-android'
33
apply plugin: 'kotlin-android-extensions'
44
apply plugin: 'kotlin-kapt'
5-
apply plugin: 'sherlock-plugin'
5+
//apply plugin: 'sherlock-plugin'
66

77
android {
88
configurations {

build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ buildscript {
55
ext.architecture_components_version = '1.1.1'
66
ext.support_libraries_version = '27.1.1'
77
ext.okhttp_version = '3.11.0'
8-
ext.VERSION_NAME = "v1.0.5"
8+
ext.VERSION_NAME = "v1.0.7"
99

1010
repositories {
1111
google()
@@ -15,11 +15,11 @@ buildscript {
1515
maven { url "https://plugins.gradle.org/m2/" }
1616
}
1717
dependencies {
18-
classpath 'com.android.tools.build:gradle:3.2.1'
18+
classpath 'com.android.tools.build:gradle:3.3.0'
1919
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
20-
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
2120
classpath "com.gradle.publish:plugin-publish-plugin:0.9.9"
22-
classpath 'com.github.shehabic.sherlock:sherlock-plugin:v1.0.5'
21+
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
22+
// classpath 'com.github.shehabic.sherlock:sherlock-plugin:v1.0.6e'
2323
// NOTE: Do not place your application dependencies here; they belong
2424
// in the individual module build.gradle files
2525
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ VERSION_CODE=0.9.2
1818
POM_DEVELOPER_ID=shehabic
1919
POM_DEVELOPER_NAME=Mohamed Shehab Osman
2020

21-
GROUP=com.github.shehabic
21+
GROUP=com.github.shehabic.sherlock
2222
POM_DESCRIPTION=A library to capture android app crashes and show their details
2323
POM_URL=https://github.com/shehabic/sherlock
2424
POM_SCM_URL=https://github.com/shehabic/sherlock

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip

sherlock-no-op/build.gradle

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ apply plugin: 'maven-publish'
44

55
android {
66
compileSdkVersion 28
7-
8-
9-
107
defaultConfig {
118
minSdkVersion 15
129
targetSdkVersion 28
@@ -41,7 +38,7 @@ repositories {
4138
publishing {
4239
publications {
4340
bar(MavenPublication) {
44-
groupId 'com.github.shehabic'
41+
groupId GROUP
4542
artifactId 'sherlock-no-op'
4643
version VERSION_NAME
4744
artifact(bundleReleaseAar)
@@ -53,7 +50,7 @@ publishing {
5350
}
5451
}
5552
}
56-
apply plugin: 'com.github.dcendents.android-maven'
53+
//apply plugin: 'com.github.dcendents.android-maven'
5754

5855

5956
//apply from: rootProject.file('gradle/publish.gradle')

sherlock-plugin/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ task javadocJar(type: Jar) {
4343
publishing {
4444
publications {
4545
maven(MavenPublication) {
46-
groupId 'com.github.shehabic'
46+
groupId GROUP
4747
artifactId 'sherlock-plugin'
4848
version VERSION_NAME
4949
from components.java

sherlock-plugin/src/main/java/com/shehabic/sherlock/plugin/SherlockClassWriter.java

Lines changed: 34 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55
import org.objectweb.asm.ClassVisitor;
66
import org.objectweb.asm.ClassWriter;
77
import org.objectweb.asm.MethodVisitor;
8+
import org.objectweb.asm.Opcodes;
89

910
import static org.objectweb.asm.ClassReader.SKIP_FRAMES;
1011
import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
11-
import static org.objectweb.asm.Opcodes.ASM6;
12-
13-
import org.objectweb.asm.Type;
14-
import org.objectweb.asm.commons.AdviceAdapter;
1512

1613
/**
1714
* @author shehabic
@@ -25,36 +22,9 @@ byte[] instrument(byte[] contents) {
2522
return writer.toByteArray();
2623
}
2724

28-
public static class ClassInfo {
29-
org.objectweb.asm.Type type;
30-
String[] interfaces;
31-
32-
ClassInfo() { }
33-
}
34-
35-
3625
public class SherlockClassVisitor extends ClassVisitor {
37-
38-
private final ClassInfo mClassInfo = new ClassInfo();
39-
40-
public void visit(
41-
int version,
42-
int access,
43-
String className,
44-
String signature,
45-
String superName,
46-
String[] interfaces
47-
) {
48-
super.visit(version, access, className, signature, superName, interfaces);
49-
50-
mClassInfo.type = Type.getObjectType(className);
51-
mClassInfo.interfaces = interfaces;
52-
}
53-
54-
5526
SherlockClassVisitor(ClassVisitor cv) {
56-
super(ASM6, cv);
57-
this.cv = cv;
27+
super(Opcodes.ASM5, cv);
5828
}
5929

6030
@Override
@@ -65,49 +35,44 @@ public MethodVisitor visitMethod(
6535
String signature,
6636
String[] exceptions
6737
) {
68-
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
69-
return new SherlockMethodVisitor(api, mv, access, name, desc);
70-
}
71-
72-
public void visitInnerClass(String name, String outerName, String innerName, int access) {
73-
super.visitInnerClass(name, outerName, innerName, access);
74-
}
75-
76-
public void visitEnd() {
77-
super.visitEnd();
38+
if (name.equals("build")) {
39+
System.out.println("Will do the builder here ... ");
40+
return new SherlockMethodVisitor(super.visitMethod(
41+
access,
42+
name,
43+
desc,
44+
signature,
45+
exceptions
46+
));
47+
}
48+
return super.visitMethod(access, name, desc, signature, exceptions);
7849
}
7950
}
8051

81-
static class SherlockMethodVisitor extends AdviceAdapter {
8252

83-
SherlockMethodVisitor(int api, MethodVisitor mv, int access, String name, String desc) {
84-
super(api, mv, access, name, desc);
53+
private static class SherlockMethodVisitor extends MethodVisitor {
54+
SherlockMethodVisitor(MethodVisitor mv) {
55+
super(Opcodes.ASM5, mv);
8556
}
8657

87-
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
88-
switch (name) {
89-
case "execute":
90-
mv.visitMethodInsn(
91-
INVOKESTATIC,
92-
"com/shehabic/sherlock/interceptors/SherlockOkHttpInterceptor",
93-
"execute",
94-
"(Lokhttp3/Call;)Lokhttp3/Response;",
95-
false
96-
);
97-
break;
98-
case "enqueue":
99-
mv.visitMethodInsn(
100-
INVOKESTATIC,
101-
"com/shehabic/sherlock/interceptors/SherlockOkHttpInterceptor",
102-
"enqueue",
103-
"(Lokhttp3/Call;Lokhttp3/Callback;)V",
104-
false
105-
);
106-
break;
107-
default:
108-
super.visitMethodInsn(opcode, owner, name, desc, itf);
109-
break;
110-
}
58+
// This method will be called before almost all instructions
59+
@Override
60+
public void visitCode() {
61+
// Puts 'this' on top of the stack. If your method is static just delete it
62+
visitVarInsn(Opcodes.ALOAD, 0);
63+
// Takes instance of class "the/full/name/of/your/Class" from top of the stack and put value of field interceptors
64+
// "Ljava/util/List;" is just internal name of java.util.List
65+
visitFieldInsn(Opcodes.GETFIELD, "okhttp3/OkHttpClient$Builder", "interceptors", "Ljava/util/List;");
66+
// Before we call add method of list we have to put target value on top of the stack
67+
visitTypeInsn(Opcodes.NEW, "com/shehabic/sherlock/interceptors/SherlockOkHttpInterceptor");
68+
visitInsn(Opcodes.DUP);
69+
// We have to call classes constructor
70+
// Internal name of constructor - <init>
71+
// ()V - signature of method. () - method doesn't have parameters. V - method returns void
72+
visitMethodInsn(Opcodes.INVOKESPECIAL, "com/shehabic/sherlock/interceptors/SherlockOkHttpInterceptor", "<init>", "()V", false);
73+
// So on top of the stack we have initialized instance of com/shehabic/sherlock/interceptors/SherlockOkHttpInterceptor
74+
// Now we can put it into list
75+
visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
11176
}
11277
}
11378
}

sherlock-plugin/src/main/java/com/shehabic/sherlock/plugin/SherlockInstrumentation.java

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import com.google.common.io.ByteStreams;
55
import com.google.common.io.Files;
66

7+
import org.apache.commons.io.FileUtils;
8+
79
import java.io.BufferedInputStream;
810
import java.io.File;
911
import java.io.FileInputStream;
@@ -14,16 +16,14 @@
1416
import java.util.jar.JarEntry;
1517
import java.util.jar.JarInputStream;
1618

17-
import org.apache.commons.io.FileUtils;
19+
class SherlockInstrumentation {
1820

19-
public class SherlockInstrumentation {
20-
ClassLoader classLoader;
21+
private static final String CLASS_TO_INSTRUMENT = "okhttp3/OkHttpClient$Builder";
2122

22-
public SherlockInstrumentation(ClassLoader cl) {
23-
this.classLoader = cl;
23+
SherlockInstrumentation(ClassLoader cl) {
2424
}
2525

26-
public void instrumentClassesInDir(
26+
void instrumentClassesInDir(
2727
final File dir,
2828
int depth,
2929
String outDir,
@@ -41,16 +41,7 @@ public void instrumentClassesInDir(
4141
if (file.isDirectory()) {
4242
++depth;
4343
String fileName = file.getName();
44-
this.instrumentClassesInDir(
45-
file,
46-
depth,
47-
(
48-
new StringBuilder(1 +
49-
String.valueOf(outDir).length() +
50-
String.valueOf(fileName).length())
51-
).append(outDir).append(fileName).append("/").toString(),
52-
changed
53-
);
44+
this.instrumentClassesInDir(file, depth, outDir + fileName + "/", changed);
5445
} else if (dirName.endsWith(".class")) {
5546
String outputDir = String.valueOf(outDir);
5647
String fileName = dirName;
@@ -69,12 +60,7 @@ public void instrumentClassesInDir(
6960
}
7061
}
7162

72-
public void instrumentClassFile(
73-
final File f,
74-
String outDir,
75-
Map<File, Status> changed
76-
) throws IOException {
77-
String filename = String.valueOf(f);
63+
private void instrumentClassFile(final File f, String outDir, Map<File, Status> changed) throws IOException {
7864
File outFile = new File(outDir);
7965
outFile.getParentFile().mkdirs();
8066
outFile.createNewFile();
@@ -87,46 +73,43 @@ public void instrumentClassFile(
8773
}
8874

8975
InputStream is = new BufferedInputStream(new FileInputStream(f));
90-
byte[] fileBytes = ByteStreams.toByteArray(is);
76+
// byte[] fileBytes = ByteStreams.toByteArray(is);
9177
is.close();
9278

93-
try {
94-
byte[] out = this.instrument(fileBytes);
95-
FileOutputStream fos = new FileOutputStream(outFile);
96-
fos.write(out);
97-
fos.close();
98-
} catch (Exception e1) {
99-
System.out.print("Error here ----------->");
100-
e1.printStackTrace();
101-
}
79+
Files.copy(f, outFile);
80+
// try {
81+
// byte[] out = this.instrument(fileBytes);
82+
// FileOutputStream fos = new FileOutputStream(outFile);
83+
// fos.write(out);
84+
// fos.close();
85+
// } catch (Exception e) {
86+
// System.out.print("[Sherlock Plugin Error]: " + e.getLocalizedMessage());
87+
// e.printStackTrace();
88+
// Files.copy(f, outFile);
89+
// }
10290

10391
}
10492

105-
public void instrumentClassesInJar(File inJarFile, File outDir) throws IOException {
106-
JarInputStream jis = new JarInputStream(new BufferedInputStream(new FileInputStream(
107-
inJarFile)));
93+
void instrumentClassesInJar(File inJarFile, File outDir) throws IOException {
94+
JarInputStream jis = new JarInputStream(new BufferedInputStream(new FileInputStream(inJarFile)));
10895

10996
JarEntry inEntry;
11097
while ((inEntry = jis.getNextJarEntry()) != null) {
11198
String name = inEntry.getName();
11299
byte[] entryBytes = ByteStreams.toByteArray(jis);
113100
jis.closeEntry();
114-
if (name.endsWith(".class") && this.checkIfInstrumentable(name)) {
101+
if (name.endsWith(".class") && this.isInstrumentable(name)) {
115102
try {
116103
entryBytes = this.instrument(entryBytes);
117104
} catch (Exception e) {
118-
105+
System.out.println("[Sherlock Plugin Error]: " + e.getLocalizedMessage());
119106
e.printStackTrace();
120107
}
121108
}
122109

123110
if (!inEntry.isDirectory()) {
124111
String var8 = String.valueOf(outDir);
125-
File outFile = new File((
126-
new StringBuilder(1 +
127-
String.valueOf(var8).length() +
128-
String.valueOf(name).length())
129-
).append(var8).append("/").append(name).toString());
112+
File outFile = new File(var8 + "/" + name);
130113
outFile.getParentFile().mkdirs();
131114
outFile.createNewFile();
132115
FileOutputStream fos = new FileOutputStream(outFile);
@@ -138,11 +121,11 @@ public void instrumentClassesInJar(File inJarFile, File outDir) throws IOExcepti
138121
jis.close();
139122
}
140123

141-
public boolean checkIfInstrumentable(String name) {
142-
return name.startsWith("okhttp3/Call");
124+
private boolean isInstrumentable(String name) {
125+
return name.startsWith(CLASS_TO_INSTRUMENT);
143126
}
144127

145-
public byte[] instrument(final byte[] in) {
128+
private byte[] instrument(final byte[] in) {
146129
SherlockClassWriter cw = new SherlockClassWriter();
147130

148131
return cw.instrument(in);
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
package com.shehabic.sherlock.plugin;
22

3-
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension;
4-
3+
import com.android.build.gradle.BaseExtension;
54
import org.gradle.api.Plugin;
65
import org.gradle.api.Project;
76

87
class SherlockPlugin implements Plugin<Project> {
98
@Override
109
public void apply(Project project) {
11-
Object ext = project.getExtensions().findByName("android");
12-
BaseAppModuleExtension androidExt = (BaseAppModuleExtension) ext;
13-
if (androidExt != null) {
14-
androidExt.registerTransform(new SherlockTransformer(project));
10+
BaseExtension androidExt = (BaseExtension) project.getExtensions().getByName("android");
11+
12+
if (project.getPlugins().findPlugin("com.android.application") != null) {
1513
project.getExtensions().create("SherlockExtension", SherlockExtension.class);
14+
androidExt.registerTransform(new SherlockTransformer(project));
15+
} else if (project.getPlugins().findPlugin("com.android.library") != null) {
16+
throw new RuntimeException("Sherlock cannot be applied to library project", null);
1617
} else {
18+
throw new RuntimeException("Need android application plugin to be applied first", null);
1719
}
1820
}
1921
}

0 commit comments

Comments
 (0)