From f10fdf4a2db83c35fbc981b68f4845cdd375fec4 Mon Sep 17 00:00:00 2001 From: "Renat I. Kashapov" Date: Sat, 17 Oct 2020 10:46:34 +0300 Subject: [PATCH 1/9] Deleted .idea and .gradle from index --- .../executionHistory/executionHistory.lock | Bin 17 -> 0 bytes .gradle/6.3/fileChanges/last-build.bin | Bin 1 -> 0 bytes .gradle/6.3/fileHashes/fileHashes.lock | Bin 17 -> 0 bytes .gradle/6.3/gc.properties | 0 .../6.5/executionHistory/executionHistory.bin | Bin 20071 -> 0 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 0 bytes .gradle/6.5/fileChanges/last-build.bin | Bin 1 -> 0 bytes .gradle/6.5/fileHashes/fileHashes.bin | Bin 18697 -> 0 bytes .gradle/6.5/fileHashes/fileHashes.lock | Bin 17 -> 0 bytes .gradle/6.5/gc.properties | 0 .../buildOutputCleanup.lock | Bin 17 -> 0 bytes .gradle/buildOutputCleanup/cache.properties | 2 -- .gradle/checksums/checksums.lock | Bin 17 -> 0 bytes .gradle/vcs-1/gc.properties | 0 .idea/.gitignore | 3 --- .idea/compiler.xml | 10 --------- .idea/gradle.xml | 18 ---------------- .idea/jarRepositories.xml | 20 ------------------ .idea/misc.xml | 7 ------ .idea/vcs.xml | 6 ------ 20 files changed, 66 deletions(-) delete mode 100644 .gradle/6.3/executionHistory/executionHistory.lock delete mode 100644 .gradle/6.3/fileChanges/last-build.bin delete mode 100644 .gradle/6.3/fileHashes/fileHashes.lock delete mode 100644 .gradle/6.3/gc.properties delete mode 100644 .gradle/6.5/executionHistory/executionHistory.bin delete mode 100644 .gradle/6.5/executionHistory/executionHistory.lock delete mode 100644 .gradle/6.5/fileChanges/last-build.bin delete mode 100644 .gradle/6.5/fileHashes/fileHashes.bin delete mode 100644 .gradle/6.5/fileHashes/fileHashes.lock delete mode 100644 .gradle/6.5/gc.properties delete mode 100644 .gradle/buildOutputCleanup/buildOutputCleanup.lock delete mode 100644 .gradle/buildOutputCleanup/cache.properties delete mode 100644 .gradle/checksums/checksums.lock delete mode 100644 .gradle/vcs-1/gc.properties delete mode 100644 .idea/.gitignore delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/jarRepositories.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/vcs.xml diff --git a/.gradle/6.3/executionHistory/executionHistory.lock b/.gradle/6.3/executionHistory/executionHistory.lock deleted file mode 100644 index a7604be1ef6e9a790cafe5f2e4f8b638218152b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 TcmZRUG;}#Ck+sR10RnOWA&mnv diff --git a/.gradle/6.3/fileChanges/last-build.bin b/.gradle/6.3/fileChanges/last-build.bin deleted file mode 100644 index f76dd238ade08917e6712764a16a22005a50573d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1 IcmZPo000310RR91 diff --git a/.gradle/6.3/fileHashes/fileHashes.lock b/.gradle/6.3/fileHashes/fileHashes.lock deleted file mode 100644 index 2b22044621848a8e6f14688644e644e50c0b6932..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 TcmZP$SDwo3m;F4I0Rl__B^Cou diff --git a/.gradle/6.3/gc.properties b/.gradle/6.3/gc.properties deleted file mode 100644 index e69de29..0000000 diff --git a/.gradle/6.5/executionHistory/executionHistory.bin b/.gradle/6.5/executionHistory/executionHistory.bin deleted file mode 100644 index ca603136957a3946fa69672fa1e9609598fd0231..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20071 zcmeI)PiWIn90%}p9d(Mbco+`Eiwvi*CH-UCO$Ax$=9K->)jGjLNYmFPTh_#vv~`M3 zWCy`I9S)fY124i*CklEQ{s9jIZ|c>f2T{a>HxV>#8n#gn9qU2l8|cd;@4esey-#1$ zLm)ARX=ZqTV1izm}eOOR=eWy%R5ikZM#43H1~G7&kx+QeSM$Ph7tl0fB*y_009U<00Izz z00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZafqy|D z#4x^H_Q!rY#sf&-dBO zg&pB@eP^PHhJr+8Ma_|@WRix(YF65ET(Xp6_n9L@U9rAyF%j<`5_<>xyWLpD4&Lc9 z5T8;_%bY2eR83|rRnOES*P4KTNqBp8!nh&@g>XDO&a4@Ba>5`D&#PKm{!Z#+2M#^` zdGC||;`PDK^^IR&?}}tsM$YQ*!#Q{}9AcfXWr+~1cS$jb&li~Vhrt&11x_q5)* z^x;-b!qy~6#nf&XRJZR7mP*VLz}t-iti3OD2dvw$HshQ_Lzv&C334WH!>lB00Iag zfB*srAbC+xP(l(Q_F9 diff --git a/.gradle/6.5/fileHashes/fileHashes.lock b/.gradle/6.5/fileHashes/fileHashes.lock deleted file mode 100644 index b89035bdbee3e3b6d10f21e051d4d887347333a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 UcmZQ}>QJ4zd*P?03=qHu05u&1g#Z8m diff --git a/.gradle/6.5/gc.properties b/.gradle/6.5/gc.properties deleted file mode 100644 index e69de29..0000000 diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock deleted file mode 100644 index 125640c0661a242e02c3c8aa44ade74fd4ef2016..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 TcmZRcxr{wXET`Ur0RkcbB@6>C diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties deleted file mode 100644 index b774acd..0000000 --- a/.gradle/buildOutputCleanup/cache.properties +++ /dev/null @@ -1,2 +0,0 @@ -#Thu Oct 08 23:16:29 MSK 2020 -gradle.version=6.3 diff --git a/.gradle/checksums/checksums.lock b/.gradle/checksums/checksums.lock deleted file mode 100644 index 2cf264e3089226e34e453839915ee03153a95c53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 TcmZR+wZ?0Uv*dYO1}FdkGnxbN diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index c8b5c9a..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 87ca0fc..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index fdc392f..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index b0ec460..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 2f18960bceca04f3d7051f7ea9f96d1309a8fd45 Mon Sep 17 00:00:00 2001 From: "Renat I. Kashapov" Date: Mon, 2 Nov 2020 09:08:59 +0300 Subject: [PATCH 2/9] V 10. Added vim swap files to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8f242ff..38a19dd 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ # Mobile Tools for Java (J2ME) .mtj.tmp/ +# vim swap files +*.swp + # Package Files # *.jar !gradle-wrapper.jar From aa842219424e5d5639ae2f790ef2da820393b984 Mon Sep 17 00:00:00 2001 From: "Renat I. Kashapov" Date: Thu, 5 Nov 2020 09:52:18 +0300 Subject: [PATCH 3/9] V11. A.java deleted --- src/main/java/A.java | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/main/java/A.java diff --git a/src/main/java/A.java b/src/main/java/A.java deleted file mode 100644 index 6be5562..0000000 --- a/src/main/java/A.java +++ /dev/null @@ -1,5 +0,0 @@ -public class A { - public static void main(String ... args){ - System.out.println("Hello, gradle + git!"); - } -} From e9a2512c951a385b2c4235d3be44487235a5f91c Mon Sep 17 00:00:00 2001 From: "Renat I. Kashapov" Date: Thu, 12 Nov 2020 09:18:03 +0300 Subject: [PATCH 4/9] v11. Unsuccessfull attempt to solve problem with JDK Proxy. --- hw05-AOPprincipes/build.gradle | 17 +++ .../src/main/java/aop/AOPClassLoader.java | 103 ++++++++++++++++++ .../main/java/aop/AOPInvocationHandler.java | 15 +++ hw05-AOPprincipes/src/main/java/aop/App.java | 29 +++++ hw05-AOPprincipes/src/main/java/aop/Log.java | 8 ++ .../src/main/java/aop/Useful.java | 7 ++ .../src/main/java/aop/UsefulImpl.java | 25 +++++ settings.gradle | 1 + 8 files changed, 205 insertions(+) create mode 100644 hw05-AOPprincipes/build.gradle create mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/App.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/Log.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/Useful.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java diff --git a/hw05-AOPprincipes/build.gradle b/hw05-AOPprincipes/build.gradle new file mode 100644 index 0000000..2e38adb --- /dev/null +++ b/hw05-AOPprincipes/build.gradle @@ -0,0 +1,17 @@ +plugins { + id 'java' + id 'application' +} + +group 'ru.otus' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' +} + +mainClassName = 'aop.App' diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java b/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java new file mode 100644 index 0000000..a75e082 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java @@ -0,0 +1,103 @@ +package aop; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.nio.file.Files; +import java.util.*; + +public class AOPClassLoader extends ClassLoader { + private List annotatedMethods; + + Class defineClass(String className) throws IOException { + File file = new File(getFileName(className)); + byte[] bytecode = Files.readAllBytes(file.toPath()); + return super.defineClass("aop." + className, bytecode, 0, bytecode.length); + } + + Class defineAppClass() throws IOException { + return this.defineClass("App"); + } + + String getFileName(String className) { + return "build" + File.separator + "classes" + File.separator + "java" + File.separator + + "main" + File.separator + "aop" + File.separator + className + ".class"; + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class resultClass = super.loadClass(name, resolve); + Method[] methods = resultClass.getMethods(); + List> markedInterfacesList = new ArrayList<>(); + annotatedMethods = new ArrayList<>(); + for (Method method : methods) { + if (method.isAnnotationPresent(Log.class)) { + determinateMarkedInterfaces(method, resultClass.getInterfaces(), markedInterfacesList); + annotatedMethods.add(method); + } + } + Field [] fields = resultClass.getFields(); + methods[0].se + if(!markedInterfacesList.isEmpty()) { + AOPInvocationHandler aopInvocationHandler = new AOPInvocationHandler(); + Method [] proxyMethods = Proxy.newProxyInstance(this, markedInterfacesList + .toArray(this.getClass().getInterfaces())/*передать Class []*/, aopInvocationHandler). + getClass().getMethods(); + for (int i =0; i< methods.length; i++){ + i. + if(methods[i].isAnnotationPresent(Log.class)){ + methods[i]=findMethodWithSameSignatureInArray(methods[i],proxyMethods); + } + System.out.println("Annotated method is " + methods[i].getName()); + } + } + return resultClass; + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + return super.loadClass(name); + } + + private void determinateMarkedInterfaces(Method method, Class[] interfaces, List> chosenInterfacesList) { + if (interfaces.length != 0) { + Arrays.stream(interfaces) + .filter(i -> Arrays.stream(i.getDeclaredMethods()) + .filter(m -> compareMethodSignature(m,method)).count() > 0) + .forEach(chosenInterfacesList::add); +// Arrays.stream(interfaces).forEach(i -> determinateCarryingInterfaces(method, i.getInterfaces(), chosenInterfacesSet)); + for(int i =0; i< interfaces.length; i++){ + determinateMarkedInterfaces(method, interfaces[i].getInterfaces(), chosenInterfacesList); + } + } + } + private boolean compareMethodSignature(Method method1, Method method2){ + Class [] parameterTypesM1 = method1.getParameterTypes(); + Class [] parameterTypesM2 = method2.getParameterTypes(); + if(parameterTypesM1.length!=parameterTypesM2.length) {return false;} + else { + for (int i = 0; i < parameterTypesM1.length; i++) { + if(parameterTypesM1[i]!=parameterTypesM2[i]) { + return false; + } + } + } + if (!method1.getName().equals(method2.getName())){ + return false; + } + return true; + } + + private Method findMethodWithSameSignatureInArray(Method method, Method [] proxyMethods){ + for(Method proxyMethod: proxyMethods){ + if(compareMethodSignature(proxyMethod, method)){ + return proxyMethod; + } + } + return null; + } + +} \ No newline at end of file diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java b/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java new file mode 100644 index 0000000..42b177f --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java @@ -0,0 +1,15 @@ +package aop; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Arrays; + +public class AOPInvocationHandler implements InvocationHandler { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if(method.isAnnotationPresent(Log.class)) { + Arrays.stream(args).forEach(System.out::println); + } + return method.invoke(proxy, new Object[]{args}); + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/App.java b/hw05-AOPprincipes/src/main/java/aop/App.java new file mode 100644 index 0000000..d3004d1 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/App.java @@ -0,0 +1,29 @@ +package aop; + +import java.lang.reflect.Method; + +public class App { + static public void main(String ... args) { + Class classLoaderClass = App.class.getClassLoader().getClass(); + if( classLoaderClass != AOPClassLoader.class) { + AOPClassLoader aopClassLoader = new AOPClassLoader(); + try { + Class loadClass = aopClassLoader.defineAppClass(); + Method method = loadClass.getMethod("main", new Class[]{String[].class}); + method.invoke(null, new Object[]{args}); + } catch (Exception e) { + e.printStackTrace(); + } + } + else{ + try { + Useful useful = new UsefulImpl(); + useful.sayHelloTo("Otus"); + System.out.println("App.main is run from AOPClassloader"); + } + catch (Exception e){ + e.printStackTrace(); + } + } + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/Log.java b/hw05-AOPprincipes/src/main/java/aop/Log.java new file mode 100644 index 0000000..691d2fe --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/Log.java @@ -0,0 +1,8 @@ +package aop; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Log { +} diff --git a/hw05-AOPprincipes/src/main/java/aop/Useful.java b/hw05-AOPprincipes/src/main/java/aop/Useful.java new file mode 100644 index 0000000..b6f7186 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/Useful.java @@ -0,0 +1,7 @@ +package aop; + +public interface Useful { + public void sayHelloTo(); + public void sayHelloTo(String name); + public void sayHelloTo(String name, short howMany); +} diff --git a/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java b/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java new file mode 100644 index 0000000..1630b36 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java @@ -0,0 +1,25 @@ +package aop; + +public class UsefulImpl implements Useful { + public UsefulImpl(){} + + @Override + public void sayHelloTo() { + System.out.println("Hello!"); + System.out.println("Constructor is " + this.getClass().getClassLoader().getName()); + } + + @Log + @Override + public void sayHelloTo(String name) { + System.out.println("Hello, " + name + "!"); + } + + @Override + public void sayHelloTo(String name, short howMany) { + for (int i = 0; i < howMany; i++) { + System.out.println("Hello, " + name + "!"); + } + } + +} diff --git a/settings.gradle b/settings.gradle index 9a32c0b..5b43c31 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,3 @@ rootProject.name = 'otus_hw' +include 'hw05-AOPprincipes' From 4746e3f073b9d51c20281d86d860106a14b8b252 Mon Sep 17 00:00:00 2001 From: "Renat I. Kashapov" Date: Sat, 21 Nov 2020 13:11:25 +0300 Subject: [PATCH 5/9] v12. Unsuccessfull attempt to solve problem with CGLIB. --- hw05-AOPprincipes/build.gradle | 7 ++ .../src/main/java/aop/AOPClassLoader.java | 88 +++++++++++++------ .../main/java/aop/AOPInvocationHandler.java | 4 +- hw05-AOPprincipes/src/main/java/aop/App.java | 2 +- .../src/main/java/aop/ClassPrinter.java | 50 +++++++++++ .../src/main/java/aop/Useful.java | 7 +- .../src/main/java/aop/UsefulImpl.java | 15 ++-- 7 files changed, 130 insertions(+), 43 deletions(-) create mode 100644 hw05-AOPprincipes/src/main/java/aop/ClassPrinter.java diff --git a/hw05-AOPprincipes/build.gradle b/hw05-AOPprincipes/build.gradle index 2e38adb..36c434f 100644 --- a/hw05-AOPprincipes/build.gradle +++ b/hw05-AOPprincipes/build.gradle @@ -12,6 +12,13 @@ repositories { dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' +// implementation 'com.google.guava:guava' + // https://mvnrepository.com/artifact/com.google.guava/guava + compile group: 'com.google.guava', name: 'guava', version: '30.0-jre' +// https://mvnrepository.com/artifact/cglib/cglib + compile group: 'cglib', name: 'cglib', version: '3.3.0' +// https://mvnrepository.com/artifact/org.ow2.asm/asm + compile group: 'org.ow2.asm', name: 'asm', version: '9.0' } mainClassName = 'aop.App' diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java b/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java index a75e082..cb92ece 100644 --- a/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java +++ b/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java @@ -1,13 +1,24 @@ package aop; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.FixedValue; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.Proxy; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; + +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; +import java.io.ObjectOutputStream; import java.lang.reflect.Method; -import java.lang.reflect.Proxy; import java.nio.file.Files; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.objectweb.asm.Opcodes.ASM9; public class AOPClassLoader extends ClassLoader { private List annotatedMethods; @@ -39,20 +50,37 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE annotatedMethods.add(method); } } - Field [] fields = resultClass.getFields(); - methods[0].se - if(!markedInterfacesList.isEmpty()) { - AOPInvocationHandler aopInvocationHandler = new AOPInvocationHandler(); - Method [] proxyMethods = Proxy.newProxyInstance(this, markedInterfacesList - .toArray(this.getClass().getInterfaces())/*передать Class []*/, aopInvocationHandler). - getClass().getMethods(); - for (int i =0; i< methods.length; i++){ - i. - if(methods[i].isAnnotationPresent(Log.class)){ - methods[i]=findMethodWithSameSignatureInArray(methods[i],proxyMethods); + if (!markedInterfacesList.isEmpty()) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(resultClass); + MethodInterceptor methodInterceptor = (obj, method, args, proxy) -> { + if (method.isAnnotationPresent(Log.class)) { + for (int i = 0; i < args.length; i++) { + System.out.println(args[i]); + } } - System.out.println("Annotated method is " + methods[i].getName()); + return proxy.invokeSuper(obj, args); + }; + enhancer.setCallback(methodInterceptor); + Class testedClass = enhancer.create(new Class[]{}, new Object[]{}).getClass(); + try { + ClassReader cr = new ClassReader("aop.UsefulImpl"); + ClassWriter cw = new ClassWriter(0); +/* ClassVisitor cv = new ClassVisitor(ASM9,cw) { + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces); + } + };*/ + ClassPrinter cp = new ClassPrinter(); + cr.accept(cp, 0); + System.out.println("aa"); + } catch (IOException e) { + e.printStackTrace(); } + Useful useful = (UsefulImpl) enhancer.create(); + System.out.println(useful.sayHelloTo("name")); + System.out.println(new UsefulImpl().sayHelloTo("a")); } return resultClass; } @@ -66,38 +94,40 @@ private void determinateMarkedInterfaces(Method method, Class[] interfaces, L if (interfaces.length != 0) { Arrays.stream(interfaces) .filter(i -> Arrays.stream(i.getDeclaredMethods()) - .filter(m -> compareMethodSignature(m,method)).count() > 0) + .filter(m -> compareMethodSignature(m, method)).count() > 0) .forEach(chosenInterfacesList::add); // Arrays.stream(interfaces).forEach(i -> determinateCarryingInterfaces(method, i.getInterfaces(), chosenInterfacesSet)); - for(int i =0; i< interfaces.length; i++){ + for (int i = 0; i < interfaces.length; i++) { determinateMarkedInterfaces(method, interfaces[i].getInterfaces(), chosenInterfacesList); } } } - private boolean compareMethodSignature(Method method1, Method method2){ - Class [] parameterTypesM1 = method1.getParameterTypes(); - Class [] parameterTypesM2 = method2.getParameterTypes(); - if(parameterTypesM1.length!=parameterTypesM2.length) {return false;} - else { + + private boolean compareMethodSignature(Method method1, Method method2) { + Class[] parameterTypesM1 = method1.getParameterTypes(); + Class[] parameterTypesM2 = method2.getParameterTypes(); + if (parameterTypesM1.length != parameterTypesM2.length) { + return false; + } else { for (int i = 0; i < parameterTypesM1.length; i++) { - if(parameterTypesM1[i]!=parameterTypesM2[i]) { + if (parameterTypesM1[i] != parameterTypesM2[i]) { return false; } } } - if (!method1.getName().equals(method2.getName())){ - return false; + if (method1.getName().equals(method2.getName())) { + return true; } - return true; + return false; } - private Method findMethodWithSameSignatureInArray(Method method, Method [] proxyMethods){ + /* private Method findMethodWithSameSignatureInArray(Method method, Method [] proxyMethods){ for(Method proxyMethod: proxyMethods){ if(compareMethodSignature(proxyMethod, method)){ return proxyMethod; } } return null; - } + }*/ } \ No newline at end of file diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java b/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java index 42b177f..530730d 100644 --- a/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java +++ b/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java @@ -1,10 +1,12 @@ package aop; -import java.lang.reflect.InvocationHandler; +import net.sf.cglib.proxy.InvocationHandler; + import java.lang.reflect.Method; import java.util.Arrays; public class AOPInvocationHandler implements InvocationHandler { + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.isAnnotationPresent(Log.class)) { diff --git a/hw05-AOPprincipes/src/main/java/aop/App.java b/hw05-AOPprincipes/src/main/java/aop/App.java index d3004d1..67edca1 100644 --- a/hw05-AOPprincipes/src/main/java/aop/App.java +++ b/hw05-AOPprincipes/src/main/java/aop/App.java @@ -4,7 +4,7 @@ public class App { static public void main(String ... args) { - Class classLoaderClass = App.class.getClassLoader().getClass(); + Class classLoaderClass = App.class.getClassLoader().getClass(); if( classLoaderClass != AOPClassLoader.class) { AOPClassLoader aopClassLoader = new AOPClassLoader(); try { diff --git a/hw05-AOPprincipes/src/main/java/aop/ClassPrinter.java b/hw05-AOPprincipes/src/main/java/aop/ClassPrinter.java new file mode 100644 index 0000000..bf9d6e1 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/ClassPrinter.java @@ -0,0 +1,50 @@ +package aop; + +import org.objectweb.asm.*; + +import static org.objectweb.asm.Opcodes.ASM9; + +public class ClassPrinter extends ClassVisitor { + public ClassPrinter() { + super(ASM9); + } + + public void visit(int version, int access, String name, + String signature, String superName, String[] interfaces) { + System.out.println(name + " extends " + superName + " " + version + " {"); + } + + public void visitSource(String source, String debug) { + } + + public void visitOuterClass(String owner, String name, String desc) { + } + + public AnnotationVisitor visitAnnotation(String desc, + boolean visible) { + return null; + } + + public void visitAttribute(Attribute attr) { + } + + public void visitInnerClass(String name, String outerName, + String innerName, int access) { + } + + public FieldVisitor visitField(int access, String name, String desc, + String signature, Object value) { + System.out.println(" " + desc + " " + name); + return null; + } + + public MethodVisitor visitMethod(int access, String name, + String desc, String signature, String[] exceptions) { + System.out.println(" " + name + desc); + return null; + } + + public void visitEnd() { + System.out.println("}"); + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/Useful.java b/hw05-AOPprincipes/src/main/java/aop/Useful.java index b6f7186..e06dfa6 100644 --- a/hw05-AOPprincipes/src/main/java/aop/Useful.java +++ b/hw05-AOPprincipes/src/main/java/aop/Useful.java @@ -1,7 +1,8 @@ package aop; public interface Useful { - public void sayHelloTo(); - public void sayHelloTo(String name); - public void sayHelloTo(String name, short howMany); + public String sayHelloTo(); + public String sayHelloTo(String name); + public String sayHelloTo(String name, short howMany); } + diff --git a/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java b/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java index 1630b36..7b7bfb5 100644 --- a/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java +++ b/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java @@ -4,22 +4,19 @@ public class UsefulImpl implements Useful { public UsefulImpl(){} @Override - public void sayHelloTo() { - System.out.println("Hello!"); - System.out.println("Constructor is " + this.getClass().getClassLoader().getName()); + public String sayHelloTo() { + return "Hello!"; } @Log @Override - public void sayHelloTo(String name) { - System.out.println("Hello, " + name + "!"); + public String sayHelloTo(String name) { + return "Hello, " + name +"!"; } @Override - public void sayHelloTo(String name, short howMany) { - for (int i = 0; i < howMany; i++) { - System.out.println("Hello, " + name + "!"); - } + public String sayHelloTo(String name, short howMany) { + return "Hello, " + name + "! " + howMany + " times."; } } From 052bb7b053006a905de882b7b2197ab5be37dc1e Mon Sep 17 00:00:00 2001 From: "Renat I. Kashapov" Date: Sat, 28 Nov 2020 00:13:06 +0300 Subject: [PATCH 6/9] v13. Unfinished project. --- hw05-AOPprincipes/build.gradle | 2 + .../src/main/java/aop/AOPClassLoader.java | 26 +- ...OPMethodTransformationByLogAnnotation.java | 46 ++++ .../src/main/java/aop/AOPMethodVisitor.java | 237 ++++++++++++++++++ hw05-AOPprincipes/src/main/java/aop/App.java | 7 +- .../src/main/java/aop/Useful.java | 6 +- .../src/main/java/aop/UsefulImpl.java | 14 +- 7 files changed, 308 insertions(+), 30 deletions(-) create mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPMethodTransformationByLogAnnotation.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPMethodVisitor.java diff --git a/hw05-AOPprincipes/build.gradle b/hw05-AOPprincipes/build.gradle index 36c434f..d252df3 100644 --- a/hw05-AOPprincipes/build.gradle +++ b/hw05-AOPprincipes/build.gradle @@ -19,6 +19,8 @@ dependencies { compile group: 'cglib', name: 'cglib', version: '3.3.0' // https://mvnrepository.com/artifact/org.ow2.asm/asm compile group: 'org.ow2.asm', name: 'asm', version: '9.0' +// https://mvnrepository.com/artifact/org.ow2.asm/asm-util + compile group: 'org.ow2.asm', name: 'asm-util', version: '9.0' } mainClassName = 'aop.App' diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java b/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java index cb92ece..eae18c7 100644 --- a/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java +++ b/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java @@ -12,6 +12,7 @@ import java.io.File; import java.io.IOException; import java.io.ObjectOutputStream; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.file.Files; import java.util.ArrayList; @@ -51,36 +52,27 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE } } if (!markedInterfacesList.isEmpty()) { - Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(resultClass); - MethodInterceptor methodInterceptor = (obj, method, args, proxy) -> { - if (method.isAnnotationPresent(Log.class)) { - for (int i = 0; i < args.length; i++) { - System.out.println(args[i]); - } - } - return proxy.invokeSuper(obj, args); - }; - enhancer.setCallback(methodInterceptor); - Class testedClass = enhancer.create(new Class[]{}, new Object[]{}).getClass(); try { ClassReader cr = new ClassReader("aop.UsefulImpl"); ClassWriter cw = new ClassWriter(0); + Class afterSam; + byte [] b2; /* ClassVisitor cv = new ClassVisitor(ASM9,cw) { @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { super.visit(version, access, name, signature, superName, interfaces); } };*/ - ClassPrinter cp = new ClassPrinter(); - cr.accept(cp, 0); +// ClassPrinter cp = new ClassPrinter(); + AOPMethodTransformationByLogAnnotation aopMethodTransformationByLogAnnotation = new AOPMethodTransformationByLogAnnotation(ASM9,cw); + cr.accept(aopMethodTransformationByLogAnnotation, 0); + b2 = cw.toByteArray(); + afterSam = defineClass(name, b2, 0, b2.length); System.out.println("aa"); + return afterSam; } catch (IOException e) { e.printStackTrace(); } - Useful useful = (UsefulImpl) enhancer.create(); - System.out.println(useful.sayHelloTo("name")); - System.out.println(new UsefulImpl().sayHelloTo("a")); } return resultClass; } diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPMethodTransformationByLogAnnotation.java b/hw05-AOPprincipes/src/main/java/aop/AOPMethodTransformationByLogAnnotation.java new file mode 100644 index 0000000..8dd95e0 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/AOPMethodTransformationByLogAnnotation.java @@ -0,0 +1,46 @@ +package aop; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; + +import static org.objectweb.asm.Opcodes.*; + +public class AOPMethodTransformationByLogAnnotation extends ClassVisitor { + + public AOPMethodTransformationByLogAnnotation(int asmVersion) { + super(asmVersion); + } + + public AOPMethodTransformationByLogAnnotation(int asmVersion, ClassVisitor classVisitor) { + super(asmVersion, classVisitor); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor methodVisitor = new AOPMethodVisitor(ASM9, super.visitMethod(access, name, descriptor, signature, exceptions), name); + return methodVisitor; +/* return new MethodVisitor(ASM9, super.visitMethod(access, name, descriptor, signature, exceptions)) { + + private boolean isLogPresent; + + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + System.out.println("desc is " + descriptor); + isLogPresent = descriptor.equals("Laop/Log;"); + System.out.println(isLogPresent); + return super.visitAnnotation(descriptor, visible); + } + + @Override + public void visitCode() { + mv.visitCode(); + if(isLogPresent){ + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("aaa"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); + } + } + };*/ + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPMethodVisitor.java b/hw05-AOPprincipes/src/main/java/aop/AOPMethodVisitor.java new file mode 100644 index 0000000..f8b20fb --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/AOPMethodVisitor.java @@ -0,0 +1,237 @@ +package aop; + +import org.objectweb.asm.*; + +import static org.objectweb.asm.Opcodes.*; + +public class AOPMethodVisitor extends MethodVisitor { + protected boolean isLogPresent; + protected String methodName; + + public AOPMethodVisitor(int api) { + super(api); + } + + public AOPMethodVisitor(int api, MethodVisitor methodVisitor, String methodName) { + super(api, methodVisitor); + this.methodName = methodName; + } + + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + isLogPresent = descriptor.equals("Laop/Log;"); + return super.visitAnnotation(descriptor, visible); + } + + @Override + public void visitCode() { + mv.visitCode(); + if (isLogPresent) { + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn(methodName); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); + } + } + + @Override // Refactor before send + public void visitMaxs(int maxStack, int maxLocals) { + mv.visitMaxs(maxStack + 3, maxLocals); + } + + public AOPMethodVisitor(int api, MethodVisitor methodVisitor) { + super(api, methodVisitor); + } + + @Override + public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { + System.out.println("visitTypeAnnotation: typeRef - " + typeRef + "; typePath - " + typePath + "; descriptor - " + descriptor); + return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); + } + + @Override + public void visitAnnotableParameterCount(int parameterCount, boolean visible) { + System.out.println("visitAnnotableParameterCount: parameterCount - " + parameterCount); + super.visitAnnotableParameterCount(parameterCount, visible); + } + + @Override + public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) { + System.out.println("visitParameterAnnotation: parameter - " + parameter + "; descriptor - " + descriptor); + return super.visitParameterAnnotation(parameter, descriptor, visible); + } + + @Override + public void visitAttribute(Attribute attribute) { + System.out.println("visitAttribute: attribute - " + attribute); + super.visitAttribute(attribute); + } + + @Override + public void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) { + if(isLogPresent){ + System.out.println("visitFrame: type -" + type + "; numLocal - " + numLocal + "; local - " + local + "; numStack - " + numStack + "; stack - " + stack); + } + super.visitFrame(type, numLocal, local, numStack, stack); + } + + @Override + public void visitInsn(int opcode) { + /*if(isLogPresent){ + System.out.println("visitInsn: opcode - " + opcode); + }*/ + super.visitInsn(opcode); + } + + @Override + public void visitIntInsn(int opcode, int operand) { + /*if(isLogPresent){ + System.out.println("visitIntInsn: opcode - " + opcode + "; operand" + operand); + }*/ + super.visitIntInsn(opcode, operand); + } + + @Override + public void visitVarInsn(int opcode, int var) { + /*if (isLogPresent){ + System.out.println("visitVarInsn: opcode - " + opcode + "; var" + var); + }*/ + super.visitVarInsn(opcode, var); + } + + @Override + public void visitTypeInsn(int opcode, String type) { + /*if (isLogPresent){ + System.out.println("visitTypeInsn: opcode - " + opcode + "; type" + type); + }*/ + super.visitTypeInsn(opcode, type); + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + /*if(isLogPresent){ + System.out.println("visitFieldInsn: opcode - " + opcode + "; owner" + owner + "; name - " + name + "; descriptor" + descriptor); + }*/ + super.visitFieldInsn(opcode, owner, name, descriptor); + } + + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { + /*if (isLogPresent){ + System.out.println("visitMethodInsn: opcode" + opcode + "; owner" + owner + "; name - " + name + "; descriptor" + descriptor); + }*/ + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + } + + @Override + public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) { + /*if(isLogPresent){ + System.out.println("visitInvokeDynamicInsn: name - " + name + "; descriptor - " + descriptor + "; bootstrapMethodHandle - " + bootstrapMethodHandle + "; bootstrapMethodArguments - "+ bootstrapMethodArguments); + }*/ + super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); + } + + @Override + public void visitJumpInsn(int opcode, Label label) { + /*if(isLogPresent){ + System.out.println("visitJumpInsn: opcode - " + opcode + "; label - " + label); + }*/ + super.visitJumpInsn(opcode, label); + } + + @Override + public void visitLabel(Label label) { + if (isLogPresent){ + System.out.println("visitLabel: label - " + label); + } + super.visitLabel(label); + } + + @Override + public void visitLdcInsn(Object value) { + /*if(isLogPresent) { + System.out.println("visitLdcInsn: value - " + value); + }*/ + super.visitLdcInsn(value); + } + + @Override + public void visitIincInsn(int var, int increment) { + /*if (isLogPresent){ + System.out.println("visitIincInsn: var - " + var + "; increment" + increment); + }*/ + super.visitIincInsn(var, increment); + } + + @Override + public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { + /*if (isLogPresent){ + System.out.println("visitTableSwitchInsn: min -" + min + "; max - " + max + "; dflt - " + dflt + "; labels - " + labels); + }*/ + super.visitTableSwitchInsn(min, max, dflt, labels); + } + + @Override + public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { + /*if(isLogPresent){ + System.out.println("visitLookupSwitchInsn: dflt - " + dflt + "; keys - " + keys + "; labels - " + labels); + }*/ + super.visitLookupSwitchInsn(dflt, keys, labels); + } + + @Override + public void visitMultiANewArrayInsn(String descriptor, int numDimensions) { + /*if (isLogPresent){ + System.out.println("visitMultiANewArrayInsn: descriptor - " + descriptor + "; numDimensions" + numDimensions); + }*/ + super.visitMultiANewArrayInsn(descriptor, numDimensions); + } + + @Override + public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { + if (isLogPresent){ + System.out.println("visitInsnAnnotation: typeRef - " + typeRef + "; typePath - " + typePath + "; descriptor - " + descriptor); + } + return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible); + } + + @Override + public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { + if (isLogPresent){ + System.out.println("visitTryCatchBlock: start - " + start + "; end - " + end + "; handler - " + handler + "; type - " + type); + } + super.visitTryCatchBlock(start, end, handler, type); + } + + @Override + public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { + if (isLogPresent){ + System.out.println("visitTryCatchAnnotation: typeRef - " + typeRef + "; typePath - " + typePath + "; " + "; descriptor - " + descriptor); + } + return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible); + } + + @Override + public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { + if(isLogPresent){ + System.out.println("visitLocalVariable: name - " + name + "; descriptor - " + descriptor + "; signature - " + signature + "; start - " + start + "; end - " + end + "; index - " + index); + } + super.visitLocalVariable(name, descriptor, signature, start, end, index); + } + + @Override + public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String descriptor, boolean visible) { + if (isLogPresent) { + System.out.println("visitLocalVariableAnnotation: typeRef - " + typeRef + "; typePath - " + typePath + "; start" + start + "; end - " + end + "; index" + index + "; descriptor - " + descriptor); + } + return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible); + } + + @Override + public void visitLineNumber(int line, Label start) { + if (isLogPresent){ + System.out.println("visitLineNumber: line - " + line + "; start - " + start); + } + super.visitLineNumber(line, start); + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/App.java b/hw05-AOPprincipes/src/main/java/aop/App.java index 67edca1..1f77bd1 100644 --- a/hw05-AOPprincipes/src/main/java/aop/App.java +++ b/hw05-AOPprincipes/src/main/java/aop/App.java @@ -4,7 +4,7 @@ public class App { static public void main(String ... args) { - Class classLoaderClass = App.class.getClassLoader().getClass(); + var classLoaderClass = App.class.getClassLoader().getClass(); if( classLoaderClass != AOPClassLoader.class) { AOPClassLoader aopClassLoader = new AOPClassLoader(); try { @@ -17,8 +17,9 @@ static public void main(String ... args) { } else{ try { - Useful useful = new UsefulImpl(); - useful.sayHelloTo("Otus"); + new UsefulImpl().sayHelloTo("bb"); +/* Useful useful = new UsefulImpl(); + useful.sayHelloTo("Otus");*/ System.out.println("App.main is run from AOPClassloader"); } catch (Exception e){ diff --git a/hw05-AOPprincipes/src/main/java/aop/Useful.java b/hw05-AOPprincipes/src/main/java/aop/Useful.java index e06dfa6..f44f8b5 100644 --- a/hw05-AOPprincipes/src/main/java/aop/Useful.java +++ b/hw05-AOPprincipes/src/main/java/aop/Useful.java @@ -1,8 +1,8 @@ package aop; public interface Useful { - public String sayHelloTo(); - public String sayHelloTo(String name); - public String sayHelloTo(String name, short howMany); + public void sayHelloTo(); + public void sayHelloTo(String name); + public void sayHelloTo(String name, short howMany); } diff --git a/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java b/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java index 7b7bfb5..0809dfd 100644 --- a/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java +++ b/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java @@ -4,19 +4,19 @@ public class UsefulImpl implements Useful { public UsefulImpl(){} @Override - public String sayHelloTo() { - return "Hello!"; + public void sayHelloTo() { +// return "Hello!"; } - @Log @Override - public String sayHelloTo(String name) { - return "Hello, " + name +"!"; + public void sayHelloTo(String name) { +// return "Hello, " + name +"!"; } + @Log @Override - public String sayHelloTo(String name, short howMany) { - return "Hello, " + name + "! " + howMany + " times."; + public void sayHelloTo(String name, short howMany) { +// return "Hello, " + name + "! " + howMany + " times."; } } From 912d2d9e0bc9e9296f650346f3c9c4e576925b1a Mon Sep 17 00:00:00 2001 From: "Renat I. Kashapov" Date: Tue, 8 Dec 2020 00:27:00 +0300 Subject: [PATCH 7/9] v14. AOP. Iteration 1. --- .../src/main/java/aop/AOPClassLoader.java | 114 ++------- .../aop/AOPLoggedMethodsCodeClassVisitor.java | 25 ++ .../AOPLoggedMethodsCodeMethodVisitor.java | 38 +++ .../AOPLoggedMethodsNamesClassVisitor.java | 24 ++ .../AOPLoggedMethodsNamesMethodVisitor.java | 73 ++++++ ...OPMethodTransformationByLogAnnotation.java | 46 ---- .../src/main/java/aop/AOPMethodVisitor.java | 237 ------------------ hw05-AOPprincipes/src/main/java/aop/App.java | 11 +- .../main/java/aop/MethodVariablesHashMap.java | 15 ++ .../main/java/aop/SomeMethodAttributes.java | 44 ++++ .../src/main/java/aop/Useful.java | 2 +- .../src/main/java/aop/UsefulImpl.java | 6 +- 12 files changed, 244 insertions(+), 391 deletions(-) create mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsCodeClassVisitor.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsCodeMethodVisitor.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsNamesClassVisitor.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsNamesMethodVisitor.java delete mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPMethodTransformationByLogAnnotation.java delete mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPMethodVisitor.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/MethodVariablesHashMap.java create mode 100644 hw05-AOPprincipes/src/main/java/aop/SomeMethodAttributes.java diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java b/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java index eae18c7..8592640 100644 --- a/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java +++ b/hw05-AOPprincipes/src/main/java/aop/AOPClassLoader.java @@ -1,78 +1,37 @@ package aop; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.FixedValue; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.Proxy; import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; - -import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; -import java.io.ObjectOutputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import static org.objectweb.asm.Opcodes.ASM9; public class AOPClassLoader extends ClassLoader { - private List annotatedMethods; - - Class defineClass(String className) throws IOException { - File file = new File(getFileName(className)); - byte[] bytecode = Files.readAllBytes(file.toPath()); - return super.defineClass("aop." + className, bytecode, 0, bytecode.length); - } - - Class defineAppClass() throws IOException { - return this.defineClass("App"); - } - - String getFileName(String className) { - return "build" + File.separator + "classes" + File.separator + "java" + File.separator - + "main" + File.separator + "aop" + File.separator + className + ".class"; - } + protected Map loggedMethods = new HashMap<>(); @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - Class resultClass = super.loadClass(name, resolve); - Method[] methods = resultClass.getMethods(); - List> markedInterfacesList = new ArrayList<>(); - annotatedMethods = new ArrayList<>(); - for (Method method : methods) { - if (method.isAnnotationPresent(Log.class)) { - determinateMarkedInterfaces(method, resultClass.getInterfaces(), markedInterfacesList); - annotatedMethods.add(method); - } - } - if (!markedInterfacesList.isEmpty()) { + Class resultClass = null; + if (!name.startsWith("java.")) { try { - ClassReader cr = new ClassReader("aop.UsefulImpl"); + ClassReader cr = new ClassReader(name); ClassWriter cw = new ClassWriter(0); - Class afterSam; - byte [] b2; -/* ClassVisitor cv = new ClassVisitor(ASM9,cw) { - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, name, signature, superName, interfaces); - } - };*/ -// ClassPrinter cp = new ClassPrinter(); - AOPMethodTransformationByLogAnnotation aopMethodTransformationByLogAnnotation = new AOPMethodTransformationByLogAnnotation(ASM9,cw); - cr.accept(aopMethodTransformationByLogAnnotation, 0); + ClassWriter cw1 = new ClassWriter(0); + byte[] b2; + AOPLoggedMethodsNamesClassVisitor aopLoggedMethodsNamesClassVisitor = new AOPLoggedMethodsNamesClassVisitor(ASM9, cw, loggedMethods); + cr.accept(aopLoggedMethodsNamesClassVisitor, 0); b2 = cw.toByteArray(); - afterSam = defineClass(name, b2, 0, b2.length); - System.out.println("aa"); - return afterSam; + ClassReader c2 = new ClassReader(b2); + AOPLoggedMethodsCodeClassVisitor aopLoggedMethodsCodeClassVisitor = new AOPLoggedMethodsCodeClassVisitor(ASM9, cw1, loggedMethods); + c2.accept(aopLoggedMethodsCodeClassVisitor, 0); + b2 = cw1.toByteArray(); + resultClass = defineClass(name, b2, 0, b2.length); } catch (IOException e) { e.printStackTrace(); } + } else { + resultClass = super.loadClass(name, resolve); } return resultClass; } @@ -81,45 +40,4 @@ public void visit(int version, int access, String name, String signature, String public Class loadClass(String name) throws ClassNotFoundException { return super.loadClass(name); } - - private void determinateMarkedInterfaces(Method method, Class[] interfaces, List> chosenInterfacesList) { - if (interfaces.length != 0) { - Arrays.stream(interfaces) - .filter(i -> Arrays.stream(i.getDeclaredMethods()) - .filter(m -> compareMethodSignature(m, method)).count() > 0) - .forEach(chosenInterfacesList::add); -// Arrays.stream(interfaces).forEach(i -> determinateCarryingInterfaces(method, i.getInterfaces(), chosenInterfacesSet)); - for (int i = 0; i < interfaces.length; i++) { - determinateMarkedInterfaces(method, interfaces[i].getInterfaces(), chosenInterfacesList); - } - } - } - - private boolean compareMethodSignature(Method method1, Method method2) { - Class[] parameterTypesM1 = method1.getParameterTypes(); - Class[] parameterTypesM2 = method2.getParameterTypes(); - if (parameterTypesM1.length != parameterTypesM2.length) { - return false; - } else { - for (int i = 0; i < parameterTypesM1.length; i++) { - if (parameterTypesM1[i] != parameterTypesM2[i]) { - return false; - } - } - } - if (method1.getName().equals(method2.getName())) { - return true; - } - return false; - } - - /* private Method findMethodWithSameSignatureInArray(Method method, Method [] proxyMethods){ - for(Method proxyMethod: proxyMethods){ - if(compareMethodSignature(proxyMethod, method)){ - return proxyMethod; - } - } - return null; - }*/ - } \ No newline at end of file diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsCodeClassVisitor.java b/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsCodeClassVisitor.java new file mode 100644 index 0000000..36fcf53 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsCodeClassVisitor.java @@ -0,0 +1,25 @@ +package aop; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import java.util.Map; +import static org.objectweb.asm.Opcodes.ASM9; + +public class AOPLoggedMethodsCodeClassVisitor extends ClassVisitor { + + protected Map loggedMethods; + + public AOPLoggedMethodsCodeClassVisitor(int asmVersion, ClassVisitor classVisitor, Map loggedMethods) { + super(asmVersion, classVisitor); + this.loggedMethods = loggedMethods; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor superMethodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions); + if (loggedMethods.get(name + descriptor) != null) { + return new AOPLoggedMethodsCodeMethodVisitor(ASM9, superMethodVisitor, loggedMethods.get(name + descriptor)); + } + return superMethodVisitor; + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsCodeMethodVisitor.java b/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsCodeMethodVisitor.java new file mode 100644 index 0000000..e6fc758 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsCodeMethodVisitor.java @@ -0,0 +1,38 @@ +package aop; + +import org.objectweb.asm.MethodVisitor; +import static org.objectweb.asm.Opcodes.*; +import java.util.Map; + +public class AOPLoggedMethodsCodeMethodVisitor extends MethodVisitor { + + protected SomeMethodAttributes someMethodAttributes; + + public AOPLoggedMethodsCodeMethodVisitor(int api, MethodVisitor methodVisitor, SomeMethodAttributes someMethodAttributes) { + super(api, methodVisitor); + this.someMethodAttributes = someMethodAttributes; + } + + @Override + public void visitCode() { + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("Method: \"" + someMethodAttributes.getName() + "\""); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); + for (Map.Entry parameter : someMethodAttributes.getMethodVariablesHashMap().entrySet()) { + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("Argument \"" + parameter.getKey() + "\": "); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); + mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitVarInsn(parameter.getValue().getType().getOpcode(ILOAD), parameter.getValue().getIndex()); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(" + transformToPrintlnArg(parameter.getValue().getType().getDescriptor()) + ")V", false); + } + } + + private String transformToPrintlnArg(String arg){ + if(arg.matches("[BSI]{1}")){ + return "I"; + } + return arg; + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsNamesClassVisitor.java b/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsNamesClassVisitor.java new file mode 100644 index 0000000..f2bc445 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsNamesClassVisitor.java @@ -0,0 +1,24 @@ +package aop; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; + +import java.util.Map; +import static org.objectweb.asm.Opcodes.*; + +public class AOPLoggedMethodsNamesClassVisitor extends ClassVisitor { + + protected Map loggedMethods; + + public AOPLoggedMethodsNamesClassVisitor(int asmVersion, ClassVisitor classVisitor, Map loggedMethods) { + super(asmVersion, classVisitor); + this.loggedMethods = loggedMethods; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor aopLoggedMethodsNamesMethodVisitor = new AOPLoggedMethodsNamesMethodVisitor(ASM9, super.visitMethod(access, name, descriptor, signature, exceptions), loggedMethods, new SomeMethodAttributes(descriptor, access, name, signature, exceptions, new MethodVariablesHashMap())); + return aopLoggedMethodsNamesMethodVisitor; + } + +} diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsNamesMethodVisitor.java b/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsNamesMethodVisitor.java new file mode 100644 index 0000000..90f6126 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/AOPLoggedMethodsNamesMethodVisitor.java @@ -0,0 +1,73 @@ +package aop; + +import org.objectweb.asm.*; +import java.util.Map; + +public class AOPLoggedMethodsNamesMethodVisitor extends MethodVisitor { + protected boolean isLogPresent; + protected SomeMethodAttributes someMethodAttributes; + protected Map loggedMethods; + + public AOPLoggedMethodsNamesMethodVisitor(int api, MethodVisitor methodVisitor, Map loggedMethods, SomeMethodAttributes someMethodAttributes) { + super(api, methodVisitor); + this.loggedMethods = loggedMethods; + this.someMethodAttributes = someMethodAttributes; + } + + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + isLogPresent = Type.getDescriptor(Log.class).equals(descriptor); + if(isLogPresent){ + loggedMethods.put(someMethodAttributes.getName() + someMethodAttributes.getDescription(), someMethodAttributes); + } + return super.visitAnnotation(descriptor, visible); + } + + @Override + public void visitMaxs(int maxStack, int maxLocals) { + mv.visitMaxs(maxStack + 3, maxLocals + 4); + } + + @Override + public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { + String methodParameters = someMethodAttributes.getDescription().replaceFirst(".*\\(","").replaceFirst("\\).*", ""); + if (isLogPresent & index > 0) { + someMethodAttributes.getMethodVariablesHashMap().put(name,new TypeIndex(index, parseParameters(methodParameters, index))); + } + super.visitLocalVariable(name, descriptor, signature, start, end, index); + } + + private Type parseParameters(String parameters, int index) { + if (index == 1) { + if (parameters.startsWith("L")) { + return Type.getType(parameters.substring(0,parameters.indexOf(';')+1)); + } else { + return Type.getType(parameters.substring(0, 1)); + } + } else { + if (parameters.startsWith("L")){ + return parseParameters(parameters.substring(parameters.indexOf(';')+1),index-1); + } else { + return parseParameters(parameters.substring(1),index-1); + } + } + } + + final protected class TypeIndex { + private int index; + private Type type; + + TypeIndex(int index, Type type) { + this.index = index; + this.type = type; + } + + protected int getIndex() { + return index; + } + + protected Type getType() { + return type; + } + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPMethodTransformationByLogAnnotation.java b/hw05-AOPprincipes/src/main/java/aop/AOPMethodTransformationByLogAnnotation.java deleted file mode 100644 index 8dd95e0..0000000 --- a/hw05-AOPprincipes/src/main/java/aop/AOPMethodTransformationByLogAnnotation.java +++ /dev/null @@ -1,46 +0,0 @@ -package aop; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; - -import static org.objectweb.asm.Opcodes.*; - -public class AOPMethodTransformationByLogAnnotation extends ClassVisitor { - - public AOPMethodTransformationByLogAnnotation(int asmVersion) { - super(asmVersion); - } - - public AOPMethodTransformationByLogAnnotation(int asmVersion, ClassVisitor classVisitor) { - super(asmVersion, classVisitor); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor methodVisitor = new AOPMethodVisitor(ASM9, super.visitMethod(access, name, descriptor, signature, exceptions), name); - return methodVisitor; -/* return new MethodVisitor(ASM9, super.visitMethod(access, name, descriptor, signature, exceptions)) { - - private boolean isLogPresent; - - @Override - public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - System.out.println("desc is " + descriptor); - isLogPresent = descriptor.equals("Laop/Log;"); - System.out.println(isLogPresent); - return super.visitAnnotation(descriptor, visible); - } - - @Override - public void visitCode() { - mv.visitCode(); - if(isLogPresent){ - mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); - mv.visitLdcInsn("aaa"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); - } - } - };*/ - } -} diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPMethodVisitor.java b/hw05-AOPprincipes/src/main/java/aop/AOPMethodVisitor.java deleted file mode 100644 index f8b20fb..0000000 --- a/hw05-AOPprincipes/src/main/java/aop/AOPMethodVisitor.java +++ /dev/null @@ -1,237 +0,0 @@ -package aop; - -import org.objectweb.asm.*; - -import static org.objectweb.asm.Opcodes.*; - -public class AOPMethodVisitor extends MethodVisitor { - protected boolean isLogPresent; - protected String methodName; - - public AOPMethodVisitor(int api) { - super(api); - } - - public AOPMethodVisitor(int api, MethodVisitor methodVisitor, String methodName) { - super(api, methodVisitor); - this.methodName = methodName; - } - - @Override - public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - isLogPresent = descriptor.equals("Laop/Log;"); - return super.visitAnnotation(descriptor, visible); - } - - @Override - public void visitCode() { - mv.visitCode(); - if (isLogPresent) { - mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); - mv.visitLdcInsn(methodName); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); - } - } - - @Override // Refactor before send - public void visitMaxs(int maxStack, int maxLocals) { - mv.visitMaxs(maxStack + 3, maxLocals); - } - - public AOPMethodVisitor(int api, MethodVisitor methodVisitor) { - super(api, methodVisitor); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - System.out.println("visitTypeAnnotation: typeRef - " + typeRef + "; typePath - " + typePath + "; descriptor - " + descriptor); - return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitAnnotableParameterCount(int parameterCount, boolean visible) { - System.out.println("visitAnnotableParameterCount: parameterCount - " + parameterCount); - super.visitAnnotableParameterCount(parameterCount, visible); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) { - System.out.println("visitParameterAnnotation: parameter - " + parameter + "; descriptor - " + descriptor); - return super.visitParameterAnnotation(parameter, descriptor, visible); - } - - @Override - public void visitAttribute(Attribute attribute) { - System.out.println("visitAttribute: attribute - " + attribute); - super.visitAttribute(attribute); - } - - @Override - public void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) { - if(isLogPresent){ - System.out.println("visitFrame: type -" + type + "; numLocal - " + numLocal + "; local - " + local + "; numStack - " + numStack + "; stack - " + stack); - } - super.visitFrame(type, numLocal, local, numStack, stack); - } - - @Override - public void visitInsn(int opcode) { - /*if(isLogPresent){ - System.out.println("visitInsn: opcode - " + opcode); - }*/ - super.visitInsn(opcode); - } - - @Override - public void visitIntInsn(int opcode, int operand) { - /*if(isLogPresent){ - System.out.println("visitIntInsn: opcode - " + opcode + "; operand" + operand); - }*/ - super.visitIntInsn(opcode, operand); - } - - @Override - public void visitVarInsn(int opcode, int var) { - /*if (isLogPresent){ - System.out.println("visitVarInsn: opcode - " + opcode + "; var" + var); - }*/ - super.visitVarInsn(opcode, var); - } - - @Override - public void visitTypeInsn(int opcode, String type) { - /*if (isLogPresent){ - System.out.println("visitTypeInsn: opcode - " + opcode + "; type" + type); - }*/ - super.visitTypeInsn(opcode, type); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { - /*if(isLogPresent){ - System.out.println("visitFieldInsn: opcode - " + opcode + "; owner" + owner + "; name - " + name + "; descriptor" + descriptor); - }*/ - super.visitFieldInsn(opcode, owner, name, descriptor); - } - - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) { - /*if (isLogPresent){ - System.out.println("visitMethodInsn: opcode" + opcode + "; owner" + owner + "; name - " + name + "; descriptor" + descriptor); - }*/ - super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); - } - - @Override - public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) { - /*if(isLogPresent){ - System.out.println("visitInvokeDynamicInsn: name - " + name + "; descriptor - " + descriptor + "; bootstrapMethodHandle - " + bootstrapMethodHandle + "; bootstrapMethodArguments - "+ bootstrapMethodArguments); - }*/ - super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); - } - - @Override - public void visitJumpInsn(int opcode, Label label) { - /*if(isLogPresent){ - System.out.println("visitJumpInsn: opcode - " + opcode + "; label - " + label); - }*/ - super.visitJumpInsn(opcode, label); - } - - @Override - public void visitLabel(Label label) { - if (isLogPresent){ - System.out.println("visitLabel: label - " + label); - } - super.visitLabel(label); - } - - @Override - public void visitLdcInsn(Object value) { - /*if(isLogPresent) { - System.out.println("visitLdcInsn: value - " + value); - }*/ - super.visitLdcInsn(value); - } - - @Override - public void visitIincInsn(int var, int increment) { - /*if (isLogPresent){ - System.out.println("visitIincInsn: var - " + var + "; increment" + increment); - }*/ - super.visitIincInsn(var, increment); - } - - @Override - public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { - /*if (isLogPresent){ - System.out.println("visitTableSwitchInsn: min -" + min + "; max - " + max + "; dflt - " + dflt + "; labels - " + labels); - }*/ - super.visitTableSwitchInsn(min, max, dflt, labels); - } - - @Override - public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { - /*if(isLogPresent){ - System.out.println("visitLookupSwitchInsn: dflt - " + dflt + "; keys - " + keys + "; labels - " + labels); - }*/ - super.visitLookupSwitchInsn(dflt, keys, labels); - } - - @Override - public void visitMultiANewArrayInsn(String descriptor, int numDimensions) { - /*if (isLogPresent){ - System.out.println("visitMultiANewArrayInsn: descriptor - " + descriptor + "; numDimensions" + numDimensions); - }*/ - super.visitMultiANewArrayInsn(descriptor, numDimensions); - } - - @Override - public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - if (isLogPresent){ - System.out.println("visitInsnAnnotation: typeRef - " + typeRef + "; typePath - " + typePath + "; descriptor - " + descriptor); - } - return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - if (isLogPresent){ - System.out.println("visitTryCatchBlock: start - " + start + "; end - " + end + "; handler - " + handler + "; type - " + type); - } - super.visitTryCatchBlock(start, end, handler, type); - } - - @Override - public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) { - if (isLogPresent){ - System.out.println("visitTryCatchAnnotation: typeRef - " + typeRef + "; typePath - " + typePath + "; " + "; descriptor - " + descriptor); - } - return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible); - } - - @Override - public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { - if(isLogPresent){ - System.out.println("visitLocalVariable: name - " + name + "; descriptor - " + descriptor + "; signature - " + signature + "; start - " + start + "; end - " + end + "; index - " + index); - } - super.visitLocalVariable(name, descriptor, signature, start, end, index); - } - - @Override - public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String descriptor, boolean visible) { - if (isLogPresent) { - System.out.println("visitLocalVariableAnnotation: typeRef - " + typeRef + "; typePath - " + typePath + "; start" + start + "; end - " + end + "; index" + index + "; descriptor - " + descriptor); - } - return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible); - } - - @Override - public void visitLineNumber(int line, Label start) { - if (isLogPresent){ - System.out.println("visitLineNumber: line - " + line + "; start - " + start); - } - super.visitLineNumber(line, start); - } -} diff --git a/hw05-AOPprincipes/src/main/java/aop/App.java b/hw05-AOPprincipes/src/main/java/aop/App.java index 1f77bd1..8dfb753 100644 --- a/hw05-AOPprincipes/src/main/java/aop/App.java +++ b/hw05-AOPprincipes/src/main/java/aop/App.java @@ -5,22 +5,19 @@ public class App { static public void main(String ... args) { var classLoaderClass = App.class.getClassLoader().getClass(); - if( classLoaderClass != AOPClassLoader.class) { + if( !classLoaderClass.getName().equals(AOPClassLoader.class.getName())) { //иначе сравнивать классы невозможно, так как это различные объекты AOPClassLoader aopClassLoader = new AOPClassLoader(); try { - Class loadClass = aopClassLoader.defineAppClass(); + Class loadClass = aopClassLoader.loadClass("aop.App", false); Method method = loadClass.getMethod("main", new Class[]{String[].class}); method.invoke(null, new Object[]{args}); } catch (Exception e) { e.printStackTrace(); } - } - else{ + } else{// классы с AOP писать в этом блоке. try { new UsefulImpl().sayHelloTo("bb"); -/* Useful useful = new UsefulImpl(); - useful.sayHelloTo("Otus");*/ - System.out.println("App.main is run from AOPClassloader"); + new UsefulImpl().sayHelloTo("cc", (short) 23); } catch (Exception e){ e.printStackTrace(); diff --git a/hw05-AOPprincipes/src/main/java/aop/MethodVariablesHashMap.java b/hw05-AOPprincipes/src/main/java/aop/MethodVariablesHashMap.java new file mode 100644 index 0000000..f5a8622 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/MethodVariablesHashMap.java @@ -0,0 +1,15 @@ +package aop; + +import java.util.HashMap; + +public class MethodVariablesHashMap extends HashMap { + @Override + public AOPLoggedMethodsNamesMethodVisitor.TypeIndex put(String name, AOPLoggedMethodsNamesMethodVisitor.TypeIndex typeIndex) { + for (AOPLoggedMethodsNamesMethodVisitor.TypeIndex existingTypeIndex : this.values()) { + if (typeIndex.getIndex() == existingTypeIndex.getIndex()) { + throw new IllegalArgumentException(); + } + } + return super.put(name, typeIndex); + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/SomeMethodAttributes.java b/hw05-AOPprincipes/src/main/java/aop/SomeMethodAttributes.java new file mode 100644 index 0000000..1d74930 --- /dev/null +++ b/hw05-AOPprincipes/src/main/java/aop/SomeMethodAttributes.java @@ -0,0 +1,44 @@ +package aop; + +public class SomeMethodAttributes { + private String description; + private int access; + private String name; + private String signature; + private String[] exceptions; + private MethodVariablesHashMap methodVariablesHashMap; + + SomeMethodAttributes(String description, int access, String name, String signature, String[] exceptions, + MethodVariablesHashMap methodVariablesHashMap) { + this.description = description; + this.access = access; + this.name = name; + this.signature = signature; + this.exceptions = exceptions; + this.methodVariablesHashMap = methodVariablesHashMap; + } + + public String getDescription() { + return this.description; + } + + public int getAccess() { + return this.access; + } + + public String getName() { + return this.name; + } + + public String getSignature() { + return this.signature; + } + + public String[] getExceptions() { + return this.exceptions; + } + + public MethodVariablesHashMap getMethodVariablesHashMap(){ + return this.methodVariablesHashMap; + } +} diff --git a/hw05-AOPprincipes/src/main/java/aop/Useful.java b/hw05-AOPprincipes/src/main/java/aop/Useful.java index f44f8b5..88debc4 100644 --- a/hw05-AOPprincipes/src/main/java/aop/Useful.java +++ b/hw05-AOPprincipes/src/main/java/aop/Useful.java @@ -3,6 +3,6 @@ public interface Useful { public void sayHelloTo(); public void sayHelloTo(String name); - public void sayHelloTo(String name, short howMany); + public void sayHelloTo(String name, double howMany); } diff --git a/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java b/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java index 0809dfd..5c17e91 100644 --- a/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java +++ b/hw05-AOPprincipes/src/main/java/aop/UsefulImpl.java @@ -1,13 +1,15 @@ package aop; public class UsefulImpl implements Useful { - public UsefulImpl(){} + public UsefulImpl() { + } @Override public void sayHelloTo() { // return "Hello!"; } + @Log @Override public void sayHelloTo(String name) { // return "Hello, " + name +"!"; @@ -15,7 +17,7 @@ public void sayHelloTo(String name) { @Log @Override - public void sayHelloTo(String name, short howMany) { + public void sayHelloTo(String name, double howMany) { // return "Hello, " + name + "! " + howMany + " times."; } From 0b442b4ada4d68f5663e0e144d5f0d7f80edbaa7 Mon Sep 17 00:00:00 2001 From: "Renat I. Kashapov" Date: Tue, 8 Dec 2020 00:28:02 +0300 Subject: [PATCH 8/9] v14. AOP. Iteration 1.1. --- .../main/java/aop/AOPInvocationHandler.java | 17 ------- .../src/main/java/aop/ClassPrinter.java | 50 ------------------- 2 files changed, 67 deletions(-) delete mode 100644 hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java delete mode 100644 hw05-AOPprincipes/src/main/java/aop/ClassPrinter.java diff --git a/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java b/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java deleted file mode 100644 index 530730d..0000000 --- a/hw05-AOPprincipes/src/main/java/aop/AOPInvocationHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -package aop; - -import net.sf.cglib.proxy.InvocationHandler; - -import java.lang.reflect.Method; -import java.util.Arrays; - -public class AOPInvocationHandler implements InvocationHandler { - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if(method.isAnnotationPresent(Log.class)) { - Arrays.stream(args).forEach(System.out::println); - } - return method.invoke(proxy, new Object[]{args}); - } -} diff --git a/hw05-AOPprincipes/src/main/java/aop/ClassPrinter.java b/hw05-AOPprincipes/src/main/java/aop/ClassPrinter.java deleted file mode 100644 index bf9d6e1..0000000 --- a/hw05-AOPprincipes/src/main/java/aop/ClassPrinter.java +++ /dev/null @@ -1,50 +0,0 @@ -package aop; - -import org.objectweb.asm.*; - -import static org.objectweb.asm.Opcodes.ASM9; - -public class ClassPrinter extends ClassVisitor { - public ClassPrinter() { - super(ASM9); - } - - public void visit(int version, int access, String name, - String signature, String superName, String[] interfaces) { - System.out.println(name + " extends " + superName + " " + version + " {"); - } - - public void visitSource(String source, String debug) { - } - - public void visitOuterClass(String owner, String name, String desc) { - } - - public AnnotationVisitor visitAnnotation(String desc, - boolean visible) { - return null; - } - - public void visitAttribute(Attribute attr) { - } - - public void visitInnerClass(String name, String outerName, - String innerName, int access) { - } - - public FieldVisitor visitField(int access, String name, String desc, - String signature, Object value) { - System.out.println(" " + desc + " " + name); - return null; - } - - public MethodVisitor visitMethod(int access, String name, - String desc, String signature, String[] exceptions) { - System.out.println(" " + name + desc); - return null; - } - - public void visitEnd() { - System.out.println("}"); - } -} From b28e9ca0eb5b474d4ceed349e6b30c13c51feb0d Mon Sep 17 00:00:00 2001 From: 1121977 Date: Thu, 22 Apr 2021 16:49:03 +0300 Subject: [PATCH 9/9] README update --- README.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c29a8be..bbb4aac 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,14 @@ -# Примеры для курса "Разработчик Java" в OTUS + +Разработайте такой функционал: метод класса можно пометить самодельной аннотацией @Log, например, так: -Группа 2020-09 +class TestLogging { @Log public void calculation(int param) {}; } -### Преподаватели -Сергей Петрелевич
-Стрекалов Павел
-Александр Оруджев
-Вячеслав Лапин
-Виталий Куценко
-Дмитрий Коган +При вызове этого метода "автомагически" в консоль должны логироваться значения параметров. Например так. -Студент: -Kashapov Renat (Кашапов Ренат)
-renat.kashapov@gmail.com \ No newline at end of file +class Demo { public void action() { new TestLogging().calculation(6); } } + +В консоле дожно быть: executed method: calculation, param: 6 + +Обратите внимание: явного вызова логирования быть не должно. + +Учтите, что аннотацию можно поставить, например, на такие методы: public void calculation(int param1) public void calculation(int param1, int param2) public void calculation(int param1, int param2, String param3)